Files
ksv741 678a671d23 feat(portfolio-view): sync delta spec and archive change
- Remove old combined requirement, add two focused requirements:
  'Состояния и ошибки Portfolio на клиенте' and
  'Представление карточек позиций на клиенте'
- Archive extend-instrument-logo-to-bonds change
2026-08-25 09:48:21 +03:00

7.6 KiB

extend-instrument-logo-to-bonds — Design

Context

Данные уже готовы: logoName приходит в PortfolioPositionDto для позиций любого типа (passthrough из T-Bank metadata, без персистенции), фронтенд строит CDN-URL через instrumentLogoUrl и рендерит логотип компонентом PositionLogo (40px, фолбэк первой буквой через onError). Ограничение «только акции» существует в одном месте представления страницы счёта.

Осложнение: локальный проп stock на PositionSection/PositionCard управляет сразу тремя аспектами — одноколоночной раскладкой grid, рендером логотипа и форматом абсолютного дохода (знаковое значение против текстовой подписи). Паритет облигаций означает, что все три аспекта применяются к секции BOND целиком; менять их по отдельности не нужно.

Ограничения репозитория: FSD-границы и public API (dependency-cruiser, Knip), только typed client поверх generated OpenAPI, i18n через локали, gate npm ci && npm run verify под Node 22.

Goals / Non-Goals

Goals:

  • Секции BOND получают полное представление плиток STOCK: одна карточка в ряду, визуальный логотип с буква-фолбэком, знаковый доход без подписи.
  • Минимальный диф в слое представления страницы счёта; переиспользование существующих instrumentLogoUrl и PositionLogo без изменений.
  • Тесты, зеркалирующие существующие сценарии акций для облигаций.

Non-Goals:

  • Логотипы для общей секции иных типов (фондов, валют и т.д.) — гейт остаётся allowlist по типам секций.
  • Изменения backend, API-контракта, generated types и OpenAPI snapshot.
  • Экстракция PositionLogo/instrumentLogoUrl в entities ради переиспользования — потребителя по-прежнему один экран.
  • Логотипы на странице upcoming events; понятие «эмитент» в модели.

Decisions

D1. Разъединить смысл флага, сохранив один проп. Проп stock переименовывается в презентационный термин (например, wide), отражающий «широкая плитка во всю строку + логотип + знаковый доход». Секции STOCK и BOND передают его, общая секция иных типов — нет. Alternative: два независимых пропа (onePerRow, withLogo). Отклонено: сегодня они всегда движутся вместе; разъединять, пока не появился тип, которому нужен только один аспект, — спекуляция.

D2. Логотип без изменений. PositionLogo и instrumentLogoUrl реиспользуются как есть, включая key={logoSrc ?? "no-logo"} для сброса failed-state между карточками и CDN-размер 160 для 40px аватара. Новых настроек размера/радиуса не вводится.

D3. Формат доходности следует за флагом. Знаковый формат без подписи применяется к STOCK и BOND, текстовая подпись остаётся только у секции иных типов — как прямое следствие D1, без отдельной ветки по типу.

D4. Тесты повторяют паттерны акций. В тестах страницы счёта добавляются случаи: облигация с logoName рендерит изображение с брендовым URL; облигация без logoName — буква-фолбэк без img; знаковый доход облигации без текстовой подписи; одноколоночная секция облигаций. Существующие тесты секции иных типов служат регрессионной сеткой неизменённого пути.

Delivery Map

Area Status Architectural outcome or N/A reason
frontend affected Представление страницы счёта: единый презентационный флаг для секций STOCK и BOND; логотип и знаковый доход на карточках облигаций; обновлённые unit/component тесты
backend N/A logoName уже возвращается для всех типов позиций; контракт Portfolio и зависимости не меняются
specs affected Утверждённые Delta Specs синхронизируются в главную спеку portfolio-view при archive после реализации
docs affected As-built: docs/features/portfolio-view.md отражает паритет облигаций; глоссарий не меняется (термин Instrument Logo уже типо-агностичен)

Contract Gate Decision

Gate Status Reason
runtime-openapi N/A API-контракт не меняется ни на одной стороне: backend вне scope, generated types не обновляются

Risks / Trade-offs

  • Редкие бренды у облигаций. Брендовые данные T-Bank для облигаций встречаются реже, чем у акций, поэтому буква-фолбэк будет видна чаще. Mitigation: фолбэк — штатное, уже протестированное поведение; спецификация явно допускает оба исхода.
  • Связанность трёх аспектов представления. Общий флаг означает: нельзя включить логотип, не сделав плитку широкой. Осознанный trade-off ради минимального дифа; точка разъединения обозначена в D1.
  • Визуальная регрессия других секций. Путь секции иных типов не меняется (ветка по умолчанию того же флага); риск ограничен одним файлом представления и покрыт существующими тестами.

Migration Plan

Поставка одним изменением frontend без флагов миграции: изменение чисто презентационное, состояние и данные не затрагиваются. Rollback — revert коммита frontend. Порядок: имплементация → npm ci && npm run verify → semantic verification против Proposal/Delta Specs/Design → as-built docs → workspace gate verify-workspace-change.sh → archive.