Files
specs/openspec/specs/brokerage-account-ledger/spec.md
T
codex-bot f0478c6d6b
Specs security / security (push) Successful in 8s
Specs verify / verify (push) Successful in 10s
spec: archive quiet-user-feedback and sync canonical specs (#50)
Native archive применил 9 added и 12 modified требований без удалений; все 10 сценариев сохранены. Новый canonical spec frontend-user-feedback внесён в AI_INDEX.
2026-10-17 22:18:27 +03:00

23 KiB
Raw Blame History

Brokerage Account Ledger Specification

Purpose

Позволяет пользователю просматривать исполненные операции одного брокерского счёта, чтобы понимать фактические денежные и инструментальные движения.

Requirements

Requirement: User can retrieve an account ledger

Система MUST предоставлять аутентифицированный журнал только для чтения одного Brokerage Account, принадлежащего текущему User. Журнал MUST содержать только исполненные операции T-Bank и при отсутствии периода по умолчанию охватывать интервал от начала текущего календарного года до момента запроса.

Scenario: Получение журнала с периодом по умолчанию

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

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

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

Requirement: User can browse a filtered ledger

Система MUST позволять User ограничивать журнал включительным периодом дат и любым подмножеством категорий trade, income, tax, fee, transfer, other. Система MUST разбивать упорядоченный результат на страницы с непрозрачным cursor и возвращать признак доступности следующей страницы.

Scenario: Фильтрация доходных операций за период

  • WHEN User запрашивает период дат и категорию income
  • THEN результат содержит только исполненные доходные операции с датой в пределах этого периода

Scenario: Продолжение истории

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

Requirement: Ledger entries preserve broker operation meaning

Система MUST представлять одну upstream-операцию одной записью журнала и MUST передавать её timestamp, тип операции, категорию, описание, доступные идентификаторы инструмента, доступную presentation metadata инструмента, денежную выплату, количество, цену, НКД и комиссию. Денежные поля MUST сохранять исходную валюту и точное десятичное значение.

Scenario: Отображение купонной выплаты

  • WHEN T-Bank возвращает исполненную купонную операцию с выплатой и данными инструмента
  • THEN запись журнала определяет её как income и передаёт исходную сумму выплаты, валюту и данные инструмента

Scenario: Отображение комиссии сделки без синтетической записи

  • WHEN T-Bank возвращает исполненную сделку, содержащую выплату и комиссию
  • THEN журнал содержит одну запись сделки с комиссией в качестве её детали

Scenario: Отображение движения бумаг без денег

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

Scenario: Доступна визуальная идентичность инструмента

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

Requirement: Account overview includes recent ledger events

Обзор счёта MUST показывать пять последних исполненных записей журнала этого счёта и действие перехода к его полному журналу. Каждая запись MUST иметь ту же визуальную идентичность инструмента и семантику денежного движения, что и запись полного журнала. Неуспешный или пустой запрос MUST оставаться локальным состоянием блока и MUST NOT заменять успешно отображённый Portfolio. При временном сбое обновления блок MUST сохранять доступные записи без технического предупреждения или ручного повтора. При отсутствии результата он SHALL показывать первичное ожидание либо нейтральную недоступность, автоматически восстанавливая чтение. Неподтверждённая пустота MUST NOT представляться отсутствием операций.

Scenario: Отображение последних событий

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

Scenario: Последние записи недоступны

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

Scenario: Последняя запись не содержит visual metadata инструмента

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

Requirement: Full ledger presents compact rows

Страница полного журнала MUST показывать для каждой записи дату, тип операции, инструмент и денежное изменение в исходной валюте в компактной структурированной строке. При доступной presentation metadata инструмента строка MUST показывать его визуальную идентичность; при её отсутствии MUST использовать понятный текстовый fallback. Для купонных и дивидендных операций на странице полного журнала и в личной истории инструмента MUST использоваться то же представление выплаты, что в доходе, прогнозе и графиках инструментов, с обозначением исполненного движения. Для каждой записи денежное изменение в исходной валюте MUST сопровождаться подписью конкретного типа события и знаком: для купонной операции — «Купон», для дивидендной — «Дивиденд», для остальных записей — подпись их категории («Сделка», «Налог», «Комиссия», «Перевод», «Прочее»). Строка MUST NOT повторять подпись типа события во вторичной метадате записи. Знак «+» / «−» и семантический цвет MUST оставаться носителями направления и MUST NOT заменяться только текстом. Страница MUST обозначать записи без движения денег нейтрально и MUST NOT показывать цену или количество.

Scenario: Отображение записи только с инструментом

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

Scenario: Отображение поступления

  • WHEN полный журнал отображает запись с положительной денежной выплатой
  • THEN строка явно показывает поступление знаком и подписью конкретного типа события («Купон», «Дивиденд» или категории) и его денежное изменение в исходной валюте, не полагаясь только на цвет

Scenario: Отображение списания

  • WHEN полный журнал отображает запись с отрицательной денежной выплатой
  • THEN строка явно показывает списание знаком и подписью конкретного типа события («Купон», «Дивиденд» или категории) и его денежное изменение в исходной валюте, не полагаясь только на цвет

Scenario: Отображение купона

  • WHEN полный журнал или личная история инструмента отображает исполненную операцию с upstream-типом купона
  • THEN запись показывает подпись «Купон» и исполненную сумму в том же представлении выплаты, что на других экранах

Scenario: Отображение дивиденда

  • WHEN полный журнал или личная история инструмента отображает исполненную операцию с upstream-типом дивиденда
  • THEN запись показывает подпись «Дивиденд» и исполненную сумму в том же представлении выплаты, что на других экранах

Scenario: Подпись типа не дублируется

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

Scenario: Отсутствует visual metadata инструмента

  • WHEN полный журнал отображает запись без доступной presentation metadata инструмента
  • THEN строка показывает понятный текстовый fallback без подмены или сокрытия доступных данных инструмента

Requirement: Кэш страниц журнала ограничивает локальные ресурсы

Система SHALL кэшировать не более 100 недавно использованных страниц Account Ledger в каждом backend process не более чем на 30 секунд. Cache key MUST включать User, Brokerage Account, нормализованные период и categories, opaque cursor и limit; порядок или дублирование categories MUST NOT создавать отдельную cache identity, а отсутствующий конец периода MUST использовать текущий 30-секундный bucket. Просроченная страница MUST NOT возвращаться, а при переполнении cache MUST удалять наименее недавно использованную страницу.

Scenario: Равнозначные фильтры используют одну cache identity

  • WHEN User в одном 30-секундном bucket повторяет запрос страницы журнала с теми же периодом, cursor и limit, но с categories в другом порядке или с дубликатами
  • THEN система использует ту же cache identity и не запрашивает upstream повторно для свежей страницы

Scenario: Большое число уникальных запросов не увеличивает cache без границы

  • WHEN backend обслуживает больше 100 уникальных запросов страниц журнала
  • THEN cache содержит не более 100 страниц и освобождает наименее недавно использованные страницы

Scenario: Просроченная страница не возвращается

  • WHEN cached страница журнала старше 30 секунд
  • THEN система не возвращает её как свежий результат и получает актуальную страницу из upstream

Requirement: User can explicitly apply ledger filters

Система MUST позволять User формировать черновик периода и категорий на странице полного журнала и применять его явным действием. Пока черновик изменён, но не применён, видимый список записей и его курсорная пагинация MUST оставаться основанными на последнем применённом состоянии. Явное применение MUST коммитить черновик в применимое состояние и сбрасывать курсорную пагинацию на первую страницу. Сброс фильтров MUST очищать черновик, немедленно применять пустой фильтр (период по умолчанию и все категории) и сбрасывать пагинацию.

Scenario: Черновик изменён, но не применён

  • WHEN User изменил период или категории в контролах фильтров, но не нажал «Применить»
  • THEN видимый список записей остаётся основанным на последнем применённом фильтре, а новый запрос к серверу не выполняется

Scenario: Применение черновика

  • WHEN User нажал «Применить» на фильтре журнала с изменённым черновиком
  • THEN черновик коммитится в применимое состояние, курсорная пагинация сбрасывается на первую страницу и выполняется новый запрос с применённым периодом и категориями

Scenario: Сброс фильтров

  • WHEN User нажал «Сбросить» на фильтре журнала
  • THEN черновик очищается, немедленно применяется пустой фильтр (период по умолчанию и все категории) и курсорная пагинация сбрасывается на первую страницу

Scenario: Пагинация по применённому фильтру

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

Requirement: Отсутствующий исторический интервал загружается только впервые

Система MUST позволять авторизованному User при первом открытии ещё не загруженного периода операций доступного Brokerage Account начать получение только недостающего интервала без ожидания T-Bank в локальном ответе. Это является исключением первой загрузки и MUST NOT запускать обновление других личных данных. Полностью загруженный прошлый интервал MUST NOT повторно сверяться из-за чтения страницы или часового обхода. Изменяемый хвост операций MUST обновляться часовым обходом. Незавершённый интервал и ошибка загрузки MUST NOT обозначаться полными, а последний подтверждённый результат MUST оставаться доступным.

Scenario: Первый просмотр отсутствующего прошлого периода

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

Scenario: Повторное открытие полного периода

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

Scenario: Ошибка загрузки

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

Requirement: Журнал восстанавливает чтение без ручного обновления

Страница журнала SHALL сохранять записи текущей выборки при временном сбое обновления и восстанавливать чтение автоматически по frontend-data-resilience. Период, категории и выбранная страница MUST сохраняться; результат другой выборки MUST NOT подменять текущую. Страница MUST NOT показывать время получения, технические статусы или действия ручного повтора. Даты операций, фильтры, действия их применения и переходы по страницам MUST оставаться доступными. При отсутствии результата SHALL применяться первичное ожидание и нейтральная недоступность, а не сообщение об отсутствии операций до подтверждения полноты.

Scenario: Обновление журнала временно не удалось

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

Scenario: Следующая страница ещё не получена

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