# Портфель по всем счетам Режим «Все счета» объединяет открытые поддерживаемые инвестиционные счета, доступные через текущее 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; изменений схемы БД и миграции пользовательских данных нет.