Files
docs/features/all-accounts.md
T

110 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Портфель по всем счетам
Режим «Все счета» объединяет открытые поддерживаемые инвестиционные счета,
доступные через текущее 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 генерируются из него.
- Портфель и доступные денежные остатки суммируются сервером точно, по исходной
валюте, с точной десятичной арифметикой. FX-конвертации нет; правила
неизвестных значений и состава сумм наследуются от [портфеля](portfolio-view.md).
- Одинаковые бумаги разных счетов показаны одной карточкой с общим названием
и идентификатором. Внутри всегда видны строки счетов: ссылка на портфель,
количество, доступная стоимость, результат, средняя цена и доля позиции.
Денежные показатели и количества остаются исходными для каждого счёта;
общая средняя цена и суммарное количество карточки не рассчитываются.
Группировка выполняется по типу инструмента и FIGI, при отсутствии FIGI —
по ISIN. Разные FIGI, отсутствующие идентификаторы и одно лишь совпадение
имени или тикера не объединяются. Порядок карточек задаёт первое вхождение
бумаги; порядок счетов внутри карточки сохраняется. Одиночные позиции
используют прежнюю карточку. Доля относится к позициям той же валюты
во всём показанном портфеле, без денежных остатков.
- Журнал объединяет операции по убыванию времени, при равном времени использует
порядок идентификаторов счетов, сохраняя порядок внутри одного счёта. ID
операций разных счетов не считаются дублями. Переводы не схлопываются.
- Доходы собираются из всех страниц операций каждого счёта за общие периоды.
Итоги, сравнения, buckets и membership рассчитывает существующий сервис дохода.
Для сравнения с годом ранее используется текущий состав счетов; новый счёт
добавляет только реально полученные выплаты. При известных датах открытия
доступность сравнения определяется самым ранним открытием в этом составе.
Закрытые счета в историческое сравнение не добавляются.
- Будущие события сортируются по дате и сохраняют отдельную строку каждого счёта.
Прогноз не включается в реализованные доходы.
## Полнота, свежесть и доступ
Для каждого общего запроса backend определяет состав доступных счетов
и единое поколение подключения. Получение данных использует эту же 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; изменений схемы БД и миграции пользовательских данных нет.