Добавлен заказ накладной
This commit is contained in:
+59
-27
@@ -119,7 +119,15 @@
|
||||
- Каждый адаптер владеет своей конфигурацией; наружу экспонирует только service-facing methods, необходимые соответствующему use-case
|
||||
- Для расчёта тарифа CDEK adapter принимает city identifiers из `DeliveryCalculationRequest`, находит запись в `cities_map`, берёт `cdek.code` и передаёт его в CDEK API
|
||||
|
||||
Для CDEK order contract mapper принимает `InitPaymentRequest`, сериализует `sender.phone` и `recipient.phone` в provider payload `phones` с одним элементом, не отправляет `services` при отсутствии значения, конвертирует `packages[*].weight` из килограммов в граммы и возвращает `entity.uuid` строкой.
|
||||
Для CDEK order contract mapper принимает новый `InitPaymentRequest` и собирает provider payload:
|
||||
- `number = orderUuid`, `type = 2`, `tariff_code = systemData.tariff.tariffCode`.
|
||||
- `sender`/`recipient` маппятся из `senderContact`/`receiverContact`: `name = fullName`, `email`, `phones = [{number, additional: phoneExt}]`. При `isCompany=true` добавляются `contragent_type="LEGAL_ENTITY"`, `company`, `inn`, `kpp`.
|
||||
- `from_location`/`to_location` собираются из `senderAddress`/`receiverAddress`: `code` берётся из `cities_map` по `cityId`, `address` склеивается строкой `"{city}, {street}, {house}, кв. {apartment}"` (хвост `кв.` опускается при пустом `apartment`), `postal_code = zip`.
|
||||
- `packages[0]` содержит `number = orderUuid`, `weight = round(float(systemData.weight) * 1000)` в граммах; при `parcelType='parcel'` добавляются `length`, `width`, `height` из `systemData.dimensions`; при `parcelType='doc'` габариты не передаются.
|
||||
- `packages[0].items[0]` пробрасывает `content.description` как `name`.
|
||||
- `shipment_point.date = pickupDate.date()`, `delivery_point.date = deliveryDate.date()` (если задан).
|
||||
- Поле верхнего уровня `comment` собирается из `content.description` (если есть).
|
||||
- Возвращает `entity.uuid` строкой.
|
||||
|
||||
### Adapter (`app/adapters/tbank`)
|
||||
- `base.py` — исключения TBank payment adapter
|
||||
@@ -203,36 +211,60 @@ postal_code: str | None
|
||||
```
|
||||
|
||||
### Входная: `InitPaymentRequest`
|
||||
Контракт ручки `/api/v1/delivery/order` использует camelCase в JSON; Pydantic-
|
||||
модели хранят snake_case поля и принимают входной JSON через alias-generator.
|
||||
```
|
||||
order_uuid: str
|
||||
price: int
|
||||
type: Literal[2]
|
||||
tariff_code: Literal[535]
|
||||
comment: str | None
|
||||
sender:
|
||||
name: str
|
||||
email: str
|
||||
phone: {number: str}
|
||||
recipient:
|
||||
name: str
|
||||
email: str
|
||||
phone: {number: str}
|
||||
from_location:
|
||||
address: str
|
||||
orderUuid: str
|
||||
senderAddress:
|
||||
cityId: int
|
||||
city: str
|
||||
country_code: str
|
||||
to_location:
|
||||
address: str
|
||||
city: str
|
||||
country_code: str
|
||||
services: list[{code: str, parameter: str}] | None
|
||||
packages: list[{number: str, weight: int, length: int, width: int, height: int, comment: str | None}]
|
||||
street: str
|
||||
house: str
|
||||
apartment: str | None
|
||||
zip: str
|
||||
comment: str | None
|
||||
senderContact:
|
||||
fullName: str
|
||||
email: str | None
|
||||
phone: str
|
||||
phoneExt: str | None
|
||||
isCompany: bool
|
||||
companyName: str | None # обязателен при isCompany=true
|
||||
inn: str | None # обязателен при isCompany=true
|
||||
kpp: str | None # обязателен при isCompany=true
|
||||
receiverAddress: <структура senderAddress>
|
||||
receiverContact: <структура senderContact>
|
||||
content:
|
||||
description: str | None
|
||||
pickupDate: datetime # ISO 8601
|
||||
deliveryDate: datetime | None # ISO 8601
|
||||
accountEmail: str
|
||||
systemData:
|
||||
tariff:
|
||||
provider: str
|
||||
serviceName: str
|
||||
price: int # копейки
|
||||
deliveryDaysMin: int
|
||||
deliveryDaysMax: int
|
||||
tariffCode: int
|
||||
parcelType: Literal[doc, parcel]
|
||||
docPackaging: Literal[envelope, bag] | None # для doc
|
||||
weight: str
|
||||
dimensions: # null/отсутствует для doc
|
||||
length: str
|
||||
width: str
|
||||
height: str
|
||||
```
|
||||
|
||||
`price` задаётся в копейках, является обязательным целым числом и должен быть больше 0.
|
||||
`from_location.address` и `to_location.address` должны содержать точные значения адреса, выбранные клиентом; payment flow не выполняет address suggestion lookup.
|
||||
`sender.phone` и `recipient.phone` представляют единственный телефон для соответствующей стороны; передача нескольких телефонов во входном API не поддерживается.
|
||||
`packages[*].weight` в `InitPaymentRequest` задаётся в килограммах; CDEK order mapper конвертирует его в граммы для provider payload.
|
||||
`systemData.tariff.price` задаётся в копейках, является обязательным целым
|
||||
числом и должен быть больше 0; backend использует его как сумму платежа
|
||||
TBank без пересчёта.
|
||||
`senderAddress.cityId` и `receiverAddress.cityId` используют общий справочник
|
||||
`cities_map` (тот же идентификатор, что и в `DeliveryCalculationRequest`).
|
||||
Для `parcelType='doc'` `systemData.dimensions` отсутствует или равен `null`,
|
||||
для `parcelType='parcel'` — обязателен.
|
||||
При `isCompany=true` поля `companyName`, `inn`, `kpp` обязательны.
|
||||
`pickupDate` и `deliveryDate` принимаются и сохраняются как ISO datetime.
|
||||
|
||||
### Выходная: `InitPaymentResponse`
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user