Files
specs/openspec/changes/unify-income-payment-cards/design.md
T
codex-bot 6c858a8858
Specs security / security (push) Successful in 9s
Specs verify / verify (push) Successful in 12s
spec: unify income payment cards and drop period comparisons (WealthLedger/main#33) (#37)
spec: unify income payment cards and drop period comparisons (WealthLedger/main#33)
2026-10-13 18:16:27 +03:00

16 KiB
Raw Blame History

Engineering Design

Context and Constraints

Аналитика дохода использует выбранный период, отдельные previous/year диапазоны и публикует их через DTO и metadata; план синхронизации также запрашивает эти диапазоны. Frontend строит блоки сравнений из ответа и показывает исполненные операции через LedgerEntryRow. Полный журнал, недавние записи и личная история бумаги используют этот же ряд; прогноз использует BrokerageEventCard; календарные карточки акции и облигации реализованы внутри соответствующих страниц. Все уже используют EntryCard либо существующие Mantine primitives, но это не один предметный компонент выплаты.

Граница реализации — утверждённые Delta Specs и System Analysis, включая целевой контракт. Доступ, деньги, полнота периода, порядок записей и формы остальных API сохраняются. Клиент получает публичный OpenAPI artifact явно.

Technical Goals / Non-Goals

  • Исключить сравнения из чтения, синхронизации, API и UI без изменения итогов выбранного периода.
  • Один компонент для купона/дивиденда в исполненной операции, прогнозе и графике бумаги; режим определяется источником, а не знаком или датой.
  • Не преобразовывать график в личный доход и не объединять чужие деньги, прогноз и сумму на бумагу. Не удалять buckets или instruments из API.

Implementation Impact Map

main

N/A: нет изменений workspace, Compose, release orchestration или конфигурации.

frontend

Affected: страница дохода и её display model, компонент записи операций, компонент будущего события, календарные карточки акций/облигаций, локальная копия публичного OpenAPI и генерируемые типы. Владельцы экранов сохраняют свои списки, фильтры и локальные состояния.

backend

Affected: расчёт и планирование income периода, чтение операций для income-analytics, DTO ответа и план фонового получения выбранного интервала. Источник исполненных операций и агрегация selected остаются владельцами денег.

qa

N/A: самостоятельного репозитория QA нет; системные проверки описывает qa-analysis.md без введения несуществующей инфраструктуры.

Decisions

main

Изменения не требуются: координация ссылками на Issue/Change, без workspace автоматизации ради одного API перехода.

frontend

Один предметный PayoutCard разместить на уровне entities, доступном страницам и компонентам других slices через public export. Он использует существующий EntryCard как визуальную основу; EntryCard не становится владельцем финансовой семантики. Презентационные данные передаются явным discriminated union по происхождению executed | forecast | schedule: исполненная запись содержит signed payment и точный timestamp; прогноз — nullable projected amount, dateKind и дату; график — nullable per-security сумму, отдельную nullable оценку и доступные даты/параметры выпуска. Ветка графика показывает дополнительные условия купона и дивиденда без размножения карточек. У отсутствующих значений текстовый fallback, ноль форматируется отдельно от неизвестного. Не вводить один универсальный произвольный набор optional props, допускающий ложную комбинацию «исполнено + оценка».

Владельцы исходных данных адаптируют типизированный ответ непосредственно на границе использования либо через узкий mapper сущности для повторных callers: LedgerEntryRow передаёт точные купоны/дивиденды в PayoutCard, прочие операции оставляет на прежнем пути; BrokerageEventCard делает то же для coupon/dividend, сохраняя maturity/offer; страницы графиков заменяют только содержимое календарной карточки. Доход продолжает вызывать LedgerEntryRow, сохраняя wrap, HTML-список и occurrence key. Личная история инструмента сохраняет quantity/price/account details там, где они доступны. Ключи списков и порядок определяются caller, не самим компонентом.

Удалить comparison-only display model, компонент блока, подписи и стили, относящиеся только к сравнениям. Не удалять предупреждение неполного selected или сохранённого snapshot. Обновить текущие fixtures и регрессии после передачи OpenAPI; генерация типов потребителя берёт только его локальную копию artifact.

Альтернатива с одинаковым CSS для трёх существующих компонентов отвергнута: не обеспечивает фактическое переиспользование. Альтернатива с общим DTO backend отвергнута: источники и денежные смыслы различны, wire-контракт остальных API не меняется.

backend

Сократить план income-analytics до selected: сервис запрашивает один диапазон, не конструирует comparison totals/availability; план экранной синхронизации не включает предыдущий год и месяц. Сохранить независимый план current-month summary и серверный выбор точных типов купона/дивиденда. В DTO удалить previous, yearComparison, comparison DTO при отсутствии других callers; dependencies сохранить в исходной форме с единственной ролью selected. Текущий shared operations range reader использует индексированные имена resource keys для трёх периодов; после одного диапазона оставить корректную идентичность selected и убрать устаревший индексированный список. Сохраняем status/coverage/freshness и публикацию подтверждённого периода. Дневные/ недельные/месячные buckets остаются, так как их удаление не согласовано.

Не вводить миграцию БД: убираются чтения и поля ответа, а не сохранённые операции или подтверждённое покрытие. Никакой пересборки прошлого дохода.

Cross-cutting Implementation

Существующая проверка пользователя/счёта и очистка личного query cache при смене подключения остаются на местах. Изменение количества планируемых диапазонов не добавляет work и не меняет поведение hourly attempt для других экранов. Существующие request ID, metadata попытки и статусы дают достаточную диагностику; новых событий или полей логирования не требуется. Пересчёта денег, валютной конвертации и нового кэша нет.

Data / Storage Changes

N/A: Prisma/SQLite schema и исторические записи не меняются; выбранное покрытие продолжает подтверждаться до публикации окончательного результата.

Contract Implementation

Backend обновляет DTO и исполняемый generated OpenAPI. Для обоих income-analytics маршрутов проверить отсутствие previous/yearComparison и наличие только selected в dependency role при сохранении nullable data, остальных полей и Problem Details. Сверить обе схемы 200 с target JSON Schema семантически, а не только с TypeScript shape; существующую проверку parity runtime OpenAPI также сохранить. Передать созданный backend artifact frontend явно; frontend обновляет snapshot и generated types штатной локальной процедурой, без чтения соседнего checkout в сборке. Прежний клиент, требующий удалённых полей, несовместим.

Developer Verification Strategy

Backend: адресные проверки планирования только выбранного интервала, чтения income summary/analytics, точных signed сумм и недоступного selected; проверка HTTP контракта и OpenAPI parity. Frontend: наблюдаемое отсутствие блоков сравнений в loaded/loading/error/empty; сохранение period URL, порядка/повторов выплат и корректные режимы общего компонента на всех потребителях. После локальных узких проверок выполнить обязательный verify каждого изменённого implementation repo. Это developer-owned проверки; системная матрица отдельно в qa-analysis.md.

UI/UX Package

Applicability and scope: changed UI; пакет полностью inline, новых изображений и assets не требуется. Один approval Design относится к этой ревизии и приведённому ниже точному источнику переиспользования.

Package revision: 1, change unify-income-payment-cards.

Screens, states and interactions: доход — фильтр, итоги, плоский список исполненных выплат, без сравнений; прогноз на странице событий/превью — пометка «Прогноз», неизвестная сумма отлична от нуля, дата реестра помечена; графики акции/облигации — «Событие по графику», разные подписи per-share/ per-bond и личной оценки. В истории операций карточка сохраняет описание, дату и доступную identity инструмента, signed Money и детали там, где были. Loaded, empty, loading, error и обновление старого snapshot сохраняют текущие локальные границы экранов. Оферта, погашение, сделка и налог не получают режим выплаты. Компонент сам не переключает состояние и не инициирует запрос.

Responsive behavior: однотактный проход по карточкам без горизонтального overflow при узкой ширине и длинных значениях; labels, значения и статусы читаются текстом и клавиатурой, цвет остаётся дополнительным признаком. Сохраняются доступные имена региона и фокус элементов фильтра.

Reused source and differences: immutable locator wealth-ledger-specs:openspec/changes/archive/2026-09-09-simplify-income-page/design.md (секция «Одна карточка соответствует одной выплате») — плоский income список, одна карточка на запись, signed Money и сохранение порядка. Дополнить только единым предметным presentation для прогнозов/графиков с явными подписями происхождения; не переносить прогноз внутрь income страницы. Визуальная основа реализации — существующий EntryCard; его геометрия остаётся общим стилем, а не заменой PayoutCard. Пакет целиком inline.

Risks / Trade-offs

  • Разные даты и null-поля трёх источников провоцируют неверные labels при слишком широком mapper: явные варианты данных и локальные проверки экранов важнее экономии нескольких props.
  • Для календаря бумаги нет логотипа/тикера в каждой записи: владелец страницы передаёт известную identity, не создавая новый запрос.
  • Меньше загружаемых диапазонов снижает объём работы, но отсутствие сравнения может изменить порядок фонового покрытия старых периодов; цель сохранения другой независимой истории остаётся прежней.

Migration / Rollout / Rollback

Сначала обновить backend DTO/логику и получить опубликованный OpenAPI, затем передать artifact frontend и обновить UI/типизацию; согласованно поставить две стороны breaking ответа. Не выпускать старый frontend против нового backend как поддерживаемую комбинацию. При rollback вернуть согласованную предыдущую пару backend/frontend и прежний OpenAPI snapshot; сохранённые операции и покрытие не требуют data rollback. Синхронизация canonical specs и AS-IS docs выполняется по отдельным approved tasks после реализации.

Solution Assessment

N/A: не создаётся новая инфраструктура, интеграция, storage, кэш или система аутентификации. Существующие EntryCard, owner-slices и DTO сохраняются; сопоставление альтернатив общего UI дано в решении frontend.