food-market/docs/sprint18-progress.md
nns 00f248a460 docs(s18): итог — 7/7 ✓ + retest 5 stage scenarios + 44 UI specs
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 19:10:08 +05:00

118 lines
7.3 KiB
Markdown
Raw 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 18 — TODO cleanup + P0 fix + UX polish
Цель: разгрести оставшиеся TODO из спринтов 14, 15, 17. Закрыть P0
из performance-baseline (race в GenerateNumberAsync), доделать
HelpTooltip integration, whats-new banner, color contrast, добавить
currency formatter, audit log filters, notification center.
Старт: 2026-06-07 (после Sprint 17). Исполнитель: Claude Opus 4.7.
## Принципы
- Каждый пункт — реальный фикс/измерение, не обещание.
- НЕ трогать: `global.json`, prod admin.food-market.kz, POS WPF.
## Чек-лист
- [x] **1. P0: race в GenerateNumberAsync**`DocumentNumberRetry`
helper с двумя слоями: `WithOrgAdvisoryLockAsync` (PG advisory lock
per (orgHash, docTypeHash)) + `SaveWithRetryAsync` (exp backoff на
оставшихся 23505 от gap-cases). Применено к RetailSalesController
POST. После k6 baseline-replay: 23505 errors = **0** (было 53%).
- [x] **2. HelpTooltip integration**`ListPageShell` расширен
optional `helpTopic` пропом → tooltip рендерится inline в заголовке.
Применено: PromotionsPage, LoyaltyProgramsPage, LoyaltyCardsPage,
OrgAuditLogPage. Для не-ListPageShell страниц (MoySkladImportPage)
— отдельный inline `<HelpTooltip>` под `PageHeader`.
- [x] **3. Whats-new banner toast**`<WhatsNewBanner>` компонент
опрашивает `/api/whats-new` (staleTime=1h), сравнивает `buildVersion`
с `localStorage.fm.lastSeenBuildVersion`. На mismatch + items за
30 дней → узкий emerald banner сверху с count'ом feat/fix + ссылкой
на /whats-new. Кнопка X / клик по ссылке сохраняют новую версию.
Не показывается на buildVersion="dev". Вшит в AppLayout `<main>`.
- [x] **4. Color contrast sweep** — bulk fix: bare `text-slate-400`
на body-text-узлах (empty-states, table-cells, помощи, hints)
`text-slate-500 dark:text-slate-400`. Затронуло 19 файлов:
DashboardWidgets, DataTable, CommandPalette, EmptyStateWithDemo,
ProductPicker, SupplyLineQuickAdd, ProductGroupTree, Field,
ProductImageGallery, ShortcutsOverlay, SuperAdminLayout, + 8 pages.
Иконки (text-slate-400 на SVG) оставлены — на них axe color-contrast
не срабатывает (decorative).
- [x] **5. Currency formatter**`useFormatCurrency()` хук в
`lib/useFormatCurrency.ts`. Берёт `defaultCurrencySymbol` из
useOrgSettings() + локаль из i18next. Возвращает stable `fmt(value, opts?)`.
DashboardWidgets (TopProducts/RecentSales/Margin) переведены на хук
— захардкоженный `₸` исчез из widget'ов. Бэкап fallback на тенге если
settings ещё не загрузились.
- [x] **6. Audit log UI filters** — OrgAuditLogPage расширен полями:
«Кто» (Select из /api/employees), «Дата с» / «по» (`<input type="date">`),
+ кнопка «Сбросить фильтры». Все 5 фильтров (entityType, action,
userId, from, to) триггерят refetch; параметры передаются в URL
query. Backend уже умел эти параметры (`OrgAuditLogController.List`).
- [x] **7. Notification center**`<NotificationCenter>` компонент
в sidebar footer'е. Bell icon с unread badge (max 9+). Popover с
максимум 30 последних событий (SalePosted/SupplyPosted/LowStock через
существующий `useNotificationsHub`). Каждое событие clickable: ведёт
на документ. «Очистить» обнуляет ленту. Esc / click-outside закрывают.
Storage: in-memory (ephemeral) — для постоянной истории есть /audit-log.
## Журнал
### 2026-06-07 старт
Sprint 17 закрыт (7/7 ✓). Поехали по TODO cleanup.
### 2026-06-07 п.1 (P0 race fix)
Сначала ретрай-loop 5→10 на 23505 в `SaveOrFkErrorAsync` — сократил
ошибки 53%→24%→21%, но не убрал. Перешёл на PostgreSQL advisory
lock: `pg_advisory_xact_lock(orgHash, docTypeHash)` внутри transactions.
После — 0 ошибок 23505 на k6 baseline-replay (5 VUs, 100 RPS, single
org). Осталось 31% 40001 Serializable conflict'ов на stock_movements —
это другой issue (over-sell prevention), решается отдельно.
### 2026-06-07 п.2-3 (HelpTooltip + WhatsNewBanner)
HelpTooltip integration — расставлен в 4 страницах через ListPageShell
prop + 1 страницу через inline (MoySklad). WhatsNewBanner — узкий toast
сверху layout'a, dismiss persistent в localStorage.
### 2026-06-07 п.4 (color contrast)
Bulk-sed по 19 файлам — `text-slate-400` в текстовом content'е
заменён на `text-slate-500 dark:text-slate-400`. Иконки оставлены.
Получено 2 raunda doubled-class'ов от sed (text-slate-500
dark:text-slate-500 dark:text-slate-400) — почищено отдельным perl-passом.
### 2026-06-07 п.5-7 (currency + audit filters + notifications)
`useFormatCurrency()` + интеграция в DashboardWidgets. OrgAuditLogPage
получил Select сотрудников + 2 date-input'a + кнопку сброса.
NotificationCenter с bell-icon в sidebar — реюзает useNotificationsHub.
### 2026-06-07 deploy + retest
Deploy через `~/deploy-stage.sh` → test.admin.food-market.kz. После
первого деплоя — 404 на `/api/employees` (фронт обращался по
несуществующему пути; реальный — `/api/organization/employees`).
Hotfix: правильный endpoint + DTO mapping (lastName+firstName+
middleName → fullName на клиенте). Второй deploy + retest:
- **stage-smoke**: 5/5 ✓
- **stage-audit-log** (api): 7/7 ✓
- **stage-2fa**: 6/6 ✓
- **stage-catalog**: 6/6 ✓
- **stage-inventory**: 8/8 ✓
- **stage-pos**: 7/7 ✓
- **stage-reports**: 8/8 ✓
- **Playwright UI-1..16** (44 specs): 44/44 ✓ за 3.2 минуты
- **UI-10 audit-log (с новыми фильтрами)**: 2/2 ✓ за 22с
## Итог
Все 7 пунктов ✓. Локальные цифры:
- **P0 race**: 23505 errors 53% → **0** в локальной k6 baseline-replay
(k6 на stage-хосте не установлен → итоговая верификация in-code
через advisory lock; стресс-проба остаётся для следующего раунда
на dev-vm с установленным k6).
- **HelpTooltip**: 5 страниц получили deep-link на /help#topic.
- **WhatsNewBanner**: 1 emerald баннер в AppLayout, dismissible.
- **Contrast**: 19 файлов почищено, WCAG-AA для body text.
- **Currency**: 1 hook + 4 интеграции в DashboardWidgets.
- **Audit filters**: 5 серверных фильтров теперь имеют UI.
- **Notifications**: bell-popover с 30 событий, 3 типа, in-memory.
- **Regression**: 5 stage-сценариев + 44 Playwright UI specs зелёные.