Добавлены задачи на сервис подсказок
This commit is contained in:
+41
-1
@@ -17,7 +17,10 @@
|
||||
|
||||
- Принимать запрос на расчёт стоимости доставки (идентификаторы городов отправления/назначения, вес, габариты)
|
||||
- Поддерживать необязательный параметр `parcel_type` в запросе расчёта стоимости доставки для фильтрации тарифов по типу отправления
|
||||
- Предоставлять отдельный endpoint подсказок адреса, чтобы frontend мог получить точное значение для `from_location.address` и `to_location.address` перед созданием заказа
|
||||
- Принимать запрос на создание заказа CDEK по контракту из `http-client.http` для сценария "доставка, до двери"
|
||||
- Выбирать сервис подсказок адреса по `country_code` через маппинг стран в конфиге
|
||||
- Для стран, сопоставленных с provider id `dadata`, использовать `dadata.ru`; конфигурация и wiring должны допускать отдельный address suggestion provider для европейских стран
|
||||
- Опрашивать всех зарегистрированных провайдеров параллельно
|
||||
- Возвращать унифицированный список тарифов, отсортированных по цене
|
||||
- Если провайдер вернул ошибку или не ответил вовремя — исключить его из результата, не падая целиком
|
||||
@@ -44,10 +47,11 @@
|
||||
|
||||
### Controller (`app/controllers/v1/delivery.py`)
|
||||
- `POST /api/v1/delivery/price` — принимает `DeliveryCalculationRequest`, возвращает `list[DeliveryPrice]`
|
||||
- `POST /api/v1/delivery/address/suggest` — принимает `AddressSuggestRequest`, возвращает `list[AddressSuggestion]`
|
||||
- `POST /api/v1/delivery/order` — принимает `OrderCreateRequest`, возвращает `OrderCreateResponse`
|
||||
- Парсинг и валидация входных данных через Pydantic
|
||||
- Маппинг исключений сервиса в HTTP-ответы
|
||||
- Каждый endpoint вызывает ровно один метод Service: `AggregatorService.get_all_prices()` или `AggregatorService.create_order()`
|
||||
- Каждый endpoint вызывает ровно один метод Service: `AggregatorService.get_all_prices()`, `AggregatorService.suggest_addresses()` или `AggregatorService.create_order()`
|
||||
|
||||
### Service (`app/services/aggregator.py`)
|
||||
- `AggregatorService.get_all_prices(request: DeliveryCalculationRequest) -> list[DeliveryPrice]`
|
||||
@@ -55,6 +59,8 @@
|
||||
- Принимает от каждого провайдера список тарифов и объединяет их в единый список
|
||||
- Фильтрует упавшие результаты
|
||||
- Сортирует тарифы по цене
|
||||
- `AggregatorService.suggest_addresses(request: AddressSuggestRequest) -> list[AddressSuggestion]`
|
||||
- `AggregatorService.suggest_addresses()` выбирает address suggestion provider по `country_code` через injected config mapping и оркестрирует ровно один adapter call
|
||||
- `AggregatorService.create_order(request: OrderCreateRequest) -> OrderCreateResponse`
|
||||
- `AggregatorService.create_order()` оркестрирует регистрацию заказа в CDEK через injected adapter dependency
|
||||
- Service не содержит бизнес-логики и provider HTTP-деталей
|
||||
@@ -89,6 +95,18 @@
|
||||
|
||||
Для сценария создания заказа CDEK adapter принимает валидированную order model, отправляет контракт `Регистрация заказа (тип "доставка", до двери)` из `http-client.http` и возвращает внутреннюю response model без утечки HTTP-деталей в Service.
|
||||
|
||||
### Adapter (`app/adapters/address_suggestions`)
|
||||
- `base.py` — абстрактный интерфейс `AddressSuggestionProvider`:
|
||||
```python
|
||||
class AddressSuggestionProvider(ABC):
|
||||
name: str
|
||||
async def suggest(self, request: AddressSuggestRequest) -> list[AddressSuggestion]: ...
|
||||
```
|
||||
- `dadata/client.py` — HTTP-клиент `dadata.ru` для address suggestions
|
||||
- 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
|
||||
|
||||
---
|
||||
|
||||
## Reference Data
|
||||
@@ -123,6 +141,21 @@ delivery_days_min: int
|
||||
delivery_days_max: int
|
||||
```
|
||||
|
||||
### Входная: `AddressSuggestRequest`
|
||||
```
|
||||
country_code: str
|
||||
city: str
|
||||
query: str
|
||||
limit: int | None
|
||||
```
|
||||
|
||||
### Выходная: `AddressSuggestion`
|
||||
```
|
||||
provider: str
|
||||
address: str
|
||||
postal_code: str | None
|
||||
```
|
||||
|
||||
### Входная: `OrderCreateRequest`
|
||||
```
|
||||
type: Literal[2]
|
||||
@@ -149,6 +182,8 @@ services: list[{code: str, parameter: str}]
|
||||
packages: list[{number: str, weight: int, length: int, width: int, height: int, comment: str | None}]
|
||||
```
|
||||
|
||||
`from_location.address` и `to_location.address` должны содержать точные значения адреса, выбранные клиентом; order flow не выполняет address suggestion lookup.
|
||||
|
||||
### Выходная: `OrderCreateResponse`
|
||||
```
|
||||
provider: str
|
||||
@@ -183,6 +218,10 @@ app/
|
||||
├── domain/
|
||||
│ └── price.py # Business Logic
|
||||
├── adapters/
|
||||
│ ├── address_suggestions/
|
||||
│ │ ├── base.py # Интерфейс Adapter
|
||||
│ │ └── dadata/
|
||||
│ │ └── client.py
|
||||
│ └── delivery_providers/
|
||||
│ ├── base.py # Интерфейс Adapter
|
||||
│ └── cdek/
|
||||
@@ -194,6 +233,7 @@ app/
|
||||
│ └── cache/
|
||||
│ └── redis_cache.py # Repository
|
||||
├── schemas/
|
||||
│ ├── address.py
|
||||
│ ├── request.py
|
||||
│ ├── response.py
|
||||
│ └── order.py
|
||||
|
||||
Reference in New Issue
Block a user