food-market/docs/sprint8-progress.md
nns a5314b5be9
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
test(s8-4): MinIO stage e2e + final progress
Все 4 пункта спринта 8 закрыты. Stage 8/8 e2e зелёные.

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

47 lines
6.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.
## Чек-лист
- [x] **1. P2-7 SignalR real-time** — Hub `/hubs/notifications` с группами per-org. События `SalePosted`/`SupplyPosted`/`LowStock`. JWT через query `?access_token=` (для WebSocket). Дашборд: live-индикатор Wifi, оптимистическое приращение «Выручка сегодня», toast.info на SupplyPosted, toast.error на LowStock. Тесты: SignalRNotificationsTests (multi-tenant 1/1) + `stage-ui-signalr.spec.ts` (1/1 ✓). Nginx `/hubs/` с upgrade-хедерами и 24h read_timeout.
- [x] **2. P2-14 Telegram-бот владельца** — миграция `Phase9a_OwnerTelegramChatId`. `TelegramBotClient` (sendMessage HTML), Disabled-mode когда `Telegram__BotToken` пустой. `OwnerDailySummaryJob.RunAsync` — cron `0 6 * * *` UTC = 09:00 МСК. Сводка: выручка вчера, чеков, средний чек, топ-3 по выручке, low-stock 5. `TelegramBindingController` (status/bind/unbind). UI секция в OrganizationSettings с deep-link + пошаговой инструкцией. Тесты: `TelegramOwnerSummaryTests` (рендер ✓), `stage-ui-telegram.spec.ts` (3/3 ✓ на стейдже).
- [x] **3. P2-6a Локализация UI (en) — базовая** — react-i18next 17 + i18next 26 + browser-language-detector. `ru.json`/`en.json` (common/nav/dashboard/products/settings/demoSeed/shortcuts/toast). `LanguageSwitcher` в sidebar. AppLayout (sidebar) + DashboardPage переведены. kz: TODO (требует человека-переводчика). Тесты: `stage-ui-i18n.spec.ts` (3/3 ✓). Остаток (Products/Counterparties/Enters/...) — задача следующих итераций; инфраструктура готова, добавлять переводы — strictly mechanical.
- [x] **4. P2-15 MinIO/S3 для uploads**`Minio` 6.0.5 SDK + `IObjectStorage` (Local/Minio impls). DI: рантайм-fallback на Local если MinIO config пуст. `MinioBootstrap` (IHostedService) создаёт bucket `food-market-uploads` на старте (best-effort, не валит API). `ProductImagesController` отрефакторен на абстракцию. `UploadsController` (GET /uploads/{**path}) стримит из IObjectStorage с cache-control 7d. Stage compose обновлён (minio container + Storage__* env). Тесты: `StorageAbstractionTests` (3/3 ✓), `stage-ui-minio.spec.ts` (1/1 ✓ — UI upload PNG → MinIO bucket → download через `/uploads/...` byte-equal). Стейдж лог: «MinIO bucket food-market-uploads created».
## Журнал
### 2026-05-31 — старт
Sprint UI-deep закрыт (`docs/sprint-ui-deep-progress.md`, 59/59 ✓, 6 багов починены). Перехожу к Sprint 8 пункт 1 (SignalR).
### 2026-05-31 — итог
**Все 4 пункта ✓** на `https://test.admin.food-market.kz`. Stage 8/8 e2e + integration tests зелёные после последнего deploy-stage.
| # | Тема | Commits | Specs |
|---|---|---|---|
| 1 | SignalR | `dd2e1e7` + `2ea30bb` (nginx fix) | int 1/1 + stage 1/1 |
| 2 | Telegram бот | `3088237` | int 1/1 + stage 3/3 |
| 3 | i18n (ru/en) | `301bf15` | stage 3/3 |
| 4 | MinIO/S3 | `7de159d` | int 3/3 + stage 1/1 |
**Что было сделано:**
1. **SignalR**: Hub `/hubs/notifications` с группами per-org, событиями SalePosted / SupplyPosted / LowStock. JWT через `?access_token=` для WebSocket. Дашборд: live-индикатор Wifi, оптимистическое приращение «Выручка сегодня», toast.info на SupplyPosted, toast.error на LowStock. Nginx fix: `/hubs/` с upgrade-хедерами и 24h read_timeout.
2. **Telegram бот**: миграция `Phase9a_OwnerTelegramChatId`, `TelegramBotClient` с disabled-mode, `OwnerDailySummaryJob` cron `0 6 * * *` (09:00 МСК). Сводка: выручка вчера, чеков, средний чек, топ-3 по выручке, low-stock 5. `TelegramBindingController` (status/bind/unbind) + UI секция с deep-link и пошаговой инструкцией. На стейдже бот в disabled-mode (`Telegram__BotToken` не задан) — UI показывает «Бот не настроен».
3. **i18n базовая**: react-i18next 17 + i18next 26, ресурсы inline (без fetch). `ru.json`/`en.json` с разделами common/nav/dashboard/products/settings/demoSeed/shortcuts/toast. `LanguageSwitcher` в sidebar. AppLayout (11 секций + 26 nav-ссылок) и DashboardPage полностью переведены. kz — TODO для следующих итераций (нужен живой переводчик). Остальные ~25 страниц — инфраструктура готова, добавление переводов механическое.
4. **MinIO/S3**: `IObjectStorage` абстракция, Local + MinIO impls. Stage compose обновлён (minio container + Storage__* env). Bucket `food-market-uploads` создаётся автоматически на старте. Runtime fallback на Local если MinIO config пустой. `ProductImagesController` отрефакторен. `UploadsController` стримит из storage с cache-control 7d. Лог стейджа подтверждает: «MinIO bucket food-market-uploads created».
**Покрытие тестами на стейдже:** stage-ui-signalr (1) + stage-ui-telegram (3) + stage-ui-i18n (3) + stage-ui-minio (1) = **8/8 ✓**.