From 7166ee51d181b04f3892ff6757a56b578ee9df64 Mon Sep 17 00:00:00 2001 From: Sergey Krylov Date: Wed, 9 Sep 2026 13:50:45 +0300 Subject: [PATCH] docs: describe simplified income page --- .../brokerage-account-income-analytics.md | 58 +++++++++++++++---- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/features/brokerage-account-income-analytics.md b/features/brokerage-account-income-analytics.md index 3fc32df..040495e 100644 --- a/features/brokerage-account-income-analytics.md +++ b/features/brokerage-account-income-analytics.md @@ -1,6 +1,6 @@ # Пассивный доход брокерского счёта -Авторизованный User открывает `/accounts/:accountId/income` из обзора выбранного Brokerage Account. Экран показывает исполненные купоны и дивиденды за применённый календарный период, а известный прогноз ближайших событий оставляет отдельным блоком. +Авторизованный User открывает `/accounts/:accountId/income` из обзора выбранного Brokerage Account. Экран показывает исполненные купоны и дивиденды за применённый календарный период: текстовые итоги по валютам, сравнения и раздел «Выплаты» с отдельной карточкой каждой включённой выплаты. ## API @@ -10,13 +10,40 @@ Оба endpoint требуют Bearer token и используют обычные ответы о неподключённом T-Bank, неверном token, недоступном счёте и временной недоступности upstream. +## Выбор периода и состояния страницы + +В блоке «Период» два календарных поля Mantine DateInput показывают даты в формате +`ДД.ММ.ГГГГ`. Календарный выбор и ручной ввод изменяют только черновик. Кнопка +«Применить» или submit с клавиатуры проверяют видимый текст и передают допустимые +даты в URL как `from=YYYY-MM-DD&to=YYYY-MM-DD`. До применения результат сохраняется; отдельной +подписи периода под фильтрами нет. Открытие URL и навигация назад восстанавливают +применённый период. + +Пустая, несуществующая или будущая дата получает ошибку у своего поля; +обратный диапазон — у поля «По». Некорректный текст не заменяется последней +допустимой датой при потере фокуса, не меняет URL и не отправляет запрос. +Календарь учитывает допустимую соседнюю дату и сегодняшний день в Europe/Moscow. +«Сбросить» сразу применяет текущий московский месяц по сегодняшний день, +восстанавливает оба поля и очищает ошибки, даже если изменён только черновик. + +При первой загрузке или новом периоде без cached data показан structural +skeleton. Пустой результат объясняет отсутствие исполненных купонов и +дивидендов, сохраняя фильтры, налоговое пояснение и сравнения. Ошибка запроса +или повреждённый membership даёт локальное состояние с действием «Повторить». +При фоновом обновлении того же периода Client Cached Snapshot и черновик +остаются видимыми: загрузку обозначает progress, неуспешное обновление — +предупреждение с retry. + +На узком экране поля и действия идут вертикально; все карточки выплат +остаются в общем потоке страницы без раскрытия или внутренних scroll-панелей. + ## Реализованный поток - 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 и валюты. +- Buckets по-прежнему приходят с backend: дни для 1–45 дней, недели для 46–180 и месяцы для более длинного периода, включая пустые buckets. Страница дохода не строит из них график или текстовую динамику; API response не меняется. +- Раздел «Выплаты» показывает единый список LedgerEntryRow-карточек в исходном порядке `entries`: одна карточка на каждую выплату. Внешних групп по инструментам или валютам, итогов и количества выплат инструмента нет. Описание, дата, доступная identity и signed Money видны в каждой карточке; валюты по-прежнему разделены в summary/comparisons. Дополнительный запрос за составом не нужен. ## Связь breakdown с выплатами @@ -27,15 +54,18 @@ серверным правилом; клиент воспринимает ключ как непрозрачную строку. Общий Ledger endpoint не приобретает income-specific поле. -Income VM группирует entries по полученному ключу. Отсутствующий, пустой или +Income VM проверяет принадлежность entries по полученному ключу до подготовки +плоского списка выплат. Отсутствующий, пустой или нестроковый ключ, неоднозначные instrument keys, неизвестная группа, другая валюта или несовпадение receipt count приводят к существующему локальному -error/retry состоянию аналитики. Частичный drill-down не показывается как +error/retry состоянию аналитики. Частичный список выплат не показывается как полный; формула идентификации в клиенте не восстанавливается. Полностью пустой -ответ допустим. Состав и порядок выплат, signed Money и сортировка breakdown -сохраняются, frontend не пересчитывает денежные итоги. +ответ допустим. Состав и исходный серверный порядок entries и signed Money +сохраняются, frontend не пересчитывает денежные итоги. Повторяющиеся operation +IDs остаются отдельными строками; ключи учитывают instrumentKey, occurrence внутри группы и +logo source для корректного обновления image fallback. -## Совместимость и локальное обновление +## Совместимость membership и локальное обновление Сначала обновляется backend: дополнительное поле совместимо с прежним frontend. Затем синхронизируются OpenAPI snapshot/generated types и обновляется @@ -46,11 +76,17 @@ backend; отсутствие membership не скрывается fallback на При регрессии сначала возвращается прежний frontend вместе с соответствующим snapshot/types и перезагружается клиент; затем при необходимости возвращается backend. Старый frontend может временно работать с новым additive response. -SQLite schema, credentials и broker-reported операции не меняются: rollback +Календарные фильтры и отдельные карточки выплат используют тот же контракт и не требуют +дополнительного обновления backend. SQLite schema, credentials и broker-reported +операции не меняются: rollback не удаляет данные, производные результаты запрашиваются заново. -## Прогноз и ограничения +## Будущие события и ограничения -Блок прогноза переиспользует `/events`: его `incomeTotalsByCurrency` содержит только coupon/dividend с известной projected amount, а на UI отображаются не более трёх ближайших таких событий. Maturity, offer и неизвестные суммы не искажают totals. Прогноз не гарантирован, не входит в фактические итоги и не зависит от выбранного исторического периода; его loading/error/empty outcome локален для блока. +На странице дохода нет блоков «Динамика» и «Ближайший прогноз». Она не запрашивает +`/events` и не зависит от его доступности. Самостоятельная страница +[«Будущие события»](brokerage-account-upcoming-events.md) по-прежнему доступна из обзора +выбранного Brokerage Account и сохраняет прежнее поведение. Будущие выплаты +не включаются в realized totals или сравнения. Аналитика read-only, не хранит историю операций и не рассчитывает налоги, инвестиционную эффективность, доходность, валютную конвертацию или общий мультивалютный итог.