Добавлен провайдер доставки CSE: SOAP-адаптер (Calc + SaveDocuments), маршрутизация init-payment по провайдеру, обобщение tariff_code до строки, география CSE в cities_map
Deploy / deploy (push) Failing after 52s

This commit is contained in:
Раис Юсупалиев
2026-05-31 20:13:52 +03:00
parent 6a2bf05ba5
commit 6c0f97adf6
41 changed files with 16113 additions and 4806 deletions
+6 -2
View File
@@ -41,9 +41,13 @@
| 032 | TODO | 2026-05-13 | Rework init-payment contract to camelCase and structured address/contact | `spec/tasks/032_rework_init_payment_contract_camelcase.md` |
| 033 | DONE | 2026-05-23 | Add CDEK waybill polling worker | `spec/tasks/033_add_waybill_polling_worker.md` |
| 034 | DONE | 2026-05-23 | Add CDEK waybill e-mail sender worker | `spec/tasks/034_add_waybill_email_sender_worker.md` |
| 035 | TODO | 2026-05-30 | Generalize tariff_code to string identifier | `spec/tasks/035_generalize_tariff_code_to_string.md` |
| 036 | TODO | 2026-05-30 | Add CSE SOAP delivery provider adapter | `spec/tasks/036_add_cse_delivery_provider_adapter.md` |
| 037 | TODO | 2026-05-30 | Add CSE geography to cities map | `spec/tasks/037_add_cse_geography_to_cities_map.md` |
| 038 | TODO | 2026-05-30 | Route init-payment validation and registration by provider | `spec/tasks/038_route_init_payment_by_provider.md` |
## Summary
- Total: **35**
- TODO: **2**
- Total: **39**
- TODO: **6**
- DONE: **33**
@@ -0,0 +1,44 @@
---
id: 035
title: Generalize tariff_code to string identifier
status: TODO
created: 2026-05-30
---
## Context
Добавляется второй провайдер доставки CSE («Карго»), который идентифицирует тариф
GUID-строкой. Текущие схемы и persistence используют числовой `tariff_code`
(`int`), несовместимый с CSE. Требуется обобщить идентификатор тарифа до строки для
обоих провайдеров.
## Goal
Перевести `tariff_code` на строковый тип в API-схемах и в persistence, сохранив
обратное поведение CDEK (числовой код передаётся как строка).
## Constraints
- Не изменять бизнес-правила в `app/domain/`.
- CDEK adapter должен формировать `tariff_code` как строку из своего числового кода.
- Сохранить совместимость существующего init-payment контракта, кроме типа
`tariff_code`.
- Изменение типа колонки выполнить миграцией Alembic.
- Не изменять файлы в `spec/`.
## Acceptance criteria
- `DeliveryPrice.tariff_code: str | None`.
- `SystemDataTariff.tariff_code: str` с непустым значением.
- CDEK `mapper`/`order_mapper` корректно работают со строковым `tariff_code`.
- Колонка `orders.tariff_code` имеет строковый тип; добавлена миграция.
- Существующие тесты обновлены под строковый `tariff_code`.
## Definition of Done
- [ ] Обновлены схемы `DeliveryPrice` и `SystemDataTariff`.
- [ ] Обновлены CDEK мапперы.
- [ ] Обновлены модель `Order` и миграция Alembic.
- [ ] Затронутые тесты проходят.
## Tests
- Обновить unit-тесты CDEK мапперов и схем.
- Проверить миграцию на тестовой БД.
## Commands
- `poetry run pytest -q`
@@ -0,0 +1,58 @@
---
id: 036
title: Add CSE SOAP delivery provider adapter
status: TODO
created: 2026-05-30
---
## Context
Нужен второй провайдер доставки CSE (система «Карго»). CSE предоставляет SOAP/1C
web-сервис (namespace `http://www.cargo3.ru`, endpoint `Web1C.1cws`), авторизация —
`login`/`password` строковыми параметрами в теле запроса. Данные передаются
универсальными структурами `Element`/`Row`; справочные значения — GUID. Спецификация
методов: `Calc` (расчёт стоимости) и `SaveDocuments` (регистрация заказа). Поллинг
статуса и получение PDF в этой задаче не реализуются.
## Goal
Реализовать adapter-пакет CSE: SOAP-транспорт и сериализация `Element`,
`CSEClient` с методами `calc()`/`save_order()`, мапперы расчёта и регистрации, и
`CSEProvider`, реализующий контракт `DeliveryProvider` плюс расчёт цены для
валидации платежа и регистрацию заказа.
## Constraints
- Только Adapter layer; без business decisions, фильтрации и сортировки.
- Весь XML/HTTP IO инкапсулирован в пакете `cse/`.
- Параметры CSE (`base_url`, `login`, `password`, retry policy, timeout, cache TTL)
приходят из секции `adapter` YAML-конфига; запрещён хардкод credentials.
- Ошибки CSE (`Properties.Error``List[Description]`) маппятся в иерархию
`ProviderClientError`/`ProviderRequestError`.
- Валюта `RUR` нормализуется в `RUB`; цена — `Decimal` в рублях.
- Не изменять файлы в `spec/`.
## Acceptance criteria
- Существует пакет `app/adapters/delivery_providers/cse/` с SOAP-сериализацией,
клиентом, мапперами и `CSEProvider` (`name = "cse"`).
- `CSEProvider.get_prices` возвращает унифицированные `DeliveryPrice` из ответа
`Calc` с `provider="cse"` и строковым `tariff_code` (GUID).
- `CSEProvider.get_payment_price` возвращает выбранный тариф для валидации платежа.
- `CSEProvider.register_order` выполняет `SaveDocuments` (`DocumentType=Order`) и
возвращает результат регистрации с номером документа.
- Адаптер использует значения из секции `adapter` YAML-конфига, включая
`cse_timeout_seconds` и `cse_cache_ttl_seconds`.
- Добавлены поля `cse_*` в `AdapterConfig` и шаблоны конфигов.
## Definition of Done
- [ ] Реализованы `soap`, `client`, `errors`, `mapper`, `order_mapper`, `CSEProvider`.
- [ ] Добавлены `cse_*` поля в `AdapterConfig`, `config.template.yaml`,
`config.test.yaml`.
- [ ] Adapter unit-тесты покрывают сериализацию/парсинг, mapping `Calc`/`SaveDocuments`
и обработку ошибок.
## Tests
- Unit-тесты SOAP-сериализации и парсинга `Element`.
- Unit-тесты мапперов на XML-примерах из спецификации.
- Тесты применения параметров CSE из секции `adapter`.
- Для внешних HTTP взаимодействий использовать stubs/mocks.
## Commands
- `poetry run pytest tests/adapters/delivery_providers/cse -q`
@@ -0,0 +1,39 @@
---
id: 037
title: Add CSE geography to cities map
status: TODO
created: 2026-05-30
---
## Context
Методы CSE `Calc` и `SaveDocuments` требуют географию отправления/доставки в виде
GUID (либо ФИАС/postcode). В проекте сопоставление город → коды провайдера хранится
в `app/cities.py` (блок `cdek` на каждый город). Для CSE требуется аналогичный блок
`cse` с GUID географии.
## Goal
Расширить `cities_map` данными географии CSE и зафиксировать справочные константы
CSE (вид груза `TypeOfCargo`, валюта `RUR`), необходимые адаптеру для запросов.
## Constraints
- Не изменять структуру существующего блока `cdek`.
- Города без поддержки CSE имеют `cse: None`.
- Константы вида груза/валюты держать в пакете адаптера `cse/` или в конфиге, без
бизнес-логики.
- Не изменять файлы в `spec/`.
## Acceptance criteria
- Каждый город в `cities_map` содержит блок `cse` (GUID географии) или `None`.
- Маппинг `parcel_type` (`doc`/`parcel`) → `TypeOfCargo` GUID и GUID валюты `RUR`
определены и используются адаптером CSE.
## Definition of Done
- [ ] `cities_map` дополнен блоком `cse`.
- [ ] Определены константы вида груза и валюты CSE.
- [ ] Тесты подтверждают чтение географии CSE для поддерживаемого города.
## Tests
- Unit-тесты сопоставления город → география CSE.
## Commands
- `poetry run pytest -q -k cities`
@@ -0,0 +1,48 @@
---
id: 038
title: Route init-payment validation and registration by provider
status: TODO
created: 2026-05-30
---
## Context
С появлением второго провайдера CSE `AggregatorService` должен выбирать адаптер
валидации цены и регистрации заказа по провайдеру выбранного тарифа. Сейчас сервис
жёстко использует единственный CDEK-адаптер. Поле `provider` уже присутствует в
`DeliveryPrice`/`SystemDataTariff`. Регистрация заказа выполняется при уведомлении
об оплате TBank. Поллинг статуса и email в этой задаче не затрагиваются.
## Goal
Маршрутизировать валидацию цены и регистрацию заказа по
`request.system_data.tariff.provider`, подключить `CSEProvider` в DI рядом с CDEK,
сохранять выбранного провайдера и номер заказа CSE в persistence.
## Constraints
- Controller вызывает Service без бизнес-ветвления.
- Service не содержит чистых бизнес-правил; маршрутизация — оркестрация.
- Не изменять контракт API, кроме уже обобщённого `tariff_code`.
- Колонки `cdek_*` не изменять; добавить `provider` и `cse_order_number` миграцией.
- Не изменять файлы в `spec/`.
## Acceptance criteria
- `GET /api/v1/delivery/calculate` возвращает агрегированные тарифы CDEK и CSE.
- `AggregatorService` выбирает адаптер валидации/регистрации по имени провайдера
тарифа; общий тип результата регистрации не привязан к CDEK.
- При оплате заказа с тарифом CSE регистрация выполняется через `CSEProvider`;
в `orders` сохранены `provider` и `cse_order_number`.
- DI в контроллере доставки инстанцирует и подключает `CSEProvider`.
## Definition of Done
- [ ] `AggregatorService` маршрутизирует по провайдеру (mapping адаптеров).
- [ ] Обобщён тип результата регистрации заказа.
- [ ] Модель `Order` и репозиторий дополнены (`provider`, `cse_order_number`,
`mark_cse_order_registered`); добавлена миграция.
- [ ] DI контроллера подключает CDEK и CSE.
- [ ] Тесты маршрутизации валидации/регистрации по провайдеру проходят.
## Tests
- Service unit-тесты маршрутизации (моки CDEK/CSE адаптеров).
- Тесты persistence для `provider`/`cse_order_number`.
## Commands
- `poetry run pytest tests/services -q`