- prepayment as DISCOUNT: live API rejects PRE_PAYMENT with 400 third_party.generic - normalize lowercase ETTN statuses returned by the live API - show Checkbox error code instead of bare 'Internal Server Error' - page size 50 for ETTN list, 429 rate limit is retryable, pause polling on it - phone in 380XXXXXXXXX format like portal receipts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
40 lines
1.5 KiB
Python
40 lines
1.5 KiB
Python
"""Схемы Checkbox API для ЕТТН-чеков (`/api/v1/ettn`).
|
|
|
|
Тело запроса собирается как обычный dict в `app/services/receipts.py` —
|
|
его снимок сохраняется в `receipts.request_body` без преобразований.
|
|
Здесь — только разбор ответа (`BaseEttnResponse`).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
|
|
|
|
class EttnStatus:
|
|
"""Статусы ЕТТН-чека в Checkbox (`OrderStatus`)."""
|
|
|
|
CREATED = "CREATED"
|
|
CANCELLED = "CANCELLED"
|
|
RECEIPT_ERROR = "RECEIPT_ERROR"
|
|
DONE = "DONE"
|
|
DONE_WITHOUT_SMS = "DONE_WITHOUT_SMS"
|
|
RETURNED = "RETURNED"
|
|
|
|
|
|
class EttnOut(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True)
|
|
|
|
id: str
|
|
status: str
|
|
ettn_number: str = Field(alias="ettnNumber")
|
|
total_sum: int | None = Field(default=None, alias="totalSum")
|
|
receipt_id: str | None = Field(default=None, alias="receiptId")
|
|
raw_error: str | None = Field(default=None, alias="rawError")
|
|
|
|
# В OpenAPI статусы заглавные, а боевой API отдаёт строчные (`"done"`,
|
|
# `"created"`) — приводим к одному регистру, иначе статусы не сопоставятся.
|
|
@field_validator("status", mode="before")
|
|
@classmethod
|
|
def _upper_status(cls, value: object) -> object:
|
|
return value.upper() if isinstance(value, str) else value
|