84 lines
19 KiB
Markdown
84 lines
19 KiB
Markdown
## 1. Базовые backend-механизмы операций и расчётов
|
||
|
||
- [x] 1.1 [backend] Расширить существующий сервис Account Ledger проверяющим доступ сборщиком полного диапазона, который переиспользует mapping страниц и LRU, проходит каждую cursor chain до terminal page и отклоняет отсутствующий либо повторяющийся continuation cursor; сохранить поведение публичного Ledger endpoint и добавить целевые regression tests.
|
||
- **Covers:** `brokerage-account-income-analytics` — `Realized income analytics is account-scoped and period-bound`; `brokerage-account-income-analytics` — `Realized analytics never presents an incomplete result as complete`
|
||
- **Verification:** Запустить целевые backend-наборы Jest для проверки ownership/cache в BrokerageOperationsService, успешного сбора нескольких страниц, распространения ошибки страницы, отсутствующего cursor и повторяющегося cursor.
|
||
- [x] 1.2 [backend] Расширить общие BigInt decimal utilities каноническим parsing/comparison десятичных строк и реализовать date-only планирование диапазонов в Europe/Moscow для периода по умолчанию и пользовательского периода, сравнения с предыдущим периодом/полным месяцем, доступности year-ago и day/week/month buckets; добавить risk-based unit tests.
|
||
- **Covers:** `brokerage-account-income-analytics` — `Realized income analytics is account-scoped and period-bound`; `brokerage-account-income-analytics` — `Period comparisons preserve calendar and currency meaning`; `brokerage-account-income-analytics` — `Analytics summary and trend remain readable per currency`
|
||
- **Verification:** Запустить целевые backend-тесты Jest для некорректных, обратных, будущих и превышающих 366 дней диапазонов, границ месяца по Москве, equal-duration и full-month comparisons, leap-day/pre-opened year comparison, порогов buckets и точной signed decimal arithmetic.
|
||
|
||
## 2. Backend-проекции дохода и публичный контракт
|
||
|
||
- [x] 2.1 [backend] Реализовать общую income aggregation core и защищённые проекции current-month summary/full analytics: выбирать только точные типы coupon/dividend, сохранять исходные валюты и знаки, формировать union для comparisons, empty buckets, точные группы инструментов и включённые primary entries.
|
||
- **Covers:** `brokerage-account-income-analytics` — `Realized income analytics is account-scoped and period-bound`; `brokerage-account-income-analytics` — `Realized income uses exact executed coupon and dividend payments`; `brokerage-account-income-analytics` — `Period comparisons preserve calendar and currency meaning`; `brokerage-account-income-analytics` — `Analytics summary and trend remain readable per currency`; `brokerage-account-income-analytics` — `Instrument breakdown is traceable to exact Ledger Entries`; `brokerage-account-income-analytics` — `Realized analytics never presents an incomplete result as complete`; `brokerage-account-income-analytics` — `Account overview has an independent current-month income summary`
|
||
- **Verification:** Запустить целевые backend-тесты сервиса для исключения неточных типов, отрицательных корректировок, мультивалютных итогов без grand total, нулевых результатов, differences сравнений, полноты buckets, стабильного instrument fallback/group ordering, сверки drill-down и поведения источника «полностью или ошибка».
|
||
- [x] 2.2 [backend] Добавить Nest DTO/controller contracts для `GET /api/v1/brokerage-accounts/:accountId/income-summary` и `GET /api/v1/brokerage-accounts/:accountId/income-analytics`, включая строгую валидацию date-only query, существующую семантику auth/account errors и Swagger schemas.
|
||
- **Covers:** `brokerage-account-income-analytics` — `Realized income analytics is account-scoped and period-bound`; `brokerage-account-income-analytics` — `Account overview has an independent current-month income summary`
|
||
- **Verification:** Запустить controller/DTO tests, проверяющие передачу аутентифицированного User, принятие периода по умолчанию и валидных дат, отклонение некорректных inputs, обработку недоступного счёта и сгенерированные response shapes.
|
||
- [x] 2.3 [backend] Добавить точный расчёт `incomeTotalsByCurrency` в существующий полный ответ Future Cash Events, учитывая только события coupon/dividend с известным projected Money и не меняя ordering событий, поведение списка и семантику ошибок.
|
||
- **Covers:** `brokerage-account-income-analytics` — `Forecast is separate from realized income`
|
||
- **Verification:** Запустить regression tests UpcomingEventsService для итогов coupon/dividend, неизвестных сумм, исключения maturity/offer, нескольких исходных валют, ошибки источника и неизменившихся ordering/content существующих событий.
|
||
- [x] 2.4 [backend] Добавить или расширить backend risk-based tests на границах service/HTTP contract для authorization, точного Money, полного cursor traversal и обратной совместимости additive public response.
|
||
- **Covers:** `brokerage-account-income-analytics` — `Realized income analytics is account-scoped and period-bound`; `brokerage-account-income-analytics` — `Realized income uses exact executed coupon and dividend payments`; `brokerage-account-income-analytics` — `Realized analytics never presents an incomplete result as complete`; `brokerage-account-income-analytics` — `Forecast is separate from realized income`
|
||
- **Verification:** Запустить затронутые backend-наборы Jest с `--runInBand` и проверить, что существующие regression cases Portfolio, Ledger и Events выполняются вместе с новыми критическими cases для money/security/public contract.
|
||
|
||
## 3. Синхронизация контракта OpenAPI
|
||
|
||
- [x] 3.1 [frontend] Скопировать сгенерированный backend-документ OpenAPI в committed frontend snapshot и регенерировать frontend schema types до добавления consumers; не редактировать transport DTO вручную.
|
||
- **Covers:** `N/A` — Это требуемый утверждённым Design мост совместимости для двух новых backend endpoints и additive Events field; он не вводит самостоятельного observable behavior.
|
||
- **Verification:** Запустить `npm run openapi:generate` в `frontend`, затем проверить, что generated `paths` содержат оба income endpoints и `incomeTotalsByCurrency` без несвязанного contract drift.
|
||
|
||
## 4. Frontend-данные, overview и состояние применённого периода
|
||
|
||
- [x] 4.1 [frontend] Добавить public API income entity и типизированные React Query hooks для summary/full analytics на основе generated `paths`, с 30-секундным stale time, без automatic retry и через существующий authenticated query client.
|
||
- **Covers:** `brokerage-account-income-analytics` — `Realized income analytics is account-scoped and period-bound`; `brokerage-account-income-analytics` — `Account overview has an independent current-month income summary`
|
||
- **Verification:** Запустить целевые hook tests для account-scoped path/query parameters, отключённых запросов без account, default summary request, cache identity применённого диапазона и настроенной query policy.
|
||
- [x] 4.2 [frontend] Интегрировать независимое состояние current-month income summary в ViewModel страницы Account и семантические section views для empty и loaded outcomes Portfolio, включая локальные loading/error/empty states и ссылку на полную аналитику.
|
||
- **Covers:** `brokerage-account-income-analytics` — `Account overview has an independent current-month income summary`
|
||
- **Verification:** Запустить tests ViewModel/view страницы Account, доказывающие отображение source-currency summary, фиксированный current-month behavior, локальную ошибку summary и сохранение видимости успешно загруженных Portfolio и соседних sections.
|
||
- [x] 4.3 [frontend] Реализовать ViewModel страницы дохода счёта с каноническими явными URL-параметрами `from`/`to`, draft state на react-hook-form/Zod, синхронизацией apply/reset и Back/Forward, состоянием полного realized query и независимой проекцией трёх ближайших forecast events из существующего Events query.
|
||
- **Covers:** `brokerage-account-income-analytics` — `Realized income analytics is account-scoped and period-bound`; `brokerage-account-income-analytics` — `User explicitly applies an analytics period represented in the URL`; `brokerage-account-income-analytics` — `Realized analytics never presents an incomplete result as complete`; `brokerage-account-income-analytics` — `Forecast is separate from realized income`
|
||
- **Verification:** Запустить целевые tests ViewModel для default URL canonicalization, изоляции draft, корректного apply, reset, восстановления navigation, ограничений для некорректного/будущего/слишком длинного периода, состояний loading/error/empty realized analytics и изоляции ошибки forecast.
|
||
|
||
## 5. Frontend-представление аналитики и навигация
|
||
|
||
- [x] 5.1 [frontend] Создать принадлежащие странице structural loading/error/empty/loaded views и source-currency sections для selected/previous/year summaries, включая требуемую формулировку налоговой границы и недоступное годовое сравнение без языка investment performance.
|
||
- **Covers:** `brokerage-account-income-analytics` — `Realized income uses exact executed coupon and dividend payments`; `brokerage-account-income-analytics` — `Period comparisons preserve calendar and currency meaning`; `brokerage-account-income-analytics` — `Realized analytics never presents an incomplete result as complete`
|
||
- **Verification:** Запустить tests рендеринга страницы для signed corrections, значений coupon/dividend/total по валютам, отсутствующего grand total, недоступного year comparison, явного успешного zero state и recoverable realized error.
|
||
- [x] 5.2 [frontend] Реализовать без новой зависимости управляемый валютой stacked trend с positive/negative baseline и его структурированный текстовый эквивалент с точными значениями, сохраняя все backend buckets, включая нулевые, для day/week/month granularities.
|
||
- **Covers:** `brokerage-account-income-analytics` — `Analytics summary and trend remain readable per currency`
|
||
- **Verification:** Запустить component tests, проверяющие переключение валюты, отдельные segments coupon/dividend, представление отрицательной корректировки, нулевые buckets, доступный с клавиатуры control и читаемые значения buckets независимо от графики/цвета.
|
||
- [x] 5.3 [frontend] Реализовать per-currency строки instrument breakdown в переданной backend сортировке и раскрываемые точные включённые Ledger Entries с переиспользованием существующего представления строки Ledger.
|
||
- **Covers:** `brokerage-account-income-analytics` — `Instrument breakdown is traceable to exact Ledger Entries`
|
||
- **Verification:** Запустить component tests, которые сверяют subtotal/total/count каждой строки с раскрытыми entries, сохраняют отрицательные корректировки и исключают несвязанные entries.
|
||
- [x] 5.4 [frontend] Добавить семантически отдельную forecast section на основе backend-поля `incomeTotalsByCurrency` и трёх ближайших подходящих Events, с локальными loading/error/empty states, предупреждением о неопределённости и ссылкой на полную страницу Events.
|
||
- **Covers:** `brokerage-account-income-analytics` — `Forecast is separate from realized income`
|
||
- **Verification:** Запустить component/page tests для source-currency forecast totals, неизвестного Money, исключения maturity/offer, фиксированного 30-дневного будущего периода, ограничения в три события, независимой ошибки forecast и неизменившегося realized content.
|
||
- [x] 5.5 [frontend] Зарегистрировать `/accounts/:accountId/income`, lazy export страницы и account breadcrumb trail, предоставить действия перехода только из overview выбранного Account и сохранить глобальную навигацию без изменений.
|
||
- **Covers:** `brokerage-account-income-analytics` — `User explicitly applies an analytics period represented in the URL`; `brokerage-account-income-analytics` — `Account overview has an independent current-month income summary`
|
||
- **Verification:** Запустить route/breadcrumb tests для прямого защищённого перехода, иерархии Accounts → account → income, ссылок overview и отсутствия нового элемента глобальной навигации.
|
||
|
||
## 6. As-built документация
|
||
|
||
- [x] 6.1 [docs] Документировать поставленный поток income analytics счёта, границу realized/forecast, endpoints, семантику source currency/date, поведение полного результата/ошибки и текущие ограничения; обновить применимые domain/system navigation без копирования planning artifacts.
|
||
- **Covers:** `N/A` — Durable as-built документация требуется утверждённой four-area Delivery Map, но не реализует дополнительного observable product requirement.
|
||
- **Verification:** Сверить затронутые Markdown links и terminology с поставленным runtime/OpenAPI behavior, затем запустить canonical gate репозитория docs.
|
||
|
||
## 7. Gates затронутых областей и cross-contract
|
||
|
||
- [x] 7.1 [backend] Запустить canonical gate backend под Node 22 после завершения всей backend-реализации и целевых risk tests.
|
||
- **Covers:** `N/A` — Это required governance completion gate затронутой backend-области; он проверяет реализацию, уже сопоставленную с утверждёнными Requirements.
|
||
- **Verification:** Запустить `npm run verify` в `backend` под Node 22.
|
||
- [x] 7.2 [frontend] Запустить canonical gate frontend под Node 22 после генерации OpenAPI, реализации route/UI и целевых tests.
|
||
- **Covers:** `N/A` — Это required governance completion gate затронутой frontend-области; он проверяет реализацию, уже сопоставленную с утверждёнными Requirements.
|
||
- **Verification:** Запустить `npm run verify` в `frontend` под Node 22.
|
||
- [x] 7.3 [docs] Запустить canonical gate docs под Node 22 после согласования as-built документации с поставленным поведением.
|
||
- **Covers:** `N/A` — Это required governance completion gate затронутой docs-области; он проверяет утверждённый documentation delivery outcome.
|
||
- **Verification:** Запустить `npm run verify` в `docs` под Node 22.
|
||
- [x] 7.4 [specs] Сверить отметки tasks только с evidence завершённой реализации и запустить strict canonical change validation без создания последующих artifacts или archive evidence.
|
||
- **Covers:** `N/A` — Это поддерживает canonical SDD authority и предоставляет gate затронутой specs-области; observable behavior реализуют backend/frontend tasks.
|
||
- **Verification:** Запустить `openspec validate portfolio-income-analytics --type change --strict --store wealth-ledger-specs` из `specs` и проверить, что у каждого завершённого checkbox есть соответствующее delivered evidence.
|
||
- [x] 7.5 [workspace] Проверить синхронизированный двусторонний runtime OpenAPI contract после публикации backend и генерации frontend snapshot/types.
|
||
- **Covers:** `N/A` — Cross-repository orchestration контракта требуется утверждённым Design, но не владеет backend- или frontend-поведением.
|
||
- **Verification:** Запустить `npm run test:openapi-contract` в `backend` под Node 22 против committed frontend OpenAPI snapshot.
|