feat: add endpoints desc
This commit is contained in:
@@ -3,7 +3,7 @@ from decimal import Decimal
|
||||
from src.application.abstractions import IUnitOfWork
|
||||
from src.application.contracts import ILogger,IReceipt
|
||||
from src.application.domain.enums import PaymentStatus
|
||||
from src.application.domain.exceptions import ApplicationException
|
||||
from src.application.domain.exceptions import ApplicationException,NotFoundException,PaymentMetadataException,ReceiptDataException
|
||||
from src.infrastructure.database.decorators import transactional
|
||||
|
||||
|
||||
@@ -17,19 +17,19 @@ class CreateCryptoTransferCompletedCommand:
|
||||
@transactional
|
||||
async def __call__(self, *, order_id: str, user_id: str, web3_transaction_hash: str | None = None) -> None:
|
||||
if not order_id:
|
||||
raise ApplicationException(status_code=400, message='Crypto transfer completed message missing order_id')
|
||||
raise PaymentMetadataException(message='Crypto transfer completed message missing order_id')
|
||||
if not user_id:
|
||||
raise ApplicationException(status_code=400, message='Crypto transfer completed message missing user_id')
|
||||
raise PaymentMetadataException(message='Crypto transfer completed message missing user_id')
|
||||
await self._unit_of_work.payment_repository.update_crypto_transfer_completed(
|
||||
order_id=order_id,
|
||||
web3_transaction_hash=web3_transaction_hash,
|
||||
)
|
||||
user = await self._unit_of_work.user_repository.get(user_id)
|
||||
if user is None:
|
||||
raise ApplicationException(status_code=404, message='User not found')
|
||||
raise NotFoundException(message='User not found')
|
||||
email = str(user.email or '').strip()
|
||||
if not email:
|
||||
raise ApplicationException(status_code=400, message='User email missing')
|
||||
raise ReceiptDataException(message='User email missing')
|
||||
customer_info = ' '.join(
|
||||
part
|
||||
for part in (
|
||||
@@ -40,28 +40,28 @@ class CreateCryptoTransferCompletedCommand:
|
||||
if part
|
||||
)
|
||||
if not customer_info:
|
||||
raise ApplicationException(status_code=400, message='User full name missing')
|
||||
raise ReceiptDataException(message='User full name missing')
|
||||
customer_inn = str(user.inn or '').strip()
|
||||
if not customer_inn:
|
||||
raise ApplicationException(status_code=400, message='User inn missing')
|
||||
raise ReceiptDataException(message='User inn missing')
|
||||
if user.birth_date is None:
|
||||
raise ApplicationException(status_code=400, message='User birth date missing')
|
||||
raise ReceiptDataException(message='User birth date missing')
|
||||
customer_birthday = f'{user.birth_date.isoformat()}T12:00:00.000Z'
|
||||
|
||||
order = await self._unit_of_work.order_repository.get_by_id(order_id)
|
||||
if order is None:
|
||||
raise ApplicationException(status_code=404, message='Order not found')
|
||||
raise NotFoundException(message='Order not found')
|
||||
if order.total_price is None:
|
||||
raise ApplicationException(status_code=400, message='Order total price missing for receipt')
|
||||
raise ReceiptDataException(message='Order total price missing for receipt')
|
||||
if order.service_fee is None:
|
||||
raise ApplicationException(status_code=400, message='Order service fee missing for receipt')
|
||||
raise ReceiptDataException(message='Order service fee missing for receipt')
|
||||
|
||||
total_amount = Decimal(str(order.total_price)).quantize(Decimal('0.01'))
|
||||
service_fee = Decimal(str(order.service_fee)).quantize(Decimal('0.01'))
|
||||
principal_amount = (total_amount - service_fee).quantize(Decimal('0.01'))
|
||||
|
||||
if principal_amount < 0:
|
||||
raise ApplicationException(status_code=400, message='Invalid receipt amounts: principal negative')
|
||||
raise ReceiptDataException(message='Invalid receipt amounts: principal negative')
|
||||
|
||||
try:
|
||||
receipt_response = await self._receipt.create_receipt(
|
||||
|
||||
@@ -7,7 +7,7 @@ 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.domain.exceptions import PriceChangedException
|
||||
from src.application.services import PaymentQuoteService
|
||||
from src.infrastructure.database.decorators import transactional
|
||||
from src.presentation.schemas.order import CreateOrder
|
||||
@@ -40,7 +40,7 @@ class CreateOrderCommand:
|
||||
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')
|
||||
raise PriceChangedException()
|
||||
|
||||
order = OrderEntity(
|
||||
user_id=user_id,
|
||||
|
||||
@@ -3,7 +3,7 @@ from ulid import ULID
|
||||
from src.application.abstractions import IUnitOfWork
|
||||
from src.application.contracts import ILogger,IQueueMessanger
|
||||
from src.application.domain.enums import PaymentStatus
|
||||
from src.application.domain.exceptions import ApplicationException
|
||||
from src.application.domain.exceptions import PaymentMetadataException
|
||||
from src.infrastructure.config import settings
|
||||
from src.infrastructure.database.decorators import transactional
|
||||
from src.presentation.schemas.itpay_payment_models import ItpayPaymentData
|
||||
@@ -25,9 +25,9 @@ class CreatePaymentCommand:
|
||||
trace_id = str(metadata.get('trace_id') or self._logger.get_trace_id())
|
||||
self._logger.set_trace_id(trace_id)
|
||||
if not order_id:
|
||||
raise ApplicationException(status_code=400, message='Itpay webhook metadata missing order_id')
|
||||
raise PaymentMetadataException(message='Itpay webhook metadata missing order_id')
|
||||
if not user_id:
|
||||
raise ApplicationException(status_code=400, message='Itpay webhook metadata missing user_id')
|
||||
raise PaymentMetadataException(message='Itpay webhook metadata missing user_id')
|
||||
payment_created = await self._unit_of_work.payment_repository.create_completed(
|
||||
user_id=user_id,
|
||||
order_id=order_id,
|
||||
|
||||
@@ -2,9 +2,17 @@ from src.application.domain.exceptions.application_exception import ApplicationE
|
||||
from src.application.domain.exceptions.bad_gateway_exception import BadGatewayException
|
||||
from src.application.domain.exceptions.bad_request_exception import BadRequestException
|
||||
from src.application.domain.exceptions.conflict_exception import ConflictException
|
||||
from src.application.domain.exceptions.csrf_exception import CsrfException
|
||||
from src.application.domain.exceptions.forbidden_exception import ForbiddenException
|
||||
from src.application.domain.exceptions.internal_server_exception import InternalServerException
|
||||
from src.application.domain.exceptions.jwt_exception import JwtException
|
||||
from src.application.domain.exceptions.not_found_exception import NotFoundException
|
||||
from src.application.domain.exceptions.payment_metadata_exception import PaymentMetadataException
|
||||
from src.application.domain.exceptions.payment_provider_exception import PaymentProviderException
|
||||
from src.application.domain.exceptions.price_changed_exception import PriceChangedException
|
||||
from src.application.domain.exceptions.receipt_data_exception import ReceiptDataException
|
||||
from src.application.domain.exceptions.receipt_provider_exception import ReceiptProviderException
|
||||
from src.application.domain.exceptions.rate_limit_exception import RateLimitException
|
||||
from src.application.domain.exceptions.service_unavailable_exception import ServiceUnavailableException
|
||||
from src.application.domain.exceptions.unauthorized_exception import UnauthorizedException
|
||||
|
||||
@@ -13,9 +21,17 @@ __all__ = [
|
||||
'BadGatewayException',
|
||||
'BadRequestException',
|
||||
'ConflictException',
|
||||
'CsrfException',
|
||||
'ForbiddenException',
|
||||
'InternalServerException',
|
||||
'JwtException',
|
||||
'NotFoundException',
|
||||
'PaymentMetadataException',
|
||||
'PaymentProviderException',
|
||||
'PriceChangedException',
|
||||
'ReceiptDataException',
|
||||
'ReceiptProviderException',
|
||||
'RateLimitException',
|
||||
'ServiceUnavailableException',
|
||||
'UnauthorizedException',
|
||||
]
|
||||
12
src/application/domain/exceptions/csrf_exception.py
Normal file
12
src/application/domain/exceptions/csrf_exception.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from __future__ import annotations
|
||||
from typing import Mapping
|
||||
from src.application.domain.exceptions.application_exception import ApplicationException
|
||||
|
||||
|
||||
class CsrfException(ApplicationException):
|
||||
def __init__(
|
||||
self,
|
||||
message: str = 'CSRF token invalid',
|
||||
headers: Mapping[str,str] | None = None,
|
||||
):
|
||||
super().__init__(status_code=403,message=message,headers=headers)
|
||||
13
src/application/domain/exceptions/jwt_exception.py
Normal file
13
src/application/domain/exceptions/jwt_exception.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from __future__ import annotations
|
||||
from typing import Mapping
|
||||
from src.application.domain.exceptions.application_exception import ApplicationException
|
||||
|
||||
|
||||
class JwtException(ApplicationException):
|
||||
def __init__(
|
||||
self,
|
||||
message: str = 'Invalid token',
|
||||
status_code: int = 401,
|
||||
headers: Mapping[str,str] | None = None,
|
||||
):
|
||||
super().__init__(status_code=status_code,message=message,headers=headers)
|
||||
@@ -0,0 +1,12 @@
|
||||
from __future__ import annotations
|
||||
from typing import Mapping
|
||||
from src.application.domain.exceptions.application_exception import ApplicationException
|
||||
|
||||
|
||||
class PaymentMetadataException(ApplicationException):
|
||||
def __init__(
|
||||
self,
|
||||
message: str = 'Payment metadata invalid',
|
||||
headers: Mapping[str,str] | None = None,
|
||||
):
|
||||
super().__init__(status_code=400,message=message,headers=headers)
|
||||
@@ -0,0 +1,12 @@
|
||||
from __future__ import annotations
|
||||
from typing import Mapping
|
||||
from src.application.domain.exceptions.application_exception import ApplicationException
|
||||
|
||||
|
||||
class PaymentProviderException(ApplicationException):
|
||||
def __init__(
|
||||
self,
|
||||
message: str = 'Payment provider error',
|
||||
headers: Mapping[str,str] | None = None,
|
||||
):
|
||||
super().__init__(status_code=502,message=message,headers=headers)
|
||||
12
src/application/domain/exceptions/price_changed_exception.py
Normal file
12
src/application/domain/exceptions/price_changed_exception.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from __future__ import annotations
|
||||
from typing import Mapping
|
||||
from src.application.domain.exceptions.application_exception import ApplicationException
|
||||
|
||||
|
||||
class PriceChangedException(ApplicationException):
|
||||
def __init__(
|
||||
self,
|
||||
message: str = 'Price has changed, please refresh and try again',
|
||||
headers: Mapping[str,str] | None = None,
|
||||
):
|
||||
super().__init__(status_code=409,message=message,headers=headers)
|
||||
13
src/application/domain/exceptions/rate_limit_exception.py
Normal file
13
src/application/domain/exceptions/rate_limit_exception.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from __future__ import annotations
|
||||
from typing import Mapping
|
||||
from src.application.domain.exceptions.application_exception import ApplicationException
|
||||
|
||||
|
||||
class RateLimitException(ApplicationException):
|
||||
def __init__(
|
||||
self,
|
||||
message: str = 'Too Many Requests',
|
||||
status_code: int = 429,
|
||||
headers: Mapping[str,str] | None = None,
|
||||
):
|
||||
super().__init__(status_code=status_code,message=message,headers=headers)
|
||||
12
src/application/domain/exceptions/receipt_data_exception.py
Normal file
12
src/application/domain/exceptions/receipt_data_exception.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from __future__ import annotations
|
||||
from typing import Mapping
|
||||
from src.application.domain.exceptions.application_exception import ApplicationException
|
||||
|
||||
|
||||
class ReceiptDataException(ApplicationException):
|
||||
def __init__(
|
||||
self,
|
||||
message: str = 'Receipt data invalid',
|
||||
headers: Mapping[str,str] | None = None,
|
||||
):
|
||||
super().__init__(status_code=400,message=message,headers=headers)
|
||||
@@ -0,0 +1,13 @@
|
||||
from __future__ import annotations
|
||||
from typing import Mapping
|
||||
from src.application.domain.exceptions.application_exception import ApplicationException
|
||||
|
||||
|
||||
class ReceiptProviderException(ApplicationException):
|
||||
def __init__(
|
||||
self,
|
||||
message: str = 'Receipt provider error',
|
||||
status_code: int = 502,
|
||||
headers: Mapping[str,str] | None = None,
|
||||
):
|
||||
super().__init__(status_code=status_code,message=message,headers=headers)
|
||||
Reference in New Issue
Block a user