From e5169a5ddf285bb23be98941ee00449dd4ed92b5 Mon Sep 17 00:00:00 2001 From: damaz91 Date: Fri, 10 Jul 2026 16:50:20 +0000 Subject: [PATCH 1/2] fix: update server to match SDK type alias changes --- .../server/services/checkout_service.py | 138 +++++++----------- 1 file changed, 52 insertions(+), 86 deletions(-) diff --git a/rest/python/server/services/checkout_service.py b/rest/python/server/services/checkout_service.py index 48da4db..d509d7f 100644 --- a/rest/python/server/services/checkout_service.py +++ b/rest/python/server/services/checkout_service.py @@ -58,8 +58,6 @@ ResponseCheckoutSchema as ResponseCheckout, ) from ucp_sdk.models.schemas.ucp import ResponseOrderSchema as ResponseOrder -from ucp_sdk.models.schemas.ucp import UcpMetadata -from ucp_sdk.models.schemas.ucp import Version from ucp_sdk.models.schemas.capability import ResponseSchema as Response from ucp_sdk.models.schemas.shopping.checkout_complete_request import ( CheckoutCompleteRequest, @@ -67,9 +65,6 @@ from ucp_sdk.models.schemas.shopping.discount import Allocation from ucp_sdk.models.schemas.shopping.discount import AppliedDiscount from ucp_sdk.models.schemas.shopping.discount import DiscountsObject -from ucp_sdk.models.schemas.shopping.fulfillment import ( - Fulfillment as FulfillmentWrapper, -) from ucp_sdk.models.schemas.shopping.order import ( Fulfillment as OrderFulfillment, ) @@ -80,14 +75,10 @@ ) from ucp_sdk.models.schemas.shopping.payment import Payment as PaymentResponse from ucp_sdk.models.schemas.shopping.types import order_line_item -from ucp_sdk.models.schemas.shopping.types import total as total_resp from ucp_sdk.models.schemas.shopping.types.expectation import Expectation from ucp_sdk.models.schemas.shopping.types.expectation import ( LineItem as ExpectationLineItem, ) -from ucp_sdk.models.schemas.shopping.types.fulfillment_destination import ( - FulfillmentDestination, -) from ucp_sdk.models.schemas.shopping.types.fulfillment_group import ( FulfillmentGroup, ) @@ -221,7 +212,7 @@ async def create_checkout( # Initialize fulfillment response fulfillment_resp = None if checkout_req.fulfillment: - req_fulfillment = checkout_req.fulfillment.root + req_fulfillment = checkout_req.fulfillment resp_methods = [] all_li_ids = [li.id for li in line_items] @@ -270,18 +261,16 @@ async def create_checkout( # ShippingDestinationResponse # Extract the inner ShippingDestinationRequest - inner_dest = dest_req.root + inner_dest = dest_req resp_destinations.append( - FulfillmentDestination( - root=ShippingDestinationResponse( - id=getattr(inner_dest, "id", None) or str(uuid.uuid4()), - address_country=inner_dest.address_country, - postal_code=inner_dest.postal_code, - address_region=inner_dest.address_region, - address_locality=inner_dest.address_locality, - street_address=inner_dest.street_address, - ) + ShippingDestinationResponse( + id=getattr(inner_dest, "id", None) or str(uuid.uuid4()), + address_country=inner_dest.address_country, + postal_code=inner_dest.postal_code, + address_region=inner_dest.address_region, + address_locality=inner_dest.address_locality, + street_address=inner_dest.street_address, ) ) @@ -298,18 +287,16 @@ async def create_checkout( ) ) - fulfillment_resp = FulfillmentWrapper( - root=FulfillmentResponseClass(methods=resp_methods) - ) + fulfillment_resp = FulfillmentResponseClass(methods=resp_methods) checkout = Checkout( ucp=ResponseCheckout( - version=Version(config.get_server_version()), + version=config.get_server_version(), capabilities={ "dev.ucp.shopping.checkout": [ Response( name="dev.ucp.shopping.checkout", - version=Version(config.get_server_version()), + version=config.get_server_version(), ) ] }, @@ -463,18 +450,16 @@ async def update_checkout( req_fulfillment = checkout_req.fulfillment resp_methods = [] - if req_fulfillment.root.methods: - logging.info( - "Request has %d methods", len(req_fulfillment.root.methods) - ) - for m_req in req_fulfillment.root.methods: + if req_fulfillment.methods: + logging.info("Request has %d methods", len(req_fulfillment.methods)) + for m_req in req_fulfillment.methods: # Find matching existing method to preserve state existing_method = None - if existing.fulfillment and existing.fulfillment.root.methods: + if existing.fulfillment and existing.fulfillment.methods: existing_method = next( ( m - for m in existing.fulfillment.root.methods + for m in existing.fulfillment.methods if m.id == getattr(m_req, "id", None) ), None, @@ -484,9 +469,9 @@ async def update_checkout( if ( not existing_method and not getattr(m_req, "id", None) - and len(existing.fulfillment.root.methods) == 1 + and len(existing.fulfillment.methods) == 1 ): - existing_method = existing.fulfillment.root.methods[0] + existing_method = existing.fulfillment.methods[0] # Resolve ID method_id = getattr(m_req, "id", None) @@ -508,7 +493,7 @@ async def update_checkout( # Use provided destinations for dest_req in m_req.destinations: # Extract inner dest - inner_dest = dest_req.root + inner_dest = dest_req dest_data = inner_dest.model_dump(exclude_none=True) # Persist addresses for known customers @@ -522,9 +507,7 @@ async def update_checkout( dest_data["id"] = saved_id resp_destinations.append( - FulfillmentDestination( - root=ShippingDestinationResponse(**dest_data) - ) + ShippingDestinationResponse(**dest_data) ) elif existing_method and existing_method.destinations: @@ -533,15 +516,13 @@ async def update_checkout( elif customer_addresses: for addr in customer_addresses: resp_destinations.append( - FulfillmentDestination( - root=ShippingDestinationResponse( - id=addr.id, - street_address=addr.street_address, - city=addr.city, - region=addr.state, # Map state to region - postal_code=addr.postal_code, - address_country=addr.country, - ) + ShippingDestinationResponse( + id=addr.id, + street_address=addr.street_address, + address_locality=addr.city, + address_region=addr.state, # Map state to region + postal_code=addr.postal_code, + address_country=addr.country, ) ) @@ -577,10 +558,8 @@ async def update_checkout( ) resp_methods.append(method_resp) - existing.fulfillment = FulfillmentWrapper( - root=FulfillmentResponseClass( - methods=resp_methods, - ) + existing.fulfillment = FulfillmentResponseClass( + methods=resp_methods, ) if getattr(checkout_req, "discounts", None): @@ -665,8 +644,8 @@ async def complete_checkout( # Validate Fulfillment (Required for completion in this implementation) fulfillment_valid = False - if checkout.fulfillment and checkout.fulfillment.root.methods: - for method in checkout.fulfillment.root.methods: + if checkout.fulfillment and checkout.fulfillment.methods: + for method in checkout.fulfillment.methods: if method.type == "shipping" and not method.selected_destination_id: continue if method.groups: @@ -711,21 +690,18 @@ async def complete_checkout( # Create and persist Order expectations = [] - if checkout.fulfillment and checkout.fulfillment.root.methods: - for method in checkout.fulfillment.root.methods: + if checkout.fulfillment and checkout.fulfillment.methods: + for method in checkout.fulfillment.methods: selected_dest = None if method.selected_destination_id and method.destinations: for dest in method.destinations: - dest_root = getattr(dest, "root", dest) - if ( - getattr(dest_root, "id", None) == method.selected_destination_id - ): + if dest.id == method.selected_destination_id: selected_dest = PostalAddress( - street_address=getattr(dest_root, "street_address", None), - address_locality=getattr(dest_root, "address_locality", None), - address_region=getattr(dest_root, "address_region", None), - postal_code=getattr(dest_root, "postal_code", None), - address_country=getattr(dest_root, "address_country", None), + street_address=dest.street_address, + address_locality=dest.address_locality, + address_region=dest.address_region, + postal_code=dest.postal_code, + address_country=dest.address_country, ) break @@ -786,25 +762,18 @@ async def complete_checkout( order_line_items.append(oli) order = Order( - ucp=UcpMetadata( - root=ResponseOrder( - version=getattr( - checkout.ucp.root, "version", Version("2026-01-23") - ), - capabilities={ - getattr(k, "root", k): v - for k, v in checkout.ucp.root.capabilities.items() - } - if hasattr(checkout.ucp.root, "capabilities") - and checkout.ucp.root.capabilities - else {}, - ) + ucp=ResponseOrder( + version=getattr(checkout.ucp, "version", "2026-01-23"), + capabilities=dict(checkout.ucp.capabilities) + if hasattr(checkout.ucp, "capabilities") and checkout.ucp.capabilities + else {}, ), id=checkout.order.id, checkout_id=checkout.id, permalink_url=checkout.order.permalink_url, line_items=order_line_items, - totals=[total_resp.Total(**t.model_dump()) for t in checkout.totals], + totals=checkout.totals, + currency=checkout.currency, fulfillment=OrderFulfillment(expectations=expectations, events=[]), ) @@ -1040,19 +1009,19 @@ async def _recalculate_totals( checkout.totals.append(TotalResponse(type="subtotal", amount=grand_total)) # Fulfillment Logic - if checkout.fulfillment and checkout.fulfillment.root.methods: + if checkout.fulfillment and checkout.fulfillment.methods: # Fetch promotions once for the loop promotions = await db.get_active_promotions(self.products_session) - for method in checkout.fulfillment.root.methods: + for method in checkout.fulfillment.methods: # 1. Identify Destination and Calculate Options calculated_options = [] if method.type == "shipping" and method.selected_destination_id: selected_dest = None if method.destinations: for dest in method.destinations: - if dest.root.id == method.selected_destination_id: - selected_dest = dest.root + if dest.id == method.selected_destination_id: + selected_dest = dest break if selected_dest: @@ -1066,10 +1035,7 @@ async def _recalculate_totals( logger.info( "Available destinations in method %s: %s", method.id, - [ - f"{d.root.id} ({d.root.address_country})" - for d in method.destinations - ], + [f"{d.id} ({d.address_country})" for d in method.destinations], ) try: # Map ShippingDestination to PostalAddress for service call From ae4221e206a24807b1f5cd8fe4da5b177be63bee Mon Sep 17 00:00:00 2001 From: damaz91 Date: Mon, 13 Jul 2026 10:16:24 +0000 Subject: [PATCH 2/2] refactor: remove inner_dest and use dest_req directly --- .../server/services/checkout_service.py | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/rest/python/server/services/checkout_service.py b/rest/python/server/services/checkout_service.py index d509d7f..75adbc5 100644 --- a/rest/python/server/services/checkout_service.py +++ b/rest/python/server/services/checkout_service.py @@ -260,17 +260,14 @@ async def create_checkout( # The response model is FulfillmentDestinationResponse -> # ShippingDestinationResponse - # Extract the inner ShippingDestinationRequest - inner_dest = dest_req - resp_destinations.append( ShippingDestinationResponse( - id=getattr(inner_dest, "id", None) or str(uuid.uuid4()), - address_country=inner_dest.address_country, - postal_code=inner_dest.postal_code, - address_region=inner_dest.address_region, - address_locality=inner_dest.address_locality, - street_address=inner_dest.street_address, + id=getattr(dest_req, "id", None) or str(uuid.uuid4()), + address_country=dest_req.address_country, + postal_code=dest_req.postal_code, + address_region=dest_req.address_region, + address_locality=dest_req.address_locality, + street_address=dest_req.street_address, ) ) @@ -492,9 +489,7 @@ async def update_checkout( if m_req.destinations: # Use provided destinations for dest_req in m_req.destinations: - # Extract inner dest - inner_dest = dest_req - dest_data = inner_dest.model_dump(exclude_none=True) + dest_data = dest_req.model_dump(exclude_none=True) # Persist addresses for known customers if existing.buyer and existing.buyer.email: