docs(specs): archive income analytics change
This commit is contained in:
@@ -0,0 +1,207 @@
|
||||
# brokerage-account-income-analytics Specification
|
||||
|
||||
## Purpose
|
||||
Позволяет User анализировать фактически полученные купоны и дивиденды одного Brokerage Account по исходным валютам, проверять состав результата и отдельно видеть известный ближайший прогноз.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Realized income analytics is account-scoped and period-bound
|
||||
|
||||
Система MUST предоставлять аутентифицированному User аналитику фактически полученного дохода только для одного открытого поддерживаемого Brokerage Account, доступного через текущий T-Bank connection User. Применённый период MUST задаваться включительными календарными датами `from` и `to` в Europe/Moscow, MUST NOT начинаться после своего окончания, MUST NOT содержать будущую дату и MUST NOT превышать 366 дней. При отсутствии применённого периода система MUST использовать интервал от первого дня текущего месяца до сегодняшнего дня включительно.
|
||||
|
||||
#### Scenario: Аналитика за период по умолчанию
|
||||
|
||||
- **WHEN** аутентифицированный User запрашивает аналитику доступного Brokerage Account без периода
|
||||
- **THEN** система рассчитывает результат от первого дня текущего месяца по Europe/Moscow до сегодняшнего дня включительно
|
||||
|
||||
#### Scenario: Аналитика за допустимый пользовательский период
|
||||
|
||||
- **WHEN** User применяет включительный период не более 366 дней без будущих дат
|
||||
- **THEN** система рассчитывает аналитику доступного Brokerage Account за все календарные даты этого периода по Europe/Moscow
|
||||
|
||||
#### Scenario: Отклонение недопустимого периода
|
||||
|
||||
- **WHEN** User запрашивает период длиннее 366 дней, с будущей датой либо с `from` после `to`
|
||||
- **THEN** система отклоняет запрос и не возвращает результат для другого или усечённого периода
|
||||
|
||||
#### Scenario: Отклонение недоступного счёта
|
||||
|
||||
- **WHEN** User запрашивает аналитику Brokerage Account, который не является открытым поддерживаемым счётом, доступным через его текущий T-Bank connection
|
||||
- **THEN** система возвращает существующий ответ о недоступности счёта и не раскрывает его доход или операции
|
||||
|
||||
### Requirement: Realized income uses exact executed coupon and dividend payments
|
||||
|
||||
Система MUST рассчитывать фактически полученный доход только по исполненным Ledger Entries с точным upstream-типом coupon или dividend. Для каждой исходной валюты система MUST отдельно возвращать общий итог, купонный subtotal и дивидендный subtotal как точные суммы исходных broker-reported payments. Знак каждой выплаты MUST сохраняться, поэтому отрицательная корректировка MUST уменьшать соответствующий итог и оставаться доступной в составе результата. Dividend transfer, погашение principal, offer, trade, transfer, fee, tax, overnight income, иной тип операции, нереализованный результат и изменение рыночной цены MUST NOT входить в фактически полученный доход. Система MUST NOT выполнять валютную конвертацию или формировать общий итог по разным валютам.
|
||||
|
||||
#### Scenario: Купоны и дивиденды образуют раздельные subtotals
|
||||
|
||||
- **WHEN** выбранный период содержит исполненные купонные и дивидендные выплаты в одной валюте
|
||||
- **THEN** система возвращает их точные раздельные subtotals и общий итог, равный их сумме в этой валюте
|
||||
|
||||
#### Scenario: Отрицательная корректировка сохраняет знак
|
||||
|
||||
- **WHEN** исполненная coupon или dividend Ledger Entry содержит отрицательную broker-reported payment
|
||||
- **THEN** система включает её с исходным знаком, уменьшает соответствующие subtotal и total и сохраняет запись доступной для проверки
|
||||
|
||||
#### Scenario: Налоги и иные операции не входят в доход
|
||||
|
||||
- **WHEN** выбранный период наряду с coupon и dividend содержит tax, fee, trade, transfer, maturity или иной тип Ledger Entry
|
||||
- **THEN** система не включает эти записи в coupon subtotal, dividend subtotal или total
|
||||
|
||||
#### Scenario: Несколько валют остаются разделёнными
|
||||
|
||||
- **WHEN** выбранный период содержит подходящие выплаты в нескольких исходных валютах
|
||||
- **THEN** система возвращает отдельные итоги по каждой валюте без сконвертированного grand total
|
||||
|
||||
### Requirement: Period comparisons preserve calendar and currency meaning
|
||||
|
||||
Система MUST сопоставлять выбранный период с непосредственно предшествующим периодом. Для полного календарного месяца предыдущим периодом MUST быть предыдущий полный календарный месяц; для любого другого периода предыдущий период MUST иметь ту же включительную продолжительность и непосредственно предшествовать выбранному. Когда соответствующие календарные даты годом ранее доступны, система MUST также показывать year-over-year comparison; когда они недоступны, система MUST обозначать сравнение как недоступное, а не подменять его нулём. Каждое сравнение MUST показывать абсолютные coupon, dividend и total значения и их денежные разницы отдельно по исходным валютам и MUST NOT характеризовать их как инвестиционную эффективность.
|
||||
|
||||
#### Scenario: Сравнение полного календарного месяца
|
||||
|
||||
- **WHEN** User применяет период от первого до последнего дня календарного месяца
|
||||
- **THEN** система сравнивает его с полным непосредственно предшествующим календарным месяцем
|
||||
|
||||
#### Scenario: Сравнение произвольного периода
|
||||
|
||||
- **WHEN** User применяет период, не являющийся полным календарным месяцем
|
||||
- **THEN** система сравнивает его с непосредственно предшествующим включительным периодом той же продолжительности
|
||||
|
||||
#### Scenario: Доступно сравнение год к году
|
||||
|
||||
- **WHEN** для соответствующих календарных дат годом ранее доступна полная история подходящих операций
|
||||
- **THEN** система показывает отдельные source-currency значения и денежные разницы относительно этого периода
|
||||
|
||||
#### Scenario: Годовая история недоступна
|
||||
|
||||
- **WHEN** полная история для соответствующих календарных дат годом ранее недоступна
|
||||
- **THEN** система обозначает year-over-year comparison как недоступное и не показывает отсутствующие данные как нулевой доход
|
||||
|
||||
### Requirement: User explicitly applies an analytics period represented in the URL
|
||||
|
||||
Страница выбранного Brokerage Account «Пассивный доход» MUST позволять User редактировать черновик `from` и `to`, не изменяя видимую аналитику до явного применения. Явное применение MUST заменить применённый период, загрузить соответствующий результат и представить применённые даты в URL страницы. Сброс MUST немедленно вернуть применённый период к текущему месяцу по сегодняшний день и синхронизировать URL. Перезагрузка или открытие URL с допустимым периодом MUST восстановить тот же применённый период. Действие перехода на страницу MUST быть доступно из выбранного Brokerage Account, а не из глобальной навигации.
|
||||
|
||||
#### Scenario: Черновик периода не применён
|
||||
|
||||
- **WHEN** User изменяет черновик `from` или `to`, но не применяет его
|
||||
- **THEN** видимые итоги, сравнения, динамика и breakdown остаются основанными на последнем применённом периоде
|
||||
|
||||
#### Scenario: Применение периода
|
||||
|
||||
- **WHEN** User явно применяет допустимый черновик периода
|
||||
- **THEN** страница загружает аналитику этого периода и отражает применённые `from` и `to` в URL
|
||||
|
||||
#### Scenario: Восстановление применённого периода из URL
|
||||
|
||||
- **WHEN** User открывает URL страницы с допустимыми `from` и `to`
|
||||
- **THEN** страница показывает аналитику за указанный применённый период
|
||||
|
||||
#### Scenario: Сброс периода
|
||||
|
||||
- **WHEN** User сбрасывает пользовательский период
|
||||
- **THEN** страница немедленно применяет период от первого дня текущего месяца по Europe/Moscow до сегодняшнего дня и синхронизирует URL
|
||||
|
||||
### Requirement: Analytics summary and trend remain readable per currency
|
||||
|
||||
Страница MUST обозначать фактический результат как «Получено купонами и дивидендами» и для каждой исходной валюты показывать total, coupon subtotal и dividend subtotal выбранного периода. Она MUST объяснять, что tax operations не включены, не называя фактический результат gross, net, суммой до налогов, суммой после налогов или налоговым расчётом. Страница MUST показывать stacked column visualization с отдельными coupon и dividend значениями: период до 45 дней включительно группируется по календарным дням, период от 46 до 180 дней включительно — по календарным неделям, более длинный период — по календарным месяцам. Пустые buckets внутри периода MUST оставаться видимыми с нулевыми значениями. При нескольких валютах явный currency control MUST переключать visualization между ними, а эквивалентные значения MUST оставаться доступными как читаемый текст, не только как графика, цвет или положение.
|
||||
|
||||
#### Scenario: Короткий период группируется по дням
|
||||
|
||||
- **WHEN** включительная продолжительность выбранного периода не превышает 45 дней
|
||||
- **THEN** visualization показывает отдельные календарные day buckets с coupon и dividend значениями и сохраняет пустые дни как нулевые buckets
|
||||
|
||||
#### Scenario: Средний период группируется по неделям
|
||||
|
||||
- **WHEN** включительная продолжительность выбранного периода составляет от 46 до 180 дней
|
||||
- **THEN** visualization показывает calendar week buckets с раздельными coupon и dividend значениями
|
||||
|
||||
#### Scenario: Длинный период группируется по месяцам
|
||||
|
||||
- **WHEN** включительная продолжительность выбранного периода превышает 180 дней
|
||||
- **THEN** visualization показывает calendar month buckets с раздельными coupon и dividend значениями
|
||||
|
||||
#### Scenario: User переключает валюту visualization
|
||||
|
||||
- **WHEN** результат содержит подходящие выплаты в нескольких валютах и User выбирает одну из них
|
||||
- **THEN** visualization и его текстовый эквивалент показывают значения только выбранной исходной валюты без изменения итогов остальных валют
|
||||
|
||||
### Requirement: Instrument breakdown is traceable to exact Ledger Entries
|
||||
|
||||
Для каждой исходной валюты страница MUST показывать instrument breakdown, отсортированный по combined total по убыванию. Каждая строка MUST содержать доступную identity Instrument, coupon subtotal, dividend subtotal, combined total и количество включённых выплат. User MUST иметь возможность перейти от строки к точным исполненным Ledger Entries выбранных Instrument, валюты и периода, которые образовали её значения; drill-down MUST сохранять отрицательные корректировки и MUST NOT включать записи вне аналитического итога.
|
||||
|
||||
#### Scenario: Breakdown показывает состав дохода по инструментам
|
||||
|
||||
- **WHEN** выбранный период содержит подходящие выплаты нескольких Instrument в одной валюте
|
||||
- **THEN** страница показывает строки по убыванию combined total с identity, двумя subtotals, combined total и receipt count каждого Instrument
|
||||
|
||||
#### Scenario: Drill-down воспроизводит строку breakdown
|
||||
|
||||
- **WHEN** User открывает drill-down строки Instrument
|
||||
- **THEN** он видит точные coupon и dividend Ledger Entries этого Instrument, периода и валюты, сумма и количество которых соответствуют строке
|
||||
|
||||
### Requirement: Realized analytics never presents an incomplete result as complete
|
||||
|
||||
Система MUST формировать выбранный результат, его comparisons, trend buckets, instrument breakdown и drill-down только после успешного получения всех необходимых cursor pages исполненных операций. Ошибка любой необходимой страницы MUST завершать расчёт восстанавливаемой ошибкой и MUST NOT возвращать частичные totals, comparisons, buckets или breakdown как полный результат. Успешный период без подходящих выплат MUST возвращать нулевой результат и отображаться с явным объяснением пустого состояния.
|
||||
|
||||
#### Scenario: Все страницы операций успешно получены
|
||||
|
||||
- **WHEN** для расчёта требуется несколько cursor pages и каждая страница успешно получена
|
||||
- **THEN** система формирует результат по всем подходящим Ledger Entries со всех страниц
|
||||
|
||||
#### Scenario: Одна из страниц операций недоступна
|
||||
|
||||
- **WHEN** получение любой необходимой cursor page завершается ошибкой
|
||||
- **THEN** страница показывает восстанавливаемую ошибку и не показывает частичный результат как полный
|
||||
|
||||
#### Scenario: В периоде нет купонов и дивидендов
|
||||
|
||||
- **WHEN** все необходимые операции успешно получены, но среди них нет подходящих coupon или dividend Ledger Entries
|
||||
- **THEN** страница показывает нулевой результат и объясняет, что за выбранный период купоны и дивиденды не найдены
|
||||
|
||||
### Requirement: Account overview has an independent current-month income summary
|
||||
|
||||
Обзор выбранного Brokerage Account MUST показывать компактный source-currency summary «Получено купонами и дивидендами» за период от первого дня текущего месяца по Europe/Moscow до сегодняшнего дня включительно и действие перехода на страницу «Пассивный доход». Summary MUST всегда использовать этот current-month период и MUST NOT наследовать последний пользовательский период страницы аналитики. Пустой или неуспешный расчёт summary MUST оставаться локальным состоянием блока и MUST NOT заменять успешно отображённый Portfolio или другие блоки обзора.
|
||||
|
||||
#### Scenario: Обзор показывает доход текущего месяца
|
||||
|
||||
- **WHEN** обзор Brokerage Account загружен и current-month analytics успешно рассчитана
|
||||
- **THEN** он показывает отдельные source-currency итоги с начала текущего месяца по сегодняшний день и переход к полной аналитике
|
||||
|
||||
#### Scenario: Пользовательский период не влияет на обзор
|
||||
|
||||
- **WHEN** User ранее применил на странице аналитики период, отличный от текущего месяца
|
||||
- **THEN** summary обзора по-прежнему рассчитывается от первого дня текущего месяца по сегодняшний день
|
||||
|
||||
#### Scenario: Current-month summary недоступен
|
||||
|
||||
- **WHEN** Portfolio обзора успешно загружен, но расчёт current-month summary завершается ошибкой
|
||||
- **THEN** Portfolio и остальные успешно загруженные блоки остаются доступными, а summary показывает собственное состояние восстановления
|
||||
|
||||
### Requirement: Forecast is separate from realized income
|
||||
|
||||
Страница «Пассивный доход» MUST показывать семантически и визуально отдельный forecast block известных coupon и dividend Future Cash Events на следующие 30 дней от сегодняшней даты независимо от выбранного исторического периода. Forecast totals MUST включать только события coupon и dividend с известной projected amount и MUST оставаться разделёнными по исходным валютам; maturity и offer MUST NOT входить в эти totals. Блок MUST показывать три ближайших подходящих события, обозначать результат как не гарантированный прогноз и предоставлять переход к существующей полной странице «Будущие события». Forecast values MUST NOT входить в realized total, comparisons, trend или instrument breakdown. Ошибка forecast MUST оставаться локальной для блока и MUST NOT скрывать успешно загруженную realized analytics.
|
||||
|
||||
#### Scenario: Forecast показывает ближайшие известные выплаты
|
||||
|
||||
- **WHEN** на следующие 30 дней известны coupon или dividend Future Cash Events
|
||||
- **THEN** блок показывает не более трёх ближайших подходящих событий, source-currency totals известных projected amounts, предупреждение о неопределённости и переход к полному списку будущих событий
|
||||
|
||||
#### Scenario: События без суммы не искажают forecast total
|
||||
|
||||
- **WHEN** подходящее coupon или dividend Future Cash Event не имеет известной projected amount
|
||||
- **THEN** событие не добавляет нулевую или вымышленную сумму в forecast total
|
||||
|
||||
#### Scenario: Maturity и offer не входят в forecast income
|
||||
|
||||
- **WHEN** ближайшие Future Cash Events содержат maturity или offer
|
||||
- **THEN** forecast block не включает их в coupon или dividend totals
|
||||
|
||||
#### Scenario: Пользовательский исторический период не влияет на forecast
|
||||
|
||||
- **WHEN** User применяет любой допустимый исторический период
|
||||
- **THEN** forecast block по-прежнему охватывает следующие 30 дней от сегодняшней даты
|
||||
|
||||
#### Scenario: Forecast недоступен при успешной realized analytics
|
||||
|
||||
- **WHEN** realized analytics успешно загружена, а запрос forecast завершается ошибкой
|
||||
- **THEN** realized totals, comparisons, trend и breakdown остаются доступными, а forecast block показывает собственную ошибку
|
||||
Reference in New Issue
Block a user