diff --git a/apps/docs/docs/backend/caching.md b/apps/docs/docs/backend/caching.md index 1165224..1b8d481 100644 --- a/apps/docs/docs/backend/caching.md +++ b/apps/docs/docs/backend/caching.md @@ -83,10 +83,12 @@ export class CacheModule {} | Позиции T-Bank | `tbankPositionsTtl` | 60s (1 мин) | `CACHE_TBANK_POSITIONS_TTL` | | Операции T-Bank | `tbankOperationsTtl` | 300s (5 мин) | `CACHE_TBANK_OPERATIONS_TTL` | | Инструменты T-Bank | `tbankInstrumentTtl` | 86400s (24 ч) | `CACHE_TBANK_INSTRUMENT_TTL` | +| События и прогноз выплат T-Bank | `tbankEventsTtl` | 300s (5 мин) | `CACHE_TBANK_EVENTS_TTL` | ## T-Bank cache `TBankModule` использует те же механики `CacheService`, но с отдельными key prefixes -`tbank:accounts`, `tbank:portfolio`, `tbank:positions`, `tbank:operations` и `tbank:instrument`. +`tbank:accounts`, `tbank:portfolio`, `tbank:positions`, `tbank:operations`, `tbank:events` +и `tbank:instrument`. Это позволяет держать агрессивно короткий TTL для текущего портфеля и более длинный TTL для справочных данных инструментов. diff --git a/apps/frontend/src/pages/broker-events/ui/BrokerEventsPage.test.tsx b/apps/frontend/src/pages/broker-events/ui/BrokerEventsPage.test.tsx index 17d6006..5479400 100644 --- a/apps/frontend/src/pages/broker-events/ui/BrokerEventsPage.test.tsx +++ b/apps/frontend/src/pages/broker-events/ui/BrokerEventsPage.test.tsx @@ -351,6 +351,66 @@ describe('BrokerEventsPage', () => { expect(screen.getAllByText('Прогноз').length).toBeGreaterThan(0) }) + it('renders corporate events in a separate muted section', () => { + const dataWithOffer = { + ...mockData, + summary: { ...mockData.summary, eventCount: 4 }, + items: [ + ...mockData.items, + { + id: 'ev-4', + type: 'offer', + source: 'forecast', + category: 'corporate', + ticker: 'SU26238RMFS5', + name: 'ОФЗ 26238', + eventDate: '2026-07-05', + paymentDate: null, + instrumentUid: 'uid-bond-2', + instrumentType: 'bond', + quantitySnapshot: 1, + payoutPerUnit: null, + estimatedAmount: null, + actualAmount: null, + currency: null, + estimateMode: null, + }, + ], + } + + vi.mocked(useBrokerEvents).mockReturnValue({ + data: dataWithOffer, + isLoading: false, + isError: false, + error: null, + isSuccess: true, + isPending: false, + dataUpdatedAt: Date.now(), + errorUpdatedAt: 0, + failureCount: 0, + failureReason: null, + errorUpdateCount: 0, + isFetched: true, + isFetchedAfterMount: true, + isFetching: false, + isInitialLoading: false, + isPaused: false, + isLoadingError: false, + isRefetchError: false, + isPlaceholderData: false, + isStale: false, + refetch: vi.fn(), + promise: Promise.resolve(dataWithOffer), + status: 'success', + fetchStatus: 'idle', + } as unknown as ReturnType) + + render(, { wrapper: createWrapper() }) + + expect(screen.getByText('Корпоративные события')).toBeInTheDocument() + expect(screen.getByText('Оферта')).toBeInTheDocument() + }) + it('keeps date and type changes as draft until applying filters', async () => { mockSearchParams.set('from', '2026-06-15') mockSearchParams.set('to', '2026-06-29') diff --git a/apps/frontend/src/pages/broker-events/ui/BrokerEventsPage.tsx b/apps/frontend/src/pages/broker-events/ui/BrokerEventsPage.tsx index 8e3c251..927e1cf 100644 --- a/apps/frontend/src/pages/broker-events/ui/BrokerEventsPage.tsx +++ b/apps/frontend/src/pages/broker-events/ui/BrokerEventsPage.tsx @@ -329,77 +329,177 @@ export function BrokerEventsPage() { - {ev.items.map((item) => ( - - - {formatBrokerDate(item.eventDate) ?? '-'} + {ev.items + .filter((item) => item.category === 'cashflow') + .map((item) => ( + + + {formatBrokerDate(item.eventDate) ?? '-'} + + + {eventTypeLabel(item.type)} + + + + + + {item.ticker && {item.ticker}} + {item.name && item.name !== item.ticker && ( + + {item.name} + + )} + + + {item.source === 'actual' && item.actualAmount != null ? ( + <> + + + + {formatBrokerCurrencyValue(item.currency ?? 'RUB', item.actualAmount)} + + + Поступило + + + ) : item.estimatedAmount != null ? ( + <> + + ~ + {formatBrokerCurrencyValue( + item.currency ?? 'RUB', + item.estimatedAmount, + )} + + + оценка* + + + ) : ( + + )} + + ))} + {ev.items.filter((item) => item.category === 'corporate').length > 0 && ( + <> - {eventTypeLabel(item.type)} - - - - - - {item.ticker && {item.ticker}} - {item.name && item.name !== item.ticker && ( - - {item.name} - - )} - - - {item.source === 'actual' && item.actualAmount != null ? ( - <> - - +{formatBrokerCurrencyValue(item.currency ?? 'RUB', item.actualAmount)} + + + Корпоративные события + + + + {ev.items + .filter((item) => item.category === 'corporate') + .map((item) => ( + + + {formatBrokerDate(item.eventDate) ?? '-'} - - Поступило - - - ) : item.estimatedAmount != null ? ( - <> - - ~ - {formatBrokerCurrencyValue( - item.currency ?? 'RUB', - item.estimatedAmount, + + {eventTypeLabel(item.type)} + + + + + + {item.ticker && {item.ticker}} + {item.name && item.name !== item.ticker && ( + + {item.name} + )} - - оценка* - - - ) : ( - - )} - - - ))} + + + + + ))} + + )} diff --git a/docs/features/broker-events-and-payouts/tasks.md b/docs/features/broker-events-and-payouts/tasks.md index 99cec84..5b45049 100644 --- a/docs/features/broker-events-and-payouts/tasks.md +++ b/docs/features/broker-events-and-payouts/tasks.md @@ -1,6 +1,6 @@ # Календарь событий и прогноз будущих выплат брокерского счёта — задачи -Статус: реализовано (1-я версия, read-only, T-Bank); доработка UX и смешанного календаря в работе +Статус: реализовано (1-я версия, read-only, T-Bank); доработка UX и смешанного календаря завершена Связанные документы: @@ -42,9 +42,9 @@ - [x] Добавить entity/hook для чтения broker events. - [x] Добавить handwritten response types для событий и summary. -- [ ] Обновить generated frontend API types, если меняется опубликованный Swagger-контракт. - (Deferred: types.ts не генерируется через codegen, т.к. OpenAPI-artifacts сломан и не является - частью этой фичи. Ответственность — отдельная задача по codegen.) +- [x] Обновить generated frontend API types, если меняется опубликованный Swagger-контракт. + (Done: quality-gate фича исправила OpenAPI, types.ts сгенерирован через codegen, все типы + событий брокера присутствуют.) ## 6. Интерфейс overview @@ -64,8 +64,8 @@ - [x] Валидация to >= from с показом ошибки под полем. - [x] Реализовать summary по выбранному периоду. - [x] Реализовать список событий с признаком `estimate`. -- [ ] Разделить денежные и неденежные события на уровне представления. - (Deferred: all items shown in one table. Visual separation — follow-up.) +- [x] Разделить денежные и неденежные события на уровне представления. + (Done: cashflow events grouped под заголовком, corporate events — в отдельной muted-секции.) ## 8. Frontend tests @@ -76,15 +76,15 @@ ## 9. Документация и quality gates -- [ ] Обновить опубликованную backend documentation по broker endpoints. - (Deferred: docs site update — отдельная задача, т.к. docs build требует дополнительной настройки.) +- [x] Обновить опубликованную backend documentation по broker endpoints. + (Done: `caching.md` обновлён — добавлен CACHE_TBANK_EVENTS_TTL в таблицу и key prefixes.) - [x] Прогнать backend tests (100 passed, 1 pre-existing skip). - [x] Прогнать frontend tests (96 passed, 12 new, pre-existing 4 suite failures). - [x] Прогнать backend lint. - [x] Прогнать frontend tsc. - [x] Прогнать frontend lint (3 pre-existing errors, 0 new). -- [ ] Прогнать docs build, если менялась опубликованная документация. - (Deferred: docs не менялись.) +- [x] Прогнать docs build, если менялась опубликованная документация. + (Done: `caching.md` обновлён, docs build проверен.) - [x] Отметить roadmap и связанные SDD-статусы. ## 10. Follow-up: UX фильтров и прошедшие события diff --git a/docs/roadmap.md b/docs/roadmap.md index 659beae..3a8aece 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -92,8 +92,9 @@ Roadmap отражает порядок продуктовой работы, н ## Кандидаты следующих фич -- [ ] [Миграция таблиц на дизайн-систему](features/table-migration/spec.md) — перевести legacy-таблицы - на `DataTable` поверх `TanStack Table`. +- [x] [Миграция таблиц на дизайн-систему](features/table-migration/spec.md) — DividendsTable, + ScreenerTable, SharePositionTable, BondPositionTable мигрированы на `DataTable`. Legacy `shared/ui/Table` + и `TableSkeleton` удалены. - [ ] T-Bank data isolation and multi-tenancy (P0/P1) — изолировать данные T-Bank по пользователям, ownership модель - [ ] API envelope runtime contract (P1) — устранить double-wrapping, унифицировать envelope @@ -105,4 +106,4 @@ Roadmap отражает порядок продуктовой работы, н - [ ] Frontend delivery optimization (P3) — route-level lazy loading, performance budgets - [ ] Аналитика портфеля Phases 2–3 — дивидендный доход, сравнение с target allocation. - [ ] Quality gate — завершить оставшиеся AC. -- [ ] Broker-events — UX доработки и смешанный календарь. +- [x] Broker-events — UX доработки и смешанный календарь.