docs: update apps/docs — fix inconsistencies, add broker events diagrams
Some checks failed
CI / ci (pull_request) Failing after 3m18s
CI / ci (push) Failing after 3m16s

This commit is contained in:
Sergey Krylov 2026-06-22 22:15:51 +03:00
parent 62a8cffc96
commit 462212c95e
11 changed files with 171 additions and 47 deletions

View File

@ -392,3 +392,16 @@
`DELETE` endpoints возвращают `{ data: null, meta }`, что отражено в OpenAPI schema и frontend
codegen types.
## Broker (T-Bank Invest)
Все broker endpoints защищены JWT и возвращают envelope `{ data, meta }`.
| Endpoint | Method | Описание |
|---|---|---|
| `/api/v1/broker/accounts` | GET | Список брокерских счетов и ИИС |
| `/api/v1/broker/accounts/:accountId/portfolio` | GET | Портфель счёта: позиции, cash, метаданные |
| `/api/v1/broker/accounts/:accountId/events` | GET | События и будущие выплаты (дивиденды, купоны) с фильтром по датам |
| `/api/v1/broker/accounts/:accountId/operations` | GET | История операций (cursor pagination) |
| `/api/v1/broker/accounts/:accountId/operations/refresh` | POST | Принудительная синхронизация операций из T-Bank |
| `/api/v1/broker/accounts/:accountId/positions` | GET | Позиции счёта (с пагинацией) |

View File

@ -48,5 +48,7 @@ apps/backend/src/
├── securities/
├── shares/
├── bonds/
└── candles/
├── candles/
├── portfolio/
└── tbank/
```

View File

@ -40,9 +40,44 @@ root CA, которым локальная сеть или proxy подписы
|---|---|
| `GET /api/v1/broker/accounts` | Открытые брокерские счета и ИИС |
| `GET /api/v1/broker/accounts/:accountId/portfolio` | Итоги портфеля, позиции, деньги и заблокированные деньги |
| `GET /api/v1/broker/accounts/:accountId/events` | Будущие события (дивиденды, купоны, погашения, оферты) и прошедшие фактические выплаты с фильтром по датам и типам |
| `GET /api/v1/broker/accounts/:accountId/operations` | История операций с cursor pagination |
| `POST /api/v1/broker/accounts/:accountId/operations/sync` | Синхронизация истории операций в локальные Prisma-таблицы |
## Поток данных для `/events`
Endpoint `/events` агрегирует будущие события и прошедшие выплаты из нескольких источников:
```mermaid
sequenceDiagram
actor User
participant Frontend
participant Backend
participant TBank as T-Bank gRPC
participant MOEX as MOEX ISS (cache)
User->>Frontend: Открывает вкладку «События»
Frontend->>Backend: GET /broker/accounts/:id/events?from=X&to=Y&types=Z
Backend->>TBank: GetPositions (текущие позиции счёта)
TBank-->>Backend: positions[]
loop Для каждой позиции
Backend->>MOEX: Получить график купонов / дивидендов
MOEX-->>Backend: futureEvents[]
end
Backend->>TBank: GetOperationsByCursor (фактические выплаты за период)
TBank-->>Backend: pastPayouts[]
Note over Backend: Агрегация + фильтр по from/to/types
Backend-->>Frontend: { events[], summary }
Frontend->>User: Отображает таблицу событий и сумму выплат
```
- **Будущие события** — строятся на лету по текущим позициям счёта и MOEX-метаданным (график купонов, даты дивидендов). Не записываются в БД.
- **Прошедшие выплаты** — извлекаются из истории операций T-Bank за указанный период.
- **Summary** — агрегированная оценка будущих выплат (не является гарантированной суммой).
- Кешируется через `CACHE_TBANK_EVENTS_TTL`.
Типы событий: `dividend`, `coupon`, `maturity`, `offer`. Первые три относятся к `cashflow`, `offer` — к `corporate`.
## Методы T-Bank
| Задача | Метод T-Bank |
@ -51,6 +86,7 @@ root CA, которым локальная сеть или proxy подписы
| Итоги портфеля | `OperationsService/GetPortfolio` |
| Деньги и settled-позиции | `OperationsService/GetPositions` |
| История операций | `OperationsService/GetOperationsByCursor` |
| События и выплаты | Агрегация из позиций счёта + фактических операций |
| Метаданные инструментов | `InstrumentsService/GetInstrumentBy` |
## Кеширование и синхронизация
@ -62,6 +98,7 @@ Direct-read endpoints используют короткий in-memory cache, ч
- портфель: `CACHE_TBANK_PORTFOLIO_TTL`
- позиции: `CACHE_TBANK_POSITIONS_TTL`
- страницы операций: `CACHE_TBANK_OPERATIONS_TTL`
- события и прогноз выплат: `CACHE_TBANK_EVENTS_TTL`
- метаданные инструментов: `CACHE_TBANK_INSTRUMENT_TTL`
Для долговременной истории операций есть отдельные таблицы Prisma:

View File

@ -7,11 +7,16 @@
| `npm run dev:backend` | Запуск NestJS в режиме watch на :3000 |
| `npm run dev:frontend` | Vite dev-сервер на `:5173`, проксирует `/api` на backend |
| `npm run dev:docs` | Docusaurus dev-сервер документации |
| `npm run dev:design-system` | Storybook dev-сервер дизайн-системы |
| `npm run build:backend` | `nest build` |
| `npm run build:frontend` | `tsc -b && vite build` |
| `npm run build:docs` | `docusaurus build` |
| `npm run build:design-system` | TypeScript build дизайн-системы |
| `npm run build:storybook` | Production build Storybook |
| `npm run test:backend` | Offline backend unit tests через Vitest |
| `npm run test:frontend` | Frontend tests через Vitest + Testing Library |
| `npm run test:design-system` | Design system tests через Vitest |
| `npm run test:storybook` | Storybook browser tests (Playwright) |
| `npm run lint` | ESLint для backend и frontend |
| `npm run format` | Prettier для всех `*.{ts,tsx}` |
| `npm run format:check` | Проверка Prettier для всех `*.{ts,tsx}` |
@ -39,6 +44,15 @@
| `npm run lint -w apps/frontend` | ESLint для `src/**/*.{ts,tsx}` |
| `npm run test -w apps/frontend` | Frontend Vitest suite |
## Design system workspace
| Команда | Описание |
|---|---|
| `npm run dev -w packages/design-system` | Storybook dev-server |
| `npm run build -w packages/design-system` | TypeScript build |
| `npm run build:storybook -w packages/design-system` | Production build Storybook |
| `npm run test -w packages/design-system` | Vitest suite |
## Docs workspace
| Команда | Описание |

View File

@ -51,6 +51,28 @@ npm run test -w apps/frontend
Тесты покрывают API-клиент, auth context, hooks, базовые pages и shared components.
## Тесты design system
Фреймворк: **Vitest** + **React Testing Library** + **Accessibility check**.
Запуск:
```bash
npm run test:design-system
# или
npm run test -w packages/design-system
```
Тесты покрывают компоненты дизайн-системы: Button, DataTable, Select, Skeleton, Money и др.
## Storybook browser tests
Интерактивные тесты Storybook через Playwright.
```bash
npm run test:storybook
```
## Live MOEX integration tests
Live MOEX checks вынесены из default backend suite.

View File

@ -1,7 +1,7 @@
# Компоненты
Published docs ниже перечисляют primary entrypoints. Legacy файлы в `components/` сохранены как
тонкие re-export shim'ы для coexistence со старыми импортами.
Published docs ниже перечисляют primary entrypoints. Все legacy-файлы в `components/` удалены,
компоненты используют FSD-структуру.
## Layout (`app/layouts/AppLayout.tsx`, legacy shim: `components/Layout.tsx`)
@ -19,7 +19,7 @@ Published docs ниже перечисляют primary entrypoints. Legacy фа
- При клике на результат переходит на `/stocks/:secid` или `/bonds/:secid`
- Закрывается при клике вне компонента
Legacy path `components/SearchBar.tsx` остаётся shim-файлом и не является primary entrypoint.
Legacy path `components/SearchBar.tsx` удалён.
## PriceChart (`widgets/price-chart/ui/PriceChart.tsx`, public API: `widgets/price-chart`)
@ -30,7 +30,7 @@ Legacy path `components/SearchBar.tsx` остаётся shim-файлом и н
- Цвета: зелёный для роста, красный для падения
- Адаптивная ширина (resize listener)
Legacy path `components/PriceChart.tsx` остаётся shim-файлом.
Legacy path `components/PriceChart.tsx` удалён.
## StockDetails (`widgets/stock-details/ui/StockDetails.tsx`, public API: `widgets/stock-details`)
@ -39,7 +39,7 @@ Legacy path `components/PriceChart.tsx` остаётся shim-файлом.
- Принимает `ShareResponse`
- Отображает: название, тикер, ISIN, цена, изменение (%), open/high/low, объём, капитализация, уровень листинга
Legacy path `components/StockDetails.tsx` остаётся shim-файлом.
Legacy path `components/StockDetails.tsx` удалён.
## BondDetails (`widgets/bond-details/ui/BondDetails.tsx`, public API: `widgets/bond-details`)
@ -48,7 +48,7 @@ Legacy path `components/StockDetails.tsx` остаётся shim-файлом.
- Принимает `BondResponse`
- Отображает: название, ISIN, цена (в % от номинала), номинал, дата погашения, купон (сумма/%), период купона, НКД, доходность к погашению, дюрация, тип
Legacy path `components/BondDetails.tsx` остаётся shim-файлом.
Legacy path `components/BondDetails.tsx` удалён.
## DividendsTable (`widgets/dividends-table/ui/DividendsTable.tsx`, public API: `widgets/dividends-table`)
@ -57,3 +57,12 @@ Legacy path `components/BondDetails.tsx` остаётся shim-файлом.
- Принимает готовый список дивидендов через props
- Рендерит payout-историю без собственных query-вызовов
- Используется page-layer как prop-driven widget
## BrokerEventsOverview (`widgets/broker-events-overview/ui/BrokerEventsOverview.tsx`, public API: `widgets/broker-events-overview`)
Обзор ближайших событий и будущих выплат брокерского счёта.
- Принимает `accountId`
- Показывает до 5 ближайших событий (дивиденды, купоны)
- Ссылка на полную страницу событий
- Состояния: загрузка, ошибка, пустой список

View File

@ -10,6 +10,7 @@
| `useStockDividends(secid)` | `['stockDividends', secid]` | 86400s | Дивиденды акции |
| `useBond(secid)` | `['bond', secid]` | 900s | Спецификация облигации |
| `useBondCandles(secid, interval, from, till)` | `['bondCandles', secid, interval, from, till]` | 3600s | Свечи облигации |
| `useBrokerEvents(accountId, { from, to, types })` | `['broker', 'events', accountId, from, to, types]` | 300s | Будущие события и прошедшие выплаты брокерского счёта |
## Public API
@ -20,6 +21,7 @@
- broker-account hooks: `entities/broker-account/index.ts`
- broker-position hooks: `entities/broker-position/index.ts`
- broker-operation hooks: `entities/broker-operation/index.ts`
- broker-event hooks: `entities/broker-event/index.ts`
- session hooks: `entities/session/index.ts`
## Конфигурация Query

View File

@ -14,8 +14,8 @@ React SPA, собранная с Vite.
## Структура исходников
Published-структура ниже описывает primary FSD entrypoints. Исторические каталоги `api/`, `context/`,
`hooks/`, `components/` ещё присутствуют в кодовой базе для ещё не мигрированных доменов.
Published-структура ниже описывает primary FSD entrypoints. Исторические каталоги полностью
мигрированы.
```
apps/frontend/src/
@ -34,6 +34,8 @@ apps/frontend/src/
│ └── layouts/
│ ├── AppLayout.tsx # Шапка + <Outlet/>
│ └── index.ts
├── features/ # FSD features
│ └── screener/ # Скринер ценных бумаг (api, model, ui)
├── shared/
│ ├── api/ # shared API client, response types, generated OpenAPI types
│ └── ui/ # shared UI primitives without domain logic
@ -55,6 +57,7 @@ apps/frontend/src/
│ ├── broker-account-card/ # Карточка брокерского счёта
│ ├── broker-accounts-summary/ # Сводка брокерских счетов
│ ├── broker-allocation-chart/ # График распределения
│ ├── broker-events-overview/ # Ближайшие события (обзор)
│ ├── broker-operations-table/ # Таблица операций
│ ├── portfolio-card/ # Карточка портфеля
│ ├── portfolio-form/ # Форма портфеля
@ -73,14 +76,9 @@ apps/frontend/src/
│ ├── screener/ # Скринер (не мигрирован)
│ ├── broker-accounts/ # FSD: page entrypoint
│ ├── broker-account/ # FSD: page entrypoint
│ ├── broker-events/ # FSD: page entrypoint
│ ├── broker-positions/ # FSD: page entrypoint
│ └── broker-operations/ # FSD: page entrypoint
├── api/
│ └── screener.ts # Screener API helpers (не мигрирован)
├── hooks/
│ └── useScreener.ts # Screener hook (не мигрирован)
├── components/
│ └── screener/ # Screener UI (не мигрирован)
├── test/
│ ├── factories.ts # Фабрики тестовых данных
│ ├── handlers.ts # MSW handlers
@ -116,6 +114,7 @@ apps/frontend/src/
| `broker-account` | API брокерских счетов | useBrokerAccounts, useBrokerAccountPortfolios | BrokerAccountLayout |
| `broker-position` | API брокерских позиций | useBrokerPositions | — |
| `broker-operation` | API брокерских операций | useBrokerOperations | — |
| `broker-event` | API брокерских событий и выплат | useBrokerEvents | — |
Каждая сущность имеет barrel-файл `index.ts`, реэкспортирующий публичное API.
@ -135,17 +134,10 @@ apps/frontend/src/
- `pages/home`, `pages/stock`, `pages/bond` — FSD page entrypoints для market pages
- `pages/broker-*` — FSD page entrypoints для брокерского домена
- Временно не мигрированы: `portfolios/`, `screener/`, `LoginPage.tsx`, `RegisterPage.tsx`, `ProfilePage.tsx`
- `pages/portfolios/` — FSD page entrypoints для портфелей
- `pages/screener/` — FSD page entrypoint для скринера
- `pages/LoginPage.tsx`, `RegisterPage.tsx`, `ProfilePage.tsx` — auth страницы, используют FSD-imports из `entities/session`
### Не мигрировано
### features
Скринер остаётся в исторической структуре:
- `api/screener.ts` — API-вызовы
- `hooks/useScreener.ts` — логика с URLSearchParams
- `components/screener/` — FilterPanel, FilterPanelBond, FilterPanelShare, ScreenerTable
- `pages/screener/ScreenerPage.tsx` — страница
Страницы аутентификации (`LoginPage`, `RegisterPage`, `ProfilePage`) — плоские, но используют FSD-импорты из `entities/session`.
ESLint-правила на границы импортов FSD пока не введены.
- `features/screener/` — скринер: FilterPanel, FilterPanelBond, FilterPanelShare, ScreenerTable, useScreener hook

View File

@ -15,6 +15,7 @@ Source of truth для маршрутов: `apps/frontend/src/app/routing/AppRou
| `/portfolios/:id` | `PortfolioDetailPage` | Protected | Детальная страница портфеля |
| `/broker` | `BrokerAccountsPage` from `pages/broker-accounts` | Protected | Список брокерских счетов |
| `/broker/:accountId` | `BrokerAccountLayout` + nested pages | Protected | Детальная область брокерского счёта |
| `/broker/:accountId/events` | `BrokerEventsPage` from `pages/broker-events` | Protected | Календарь событий и выплат |
Все page entrypoints живут в FSD-слоях:
@ -25,6 +26,7 @@ Source of truth для маршрутов: `apps/frontend/src/app/routing/AppRou
- `pages/broker-account`
- `pages/broker-positions`
- `pages/broker-operations`
- `pages/broker-events`
Все страницы обёрнуты в `AppLayout`, который содержит:
@ -87,7 +89,37 @@ Source of truth для маршрутов: `apps/frontend/src/app/routing/AppRou
<Route path="shares" element={<BrokerPositionsPage type="share" title="Акции" />} />
<Route path="bonds" element={<BrokerPositionsPage type="bond" title="Облигации" />} />
<Route path="operations" element={<BrokerOperationsPage />} />
<Route path="events" element={<BrokerEventsPage />} />
</Route>
</Route>
</Routes>
```
## Композиция страницы событий
Страница `/broker/:accountId/events` собирается из FSD-слоёв:
```mermaid
flowchart TB
BrokerEventsPage["pages/broker-events<br/>BrokerEventsPage"]
useBrokerEvents["entities/broker-event<br/>useBrokerEvents"]
BrokerEventApi["entities/broker-event/api<br/>brokerEventApi"]
BrokerEventsOverview["widgets/broker-events-overview<br/>BrokerEventsOverview"]
DS["@moex-vibe/design-system<br/>DatePicker, Select, Button<br/>DataTable, Metric, LoadingState"]
BrokerEventsPage --> useBrokerEvents
BrokerEventsPage --> BrokerEventsOverview
BrokerEventsPage --> DS
useBrokerEvents --> BrokerEventApi
subgraph Overview["Обзор на dashboard счёта"]
BrokerAccountOverview["pages/broker-account<br/>BrokerAccountOverviewPage"]
BrokerAccountOverview --> BrokerEventsOverview
end
```
- `BrokerEventsPage` — entrypoint страницы: фильтр по датам/типам, таблица событий, summary
- `BrokerEventsOverview` — компактный блок 5 ближайших событий (используется на overview счёта)
- `useBrokerEvents` — TanStack Query hook с ключом `['broker', 'events', accountId, from, to, types]`
```

View File

@ -18,25 +18,21 @@ env:
## Jobs
### lint
Единый job `ci` выполняет последовательно:
- `actions/checkout@v4`
- `actions/setup-node@v4` (Node 20)
- `npm ci`
- `npm run lint` (ESLint для бэкенда)
- `npx prettier --check "**/*.{ts,tsx}"` (проверка форматирования)
1. **Checkout**`actions/checkout@v4`
2. **Setup Node**`actions/setup-node@v4` (Node 20)
3. **Install**`npm ci`
4. **Lint**`npm run lint`
5. **Format check**`npm run format:check`
6. **Test backend**`npm run test:backend`
7. **Test frontend**`npm run test:frontend`
8. **Test design system**`npm run test:design-system`
9. **Test Storybook (browser)**`npm run test:storybook`
10. **Build backend**`npm run build:backend`
11. **Build frontend**`npm run build:frontend`
12. **Build design system**`npm run build:design-system`
13. **Build Storybook**`npm run build:storybook`
14. **Build docs**`npm run build:docs`
### test
- `actions/checkout@v4`
- `actions/setup-node@v4` (Node 20)
- `npm ci`
- `npm run test:backend` (vitest)
### build
- `actions/checkout@v4`
- `actions/setup-node@v4` (Node 20)
- `npm ci`
- `npm run build:backend` (nest build)
- `npm run build:frontend` (tsc -b && vite build)
При failure Storybook build артефакты загружаются для диагностики.

View File

@ -78,6 +78,11 @@ const sidebars: SidebarsConfig = {
'adr/ADR-009-portfolio-domain',
'adr/ADR-010-backend-price-computation',
'adr/ADR-011-tbank-invest-grpc',
'adr/ADR-012-frontend-broker-account-aggregation',
'adr/ADR-013-frontend-fsd-broker-pilot',
'adr/ADR-014-frontend-fsd-market-pages',
'adr/ADR-015-frontend-libraries-modernization',
'adr/ADR-016-design-system',
],
},
],