Files
specs/openspec/changes/unify-income-payment-cards/system-analysis/analysis.md
T
ksv741 c6f369c2d1
Conventional commits / commits (pull_request) Successful in 13s
Specs security / security (pull_request) Successful in 8s
Specs verify / verify (pull_request) Successful in 10s
spec: add unify-income-payment-cards change (WealthLedger/main#33)
2026-10-13 17:46:31 +03:00

124 lines
11 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.
# 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 при сохранении нормативных
различий денежного и календарного смысла.