from __future__ import annotations from dataclasses import dataclass from decimal import Decimal from src.application.abstractions import IUnitOfWork from src.application.contracts import ILogger from src.application.domain.entities import OrderEntity,PaymentEntity from src.application.domain.exceptions import NotFoundException from src.application.services import PaymentQuote,PaymentQuoteService from src.infrastructure.database.decorators import transactional @dataclass(slots=True) class OrderPaymentResult: order: OrderEntity payment: PaymentEntity | None class GetPaymentConfigCommand: def __init__(self, *, payment_quote_service: PaymentQuoteService, logger: ILogger): self._payment_quote_service = payment_quote_service self._logger = logger async def __call__(self) -> PaymentQuote: quote = await self._payment_quote_service.get_reference_quote(Decimal('1.00')) self._logger.info({'event':'payment_config_requested'}) return quote class GetPaymentQuoteCommand: def __init__(self, *, payment_quote_service: PaymentQuoteService, logger: ILogger): self._payment_quote_service = payment_quote_service self._logger = logger async def __call__(self, usdt_amount: Decimal) -> PaymentQuote: quote = await self._payment_quote_service.get_quote(usdt_amount) self._logger.info({'event':'payment_quote_requested','usdt_amount':str(usdt_amount)}) return quote class GetPaymentQuoteFromRubCommand: def __init__(self, *, payment_quote_service: PaymentQuoteService, logger: ILogger): self._payment_quote_service = payment_quote_service self._logger = logger async def __call__(self, total_rub: Decimal) -> PaymentQuote: quote = await self._payment_quote_service.get_quote_from_total_rub(total_rub) self._logger.info({'event':'payment_quote_from_rub_requested','total_rub':str(total_rub)}) return quote class ListOrdersCommand: def __init__(self, *, unit_of_work: IUnitOfWork, logger: ILogger): self._unit_of_work = unit_of_work self._logger = logger @transactional async def __call__(self, *, user_id: str, limit: int, offset: int) -> list[OrderPaymentResult]: orders = await self._unit_of_work.order_repository.list_by_user_id( user_id=user_id, limit=limit, offset=offset, ) items: list[OrderPaymentResult] = [] for order in orders: if order.id is None: continue payment = await self._unit_of_work.payment_repository.get_by_order_id(order.id) items.append(OrderPaymentResult(order=order,payment=payment)) self._logger.info({'event':'orders_list_requested','user_id':user_id,'limit':limit,'offset':offset}) return items class ListPaymentsCommand: def __init__(self, *, unit_of_work: IUnitOfWork, logger: ILogger): self._unit_of_work = unit_of_work self._logger = logger @transactional async def __call__(self, *, user_id: str, limit: int, offset: int) -> list[PaymentEntity]: payments = await self._unit_of_work.payment_repository.list_by_user_id( user_id=user_id, limit=limit, offset=offset, ) self._logger.info({'event':'payments_list_requested','user_id':user_id,'limit':limit,'offset':offset}) return payments class GetPaymentCommand: def __init__(self, *, unit_of_work: IUnitOfWork, logger: ILogger): self._unit_of_work = unit_of_work self._logger = logger @transactional async def __call__(self, *, payment_id: str, user_id: str) -> PaymentEntity: payment = await self._unit_of_work.payment_repository.get_by_id_for_user( payment_id=payment_id, user_id=user_id, ) if payment is None: raise NotFoundException(message='Payment not found') self._logger.info({'event':'payment_detail_requested','payment_id':payment_id,'user_id':user_id}) return payment class GetOrderCommand: def __init__(self, *, unit_of_work: IUnitOfWork, logger: ILogger): self._unit_of_work = unit_of_work self._logger = logger @transactional async def __call__(self, *, order_id: str, user_id: str) -> OrderPaymentResult: order = await self._unit_of_work.order_repository.get_by_id_for_user(order_id=order_id,user_id=user_id) if order is None: raise NotFoundException(message='Order not found') payment = await self._unit_of_work.payment_repository.get_by_order_id(order_id) self._logger.info({'event':'order_detail_requested','order_id':order_id,'user_id':user_id}) return OrderPaymentResult(order=order,payment=payment) class GetOrderStatusCommand: def __init__(self, *, unit_of_work: IUnitOfWork, logger: ILogger): self._unit_of_work = unit_of_work self._logger = logger @transactional async def __call__(self, *, order_id: str, user_id: str) -> OrderPaymentResult: order = await self._unit_of_work.order_repository.get_by_id_for_user(order_id=order_id,user_id=user_id) if order is None: raise NotFoundException(message='Order not found') payment = await self._unit_of_work.payment_repository.get_by_order_id(order_id) self._logger.info({'event':'order_status_requested','order_id':order_id,'user_id':user_id}) return OrderPaymentResult(order=order,payment=payment)