Ship fleet, availability, pricing, dispatch, routing, tracking, and settlement on delivery-service 0.10.8.0 with migrations and phase tests green. Co-authored-by: Cursor <cursoragent@cursor.com>
67 lines
2.1 KiB
Python
67 lines
2.1 KiB
Python
"""Settlement validators — Phase 10.8."""
|
|
from __future__ import annotations
|
|
|
|
from decimal import Decimal
|
|
|
|
from shared.exceptions import AppError
|
|
|
|
from app.models.types import SettlementIntentStatus
|
|
|
|
ALLOWED_TRANSITIONS: dict[str, set[SettlementIntentStatus]] = {
|
|
"submit": {SettlementIntentStatus.DRAFT},
|
|
"settle": {SettlementIntentStatus.SUBMITTED},
|
|
"fail": {SettlementIntentStatus.SUBMITTED},
|
|
"cancel": {SettlementIntentStatus.DRAFT, SettlementIntentStatus.PENDING},
|
|
}
|
|
|
|
TARGET_STATUS: dict[str, SettlementIntentStatus] = {
|
|
"submit": SettlementIntentStatus.SUBMITTED,
|
|
"settle": SettlementIntentStatus.SETTLED,
|
|
"fail": SettlementIntentStatus.FAILED,
|
|
"cancel": SettlementIntentStatus.CANCELLED,
|
|
}
|
|
|
|
TERMINAL = frozenset(
|
|
{
|
|
SettlementIntentStatus.SETTLED,
|
|
SettlementIntentStatus.FAILED,
|
|
SettlementIntentStatus.CANCELLED,
|
|
}
|
|
)
|
|
|
|
|
|
def ensure_settlement_transition(*, action: str, current: SettlementIntentStatus) -> None:
|
|
if current in TERMINAL:
|
|
raise AppError(
|
|
"تسویه در وضعیت پایانی است",
|
|
status_code=409,
|
|
error_code="settlement_terminal",
|
|
details={"status": current.value, "action": action},
|
|
)
|
|
allowed = ALLOWED_TRANSITIONS.get(action, set())
|
|
if current not in allowed:
|
|
raise AppError(
|
|
"انتقال وضعیت تسویه مجاز نیست",
|
|
status_code=409,
|
|
error_code="invalid_settlement_transition",
|
|
details={
|
|
"from_status": current.value,
|
|
"action": action,
|
|
"allowed_from": sorted(s.value for s in allowed),
|
|
},
|
|
)
|
|
|
|
|
|
def target_settlement_status(action: str) -> SettlementIntentStatus:
|
|
return TARGET_STATUS[action]
|
|
|
|
|
|
def validate_settlement_amount(amount: Decimal) -> Decimal:
|
|
if amount <= 0:
|
|
raise AppError(
|
|
"مبلغ تسویه باید بزرگتر از صفر باشد",
|
|
status_code=422,
|
|
error_code="invalid_settlement_amount",
|
|
)
|
|
return amount
|