docs: document income without comparisons and unified payouts (WealthLedger/main#33)
102 lines
12 KiB
Markdown
102 lines
12 KiB
Markdown
# Пассивный доход брокерского счёта
|
|
|
|
Пассивный доход отвечает на вопрос «сколько брокер сообщил исполненными
|
|
купонами и дивидендами за выбранный период». Пользователь открывает
|
|
`/accounts/:accountId/income` из обзора счёта или
|
|
[общий доход](../portfolio/all-accounts.md) по доступным счетам.
|
|
Экран показывает итоги по валютам и отдельную карточку каждой
|
|
включённой выплаты. Источником служат [исполненные операции](../operations/overview.md),
|
|
а не изменение цены портфеля и не календарь будущих выплат.
|
|
|
|
Суммы сохраняют знак брокерского денежного движения. Налоговые операции
|
|
не включаются; результат не называется суммой до или после налогов,
|
|
инвестиционной эффективностью или налоговым расчётом.
|
|
|
|
## Период и данные
|
|
|
|
`GET /api/v1/brokerage-accounts/:accountId/income-summary` возвращает текущий месяц по сегодняшнюю дату для компактного блока обзора. Он не зависит от периода, который пользователь ранее выбрал на странице аналитики.
|
|
|
|
`GET /api/v1/brokerage-accounts/:accountId/income-analytics?from=YYYY-MM-DD&to=YYYY-MM-DD` возвращает полный результат. Даты задают включительный период в `Europe/Moscow`; без них применяется текущий месяц. Период не может быть будущим или обратным. Максимальная длительность периода не ограничена.
|
|
|
|
Оба запроса требуют Bearer token и используют обычные ответы о неподключённом T-Bank, отклонённом токене, недоступном счёте и временной недоступности источника.
|
|
|
|
## Выбор периода и состояния страницы
|
|
|
|
В блоке «Период» два календарных поля Mantine DateInput показывают даты в формате
|
|
`ДД.ММ.ГГГГ`. Календарный выбор и ручной ввод изменяют только черновик. Кнопка
|
|
«Применить» или отправка формы с клавиатуры проверяют видимый текст и передают допустимые
|
|
даты в URL как `from=YYYY-MM-DD&to=YYYY-MM-DD`. До применения результат сохраняется; отдельной
|
|
подписи периода под фильтрами нет. Открытие URL и навигация назад восстанавливают
|
|
применённый период.
|
|
|
|
Пустая, несуществующая или будущая дата получает ошибку у своего поля;
|
|
обратный диапазон — у поля «По». Некорректный текст не заменяется последней
|
|
допустимой датой при потере фокуса, не меняет URL и не отправляет запрос.
|
|
Календарь учитывает допустимую соседнюю дату и сегодняшний день в Europe/Moscow.
|
|
«Сбросить» сразу применяет текущий московский месяц по сегодняшний день,
|
|
восстанавливает оба поля и очищает ошибки, даже если изменён только черновик.
|
|
|
|
При первой загрузке или новом периоде без сохранённых данных показан
|
|
каркас страницы. Пустой результат объясняет отсутствие исполненных купонов и
|
|
дивидендов, сохраняя фильтры и налоговое пояснение. Ошибка запроса
|
|
или нарушение принадлежности выплат даёт локальное состояние с действием «Повторить».
|
|
При фоновом обновлении того же периода сохранённый ответ и черновик
|
|
остаются видимыми: загрузку обозначает индикатор, неуспешное обновление —
|
|
предупреждение с повторной попыткой.
|
|
|
|
На узком экране поля и действия идут вертикально; все карточки выплат
|
|
остаются в общем потоке страницы без раскрытия или внутренних областей прокрутки.
|
|
|
|
## Какие выплаты входят в результат
|
|
|
|
- Backend проверяет доступ локально и читает сохранённые операции. Фоновая загрузка должна завершить все страницы; ошибка страницы или повреждённая цепочка курсоров не подтверждают полноту.
|
|
- Только точные типы купона и дивиденда источника формируют результат. Суммы остаются точными десятичными строками в исходной валюте; отрицательные корректировки сохраняют знак. Налоги, комиссии, сделки, переводы, погашения и переводы дивидендов не входят в доход.
|
|
- Итоги, временные интервалы и разбиение по инструментам не смешивают валюты и не создают общий конвертированный итог. Система не загружает другие периоды ради сравнения полученного дохода с выбранным.
|
|
- Временные интервалы по-прежнему приходят с backend: дни для 1–45 дней, недели для 46–180 и месяцы для более длинного периода, включая пустые интервалы. Страница дохода не строит из них график или текстовую динамику; ответ API не меняется.
|
|
- Раздел «Выплаты» показывает единый список карточек выплат в исходном порядке `entries`: одна карточка на каждую выплату. Внешних групп по инструментам или валютам, итогов и количества выплат инструмента нет. Описание, дата, доступные идентификаторы инструмента и сумма со знаком видны в каждой карточке; валюты разделены в итогах. Дополнительный запрос за составом не нужен.
|
|
|
|
## Полнота и принадлежность выплат
|
|
|
|
Доходы читают сохранённые операции и coverage в согласованной транзакции.
|
|
Только выбранный период определяет готовность результата. Неполный период
|
|
не получает окончательных итогов.
|
|
Подтверждённый пустой период отличается от ещё не загруженного. При смене
|
|
периода прежний snapshot не показывается под новым названием.
|
|
|
|
Ручная сверка полного периода сохраняет весь прежний результат до успешной
|
|
атомарной публикации всех необходимых интервалов и счетов. История счёта
|
|
может ещё догружаться после готовности выбранного месяца.
|
|
|
|
Каждая запись `income-analytics.entries` содержит обязательный `instrumentKey`,
|
|
равный `key` соответствующей строки `instruments`. Backend вычисляет этот ключ
|
|
один раз при подготовке записей дохода и использует его же для группировки.
|
|
Приоритет UID, FIGI, ticker/type и ID операции с разделением по валюте остаётся
|
|
серверным правилом; клиент воспринимает ключ как непрозрачную строку.
|
|
Это поле принадлежит ответу аналитики; общий журнал операций его не требует.
|
|
|
|
Backend обеспечивает принадлежность выплат, валюту и receipt count при
|
|
построении entries и instrument groups из одного набора данных. Frontend
|
|
доверяет типизированному contract, не восстанавливает формулу идентификации
|
|
и не выполняет второй consistency validator. Полностью пустой ответ допустим.
|
|
Состав и исходный серверный порядок записей и знак сумм
|
|
сохраняются, frontend не пересчитывает денежные итоги. Стабильный ID в пределах подключения и счёта определяет одну операцию:
|
|
повторная сверка обновляет её без двойного учёта. Одинаковые ID разных счетов
|
|
остаются разными выплатами. Изменение источника логотипа позволяет заново
|
|
показать изображение после буквенной заглушки.
|
|
|
|
## Будущие события и ограничения
|
|
|
|
На странице дохода нет блоков «Динамика» и «Ближайший прогноз», блоков
|
|
сравнения периодов и сообщений об их недоступности. Она не запрашивает
|
|
`/events` и не зависит от его доступности. Самостоятельная страница
|
|
[«Будущие события»](upcoming-events.md) по-прежнему доступна из обзора
|
|
выбранного счёта и сохраняет прежнее поведение. Будущие выплаты
|
|
не включаются в итоги полученного дохода.
|
|
|
|
Аналитика читает сохранённую историю операций и не рассчитывает налоги, инвестиционную эффективность, доходность, валютную конвертацию или общий мультивалютный итог.
|
|
|
|
Основное проверяемое поведение — в [спецификации дохода](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/brokerage-account-income-analytics/spec.md),
|
|
точная форма ответа — в [HTTP API](../../architecture/http-api.md).
|
|
Не следует использовать календарь будущих событий для восстановления
|
|
состава уже полученного дохода.
|