from datetime import date from decimal import Decimal from enum import Enum from http import HTTPStatus from typing import Annotated from aws_lambda_powertools.event_handler.api_gateway import Router from aws_lambda_powertools.event_handler.exceptions import NotFoundError from aws_lambda_powertools.event_handler.openapi.params import Body, Query from layercake.dateutils import now from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair from api_gateway import JSONResponse from boto3clients import dynamodb_client from config import ORDER_TABLE, USER_TABLE from exceptions import OrgNotFoundError router = Router() dyn = DynamoDBPersistenceLayer(ORDER_TABLE, dynamodb_client) class BillingNotFoundError(NotFoundError): ... class PaymentMethod(str, Enum): BANK_SLIP = 'BANK_SLIP' MANUAL = 'MANUAL' @router.get('//billing') def billing( org_id: str, start_date: Annotated[date, Query()], end_date: Annotated[date, Query()], ): pk = f'BILLING#ORG#{org_id}' sk = f'START#{start_date}#END#{end_date}' billing = dyn.collection.get_item( KeyPair(pk, sk), exc_cls=BillingNotFoundError, ) return billing | dyn.collection.query( KeyPair( pk=pk, sk=f'{sk}#ENROLLMENT', ), limit=150, ) @router.put('//billing') def update( org_id: str, due_days: Annotated[Decimal, Body(embed=True, ge=1, le=90)], payment_method: Annotated[PaymentMethod, Body(embed=True)], ): with dyn.transact_writer() as transact: transact.condition( key=KeyPair(org_id, '0'), cond_expr='attribute_exists(sk)', exc_cls=OrgNotFoundError, table_name=USER_TABLE, ) transact.put( item={ 'id': org_id, 'sk': 'METADATA#BILLING', 'due_days': due_days, 'payment_method': payment_method.value, 'created_at': now(), }, table_name=USER_TABLE, ) return JSONResponse(status_code=HTTPStatus.NO_CONTENT)