from http import HTTPStatus from typing import Annotated from aws_lambda_powertools.event_handler.api_gateway import Router from aws_lambda_powertools.event_handler.openapi.params import Body from layercake.dateutils import now from layercake.dynamodb import ( DynamoDBPersistenceLayer, KeyPair, SortKey, TransactKey, ) from pydantic import UUID4 from api_gateway import JSONResponse from boto3clients import dynamodb_client from config import ORDER_TABLE from exceptions import ConflictError, OrderConflictError, OrderNotFoundError from middlewares.authentication_middleware import User as Authenticated from .checkout import router as checkout from .payment_retries import router as payment_retries __all__ = ['checkout', 'payment_retries'] router = Router() dyn = DynamoDBPersistenceLayer(ORDER_TABLE, dynamodb_client) class FulfillmentConflictError(ConflictError): ... @router.get('/') def get_order(order_id: str): order = dyn.collection.get_items( TransactKey(order_id) + SortKey('0') + SortKey('ITEMS', rename_key='items', path_spec='items') + SortKey('CREATED_BY', rename_key='created_by') + SortKey('ADDRESS', rename_key='address') + SortKey('CREDIT_CARD', rename_key='credit_card') + SortKey('INVOICE', rename_key='invoice') + SortKey('FEE', rename_key='fee') + SortKey('TRANSACTION#STATS', rename_key='stats') + SortKey('FULFILLMENT', rename_key='fulfillment'), ) if not order: raise OrderNotFoundError('Order not found') attempts = dyn.collection.query(KeyPair(order_id, 'TRANSACTION#ATTEMPT#')) enrollments = dyn.collection.query(KeyPair(order_id, 'ENROLLMENT#')) return ( order | { 'payment_attempts': attempts['items'], 'enrollments': enrollments['items'], } # Post-migration (orders): remove the following lines | ({'created_at': order['create_date']} if 'create_date' in order else {}) | ({'paid_at': order['payment_date']} if 'payment_date' in order else {}) ) @router.post('//fulfillment') def fulfillment( order_id: str, org_id: Annotated[str | UUID4, Body(embed=True)], ): created_by: Authenticated = router.context['user'] with dyn.transact_writer() as transact: transact.condition( key=KeyPair(order_id, '0'), cond_expr='attribute_exists(sk) AND org_id = :org_id', expr_attr_values={ ':org_id': org_id, }, exc_cls=OrderConflictError, ) transact.put( item={ 'id': order_id, 'sk': 'FULFILLMENT', 'status': 'IN_PROGRESS', 'org_id': org_id, 'created_by': { 'id': created_by.id, 'name': created_by.name, }, 'created_at': now(), }, cond_expr='attribute_not_exists(sk)', exc_cls=FulfillmentConflictError, ) return JSONResponse(status_code=HTTPStatus.NO_CONTENT)