import uuid from sqlalchemy import select from sqlalchemy.exc import IntegrityError from sqlalchemy.ext.asyncio import AsyncSession from app.models import OutboxEvent, Payment from app.schemas import PaymentCreate, PaymentCreatedEvent async def create_payment( session: AsyncSession, request: PaymentCreate, idempotency_key: str, ) -> Payment: payment_id = uuid.uuid4() payment = Payment( id=payment_id, amount=request.amount, currency=request.currency, description=request.description, metadata_=request.metadata, idempotency_key=idempotency_key, webhook_url=str(request.webhook_url), ) event = PaymentCreatedEvent(payment_id=payment_id) outbox_event = OutboxEvent( aggregate_id=payment_id, event_type="payment.created", payload=event.model_dump(mode="json"), ) session.add_all((payment, outbox_event)) try: await session.commit() except IntegrityError: await session.rollback() existing = await session.scalar( select(Payment).where(Payment.idempotency_key == idempotency_key) ) if existing is None: raise return existing return payment async def get_payment(session: AsyncSession, payment_id: uuid.UUID) -> Payment | None: return await session.get(Payment, payment_id)