spec: unify income payment cards and drop period comparisons (WealthLedger/main#33)
11 KiB
System Analysis
Requirement Coverage
| Нормативная область | Поток и контракт |
|---|---|
brokerage-account-income-analytics: удаление Period comparisons preserve calendar and currency meaning, выбранный период, полнота, читаемые итоги, отсутствие прогноза |
income-period.mmd, target schema |
brokerage-account-income-analytics: точные карточки выплат |
payment-sources.mmd, существующая форма entries |
brokerage-account-ledger: журнал, недавние операции и история инструмента |
payment-sources.mmd, существующий ответ операций |
brokerage-account-upcoming-events: полный список и превью |
payment-sources.mmd, существующий ответ событий |
instrument-income-schedules: будущее, прошлое, неопределённая дата/сумма |
payment-sources.mmd, существующие ответы календарей |
Systems and Responsibilities
- Пользователь выбирает применённый период и отличает исполненные выплаты от возможных поступлений и условий выпуска.
- Frontend хранит применённые даты в URL, показывает только финансовые значения их собственного источника и использует один предметный компонент для купонов/дивидендов всех трёх режимов. Он не выводит исполнение из календаря.
- Backend проверяет доступ, период и покрытие операций; формирует точные source-currency итоги и записи выбранного периода. Для income-analytics не запрашивает предыдущий или годовой период ради сравнения.
- Сохранённые операции T-Bank остаются источником фактических выплат; прогноз основан на позиции, календарь бумаги — на опубликованных условиях T-Bank/MOEX. Они не становятся взаимозаменяемыми при объединении представления.
Interaction Flows
- Доход выбранного периода: доступ, полнота, успешный/пустой результат и неполное покрытие без запросов сравнения.
- Три источника карточки выплаты: подтверждённая операция, будущий прогноз и событие календаря; остальные типы сохраняют существующее представление.
Contracts
| Производитель → потребитель | Транспорт / операция | Целевой контракт |
|---|---|---|
| Backend → frontend | GET /api/v1/brokerage-accounts/{accountId}/income-analytics, GET /api/v1/brokerage-accounts/all/income-analytics, application/json 200 |
JSON Schema ограничений ответа поверх текущего 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; для dividenddateKind=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 при сохранении нормативных различий денежного и календарного смысла.