120 lines
12 KiB
Markdown
120 lines
12 KiB
Markdown
# Портфель по всем счетам
|
||
|
||
Режим «Все счета» объединяет открытые поддерживаемые инвестиционные счета,
|
||
доступные через текущее подключение T-Bank. Состав совпадает с политикой
|
||
[списка счетов](../accounts/overview.md); закрытые и недоступные счета не включаются.
|
||
`all` — зарезервированное обозначение общего режима, которое не передаётся
|
||
брокеру как идентификатор счёта.
|
||
|
||
## Маршруты и навигация
|
||
|
||
| Маршрут | Содержание |
|
||
| --- | --- |
|
||
| `/accounts` | Список отдельных счетов и действие открытия общего портфеля |
|
||
| `/accounts/all` | Общий портфель и превью операций, дохода и будущих событий |
|
||
| `/accounts/all/operations` | Общий журнал исполненных операций |
|
||
| `/accounts/all/income` | Купоны и дивиденды за календарный период |
|
||
| `/accounts/all/events` | Будущие события всех доступных счетов |
|
||
|
||
Общий режим использует те же страницы разделов с обозначением `all`.
|
||
На страницах счёта и общего режима переключатель «Счёт»
|
||
сохраняет текущий раздел и применённые URL-фильтры. При переключении пагинация
|
||
начинается заново. Журнал хранит применённые `from`, `to` и `categories` в URL;
|
||
черновые значения применяются кнопкой. Раздел дохода сохраняет свой прежний
|
||
календарный контракт. Хлебные крошки называют общий режим «Все счета».
|
||
|
||
## Данные и вычисления
|
||
|
||
Backend публикует статические маршруты под `/api/v1/brokerage-accounts/all`:
|
||
`/portfolio`, `/operations`, `/income-summary`, `/income-analytics`, `/events`.
|
||
У них те же формы данных и фильтры, что у соответствующих разделов отдельного
|
||
счёта. Позиции, операции (включая выплаты дохода) и события сохраняют источник
|
||
в поле `account: { id, name }`; в ответах одного счёта это поле отсутствует.
|
||
Валютные итоги и деньги агрегированы. Точную форму транспорта задаёт
|
||
[OpenAPI backend](../../architecture/http-api.md).
|
||
|
||
- Портфель и доступные денежные остатки суммируются сервером точно, по исходной
|
||
валюте, с точной десятичной арифметикой. FX-конвертации нет; правила
|
||
неизвестных значений и состава сумм наследуются от [портфеля](data-reference.md).
|
||
- Одинаковые бумаги разных счетов показаны одной карточкой с общим названием
|
||
и идентификатором. Внутри всегда видны строки счетов: ссылка на портфель,
|
||
количество, доступная стоимость, результат, средняя цена и доля позиции.
|
||
Денежные показатели и количества остаются исходными для каждого счёта;
|
||
общая средняя цена и суммарное количество карточки не рассчитываются.
|
||
Группировка выполняется по типу инструмента и первому доступному
|
||
идентификатору: UID, затем FIGI, затем ISIN. Разные выбранные идентификаторы
|
||
или их отсутствие, а также одно лишь совпадение имени или тикера не
|
||
объединяют позиции. Повторные строки одного счёта остаются отдельными.
|
||
API сохраняет позиции каждого счёта; объединяется только их представление.
|
||
Порядок карточек задаёт первое вхождение
|
||
бумаги; порядок счетов внутри карточки сохраняется. Одиночные позиции
|
||
используют прежнюю карточку. Доля относится к позициям той же валюты
|
||
во всём показанном портфеле, без денежных остатков.
|
||
- Журнал объединяет операции по убыванию времени, при равном времени использует
|
||
порядок идентификаторов счетов, сохраняя порядок внутри одного счёта. ID
|
||
операций разных счетов не считаются дублями. Переводы не схлопываются.
|
||
- Доходы собираются из всех страниц операций каждого счёта за общие периоды.
|
||
Итоги, сравнения, временные интервалы и принадлежность выплат рассчитывает
|
||
сервис дохода.
|
||
Для сравнения с годом ранее используется текущий состав счетов; новый счёт
|
||
добавляет только реально полученные выплаты. При известных датах открытия всех счетов
|
||
доступность сравнения определяется самым ранним открытием в этом составе.
|
||
Закрытые счета в историческое сравнение не добавляются.
|
||
- Будущие события сортируются по дате и сохраняют отдельную строку каждого счёта.
|
||
Прогноз не включается в реализованные доходы.
|
||
|
||
## Полнота, свежесть и доступ
|
||
|
||
Для каждого общего запроса backend определяет состав доступных счетов
|
||
и единое поколение подключения. Получение данных использует эту же границу подключения;
|
||
проверки сессии, доступа и существующий лимитер внешних запросов сохраняются.
|
||
Финансовые данные не сохраняются в БД; снимки и продолжения хранятся
|
||
в памяти процесса.
|
||
|
||
Ошибка источника не превращается в частичный успешный ответ раздела.
|
||
Портфель может использовать разрешённый существующей политикой запасной снимок
|
||
отдельного счёта. Тогда общий `isStale` равен `true`, а `lastSuccessfulAt`
|
||
показывает самое раннее время среди включённых снимков. Для пустого состава
|
||
возвращается корректный пустой результат. Общий запрос не является атомарным
|
||
наблюдением всех счетов в один момент времени.
|
||
|
||
Ошибка блока операций, доходов или будущих событий не скрывает основной
|
||
портфель. При фоновом обновлении страницы уже полученный результат сохраняется
|
||
с индикатором или предупреждением и повторной попыткой. Смена сессии или
|
||
подключения сбрасывает общий режим вместе с остальными финансовыми запросами.
|
||
|
||
## Общая пагинация операций
|
||
|
||
Сервис объединяет потоки страниц каждого счёта и сохраняет непрочитанные строки
|
||
между запросами. Фильтрованные пустые страницы не обрывают поток. Повреждённая
|
||
цепочка курсоров и нарушенный порядок дат возвращают ошибку без частичной страницы.
|
||
|
||
Курсор общего журнала — случайный непрозрачный идентификатор продолжения,
|
||
привязанного к пользователю, поколению подключения, составу счетов, фильтрам
|
||
и размеру страницы. Верхняя граница периода фиксируется первым запросом.
|
||
Состояние ограничено 100 продолжениями на процесс со сроком жизни пять минут;
|
||
повторный запрос того же продолжения возвращает тот же успешный результат.
|
||
|
||
Неизвестный, вытесненный, истёкший либо несовместимый курсор возвращает
|
||
`400 INVALID_OPERATIONS_CURSOR`. Действие «Повторить» сбрасывает пагинацию,
|
||
обновляет первую страницу и сохраняет фильтры. Перезапуск backend также
|
||
инвалидирует продолжения. Раздел рассчитан на один экземпляр backend, как
|
||
существующий финансовый кэш.
|
||
|
||
## Совместимость и границы требований
|
||
|
||
Общий режим добавляет маршруты, сохраняя маршруты отдельных счетов.
|
||
При совместном обновлении сначала нужен backend, затем frontend с
|
||
соответствующим сгенерированным контрактом; прежний клиент продолжает
|
||
работать с отдельными счетами. При откате сначала возвращается клиент.
|
||
Этот механизм не требует изменения схемы SQLite и миграции финансовых данных.
|
||
|
||
Основные спецификации [портфеля](../../../specs/openspec/specs/portfolio-view/spec.md),
|
||
[операций](../../../specs/openspec/specs/brokerage-account-ledger/spec.md),
|
||
[дохода](../../../specs/openspec/specs/brokerage-account-income-analytics/spec.md)
|
||
и [событий](../../../specs/openspec/specs/brokerage-account-upcoming-events/spec.md)
|
||
описывают отдельный счёт. Общий режим подтверждён действующими маршрутизаторами,
|
||
сервисами и [проверками агрегации](../../../backend/src/tbank/all-accounts.spec.ts),
|
||
но не выделен в самостоятельную основную спецификацию. Не следует считать
|
||
описание общего режима изменением требований к отдельному счёту.
|