Skip to content

Commit

Permalink
server/order: fix invoice handling when there are only prorations
Browse files Browse the repository at this point in the history
  • Loading branch information
frankie567 committed Aug 12, 2024
1 parent 1b460db commit 9f8b8c7
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 8 deletions.
36 changes: 29 additions & 7 deletions server/polar/order/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,14 +215,36 @@ async def create_order_from_stripe(
for line in invoice.lines.data:
if not line.proration and line.price is not None:
stripe_price_ids.add(line.price.id)
if len(stripe_price_ids) != 1:

product_price: ProductPrice | None = None
# For invoices with only one line item, get the price from the line item
if len(stripe_price_ids) == 1:
stripe_price_id = stripe_price_ids.pop()
product_price = await product_price_service.get_by_stripe_price_id(
session, stripe_price_id
)
if product_price is None:
raise ProductPriceDoesNotExist(invoice.id, stripe_price_id)
# For invoices with only prorations, try to get the price from the subscription metadata
elif len(stripe_price_ids) == 0:
if (
invoice.subscription_details is None
or invoice.subscription_details.metadata is None
or (
(price_id := invoice.subscription_details.metadata.get("price_id"))
is None
)
):
raise CantDetermineInvoicePrice(invoice.id)
product_price = await product_price_service.get_by_id(
session, uuid.UUID(price_id)
)
if product_price is None:
raise CantDetermineInvoicePrice(invoice.id)
# For invoices with multiple line items, we can't determine the price
else:
raise CantDetermineInvoicePrice(invoice.id)
stripe_price_id = stripe_price_ids.pop()
product_price = await product_price_service.get_by_stripe_price_id(
session, stripe_price_id
)
if product_price is None:
raise ProductPriceDoesNotExist(invoice.id, stripe_price_id)

product = product_price.product

user: User | None = None
Expand Down
35 changes: 34 additions & 1 deletion server/tests/order/test_service.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from typing import Any
from unittest.mock import AsyncMock

import pytest
Expand Down Expand Up @@ -43,6 +44,7 @@ def construct_stripe_invoice(
tax: int = 2000,
charge_id: str = "CHARGE_ID",
subscription_id: str | None = "SUBSCRIPTION_ID",
subscription_details: dict[str, Any] | None = None,
customer_id: str = "CUSTOMER_ID",
lines: list[tuple[str, bool]] = [("PRICE_ID", False)],
metadata: dict[str, str] = {},
Expand All @@ -56,6 +58,7 @@ def construct_stripe_invoice(
"currency": "usd",
"charge": charge_id,
"subscription": subscription_id,
"subscription_details": subscription_details,
"customer": customer_id,
"lines": {
"data": [
Expand Down Expand Up @@ -211,7 +214,6 @@ async def test_not_a_order_invoice(
"lines",
(
[],
[("PRICE_1", True), ("PRICE_2", True)],
[("PRICE_1", False), ("PRICE_2", False)],
),
)
Expand Down Expand Up @@ -303,6 +305,37 @@ async def test_subscription_proration(
assert order.subscription == subscription
assert order.user.stripe_customer_id == invoice.customer

async def test_subscription_only_proration(
self,
session: AsyncSession,
save_fixture: SaveFixture,
subscription: Subscription,
product: Product,
) -> None:
invoice = construct_stripe_invoice(
subscription_id=subscription.stripe_subscription_id,
lines=[
("PRICE_1", True),
("PRICE_2", True),
],
subscription_details={"metadata": {"price_id": str(product.prices[0].id)}},
)

payment_transaction = await create_transaction(
save_fixture, type=TransactionType.payment
)
payment_transaction.charge_id = "CHARGE_ID"
await save_fixture(payment_transaction)

order = await order_service.create_order_from_stripe(session, invoice=invoice)

assert order.amount == invoice.total - (invoice.tax or 0)
assert order.user.id == subscription.user_id
assert order.product == product
assert order.product_price == product.prices[0]
assert order.subscription == subscription
assert order.user.stripe_customer_id == invoice.customer

async def test_subscription_with_account(
self,
enqueue_job_mock: AsyncMock,
Expand Down

0 comments on commit 9f8b8c7

Please sign in to comment.