013 add price multiplier

This commit is contained in:
Раис Юсупалиев
2026-03-09 16:14:49 +03:00
parent da301d4bc4
commit 2bd884c8d5
20 changed files with 312 additions and 25 deletions
+4 -3
View File
@@ -1,7 +1,7 @@
# Spec Tasks Index
> ⚠️ This file is generated. Do not edit manually.
> Generated at (UTC): `2026-03-08T19:58:23+00:00`
> Generated at (UTC): `2026-03-09T13:13:56+00:00`
## Tasks
@@ -20,9 +20,10 @@
| 010 | DONE | 2026-03-08 | Migrate to YAML-only configuration loading | `spec/tasks/010_migrate_to_yaml_only_configuration.md` |
| 011 | DONE | 2026-03-08 | Migrate Redis repository client to aioredis | `spec/tasks/011_migrate_redis_repository_to_aioredis.md` |
| 012 | DONE | 2026-03-08 | Remove observability and SigNoz stack for phase 1 | `spec/tasks/012_remove_observability_and_signoz_for_phase1.md` |
| 013 | DONE | 2026-03-09 | Add configurable provider price multiplier in domain logic | `spec/tasks/013_add_configurable_provider_price_multiplier.md` |
## Summary
- Total: **13**
- Total: **14**
- TODO: **0**
- DONE: **13**
- DONE: **14**
+3
View File
@@ -20,6 +20,7 @@
- Возвращать унифицированный список тарифов, отсортированных по цене
- Если провайдер вернул ошибку или не ответил вовремя — исключить его из результата, не падая целиком
- Кешировать ответы провайдеров для исключения повторных внешних запросов. Время кэширования вынести в конфиг
- Применять к цене, полученной от провайдера, конфигурируемый мультипликатор и округлять итоговую цену до целого значения
---
@@ -54,6 +55,8 @@
### Business Logic (`app/domain/`)
- Правила сортировки и фильтрации тарифов
- Логика сравнения цен
- Правила применения конфигурируемого мультипликатора к ценам провайдеров
- Округление цены после применения мультипликатора до целого значения по детерминированному правилу
- Нормализация входных данных (например, правила округления веса)
- Чистые функции, без IO, без зависимостей от фреймворков
@@ -0,0 +1,47 @@
---
id: 013
title: Add configurable provider price multiplier in domain logic
status: DONE
created: 2026-03-09
---
## Context
Сейчас `app/domain/price.py` валидирует и сортирует тарифы провайдеров без дополнительной постобработки цены. Появилось новое требование: перед возвратом результата применять к цене провайдера конфигурируемый multiplier из YAML-конфига и округлять итог до целого числа.
## Goal
Добавить в Business Logic детерминированное правило пересчёта `DeliveryPrice.price` через multiplier из секции `business_logic` и провести это значение через конфигурацию и service orchestration без переноса формулы в Service или Adapter.
## Constraints
- Соблюдать layered architecture из `AGENTS.md`.
- Формула умножения и округления должна жить только в `app/domain/`; Service может только передавать нужный параметр и делегировать вызов.
- Значение multiplier должно читаться из YAML-конфига через секцию `business_logic`.
- После применения multiplier цена должна оставаться `Decimal`, но иметь целочисленное значение.
- Правило округления должно быть явным и детерминированным: до `Decimal("1")` c `ROUND_HALF_UP`.
- Не изменять provider adapters, внешние HTTP-контракты и формат ответа кроме нового значения `price`.
- Не изменять файлы в `spec/`.
## Acceptance criteria
- В `business_logic` configuration section добавлено обязательное поле для multiplier цены провайдера с валидацией положительного значения.
- Domain functions применяют multiplier к каждой валидной цене провайдера до сортировки результата.
- Итоговая цена после умножения округляется до целого значения по правилу `ROUND_HALF_UP`.
- Service не содержит формулу расчёта и по-прежнему делегирует обработку цен в domain logic.
- Поведение одинаково для свежих ответов провайдера и для cache hit: в обоих случаях наружу возвращается уже пересчитанная цена.
## Definition of Done
- [ ] Обновлена конфигурация `business_logic` и YAML fixtures/example configs для multiplier.
- [ ] Реализована pure domain logic для пересчёта и округления цены.
- [ ] Service wiring передаёт multiplier в domain logic без добавления business rules в Service.
- [ ] Unit/service/config tests покрывают стандартные и edge-case сценарии.
## Tests
- Обновить `tests/domain/test_price.py` для проверки multiplier, округления `ROUND_HALF_UP`, пустого input и невалидных цен.
- Обновить `tests/services/test_aggregator.py` для проверки делегирования multiplier и одинакового поведения fresh/cache hit.
- Обновить `tests/config/test_config_sections.py` для проверки чтения multiplier из YAML и валидации невалидных значений.
- При необходимости обновить `tests/smoke/test_app_import.py` под обязательное новое поле конфигурации.
## Commands
- `poetry run pytest tests/domain/test_price.py -q`
- `poetry run pytest tests/services/test_aggregator.py -q`
- `poetry run pytest tests/config/test_config_sections.py -q`
- `poetry run pytest tests/smoke/test_app_import.py -q`
- `python3 spec/gen_spec_index.py --check`