# Финальный HTML Parity брокерского overview — план реализации > **Для агентных исполнителей:** ОБЯЗАТЕЛЬНЫЙ SUB-SKILL: использовать > `superpowers:subagent-driven-development` (предпочтительно) или `superpowers:executing-plans` для > пошагового выполнения. Шаги ведутся чекбоксами `- [ ]`. **Цель:** привести `/broker/:accountId` к финальному HTML-эталону `docs/research/frontend-overview-redesign/example.html` без изменения URL-структуры счёта. **Архитектура:** backend расширяет существующий broker read API минимальными агрегатами и историей стоимости. Frontend остаётся в FSD-границах `entities/broker-*`, `widgets/broker-dashboard`, `widgets/broker-account-layout`; dashboard-композиция меняется с промежуточной версии на финальную HTML parity структуру. **Технологии:** NestJS, Prisma/T-Bank broker operations read path, Swagger/OpenAPI codegen, React 18, TanStack Query, TanStack Router, MUI + `@moex-vibe/design-system`, Vitest, Testing Library. --- ## Canonical Research Source - Использовать как visual source of truth: `docs/research/frontend-overview-redesign/example.html`. - Не использовать как source of truth: `docs/research/2026-06-27-broker-account-redesign.html`, пока файл не синхронизирован с финальным макетом. - Production UI не переносит demo-control `Данные / Загрузка`; этот control нужен только HTML-макету. ## Файлы ### Backend - Modify: `apps/backend/src/modules/tbank/dto/broker-analytics-response.dto.ts` — добавить `totalFees`, `totalTaxesPaid`. - Create: `apps/backend/src/modules/tbank/dto/broker-portfolio-history-response.dto.ts` — DTO для 6-месячной истории стоимости. - Modify: `apps/backend/src/modules/tbank/dto/broker-envelope.dto.ts` — envelope для history endpoint. - Modify: `apps/backend/src/modules/tbank/dto/broker-operation-query.dto.ts` — query `categories`. - Modify: `apps/backend/src/modules/tbank/services/broker-analytics.service.ts` — агрегировать fee/tax. - Create: `apps/backend/src/modules/tbank/services/broker-portfolio-history.service.ts` — read-model истории стоимости. - Modify: `apps/backend/src/modules/tbank/services/broker-operations.service.ts` — применять category-фильтр до ответа. - Modify: `apps/backend/src/modules/tbank/tbank.controller.ts` — endpoint portfolio history. - Modify: backend tests рядом с изменёнными сервисами/controller. ### Frontend data - Modify: `apps/frontend/src/shared/api/index.ts` — экспорт нового `BrokerPortfolioHistory`. - Create: `apps/frontend/src/entities/broker-account/api/brokerPortfolioHistoryApi.ts`. - Create: `apps/frontend/src/entities/broker-account/model/useBrokerPortfolioHistory.ts`. - Modify: `apps/frontend/src/entities/broker-account/index.ts` — экспорт hook/API. - Modify: `apps/frontend/src/entities/broker-operation/api/brokerOperationApi.ts` — query `categories`. ### Frontend UI - Modify: `apps/frontend/src/widgets/broker-account-layout/ui/BrokerAccountLayout.tsx` — title yield рядом с заголовком счёта, без page-header skeleton. - Modify: `apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.tsx` — финальный порядок блоков и источники данных. - Replace/Remove: `BrokerDashboardHero.tsx` из overview-композиции; файл можно оставить только если больше используется в тестах/экспортах, но в `/broker/:accountId` он не рендерится. - Create: `apps/frontend/src/widgets/broker-dashboard/ui/BrokerPortfolioHistoryCard.tsx`. - Modify: `BrokerDashboardAnalyticsCard.tsx`, `BrokerDashboardAllocationCard.tsx`, `BrokerDashboardEventsCard.tsx`, `BrokerDashboardSkeleton.tsx`. - Modify/Create helpers в `apps/frontend/src/widgets/broker-dashboard/lib/` для chart points, latest event rows, analytics display и visual tones. - Modify: `apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.test.tsx` и helper unit tests. ### Docs - Modify: `docs/features/broker-account-overview-html-parity/tasks.md` по факту выполнения. - Не переписывать `docs/features/broker-dashboard-redesign/*`; старая фича остаётся историей промежуточной итерации. ## Data Contracts ### Analytics `BrokerAnalyticsDto` расширяется: ```ts totalFees: number totalTaxesPaid: number ``` Расчёт: - `totalFees` = сумма absolute payment values executed операций категории `fee`; - `totalTaxesPaid` = сумма absolute payment values executed операций категории `tax`; - значения возвращаются как положительные агрегаты; - frontend отображает их со знаком минус и negative tone. ### Portfolio History Endpoint: ```text GET /api/v1/broker/accounts/:accountId/portfolio/history?months=6 ``` Response data: ```ts type BrokerPortfolioHistoryData = { accountId: string points: Array<{ month: string label: string value: BrokerMoneyDto }> asOf: string } ``` Правила v1: - `months` по умолчанию 6, допустимый диапазон 2-12; - `points.length === months`; - `month` в формате `YYYY-MM`; - `label` — короткое русское имя месяца; - последняя точка равна текущей `portfolio.totals.portfolio`; - предыдущие точки могут быть estimated read-model из текущей стоимости и executed операций за период; - контракт должен позволять позже заменить estimated calculation на persisted snapshots. ### Operation Categories `BrokerOperationQueryDto` получает: ```ts categories?: string ``` Правила: - comma-separated значения из `trade,income,tax,fee,transfer,other`; - неизвестные категории игнорировать или валидировать с `400`; выбрать один вариант и покрыть тестом; - filtering выполняется до формирования page response; - overview `Последние события` запрашивает `categories=income,tax,fee`, `state=OPERATION_STATE_EXECUTED`, `limit=7`. ## Implementation Tasks ### Task 1: Docs and research alignment **Files:** - `docs/features/broker-account-overview-html-parity/spec.md` - `docs/features/broker-account-overview-html-parity/plan.md` - `docs/features/broker-account-overview-html-parity/tasks.md` - Проверить, что docs ссылаются на `docs/research/frontend-overview-redesign/example.html`. - Проверить, что docs явно запрещают использовать старый dated HTML как canonical reference. - Зафиксировать финальный порядок блоков и отсутствие production demo-toggle. ### Task 2: Backend analytics contract **Files:** - `apps/backend/src/modules/tbank/dto/broker-analytics-response.dto.ts` - `apps/backend/src/modules/tbank/services/broker-analytics.service.ts` - `apps/backend/src/modules/tbank/services/broker-analytics.service.spec.ts` - `apps/backend/src/modules/tbank/tbank.controller.spec.ts` - Добавить `totalFees`, `totalTaxesPaid` в DTO и тестовый response. - Расширить analytics service наборами fee/tax типов через существующую категоризацию операций. - Считать fee/tax только по executed операциям с `payment`. - Возвращать округление до копеек аналогично текущим analytics агрегатам. ### Task 3: Backend portfolio history endpoint **Files:** - `apps/backend/src/modules/tbank/dto/broker-portfolio-history-response.dto.ts` - `apps/backend/src/modules/tbank/dto/broker-envelope.dto.ts` - `apps/backend/src/modules/tbank/services/broker-portfolio-history.service.ts` - `apps/backend/src/modules/tbank/tbank.controller.ts` - `apps/backend/src/modules/tbank/tbank.controller.spec.ts` - Добавить DTO для history point и envelope. - Добавить service, который проверяет account access через `BrokerAccountsService`. - Получить текущую стоимость через existing portfolio service или общий read path без дублирования T-Bank вызовов сверх необходимого. - Вернуть 6 monthly points для default query. - Покрыть default months, invalid account и shape response тестами. ### Task 4: Backend operation category filtering **Files:** - `apps/backend/src/modules/tbank/dto/broker-operation-query.dto.ts` - `apps/backend/src/modules/tbank/services/broker-operations.service.ts` - `apps/backend/src/modules/tbank/services/broker-operations.service.spec.ts` - Добавить `categories` query. - Применить category filtering к mapped operations page перед отдачей response. - Если T-Bank page может содержать меньше 7 подходящих операций после фильтрации, documented v1 поведение: endpoint возвращает подходящие операции из текущей fetched page; full backfill pagination не требуется. - Покрыть `categories=income,tax,fee` и неизвестную категорию тестом. ### Task 5: OpenAPI and frontend generated types **Files:** - `apps/frontend/src/shared/api/types.ts` - `apps/frontend/src/shared/api/index.ts` - Запустить backend dev server. - Выполнить `npm run codegen -w apps/frontend`. - Не редактировать generated `types.ts` вручную. - Экспортировать новые frontend aliases из `shared/api/index.ts`. - Проверить, что generated schemas содержат `totalFees`, `totalTaxesPaid`, `BrokerPortfolioHistoryDataDto`. ### Task 6: Frontend data hooks **Files:** - `apps/frontend/src/entities/broker-account/api/brokerPortfolioHistoryApi.ts` - `apps/frontend/src/entities/broker-account/model/useBrokerPortfolioHistory.ts` - `apps/frontend/src/entities/broker-account/index.ts` - `apps/frontend/src/entities/broker-operation/api/brokerOperationApi.ts` - Добавить `getBrokerPortfolioHistory(accountId, { months })`. - Добавить `useBrokerPortfolioHistory(accountId, { months: 6 })` с query key `['broker', 'portfolio-history', accountId, months]`. - Добавить `categories` в `BrokerOperationQuery`. - Не менять существующие hooks detailed вкладок. ### Task 7: Page title yield **Files:** - `apps/frontend/src/widgets/broker-account-layout/ui/BrokerAccountLayout.tsx` - `apps/frontend/src/pages/broker-account/ui/BrokerAccountOverviewPage.tsx` - `apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.tsx` - Перенести compact yield UI рядом с `Брокерский счёт`. - Убрать отдельный hero KPI из overview. - Не показывать page-title skeleton в loading state. - Сохранить доступность: доходность имеет `aria-label="Доходность счёта"` или эквивалент. ### Task 8: Portfolio history card **Files:** - `apps/frontend/src/widgets/broker-dashboard/ui/BrokerPortfolioHistoryCard.tsx` - `apps/frontend/src/widgets/broker-dashboard/lib/dashboardPortfolioHistory.ts` - `apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.tsx` - `apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardSkeleton.tsx` - Создать карточку `Стоимость портфеля за 6 месяцев`. - Нарисовать SVG line/area chart без visible point markers. - Использовать 6 backend points и подписи месяцев из response. - Сделать loading chart indicator без skeleton месяцев. - Обеспечить одинаковую min-height loaded/loading. - Первая и последняя точки графика должны совпадать с краями области. ### Task 9: Analytics card parity **Files:** - `apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardAnalyticsCard.tsx` - `apps/frontend/src/widgets/broker-dashboard/lib/dashboardVisual.ts` - `apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.test.tsx` - Summary row: `Стоимость портфеля`, `Всего доходов`. - Detail grid: `Пополнения`, `Выводы`, `Дивиденды`, `Купоны`, `Комиссия`, `Уплаченные налоги`. - Удалить `Нетто` и `Всего получено` из overview-card. - Отображать `totalFees` и `totalTaxesPaid` как negative UI amounts. - Сохранить skeleton геометрию 2 + 6 карточек. ### Task 10: Allocation card parity **Files:** - `apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardAllocationCard.tsx` - `apps/frontend/src/entities/broker-position/model/brokerAllocation.ts` - Переименовать карточку в `Структура`. - Убрать subtitle `Структура портфеля`. - Показать итоговую стоимость под заголовком. - Отобразить только строки `Акции`, `Облигации`, `Деньги` для overview parity. - Сохранить корректное поведение для отсутствующих/нулевых значений. ### Task 11: Latest events card parity **Files:** - `apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardEventsCard.tsx` - `apps/frontend/src/widgets/broker-dashboard/lib/dashboardEvents.ts` - `apps/frontend/src/widgets/broker-dashboard/lib/dashboardVisual.ts` - `apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.tsx` - Переключить overview source с `useBrokerEvents` на `useBrokerOperations` с `categories=income,tax,fee`, `limit=7`. - Убрать filters toolbar, count badge, footer summary и колонку `Статус`. - Переименовать карточку в `Последние события`. - Отсортировать rows новые → старые. - Инструмент: название сверху жирным, ticker/ISIN снизу серым. - Тип: бейдж `Дивиденд`, `Купон`, `Погашение`, `Налог`, `Комиссия`. - Налоговые/комиссионные/отрицательные операции отображать красным. ### Task 12: Tests, build, visual QA **Files:** - `apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.test.tsx` - backend specs из предыдущих задач - `docs/features/broker-account-overview-html-parity/tasks.md` - Backend targeted tests: `npm run test -w apps/backend -- src/modules/tbank/services/broker-analytics.service.spec.ts src/modules/tbank/services/broker-operations.service.spec.ts src/modules/tbank/tbank.controller.spec.ts` - Frontend targeted tests: `npm run test -w apps/frontend -- --run src/widgets/broker-dashboard` - Full checks: `npm run test:frontend` `npm run lint -w apps/frontend` `npm run build:frontend` - Visual QA: desktop `/broker/:accountId`; mobile viewport `390x844`; compare against `docs/research/frontend-overview-redesign/example.html`. - Update `tasks.md` statuses and notes after verification. ## Risks and Decisions - History chart v1 uses estimated read-model; exact historical market value requires future snapshots. - Category filtering after one fetched T-Bank page may underfill latest events; acceptable for v1 unless testing shows too many empty overview rows. - The HTML mock uses static values. React must match structure and visual behavior, not literal amounts. - `Последние события` is intentionally based on executed operations, not calendar events, because the final HTML shows already happened cashflow rows and removes status/forecast semantics. ## Verification Matrix - Spec requirements map to tasks 2-11. - Backend API requirements map to tasks 2-5. - Frontend order and visual parity map to tasks 7-11. - Loading stability and mobile overflow are verified in task 12.