Files
docs/domains/portfolio/all-accounts.md
T
ksv741 97069d6f6d
Docs security / security (pull_request) Successful in 6s
Docs verify / verify (pull_request) Successful in 11s
Conventional commits / commits (pull_request) Successful in 16s
Docs security / security (push) Successful in 9s
Docs verify / verify (push) Successful in 10s
docs: make documentation checks self-contained
2026-09-15 20:45:40 +03:00

120 lines
12 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. Состав совпадает с политикой
[списка счетов](../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 и миграции финансовых данных.
Основные спецификации [портфеля](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/portfolio-view/spec.md),
[операций](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/brokerage-account-ledger/spec.md),
[дохода](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/brokerage-account-income-analytics/spec.md)
и [событий](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/brokerage-account-upcoming-events/spec.md)
описывают отдельный счёт. Общий режим подтверждён действующими маршрутизаторами,
сервисами и [проверками агрегации](https://git.personal.ksv741.ru/WealthLedger/backend/src/commit/016782657acfd35ff3fd755462007938fac35156/src/modules/investments/all-accounts.spec.ts),
но не выделен в самостоятельную основную спецификацию. Не следует считать
описание общего режима изменением требований к отдельному счёту.