Files
specs/openspec/changes/persist-tbank-data/specs/brokerage-account-income-analytics/spec.md
T
ksv741 2f5814abdd
Conventional commits / commits (pull_request) Successful in 12s
Specs security / security (pull_request) Successful in 7s
Specs verify / verify (pull_request) Successful in 11s
Specs security / security (push) Successful in 7s
Specs verify / verify (push) Successful in 9s
spec: complete persist-tbank-data implementation
Record the approved proposal, delta specifications, design and 27 verified
implementation tasks. Keep the change active; archiving and main-spec synchronization
are deferred.
2026-09-26 21:29:24 +03:00

21 KiB
Raw Blame History

MODIFIED Requirements

Requirement: Realized income analytics is account-scoped and period-bound

Система MUST предоставлять аутентифицированному User аналитику фактически полученного дохода выбранного открытого поддерживаемого Brokerage Account либо существующего режима «Все счета» (all) из счетов, доступных через текущий T-Bank connection User. В режиме all система MUST проверять доступ каждого входящего счёта и подтверждать полноту каждого исходного периода по всем входящим счетам; отсутствующий вклад счёта MUST NOT заменяться нулём. Применённый период MUST задаваться включительными календарными датами from и to в Europe/Moscow, MUST NOT начинаться после своего окончания, MUST NOT содержать будущую дату. Система MUST NOT ограничивать максимальную длительность периода. При отсутствии применённого периода система MUST использовать интервал от первого дня текущего месяца до сегодняшнего дня включительно.

Чтение MUST использовать сохранённые операции текущего подключения и локальное подтверждение доступа без синхронного запроса T-Bank. Ответ MUST иметь envelope { data, meta } по tbank-data-sync. Полнота MUST определяться для выбранного периода и каждого необходимого периода сравнения отдельно. Запрос MUST приоритетно загружать их пропуски до фоновой догрузки остальной истории; известные правила календарных дат MUST сохраняться.

Scenario: Аналитика за период по умолчанию

  • WHEN аутентифицированный User запрашивает аналитику доступного Brokerage Account без периода
  • THEN система рассчитывает результат от первого дня текущего месяца по Europe/Moscow до сегодняшнего дня включительно

Scenario: Аналитика за допустимый пользовательский период

  • WHEN User применяет включительный период любой длительности, в том числе более 366 дней, без будущих дат
  • THEN система рассчитывает аналитику доступного Brokerage Account за все календарные даты этого периода по Europe/Moscow

Scenario: Отклонение недопустимого периода

  • WHEN User запрашивает период с некорректной или будущей датой либо с from после to
  • THEN система отклоняет запрос и не возвращает результат для другого или усечённого периода

Scenario: Отклонение недоступного счёта

  • WHEN User запрашивает аналитику Brokerage Account, который не является открытым поддерживаемым счётом, доступным через его текущий T-Bank connection
  • THEN система возвращает существующий ответ о недоступности счёта и не раскрывает его доход или операции

Scenario: Общий доход требует полноты всех счетов

  • WHEN User запрашивает режим all и выбранный период одного доступного счёта ещё не загружен полностью
  • THEN система не возвращает окончательные общие суммы, сохраняет раздельное состояние покрытия счетов и запрашивает недостающую разрешённую историю

Scenario: Открыт ещё не загруженный период

  • WHEN запрошенный допустимый период ещё не имеет сохранённых операций или подтверждённого полного пустого покрытия
  • THEN система отвечает 200 со статусом первичной загрузки или частичного покрытия, запрашивает нужные интервалы и не выдаёт нулевой окончательный доход

Requirement: Period comparisons preserve calendar and currency meaning

Система MUST сопоставлять выбранный период с непосредственно предшествующим периодом. Для полного календарного месяца предыдущим периодом MUST быть предыдущий полный календарный месяц; для любого другого периода предыдущий период MUST иметь ту же включительную продолжительность и непосредственно предшествовать выбранному. Когда соответствующие календарные даты годом ранее доступны, система MUST также показывать year-over-year comparison; когда они недоступны, система MUST обозначать сравнение как недоступное, а не подменять его нулём. Только сравнение с подтверждённым полным покрытием обоих периодов MUST показывать абсолютные coupon, dividend и total значения и их денежные разницы отдельно по исходным валютам и MUST NOT характеризовать их как инвестиционную эффективность.

Отсутствие ещё не загруженной истории сравнения MUST отличаться от невозможности сравнения по календарю или доступной истории счёта. Система MUST сообщать загрузку, неполноту либо ошибку каждого периода сравнения и MUST NOT подменять их нулевыми суммами или денежными разницами. Полный основной период MAY отображаться при отдельно обозначенной незавершённой загрузке сравнения; его значения MUST NOT смешиваться с частичным сравнением.

Scenario: Сравнение полного календарного месяца

  • WHEN User применяет период от первого до последнего дня календарного месяца
  • THEN система сравнивает его с полным непосредственно предшествующим календарным месяцем

Scenario: Сравнение произвольного периода

  • WHEN User применяет период, не являющийся полным календарным месяцем
  • THEN система сравнивает его с непосредственно предшествующим включительным периодом той же продолжительности

Scenario: Доступно сравнение год к году

  • WHEN для соответствующих календарных дат годом ранее доступна полная история подходящих операций
  • THEN система показывает отдельные source-currency значения и денежные разницы относительно этого периода

Scenario: Годовая история недоступна

  • WHEN полная история для соответствующих календарных дат годом ранее недоступна
  • THEN система обозначает year-over-year comparison как недоступное и не показывает отсутствующие данные как нулевой доход

Scenario: Основной период полон, сравнение ещё загружается

  • WHEN выбранный период имеет подтверждённое полное покрытие, а необходимый предыдущий период ещё загружается
  • THEN система возвращает полный итог выбранного периода, отмечает загрузку сравнения и не возвращает для него окончательные суммы или разницы

Scenario: Сравнение догружено после основного периода

  • WHEN все необходимые интервалы периода сравнения успешно завершены
  • THEN следующее локальное чтение возвращает его точные валютные суммы и разницы без ожидания T-Bank

Requirement: Realized analytics never presents an incomplete result as complete

Система MUST формировать окончательные totals, trend buckets, instrument breakdown и drill-down выбранного периода только по подтверждённому полному покрытию его исполненных операций. Каждое comparison MUST отдельно требовать полного покрытия своих исходных периодов. Повторное локальное чтение полного периода MUST NOT ожидать повторного получения cursor pages T-Bank. Ошибка любой необходимой страницы фоновой загрузки MUST сохранять подтверждённый ранее результат и покрытие, фиксировать восстанавливаемую ошибку синхронизации и MUST NOT возвращать частичные totals, comparisons, buckets или breakdown как полный результат. Если полный выбранный результат ещё не получен, envelope MUST возвращать data: null с отсутствующим либо частичным покрытием в meta, а интерфейс MUST показывать незавершённую загрузку либо её ошибку без окончательных финансовых итогов. Успешный период без подходящих выплат MUST возвращать нулевой результат и отображаться с явным объяснением пустого состояния.

Scenario: Все страницы операций успешно получены

  • WHEN для покрытия расчёта требуется несколько cursor pages и каждая страница успешно сохранена с подтверждением окончания диапазона
  • THEN система формирует результат по всем подходящим Ledger Entries со всех страниц

Scenario: Одна из страниц операций недоступна

  • WHEN получение любой необходимой cursor page завершается ошибкой
  • THEN ответ сообщает ошибку синхронизации, а страница сохраняет ранее полный результат с прежним временем либо показывает ошибку незавершённой загрузки без окончательных частичных итогов

Scenario: В периоде нет купонов и дивидендов

  • WHEN все необходимые операции успешно получены, но среди них нет подходящих coupon или dividend Ledger Entries
  • THEN страница показывает нулевой результат и объясняет, что за выбранный период купоны и дивиденды не найдены

Scenario: Частичная загрузка пока не нашла дохода

  • WHEN только часть операций выбранного периода получена и в этой части нет купонов или дивидендов
  • THEN система не возвращает окончательный нулевой результат и сообщает неполноту периода

Scenario: Ошибка ручной сверки полного периода

  • WHEN ранее полный период перечитывается вручную и промежуточная страница не получена
  • 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 или другие блоки обзора.

Summary MUST использовать тот же локальный источник операций и правило полноты, что и полная аналитика. До завершения требуемого текущего периода он MUST показывать состояние загрузки или неполноты без окончательного нулевого дохода. Ошибка фонового обновления MUST сохранять ранее полный summary с прежним временем и безопасным предупреждением.

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 показывает собственное состояние восстановления

Scenario: Текущий месяц ещё не загружен полностью

  • WHEN обзор доступен, но текущий месяц операций имеет пропуски
  • THEN блок дохода обозначает неполноту или загрузку, не выдаёт частичный доход за окончательный и не скрывает Portfolio

Requirement: Income payments remain traceable to exact Ledger Entries

В разделе «Выплаты» страница MUST показывать единый список карточек точных исполненных Ledger Entries применённого периода в исходном серверном порядке entries. Каждая выплата MUST иметь собственную сразу видимую карточку с описанием, датой, доступной identity Instrument и signed Money в исходной валюте. Страница MUST NOT добавлять внешние группировочные карточки или заголовки по Instrument либо валюте, subtotals инструмента или количество выплат инструмента. Список MUST сохранять отрицательные корректировки как самостоятельные Ledger Entries и MUST отражать одну запись на идентичность User, Brokerage Account, текущее подключение и operation ID; повторная загрузка того же ID MUST обновлять поля и MUST NOT удваивать выплату. Одинаковые operation IDs разных счетов MUST оставаться отдельными записями. Список MUST NOT включать записи вне аналитического итога. Отказ от группировочного UI MUST NOT отменять проверки принадлежности entries к instrumentKey, валюты и receipt count ответа или приводить к пересчёту денежных итогов на клиенте.

Scenario: Каждая выплата показана отдельной карточкой

  • WHEN выбранный период содержит несколько включённых Ledger Entries одного или разных Instrument
  • THEN раздел «Выплаты» сразу показывает отдельную карточку каждой записи в исходном порядке без внешних группировочных блоков, раскрытия, итогов инструмента и receipt count на UI

Scenario: Список воспроизводит точный состав дохода

  • WHEN User просматривает загруженный раздел «Выплаты»
  • THEN он видит все и только включённые coupon и dividend Ledger Entries применённого периода с датой, описанием, доступной identity и исходной суммой

Scenario: Отрицательная корректировка и повторяющиеся IDs сохраняются

  • WHEN доход содержит отрицательную корректировку, повторно загруженный ID того же счёта либо одинаковые operation IDs разных счетов
  • THEN корректировка отображается с исходным знаком; одна операция того же счёта имеет одну карточку с актуальными полями, а операции разных счетов остаются отдельными карточками

Scenario: Валюта видна в сумме каждой выплаты

  • WHEN подходящие выплаты одного Instrument представлены в нескольких исходных валютах
  • THEN каждая карточка показывает свою Money с исходной валютой, без отдельного заголовка валютной группы или объединённого мультивалютного итога