# System Analysis ## Requirement Coverage | Нормативная область | Поток и контракт | | --- | --- | | `brokerage-account-income-analytics`: удаление `Period comparisons preserve calendar and currency meaning`, выбранный период, полнота, читаемые итоги, отсутствие прогноза | [income-period.mmd](sequences/income-period.mmd), [target schema](contracts/income-analytics-response.schema.json) | | `brokerage-account-income-analytics`: точные карточки выплат | [payment-sources.mmd](sequences/payment-sources.mmd), существующая форма entries | | `brokerage-account-ledger`: журнал, недавние операции и история инструмента | [payment-sources.mmd](sequences/payment-sources.mmd), существующий ответ операций | | `brokerage-account-upcoming-events`: полный список и превью | [payment-sources.mmd](sequences/payment-sources.mmd), существующий ответ событий | | `instrument-income-schedules`: будущее, прошлое, неопределённая дата/сумма | [payment-sources.mmd](sequences/payment-sources.mmd), существующие ответы календарей | ## Systems and Responsibilities - Пользователь выбирает применённый период и отличает исполненные выплаты от возможных поступлений и условий выпуска. - Frontend хранит применённые даты в URL, показывает только финансовые значения их собственного источника и использует один предметный компонент для купонов/дивидендов всех трёх режимов. Он не выводит исполнение из календаря. - Backend проверяет доступ, период и покрытие операций; формирует точные source-currency итоги и записи выбранного периода. Для income-analytics не запрашивает предыдущий или годовой период ради сравнения. - Сохранённые операции T-Bank остаются источником фактических выплат; прогноз основан на позиции, календарь бумаги — на опубликованных условиях T-Bank/MOEX. Они не становятся взаимозаменяемыми при объединении представления. ## Interaction Flows - [Доход выбранного периода](sequences/income-period.mmd): доступ, полнота, успешный/пустой результат и неполное покрытие без запросов сравнения. - [Три источника карточки выплаты](sequences/payment-sources.mmd): подтверждённая операция, будущий прогноз и событие календаря; остальные типы сохраняют существующее представление. ## Contracts | Производитель → потребитель | Транспорт / операция | Целевой контракт | | --- | --- | --- | | Backend → frontend | `GET /api/v1/brokerage-accounts/{accountId}/income-analytics`, `GET /api/v1/brokerage-accounts/all/income-analytics`, `application/json` 200 | [JSON Schema ограничений ответа](contracts/income-analytics-response.schema.json) поверх текущего backend-generated OpenAPI: убрать `data.previous`, `data.yearComparison`, comparison roles в `meta.dependencies`; оставить выбранный период и все прочие поля и ошибки в исходном смысле. | | Backend → frontend | Income summary, операции, события, календари акций/облигаций | Без изменений wire-формы; типизированные исходные данные адаптируются к общему представлению купона/дивиденда на границе UI. | Целевой schema-файл описывает *изменение* ответа и не подменяет полную схему неизменённых полей; при согласовании используется вместе с предоставленным OpenAPI snapshot. `meta.dependencies` содержит только зависимость выбранного периода с ролью `selected`; это не новая причина загрузки другого периода. Существующие auth, invalid-period и resource errors не меняются. Отсутствуют новые операции/версии и callback-протоколы. Порядок entries и повторяющиеся ID сохраняются; повторный HTTP read не должен создавать второе зачисление. ## Data and State Semantics - `data: null` с незавершённым покрытием выбранного периода не становится нулевым доходом. Успешный полный период без qualifying entries — доступный нулевой результат. Свежесть и попытка обновления относятся к выбранному результату, не к удалённым comparison-периодам. - Купоны/дивиденды фактического дохода — точные исполненные операции с исходным знаком, валютой и timestamp; календарное событие с прошедшей датой не доказывает их наличие. - Forecast projected amount может быть `null`; для dividend `dateKind=registry` означает дату реестра, не зачисления. График хранит per-share/per-bond Money, опциональную оценку по позиции, известные даты и время источника отдельно от `payment` исполненной операции. Неизвестное не становится нулём. - Общий предметный компонент получает явный режим происхождения данных; адаптация не пересчитывает backend totals и не меняет source identity. ## Error and Recovery Semantics - Некорректный черновик остаётся на клиенте с ошибкой поля; серверный invalid period и отказ доступа сохраняют действующие ответы без fallback на другой период или чужой счёт. - Ошибка получения страницы исполненных операций не завершает покрытие выбранного периода и не публикует частичный итог как полный. Последний подтверждённый результат и его исходное время остаются независимыми от неуспеха последней попытки. - Ошибка прогноза не скрывает уже загруженный доход; отсутствие оценки, логотипа либо даты в календаре не создаёт ложного исполнения или нуля. - Поздний ответ прежнего подключения не должен восстановить личные данные нового/недоступного подключения; граница доступа сохраняется. ## Observability Semantics - Существующие status результата, `meta` полноты/попытки и request correlation позволяют отличить полный выбранный период, pending и failure. - Событие синхронизации выбранного периода не включает comparison-only dependencies; получение прошлого/годового интервала для иных самостоятельных запросов не считается сравнением дохода. - Новых аналитических событий или чувствительных атрибутов не требуется. ## Security and NFR at System Boundaries - Bearer-сессия, текущее подключение и доступ к выбранному счёту проверяются до выдачи личных операций; `all` ограничен доступными счетами. - Даты остаются включительными календарными датами Europe/Moscow, без максимальной длительности; валюты не конвертируются. Не вводится новый SLA. ## Compatibility / Migration Удаление `previous` и `yearComparison` из ответа намеренно breaking для потребителя старой формы. Backend публикует обновлённый исполняемый OpenAPI; frontend получает его как явный artifact и обновляет локальные типы прежде, чем интеграция начнёт опираться на новую форму. Строгая semantic compatibility между новым OpenAPI и target schema проверяется до поставки. При поставке backend и frontend согласуются как пара, без обещания одновременной совместимости со старым потребителем. Существующие поля buckets/instruments, запросы сводки/журнала/прогноза и их доступность не меняются. ## Durable Documentation Candidates - `docs/domains/income/overview.md`: отсутствие сравнений и загрузки чужих периодов, только полнота выбранного периода. - `docs/domains/portfolio/all-accounts.md`, `docs/adr/017-local-tbank-reads-and-background-sync.md`: проверить упоминания приоритета и смысла удалённых comparisons; ADR хранить как историческое решение, не переписывать как AS-IS. - `docs/domains/income/upcoming-events.md`, `docs/domains/instruments/stocks.md`, `docs/domains/instruments/bonds.md`, `docs/domains/operations/overview.md`: общая карточка при сохранении границы между исполнением, прогнозом и графиком. ## Open Questions Нет блокирующих вопросов в утверждённом scope. Детали визуальной композиции общего компонента остаются за Engineering Design при сохранении нормативных различий денежного и календарного смысла.