docs: document hourly investment reads
Docs security / security (push) Successful in 46s
Docs verify / verify (push) Successful in 13s

This commit was merged in pull request #32.
This commit is contained in:
2026-10-09 21:13:45 +03:00
committed by ksv741
parent df6f0109ed
commit f0cab445d7
6 changed files with 154 additions and 121 deletions
+30 -23
View File
@@ -40,10 +40,10 @@
## Период и список
Без фильтра период начинается сегодня в UTC и заканчивается через 30 дней
после начала, обе даты включены. Поля «С» и «По» позволяют изменить период:
«Применить» сохраняет выбранные календарные даты в URL и запрашивает результат,
«Сбросить» возвращает период по умолчанию. Обзор счёта сохраняет прогноз
на текущую дату и следующие 30 дней.
после начала, обе даты включены. `from` и `to` принимают только строгие даты
`YYYY-MM-DD`; без `from` используется текущая дата UTC, без `to` — `from + 30`
календарных дней. Поля «С» и «По» сохраняют выбранные календарные даты в URL,
а «Сбросить» возвращает период по умолчанию.
События упорядочены по календарной дате. У каждой строки видны тип,
инструмент, дата и доступная сумма в исходной валюте. Список не имеет
@@ -52,10 +52,13 @@
отсутствия всех будущих выплат. Инструмент без поддерживаемых данных
не получает искусственную строку «нет данных».
API принимает необязательные `from` и `to` в формате `YYYY-MM-DD` для
отдельного и общего счёта. Без `from` используется сегодня в UTC,
без `to` — 30 дней после начала. Неверный формат или несуществующая дата
дают `400`; обратный период — `400 INVALID_EVENTS_PERIOD`.
Сохранённый forecast сохраняет свой `calculatedAt` и исходное включительное
окно. GET для отдельного счёта или `all` возвращает только пересечение этого
окна и запрошенного UTC-периода, не меняя ни `calculatedAt`, ни исходное окно.
Пустое пересечение или отсутствие событий в пересечении — успешный пустой
список с теми же metadata; это не отсутствие forecast. Неверный формат или
несуществующая дата дают `400`; обратный период — `400 INVALID_EVENTS_PERIOD`
без замены периода и без запуска личной работы.
Фильтрация на сервере предшествует сортировке и вычислению
`incomeTotalsByCurrency`, включающего только купоны и дивиденды.
Итоги остаются в ответе API; полный экран показывает список без общего итога.
@@ -63,26 +66,30 @@ API принимает необязательные `from` и `to` в форма
## Получение и отказы
Запрос требует сессии, подключения и локально подтверждённого membership.
Прогноз строится из личного сохранённого portfolio и общих календарей: T-Bank для
дивидендов, MOEX для bond events. Отдельного синхронного получения portfolio
нет. Личные оценки сохраняются отдельно от общих календарей.
Он читает сохранённый forecast и не запускает личную синхронизацию. Часовой
обход строит forecast из полного личного portfolio и общих календарей: T-Bank
для дивидендов, MOEX для bond events. Личные оценки сохраняются отдельно от
общих календарей.
Последний полный forecast привязан к scope, периоду и membership.
Если новый portfolio требует ещё недоступного календаря, прежний полный
прогноз и его source times остаются, в том числе после рестарта. Новый
полный результат заменяет его атомарно. Без fallback показывается
missing/partial, а не подтверждённое отсутствие выплат. Другой период или
изменившийся membership не получают старый прогноз под новым названием.
Source failure сообщается в metadata и не изменяет успешное время.
Последний полный forecast привязан к scope, исходному окну и membership. Если
часовой обход не может получить полный новый forecast, прежний полный прогноз,
его `calculatedAt` и исходное окно остаются читаемыми, в том числе после
рестарта; `meta.lastAttempt` отдельно сообщает об ошибке обновления. Без
полного forecast `data: null` и metadata обозначает initial loading либо
временную недоступность, а не подтверждённое отсутствие выплат. В режиме `all`
результат complete только при полном вкладе каждого включённого счёта. Другой
scope или изменившийся membership не получают старый forecast под новым
названием.
Успешный ответ MOEX без запрошенного блока означает отсутствие поддерживаемых
событий этого источника; это отличается от transport failure и повреждённого
формата ответа.
При первом открытии показан каркас заголовка и строк, без интерактивных
заглушек. Пустой ответ сохраняет возможность изменить период.
При обычном фоновом обновлении уже полученные данные остаются на экране,
ошибка получает предупреждение и повторную попытку. Без выбранного счёта
запрос не выполняется. Смена сессии и подключения следует
При первом открытии без complete forecast показан каркас заголовка и строк,
без интерактивных заглушек. Пустой успешный ответ сохраняет возможность
изменить период. При failed HTTP reread уже полученный Client Cached Snapshot
остаётся на экране; это отличается от server-side failed hourly attempt.
Повторная попытка перечитывает только HTTP-ответ. Без выбранного счёта запрос
не выполняется. Смена сессии и подключения следует
[общим правилам финансовых данных](../../architecture/cross-cutting/data-freshness.md).
Внешние границы объясняют интеграции [T-Bank](../../integrations/tbank.md)
+32 -31
View File
@@ -1,46 +1,47 @@
# Загрузка портфеля
Экран `/accounts/:accountId` читает последний полный snapshot из SQLite
после проверки сессии, подключения и локального membership. Если список
счетов ещё неизвестен, сервер сообщает о загрузке доступа без выдачи личных
данных неизвестного ID. Известный недоступный счёт возвращает `404`.
Экран `/accounts/:accountId` читает последний полный snapshot из SQLite после
проверки сессии, подключения и локального membership. Если список счетов ещё
неизвестен, сервер сообщает о загрузке доступа без выдачи личных данных
неизвестного ID. Известный недоступный счёт возвращает `404`.
## Основной обмен
Обычный GET возвращает локальный envelope. Missing/stale зависимости
запрашиваются в фоне; чтение не ждёт T-Bank. Для нового полного snapshot
нужны оба финансовых ответа `GetPortfolio` и `GetPositions`. Суммы и позиции
публикуются вместе; metadata дополняет представление независимо, с доступным
UID/FIGI вместо имени до её загрузки.
Обычный GET и retry возвращают read-only локальный `{ data, meta }` envelope:
они не ждут и не вызывают T-Bank и не предлагают ручную синхронизацию. Часовой
обход текущего подключения обновляет Portfolio независимо от экрана. Для нового
полного snapshot ему нужны оба финансовых ответа `GetPortfolio` и
`GetPositions`; суммы и позиции публикуются вместе. Metadata инструмента
дополняет представление независимо, с доступным UID/FIGI вместо имени до её
онлайн-загрузки.
Свежесть portfolio — 60 секунд. Истечение срока не удаляет snapshot и не
создаёт таймер. «Обновить» на обзоре перечитывает зависимости текущего экрана:
membership, portfolio, показанные операции, доход и будущие события.
Секции могут быть готовы независимо. Подробнее —
[свежесть](../../../architecture/cross-cutting/data-freshness.md).
Открытый экран выполняет локальное перечитывание не чаще одного раза в
30 минут; retry также повторяет только HTTP GET. `data: null` означает, что
полного snapshot ещё нет, а не нулевой портфель. Пустой подтверждённый portfolio
остаётся available complete result. Секции могут быть готовы независимо.
Подробнее — [свежесть](../../../architecture/cross-cutting/data-freshness.md).
## Границы доступа
Публикация проверяет connection revision и attempt в той же транзакции.
Замена или удаление подключения не допускает позднюю запись прежней работы.
Frontend очищает недоступный personal view и отклоняет запоздалые ответы.
В режиме [«Все счета»](../all-accounts.md#полнота-свежесть-и-доступ) состав
accounts и snapshots читается согласованно, но их source times могут различаться.
Публикация проверяет connection revision и attempt в той же транзакции. Замена
или удаление подключения не допускает позднюю запись прежней работы. Frontend
очищает недоступный personal view и отклоняет запоздалые ответы. В режиме
[«Все счета»](../all-accounts.md#полнота-свежесть-и-доступ) состав accounts и
snapshots читается согласованно, но их source times могут различаться.
## Ошибки и результат для пользователя
Нет подключения — `409 TBANK_NOT_CONNECTED`, известный отказ токена —
`400 INVALID_TBANK_TOKEN`, недоступный счёт — `404`. Они не маскируются
запасным snapshot. Transient source failure оставляет прежний полный портфель
и его исходное время с безопасным предупреждением. При отсутствии snapshot
показывается missing/failed, без нулевых итогов. `503` означает ошибку
обслуживания HTTP-запроса, а не принятой фоновой работы.
запасным snapshot. Временная ошибка часового обхода оставляет прежний полный
portfolio и его исходное `lastSuccessfulAt`; `meta.lastAttempt` сообщает о
failed или partial попытке отдельно. `Portfolio.isStale` сообщает возраст
snapshot, а Client Cached Snapshot и ошибка браузерного HTTP-перечитывания
имеют независимый смысл. При отсутствии полного snapshot `data: null` и
metadata обозначает initial loading либо временную недоступность, без нулевых
итогов. `503` означает ошибку обслуживания самого HTTP-запроса, а не
завершившуюся фоновую работу.
Observer запрашивает статус известной работы, затем `sync=observe` читает
изменившийся ресурс без запуска синхронизации. При уходе и terminal outcome
наблюдение прекращается. Повторное открытие может запросить недостающее;
после рестарта сохранённый snapshot доступен сразу.
Денежные правила находятся в [справочнике](../data-reference.md),
проверка расхождения — в [диагностике](../how-to/investigate-discrepancy.md),
RPC/лимиты — в [интеграции T-Bank](../../../integrations/tbank.md).
Денежные правила находятся в [справочнике](../data-reference.md), проверка
расхождения — в [диагностике](../how-to/investigate-discrepancy.md), RPC/лимиты
— в [интеграции T-Bank](../../../integrations/tbank.md).