T8: define task — ISO 4217 per-currency decimals (req ready)
Follow-up to T3 (Decimal migration): display layer still hardcodes :,.2f everywhere, which is wrong for JPY (0 dp) and 3-dp currencies like BHD/KWD/OMR. T8 = display-only refactor: - CURRENCY_DECIMALS + CurrencyConverter.format_money() in domain/ - replace 14 :,.2f literals across infrastructure/cli/ - rework 2 i18n templates that bake the format into the message string - extend tests/test_currency.py with JPY/BHD/USD/CHF cases Locked decisions (HALF_UP, ',' separator, suffix for unknown codes, internal precision untouched) recorded in req-T8.json for the executing node.
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"$schema": "metaagent-task-manifest",
|
||||
"version": "3.0",
|
||||
"session_id": "metaagent-005",
|
||||
"goal": "Серьёзный архитектурный рефактор: A1+A10 (слои+version), A2+A3 (pydantic), A4 (decimal), A7+A8+A9 (DI+repo), A5 (CLI decompose)",
|
||||
"session_id": "metaagent-006",
|
||||
"goal": "Серьёзный архитектурный рефактор: A1+A10 (слои+version), A2+A3 (pydantic), A4 (decimal), A7+A8+A9 (DI+repo), A5 (CLI decompose). P1: ISO 4217-aware currency display",
|
||||
"created_at": "2026-10-08T15:58:00Z",
|
||||
"tasks": [
|
||||
{ "id": "T1", "title": "Реструктуризация в domain/application/infrastructure + version=1", "status": "archived", "origin": "user:direct" },
|
||||
@@ -11,6 +11,7 @@
|
||||
{ "id": "T4", "title": "Repository pattern — ModelRepository", "status": "archived", "origin": "user:direct" },
|
||||
{ "id": "T5", "title": "Dependency Injection в сервисах", "status": "archived", "origin": "user:direct" },
|
||||
{ "id": "T6", "title": "Декомпозиция CLI", "status": "archived", "origin": "user:direct" },
|
||||
{ "id": "T7", "title": "Финальная валидация", "status": "archived", "origin": "user:direct" }
|
||||
{ "id": "T7", "title": "Финальная валидация", "status": "archived", "origin": "user:direct" },
|
||||
{ "id": "T8", "title": "ISO 4217-aware форматирование денег (per-currency decimals)", "status": "pending", "origin": "user:direct" }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# Task Manifest
|
||||
|
||||
**Session:** `metaagent-005`
|
||||
**Session:** `metaagent-005` (initial) → `metaagent-006` (T8 pending)
|
||||
**Goal:** Серьёзный архитектурный рефактор
|
||||
**Date:** 2026-10-08
|
||||
**Total tasks:** 7
|
||||
**Total tasks:** 8 (7 archived, 1 pending)
|
||||
|
||||
---
|
||||
|
||||
@@ -121,3 +121,34 @@
|
||||
- [ ] cf init, cf forecast, cf scenario, cf compare — работают
|
||||
- [ ] cf import data.xlsx → cf export — round-trip
|
||||
- [ ] README.md обновлён под новую структуру
|
||||
|
||||
---
|
||||
|
||||
## T8: ISO 4217-aware форматирование денег (per-currency decimals)
|
||||
|
||||
**Зависимости:** T3 (Decimal уже мигрирован)
|
||||
**Файлы:** `domain/currency.py`, `infrastructure/cli/services.py`, `infrastructure/cli/commands/{info,config_cmd}.py`, `infrastructure/cli/i18n.py`, `tests/test_currency.py`, `tests/test_i18n.py`
|
||||
|
||||
**Контекст:** Миграция на Decimal (T3) устранила арифметические ошибки, но отображение денег осталось наивным: во всех местах захардкожен формат `:,.2f` / `:.2f`. Это даёт два бага: (1) JPY показывается как `¥1,234.00` вместо `¥1,234`; (2) BHD/KWD/OMR (3 знака) вообще не поддерживаются. Словарь `CURRENCY_SYMBOLS` в `domain/currency.py` объявляет 8 валют, но семантика ISO 4217 не реализована.
|
||||
|
||||
**Что:**
|
||||
- Ввести `CURRENCY_DECIMALS: dict[str, int]` в `domain/currency.py` (минимум: JPY=0, BHD/KWD/OMR=3, остальные из поддерживаемого списка=2).
|
||||
- Добавить `CurrencyConverter.format_money(amount: Decimal, currency: str) -> str` — единая точка форматирования (символ + количество знаков).
|
||||
- Заменить все 14 захардкоженных `:,.2f` в `services.py`, `info.py`, `config_cmd.py` на вызов `format_money()` (или новый форматтер в i18n-шаблонах).
|
||||
- Переработать i18n-шаблоны `cmd.config.transaction_add.ok` и `cmd.config.recurring_add.ok` — убрать `{amount:.2f}`, передавать уже отформатированную строку.
|
||||
- Сохранить `_q()` в `forecast.py` для **сериализации прогноза** (JSON-результат должен быть стабильным), но не трогать внутреннюю арифметику — она остаётся на полной точности Decimal.
|
||||
- Граничный кейс: при конвертации `0.1 USD → JPY` сейчас даёт 8.07 JPY вместо ~7.86 JPY из-за `quantize("0.01")` в `convert()`. Решить — квантовать только при отображении, не при конверсии.
|
||||
|
||||
**Acceptance:**
|
||||
- [ ] `format_money(Decimal("1234.567"), "JPY") == "¥1,235"` (округление банкирское или HALF_UP — зафиксировать)
|
||||
- [ ] `format_money(Decimal("1234.567"), "USD") == "$1,234.57"`
|
||||
- [ ] `format_money(Decimal("1.234"), "BHD") == "BHD 1.234"` (3 знака)
|
||||
- [ ] Ни одного литерала `:,.2f` / `:.2f` для денег в `infrastructure/cli/` (за исключением явных UNIT-тестов форматтера)
|
||||
- [ ] Новые тесты в `tests/test_currency.py`: по одному на JPY, BHD, USD, плюс round-trip `format_money(format_money(x))` стабилен
|
||||
- [ ] `pytest` зелёный, существующие 67 тестов не сломаны
|
||||
- [ ] `cf info` на модели с JPY-счётом показывает целые йены, без `.00`
|
||||
|
||||
**Открытые вопросы (на согласование перед выполнением):**
|
||||
1. Округление для отображения — `ROUND_HALF_UP` (банковское кругление) или `ROUND_HALF_EVEN` (banker's rounding)? По умолчанию предлагаю `HALF_UP` для совместимости с T3.
|
||||
2. Формат `1,234` vs `1 234` (разделитель тысяч) — текущий `:,.2f` даёт запятую; оставляем?
|
||||
3. Для валют без символа в `CURRENCY_SYMBOLS` (например CHF) — выводить код префиксом (`CHF 1,234.56`) или суффиксом (`1,234.56 CHF`)?
|
||||
|
||||
Reference in New Issue
Block a user