docs: describe all-accounts behavior
This commit is contained in:
@@ -50,6 +50,7 @@ Cross-area topology — [system overview](architecture/system-overview.md).
|
|||||||
| Предмет задачи | Current behavior |
|
| Предмет задачи | Current behavior |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Счета и их сводки | [Brokerage accounts](features/brokerage-accounts.md) |
|
| Счета и их сводки | [Brokerage accounts](features/brokerage-accounts.md) |
|
||||||
|
| Общий портфель и разделы по всем счетам | [All accounts](features/all-accounts.md) |
|
||||||
| Позиции/суммы портфеля, backend cache | [Portfolio](features/portfolio-view.md) |
|
| Позиции/суммы портфеля, backend cache | [Portfolio](features/portfolio-view.md) |
|
||||||
| Операции/фильтры/cursor | [Account ledger](features/brokerage-account-ledger.md) |
|
| Операции/фильтры/cursor | [Account ledger](features/brokerage-account-ledger.md) |
|
||||||
| Будущие выплаты | [Upcoming events](features/brokerage-account-upcoming-events.md) |
|
| Будущие выплаты | [Upcoming events](features/brokerage-account-upcoming-events.md) |
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
# Портфель по всем счетам
|
||||||
|
|
||||||
|
Режим «Все счета» объединяет открытые поддерживаемые инвестиционные счета,
|
||||||
|
доступные через текущее T-Bank connection. Состав совпадает с политикой
|
||||||
|
[списка счетов](brokerage-accounts.md); закрытые и недоступные счета не включаются.
|
||||||
|
`all` — зарезервированное обозначение общего режима, которое не передаётся
|
||||||
|
брокеру как идентификатор счёта.
|
||||||
|
|
||||||
|
## Маршруты и навигация
|
||||||
|
|
||||||
|
| Маршрут | Содержание |
|
||||||
|
| --- | --- |
|
||||||
|
| `/accounts` | Список отдельных счетов и действие открытия общего портфеля |
|
||||||
|
| `/accounts/all` | Общий портфель и превью операций, дохода и будущих событий |
|
||||||
|
| `/accounts/all/operations` | Общий журнал исполненных операций |
|
||||||
|
| `/accounts/all/income` | Купоны и дивиденды за календарный период |
|
||||||
|
| `/accounts/all/events` | Будущие события всех доступных счетов |
|
||||||
|
|
||||||
|
Статические маршруты используют существующие страницы с явно переданным
|
||||||
|
контекстом `all`. На страницах счёта и общего режима переключатель «Счёт»
|
||||||
|
сохраняет текущий раздел и применённые URL-фильтры. При переключении пагинация
|
||||||
|
начинается заново. Журнал хранит применённые `from`, `to` и `categories` в URL;
|
||||||
|
черновые значения применяются кнопкой. Раздел дохода сохраняет свой прежний
|
||||||
|
календарный контракт. Хлебные крошки называют общий режим «Все счета».
|
||||||
|
|
||||||
|
## Данные и вычисления
|
||||||
|
|
||||||
|
Backend публикует статические endpoints под `/api/v1/brokerage-accounts/all`:
|
||||||
|
`/portfolio`, `/operations`, `/income-summary`, `/income-analytics`, `/events`.
|
||||||
|
У них те же формы данных и фильтры, что у соответствующих разделов отдельного
|
||||||
|
счёта. Строки общего ответа дополнительно содержат `account: { id, name }`;
|
||||||
|
в ответах одного счёта это поле отсутствует. Источник wire contract — runtime
|
||||||
|
OpenAPI, snapshot и frontend types генерируются из него.
|
||||||
|
|
||||||
|
- Портфель и доступные денежные остатки суммируются сервером точно, по исходной
|
||||||
|
валюте, через существующую decimal-арифметику. FX-конвертации нет; правила
|
||||||
|
неизвестных значений и состава сумм наследуются от [портфеля](portfolio-view.md).
|
||||||
|
- Одинаковые бумаги разных счетов показаны одной карточкой с общим названием
|
||||||
|
и идентификатором. Внутри всегда видны строки счетов: ссылка на портфель,
|
||||||
|
количество, доступная стоимость, результат, средняя цена и доля позиции.
|
||||||
|
Денежные показатели и количества остаются исходными для каждого счёта;
|
||||||
|
общая средняя цена и суммарное количество карточки не рассчитываются.
|
||||||
|
Группировка выполняется по типу инструмента и FIGI, при отсутствии FIGI —
|
||||||
|
по ISIN. Разные FIGI, отсутствующие идентификаторы и одно лишь совпадение
|
||||||
|
имени или тикера не объединяются. Порядок карточек задаёт первое вхождение
|
||||||
|
бумаги; порядок счетов внутри карточки сохраняется. Одиночные позиции
|
||||||
|
используют прежнюю карточку. Доля относится к позициям той же валюты
|
||||||
|
во всём показанном портфеле, без денежных остатков.
|
||||||
|
- Журнал объединяет операции по убыванию времени, при равном времени использует
|
||||||
|
порядок идентификаторов счетов, сохраняя порядок внутри одного счёта. ID
|
||||||
|
операций разных счетов не считаются дублями. Переводы не схлопываются.
|
||||||
|
- Доходы собираются из всех страниц операций каждого счёта за общие периоды.
|
||||||
|
Итоги, сравнения, buckets и membership рассчитывает существующий сервис дохода.
|
||||||
|
Для сравнения с годом ранее используется текущий состав счетов; новый счёт
|
||||||
|
добавляет только реально полученные выплаты. При известных датах открытия
|
||||||
|
доступность сравнения определяется самым ранним открытием в этом составе.
|
||||||
|
Закрытые счета в историческое сравнение не добавляются.
|
||||||
|
- Будущие события сортируются по дате и сохраняют отдельную строку каждого счёта.
|
||||||
|
Прогноз не включается в реализованные доходы.
|
||||||
|
|
||||||
|
## Полнота, свежесть и доступ
|
||||||
|
|
||||||
|
Каждый общий запрос получает состав счетов и единую generation через
|
||||||
|
`TbankAccessService`. Получение данных использует эту же connection boundary;
|
||||||
|
проверки сессии, доступа и существующий лимитер внешних запросов сохраняются.
|
||||||
|
Финансовые данные не сохраняются в БД; новые зависимости не добавляются.
|
||||||
|
|
||||||
|
Ошибка источника не превращается в частичный успешный ответ раздела.
|
||||||
|
Портфель может использовать разрешённый существующей политикой stale snapshot
|
||||||
|
отдельного счёта. Тогда общий `isStale` равен `true`, а `lastSuccessfulAt`
|
||||||
|
показывает самое раннее время среди включённых снимков. Для пустого состава
|
||||||
|
возвращается корректный пустой результат. Общий запрос не является атомарным
|
||||||
|
наблюдением всех счетов в один момент времени.
|
||||||
|
|
||||||
|
Ошибка блока операций, доходов или будущих событий не скрывает основной
|
||||||
|
портфель. При фоновом обновлении страницы уже полученный результат сохраняется
|
||||||
|
с индикатором или предупреждением и повторной попыткой. Смена сессии или
|
||||||
|
connection сбрасывает общий режим вместе с существующим financial query subtree.
|
||||||
|
|
||||||
|
## Общая пагинация операций
|
||||||
|
|
||||||
|
Сервис объединяет потоки страниц каждого счёта и сохраняет непрочитанные строки
|
||||||
|
между запросами. Фильтрованные пустые страницы не обрывают поток. Повреждённая
|
||||||
|
cursor chain и нарушенный порядок дат возвращают ошибку без частичной страницы.
|
||||||
|
|
||||||
|
Курсор общего журнала — случайный непрозрачный идентификатор продолжения,
|
||||||
|
привязанного к пользователю, generation подключения, составу счетов, фильтрам
|
||||||
|
и размеру страницы. Верхняя граница периода фиксируется первым запросом.
|
||||||
|
Состояние ограничено 100 продолжениями на процесс с TTL пять минут;
|
||||||
|
повторный запрос того же продолжения возвращает тот же успешный результат.
|
||||||
|
|
||||||
|
Неизвестный, вытесненный, истёкший либо несовместимый курсор возвращает
|
||||||
|
`400 INVALID_OPERATIONS_CURSOR`. Действие «Повторить» сбрасывает пагинацию,
|
||||||
|
обновляет первую страницу и сохраняет фильтры. Перезапуск backend также
|
||||||
|
инвалидирует продолжения. Раздел рассчитан на один backend instance, как
|
||||||
|
существующий финансовый кэш.
|
||||||
|
|
||||||
|
## Проверка и совместимость
|
||||||
|
|
||||||
|
Агрегация проверяется service tests: точные суммы, исходные счета, порядок и
|
||||||
|
буферизация страниц, совпадающие ID, фильтрация, полнота, connection boundary,
|
||||||
|
сравнение дохода, stale и пустые результаты. Configured HTTP tests проверяют
|
||||||
|
Bearer guard, выбор статических маршрутов, валидацию и публичные ошибки.
|
||||||
|
Frontend tests проверяют прямые ссылки, переключение с фильтрами, сброс курсора
|
||||||
|
и сохранение снимка при ошибке обновления.
|
||||||
|
|
||||||
|
Обновление аддитивное: сначала backend, затем frontend с generated contract.
|
||||||
|
Прежний frontend продолжает работать с отдельными счетами. При откате сначала
|
||||||
|
возвращается frontend; изменений схемы БД и миграции пользовательских данных нет.
|
||||||
Reference in New Issue
Block a user