food-market/docs/sprint8-progress.md
nns dd2e1e7af2
Some checks are pending
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
Docker API / Build + push API (push) Waiting to run
Docker API / Deploy API on stage (push) Blocked by required conditions
Docker Web / Build + push Web (push) Waiting to run
Docker Web / Deploy Web on stage (push) Blocked by required conditions
feat(realtime): SignalR hub /hubs/notifications per-org + dashboard live
P2-7 Sprint 8 пункт 1.

Backend:
- src/food-market.api/Realtime/NotificationsHub.cs — SignalR-хаб, группы
  org:{orgId:N}. JWT через Authorization-хедер (стандартно) или через
  query ?access_token=... (для WebSocket — браузерные не могут слать
  кастомные хедеры). SuperAdmin override через ?orgOverride=<id>.
- NotificationsPublisher.cs — singleton, IHubContext-обёртка.
- Program.cs — AddSignalR + MapHub. Middleware копирует ?access_token=
  в Authorization для /hubs/* до UseAuthentication.
- RetailSalesController.Post → публикует SalePosted + LowStockPayload
  если после движения товара остаток < MinStock. Best-effort: notify
  ошибка не валит транзакцию.
- SuppliesController.Post → SupplyPosted.

Events (camelCase в JSON):
- SalePosted { saleId, number, total, storeId, cashierName, retailPointId, postedAt }
- SupplyPosted { supplyId, number, total, supplierId, supplierName, postedAt }
- LowStock { productId, productName, storeId, storeName, quantity, minStock }

Web:
- @microsoft/signalr 10.0.0 client.
- src/lib/useNotificationsHub.ts — hook с автореконнектом, accessTokenFactory.
- DashboardPage:
  • liveRevenueDelta / liveCountDelta — оптимистическое приращение
    «Выручка сегодня» сразу при SalePosted (до refetch stats);
  • toast.info на SupplyPosted; toast.error на LowStock;
  • Wifi/WifiOff индикатор в header.

Тесты:
- SignalRNotificationsTests: A постит retail-sale → A получает SalePosted,
  B (другая org) НЕ получает — multi-tenant. ✓ 1/1 локально.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 19:29:59 +05:00

2.1 KiB
Raw Blame History

Sprint 8 — real-time + Telegram-бот владельца + локализация + MinIO

Цель: добавить «живой» опыт (live-обновление виджетов через SignalR), канал для уведомлений владельцу (Telegram-бот с ежедневной сводкой), английский UI (i18n) и перенести uploads в MinIO/S3.

Старт: 2026-05-31. Исполнитель: Claude Opus 4.7 (автономный режим).

Принципы

  • Multi-tenant обязателен — Hub-группы per-org, OwnerTelegramChatId на Organization, MinIO bucket общий но object-key {orgId}/....
  • Каждый пункт: dotnet build + локальные тесты + ~/deploy-stage.sh + retest на https://test.admin.food-market.kz.
  • НЕ трогать: global.json, прод-стек (admin.food-market.kz), POS WPF.

Чек-лист

  • 1. P2-7 SignalR real-time — Hub /hubs/notifications с группами per-org. События SalePosted / SupplyPosted / LowStock. JWT auth на коннекте. Дашборд live-виджет «Продажи сегодня» + bell-toast low-stock.
  • 2. P2-14 Telegram-бот владельца — Hangfire OwnerDailySummaryJob 09:00 МСК, ежедневная сводка (выручка вчера, продажи, топ-3, low-stock). Привязка через deep-link → Organization.OwnerTelegramChatId. UI в OrgSettings.
  • 3. P2-6a Локализация UI (en) — react-i18next, ru.json + en.json, language switcher в header. kz TODO. На стейдже smoke — все страницы переключаются.
  • 4. P2-15 MinIO/S3 для uploadsMinio SDK, bucket food-market-uploads, авто-создание на старте, миграция existing volume. Storage:Type=Local|Minio с fallback на Local. Тесты + UI upload картинки.

Журнал

2026-05-31 — старт

Sprint UI-deep закрыт (docs/sprint-ui-deep-progress.md, 59/59 ✓, 6 багов починены). Перехожу к Sprint 8 пункт 1 (SignalR).