Files
pay-service/src/application/commands/create_order_command.py
2026-05-11 19:04:39 +03:00

69 lines
2.7 KiB
Python

from __future__ import annotations
from datetime import datetime, timezone
from decimal import Decimal
from ulid import ULID
from src.application.abstractions import IUnitOfWork
from src.application.contracts import ILogger
from src.application.contracts import IItPayService
from src.application.domain.entities.order import OrderEntity
from src.application.domain.enums import OrderStatus
from src.application.domain.exceptions import ApplicationException
from src.application.services import PaymentQuoteService
from src.infrastructure.database.decorators import transactional
from src.presentation.schemas.order import CreateOrder
class CreateOrderCommand:
def __init__(
self,
*,
unit_of_work: IUnitOfWork,
logger: ILogger,
payment_quote_service: PaymentQuoteService,
itpay_service: IItPayService,
) -> None:
self._unit_of_work = unit_of_work
self._logger = logger
self._payment_quote_service = payment_quote_service
self._itpay_service = itpay_service
@transactional
async def __call__(self, payment_data: CreateOrder, user_id: str) -> OrderEntity:
client_payment_id = str(ULID())
quote = await self._payment_quote_service.get_quote(payment_data.usdt_amount)
actual_gas_fee = quote.gas_fee
actual_usdt_exchange_rate = quote.usdt_exchange_rate
actual_service_fee = quote.service_fee
actual_total_price = quote.total_price
if actual_total_price > payment_data.total_price * Decimal('1.01'):
self._logger.error('Price has changed, please refresh and try again')
raise ApplicationException(status_code=409, message='Price has changed, please refresh and try again')
order = OrderEntity(
user_id=user_id,
usdt_amount=payment_data.usdt_amount,
usdt_exchange_rate=actual_usdt_exchange_rate,
gas_fee=actual_gas_fee,
service_fee=actual_service_fee,
total_price=actual_total_price,
status=OrderStatus.PENDING,
created_at=datetime.now(timezone.utc),
client_payment_id=client_payment_id,
)
saved = await self._unit_of_work.order_repository.create(order)
with_itpay = await self._itpay_service.create_payment(saved,self._logger.get_trace_id())
if with_itpay.status in (
OrderStatus.CANCELLED,
OrderStatus.REJECTED,
OrderStatus.ERROR,
):
await self._unit_of_work.order_repository.update_after_itpay_failure(with_itpay)
else:
await self._unit_of_work.order_repository.update_after_itpay_payment_created(with_itpay)
return with_itpay