spec: unify income payment cards and drop period comparisons (WealthLedger/main#33) #37
@@ -0,0 +1,2 @@
|
||||
schema: wealth-ledger-sdd-v2
|
||||
created: 2026-10-13
|
||||
@@ -0,0 +1,208 @@
|
||||
# Engineering Design
|
||||
|
||||
## Context and Constraints
|
||||
|
||||
Аналитика дохода использует выбранный период, отдельные previous/year диапазоны
|
||||
и публикует их через DTO и metadata; план синхронизации также запрашивает эти
|
||||
диапазоны. Frontend строит блоки сравнений из ответа и показывает исполненные
|
||||
операции через `LedgerEntryRow`. Полный журнал, недавние записи и личная история
|
||||
бумаги используют этот же ряд; прогноз использует `BrokerageEventCard`;
|
||||
календарные карточки акции и облигации реализованы внутри соответствующих
|
||||
страниц. Все уже используют `EntryCard` либо существующие Mantine primitives,
|
||||
но это не один предметный компонент выплаты.
|
||||
|
||||
Граница реализации — утверждённые Delta Specs и
|
||||
[System Analysis](system-analysis/analysis.md), включая
|
||||
[целевой контракт](system-analysis/contracts/income-analytics-response.schema.json).
|
||||
Доступ, деньги, полнота периода, порядок записей и формы остальных API
|
||||
сохраняются. Клиент получает публичный OpenAPI artifact явно.
|
||||
|
||||
## Technical Goals / Non-Goals
|
||||
|
||||
- Исключить сравнения из чтения, синхронизации, API и UI без изменения итогов
|
||||
выбранного периода.
|
||||
- Один компонент для купона/дивиденда в исполненной операции, прогнозе и
|
||||
графике бумаги; режим определяется источником, а не знаком или датой.
|
||||
- Не преобразовывать график в личный доход и не объединять чужие деньги,
|
||||
прогноз и сумму на бумагу. Не удалять `buckets` или `instruments` из API.
|
||||
|
||||
## Implementation Impact Map
|
||||
|
||||
### main
|
||||
|
||||
N/A: нет изменений workspace, Compose, release orchestration или конфигурации.
|
||||
|
||||
### frontend
|
||||
|
||||
Affected: страница дохода и её display model, компонент записи операций,
|
||||
компонент будущего события, календарные карточки акций/облигаций, локальная
|
||||
копия публичного OpenAPI и генерируемые типы. Владельцы экранов сохраняют
|
||||
свои списки, фильтры и локальные состояния.
|
||||
|
||||
### backend
|
||||
|
||||
Affected: расчёт и планирование income периода, чтение операций для
|
||||
income-analytics, DTO ответа и план фонового получения выбранного интервала.
|
||||
Источник исполненных операций и агрегация selected остаются владельцами денег.
|
||||
|
||||
### qa
|
||||
|
||||
N/A: самостоятельного репозитория QA нет; системные проверки описывает
|
||||
`qa-analysis.md` без введения несуществующей инфраструктуры.
|
||||
|
||||
## Decisions
|
||||
|
||||
### main
|
||||
|
||||
Изменения не требуются: координация ссылками на Issue/Change, без workspace
|
||||
автоматизации ради одного API перехода.
|
||||
|
||||
### frontend
|
||||
|
||||
Один предметный `PayoutCard` разместить на уровне `entities`, доступном
|
||||
страницам и компонентам других slices через public export. Он использует
|
||||
существующий `EntryCard` как визуальную основу; `EntryCard` не становится
|
||||
владельцем финансовой семантики. Презентационные данные передаются явным
|
||||
discriminated union по происхождению `executed | forecast | schedule`:
|
||||
исполненная запись содержит signed payment и точный timestamp; прогноз —
|
||||
nullable projected amount, dateKind и дату; график — nullable per-security
|
||||
сумму, отдельную nullable оценку и доступные даты/параметры выпуска. Ветка
|
||||
графика показывает дополнительные условия купона и дивиденда без размножения
|
||||
карточек. У отсутствующих значений текстовый fallback, ноль форматируется
|
||||
отдельно от неизвестного. Не вводить один универсальный произвольный набор
|
||||
optional props, допускающий ложную комбинацию «исполнено + оценка».
|
||||
|
||||
Владельцы исходных данных адаптируют типизированный ответ непосредственно на
|
||||
границе использования либо через узкий mapper сущности для повторных callers:
|
||||
`LedgerEntryRow` передаёт точные купоны/дивиденды в `PayoutCard`, прочие
|
||||
операции оставляет на прежнем пути; `BrokerageEventCard` делает то же для
|
||||
coupon/dividend, сохраняя maturity/offer; страницы графиков заменяют только
|
||||
содержимое календарной карточки. Доход продолжает вызывать `LedgerEntryRow`,
|
||||
сохраняя `wrap`, HTML-список и occurrence key. Личная история инструмента
|
||||
сохраняет quantity/price/account details там, где они доступны. Ключи списков
|
||||
и порядок определяются caller, не самим компонентом.
|
||||
|
||||
Удалить comparison-only display model, компонент блока, подписи и стили,
|
||||
относящиеся только к сравнениям. Не удалять предупреждение неполного
|
||||
selected или сохранённого snapshot. Обновить текущие fixtures и регрессии
|
||||
после передачи OpenAPI; генерация типов потребителя берёт только его
|
||||
локальную копию artifact.
|
||||
|
||||
Альтернатива с одинаковым CSS для трёх существующих компонентов отвергнута:
|
||||
не обеспечивает фактическое переиспользование. Альтернатива с общим DTO
|
||||
backend отвергнута: источники и денежные смыслы различны, wire-контракт
|
||||
остальных API не меняется.
|
||||
|
||||
### backend
|
||||
|
||||
Сократить план income-analytics до selected: сервис запрашивает один диапазон,
|
||||
не конструирует comparison totals/availability; план экранной синхронизации
|
||||
не включает предыдущий год и месяц. Сохранить независимый план current-month
|
||||
summary и серверный выбор точных типов купона/дивиденда. В DTO удалить
|
||||
`previous`, `yearComparison`, comparison DTO при отсутствии других callers;
|
||||
`dependencies` сохранить в исходной форме с единственной ролью `selected`.
|
||||
Текущий shared operations range reader использует индексированные имена
|
||||
resource keys для трёх периодов; после одного диапазона оставить корректную
|
||||
идентичность selected и убрать устаревший индексированный список. Сохраняем
|
||||
status/coverage/freshness и публикацию подтверждённого периода. Дневные/
|
||||
недельные/месячные buckets остаются, так как их удаление не согласовано.
|
||||
|
||||
Не вводить миграцию БД: убираются чтения и поля ответа, а не сохранённые
|
||||
операции или подтверждённое покрытие. Никакой пересборки прошлого дохода.
|
||||
|
||||
## Cross-cutting Implementation
|
||||
|
||||
Существующая проверка пользователя/счёта и очистка личного query cache при
|
||||
смене подключения остаются на местах. Изменение количества планируемых
|
||||
диапазонов не добавляет work и не меняет поведение hourly attempt для других
|
||||
экранов. Существующие request ID, metadata попытки и статусы дают достаточную
|
||||
диагностику; новых событий или полей логирования не требуется. Пересчёта
|
||||
денег, валютной конвертации и нового кэша нет.
|
||||
|
||||
## Data / Storage Changes
|
||||
|
||||
N/A: Prisma/SQLite schema и исторические записи не меняются; выбранное
|
||||
покрытие продолжает подтверждаться до публикации окончательного результата.
|
||||
|
||||
## Contract Implementation
|
||||
|
||||
Backend обновляет DTO и исполняемый generated OpenAPI. Для обоих
|
||||
income-analytics маршрутов проверить отсутствие `previous`/`yearComparison`
|
||||
и наличие только `selected` в dependency role при сохранении nullable `data`,
|
||||
остальных полей и Problem Details. Сверить обе схемы 200 с
|
||||
[target JSON Schema](system-analysis/contracts/income-analytics-response.schema.json)
|
||||
семантически, а не только с TypeScript shape; существующую проверку parity
|
||||
runtime OpenAPI также сохранить. Передать созданный backend artifact frontend
|
||||
явно; frontend обновляет snapshot и generated types штатной локальной
|
||||
процедурой, без чтения соседнего checkout в сборке. Прежний клиент,
|
||||
требующий удалённых полей, несовместим.
|
||||
|
||||
## Developer Verification Strategy
|
||||
|
||||
Backend: адресные проверки планирования только выбранного интервала, чтения
|
||||
income summary/analytics, точных signed сумм и недоступного selected;
|
||||
проверка HTTP контракта и OpenAPI parity. Frontend: наблюдаемое отсутствие
|
||||
блоков сравнений в loaded/loading/error/empty; сохранение period URL,
|
||||
порядка/повторов выплат и корректные режимы общего компонента на всех
|
||||
потребителях. После локальных узких проверок выполнить обязательный verify
|
||||
каждого изменённого implementation repo. Это developer-owned проверки;
|
||||
системная матрица отдельно в `qa-analysis.md`.
|
||||
|
||||
## UI/UX Package
|
||||
|
||||
**Applicability and scope:** changed UI; пакет полностью inline, новых
|
||||
изображений и assets не требуется. Один approval Design относится к этой
|
||||
ревизии и приведённому ниже точному источнику переиспользования.
|
||||
|
||||
**Package revision:** `1`, change `unify-income-payment-cards`.
|
||||
|
||||
**Screens, states and interactions:** доход — фильтр, итоги, плоский список
|
||||
исполненных выплат, без сравнений; прогноз на странице событий/превью —
|
||||
пометка «Прогноз», неизвестная сумма отлична от нуля, дата реестра помечена;
|
||||
графики акции/облигации — «Событие по графику», разные подписи per-share/
|
||||
per-bond и личной оценки. В истории операций карточка сохраняет описание,
|
||||
дату и доступную identity инструмента, signed Money и детали там, где были.
|
||||
Loaded, empty, loading, error и обновление старого snapshot сохраняют текущие
|
||||
локальные границы экранов. Оферта, погашение, сделка и налог не получают
|
||||
режим выплаты. Компонент сам не переключает состояние и не инициирует запрос.
|
||||
|
||||
**Responsive behavior:** однотактный проход по карточкам без горизонтального
|
||||
overflow при узкой ширине и длинных значениях; labels, значения и статусы
|
||||
читаются текстом и клавиатурой, цвет остаётся дополнительным признаком.
|
||||
Сохраняются доступные имена региона и фокус элементов фильтра.
|
||||
|
||||
**Reused source and differences:** immutable locator
|
||||
`wealth-ledger-specs:openspec/changes/archive/2026-09-09-simplify-income-page/design.md`
|
||||
(секция «Одна карточка соответствует одной выплате») — плоский income список,
|
||||
одна карточка на запись, signed Money и сохранение порядка. Дополнить
|
||||
только единым предметным presentation для прогнозов/графиков с явными
|
||||
подписями происхождения; не переносить прогноз внутрь income страницы.
|
||||
Визуальная основа реализации — существующий `EntryCard`; его геометрия
|
||||
остаётся общим стилем, а не заменой `PayoutCard`. Пакет целиком inline.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- Разные даты и null-поля трёх источников провоцируют неверные labels при
|
||||
слишком широком mapper: явные варианты данных и локальные проверки экранов
|
||||
важнее экономии нескольких props.
|
||||
- Для календаря бумаги нет логотипа/тикера в каждой записи: владелец страницы
|
||||
передаёт известную identity, не создавая новый запрос.
|
||||
- Меньше загружаемых диапазонов снижает объём работы, но отсутствие сравнения
|
||||
может изменить порядок фонового покрытия старых периодов; цель сохранения
|
||||
другой независимой истории остаётся прежней.
|
||||
|
||||
## Migration / Rollout / Rollback
|
||||
|
||||
Сначала обновить backend DTO/логику и получить опубликованный OpenAPI, затем
|
||||
передать artifact frontend и обновить UI/типизацию; согласованно поставить
|
||||
две стороны breaking ответа. Не выпускать старый frontend против нового
|
||||
backend как поддерживаемую комбинацию. При rollback вернуть согласованную
|
||||
предыдущую пару backend/frontend и прежний OpenAPI snapshot; сохранённые
|
||||
операции и покрытие не требуют data rollback. Синхронизация canonical specs
|
||||
и AS-IS docs выполняется по отдельным approved tasks после реализации.
|
||||
|
||||
## Solution Assessment
|
||||
|
||||
N/A: не создаётся новая инфраструктура, интеграция, storage, кэш или система
|
||||
аутентификации. Существующие `EntryCard`, owner-slices и DTO сохраняются;
|
||||
сопоставление альтернатив общего UI дано в решении frontend.
|
||||
@@ -0,0 +1,50 @@
|
||||
# Documentation Impact
|
||||
|
||||
## Summary
|
||||
|
||||
Обновление canonical AS-IS нужно: документы сейчас прямо описывают сравнения
|
||||
дохода и три разных формы карточек выплат. После поставки описание должно
|
||||
отражать только выбранный период и единое представление купонов/дивидендов
|
||||
с разной степенью подтверждения. Целевые страницы уже существуют; новых
|
||||
разделов навигации не требуется.
|
||||
|
||||
## Documentation Changes
|
||||
|
||||
| Action | Target | Category | Resulting AS-IS | Source | Verification |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| update | `docs/domains/income/overview.md` | domain | Удалены блоки и расчёт comparisons, а также сведения о comparison coverage и процентах; income API содержит только данные выбранного периода, buckets сохраняются; плоский список фактических выплат использует общее представление купона/дивиденда. | `specs/brokerage-account-income-analytics/spec.md`; `system-analysis/analysis.md` §§ Contracts, Data and State Semantics | Сверить текст о расчёте, полноте, пустоте и карточках с двумя income API ответами и фактической страницей. |
|
||||
| update | `docs/domains/portfolio/all-accounts.md` | domain | Для `all` доход учитывает доступные счета, выбранный период, source currencies и принадлежность entries без годового/предыдущего сравнения. | `specs/brokerage-account-income-analytics/spec.md`; `system-analysis/analysis.md` §§ Contracts, Security and NFR at System Boundaries | В документе нет правил year comparison; данные `all` соответствуют ответу и интерфейсу. |
|
||||
| update | `docs/domains/operations/overview.md` | domain | Купоны/дивиденды в полном журнале, пяти недавних операциях и истории инструмента показаны одним предметным представлением исполненной выплаты; не-доходные операции сохраняют прежнюю семантику и детали. | `specs/brokerage-account-ledger/spec.md`; `design.md` § Decisions/frontend | Сопоставить три экрана, знак, исходную валюту, описание и дополнительную историю инструмента. |
|
||||
| update | `docs/domains/income/upcoming-events.md` | domain | Полный прогноз и превью используют общее представление купона/дивиденда с пометкой прогноза, nullable Money и датой реестра для dividend; offer/maturity сохраняют смысл. | `specs/brokerage-account-upcoming-events/spec.md`; `system-analysis/analysis.md` § Data and State Semantics | Сверить оба экрана с типизированным ответом, неизвестной суммой, dateKind и отсутствием фактического дохода в прогнозе. |
|
||||
| update | `docs/domains/instruments/stocks.md` | domain | Будущий и прошедший дивидендный график используют общую карточку с пометкой события по графику; сумма на акцию, оценка и дата реестра не выдаются за личное зачисление. История личных операций остаётся отдельной. | `specs/instrument-income-schedules/spec.md`; `design.md` §§ Decisions/frontend, UI/UX Package | Сверить разные деньги/даты и границу между графиком и операцией на странице акции. |
|
||||
| update | `docs/domains/instruments/bonds.md` | domain | Купонный календарь и прошлые события используют общую карточку с суммой на облигацию, отдельной оценкой и известными параметрами; исполнение подтверждает только личная история. | `specs/instrument-income-schedules/spec.md`; `design.md` §§ Decisions/frontend, UI/UX Package | Сверить ближайший/прошлый/недатированный купон и неизвестную сумму на странице облигации. |
|
||||
| update | `docs/architecture/http-api.md` | architecture | Зафиксировать, что оба income-analytics ответа больше не содержат данных сравнения; публичный контракт остаётся backend-generated OpenAPI, frontend получает обновлённый snapshot отдельно. Не дублировать машинную схему. | `system-analysis/analysis.md` §§ Contracts, Compatibility / Migration | Сверить описание с опубликованным OpenAPI и отсутствием comparison fields/roles. |
|
||||
|
||||
## Diagram Promotion
|
||||
|
||||
Не переносить `system-analysis/sequences/income-period.mmd` и
|
||||
`system-analysis/sequences/payment-sources.mmd`: устойчивые инварианты
|
||||
помещаются в тематические страницы; подробный сценарный flow полезен в
|
||||
архиве change, а не как параллельная AS-IS диаграмма.
|
||||
|
||||
## ADR Decision
|
||||
|
||||
N/A: изменяется продуктовый UI и ответ income API, не вводится новое
|
||||
долгоживущее архитектурное правило или интеграция. Существующий
|
||||
`docs/adr/017-local-tbank-reads-and-background-sync.md` — исторический
|
||||
принятый документ о старом поведении; не переписывать старое решение
|
||||
задним числом. Актуальный текст о выбранном периоде должен жить в
|
||||
`docs/domains/income/overview.md` и cross-cutting AS-IS при необходимости.
|
||||
|
||||
## Glossary / Navigation Impact
|
||||
|
||||
Новых терминов или маршрутов нет. Существующие значения «выплата», «прогноз»,
|
||||
«операция» и «событие графика» разъясняются в тематических страницах.
|
||||
`docs/overview.md` сохраняет существующую ссылку на доход.
|
||||
|
||||
## No-Change Rationale
|
||||
|
||||
Не создавать новую страницу `docs/design/`, не переносить target JSON Schema
|
||||
и не менять интеграционные описания T-Bank/MOEX: данные их источников и
|
||||
вычисления не изменяются. Остальные docs/ и исторические ADR не требуют
|
||||
обновления.
|
||||
@@ -0,0 +1,90 @@
|
||||
# Proposal
|
||||
|
||||
## Why
|
||||
|
||||
Сравнения с предыдущим периодом и годом ранее не помогают пользователю решить
|
||||
основную задачу страницы «Пассивный доход»: увидеть фактически полученные купоны
|
||||
и дивиденды за выбранный период. Они усложняют экран и требуют получения данных
|
||||
за дополнительные периоды. Купоны и дивиденды в истории операций, прогнозах и
|
||||
календарях инструментов представлены разными карточками; сходный вид при этом
|
||||
не обеспечивает единого представления выплаты и ясной границы между полученными
|
||||
деньгами и ожидаемым событием.
|
||||
|
||||
## What Changes
|
||||
|
||||
- **BREAKING**: сравнения дохода с предыдущим периодом и годом ранее перестают
|
||||
рассчитываться, загружаться и предоставляться потребителям аналитики.
|
||||
- Страница «Пассивный доход» показывает выбранный период, итоги по исходным
|
||||
валютам и все включённые исполненные выплаты без блоков сравнений и их состояний.
|
||||
- Купоны и дивиденды во всех существующих местах показа выплат используют одно
|
||||
предметное представление. Оно явно различает исполненную выплату, прогноз и
|
||||
запись графика инструмента, сохраняя смысл дат и денежных величин.
|
||||
|
||||
## Scope
|
||||
|
||||
### In Scope
|
||||
|
||||
- Аналитика дохода одного счёта и режима «Все счета»: удаление сравнения
|
||||
периодов из результата и связанных чтений, при сохранении дохода выбранного
|
||||
периода и самостоятельной сводки текущего месяца.
|
||||
- Карточки купонов и дивидендов в доходе, журнале и недавних операциях,
|
||||
личной истории инструмента, полном списке и превью будущих событий,
|
||||
календарях и истории выплат акций и облигаций.
|
||||
- Обновление нормативного поведения и согласование изменённого публичного
|
||||
контракта с потребителями.
|
||||
|
||||
### Out of Scope / Non-Goals
|
||||
|
||||
- Возврат графика динамики либо прогноза на страницу дохода; удаление иных
|
||||
исторических данных аналитики, не относящихся к сравнению периодов.
|
||||
- Изменение отбора исполненных операций, расчёта итогов, налоговой трактовки,
|
||||
прогноза или правил происхождения календарных событий.
|
||||
- Унификация карточек сделок, налогов, комиссий, погашений и оферт.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `specs/instrument-income-schedules/spec.md` — различимое представление
|
||||
будущих и прошедших событий графиков выплат акций и облигаций, не выдаваемых
|
||||
за подтверждённое личное зачисление.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `specs/brokerage-account-income-analytics/spec.md` — результат без сравнений
|
||||
и единое представление исполненных выплат.
|
||||
- `specs/brokerage-account-ledger/spec.md` — то же представление купонов и
|
||||
дивидендов в полном журнале, недавних операциях и истории инструмента.
|
||||
- `specs/brokerage-account-upcoming-events/spec.md` — то же представление
|
||||
прогнозных купонов и дивидендов на странице событий и в превью.
|
||||
|
||||
## Impact
|
||||
|
||||
Пользователь видит более короткую страницу дохода и узнаваемую карточку
|
||||
купона или дивиденда на смежных экранах. Аналитика прекращает запрос
|
||||
дополнительных периодов для сравнения, меняется публичный ответ и его
|
||||
потребители. Исполненные операции, будущие события и графики инструментов
|
||||
сохраняют разные источники и статус достоверности. Затронуты поведение
|
||||
интерфейса, инвестиционная аналитика, публикация контракта и документация
|
||||
дохода и событий.
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- На странице дохода нет сравнений и сообщений об их недоступности; выбранный
|
||||
период, итоги, налоговое пояснение и отдельная карточка каждой фактической
|
||||
выплаты доступны как прежде.
|
||||
- Чтение и синхронизация дохода не требуют периодов сравнения, а ответ
|
||||
аналитики их не предоставляет. Полнота выбранного периода и итоги сохраняются.
|
||||
- Купон и дивиденд на перечисленных экранах представлены одним предметным
|
||||
компонентом; полученная сумма имеет исходный знак и валюту, прогноз может
|
||||
не иметь суммы, а календарное событие не называется полученным доходом.
|
||||
- Остальные типы операций и будущих событий не теряют своего представления.
|
||||
|
||||
## Assumptions / Dependencies
|
||||
|
||||
- Изменение публичного ответа согласуется с его потребителями при поставке;
|
||||
удаление сравнений намеренно несовместимо с прежней формой ответа.
|
||||
- Одна карточка может показывать данные разной природы без ложного обещания
|
||||
зачисления: исполненная операция, прогноз и график остаются различимыми.
|
||||
- Планирование и реализация связаны с координирующей Issue
|
||||
`WealthLedger/main#33`.
|
||||
@@ -0,0 +1,99 @@
|
||||
# QA Analysis
|
||||
|
||||
## Verification Scope
|
||||
|
||||
### In Scope
|
||||
|
||||
Удаление сравнения дохода по `brokerage-account-income-analytics` и
|
||||
семантика выплаты на экранах дохода, журнала, истории инструмента,
|
||||
будущих событий и графиков акций/облигаций по четырём delta capabilities.
|
||||
Проверяется поведение пользователя и публичного API как системы.
|
||||
|
||||
### Out of Scope
|
||||
|
||||
Пересмотр правил расчёта купонов/дивидендов брокером, налоговая оценка,
|
||||
удаление buckets, новые типы событий, компонентные и внутренние тесты
|
||||
реализации, несуществующий QA репозиторий.
|
||||
|
||||
## Coverage Matrix
|
||||
|
||||
| Requirement / Scenario из Delta Specs | Наблюдаемая системная проверка |
|
||||
| --- | --- |
|
||||
| `brokerage-account-income-analytics` — removed `Period comparisons preserve calendar and currency meaning`; `Analytics summary remains readable per currency / Динамика отсутствует для периода любой длительности` | На коротком/многолетнем периоде нет comparison UI или состояний; 200 ответ обоих income-analytics маршрутов не содержит comparison fields/roles, и чтение не инициирует дополнительные диапазоны ради сравнения. |
|
||||
| `User explicitly applies an analytics period represented in the URL / Черновик периода не применён`, `Применение периода`, `Восстановление применённого периода из URL`, `Сброс периода`, `Недопустимый черновик периода` | Итоги и карточки меняются только после применения; URL/back/reset, неверные даты и доступность ввода сохраняют поведение без блоков сравнений. |
|
||||
| `Realized analytics never presents an incomplete result as complete / Все страницы операций успешно получены`, `Одна из страниц операций недоступна`, `В периоде нет купонов и дивидендов` | Выбранный период с полной историей показывает итог; отсутствие или ошибка покрытия не выглядит нулём; подтверждённый пустой период отличим. |
|
||||
| `Income payments remain traceable to exact Ledger Entries / Каждая выплата показана отдельной карточкой`, `Отрицательная корректировка и повторяющиеся IDs сохраняются`, `Валюта видна в сумме каждой выплаты` | Порядок и количество карточек равны серверным entries; повторы и минус в исходной валюте сохранены; нет внешних групп. |
|
||||
| `Income page excludes upcoming forecasts / Данные будущих событий недоступны` | Недоступный прогноз не скрывает полный полученный доход и не возвращает прогнозный блок. |
|
||||
| `brokerage-account-ledger` — `Full ledger presents compact rows / Отображение купона`, `Отображение дивиденда`, `Подпись типа не дублируется`; `Account overview includes recent ledger events / Отображение последних событий` | Полный журнал, превью и история инструмента используют одну карточку выплаченного купона/дивиденда, сохраняют signed Money, детали и fallback; другие операции сохраняют ряд. |
|
||||
| `brokerage-account-upcoming-events` — `Account page presents an upcoming events list / Просмотр ближайших событий`, `Прогнозный дивиденд с неизвестной суммой`; `Account overview includes upcoming events / Отображение ближайших событий` | Та же карточка для прогноза в списке и превью, «прогноз», дата реестра и отсутствие суммы не превращаются в исполнение/ноль; offer/maturity не становятся выплатой. |
|
||||
| `instrument-income-schedules / Будущий купон с известными условиями`, `Прошедший дивиденд без подтверждённой операции`, `Неизвестные условия графика` | На страницах бумаг та же карточка, но пометка графика, отдельные сумма на бумагу и оценка; прошлое событие не названо полученным, null не превращён в ноль. |
|
||||
|
||||
## Cross-system Verification
|
||||
|
||||
Сравнить оба 200 ответа income-analytics с
|
||||
`system-analysis/contracts/income-analytics-response.schema.json` и
|
||||
опубликованным OpenAPI; проверить отсутствие comparison ranges в запросах
|
||||
при чтении и планировании income, не запрещая независимый запрос прошлого
|
||||
периода пользователем. Проверить неполный/ошибочный selected, недоступный счёт,
|
||||
новое подключение и поздний ответ старого без утечки дохода. Порядок и
|
||||
повторение ID проверить на ответе нескольких операций; нулевая сумма и
|
||||
отсутствующая сумма должны иметь разные значения. Фоновые HTTP ошибки
|
||||
прогноза и календаря не должны менять исполненную выплату. Отдельных
|
||||
callback и новых timeout контрактов нет.
|
||||
|
||||
## Risk-based Priorities
|
||||
|
||||
1. Точность финансового смысла и граница доступа: исправления с отрицательным
|
||||
знаком, мультивалютность, «прошлый график» против факта, нет ложного нуля.
|
||||
2. Breaking ответ и избыточная загрузка: оба маршрута, отсутствие comparison
|
||||
fields/dependencies, синхронизация только выбранного периода.
|
||||
3. Регрессии соседних экранов: предложенные выплаты, maturity/offer, trades,
|
||||
текущий месяц на обзоре, back/forward и сохранённый snapshot.
|
||||
|
||||
## Test Data and Environment Needs
|
||||
|
||||
Тестовый доступный и недоступный счёт, режим `all`, завершённый и неполный
|
||||
периоды; coupon/dividend одной и нескольких валют, отрицательная корректировка,
|
||||
повтор operation ID, подтверждённо пустой период. Прогноз с известной/нулевой/
|
||||
неизвестной суммой, dividend с датой реестра; расписание с per-security Money,
|
||||
отдельной оценкой и отсутствующими датами. Управляемая доступность источника
|
||||
и возможность наблюдать только показанные запросы/ресурсные metadata.
|
||||
|
||||
## Manual / Exploratory Scope
|
||||
|
||||
Пройти страницу дохода с клавиатуры и узкого viewport, проверить доступные
|
||||
подписи, перенос длинных сумм и отсутствие горизонтальной прокрутки; перейти
|
||||
между income, журналом, личной историей инструмента, будущими событиями и
|
||||
календарём выпуска. Сравнить смысл подписи в трёх режимах при одинаковой
|
||||
дате и тикере. Отдельно проверить empty/loading/error/recovery и preview.
|
||||
|
||||
## Automation Candidates
|
||||
|
||||
Black-box API: сравнение фактического schema обоих маршрутов с target,
|
||||
успешный/ошибочный/пустой selected и отсутствие запросов к comparison ranges.
|
||||
Сквозные journeys: переход от аккаунта через income/ledger к событию прогноза
|
||||
и календарю инструмента с проверкой подписей и денег. Repository automation:
|
||||
`deferred until QA repo exists`; текущее подтверждение возможно вручную и
|
||||
через existing system-level HTTP/browser runners без требования нового repo.
|
||||
|
||||
## Observability Verification
|
||||
|
||||
По metadata ответа различить complete, pending, failed selected; запрос
|
||||
исторического периода не должен сопровождаться comparison-only dependencies.
|
||||
На отказе проверить корреляцию HTTP request ID и безопасного ответа, не
|
||||
ожидая новых событий журналирования или передачи личных данных в лог.
|
||||
|
||||
## Regression Impact
|
||||
|
||||
Полный журнал, недавние операции, страница акции/облигации и их фильтры,
|
||||
превью/полный прогноз, summary текущего месяца, мультивалютность и
|
||||
независимые loading/error states. Затронутые публичные потребители
|
||||
income-analytics требуют обновления контракта как пары backend/frontend.
|
||||
|
||||
## Gaps / Blockers
|
||||
|
||||
Блокирующих semantic gaps после утверждения Specs/System Analysis нет.
|
||||
Если опубликованный backend OpenAPI не удовлетворяет target либо картинка
|
||||
«получено» появляется на графике, маршрутизировать несовпадение в System
|
||||
Analysis/Delta Specs до принятия реализации; внутреннюю стратегию исправления
|
||||
определяют владельцы реализации.
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
## REMOVED Requirements
|
||||
|
||||
### Requirement: Period comparisons preserve calendar and currency meaning
|
||||
|
||||
**Reason**: Сравнения с предыдущим периодом и годом ранее больше не входят в
|
||||
назначение аналитики полученного дохода и требуют избыточной загрузки истории.
|
||||
|
||||
**Migration**: Пользователь видит только итоги и состав выплат применённого
|
||||
периода; потребители ответа аналитики больше не получают данные сравнений и
|
||||
состояния их доступности. Исторический период можно по-прежнему применить
|
||||
самостоятельно, но система не сопоставляет его с другим периодом автоматически.
|
||||
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: User explicitly applies an analytics period represented in the URL
|
||||
|
||||
Страница выбранного Brokerage Account «Пассивный доход» MUST позволять User редактировать черновик `from` и `to`, не изменяя видимую аналитику до явного применения. Верхний блок фильтров MUST предоставлять два подписанных календарных поля начала и окончания периода с тем же взаимодействием выбора даты, что в истории событий портфеля, и отображением дат в формате `ДД.ММ.ГГГГ`. Поля и действия применения и сброса MUST быть доступны с клавиатуры. Явное применение MUST заменить применённый период, загрузить соответствующий результат и представить применённые даты в URL страницы. Недопустимый черновик MUST показывать ошибку соответствующего поля и MUST NOT заменять последний применённый период. Сброс MUST немедленно вернуть применённый период к текущему месяцу по сегодняшний день и синхронизировать URL. Перезагрузка или открытие URL с допустимым периодом MUST восстановить тот же применённый период. Страница MUST NOT дублировать период отдельной подписью под блоком фильтров. Действие перехода на страницу MUST быть доступно из выбранного Brokerage Account, а не из глобальной навигации.
|
||||
|
||||
#### Scenario: Черновик периода не применён
|
||||
|
||||
- **WHEN** User изменяет черновик `from` или `to`, но не применяет его
|
||||
- **THEN** видимые итоги и карточки выплат остаются основанными на последнем применённом периоде
|
||||
|
||||
#### Scenario: Выбор дат в верхнем блоке
|
||||
|
||||
- **WHEN** User выбирает начало и окончание периода через календарные поля
|
||||
- **THEN** выбранные даты отображаются в подписанных полях в формате `ДД.ММ.ГГГГ`, а изменение остаётся черновиком до явного применения
|
||||
|
||||
#### Scenario: Управление фильтрами с клавиатуры
|
||||
|
||||
- **WHEN** User управляет верхним блоком фильтров с клавиатуры
|
||||
- **THEN** он может последовательно перейти к обоим полям дат, изменить период и выполнить применение или сброс без мыши
|
||||
|
||||
#### Scenario: Применение периода
|
||||
|
||||
- **WHEN** User явно применяет допустимый черновик периода
|
||||
- **THEN** страница загружает аналитику этого периода и отражает применённые `from` и `to` в URL
|
||||
|
||||
#### Scenario: Недопустимый черновик периода
|
||||
|
||||
- **WHEN** User пытается применить черновик с отсутствующей, некорректной или будущей датой либо с `from` после `to`
|
||||
- **THEN** страница показывает ошибку соответствующего поля и сохраняет последний применённый период, его URL и видимую аналитику
|
||||
|
||||
#### Scenario: Восстановление применённого периода из URL
|
||||
|
||||
- **WHEN** User открывает URL страницы с допустимыми `from` и `to`
|
||||
- **THEN** страница показывает аналитику за указанный применённый период
|
||||
|
||||
#### Scenario: Сброс периода
|
||||
|
||||
- **WHEN** User сбрасывает пользовательский период
|
||||
- **THEN** страница немедленно применяет период от первого дня текущего месяца по Europe/Moscow до сегодняшнего дня и синхронизирует URL
|
||||
|
||||
### Requirement: Realized analytics never presents an incomplete result as complete
|
||||
|
||||
Система MUST формировать выбранный результат, его trend buckets, instrument breakdown и drill-down только после успешного получения всех необходимых cursor pages исполненных операций выбранного периода. Ошибка любой необходимой страницы MUST завершать расчёт восстанавливаемой ошибкой и MUST NOT возвращать частичные totals, buckets или breakdown как полный результат. Успешный период без подходящих выплат MUST возвращать нулевой результат и отображаться с явным объяснением пустого состояния. Система MUST NOT загружать другие периоды ради сравнения полученного дохода с выбранным периодом.
|
||||
|
||||
#### Scenario: Все страницы операций успешно получены
|
||||
|
||||
- **WHEN** для расчёта требуется несколько cursor pages и каждая страница успешно получена
|
||||
- **THEN** система формирует результат по всем подходящим Ledger Entries со всех страниц выбранного периода без расчёта сравнений с другими периодами
|
||||
|
||||
#### Scenario: Одна из страниц операций недоступна
|
||||
|
||||
- **WHEN** получение любой необходимой cursor page завершается ошибкой
|
||||
- **THEN** страница показывает восстанавливаемую ошибку и не показывает частичный результат как полный
|
||||
|
||||
#### Scenario: В периоде нет купонов и дивидендов
|
||||
|
||||
- **WHEN** все необходимые операции успешно получены, но среди них нет подходящих coupon или dividend Ledger Entries
|
||||
- **THEN** страница показывает нулевой результат и объясняет, что за выбранный период купоны и дивиденды не найдены
|
||||
|
||||
### Requirement: Income payments remain traceable to exact Ledger Entries
|
||||
|
||||
В разделе «Выплаты» страница MUST показывать единый список карточек точных исполненных Ledger Entries применённого периода в исходном серверном порядке entries. Каждая выплата MUST иметь собственную сразу видимую карточку с описанием, датой исполнения, доступной identity Instrument и signed Money в исходной валюте. Купоны и дивиденды MUST использовать то же представление выплаты, что и на экранах журнала, прогноза и графиков инструментов, при этом карточка MUST обозначать эту сумму именно как фактически исполненную, а не прогнозную. Страница MUST NOT добавлять внешние группировочные карточки или заголовки по Instrument либо валюте, subtotals инструмента или количество выплат инструмента. Список MUST сохранять отрицательные корректировки и повторяющиеся operation IDs как отдельные записи и MUST NOT включать записи вне аналитического итога. Backend MUST обеспечивать согласованность entries, instrumentKey, валюты и receipt count при формировании ответа из одного набора записей. Frontend SHALL доверять типизированному contract без второго runtime consistency validator и MUST NOT пересчитывать денежные итоги.
|
||||
|
||||
#### Scenario: Каждая выплата показана отдельной карточкой
|
||||
|
||||
- **WHEN** выбранный период содержит несколько включённых Ledger Entries одного или разных Instrument
|
||||
- **THEN** раздел «Выплаты» сразу показывает отдельную карточку каждой записи в исходном порядке без внешних группировочных блоков, раскрытия, итогов инструмента и receipt count на UI
|
||||
|
||||
#### Scenario: Список воспроизводит точный состав дохода
|
||||
|
||||
- **WHEN** User просматривает загруженный раздел «Выплаты»
|
||||
- **THEN** он видит все и только включённые coupon и dividend Ledger Entries применённого периода с датой, описанием, доступной identity и исходной суммой, обозначенной как исполненная выплата
|
||||
|
||||
#### Scenario: Отрицательная корректировка и повторяющиеся IDs сохраняются
|
||||
|
||||
- **WHEN** доход содержит отрицательную корректировку либо несколько включённых entries с одинаковым operation ID
|
||||
- **THEN** каждая запись остаётся отдельной карточкой, а корректировка отображается с исходным знаком
|
||||
|
||||
#### Scenario: Валюта видна в сумме каждой выплаты
|
||||
|
||||
- **WHEN** подходящие выплаты одного Instrument представлены в нескольких исходных валютах
|
||||
- **THEN** каждая карточка показывает свою Money с исходной валютой, без отдельного заголовка валютной группы или объединённого мультивалютного итога
|
||||
|
||||
### Requirement: Analytics summary remains readable per currency
|
||||
|
||||
Страница MUST обозначать фактический результат как «Получено купонами и дивидендами» и для каждой исходной валюты показывать total, coupon subtotal и dividend subtotal выбранного периода. Она MUST объяснять, что tax operations не включены, не называя фактический результат gross, net, суммой до налогов, суммой после налогов или налоговым расчётом. Значения MUST оставаться доступными как читаемый текст, не только как графика, цвет или положение. Страница MUST NOT показывать блок «Динамика», его график, переключатель валюты графика или текстовый список временных buckets независимо от длительности выбранного периода. Страница MUST NOT показывать блоки «Предыдущий период» и «Годом ранее» или сообщения о недоступности сравнений.
|
||||
|
||||
#### Scenario: Итоги дохода доступны как текст
|
||||
|
||||
- **WHEN** выбранный период содержит исполненные купонные или дивидендные выплаты
|
||||
- **THEN** страница показывает читаемые total, coupon subtotal и dividend subtotal с обозначением фактически полученного дохода и объяснением исключения tax operations
|
||||
|
||||
#### Scenario: Итоги нескольких валют остаются разделёнными
|
||||
|
||||
- **WHEN** результат содержит подходящие выплаты в нескольких исходных валютах
|
||||
- **THEN** страница показывает отдельные читаемые итоги каждой валюты без конвертации и общего итога разных валют
|
||||
|
||||
#### Scenario: Динамика отсутствует для периода любой длительности
|
||||
|
||||
- **WHEN** User открывает аналитику или применяет допустимый период любой длительности
|
||||
- **THEN** страница показывает итоги и выплаты без динамики, сравнений периодов и состояний их доступности
|
||||
|
||||
### Requirement: Income page excludes upcoming forecasts
|
||||
|
||||
Страница «Пассивный доход» MUST NOT показывать блок «Ближайший прогноз», его суммы, список будущих выплат, состояния загрузки, пустоты или ошибки. Forecast values MUST NOT входить в realized total, trend buckets или instrument breakdown. Доступность данных Future Cash Events MUST NOT влиять на отображение успешно загруженной realized analytics. Существующая самостоятельная страница «Будущие события» и её доступность из выбранного Brokerage Account MUST сохраняться.
|
||||
|
||||
#### Scenario: Известные будущие выплаты не появляются на странице дохода
|
||||
|
||||
- **WHEN** для выбранного Brokerage Account известны будущие coupon или dividend события с суммой или без неё либо maturity или offer события
|
||||
- **THEN** страница дохода не показывает блок «Ближайший прогноз» и не включает эти будущие события в фактически полученный доход
|
||||
|
||||
#### Scenario: Изменение исторического периода не возвращает прогноз
|
||||
|
||||
- **WHEN** User применяет допустимый исторический период или сбрасывает фильтры
|
||||
- **THEN** страница показывает соответствующую realized analytics без блока «Ближайший прогноз»
|
||||
|
||||
#### Scenario: Данные будущих событий недоступны
|
||||
|
||||
- **WHEN** realized analytics успешно загружена, а данные Future Cash Events недоступны
|
||||
- **THEN** итоги и карточки выплат остаются доступными, а страница дохода не показывает состояние ошибки или загрузки прогноза
|
||||
|
||||
#### Scenario: Самостоятельная страница будущих событий сохраняется
|
||||
|
||||
- **WHEN** User переходит из выбранного Brokerage Account на существующую страницу «Будущие события»
|
||||
- **THEN** эта страница остаётся доступной с прежним поведением независимо от отсутствия прогноза на странице дохода
|
||||
@@ -0,0 +1,59 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Account overview includes recent ledger events
|
||||
|
||||
Обзор счёта MUST показывать пять последних исполненных записей журнала этого счёта и действие перехода к его полному журналу. Каждая показанная запись MUST иметь ту же визуальную идентичность инструмента и семантику денежного движения, что и запись полного журнала. Исполненные купоны и дивиденды MUST иметь то же представление выплаты, что и на других экранах с купонами и дивидендами; остальные операции сохраняют представление записи журнала. Неуспешный или пустой запрос последних записей MUST оставаться локальным состоянием блока последних событий и MUST NOT заменять успешно отображённый обзор Portfolio.
|
||||
|
||||
#### Scenario: Отображение последних событий
|
||||
|
||||
- **WHEN** загружается обзор счёта и его журнал содержит исполненные операции
|
||||
- **THEN** обзор показывает не более пяти последних записей и ссылку на полный журнал, а купоны и дивиденды узнаваемы по тому же представлению выплаты
|
||||
|
||||
#### Scenario: Последние записи недоступны
|
||||
|
||||
- **WHEN** обзор счёта успешно загружается, но запрос последних записей завершается ошибкой
|
||||
- **THEN** обзор Portfolio остаётся доступным, а блок последних событий отображает собственное состояние восстановления
|
||||
|
||||
#### Scenario: Последняя запись не содержит visual metadata инструмента
|
||||
|
||||
- **WHEN** одна из последних записей не имеет доступной presentation metadata инструмента
|
||||
- **THEN** обзор показывает для неё понятный текстовый fallback и сохраняет дату, тип, инструмент и денежное изменение записи доступными для чтения
|
||||
|
||||
### Requirement: Full ledger presents compact rows
|
||||
|
||||
Страница полного журнала MUST показывать для каждой записи дату, тип операции, инструмент и денежное изменение в исходной валюте в компактной структурированной строке. При доступной presentation metadata инструмента строка MUST показывать его визуальную идентичность; при её отсутствии MUST использовать понятный текстовый fallback. Для купонных и дивидендных операций на странице полного журнала и в личной истории инструмента MUST использоваться то же представление выплаты, что в доходе, прогнозе и графиках инструментов, с обозначением исполненного движения. Для каждой записи денежное изменение в исходной валюте MUST сопровождаться подписью конкретного типа события и знаком: для купонной операции — «Купон», для дивидендной — «Дивиденд», для остальных записей — подпись их категории («Сделка», «Налог», «Комиссия», «Перевод», «Прочее»). Строка MUST NOT повторять подпись типа события во вторичной метадате записи. Знак «+» / «−» и семантический цвет MUST оставаться носителями направления и MUST NOT заменяться только текстом. Страница MUST обозначать записи без движения денег нейтрально и MUST NOT показывать цену или количество.
|
||||
|
||||
#### Scenario: Отображение записи только с инструментом
|
||||
|
||||
- **WHEN** полный журнал отображает запись без денежной выплаты
|
||||
- **THEN** страница определяет её как запись без движения денег
|
||||
|
||||
#### Scenario: Отображение поступления
|
||||
|
||||
- **WHEN** полный журнал отображает запись с положительной денежной выплатой
|
||||
- **THEN** строка явно показывает поступление знаком и подписью конкретного типа события («Купон», «Дивиденд» или категории) и его денежное изменение в исходной валюте, не полагаясь только на цвет
|
||||
|
||||
#### Scenario: Отображение списания
|
||||
|
||||
- **WHEN** полный журнал отображает запись с отрицательной денежной выплатой
|
||||
- **THEN** строка явно показывает списание знаком и подписью конкретного типа события («Купон», «Дивиденд» или категории) и его денежное изменение в исходной валюте, не полагаясь только на цвет
|
||||
|
||||
#### Scenario: Отображение купона
|
||||
|
||||
- **WHEN** полный журнал или личная история инструмента отображает исполненную операцию с upstream-типом купона
|
||||
- **THEN** запись показывает подпись «Купон» и исполненную сумму в том же представлении выплаты, что на других экранах
|
||||
|
||||
#### Scenario: Отображение дивиденда
|
||||
|
||||
- **WHEN** полный журнал или личная история инструмента отображает исполненную операцию с upstream-типом дивиденда
|
||||
- **THEN** запись показывает подпись «Дивиденд» и исполненную сумму в том же представлении выплаты, что на других экранах
|
||||
|
||||
#### Scenario: Подпись типа не дублируется
|
||||
|
||||
- **WHEN** полный журнал отображает запись с типом события и вторичной метадатой
|
||||
- **THEN** подпись типа события присутствует в строке один раз и не повторяется во вторичной метадате записи
|
||||
|
||||
#### Scenario: Отсутствует visual metadata инструмента
|
||||
|
||||
- **WHEN** полный журнал отображает запись без доступной presentation metadata инструмента
|
||||
- **THEN** строка показывает понятный текстовый fallback без подмены или сокрытия доступных данных инструмента
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Account page presents an upcoming events list
|
||||
|
||||
Страница Brokerage Account MUST предоставлять read-only действие перехода на отдельную страницу «Будущие события». Эта страница MUST показывать события сохранённого полного прогноза компактным списком без фильтров, пагинации, суммарного итога или действия ручной синхронизации, с датой, типом, инструментом и прогнозной суммой в исходной валюте, если она известна. Купоны и дивиденды MUST использовать то же представление выплаты, что и исполненные купоны, дивиденды и события графика инструмента, но MUST быть явно обозначены как прогноз, а не полученные деньги. Дата дивиденда MUST быть обозначена как дата реестра. Страница MUST показывать `calculatedAt`, исходное окно прогноза и наблюдаемые freshness, полноту, время последнего успешного прогноза, последнюю часовую попытку и доступность из `meta` понятным текстом или иконкой с доступным именем, а не только цветом. Она MUST объяснять, что прогноз рассчитан по количеству бумаг на `calculatedAt`, а показанные события дополнительно ограничены запрошенным включительным UTC-окном; прогноз указан до налогов и может быть неполным из-за доступности данных источника. Открытие страницы и повтор HTTP-чтения MUST NOT запускать личную синхронизацию.
|
||||
|
||||
#### Scenario: Просмотр ближайших событий
|
||||
|
||||
- **WHEN** User открывает «Будущие события» из обзора Brokerage Account
|
||||
- **THEN** он видит отсортированный read-only список событий сохранённого 30-календарного окна и `calculatedAt`, где купоны и дивиденды представлены как прогнозные выплаты, а offer обозначен без суммы
|
||||
|
||||
#### Scenario: Прогнозный дивиденд с неизвестной суммой
|
||||
|
||||
- **WHEN** прогноз содержит дивиденд с известной датой реестра, но без суммы
|
||||
- **THEN** его карточка обозначает дату как дату реестра и сумму как неизвестную, не показывает нулевую или полученную выплату
|
||||
|
||||
#### Scenario: Пустое состояние страницы
|
||||
|
||||
- **WHEN** запрос будущих событий успешно возвращает пустой список
|
||||
- **THEN** страница сообщает, что в сохранённом окне прогноза событий не найдено, показывает `calculatedAt` и объясняет ограничения покрытия источника
|
||||
|
||||
#### Scenario: Первая загрузка либо ошибка без сохранённого прогноза
|
||||
|
||||
- **WHEN** запрос будущих событий возвращает `data: null`, а `meta` обозначает выполнение первой загрузки либо её неуспех
|
||||
- **THEN** страница показывает доступное состояние загрузки либо ошибки без частичного списка и предоставляет при ошибке действие повторить только HTTP-чтение
|
||||
|
||||
#### Scenario: Ошибка страницы
|
||||
|
||||
- **WHEN** запрос будущих событий завершается ошибкой
|
||||
- **THEN** страница не показывает частичный список и предоставляет действие повторить только HTTP-чтение
|
||||
|
||||
#### Scenario: Ошибка обновления при сохранённом прогнозе на странице
|
||||
|
||||
- **WHEN** запрос будущих событий возвращает последний полный прогноз вместе с ошибкой его обновления
|
||||
- **THEN** страница показывает этот прогноз с его исходными `calculatedAt` и окном, отдельно сообщает об ошибке обновления и предоставляет действие повторить только HTTP-чтение
|
||||
|
||||
### Requirement: Account overview includes upcoming events
|
||||
|
||||
Обзор Brokerage Account MUST показывать не более пяти ближайших Future Cash Event сохранённого полного прогноза в применённом запрошенном окне, его `calculatedAt`, исходное окно, наблюдаемую freshness, полноту, последнюю часовую попытку и доступность из `meta`, а также действие перехода на read-only полную страницу «Будущие события». Купоны и дивиденды MUST быть представлены той же карточкой выплаты, что на полной странице событий и остальных экранах, с явным обозначением прогнозного статуса; погашение и оферта сохраняют своё значение. Статус MUST быть понятен текстом или иконкой с доступным именем, а не только цветом. Неуспешное обновление при сохранённом прогнозе MUST оставаться локальным состоянием блока, сохранять показанные события и их исходное окно и MUST NOT заменять успешно отображённый Portfolio. Если полного прогноза нет, неуспешное обновление MUST оставаться локальным состоянием блока без частичного списка. Обзор MUST NOT предоставлять действие ручной синхронизации; его повтор MUST выполнять только HTTP-чтение.
|
||||
|
||||
#### Scenario: Отображение ближайших событий
|
||||
|
||||
- **WHEN** обзор счёта успешно загружен и сохранённый прогноз содержит будущие события
|
||||
- **THEN** обзор показывает первые пять событий в порядке даты, `calculatedAt` и действие перехода к полной странице, используя единое представление для прогнозных купонов и дивидендов
|
||||
|
||||
#### Scenario: Ближайшие события недоступны без сохранённого прогноза
|
||||
|
||||
- **WHEN** обзор счёта успешно загружен, а события возвращают `data: null` и `meta` обозначает выполнение первой загрузки либо её неуспех
|
||||
- **THEN** Portfolio остаётся доступным, а блок будущих событий отображает собственное доступное состояние загрузки либо ошибки без частичного списка
|
||||
|
||||
#### Scenario: Ближайшие события недоступны
|
||||
|
||||
- **WHEN** обзор счёта успешно загружен, но запрос будущих событий завершается ошибкой
|
||||
- **THEN** Portfolio остаётся доступным, а блок будущих событий отображает собственную ошибку
|
||||
|
||||
#### Scenario: Неуспешное обновление не скрывает сохранённый прогноз
|
||||
|
||||
- **WHEN** обзор счёта получает сохранённый полный прогноз вместе с ошибкой его обновления
|
||||
- **THEN** Portfolio и события сохранённого окна остаются доступными, а блок отдельно обозначает ошибку и предлагает повторить только HTTP-чтение
|
||||
@@ -0,0 +1,25 @@
|
||||
## Purpose
|
||||
|
||||
Позволяет отличать опубликованные календарные сведения о купонах и дивидендах
|
||||
инструмента от фактически полученных личных выплат и прогноза по позиции.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Instrument payout schedules do not imply executed income
|
||||
|
||||
На страницах акций и облигаций известные будущие, прошедшие и недатированные события графика дивидендов или купонов MUST использовать то же представление выплаты, что и купоны/дивиденды других экранов, но MUST обозначать их как события графика, не подтверждающие фактическое зачисление. Доступные дата реестра, дата выплаты, сумма на одну бумагу и отдельная личная оценка MUST сохранять свои подписи и смысл; неизвестная сумма или дата MUST NOT подменяться нулём или вымышленной датой. Исполненная личная операция MUST оставаться отличимой от события графика, даже когда их даты совпадают.
|
||||
|
||||
#### Scenario: Будущий купон с известными условиями
|
||||
|
||||
- **WHEN** User просматривает будущий купон облигации с известными датой выплаты, суммой на облигацию и оценкой для позиции
|
||||
- **THEN** единое представление показывает купон как событие графика, сохраняет обе разные суммы и дату и не называет оценку полученными деньгами
|
||||
|
||||
#### Scenario: Прошедший дивиденд без подтверждённой операции
|
||||
|
||||
- **WHEN** User просматривает в истории акции событие дивидендного графика с прошедшей датой реестра
|
||||
- **THEN** представление показывает его как событие графика с суммой на акцию, а не как исполненную выплату пользователю
|
||||
|
||||
#### Scenario: Неизвестные условия графика
|
||||
|
||||
- **WHEN** в купонном или дивидендном графике отсутствует дата выплаты либо денежное значение
|
||||
- **THEN** представление сохраняет известные сведения и явно различает неизвестное значение и ноль без вымышленной даты зачисления
|
||||
@@ -0,0 +1,123 @@
|
||||
# System Analysis
|
||||
|
||||
## Requirement Coverage
|
||||
|
||||
| Нормативная область | Поток и контракт |
|
||||
| --- | --- |
|
||||
| `brokerage-account-income-analytics`: удаление `Period comparisons preserve calendar and currency meaning`, выбранный период, полнота, читаемые итоги, отсутствие прогноза | [income-period.mmd](sequences/income-period.mmd), [target schema](contracts/income-analytics-response.schema.json) |
|
||||
| `brokerage-account-income-analytics`: точные карточки выплат | [payment-sources.mmd](sequences/payment-sources.mmd), существующая форма entries |
|
||||
| `brokerage-account-ledger`: журнал, недавние операции и история инструмента | [payment-sources.mmd](sequences/payment-sources.mmd), существующий ответ операций |
|
||||
| `brokerage-account-upcoming-events`: полный список и превью | [payment-sources.mmd](sequences/payment-sources.mmd), существующий ответ событий |
|
||||
| `instrument-income-schedules`: будущее, прошлое, неопределённая дата/сумма | [payment-sources.mmd](sequences/payment-sources.mmd), существующие ответы календарей |
|
||||
|
||||
## Systems and Responsibilities
|
||||
|
||||
- Пользователь выбирает применённый период и отличает исполненные выплаты от
|
||||
возможных поступлений и условий выпуска.
|
||||
- Frontend хранит применённые даты в URL, показывает только финансовые значения
|
||||
их собственного источника и использует один предметный компонент для
|
||||
купонов/дивидендов всех трёх режимов. Он не выводит исполнение из календаря.
|
||||
- Backend проверяет доступ, период и покрытие операций; формирует точные
|
||||
source-currency итоги и записи выбранного периода. Для income-analytics не
|
||||
запрашивает предыдущий или годовой период ради сравнения.
|
||||
- Сохранённые операции T-Bank остаются источником фактических выплат; прогноз
|
||||
основан на позиции, календарь бумаги — на опубликованных условиях T-Bank/MOEX.
|
||||
Они не становятся взаимозаменяемыми при объединении представления.
|
||||
|
||||
## Interaction Flows
|
||||
|
||||
- [Доход выбранного периода](sequences/income-period.mmd): доступ, полнота,
|
||||
успешный/пустой результат и неполное покрытие без запросов сравнения.
|
||||
- [Три источника карточки выплаты](sequences/payment-sources.mmd): подтверждённая
|
||||
операция, будущий прогноз и событие календаря; остальные типы сохраняют
|
||||
существующее представление.
|
||||
|
||||
## Contracts
|
||||
|
||||
| Производитель → потребитель | Транспорт / операция | Целевой контракт |
|
||||
| --- | --- | --- |
|
||||
| Backend → frontend | `GET /api/v1/brokerage-accounts/{accountId}/income-analytics`, `GET /api/v1/brokerage-accounts/all/income-analytics`, `application/json` 200 | [JSON Schema ограничений ответа](contracts/income-analytics-response.schema.json) поверх текущего backend-generated OpenAPI: убрать `data.previous`, `data.yearComparison`, comparison roles в `meta.dependencies`; оставить выбранный период и все прочие поля и ошибки в исходном смысле. |
|
||||
| Backend → frontend | Income summary, операции, события, календари акций/облигаций | Без изменений wire-формы; типизированные исходные данные адаптируются к общему представлению купона/дивиденда на границе UI. |
|
||||
|
||||
Целевой schema-файл описывает *изменение* ответа и не подменяет полную схему
|
||||
неизменённых полей; при согласовании используется вместе с предоставленным
|
||||
OpenAPI snapshot. `meta.dependencies` содержит только зависимость выбранного
|
||||
периода с ролью `selected`; это не новая причина загрузки другого периода.
|
||||
Существующие auth, invalid-period и resource errors не меняются. Отсутствуют
|
||||
новые операции/версии и callback-протоколы. Порядок entries и повторяющиеся ID
|
||||
сохраняются; повторный HTTP read не должен создавать второе зачисление.
|
||||
|
||||
## Data and State Semantics
|
||||
|
||||
- `data: null` с незавершённым покрытием выбранного периода не становится
|
||||
нулевым доходом. Успешный полный период без qualifying entries — доступный
|
||||
нулевой результат. Свежесть и попытка обновления относятся к выбранному
|
||||
результату, не к удалённым comparison-периодам.
|
||||
- Купоны/дивиденды фактического дохода — точные исполненные операции с
|
||||
исходным знаком, валютой и timestamp; календарное событие с прошедшей датой
|
||||
не доказывает их наличие.
|
||||
- Forecast projected amount может быть `null`; для dividend `dateKind=registry`
|
||||
означает дату реестра, не зачисления. График хранит per-share/per-bond Money,
|
||||
опциональную оценку по позиции, известные даты и время источника отдельно от
|
||||
`payment` исполненной операции. Неизвестное не становится нулём.
|
||||
- Общий предметный компонент получает явный режим происхождения данных;
|
||||
адаптация не пересчитывает backend totals и не меняет source identity.
|
||||
|
||||
## Error and Recovery Semantics
|
||||
|
||||
- Некорректный черновик остаётся на клиенте с ошибкой поля; серверный invalid
|
||||
period и отказ доступа сохраняют действующие ответы без fallback на другой
|
||||
период или чужой счёт.
|
||||
- Ошибка получения страницы исполненных операций не завершает покрытие
|
||||
выбранного периода и не публикует частичный итог как полный. Последний
|
||||
подтверждённый результат и его исходное время остаются независимыми от
|
||||
неуспеха последней попытки.
|
||||
- Ошибка прогноза не скрывает уже загруженный доход; отсутствие оценки,
|
||||
логотипа либо даты в календаре не создаёт ложного исполнения или нуля.
|
||||
- Поздний ответ прежнего подключения не должен восстановить личные данные
|
||||
нового/недоступного подключения; граница доступа сохраняется.
|
||||
|
||||
## Observability Semantics
|
||||
|
||||
- Существующие status результата, `meta` полноты/попытки и request correlation
|
||||
позволяют отличить полный выбранный период, pending и failure.
|
||||
- Событие синхронизации выбранного периода не включает comparison-only
|
||||
dependencies; получение прошлого/годового интервала для иных самостоятельных
|
||||
запросов не считается сравнением дохода.
|
||||
- Новых аналитических событий или чувствительных атрибутов не требуется.
|
||||
|
||||
## Security and NFR at System Boundaries
|
||||
|
||||
- Bearer-сессия, текущее подключение и доступ к выбранному счёту проверяются
|
||||
до выдачи личных операций; `all` ограничен доступными счетами.
|
||||
- Даты остаются включительными календарными датами Europe/Moscow, без
|
||||
максимальной длительности; валюты не конвертируются. Не вводится новый SLA.
|
||||
|
||||
## Compatibility / Migration
|
||||
|
||||
Удаление `previous` и `yearComparison` из ответа намеренно breaking для
|
||||
потребителя старой формы. Backend публикует обновлённый исполняемый OpenAPI;
|
||||
frontend получает его как явный artifact и обновляет локальные типы прежде,
|
||||
чем интеграция начнёт опираться на новую форму. Строгая semantic compatibility
|
||||
между новым OpenAPI и target schema проверяется до поставки. При поставке
|
||||
backend и frontend согласуются как пара, без обещания одновременной
|
||||
совместимости со старым потребителем. Существующие поля buckets/instruments,
|
||||
запросы сводки/журнала/прогноза и их доступность не меняются.
|
||||
|
||||
## Durable Documentation Candidates
|
||||
|
||||
- `docs/domains/income/overview.md`: отсутствие сравнений и загрузки чужих
|
||||
периодов, только полнота выбранного периода.
|
||||
- `docs/domains/portfolio/all-accounts.md`,
|
||||
`docs/adr/017-local-tbank-reads-and-background-sync.md`: проверить
|
||||
упоминания приоритета и смысла удалённых comparisons; ADR хранить как
|
||||
историческое решение, не переписывать как AS-IS.
|
||||
- `docs/domains/income/upcoming-events.md`, `docs/domains/instruments/stocks.md`,
|
||||
`docs/domains/instruments/bonds.md`, `docs/domains/operations/overview.md`:
|
||||
общая карточка при сохранении границы между исполнением, прогнозом и графиком.
|
||||
|
||||
## Open Questions
|
||||
|
||||
Нет блокирующих вопросов в утверждённом scope. Детали визуальной композиции
|
||||
общего компонента остаются за Engineering Design при сохранении нормативных
|
||||
различий денежного и календарного смысла.
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://wealthledger.local/contracts/unify-income-payment-cards/income-analytics-response.schema.json",
|
||||
"title": "Целевое изменение ответа income-analytics",
|
||||
"description": "Ограничения поверх неизменённых свойств текущего backend-generated OpenAPI: точный контракт остальных полей остаётся у опубликованного OpenAPI. Применяется к 200 application/json обоих маршрутов income-analytics.",
|
||||
"type": "object",
|
||||
"required": ["data", "meta"],
|
||||
"properties": {
|
||||
"data": {
|
||||
"anyOf": [
|
||||
{ "type": "null" },
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"accountId",
|
||||
"period",
|
||||
"totalsByCurrency",
|
||||
"calculatedAt",
|
||||
"bucketGranularity",
|
||||
"buckets",
|
||||
"instruments",
|
||||
"entries"
|
||||
],
|
||||
"properties": {
|
||||
"previous": false,
|
||||
"yearComparison": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"meta": {
|
||||
"type": "object",
|
||||
"required": ["dependencies"],
|
||||
"properties": {
|
||||
"dependencies": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["role"],
|
||||
"properties": { "role": { "const": "selected" } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
sequenceDiagram
|
||||
actor User
|
||||
participant UI as WealthLedger frontend
|
||||
participant API as WealthLedger backend
|
||||
participant Store as Saved investment data
|
||||
participant Broker as T-Bank
|
||||
User->>UI: Open income page / apply from,to
|
||||
UI->>API: GET income-analytics(accountId or all, from, to)
|
||||
API->>Store: Verify session, membership, selected-period coverage and operations
|
||||
alt Access denied or invalid period
|
||||
API-->>UI: Problem Details (access/input error)
|
||||
UI-->>User: Account/period error; preserve last applied data on invalid draft
|
||||
else Selected period complete
|
||||
Store-->>API: Confirmed selected operations and source state
|
||||
API-->>UI: data with selected totals/entries + meta(selected)
|
||||
UI-->>User: Totals and executed payment cards, no comparisons
|
||||
else Selected period missing or incomplete
|
||||
Store-->>API: Incomplete coverage + resource state
|
||||
API-->>UI: data null + meta(selected)
|
||||
UI-->>User: Loading or recoverable error, no partial final totals
|
||||
opt First read of missing historical interval
|
||||
API->>Broker: Begin bounded acquisition of missing selected interval
|
||||
Broker-->>Store: Publish only confirmed complete result
|
||||
end
|
||||
end
|
||||
Note over API,Store: No previous/year-ago interval is requested for comparison
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
sequenceDiagram
|
||||
actor User
|
||||
participant UI as WealthLedger frontend
|
||||
participant API as WealthLedger backend
|
||||
participant Source as Broker / market source
|
||||
alt Executed coupon or dividend
|
||||
Source-->>API: Confirmed operation with signed payment and timestamp
|
||||
API-->>UI: Ledger/income entry with original Money and instrument identity
|
||||
UI-->>User: Shared payout card - executed, original signed amount
|
||||
else Upcoming coupon or dividend
|
||||
Source-->>API: Forecast event based on position at calculatedAt
|
||||
API-->>UI: Future event, date kind and nullable projected Money
|
||||
UI-->>User: Same payout card - forecast, registry date where applicable
|
||||
else Instrument schedule event
|
||||
Source-->>API: Published coupon/dividend terms, possibly undated/unknown
|
||||
API-->>UI: Per-security amount, optional estimate and dates
|
||||
UI-->>User: Same payout card - schedule, not a confirmed receipt
|
||||
else Other operation or future event
|
||||
API-->>UI: Trade/tax/fee/maturity/offer data
|
||||
UI-->>User: Existing non-payout representation
|
||||
end
|
||||
Note over UI,User: Same payout presentation; source and certainty remain explicit
|
||||
@@ -0,0 +1,67 @@
|
||||
# Tasks
|
||||
|
||||
## 1. Удаление сравнений и поставка контракта дохода
|
||||
|
||||
- [x] 1.1 [backend] Оставить для дохода только выбранный период в чтении и планировании фоновой загрузки; сохранить точные итоги, signed entries, полноту, текущую месячную сводку и существующие buckets.
|
||||
- **Covers:** `brokerage-account-income-analytics` — `Period comparisons preserve calendar and currency meaning` (удаление); `brokerage-account-income-analytics` — `Realized analytics never presents an incomplete result as complete`; `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`.
|
||||
- **Source:** `design.md` §§ Decisions/backend, Data / Storage Changes; `system-analysis/analysis.md` §§ Interaction Flows, Data and State Semantics.
|
||||
- **Verification:** адресные backend tests: один выбранный диапазон в аналитике и screen sync, без previous/year; полные, неполные, пустые, многостраничные и signed-мультивалютные результаты; неизменная current-month summary.
|
||||
- **Depends on:** none
|
||||
|
||||
- [x] 1.2 [backend] Удалить comparison-only поля и роли из обоих публичных income-analytics ответов и опубликовать обновлённый backend-generated OpenAPI как явный контракт для frontend.
|
||||
- **Covers:** `brokerage-account-income-analytics` — `Period comparisons preserve calendar and currency meaning` (удаление); `brokerage-account-income-analytics` — `Realized analytics never presents an incomplete result as complete`.
|
||||
- **Source:** `system-analysis/analysis.md` §§ Contracts, Compatibility / Migration; `system-analysis/contracts/income-analytics-response.schema.json`; `design.md` § Contract Implementation.
|
||||
- **Verification:** `npm run openapi:generate`, `npm run test:openapi-contract` и сопоставление 200 response schema обоих маршрутов с утверждённым target: отсутствуют `previous`, `yearComparison` и роли `previous`/`year`, остальные данные/ошибки сохранены; релевантные HTTP checks и `npm run verify` в backend.
|
||||
- **Depends on:** 1.1
|
||||
|
||||
- [x] 1.3 [frontend] Обновить полученный OpenAPI snapshot и generated types, удалить UI, display-only расчёты и состояния сравнений на странице дохода, сохранив фильтры, итоги, налоговое пояснение, плоские выплаты и состояния выбранного периода.
|
||||
- **Covers:** `brokerage-account-income-analytics` — `Period comparisons preserve calendar and currency meaning` (удаление); `brokerage-account-income-analytics` — `User explicitly applies an analytics period represented in the URL`; `brokerage-account-income-analytics` — `Analytics summary remains readable per currency`; `brokerage-account-income-analytics` — `Income page excludes upcoming forecasts`; `brokerage-account-income-analytics` — `Realized analytics never presents an incomplete result as complete`.
|
||||
- **Source:** `design.md` §§ Decisions/frontend, Contract Implementation, UI/UX Package; `system-analysis/analysis.md` § Contracts.
|
||||
- **Verification:** frontend behavior checks для applied/draft периода, URL/back/reset, неполного/пустого/ошибочного selected и отсутствия comparison headings/notices во всех состояниях; локальные typecheck и `npm run verify` на итоговом frontend diff.
|
||||
- **Depends on:** 1.2
|
||||
|
||||
## 2. Одна предметная карточка купона и дивиденда
|
||||
|
||||
- [x] 2.1 [frontend] Предоставить единый публичный компонент выплаты с явными режимами исполнения, прогноза и графика, сохранив исходную валюту, знак, отсутствие данных и различимые подписи суммы/дат.
|
||||
- **Covers:** `brokerage-account-income-analytics` — `Income payments remain traceable to exact Ledger Entries`; `brokerage-account-ledger` — `Full ledger presents compact rows`; `brokerage-account-upcoming-events` — `Account page presents an upcoming events list`; `instrument-income-schedules` — `Instrument payout schedules do not imply executed income`.
|
||||
- **Source:** `design.md` §§ Decisions/frontend, UI/UX Package; `system-analysis/analysis.md` § Data and State Semantics.
|
||||
- **Verification:** frontend checks разных source modes с signed Money, нулём против неизвестного, registry date и separate per-security/position amounts; `npm run deps`, `npm run typecheck`.
|
||||
- **Depends on:** none
|
||||
|
||||
- [x] 2.2 [frontend] Использовать единый компонент для исполненных купонов/дивидендов в доходе, полном журнале, недавних операциях и личной истории инструментов; сохранить порядок, повторы и представление остальных операций.
|
||||
- **Covers:** `brokerage-account-income-analytics` — `Income payments remain traceable to exact Ledger Entries`; `brokerage-account-ledger` — `Account overview includes recent ledger events`; `brokerage-account-ledger` — `Full ledger presents compact rows`.
|
||||
- **Source:** `design.md` §§ Decisions/frontend, UI/UX Package; `qa-analysis.md` § Coverage Matrix.
|
||||
- **Verification:** frontend checks для одного и того же типа карточки во всех перечисленных местах, повторов IDs, исправлений с минусом, fallback identity, деталей личной истории и неизменённых trade/tax rows.
|
||||
- **Depends on:** 2.1
|
||||
|
||||
- [x] 2.3 [frontend] Использовать тот же компонент в полном прогнозе и его превью только для купонов/дивидендов, обозначить прогноз и дату реестра дивиденда, сохранить offer/maturity.
|
||||
- **Covers:** `brokerage-account-upcoming-events` — `Account page presents an upcoming events list`; `brokerage-account-upcoming-events` — `Account overview includes upcoming events`.
|
||||
- **Source:** `design.md` §§ Decisions/frontend, UI/UX Package; `system-analysis/analysis.md` § Data and State Semantics.
|
||||
- **Verification:** frontend checks для известной, нулевой и неизвестной projected amount, registry date, preview/full list, offer/maturity и локальных ошибок источника.
|
||||
- **Depends on:** 2.1
|
||||
|
||||
- [x] 2.4 [frontend] Использовать тот же компонент в будущих и прошедших графиках акций/облигаций с отдельными подписями условий на бумагу и оценки без приписывания личного зачисления.
|
||||
- **Covers:** `instrument-income-schedules` — `Instrument payout schedules do not imply executed income`.
|
||||
- **Source:** `design.md` §§ Decisions/frontend, UI/UX Package; `system-analysis/analysis.md` § Data and State Semantics.
|
||||
- **Verification:** frontend checks для будущего купона, прошлого дивиденда, недатированного/неизвестного условия, разных сумм на бумагу и позицию; проверка узкого viewport и клавиатуры, `npm run verify` на итоговом frontend diff.
|
||||
- **Depends on:** 2.1
|
||||
|
||||
## 3. Актуальная документация после подтверждения целевого поведения
|
||||
|
||||
- [x] 3.1 [docs] Привести страницы дохода одного и всех счетов к состоянию без сравнений и описать прежнюю полноту выбранного периода.
|
||||
- **Covers:** `brokerage-account-income-analytics` — `Period comparisons preserve calendar and currency meaning` (удаление); `brokerage-account-income-analytics` — `Analytics summary remains readable per currency`; `brokerage-account-income-analytics` — `Realized analytics never presents an incomplete result as complete`.
|
||||
- **Source:** `docs-impact.md` § Documentation Changes — `docs/domains/income/overview.md`, `docs/domains/portfolio/all-accounts.md`.
|
||||
- **Verification:** сопоставление двух страниц с согласованными ответами income API, UI и проверка ссылок/Markdown средствами docs repo.
|
||||
- **Depends on:** 1.2, 1.3
|
||||
|
||||
- [x] 3.2 [docs] Зафиксировать одинаковую карточку исполненной выплаты, прогнозного события и графика с разными финансовыми смыслами на существующих тематических страницах.
|
||||
- **Covers:** `brokerage-account-income-analytics` — `Income payments remain traceable to exact Ledger Entries`; `brokerage-account-ledger` — `Full ledger presents compact rows`; `brokerage-account-ledger` — `Account overview includes recent ledger events`; `brokerage-account-upcoming-events` — `Account page presents an upcoming events list`; `brokerage-account-upcoming-events` — `Account overview includes upcoming events`; `instrument-income-schedules` — `Instrument payout schedules do not imply executed income`.
|
||||
- **Source:** `docs-impact.md` § Documentation Changes — `docs/domains/operations/overview.md`, `docs/domains/income/upcoming-events.md`, `docs/domains/instruments/stocks.md`, `docs/domains/instruments/bonds.md`.
|
||||
- **Verification:** сверить текст четырёх страниц с экранами и публичными исходными данными, проверить ссылки/Markdown средствами docs repo.
|
||||
- **Depends on:** 2.2, 2.3, 2.4
|
||||
|
||||
- [x] 3.3 [docs] Обновить описание HTTP income analytics без дублирования машинной схемы.
|
||||
- **Covers:** `brokerage-account-income-analytics` — `Period comparisons preserve calendar and currency meaning` (удаление).
|
||||
- **Source:** `docs-impact.md` § Documentation Changes — `docs/architecture/http-api.md`; `system-analysis/analysis.md` § Contracts.
|
||||
- **Verification:** сопоставить текст с опубликованным backend OpenAPI обоих маршрутов и target schema, проверить ссылки/Markdown средствами docs repo.
|
||||
- **Depends on:** 1.2
|
||||
Reference in New Issue
Block a user