feat: Add new command
This commit is contained in:
@@ -23,6 +23,7 @@ from src.application.commands.organization_wallet_commands import (
|
|||||||
from src.application.commands.purchase_request_commands import (
|
from src.application.commands.purchase_request_commands import (
|
||||||
ListPurchaseRequestsCommand,
|
ListPurchaseRequestsCommand,
|
||||||
GetPurchaseRequestCommand,
|
GetPurchaseRequestCommand,
|
||||||
|
UpdatePurchaseRequestCommand,
|
||||||
UpdatePurchaseRequestStatusCommand,
|
UpdatePurchaseRequestStatusCommand,
|
||||||
SetPurchaseRequestQuoteCommand,
|
SetPurchaseRequestQuoteCommand,
|
||||||
)
|
)
|
||||||
@@ -41,6 +42,7 @@ __all__ = [
|
|||||||
'UpdateOrganizationCommand',
|
'UpdateOrganizationCommand',
|
||||||
'ListPurchaseRequestsCommand',
|
'ListPurchaseRequestsCommand',
|
||||||
'GetPurchaseRequestCommand',
|
'GetPurchaseRequestCommand',
|
||||||
|
'UpdatePurchaseRequestCommand',
|
||||||
'UpdatePurchaseRequestStatusCommand',
|
'UpdatePurchaseRequestStatusCommand',
|
||||||
'SetPurchaseRequestQuoteCommand',
|
'SetPurchaseRequestQuoteCommand',
|
||||||
'ListOrganizationDocumentsCommand',
|
'ListOrganizationDocumentsCommand',
|
||||||
|
|||||||
@@ -81,10 +81,46 @@ class UpdatePurchaseRequestStatusCommand:
|
|||||||
values['tx_hash'] = tx_hash
|
values['tx_hash'] = tx_hash
|
||||||
if status == 'completed':
|
if status == 'completed':
|
||||||
values['completed_at'] = datetime.now(timezone.utc)
|
values['completed_at'] = datetime.now(timezone.utc)
|
||||||
|
else:
|
||||||
|
values['completed_at'] = None
|
||||||
|
|
||||||
return await self._unit_of_work.purchase_request_repository.update(request_id, values=values)
|
return await self._unit_of_work.purchase_request_repository.update(request_id, values=values)
|
||||||
|
|
||||||
|
|
||||||
|
class UpdatePurchaseRequestCommand:
|
||||||
|
ALLOWED_FIELDS = frozenset({
|
||||||
|
'status',
|
||||||
|
'usdt_amount',
|
||||||
|
'rub_amount',
|
||||||
|
'exchange_rate',
|
||||||
|
'service_fee_percent',
|
||||||
|
'comment',
|
||||||
|
'admin_comment',
|
||||||
|
'target_wallet_chain',
|
||||||
|
'target_wallet_address',
|
||||||
|
'tx_hash',
|
||||||
|
'assigned_to',
|
||||||
|
})
|
||||||
|
|
||||||
|
def __init__(self, unit_of_work: IUnitOfWork, logger: ILogger):
|
||||||
|
self._unit_of_work = unit_of_work
|
||||||
|
self._logger = logger
|
||||||
|
|
||||||
|
@transactional
|
||||||
|
async def __call__(self, request_id: str, *, values: dict[str, Any]) -> PurchaseRequestEntity:
|
||||||
|
filtered = {k: v for k, v in values.items() if k in self.ALLOWED_FIELDS}
|
||||||
|
status = filtered.get('status')
|
||||||
|
if status is not None:
|
||||||
|
if status not in VALID_STATUSES:
|
||||||
|
raise ApplicationException(status_code=400, message='Invalid status')
|
||||||
|
if status == 'completed':
|
||||||
|
filtered['completed_at'] = datetime.now(timezone.utc)
|
||||||
|
else:
|
||||||
|
filtered['completed_at'] = None
|
||||||
|
|
||||||
|
return await self._unit_of_work.purchase_request_repository.update(request_id, values=filtered)
|
||||||
|
|
||||||
|
|
||||||
class SetPurchaseRequestQuoteCommand:
|
class SetPurchaseRequestQuoteCommand:
|
||||||
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
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ from src.application.commands import (
|
|||||||
SearchPartiesCommand,
|
SearchPartiesCommand,
|
||||||
SetPurchaseRequestQuoteCommand,
|
SetPurchaseRequestQuoteCommand,
|
||||||
UpdateOrganizationCommand,
|
UpdateOrganizationCommand,
|
||||||
|
UpdatePurchaseRequestCommand,
|
||||||
UpdatePurchaseRequestStatusCommand,
|
UpdatePurchaseRequestStatusCommand,
|
||||||
PutOrganizationDocumentCommand,
|
PutOrganizationDocumentCommand,
|
||||||
)
|
)
|
||||||
@@ -186,6 +187,13 @@ def get_update_purchase_request_status_command(
|
|||||||
return UpdatePurchaseRequestStatusCommand(uow, logger)
|
return UpdatePurchaseRequestStatusCommand(uow, logger)
|
||||||
|
|
||||||
|
|
||||||
|
def get_update_purchase_request_command(
|
||||||
|
uow: IUnitOfWork = Depends(get_unit_of_work),
|
||||||
|
logger: ILogger = Depends(get_logger),
|
||||||
|
) -> UpdatePurchaseRequestCommand:
|
||||||
|
return UpdatePurchaseRequestCommand(uow, logger)
|
||||||
|
|
||||||
|
|
||||||
def get_set_purchase_request_quote_command(
|
def get_set_purchase_request_quote_command(
|
||||||
uow: IUnitOfWork = Depends(get_unit_of_work),
|
uow: IUnitOfWork = Depends(get_unit_of_work),
|
||||||
logger: ILogger = Depends(get_logger),
|
logger: ILogger = Depends(get_logger),
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ from src.application.commands import (
|
|||||||
GetPurchaseRequestCommand,
|
GetPurchaseRequestCommand,
|
||||||
ListPurchaseRequestsCommand,
|
ListPurchaseRequestsCommand,
|
||||||
SetPurchaseRequestQuoteCommand,
|
SetPurchaseRequestQuoteCommand,
|
||||||
|
UpdatePurchaseRequestCommand,
|
||||||
UpdatePurchaseRequestStatusCommand,
|
UpdatePurchaseRequestStatusCommand,
|
||||||
)
|
)
|
||||||
from src.application.domain.dto import AdminAuthContext
|
from src.application.domain.dto import AdminAuthContext
|
||||||
@@ -12,6 +13,7 @@ from src.presentation.dependencies.commands import (
|
|||||||
get_get_purchase_request_command,
|
get_get_purchase_request_command,
|
||||||
get_list_purchase_requests_command,
|
get_list_purchase_requests_command,
|
||||||
get_set_purchase_request_quote_command,
|
get_set_purchase_request_quote_command,
|
||||||
|
get_update_purchase_request_command,
|
||||||
get_update_purchase_request_status_command,
|
get_update_purchase_request_status_command,
|
||||||
)
|
)
|
||||||
from src.presentation.schemas.mappers import purchase_request_to_response
|
from src.presentation.schemas.mappers import purchase_request_to_response
|
||||||
@@ -19,6 +21,7 @@ from src.presentation.schemas.organization import (
|
|||||||
PurchaseRequestListResponse,
|
PurchaseRequestListResponse,
|
||||||
PurchaseRequestResponse,
|
PurchaseRequestResponse,
|
||||||
SetPurchaseRequestQuoteBody,
|
SetPurchaseRequestQuoteBody,
|
||||||
|
UpdatePurchaseRequestBody,
|
||||||
UpdatePurchaseRequestStatusBody,
|
UpdatePurchaseRequestStatusBody,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -56,6 +59,17 @@ async def get_purchase_request(
|
|||||||
return purchase_request_to_response(item)
|
return purchase_request_to_response(item)
|
||||||
|
|
||||||
|
|
||||||
|
@purchase_requests_router.patch('/{request_id}', response_model=PurchaseRequestResponse)
|
||||||
|
async def update_purchase_request(
|
||||||
|
request_id: str,
|
||||||
|
body: UpdatePurchaseRequestBody,
|
||||||
|
auth: AdminAuthContext = Depends(require_admin_role('compliance', 'superadmin')),
|
||||||
|
command: UpdatePurchaseRequestCommand = Depends(get_update_purchase_request_command),
|
||||||
|
):
|
||||||
|
item = await command(request_id, values=body.model_dump(exclude_unset=True))
|
||||||
|
return purchase_request_to_response(item)
|
||||||
|
|
||||||
|
|
||||||
@purchase_requests_router.patch('/{request_id}/status', response_model=PurchaseRequestResponse)
|
@purchase_requests_router.patch('/{request_id}/status', response_model=PurchaseRequestResponse)
|
||||||
async def update_purchase_request_status(
|
async def update_purchase_request_status(
|
||||||
request_id: str,
|
request_id: str,
|
||||||
|
|||||||
@@ -121,6 +121,20 @@ class UpdatePurchaseRequestStatusBody(BaseModel):
|
|||||||
tx_hash: str | None = None
|
tx_hash: str | None = None
|
||||||
|
|
||||||
|
|
||||||
|
class UpdatePurchaseRequestBody(BaseModel):
|
||||||
|
status: str | None = None
|
||||||
|
usdt_amount: Decimal | None = Field(default=None, gt=0)
|
||||||
|
rub_amount: Decimal | None = Field(default=None, gt=0)
|
||||||
|
exchange_rate: Decimal | None = Field(default=None, gt=0)
|
||||||
|
service_fee_percent: Decimal | None = Field(default=None, ge=0)
|
||||||
|
comment: str | None = None
|
||||||
|
admin_comment: str | None = None
|
||||||
|
target_wallet_chain: str | None = Field(default=None, max_length=16)
|
||||||
|
target_wallet_address: str | None = Field(default=None, max_length=128)
|
||||||
|
tx_hash: str | None = Field(default=None, max_length=128)
|
||||||
|
assigned_to: str | None = None
|
||||||
|
|
||||||
|
|
||||||
class SetPurchaseRequestQuoteBody(BaseModel):
|
class SetPurchaseRequestQuoteBody(BaseModel):
|
||||||
rub_amount: Decimal = Field(gt=0)
|
rub_amount: Decimal = Field(gt=0)
|
||||||
exchange_rate: Decimal = Field(gt=0)
|
exchange_rate: Decimal = Field(gt=0)
|
||||||
|
|||||||
Reference in New Issue
Block a user