Bind Nova Poshta API key to cash register (#3)

Each cash register stores its own encrypted NP API key. Status polling uses
register keys and binds an order to the register whose key sees the TTN as
its own (PhoneSender present); ETTN receipts are created from that register.
Migration 0008 moves the old NOVA_POSHTA_API_KEY into the default register.

Closes #3

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-25 13:02:40 +03:00
co-authored by Claude Opus 5.5
parent 2b92d82693
commit 8b3c2b6d63
22 changed files with 531 additions and 73 deletions
+10
View File
@@ -32,9 +32,19 @@ class TrackingStatusOut(BaseModel):
# какого-то типа накладной не возвращает `AfterpaymentOnGoodsCost`.
cod_amount: str | None = Field(default=None)
# Телефон отправителя NP отдаёт только кабинету отправителя (или получателя):
# по чужому ключу без телефона ответ урезан — нет ни отправителя, ни
# `AfterpaymentOnGoodsCost`. По этому полю определяется, чья это посылка.
phone_sender: str | None = Field(default=None, alias="PhoneSender")
# Статус оплаты аналогично раздвоен на `PaymentStatus`/`ExpressWaybillPaymentStatus`.
payment_status: str | None = Field(default=None)
@property
def is_own(self) -> bool:
"""ТТН видна ключу как своя — отправлена из кабинета этого ключа."""
return bool(self.phone_sender)
@model_validator(mode="before")
@classmethod
def _fold_express_fields(cls, data: Any) -> Any: