Добавлен yandex geosuggest
This commit is contained in:
@@ -176,13 +176,10 @@ def load_tasks() -> List[TaskMeta]:
|
||||
|
||||
|
||||
def render_index(tasks: List[TaskMeta]) -> str:
|
||||
generated_at = dt.datetime.now(tz=dt.timezone.utc).replace(microsecond=0).isoformat()
|
||||
|
||||
lines: List[str] = []
|
||||
lines.append("# Spec Tasks Index")
|
||||
lines.append("")
|
||||
lines.append("> ⚠️ This file is generated. Do not edit manually.")
|
||||
lines.append(f"> Generated at (UTC): `{generated_at}`")
|
||||
lines.append("")
|
||||
lines.append("## Tasks")
|
||||
lines.append("")
|
||||
|
||||
+4
-3
@@ -1,7 +1,7 @@
|
||||
# Spec Tasks Index
|
||||
|
||||
> ⚠️ This file is generated. Do not edit manually.
|
||||
> Generated at (UTC): `2026-03-28T21:02:29+00:00`
|
||||
> Generated at (UTC): `2026-03-29T15:00:18+00:00`
|
||||
|
||||
## Tasks
|
||||
|
||||
@@ -30,9 +30,10 @@
|
||||
| 020 | DONE | 2026-03-21 | Rename price request model and use cities_map for CDEK codes | `spec/tasks/020_rename_price_request_model_and_use_cities_map_for_cdek_codes.md` |
|
||||
| 021 | DONE | 2026-03-25 | Add address suggestion adapter and country provider mapping | `spec/tasks/021_add_address_suggestion_adapter_and_country_mapping.md` |
|
||||
| 022 | DONE | 2026-03-25 | Add address suggestion endpoint | `spec/tasks/022_add_address_suggestion_endpoint.md` |
|
||||
| 023 | DONE | 2026-03-29 | Add Yandex Geosuggest address suggestion adapter and CIS routing | `spec/tasks/023_add_yandex_geosuggest_address_suggestion_adapter.md` |
|
||||
|
||||
## Summary
|
||||
|
||||
- Total: **23**
|
||||
- Total: **24**
|
||||
- TODO: **1**
|
||||
- DONE: **22**
|
||||
- DONE: **23**
|
||||
|
||||
+8
-2
@@ -20,7 +20,9 @@
|
||||
- Предоставлять отдельный endpoint подсказок адреса, чтобы frontend мог получить точное значение для `from_location.address` и `to_location.address` перед созданием заказа
|
||||
- Принимать запрос на создание заказа CDEK по контракту из `http-client.http` для сценария "доставка, до двери"
|
||||
- Выбирать сервис подсказок адреса по `country_code` через маппинг стран в конфиге
|
||||
- Для стран, сопоставленных с provider id `dadata`, использовать `dadata.ru`; конфигурация и wiring должны допускать отдельный address suggestion provider для европейских стран
|
||||
- Для `RU`, `BY` и `KZ`, сопоставленных с provider id `dadata`, использовать `dadata.ru`
|
||||
- Для `AM`, `AZ`, `KG`, `MD`, `TJ`, `TM` и `UZ`, сопоставленных с provider id `yandex_geosuggest`, использовать Yandex Geosuggest
|
||||
- Конфигурация и wiring должны допускать отдельные address suggestion providers для других регионов
|
||||
- Опрашивать всех зарегистрированных провайдеров параллельно
|
||||
- Возвращать унифицированный список тарифов, отсортированных по цене
|
||||
- Если провайдер вернул ошибку или не ответил вовремя — исключить его из результата, не падая целиком
|
||||
@@ -103,9 +105,11 @@
|
||||
async def suggest(self, request: AddressSuggestRequest) -> list[AddressSuggestion]: ...
|
||||
```
|
||||
- `dadata/client.py` — HTTP-клиент `dadata.ru` для address suggestions
|
||||
- `yandex_geosuggest/client.py` — HTTP-клиент Yandex Geosuggest `GET https://suggest-maps.yandex.ru/v1/suggest`
|
||||
- provider-specific модули address suggestion adapters инкапсулируют внешние API-контракты, auth, serialization и error handling
|
||||
- В конфиге adapter layer хранится маппинг `country_code -> provider_id` для выбора address suggestion provider
|
||||
- Address suggestion adapters возвращают только унифицированные internal models без утечки provider-specific payload в Service
|
||||
- Для Yandex Geosuggest adapter возвращает `postal_code=None`, так как контракт Geosuggest не используется как источник почтового индекса
|
||||
|
||||
---
|
||||
|
||||
@@ -222,7 +226,9 @@ app/
|
||||
├── adapters/
|
||||
│ ├── address_suggestions/
|
||||
│ │ ├── base.py # Интерфейс Adapter
|
||||
│ │ └── dadata/
|
||||
│ │ ├── dadata/
|
||||
│ │ └── client.py
|
||||
│ │ └── yandex_geosuggest/
|
||||
│ │ └── client.py
|
||||
│ └── delivery_providers/
|
||||
│ ├── base.py # Интерфейс Adapter
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
---
|
||||
id: 023
|
||||
title: Add Yandex Geosuggest address suggestion adapter and CIS routing
|
||||
status: DONE
|
||||
created: 2026-03-29
|
||||
---
|
||||
|
||||
## Context
|
||||
Текущий flow подсказок адреса поддерживает только `dadata` и уже использует routing по `country_code` через YAML-конфиг. Появилось новое требование: для части стран СНГ использовать отдельный provider `Yandex Geosuggest`, чтобы разгрузить `dadata` и зафиксировать routing по странам на уровне конфигурации.
|
||||
|
||||
## Goal
|
||||
Добавить новый adapter `yandex_geosuggest` для address suggestions, настроить routing по `country_code` так, чтобы `RU`, `BY` и `KZ` оставались на `dadata`, а `AM`, `AZ`, `KG`, `MD`, `TJ`, `TM` и `UZ` шли через `Yandex Geosuggest`, и покрыть это тестами без изменения публичного API endpoint.
|
||||
|
||||
## Constraints
|
||||
- Scope задачи ограничен flow подсказок адреса: YAML-конфиг, wiring зависимостей, service routing, новый adapter и тесты.
|
||||
- Controller path и публичный контракт `POST /api/v1/delivery/suggest-address` не изменять.
|
||||
- Service остаётся orchestration layer: выбирает provider по injected config mapping и вызывает ровно один adapter без provider-specific HTTP-логики.
|
||||
- Внешний IO должен оставаться только внутри нового adapter `app/adapters/address_suggestions/yandex_geosuggest/`.
|
||||
- Для `RU`, `BY` и `KZ` existing mapping на `dadata` должен сохраниться без изменения контракта `dadata` adapter.
|
||||
- Для `AM`, `AZ`, `KG`, `MD`, `TJ`, `TM` и `UZ` конфиг должен выбирать provider id `yandex_geosuggest`.
|
||||
- Новый adapter должен следовать официальному HTTP-контракту Yandex Geosuggest: `GET https://suggest-maps.yandex.ru/v1/suggest`, обязательные query-параметры `apikey` и `text`; для полного адреса использовать `print_address=1`; если в internal request передан `limit`, он должен маппиться в query-параметр `results`.
|
||||
- Unified mapping наружу должен по-прежнему возвращать только `AddressSuggestion` без утечки provider-specific payload.
|
||||
- Для Yandex Geosuggest поле `postal_code` не извлекается из provider response и должно возвращаться как `None`.
|
||||
- Ошибки Yandex Geosuggest `400` должны маппиться в deterministic provider request error; `403`, `429`, transport errors и `5xx` должны маппиться в adapter client error/unavailable path.
|
||||
- Scope задачи не включает добавление европейского provider, изменение order flow, price flow, новых endpoint'ов и расширение internal model `AddressSuggestion`.
|
||||
- Не изменять файлы в `spec/`.
|
||||
|
||||
## Acceptance criteria
|
||||
- В конфиге address suggestion providers добавлен provider id `yandex_geosuggest` с параметрами, необходимыми для вызова Yandex Geosuggest.
|
||||
- Country mapping в конфиге маршрутизирует `RU`, `BY`, `KZ` на `dadata`, а `AM`, `AZ`, `KG`, `MD`, `TJ`, `TM`, `UZ` на `yandex_geosuggest`.
|
||||
- Реализован adapter `app/adapters/address_suggestions/yandex_geosuggest/client.py`, который отправляет запрос в Yandex Geosuggest по официальному контракту и возвращает `list[AddressSuggestion]`.
|
||||
- Adapter использует `request.city` и `request.query` как значение `text`, передаёт `print_address=1`, а `request.limit` при наличии маппит в `results`.
|
||||
- Поля `address`, `street`, `house` и `flat` детерминированно извлекаются из ответа Yandex Geosuggest без утечки внешнего payload за пределы adapter contract, а `postal_code` возвращается как `None`.
|
||||
- `AggregatorService.suggest_addresses()` по `country_code` выбирает `yandex_geosuggest` для стран `AM`, `AZ`, `KG`, `MD`, `TJ`, `TM`, `UZ` и сохраняет routing на `dadata` для `RU`, `BY`, `KZ`.
|
||||
- При ответе Yandex Geosuggest с `400` service flow возвращает deterministic bad-request path, а при `403`, `429`, `5xx` и transport failure — deterministic unavailable path.
|
||||
|
||||
## Definition of Done
|
||||
- [ ] Добавлена конфигурация `yandex_geosuggest` и обновлён mapping стран для address suggestions.
|
||||
- [ ] Реализован новый Yandex Geosuggest adapter без утечки HTTP-деталей в Service.
|
||||
- [ ] Обновлён wiring address suggestion providers без изменения публичного endpoint контракта.
|
||||
- [ ] Добавлены tests для config, adapter mapping/error handling и service routing по странам СНГ, включая `postal_code=None` для Yandex Geosuggest.
|
||||
- [ ] Пройдены все команды из раздела Commands.
|
||||
|
||||
## Tests
|
||||
- Обновить `tests/config/test_config_sections.py` для проверки секции `yandex_geosuggest` и явного country mapping: `RU`, `BY`, `KZ` -> `dadata`; `AM`, `AZ`, `KG`, `MD`, `TJ`, `TM`, `UZ` -> `yandex_geosuggest`.
|
||||
- Добавить `tests/adapters/address_suggestions/yandex_geosuggest/test_client.py` для success case, mapping `limit -> results`, извлечения `address`/`street`/`house`/`flat`, возврата `postal_code=None` и error scenarios `400`, `403`, `429`, `5xx`.
|
||||
- Обновить `tests/services/test_address_suggestions.py` для проверки routing на `yandex_geosuggest` по странам `AM`, `AZ`, `KG`, `MD`, `TJ`, `TM`, `UZ` и сохранения routing на `dadata` для `RU`, `BY`, `KZ`.
|
||||
- При необходимости обновить `tests/controllers/v1/test_address_suggestions.py` только для совместимости существующего endpoint с новым provider routing без изменения публичного API.
|
||||
|
||||
## Commands
|
||||
- `poetry run pytest tests/config/test_config_sections.py -q`
|
||||
- `poetry run pytest tests/adapters/address_suggestions/yandex_geosuggest/test_client.py -q`
|
||||
- `poetry run pytest tests/services/test_address_suggestions.py -q`
|
||||
- `poetry run pytest tests/controllers/v1/test_address_suggestions.py -q`
|
||||
- `python3 spec/gen_spec_index.py`
|
||||
Reference in New Issue
Block a user