Record the approved proposal, delta specifications, design and 27 verified implementation tasks. Keep the change active; archiving and main-spec synchronization are deferred.
23 KiB
MODIFIED Requirements
Requirement: Список активных брокерских счетов
Система SHALL предоставлять авторизованному User GET /api/v1/brokerage-accounts, возвращающий envelope { data, meta }, где data содержит сохранённый массив открытых поддерживаемых инвестиционных счетов T-Bank, доступных через текущий T-Bank connection User, в порядке, полученном от T-Bank. Каждый элемент MUST содержать стабильный id, непустое name, нормализованный type (BROKERAGE, INDIVIDUAL_INVESTMENT, INVEST_BOX или MONEY_MARKET_FUND) и nullable openedOn в формате YYYY-MM-DD. Система MUST включать только счета T-Bank типов «брокерский счёт», «ИИС», «Инвесткопилка» и «фонд денежного рынка»; банковские и неизвестные типы MUST NOT возвращаться. Система MUST удалить внешние пробелы из имени и при пустом результате использовать непустое название соответствующего типа.
Каждый элемент MUST также содержать nullable portfolioSummary. Доступная сводка MUST содержать totalsByCurrency: точные Money-итоги Portfolio по исходным ISO-валютам, включающие стоимость позиций и Cash Balance в той же валюте. Она MUST NOT содержать FX-конвертированный или межвалютный итог и MUST NOT выдавать Cash Balance за самостоятельный второй итог. Если успешная сводка Portfolio конкретного доступного счёта ещё не сохранена, portfolioSummary MUST быть null, не исключая этот счёт из списка и не делая список неуспешным. Пустой доступный Portfolio MUST передаваться доступной сводкой с пустым totalsByCurrency, а не null.
Список Brokerage Account и его сводки постоянно сохраняются и являются результатом последнего успешного наблюдения текущего брокерского подключения и MUST NOT создавать ожидание, что WealthLedger хранит долговременное право владения счётом или Portfolio независимо от T-Bank connection.
Обычный запрос MUST читать сохранённый список и доступные сводки без ожидания T-Bank. Срок свежести списка MUST составлять пять минут; сводки MUST следовать минутной свежести Portfolio. Отсутствующий список MUST возвращаться как 200 с data: null, meta.availability: missing и состоянием запрошенной загрузки. Только успешно полученный полный пустой список MUST возвращаться как data: [] с meta.availability: complete. Время, свежесть и состояние загрузки MUST передаваться по контракту tbank-data-sync. Отсутствие либо ошибка загрузки сводки MUST отличаться от отсутствия самого счёта; сохранённая успешная сводка MUST оставаться доступной после временной ошибки её обновления.
Scenario: Поддерживаемые счета возвращаются в upstream-порядке
- WHEN User с действующим T-Bank connection запрашивает список, а последняя успешная синхронизация сохранила открытые брокерский счёт, ИИС и неподдержанный дебетовый счёт
- THEN система отвечает
200с массивом брокерского счёта и ИИС вdataв исходном порядке T-Bank без дебетового счёта
Scenario: Пустой список поддерживаемых счетов
- WHEN User с действующим T-Bank connection имеет сохранённый успешно подтверждённый пустой список открытых поддерживаемых инвестиционных счетов
- THEN система отвечает
200сdata: []иmeta.availability: complete
Scenario: Пустое название получает fallback
- WHEN T-Bank возвращает поддерживаемый открытый счёт с пустым либо состоящим из пробелов именем
- THEN система отвечает этим счётом с непустым названием его нормализованного типа
Scenario: Дата открытия отсутствует
- WHEN T-Bank не возвращает дату открытия поддерживаемого открытого счёта
- THEN система отвечает этим счётом с
openedOn: null
Scenario: Мультивалютная сводка счёта
- WHEN доступный Portfolio счёта содержит итоги в RUB и USD, включая Cash Balance в USD
- THEN ответ содержит одну доступную
portfolioSummaryс отдельными Money-итогами RUB и USD без FX-конвертации, общего итога или отдельного итога Cash Balance
Scenario: Сводка одного счёта временно недоступна
- WHEN список доступных счетов получен, но Portfolio одного из них ещё не сохранён и его загрузка временно недоступна
- THEN система отвечает
200всеми счетами в исходном порядке, передаёт для этого счётаportfolioSummary: nullи не заменяет успешные сводки остальных счетов ошибкой списка
Scenario: Доступный Portfolio пуст
- WHEN доступный счёт не имеет ненулевых позиций и доступных денежных остатков
- THEN система передаёт доступную
portfolioSummaryс пустымtotalsByCurrency
Scenario: Список ещё не загружен
- WHEN User впервые запрашивает список текущего подключения и успешного сохранённого результата ещё нет
- THEN система возвращает
200сdata: null, состоянием загрузки вmeta, запрашивает фоновую синхронизацию и не выдаёт отсутствие данных за отсутствие счетов
Scenario: Ошибка обновления сохранённой сводки
- WHEN обновление Portfolio одного счёта временно неуспешно и его успешная сводка уже сохранена
- THEN список сохраняет эту сводку с прежним временем и видимым состоянием ошибки обновления вместо
null
Requirement: Состояния недоступности списка счетов
Система MUST возвращать последний полностью сохранённый список текущего подключения без синхронной проверки T-Bank. Неполный ответ обновления MUST NOT заменять полный список. При отсутствии T-Bank connection система MUST отвечать 409 Problem Details с code TBANK_NOT_CONNECTED. Если для текущего подключения уже подтверждено отклонение token как неаутентифицированного или без прав, система MUST отвечать 400 Problem Details с code INVALID_TBANK_TOKEN и сохранять connection. При временной либо иной upstream-ошибке фонового обновления система MUST сохранять прежний список и время его успешной загрузки, при наблюдении завершённой попытки возвращая 200 с meta.sync.state: failed и безопасным meta.sync.errorCode. Обычный запрос экрана либо ручное обновление MAY запросить новую попытку согласно tbank-data-sync; наблюдение статуса MUST NOT запускать её. При отсутствии сохранённого списка data MUST оставаться null. Ошибка обновления MUST NOT менять время успешной загрузки и сама по себе MUST NOT делать ещё свежие данные устаревшими; свежесть MUST продолжать определяться сроком соответствующего источника. Подтверждённая недействительность текущего token MUST запрещать выдачу личных данных, включая сохранённый список; локальная сессия и текущая граница подключения MUST проверяться до чтения.
Scenario: Подключение отсутствует
- WHEN User без сохранённого T-Bank connection запрашивает список
- THEN система не обращается к T-Bank и отвечает
409Problem Details с codeTBANK_NOT_CONNECTED
Scenario: Сохранённый token больше не действителен
- WHEN фоновая проверка подтвердила, что T-Bank отклоняет token текущего подключения как неаутентифицированный или без прав, и User снова запрашивает список
- THEN система отвечает
400Problem Details с codeINVALID_TBANK_TOKENи не удаляет connection
Scenario: T-Bank временно недоступен
- WHEN фоновое обновление списка завершается временной либо иной upstream-ошибкой
- THEN последующее наблюдение результата без нового запуска отвечает
200с последним сохранённым списком либоdata: null,meta.sync.state: failedиmeta.sync.errorCode: TBANK_UNAVAILABLE, не подтверждая новую успешную загрузку
Requirement: Экран списка брокерских счетов
Клиент SHALL загружать список при открытии защищённого маршрута /accounts и предоставлять действие «Обновить», без автоматического refetch при возврате фокуса. Клиент MUST использовать успешный frontend-кэш списка в течение 60 секунд. После истечения этого срока клиент MUST запрашивать локальный результат и состояние синхронизации; при уже имеющемся успешном списке он MUST сохранять последний успешный Client Cached Snapshot видимым во время фонового обновления и после его ошибки, ясно отделяя это состояние от свежего результата. Клиент MUST читать список из data, показывать свежесть и состояние синхронизации из meta и MUST NOT считать успешный HTTP-ответ с data: null пустым списком. Ручное обновление MUST обходить проверку давности списка и показанных сводок, не обновляя всю историю счетов. При успешном непустом ответе клиент MUST отобразить адаптивный одноколоночный список широких интерактивных карточек счетов с локализованными типом и, если доступна, датой открытия без времени; каждая карточка MUST ясно показывать тип, имя, финансовую сводку, вторичные метаданные и заметное действие открытия счёта, вести на /accounts/:accountId по всей области и сохранять доступное клавиатурное состояние. После успешной замены или удаления T-Bank connection клиент MUST инвалидировать список счетов.
Для доступной portfolioSummary карточка MUST показывать не более двух Money-итогов в исходных валютах и обозначать наличие остальных валют, если они есть; она MUST NOT показывать или подразумевать FX-конвертацию, межвалютный агрегированный итог либо Cash Balance как отдельный второй итог. При portfolioSummary: null карточка MUST показывать локальное безопасное состояние временной недоступности сводки, сохраняя метаданные счёта и возможность открыть его. При доступной пустой сводке карточка MUST не выдавать отсутствие итогов за временную ошибку.
Scenario: Пользователь открывает счёт из списка
- WHEN клиент успешно загрузил непустой список и User выбирает карточку счёта
- THEN клиент переходит на
/accounts/:accountIdсidвыбранного счёта
Scenario: Список пуст
- WHEN клиент получает
data: []сmeta.availability: complete - THEN клиент показывает штатное сообщение об отсутствии инвестиционных счетов T-Bank
Scenario: Список берётся из свежего frontend-кэша
- WHEN User повторно открывает список в течение 60 секунд после успешной загрузки
- THEN клиент показывает сохранённые счета без нового API-запроса
Scenario: Устаревший список загружается повторно
- WHEN User открывает список после истечения 60 секунд frontend-кэша и уже существует последний успешный список
- THEN клиент оставляет этот список видимым во время нового запроса и ясно обозначает фоновое обновление
Scenario: Ошибка фонового обновления не скрывает snapshot
- WHEN обновление устаревшего списка завершается временной ошибкой при наличии последнего успешного Client Cached Snapshot
- THEN клиент сохраняет snapshot видимым, безопасно сообщает о неуспешном обновлении и предоставляет применимое действие повторной загрузки
Scenario: Карточка ограничивает валютные итоги
- WHEN доступная сводка счёта содержит итоги в трёх или более валютах
- THEN карточка показывает не более двух исходных валютных итогов и обозначает наличие остальных без общего сконвертированного значения
Scenario: Недоступность сводки локальна карточке
- WHEN клиент получает список, в котором
portfolioSummaryодного счёта равнаnull - THEN он показывает временную недоступность только на этой карточке, не скрывает остальные карточки и сохраняет переход на детали недоступной сводки счёта
Scenario: Пустая сводка не является ошибкой
- WHEN клиент получает доступную
portfolioSummaryс пустымtotalsByCurrency - THEN он показывает нейтральное состояние отсутствия финансовых итогов, а не состояние временной недоступности
Scenario: Начальная загрузка не становится пустым списком
- WHEN клиент получает
data: nullсо статусом запрошенной синхронизации - THEN он показывает состояние первичной загрузки или её ошибки, а не сообщение об отсутствии инвестиционных счетов
Scenario: Ручное обновление списка
- WHEN User нажимает «Обновить» на экране списка счетов
- THEN клиент запрашивает обновление списка и показанных сводок независимо от давности, сохраняя доступные данные и отображая прогресс
Requirement: Клиентские состояния ошибки списка счетов
Клиент MUST NOT автоматически повторять неуспешный запрос списка. При TBANK_NOT_CONNECTED клиент SHALL показать объяснение отсутствия подключения и действие «Открыть настройки T-Bank». При INVALID_TBANK_TOKEN клиент SHALL показать объяснение недействительного token и то же действие. При TBANK_UNAVAILABLE клиент SHALL показать безопасное объяснение временной недоступности, действие повторной загрузки и действие открытия настроек T-Bank. При иной ошибке клиент MUST показать общий безопасный error-state только с действием повторной загрузки. При TBANK_NOT_CONNECTED или INVALID_TBANK_TOKEN клиент MUST скрыть личные данные даже при наличии Client Cached Snapshot. Для временной и неизвестной ошибки без snapshot клиент MUST показать ошибку без списка; при наличии snapshot он MUST сохранить его видимым с безопасным предупреждением. meta.sync.state: failed MUST отображаться как ошибка фоновой синхронизации, отдельно от ошибки HTTP-запроса; успешный HTTP-ответ сам по себе MUST NOT скрывать такую ошибку.
Scenario: Подключение требуется
- WHEN клиент получает
TBANK_NOT_CONNECTED - THEN клиент не показывает список и предлагает открыть настройки T-Bank
Scenario: Известная ошибка не повторяется автоматически
- WHEN запрос списка завершается известной ошибкой либо сервер сообщает завершённую неуспешную синхронизацию
- THEN клиент не выполняет дополнительные запросы, пока User не выберет действие повторной загрузки
Scenario: Token требует внимания
- WHEN клиент получает
INVALID_TBANK_TOKEN - THEN клиент не показывает список и предлагает открыть настройки T-Bank
Scenario: Временная ошибка T-Bank
- WHEN клиент получает
TBANK_UNAVAILABLEи сохранённого списка нет - THEN клиент не показывает список и предлагает повторить загрузку либо открыть настройки T-Bank
Scenario: Неизвестная ошибка загрузки
- WHEN клиент получает ошибку без известного кода списка счетов и сохранённого списка нет
- THEN клиент не показывает список и предлагает только повторить загрузку
Scenario: Известная ошибка при сохранённом snapshot
- WHEN фоновое обновление списка с последним успешным Client Cached Snapshot получает
TBANK_UNAVAILABLEчерез HTTP-ошибку либоmeta.sync.errorCode - THEN клиент сохраняет snapshot видимым, сообщает о временной недоступности и предлагает повторить загрузку либо открыть настройки T-Bank