109 lines
11 KiB
Markdown
109 lines
11 KiB
Markdown
# Tasks
|
||
|
||
Issue: WealthLedger/main#54. Ветки в каждом repo:
|
||
`feature/54-investment-performance-vs-index` от актуального `develop`.
|
||
|
||
## 1. Backend: история индексов
|
||
|
||
- [x] 1.1 [backend] Хранилище дневных закрытий индексов и состояния догрузки (аддитивная миграция)
|
||
- **Covers:** `instruments/market-index-history` — `Дневная история индексов Мосбиржи`
|
||
- **Source:** design «Data / Storage Changes»
|
||
- **Verification:** `npx prisma migrate dev` на одноразовой копии БД; `npm run verify`
|
||
- **Depends on:** none
|
||
- [x] 1.2 [backend] `MoexClient.indexHistory(secid, from, till)`: пагинация `history.cursor`, строгий разбор, сбой без частичных строк
|
||
- **Covers:** `instruments/market-index-history` — `Дневная история индексов Мосбиржи`
|
||
- **Source:** system-analysis «Contracts» (MOEX ISS), [index-refresh.mmd](system-analysis/sequences/index-refresh.mmd); design backend 5
|
||
- **Verification:** `moex.client.spec.ts`: несколько страниц, невалидная страница, таймаут, не-2xx
|
||
- **Depends on:** none
|
||
- [x] 1.3 [backend] `MarketIndexHistoryService`: покрытие периода, догрузка не чаще раза в час, single-flight, upsert, лог `integration.moex.index_history.*`, сбой → недостаточно покрытия
|
||
- **Covers:** `instruments/market-index-history` — `Дневная история индексов Мосбиржи`, `Свежесть и недоступность истории индексов`
|
||
- **Source:** system-analysis «Индексы MOEX», «Error and Recovery Semantics»; design backend 5, «Cross-cutting Implementation»
|
||
- **Verification:** unit-тесты сервиса (покрытие ±10 дн., час, параллельные вызовы, сбой с историей и без); `npm run verify`
|
||
- **Depends on:** 1.1, 1.2
|
||
|
||
## 2. Backend: расчёт результата
|
||
|
||
- [x] 2.1 [backend] Вынести `isCompleteValuation(snapshot)` в portfolio domain и использовать его при записи истории оценки
|
||
- **Covers:** `portfolio/investment-performance` — `Недоступный и неполный результат`
|
||
- **Source:** design backend 2; qa-analysis «Regression Impact»
|
||
- **Verification:** существующие тесты `portfolio-value-history` и новые unit-тесты функции проходят; `npm run verify`
|
||
- **Depends on:** none
|
||
- [x] 2.2 [backend] Domain: маппинг типов операций → роли, внешние потоки по дате Europe/Moscow, отсечка по `fetchedAt`, кандидаты на переводы в `all` без автоматического подтверждения, причины недоступности в порядке приоритета
|
||
- **Covers:** `portfolio/investment-performance` — `Внешние денежные потоки`, `Недоступный и неполный результат`
|
||
- **Source:** system-analysis «Маппинг операций T-Bank», «Переводы между счетами в all», «Причины недоступности»; design backend 4, 7
|
||
- **Verification:** unit-тесты: счёт A (130 000 / 10 000), `UNCONFIRMED_TRANSFER` при совпадении операций, перевод на исключённый счёт, бумаги без пары, USD, порядок причин
|
||
- **Depends on:** none
|
||
- [x] 2.3 [backend] Domain: XIRR (Ньютон + бисекция, проверка знака), basis annual/period, теневой портфель MCFTRR/IMOEX, опережение, series
|
||
- **Covers:** `portfolio/investment-performance` — `Доходность с учётом сумм и дат потоков`, `Те же деньги в индексе Мосбиржи`, `Справочный индекс без дивидендов`, `График результата`
|
||
- **Source:** system-analysis «Расчёт»; design backend 3
|
||
- **Verification:** unit-тесты с эталонными константами (LibreOffice/scipy, допуск 1e-6): 10 % за 730 дн., 110 000 ₽ по индексу, поток в выходной, `NO_SOLUTION`, `AMBIGUOUS_RETURN`, period basis, отставание
|
||
- **Depends on:** none
|
||
- [x] 2.4 [backend] Модуль `performance`: маршруты `GET /brokerage-accounts/{accountId|all}/performance`, доступ, сборка ответа, DTO, `UnavailableReason`, лог `performance.calculated`
|
||
- **Covers:** `portfolio/investment-performance` — `Результат инвестирования выбранного счёта`, `Недоступный и неполный результат`; `instruments/market-index-history` — `Свежесть и недоступность истории индексов`
|
||
- **Source:** contract [investment-performance.openapi.yaml](system-analysis/contracts/investment-performance.openapi.yaml), [performance-read.mmd](system-analysis/sequences/performance-read.mmd); design backend 1, 6
|
||
- **Verification:** e2e на SQLite (`npm run test:sqlite`): 200 ready, `data: null`, `all` incomplete, 401/404/503, MOEX недоступен с историей и без; `npm run verify`
|
||
- **Depends on:** 1.3, 2.1, 2.2, 2.3
|
||
- [x] 2.5 [backend] Обновить generated OpenAPI и сверить его с целевым контрактом
|
||
- **Covers:** `portfolio/investment-performance` — `Результат инвестирования выбранного счёта`
|
||
- **Source:** design «Contract Implementation»
|
||
- **Verification:** `npm run openapi:generate`; `npm run openapi:check`; построчная сверка маршрутов, required, nullable, enum и форматов с `investment-performance.openapi.yaml`, результат — в описании PR
|
||
- **Depends on:** 2.4
|
||
|
||
## 3. Frontend
|
||
|
||
- [x] 3.1 [frontend] Обновить OpenAPI snapshot и типы, entity `performance` с `usePerformance(accountId)`
|
||
- **Covers:** `portfolio/investment-performance` — `Результат инвестирования выбранного счёта`
|
||
- **Source:** design frontend 1, «Contract Implementation»
|
||
- **Verification:** `npm run openapi:generate`; `npm run openapi:check`; `npm run typecheck`
|
||
- **Depends on:** 2.5
|
||
- [x] 3.2 [frontend] Форматтеры `formatSignedPercent`, `formatPercentagePoints` (знак U+2212, 1 знак)
|
||
- **Covers:** `portfolio/investment-performance` — `Вкладка «Результат» на странице счёта`
|
||
- **Source:** design frontend 4
|
||
- **Verification:** unit-тесты: положительное, отрицательное, ноль, округление
|
||
- **Depends on:** none
|
||
- [x] 3.3 [frontend] Вкладка «Результат»: container, VM, view, KPI, alerts, недоступно, skeleton, ошибка секции, «Как считали», hint, строки `portfolio.performance.*`
|
||
- **Covers:** `portfolio/investment-performance` — `Вкладка «Результат» на странице счёта`, `Недоступный и неполный результат`
|
||
- **Source:** design frontend 2, 3, 6, 7, «UI/UX Package»; prototype вариант A
|
||
- **Verification:** тесты VM и view (RTL + MSW): обгоняю, отстаю, меньше года, неполный, недоступно, неизвестная причина, загрузка, ошибка только во вкладке; `npm run verify`
|
||
- **Depends on:** 3.1, 3.2
|
||
- [x] 3.4 [frontend] График результата: LineChart с тремя сериями и точкой текущей стоимости, tooltip, текстовая альтернатива, пояснение об отсутствии прошлой стоимости, состояние без series
|
||
- **Covers:** `portfolio/investment-performance` — `График результата`, `Справочный индекс без дивидендов`
|
||
- **Source:** design frontend 5, «UI/UX Package»
|
||
- **Verification:** тесты view: серии, `aria-label` с итогами, отсутствие референсной линии, пустой series; browser-тест на 390px без горизонтальной прокрутки; `npm run verify`
|
||
- **Depends on:** 3.3
|
||
|
||
## 4. Docs
|
||
|
||
- [x] 4.1 [docs] ADR 023 и строка в `adr/README.md`
|
||
- **Covers:** `N/A` — документация решения
|
||
- **Source:** docs-impact: `docs/adr/023-investment-performance-vs-index.md`, `docs/adr/README.md`
|
||
- **Verification:** `npm run verify`
|
||
- **Depends on:** none
|
||
- [x] 4.2 [docs] Страница `domains/portfolio/investment-performance.md` и обновления `all-accounts.md`, `data-reference.md`, `portfolio/overview.md`
|
||
- **Covers:** `N/A` — документация текущего поведения
|
||
- **Source:** docs-impact: соответствующие строки таблицы
|
||
- **Verification:** `npm run verify`; сверка с реализованным поведением 2.4 и 3.3
|
||
- **Depends on:** 2.4, 3.3, 4.1
|
||
- [x] 4.3 [docs] Глоссарий, `overview.md`, `income/overview.md`: новые термины и снятие конфликтующих запретов
|
||
- **Covers:** `N/A` — терминология
|
||
- **Source:** docs-impact: `docs/glossary.md`, `docs/overview.md`, `docs/domains/income/overview.md`
|
||
- **Verification:** `npm run verify`; `grep -rn "доходност" .` — только новое значение или оговорки «не является»
|
||
- **Depends on:** 4.1
|
||
- [x] 4.4 [docs] `integrations/moex.md` (раздел «Индексы»), `architecture/context.md`, `architecture/http-api.md`
|
||
- **Covers:** `N/A` — документация интеграции и API
|
||
- **Source:** docs-impact: соответствующие строки таблицы
|
||
- **Verification:** `npm run verify`; сверка с generated OpenAPI из 2.5
|
||
- **Depends on:** 2.5
|
||
|
||
## 5. Завершение
|
||
|
||
- [x] 5.1 [specs] Commit planning artifacts и прототипа; PR в `develop`
|
||
- **Covers:** `N/A` — поставка planning artifacts
|
||
- **Source:** engineering workflow
|
||
- **Verification:** `npm run validate`; `git diff --check`
|
||
- **Depends on:** none
|
||
|
||
Ручная приёмка на реальных данных Change Owner (парность переводов,
|
||
правдоподобие результата) и semantic verify/archive выполняются по
|
||
qa-analysis до закрытия Issue. Это не implementation task.
|