Files
docs/features/brokerage-account-income-analytics.md
T

57 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Пассивный доход брокерского счёта
Авторизованный User открывает `/accounts/:accountId/income` из обзора выбранного Brokerage Account. Экран показывает исполненные купоны и дивиденды за применённый календарный период, а известный прогноз ближайших событий оставляет отдельным блоком.
## API
`GET /api/v1/brokerage-accounts/:accountId/income-summary` возвращает текущий месяц по сегодняшнюю дату для компактного блока обзора. Он не зависит от периода, который User ранее выбрал на странице аналитики.
`GET /api/v1/brokerage-accounts/:accountId/income-analytics?from=YYYY-MM-DD&to=YYYY-MM-DD` возвращает полный результат. Даты задают включительный период в `Europe/Moscow`; без них применяется текущий месяц. Период не может быть будущим, обратным или длиннее 366 дней.
Оба endpoint требуют Bearer token и используют обычные ответы о неподключённом T-Bank, неверном token, недоступном счёте и временной недоступности upstream.
## Реализованный поток
- Backend проверяет доступ к счёту, проходит все cursor pages исполненных операций и не возвращает частичный результат при ошибке страницы или повреждённой cursor chain.
- Только точные upstream types coupon и dividend формируют результат. Суммы остаются exact decimal strings в исходной валюте; отрицательные корректировки сохраняют знак. Налоги, комиссии, сделки, переводы, погашения и dividend transfer не входят в доход.
- Итоги, сравнения, buckets и Instrument breakdown не смешивают валюты и не создают общий FX total. Сравнения показывают предыдущий период и, когда календарная дата и история счёта позволяют, период годом ранее.
- Trend buckets приходят с backend: дни для 1–45 дней, недели для 46–180 и месяцы для более длинного периода. Пустые buckets остаются в response и текстовом представлении.
- Breakdown раскрывает включённые Ledger Entries из того же ответа, поэтому отображённые строки не требуют отдельного запроса и воспроизводят сумму Instrument и валюты.
## Связь breakdown с выплатами
Каждая запись `income-analytics.entries` содержит обязательный `instrumentKey`,
равный `key` соответствующей строки `instruments`. Backend вычисляет этот ключ
один раз при подготовке income entries и использует его же для группировки.
Приоритет UID, FIGI, ticker/type и operation ID с разделением по валюте остаётся
серверным правилом; клиент воспринимает ключ как непрозрачную строку.
Общий Ledger endpoint не приобретает income-specific поле.
Income VM группирует entries по полученному ключу. Отсутствующий, пустой или
нестроковый ключ, неоднозначные instrument keys, неизвестная группа, другая
валюта или несовпадение receipt count приводят к существующему локальному
error/retry состоянию аналитики. Частичный drill-down не показывается как
полный; формула идентификации в клиенте не восстанавливается. Полностью пустой
ответ допустим. Состав и порядок выплат, signed Money и сортировка breakdown
сохраняются, frontend не пересчитывает денежные итоги.
## Совместимость и локальное обновление
Сначала обновляется backend: дополнительное поле совместимо с прежним
frontend. Затем синхронизируются OpenAPI snapshot/generated types и обновляется
frontend consumer. При переключении клиент перезагружается, чтобы не переносить
старые in-memory results и незавершённые запросы. Новый frontend требует новый
backend; отсутствие membership не скрывается fallback на прежнюю формулу.
При регрессии сначала возвращается прежний frontend вместе с соответствующим
snapshot/types и перезагружается клиент; затем при необходимости возвращается
backend. Старый frontend может временно работать с новым additive response.
SQLite schema, credentials и broker-reported операции не меняются: rollback
не удаляет данные, производные результаты запрашиваются заново.
## Прогноз и ограничения
Блок прогноза переиспользует `/events`: его `incomeTotalsByCurrency` содержит только coupon/dividend с известной projected amount, а на UI отображаются не более трёх ближайших таких событий. Maturity, offer и неизвестные суммы не искажают totals. Прогноз не гарантирован, не входит в фактические итоги и не зависит от выбранного исторического периода; его loading/error/empty outcome локален для блока.
Аналитика read-only, не хранит историю операций и не рассчитывает налоги, инвестиционную эффективность, доходность, валютную конвертацию или общий мультивалютный итог.