codex/broker-accounts-overview #22
@ -0,0 +1,92 @@
|
||||
# ADR-012: Сводка брокерских счетов агрегируется на frontend
|
||||
|
||||
**Статус:** Accepted
|
||||
|
||||
**Дата:** 2026-06-19
|
||||
|
||||
## Контекст
|
||||
|
||||
Страница списка брокерских счетов должна показывать общую стоимость, дневной результат, свободные
|
||||
деньги и распределение активов, а также подробные показатели каждого счёта. Endpoint
|
||||
`GET /api/v1/broker/accounts` возвращает только метаданные счетов. Все необходимые финансовые данные
|
||||
уже доступны через `GET /api/v1/broker/accounts/:accountId/portfolio`.
|
||||
|
||||
Текущий продуктовый сценарий предполагает один–три открытых счёта. Backend кеширует ответы портфеля
|
||||
и ограничивает запросы к T-Bank через общую очередь.
|
||||
|
||||
## Рассмотренные варианты
|
||||
|
||||
### 1. Агрегация существующих ответов на frontend
|
||||
|
||||
Frontend получает список счетов, параллельно запрашивает портфель каждого счёта и строит общую
|
||||
сводку из успешно загруженных ответов.
|
||||
|
||||
Преимущества:
|
||||
|
||||
- не появляется новый API-контракт с данными, уже доступными в portfolio endpoint;
|
||||
- каждый счёт может загружаться и восстанавливаться после ошибки независимо;
|
||||
- при одном–трёх счетах число запросов остаётся ограниченным;
|
||||
- используются существующие backend cache и rate limiting.
|
||||
|
||||
Недостатки:
|
||||
|
||||
- страница выполняет `1 + N` HTTP-запросов;
|
||||
- ответы могут иметь разные значения `asOf` и не образуют атомарный снимок;
|
||||
- правила презентационной агрегации находятся на frontend.
|
||||
|
||||
### 2. Новый aggregate endpoint
|
||||
|
||||
Добавить endpoint, который возвращает список счетов, их портфели и общую сводку одним ответом.
|
||||
|
||||
Преимущества:
|
||||
|
||||
- один HTTP-запрос с frontend;
|
||||
- единый серверный контракт агрегации;
|
||||
- проще переиспользовать сводку другими клиентами.
|
||||
|
||||
Недостатки:
|
||||
|
||||
- новый контракт дублирует существующие portfolio-данные;
|
||||
- нужно определить семантику частичных ошибок и кеширования составного ответа;
|
||||
- endpoint всё равно получает портфели нескольких счетов и не гарантирует атомарность данных T-Bank.
|
||||
|
||||
### 3. Расширение endpoint списка счетов
|
||||
|
||||
Добавить финансовую сводку каждого счёта в `GET /api/v1/broker/accounts`.
|
||||
|
||||
Преимущества:
|
||||
|
||||
- frontend получает всё одним запросом;
|
||||
- карточки становятся простыми потребителями ответа.
|
||||
|
||||
Недостатки:
|
||||
|
||||
- лёгкий endpoint метаданных превращается в дорогой составной запрос;
|
||||
- меняются его кеширование, время ответа и семантика ошибок;
|
||||
- потребители списка счетов вынужденно получают финансовые данные.
|
||||
|
||||
## Решение
|
||||
|
||||
Использовать вариант 1: агрегировать существующие portfolio-ответы на frontend.
|
||||
|
||||
Frontend параллельно запрашивает портфели после получения списка счетов. Общая сводка строится только
|
||||
из успешно загруженных ответов и явно помечается как частичная, если часть счетов недоступна. Ошибка
|
||||
одного портфеля не блокирует остальные карточки.
|
||||
|
||||
Денежные значения группируются по валюте. Frontend не выполняет неявную валютную конвертацию и не
|
||||
складывает несопоставимые суммы. Значения `asOf` отдельных ответов сохраняют свой смысл; сводка не
|
||||
считается транзакционно согласованным снимком.
|
||||
|
||||
## Последствия
|
||||
|
||||
- Страница выполняет один запрос списка и до трёх параллельных запросов портфелей.
|
||||
- Backend остаётся источником финансовых данных отдельного счёта, а frontend владеет только их
|
||||
представлением и агрегацией для этой страницы.
|
||||
- Частичные ошибки становятся штатным состоянием интерфейса и должны быть покрыты тестами.
|
||||
- API, OpenAPI и frontend codegen для этой фичи не меняются.
|
||||
- Решение следует пересмотреть, если выполняется хотя бы одно условие:
|
||||
- продукт поддерживает более трёх одновременно отображаемых счетов;
|
||||
- измерения показывают неприемлемую задержку или нагрузку от `1 + N` запросов;
|
||||
- нескольким клиентам нужна одинаковая серверная сводка;
|
||||
- появляется требование к согласованному серверному снимку или серверной валютной конвертации;
|
||||
- правила агрегации становятся самостоятельной бизнес-логикой, а не логикой представления.
|
||||
@ -1,7 +1,7 @@
|
||||
# Архитектурные решения (ADR)
|
||||
|
||||
| ADR | Статус | Описание |
|
||||
|---|---|---|
|
||||
| ------------------------------------------------------ | ---------- | ---------------------------------------------- |
|
||||
| [ADR-001](ADR-001-backend-single-point-of-access) | Accepted | Backend — единственная точка доступа к MOEX |
|
||||
| [ADR-002](ADR-002-in-memory-cache) | Accepted | Стратегия in-memory cache |
|
||||
| [ADR-003](ADR-003-rate-limiting-strategy) | Accepted | Стратегия rate limiting |
|
||||
@ -13,5 +13,6 @@
|
||||
| [ADR-009](ADR-009-portfolio-domain) | Accepted | Доменная модель портфеля |
|
||||
| [ADR-010](ADR-010-backend-price-computation) | Accepted | Расчёт цен на backend |
|
||||
| [ADR-011](ADR-011-tbank-invest-grpc) | Accepted | Интеграция с T-Bank Invest через gRPC |
|
||||
| [ADR-012](ADR-012-frontend-broker-account-aggregation) | Accepted | Агрегация сводки брокерских счетов на frontend |
|
||||
|
||||
Все опубликованные ADR находятся в `apps/docs/docs/adr/` и отображаются в этом Docusaurus-разделе.
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
- [T-Bank broker portfolios](../features/tbank-broker-portfolios/spec.md)
|
||||
- [Отображение брокерского портфеля](../features/broker-portfolio-display/spec.md)
|
||||
- [x] [Разделы брокерского счёта](../features/broker-account-sections/spec.md) — реализовано
|
||||
- [Информативный обзор брокерских счетов](../features/broker-accounts-overview/spec.md)
|
||||
- [Улучшение UI операций](../features/broker-operations-ui-improvements/spec.md)
|
||||
- [Пагинация и загрузка позиций](../features/broker-positions-pagination-and-loading/spec.md)
|
||||
- [Исправление deadline и очереди T-Bank](../features/tbank-deadline-queue-fix/spec.md)
|
||||
|
||||
155
docs/features/broker-accounts-overview/spec.md
Normal file
155
docs/features/broker-accounts-overview/spec.md
Normal file
@ -0,0 +1,155 @@
|
||||
# Информативный обзор брокерских счетов
|
||||
|
||||
Дата: 2026-06-19
|
||||
Статус: согласовано к планированию
|
||||
Эпик: [Портфель брокера](../../epics/BrokerPortfolio.md)
|
||||
|
||||
## Контекст
|
||||
|
||||
Страница `/broker` показывает открытые брокерские счета и ИИС карточками, но полезная информация в
|
||||
них ограничена названием, типом, техническим статусом и идентификатором. Пользователь не может на
|
||||
одном экране оценить совокупный капитал, сравнить счета и понять структуру активов.
|
||||
|
||||
Страница предназначена преимущественно для одного–трёх счетов.
|
||||
|
||||
## Цель
|
||||
|
||||
Превратить список брокерских счетов в компактный финансовый обзор, который с первого взгляда
|
||||
отвечает на вопросы:
|
||||
|
||||
- сколько средств находится на всех доступных счетах;
|
||||
- как изменилась их стоимость за день;
|
||||
- сколько свободных денег доступно;
|
||||
- как капитал распределён между счетами и основными классами активов;
|
||||
- какой счёт нужно открыть для подробного анализа.
|
||||
|
||||
## Область изменений
|
||||
|
||||
Фича изменяет страницу списка брокерских счетов и включает:
|
||||
|
||||
- общую сводку по успешно загруженным счетам;
|
||||
- информативные карточки отдельных счетов;
|
||||
- независимую загрузку данных каждого счёта;
|
||||
- состояния загрузки, частичной ошибки и отсутствия счетов;
|
||||
- адаптивное отображение на широких и узких экранах.
|
||||
|
||||
Детальные страницы счёта, позиции, операции, торговые действия и правила расчёта показателей,
|
||||
приходящих от T-Bank, не изменяются.
|
||||
|
||||
## Требования
|
||||
|
||||
### 1. Общая сводка
|
||||
|
||||
Над списком счетов отображается сводка по портфелям, данные которых успешно загружены:
|
||||
|
||||
- количество доступных счетов;
|
||||
- совокупная стоимость портфелей;
|
||||
- совокупный дневной результат в деньгах и процентах;
|
||||
- свободные деньги;
|
||||
- распределение стоимости по акциям, облигациям, фондам, деньгам и прочим активам.
|
||||
|
||||
Денежные значения разных валют не складываются и показываются отдельными суммами. Процентный
|
||||
дневной результат и единое распределение активов показываются только для сопоставимых денежных
|
||||
значений одной валюты. Интерфейс не выполняет неявную конвертацию валют.
|
||||
|
||||
Для каждой валюты совокупный дневной процент рассчитывается как отношение суммы дневных изменений
|
||||
к суммарной стоимости портфелей на начало дня:
|
||||
|
||||
```text
|
||||
sum(daily) / (sum(portfolio) - sum(daily)) * 100
|
||||
```
|
||||
|
||||
Процент не показывается, если хотя бы у одного включённого в валютную группу счёта отсутствует
|
||||
стоимость или дневное изменение либо если стоимость на начало дня неположительна.
|
||||
|
||||
Если загружены не все счета, сводка явно сообщает, по скольким счетам рассчитаны показатели.
|
||||
Недоступный счёт не включается в агрегированные значения.
|
||||
|
||||
### 2. Карточка счёта
|
||||
|
||||
Для каждого счёта показываются:
|
||||
|
||||
- название;
|
||||
- понятный тип: `Брокерский счёт` или `ИИС`;
|
||||
- дата открытия, если она доступна;
|
||||
- текущая стоимость;
|
||||
- дневной результат в деньгах и процентах;
|
||||
- ожидаемая доходность;
|
||||
- распределение стоимости по основным классам активов.
|
||||
|
||||
Технический идентификатор, сырой enum статуса и сырой enum уровня доступа в карточке не
|
||||
отображаются.
|
||||
|
||||
Вся карточка является доступной с клавиатуры ссылкой на обзор выбранного счёта. Цвет доходности
|
||||
используется только как дополнительный признак: знак и числовое значение остаются видимыми.
|
||||
|
||||
### 3. Загрузка
|
||||
|
||||
После получения списка счетов данные их портфелей загружаются независимо. До появления значений
|
||||
общая сводка и карточки показывают skeleton-состояние с устойчивыми размерами, чтобы содержимое не
|
||||
скакало при загрузке.
|
||||
|
||||
Появление данных одного счёта не должно ждать завершения остальных запросов.
|
||||
|
||||
### 4. Ошибки
|
||||
|
||||
Ошибка загрузки списка счетов показывает ошибку всей страницы.
|
||||
|
||||
Ошибка загрузки портфеля отдельного счёта:
|
||||
|
||||
- не скрывает другие счета;
|
||||
- не блокирует переход в доступные счета;
|
||||
- показывает локальное сообщение в карточке проблемного счёта;
|
||||
- позволяет повторить загрузку этого счёта;
|
||||
- исключает этот счёт из общей сводки и маркирует сводку как частичную.
|
||||
|
||||
### 5. Пустое состояние
|
||||
|
||||
Если открытых брокерских счетов и ИИС нет, страница показывает отдельное пустое состояние вместо
|
||||
пустой сетки карточек. Текст объясняет, какие счета появятся на странице после подключения T-Bank.
|
||||
|
||||
### 6. Адаптивность
|
||||
|
||||
При одном–трёх счетах карточки располагаются вертикально и сохраняют единый порядок показателей для
|
||||
быстрого сравнения.
|
||||
|
||||
На узком экране показатели переносятся на несколько строк, диаграмма распределения остаётся
|
||||
читаемой, а интерактивные области не требуют горизонтальной прокрутки.
|
||||
|
||||
## Ограничения
|
||||
|
||||
- Страница остаётся read-only.
|
||||
- Frontend не обращается к T-Bank напрямую.
|
||||
- Агрегация не пересчитывает показатели отдельного счёта: исходные стоимости и доходность берутся
|
||||
из существующих ответов портфеля. Единственный новый производный показатель — совокупный дневной
|
||||
процент по явно заданной в этой спецификации формуле.
|
||||
- Данные разных счетов могут иметь разные моменты `asOf`; интерфейс не представляет сводку как
|
||||
транзакционно согласованный снимок.
|
||||
- Решение рассчитано на один–три счёта. Расширение этого предположения требует пересмотра
|
||||
[ADR-012](../../../apps/docs/docs/adr/ADR-012-frontend-broker-account-aggregation.md).
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- Над счетами показана общая стоимость, дневной результат, свободные деньги, число счетов и
|
||||
распределение активов.
|
||||
- Значения разных валют не складываются без курса конвертации.
|
||||
- Каждая успешно загруженная карточка показывает стоимость, доходность, тип и распределение активов.
|
||||
- Название и дата открытия показываются, когда доступны.
|
||||
- Технический ID и сырые T-Bank enum-значения не отображаются.
|
||||
- Вся карточка ведёт на обзор соответствующего счёта и доступна с клавиатуры.
|
||||
- Во время загрузки отображаются skeleton-состояния без заметного изменения геометрии страницы.
|
||||
- Ошибка одного портфеля не скрывает остальные счета и не включает недоступные данные в сводку.
|
||||
- Пользователь может повторить запрос проблемного счёта.
|
||||
- При отсутствии счетов отображается объясняющее пустое состояние.
|
||||
- Страница не требует горизонтальной прокрутки на поддерживаемых мобильных ширинах.
|
||||
- Unit-тесты покрывают агрегацию, валютные ограничения и расчёт распределения.
|
||||
- Component-тесты покрывают успешную загрузку, skeleton, пустое состояние, частичную ошибку,
|
||||
повторный запрос и переход в счёт.
|
||||
|
||||
## Не цели
|
||||
|
||||
- Добавление aggregate endpoint на backend.
|
||||
- Конвертация валют и получение валютных курсов.
|
||||
- Поддержка более трёх счетов как отдельного плотного режима.
|
||||
- Изменение детальной страницы брокерского счёта.
|
||||
- Изменение T-Bank DTO, OpenAPI-контракта или сгенерированных frontend-типов.
|
||||
@ -11,6 +11,7 @@ Roadmap отражает порядок продуктовой работы, н
|
||||
Цель: сделать реальные брокерские счета понятными на уровне обзора, позиций и операций.
|
||||
|
||||
- [x] [Разделы брокерского счёта](features/broker-account-sections/spec.md) — реализовано.
|
||||
- [ ] [Информативный обзор брокерских счетов](features/broker-accounts-overview/spec.md) — согласовано к планированию.
|
||||
|
||||
## Следующие этапы для активной фичи
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user