Skip to content

Commit 355c6ad

Browse files
claudepieterbeulque
authored andcommitted
Use PolarRequestValidationError for billing address validation
Replace custom InvoiceBillingAddressUpdateError with standard PolarRequestValidationError for better consistency with the codebase.
1 parent a90122f commit 355c6ad

File tree

4 files changed

+38
-39
lines changed

4 files changed

+38
-39
lines changed

clients/packages/ui/src/components/atoms/CountryPicker.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,12 @@ const CountryPicker = ({
4141
}) => {
4242
const countryMap = getCountryList(allowedCountries as TCountryCode[])
4343
return (
44-
<Select onValueChange={onChange} value={value} autoComplete={autoComplete} disabled={disabled}>
44+
<Select
45+
onValueChange={onChange}
46+
value={value}
47+
autoComplete={autoComplete}
48+
disabled={disabled}
49+
>
4550
<SelectTrigger className={className} disabled={disabled}>
4651
<SelectValue
4752
placeholder="Country"

server/polar/customer_portal/endpoints/order.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
from polar.openapi import APITag
1313
from polar.order.schemas import OrderID
1414
from polar.order.service import (
15-
InvoiceBillingAddressUpdateError,
1615
MissingInvoiceBillingDetails,
1716
NotPaidOrder,
1817
PaymentAlreadyInProgress,
@@ -114,13 +113,7 @@ async def get(
114113
"/{id}",
115114
summary="Update Order",
116115
response_model=CustomerOrder,
117-
responses={
118-
404: OrderNotFound,
119-
422: {
120-
"description": "Cannot update billing address country/state after order is paid.",
121-
"model": InvoiceBillingAddressUpdateError.schema(),
122-
},
123-
},
116+
responses={404: OrderNotFound},
124117
)
125118
async def update(
126119
id: OrderID,

server/polar/order/endpoints.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,7 @@
2626
from . import auth, sorting
2727
from .schemas import Order as OrderSchema
2828
from .schemas import OrderID, OrderInvoice, OrderNotFound, OrderUpdate
29-
from .service import (
30-
InvoiceBillingAddressUpdateError,
31-
MissingInvoiceBillingDetails,
32-
NotPaidOrder,
33-
)
29+
from .service import MissingInvoiceBillingDetails, NotPaidOrder
3430
from .service import order as order_service
3531

3632
router = APIRouter(prefix="/orders", tags=["orders", APITag.public, APITag.mcp])
@@ -177,13 +173,7 @@ async def get(
177173
"/{id}",
178174
summary="Update Order",
179175
response_model=OrderSchema,
180-
responses={
181-
404: OrderNotFound,
182-
422: {
183-
"description": "Cannot update billing address country/state after order is paid.",
184-
"model": InvoiceBillingAddressUpdateError.schema(),
185-
},
186-
},
176+
responses={404: OrderNotFound},
187177
)
188178
async def update(
189179
id: OrderID,

server/polar/order/service.py

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from polar.event.service import event as event_service
2929
from polar.event.system import OrderPaidMetadata, SystemEvent, build_system_event
3030
from polar.eventstream.service import publish as eventstream_publish
31-
from polar.exceptions import PolarError
31+
from polar.exceptions import PolarError, PolarRequestValidationError
3232
from polar.file.s3 import S3_SERVICES
3333
from polar.held_balance.service import held_balance as held_balance_service
3434
from polar.integrations.stripe.service import stripe as stripe_service
@@ -223,16 +223,6 @@ def __init__(self, subscription: Subscription) -> None:
223223
super().__init__(message)
224224

225225

226-
class InvoiceBillingAddressUpdateError(OrderError):
227-
def __init__(self, order: Order) -> None:
228-
self.order = order
229-
message = (
230-
"Cannot update billing address country or state after order is paid, "
231-
"as VAT was calculated based on the original address."
232-
)
233-
super().__init__(message, 422)
234-
235-
236226
def _is_empty_customer_address(customer_address: dict[str, Any] | None) -> bool:
237227
return customer_address is None or customer_address["country"] is None
238228

@@ -355,14 +345,35 @@ async def update(
355345
new_address = order_update.billing_address
356346
existing_address = order.billing_address
357347

358-
# Check if country or state is being changed
359-
new_country = new_address.country if new_address else None
348+
new_country = str(new_address.country) if new_address else None
360349
new_state = new_address.state if new_address else None
361-
existing_country = existing_address.get("country") if existing_address else None
362-
existing_state = existing_address.get("state") if existing_address else None
363-
364-
if new_country != existing_country or new_state != existing_state:
365-
raise InvoiceBillingAddressUpdateError(order)
350+
existing_country = (
351+
str(existing_address.country) if existing_address else None
352+
)
353+
existing_state = existing_address.state if existing_address else None
354+
355+
if new_country != existing_country:
356+
raise PolarRequestValidationError(
357+
[
358+
{
359+
"type": "value_error",
360+
"loc": ("body", "billing_address", "country"),
361+
"msg": "Cannot change country after order is paid.",
362+
"input": new_country,
363+
}
364+
]
365+
)
366+
if new_state != existing_state:
367+
raise PolarRequestValidationError(
368+
[
369+
{
370+
"type": "value_error",
371+
"loc": ("body", "billing_address", "state"),
372+
"msg": "Cannot change state after order is paid.",
373+
"input": new_state,
374+
}
375+
]
376+
)
366377

367378
repository = OrderRepository.from_session(session)
368379
order = await repository.update(

0 commit comments

Comments
 (0)