docs: add broker overview html parity spec

This commit is contained in:
Sergey Krylov 2026-06-27 19:22:54 +03:00
parent 3fdceb9438
commit c4b93f9f0c
3 changed files with 654 additions and 0 deletions

View File

@ -0,0 +1,329 @@
# Финальный 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.

View File

@ -0,0 +1,208 @@
# Финальный редизайн обзора брокерского счёта по HTML-эталону
Дата: 2026-06-27
Статус: спецификация подготовлена
Эпик: [Портфель брокера](../../epics/BrokerPortfolio.md)
## Контекст
Маршрут `/broker/:accountId` уже был переведён на dashboard-композицию в рамках
`docs/features/broker-dashboard-redesign`, но эта итерация отражает промежуточный вариант:
`Hero → События → Доходы → Аналитика доходности → Аллокация`.
После интерактивной дизайн-итерации пользователь согласовал финальный HTML-эталон в
`docs/research/frontend-overview-redesign/example.html`. Именно этот файл является canonical visual
reference для текущей фичи. Файл `docs/research/2026-06-27-broker-account-redesign.html` содержит более
раннюю версию и не должен использоваться как источник истины, пока не будет синхронизирован.
Финальный экран должен выглядеть как HTML-эталон, но работать на реальных данных приложения,
существующих FSD-границах, backend API и текущей светлой теме MoexVibe.
## Цель
Переделать обзор брокерского счёта `/broker/:accountId` так, чтобы production React-страница визуально
и поведенчески соответствовала финальному HTML-эталону:
`Заголовок счёта → Стоимость портфеля за 6 месяцев → Аналитика доходности → Структура → Последние события`.
## Пользовательский результат
Пользователь на `/broker/:accountId` может:
- сразу увидеть название счёта, текущую доходность и дневное изменение;
- увидеть график стоимости портфеля за последние 6 месяцев;
- увидеть ключевые показатели доходности, включая комиссии и уплаченные налоги;
- увидеть структуру портфеля в компактном bar-chart виде;
- увидеть последние уже произошедшие события/денежные операции по счёту;
- перейти в подробные вкладки `Акции`, `Облигации`, `Операции`, `События`, `Аналитика`.
## Область изменений
Входит в scope:
- frontend-маршрут `/broker/:accountId` и виджеты `widgets/broker-dashboard`;
- layout заголовка счёта в `widgets/broker-account-layout`;
- backend read endpoints брокерского домена, необходимые для честного отображения HTML parity;
- OpenAPI/codegen для новых или расширенных DTO;
- тесты backend/frontend и визуальная проверка desktop/mobile.
Не входит в scope:
- редизайн подробных вкладок `Акции`, `Облигации`, `Операции`, `События`, `Аналитика`;
- dark mode;
- demo-переключатель `Данные / Загрузка` из HTML-эталона;
- полноценное хранилище исторических снапшотов портфеля;
- изменение URL-структуры `/broker/:accountId/*`.
## Требования
### 1. Общая композиция
- `/broker/:accountId` остаётся overview выбранного брокерского счёта.
- Страница использует порядок блоков из HTML-эталона:
`Заголовок счёта`, `Стоимость портфеля за 6 месяцев`, `Аналитика доходности`, `Структура`,
`Последние события`.
- Отдельный hero KPI-блок удаляется из overview-композиции.
- Блок `Доходы` удаляется из overview-композиции. Подробные доходные операции остаются доступны через
вкладку `Операции`.
- Существующая навигация счёта остаётся горизонтальными вкладками над dashboard-контентом.
- На desktop и mobile блоки идут одной колонкой в одинаковом порядке.
- Production UI не содержит demo-toggle `Данные / Загрузка`.
### 2. Заголовок счёта
- Заголовок показывает название счёта или fallback `Брокерский счёт`.
- Справа от заголовка, визуально меньшим блоком, показывается доходность счёта:
`Доходность`, значение процента и supporting text `За день: ...`.
- Доходность берётся из `analytics.totalReturnPercent`, если доступна, иначе из
`portfolio.yields.expectedPercent`, иначе отображается `—`.
- Дневное изменение берётся из `portfolio.yields.daily`, иначе отображается `—`.
- Отрицательная доходность окрашивается красным, положительная зелёным, недоступная нейтральным.
- В loading-состоянии заголовок не показывает skeleton-полосы. Layout должен сохранять стабильную
высоту и не прыгать после загрузки.
### 3. Стоимость портфеля за 6 месяцев
- Первый dashboard-блок называется `Стоимость портфеля за 6 месяцев`.
- Карточка использует зелёный градиентный фон и тонкую зелёную рамку как в HTML-эталоне.
- В карточке отображаются:
- label `Текущая стоимость`;
- текущая стоимость портфеля из `portfolio.totals.portfolio`;
- плавный line/area chart по 6 месячным точкам.
- График показывает ровно 6 подписей месяцев и 6 значений, соответствующих этим месяцам.
- Первая точка линии начинается у левого края области графика, последняя — у правого края.
- Visible point markers не отображаются; линия плавная.
- Подписи месяцев не выходят за границы карточки.
- Loading-состояние графика использует chart-like indicator без skeleton-подписей месяцев.
- Высота карточки в loading и loaded состояниях должна совпадать.
### 4. Аналитика доходности
- Блок называется `Аналитика доходности`.
- Верхний summary-row содержит только:
- `Стоимость портфеля`;
- `Всего доходов`.
- Detail-grid содержит ровно:
- `Пополнения`;
- `Выводы`;
- `Дивиденды`;
- `Купоны`;
- `Комиссия`;
- `Уплаченные налоги`.
- Поля `Нетто` и `Всего получено` не отображаются в overview-карточке.
- RUB отображается как `₽`, а не `RUB`.
- Положительные финансовые значения окрашиваются зелёным, отрицательные/уменьшающие баланс —
красным.
- `Комиссия` и `Уплаченные налоги` отображаются как отрицательные UI-суммы, даже если backend хранит
агрегат абсолютным положительным числом.
- Loading-состояние использует skeleton-карточки той же геометрии, чтобы интерфейс не прыгал.
### 5. Структура
- Блок называется `Структура`.
- Под заголовком показывается итоговая стоимость портфеля.
- Под итогом отображаются горизонтальные бары:
- `Акции`;
- `Облигации`;
- `Деньги`.
- Каждая строка показывает название сектора, сумму и процент.
- Цвета соответствуют HTML-эталону: акции — синий, облигации — янтарный, деньги — фиолетовый.
- Если значение сектора отсутствует или равно нулю, строка остаётся читаемой и не ломает layout.
- Общая карточка не содержит subtitle `Структура портфеля`.
### 6. Последние события
- Блок называется `Последние события`.
- Блок показывает только уже произошедшие записи, которые меняют или отражают денежный поток счёта.
- Источник данных — executed broker operations с категориями `income`, `tax`, `fee`.
- Записи сортируются от новых к старым.
- В overview показывается не более 7 последних записей.
- Таблица содержит колонки:
- `Дата`;
- `Инструмент`;
- `Тип`;
- `Сумма`.
- Колонка `Статус` не отображается.
- Toolbar фильтров, count badge и footer summary не отображаются в overview-карточке.
- В колонке `Инструмент` название отображается сверху жирным, ticker/ISIN снизу серым.
- Для операций без названия основная строка берётся из ticker/figi/description без дублирования в subtitle.
- Тип операции отображается бейджем: `Дивиденд`, `Купон`, `Погашение`, `Налог`, `Комиссия` или
безопасный fallback.
- Всё, что уменьшает баланс, отображается красным: сумма, типовой бейдж и tone строки/значения.
- Для налоговых операций в колонке `Тип` должен быть бейдж `Налог`, а не исходный income/coupon label.
- Блок содержит ссылку `Все события` на подробную вкладку `/broker/:accountId/events` или согласованный
detailed cashflow route, если реализация выделит его отдельно.
- Ошибка загрузки последних событий не ломает остальные блоки.
### 7. Backend API
- `BrokerAnalyticsDto` расширяется полями:
- `totalFees: number`;
- `totalTaxesPaid: number`.
- `totalFees` считается из executed broker operations категории `fee`.
- `totalTaxesPaid` считается из executed broker operations категории `tax`.
- Оба агрегата возвращаются абсолютными положительными числами; frontend отвечает за знак отображения.
- Добавляется endpoint:
`GET /api/v1/broker/accounts/:accountId/portfolio/history?months=6`.
- Endpoint возвращает envelope с данными:
- `accountId: string`;
- `points: Array<{ month: string; label: string; value: BrokerMoneyDto }>`;
- `asOf: string`.
- `month` имеет формат `YYYY-MM`.
- `label` содержит короткое русское имя месяца для оси.
- `points.length` равен запрошенному `months`, по умолчанию 6.
- Для v1 допускается estimated read-model из текущей стоимости портфеля и executed operations. Shape
контракта должен позволять позже заменить расчёт на реальные snapshots без изменения frontend.
- `BrokerOperationQueryDto` расширяется фильтром `categories?: string`.
- `categories` принимает comma-separated категории из существующего набора:
`trade,income,tax,fee,transfer,other`.
- `GET /broker/accounts/:accountId/operations` применяет `categories` до пагинации/лимита, чтобы overview
не фильтровал неполную страницу на клиенте.
### 8. Загрузка, ошибки и пустые состояния
- Ошибка portfolio остаётся page-level ошибкой.
- Ошибка analytics, history или latest events отображается только внутри соответствующей карточки.
- Недоступные значения отображаются как `—`, не подменяются нулём.
- Loading-состояния должны сохранять высоты карточек и не вызывать layout shift.
- На mobile не должно быть общего горизонтального overflow. Горизонтальный scroll допустим только внутри
таблицы, если без него невозможно сохранить читаемость.
## Acceptance Criteria
- `/broker/:accountId` отображает блоки в порядке:
`Стоимость портфеля за 6 месяцев`, `Аналитика доходности`, `Структура`, `Последние события`.
- Верхняя строка страницы показывает `Брокерский счёт` и доходность рядом с ним, без отдельного hero.
- Production UI не показывает demo-toggle `Данные / Загрузка`.
- График стоимости имеет 6 подписей месяцев и 6 точек данных; линия начинается слева и заканчивается
справа.
- Loading графика не содержит skeleton-подписей месяцев и имеет ту же высоту, что loaded состояние.
- Analytics overview показывает `Комиссия` и `Уплаченные налоги`, не показывает `Нетто` и
`Всего получено`.
- `Структура` показывает итоговую стоимость и бары `Акции`, `Облигации`, `Деньги`.
- `Последние события` показывает только произошедшие записи, отсортированные новые → старые.
- Таблица `Последние события` не содержит toolbar, count badge, footer summary и колонку `Статус`.
- Операции налогов/комиссий и другие списания отображаются красным.
- Backend Swagger содержит новые analytics fields, portfolio history endpoint и `categories` query.
- Frontend generated types обновлены через codegen.
- Desktop и mobile визуально соответствуют `docs/research/frontend-overview-redesign/example.html`.

View File

@ -0,0 +1,117 @@
# Финальный редизайн брокерского overview по HTML — задачи
Дата: 2026-06-27
Статус: документация подготовлена, реализация не начата
## Документация и pre-flight
- [x] Создать `docs/features/broker-account-overview-html-parity/spec.md`.
- [x] Создать `docs/features/broker-account-overview-html-parity/plan.md`.
- [x] Создать `docs/features/broker-account-overview-html-parity/tasks.md`.
- [x] Зафиксировать canonical visual reference:
`docs/research/frontend-overview-redesign/example.html`.
- [x] Зафиксировать, что `docs/research/2026-06-27-broker-account-redesign.html` не является
source of truth для этой итерации.
- [x] Зафиксировать финальный порядок блоков:
`Заголовок счёта → Стоимость портфеля за 6 месяцев → Аналитика доходности → Структура → Последние события`.
- [x] Зафиксировать, что production UI не переносит demo-toggle `Данные / Загрузка`.
- [ ] Перед началом реализации убедиться, что работа идёт в feature branch.
- [ ] Перед началом реализации запустить baseline checks текущей ветки.
## Backend contract
- [ ] Расширить `BrokerAnalyticsDto` полями `totalFees` и `totalTaxesPaid`.
- [ ] Обновить `BrokerAnalyticsService`: считать комиссии из executed операций категории `fee`.
- [ ] Обновить `BrokerAnalyticsService`: считать уплаченные налоги из executed операций категории `tax`.
- [ ] Обновить `broker-analytics.service.spec.ts` для новых агрегатов и округления.
- [ ] Добавить DTO для `BrokerPortfolioHistoryData`.
- [ ] Добавить envelope DTO для portfolio history endpoint.
- [ ] Добавить `BrokerPortfolioHistoryService`.
- [ ] Добавить endpoint `GET /api/v1/broker/accounts/:accountId/portfolio/history?months=6`.
- [ ] Покрыть portfolio history default months и response shape тестами.
- [ ] Добавить `categories?: string` в `BrokerOperationQueryDto`.
- [ ] Обновить `BrokerOperationsService`: применять category filtering для operations response.
- [ ] Покрыть `categories=income,tax,fee` и неизвестные категории тестами.
- [ ] Обновить `TBankController` и `tbank.controller.spec.ts` под новый endpoint/DTO.
## OpenAPI и frontend data layer
- [ ] Запустить backend dev server для Swagger JSON.
- [ ] Выполнить `npm run codegen -w apps/frontend`.
- [ ] Проверить, что generated types содержат `totalFees`, `totalTaxesPaid` и portfolio history schemas.
- [ ] Экспортировать новый `BrokerPortfolioHistory` alias из `apps/frontend/src/shared/api/index.ts`.
- [ ] Добавить `getBrokerPortfolioHistory`.
- [ ] Добавить `useBrokerPortfolioHistory`.
- [ ] Добавить `categories` в frontend `BrokerOperationQuery`.
- [ ] Не редактировать `apps/frontend/src/shared/api/types.ts` вручную.
## Frontend composition
- [ ] Перестроить `BrokerDashboard` на финальный порядок блоков.
- [ ] Убрать `BrokerDashboardHero` из overview-render path.
- [ ] Перенести compact yield UI в заголовок счёта рядом с `Брокерский счёт`.
- [ ] Убедиться, что page title loading state не показывает skeleton-полосы.
- [ ] Создать `BrokerPortfolioHistoryCard`.
- [ ] Подключить `useBrokerPortfolioHistory(accountId, { months: 6 })`.
- [ ] Заменить overview `BrokerDashboardIncomeCard` на `BrokerPortfolioHistoryCard`.
- [ ] Обновить `BrokerDashboardSkeleton` под финальный порядок и стабильные высоты.
## Frontend visual parity
- [ ] Карточка `Стоимость портфеля за 6 месяцев`: зелёный градиентный фон и зелёная рамка.
- [ ] График стоимости: 6 месячных значений, 6 подписей месяцев, плавная линия без visible markers.
- [ ] График стоимости: первая точка у левого края, последняя у правого края.
- [ ] Loading графика: chart-like indicator без skeleton месяцев.
- [ ] Analytics summary: только `Стоимость портфеля` и `Всего доходов`.
- [ ] Analytics detail grid: `Пополнения`, `Выводы`, `Дивиденды`, `Купоны`, `Комиссия`,
`Уплаченные налоги`.
- [ ] Analytics overview не показывает `Нетто` и `Всего получено`.
- [ ] `Комиссия` и `Уплаченные налоги` отображаются как отрицательные UI-суммы.
- [ ] Карточка структуры называется `Структура`.
- [ ] Карточка структуры не показывает subtitle `Структура портфеля`.
- [ ] Карточка структуры показывает итоговую стоимость под заголовком.
- [ ] Карточка структуры показывает бары `Акции`, `Облигации`, `Деньги`.
- [ ] Карточка последних событий называется `Последние события`.
- [ ] Последние события используют executed operations, а не calendar events.
- [ ] Последние события отсортированы новые → старые.
- [ ] Последние события не показывают toolbar, count badge, footer summary и колонку `Статус`.
- [ ] Инструмент в последних событиях: название сверху жирным, ticker/ISIN снизу серым.
- [ ] Налоги/комиссии/списания отображаются красным и с корректным бейджем типа.
- [ ] На mobile нет page-level horizontal overflow.
## Tests
- [ ] Backend targeted:
`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:
`npm run test -w apps/frontend -- --run src/widgets/broker-dashboard`
- [ ] Full frontend:
`npm run test:frontend`
- [ ] Frontend lint:
`npm run lint -w apps/frontend`
- [ ] Frontend build:
`npm run build:frontend`
- [ ] Проверить OpenAPI/codegen после backend изменений.
## Visual QA
- [ ] Проверить `/broker/:accountId` на desktop против
`docs/research/frontend-overview-redesign/example.html`.
- [ ] Проверить `/broker/:accountId` на viewport `390x844`.
- [ ] Проверить, что loading/loaded высоты карточек не вызывают layout shift.
- [ ] Проверить, что подписи месяцев графика не выходят за границы карточки.
- [ ] Проверить, что таблица последних событий читаема на mobile.
## Definition of Done
- [ ] Все acceptance criteria из `spec.md` выполнены.
- [ ] Backend tests проходят.
- [ ] Frontend targeted tests проходят.
- [ ] `npm run test:frontend` проходит.
- [ ] `npm run lint -w apps/frontend` проходит.
- [ ] `npm run build:frontend` проходит.
- [ ] Generated OpenAPI types обновлены через codegen.
- [ ] Visual QA desktop/mobile выполнена.
- [ ] Существующие detailed вкладки `Акции`, `Облигации`, `Операции`, `События`, `Аналитика`
остаются доступны.
- [ ] `tasks.md` обновлён по факту выполнения.