feat: add get payments and orders

This commit is contained in:
2026-05-17 15:55:51 +03:00
parent 50bfaa9264
commit e41e89277f
7 changed files with 107 additions and 5 deletions

View File

@@ -29,6 +29,11 @@ class IPaymentRepository(ABC):
raise NotImplementedError raise NotImplementedError
@abstractmethod
async def get_by_id_for_user(self,*,payment_id:str,user_id:str) -> PaymentEntity | None:
raise NotImplementedError
@abstractmethod @abstractmethod
async def list_by_user_id(self,*,user_id:str,limit:int,offset:int) -> list[PaymentEntity]: async def list_by_user_id(self,*,user_id:str,limit:int,offset:int) -> list[PaymentEntity]:
raise NotImplementedError raise NotImplementedError

View File

@@ -1,4 +1,4 @@
from src.application.commands.create_order_command import CreateOrderCommand from src.application.commands.create_order_command import CreateOrderCommand
from src.application.commands.create_payment_command import CreatePaymentCommand from src.application.commands.create_payment_command import CreatePaymentCommand
from src.application.commands.create_crypto_transfer_completed_command import CreateCryptoTransferCompletedCommand from src.application.commands.create_crypto_transfer_completed_command import CreateCryptoTransferCompletedCommand
from src.application.commands.payment_read_commands import GetOrderCommand,GetOrderStatusCommand,GetPaymentConfigCommand,GetPaymentQuoteCommand,GetPaymentQuoteFromRubCommand,ListOrdersCommand,ListPaymentsCommand,OrderPaymentResult from src.application.commands.payment_read_commands import GetOrderCommand,GetOrderStatusCommand,GetPaymentCommand,GetPaymentConfigCommand,GetPaymentQuoteCommand,GetPaymentQuoteFromRubCommand,ListOrdersCommand,ListPaymentsCommand,OrderPaymentResult

View File

@@ -91,6 +91,24 @@ class ListPaymentsCommand:
return payments 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: class GetOrderCommand:
def __init__(self, *, unit_of_work: IUnitOfWork, logger: ILogger): def __init__(self, *, unit_of_work: IUnitOfWork, logger: ILogger):
self._unit_of_work = unit_of_work self._unit_of_work = unit_of_work

View File

@@ -103,6 +103,14 @@ class PaymentRepository(IPaymentRepository):
return self._to_entity(model) return self._to_entity(model)
async def get_by_id_for_user(self,*,payment_id:str,user_id:str) -> PaymentEntity | None:
stmt=select(Payment).where(Payment.id==payment_id,Payment.user_id==user_id)
model=await self._session.scalar(stmt)
if model is None:
return None
return self._to_entity(model)
async def list_by_user_id(self,*,user_id:str,limit:int,offset:int) -> list[PaymentEntity]: async def list_by_user_id(self,*,user_id:str,limit:int,offset:int) -> list[PaymentEntity]:
stmt=( stmt=(
select(Payment) select(Payment)

View File

@@ -1,7 +1,7 @@
from __future__ import annotations from __future__ import annotations
from fastapi import Depends from fastapi import Depends
from src.application.abstractions import IUnitOfWork from src.application.abstractions import IUnitOfWork
from src.application.commands import CreateCryptoTransferCompletedCommand,CreateOrderCommand,CreatePaymentCommand,GetOrderCommand,GetOrderStatusCommand,GetPaymentConfigCommand,GetPaymentQuoteCommand,GetPaymentQuoteFromRubCommand,ListOrdersCommand,ListPaymentsCommand from src.application.commands import CreateCryptoTransferCompletedCommand,CreateOrderCommand,CreatePaymentCommand,GetOrderCommand,GetOrderStatusCommand,GetPaymentCommand,GetPaymentConfigCommand,GetPaymentQuoteCommand,GetPaymentQuoteFromRubCommand,ListOrdersCommand,ListPaymentsCommand
from src.application.contracts import ICache,ILogger,IQueueMessanger,IReceipt from src.application.contracts import ICache,ILogger,IQueueMessanger,IReceipt
from src.application.contracts.i_itpay_service import IItPayService from src.application.contracts.i_itpay_service import IItPayService
from src.application.services import PaymentQuoteService from src.application.services import PaymentQuoteService
@@ -80,6 +80,13 @@ def get_list_payments_command(
return ListPaymentsCommand(unit_of_work=unit_of_work,logger=logger) return ListPaymentsCommand(unit_of_work=unit_of_work,logger=logger)
def get_payment_command(
logger: ILogger = Depends(get_logger),
unit_of_work: IUnitOfWork = Depends(get_unit_of_work),
) -> GetPaymentCommand:
return GetPaymentCommand(unit_of_work=unit_of_work,logger=logger)
def get_order_command( def get_order_command(
logger: ILogger = Depends(get_logger), logger: ILogger = Depends(get_logger),
unit_of_work: IUnitOfWork = Depends(get_unit_of_work), unit_of_work: IUnitOfWork = Depends(get_unit_of_work),

View File

@@ -6,7 +6,7 @@ from fastapi import APIRouter,Depends,Query,Request,WebSocket,WebSocketDisconnec
from fastapi.responses import ORJSONResponse from fastapi.responses import ORJSONResponse
from fastapi.security.utils import get_authorization_scheme_param from fastapi.security.utils import get_authorization_scheme_param
from ulid import ULID from ulid import ULID
from src.application.commands import CreateOrderCommand,CreatePaymentCommand,GetOrderCommand,GetOrderStatusCommand,GetPaymentConfigCommand,GetPaymentQuoteCommand,GetPaymentQuoteFromRubCommand,ListOrdersCommand,ListPaymentsCommand from src.application.commands import CreateOrderCommand,CreatePaymentCommand,GetOrderCommand,GetOrderStatusCommand,GetPaymentCommand,GetPaymentConfigCommand,GetPaymentQuoteCommand,GetPaymentQuoteFromRubCommand,ListOrdersCommand,ListPaymentsCommand
from src.application.contracts import IJwtService,ILogger from src.application.contracts import IJwtService,ILogger
from src.application.domain.dto import AccessTokenPayload,AuthContext from src.application.domain.dto import AccessTokenPayload,AuthContext
from src.application.domain.entities import OrderEntity,PaymentEntity from src.application.domain.entities import OrderEntity,PaymentEntity
@@ -15,10 +15,10 @@ from src.application.domain.exceptions import ApplicationException,ConflictExcep
from src.application.services import PaymentQuote from src.application.services import PaymentQuote
from src.infrastructure.context_vars import trace_id_var from src.infrastructure.context_vars import trace_id_var
from src.presentation.decorators import require_access_token, csrf_protect from src.presentation.decorators import require_access_token, csrf_protect
from src.presentation.dependencies.commands import get_create_order_command,get_create_payment_command,get_list_orders_command,get_list_payments_command,get_order_command,get_order_status_command,get_payment_config_command,get_payment_quote_command,get_payment_quote_from_rub_command from src.presentation.dependencies.commands import get_create_order_command,get_create_payment_command,get_list_orders_command,get_list_payments_command,get_order_command,get_order_status_command,get_payment_command,get_payment_config_command,get_payment_quote_command,get_payment_quote_from_rub_command
from src.presentation.dependencies.logger import get_logger from src.presentation.dependencies.logger import get_logger
from src.presentation.dependencies.security import get_jwt_service from src.presentation.dependencies.security import get_jwt_service
from src.presentation.schemas.order import CreateOrder,CreateOrderResponse,ErrorResponse,OrderDetailResponse,OrderPaymentResponse,OrdersResponse,OrderStatusResponse,OrderWithPaymentResponse,PaymentConfigResponse,PaymentQuoteResponse,PaymentResponse,PaymentsResponse from src.presentation.schemas.order import CreateOrder,CreateOrderResponse,ErrorResponse,OrderDetailResponse,OrderPaymentResponse,OrdersResponse,OrderStatusResponse,OrderWithPaymentResponse,PaymentConfigResponse,PaymentDetailResponse,PaymentQuoteResponse,PaymentResponse,PaymentsResponse
from src.presentation.schemas.itpay_payment_models import ItpayPaymentData from src.presentation.schemas.itpay_payment_models import ItpayPaymentData
order_router = APIRouter(prefix='/order', tags=['orders']) order_router = APIRouter(prefix='/order', tags=['orders'])
@@ -245,6 +245,65 @@ async def payment_quote_from_rub(
return _payment_quote_response(quote) return _payment_quote_response(quote)
@payment_router.get(
'/orders',
response_model=OrdersResponse,
status_code=200,
responses=ERROR_RESPONSES,
)
@csrf_protect()
async def payment_list_orders(
request: Request,
limit: int = Query(default=20, ge=1, le=100),
offset: int = Query(default=0, ge=0),
auth: AuthContext = Depends(require_access_token),
command: ListOrdersCommand = Depends(get_list_orders_command),
) -> OrdersResponse:
orders = await command(user_id=auth.user_id,limit=limit,offset=offset)
items = [_order_with_payment_response(item.order,item.payment) for item in orders]
return OrdersResponse(status_code=200,orders=items,limit=limit,offset=offset)
@payment_router.get(
'/payments',
response_model=PaymentsResponse,
status_code=200,
responses=ERROR_RESPONSES,
)
@csrf_protect()
async def payment_list_payments(
request: Request,
limit: int = Query(default=20, ge=1, le=100),
offset: int = Query(default=0, ge=0),
auth: AuthContext = Depends(require_access_token),
command: ListPaymentsCommand = Depends(get_list_payments_command),
) -> PaymentsResponse:
payments = await command(user_id=auth.user_id,limit=limit,offset=offset)
return PaymentsResponse(
status_code=200,
payments=[_payment_response(payment) for payment in payments],
limit=limit,
offset=offset,
)
@payment_router.get(
'/payments/{payment_id}',
response_model=PaymentDetailResponse,
status_code=200,
responses=ERROR_RESPONSES,
)
@csrf_protect()
async def payment_detail(
request: Request,
payment_id: str,
auth: AuthContext = Depends(require_access_token),
command: GetPaymentCommand = Depends(get_payment_command),
) -> PaymentDetailResponse:
payment = await command(payment_id=payment_id,user_id=auth.user_id)
return PaymentDetailResponse(status_code=200,payment=_payment_response(payment))
@orders_router.get( @orders_router.get(
'/orders', '/orders',
response_model=OrdersResponse, response_model=OrdersResponse,

View File

@@ -100,6 +100,11 @@ class PaymentsResponse(BaseModel):
offset: int offset: int
class PaymentDetailResponse(BaseModel):
status_code: int
payment: PaymentResponse
class OrderStatusResponse(BaseModel): class OrderStatusResponse(BaseModel):
status_code: int status_code: int
order_id: str order_id: str