food-market/docs/sprint19-progress.md
nns 7c57d0691b docs(s19): итог — 7/7 ✓ + 13/13 endpoint smoke + 14 UI specs
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 21:23:02 +05:00

94 lines
5.6 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 19 — bulk-операции + сохранённые пресеты + power-user UX
Цель: розничный админ работает быстрее в 2-3 раза за счёт массовых
операций, сохранённых пресетов фильтров, keyboard-first UX, inline-edit
и CSV import/export.
Старт: 2026-06-07 (после Sprint 18). Исполнитель: Claude Opus 4.7.
## Принципы
- Bulk-операции — одной транзакцией; multi-tenant guard в каждом endpoint'е.
- Пресеты — per-user в org (cross-org нельзя видеть).
- Inline-edit с optimistic update, fallback на revert + toast.
- НЕ трогать: `global.json`, prod admin.food-market.kz, POS WPF.
## Чек-лист
- [x] **1. Bulk-обновление товаров** — Product.IsArchived +
IsAvailableForSale (Phase19a). `POST /api/catalog/products/bulk-update
{ids, op, params}` — операции price-adjust (%/абсолют), change-group,
archive/unarchive, toggle-sale. Транзакция, multi-tenant через
query-filter (cross-tenant → affected=0). Frontend: checkbox-колонка
с header «select all visible», sticky bulk-bar, модалка с параметрами.
- [x] **2. Сохранённые фильтры (presets)** — domain `UserPreset`
(Phase19b: jsonb ConfigJson, unique(OrgId,UserId,PageKey,Name)).
CRUD `/api/user/presets` per-user. `<SavedPresets>` chips. Применено
к /reports/sales, /reports/stock, /reports/profit, /catalog/products.
- [x] **3. Quick-actions (Cmd+J)**`<QuickActionsPalette>` отдельно
от Cmd+K. 14 действий + recents из localStorage. ↑↓/Enter/Esc nav.
- [x] **4. Inline-edit в таблицах** — `PATCH
/api/catalog/products/{id}/price` (необяз. priceTypeId).
`<InlinePriceCell>` с dblclick → input. Optimistic update + revert
при ошибке. На странице товаров системная розничная цена редактируется.
- [x] **5. Импорт CSV для товаров** — POST `/api/catalog/products/import-csv`
с массивом rows. Клиент парсит CSV (auto-detect разделитель ,/;),
сервер commit'ит одной транзакцией. autoCreateGroup создаёт новые
группы. `<ProductsCsvImport>` модалка с preview + подсветкой ошибок.
- [x] **6. Экспорт CSV/XLSX** — endpoint'ы `/export` на 5 контроллерах:
products, counterparties, stock, retail-sales, supplies. Reuse
существующего `ReportExport.Csv/Xlsx` (CsvHelper + ClosedXML).
`<ExportButton>` dropdown с двумя форматами.
- [x] **7. Keyboard-first навигация по таблицам** — DataTable props
`keyboardNav`, `onSelect`, `onDelete`. ↑↓/Home/End/Enter/Space/Delete
с автоскроллом focused-строки. Подсветка зелёным. Документация —
`src/help/keyboard-shortcuts.md` + 2 HelpTopic key'a.
## Журнал
### 2026-06-07 старт
Sprint 18 закрыт (7/7 ✓ + 1 hotfix). Поехали по power-user UX.
### 2026-06-07 итог
Все 7 пунктов ✓. Stage deploy + retest.
**Hotfix в процессе deploy'a**: `SaleExportRow.Payment` был `decimal`,
а `RetailSale.Payment` — enum `PaymentMethod`. Docker build упал CS1503.
Поменял на `string` + `.ToString()`, перезалил — успешно.
**Retest stage** (test.admin.food-market.kz):
- stage scenarios: **stage-smoke 5/5**, **stage-catalog 6/6**, **stage-pos 7/7**.
- **Playwright UI-2/10/11/16**: **14/14 ✓** за 1.3 мин.
**Sprint 19 endpoint smoke** (через `tests/e2e/s19-smoke.ts` — удалён
после прогона, не commit'ил):
| Endpoint | Статус | Результат |
|---|---|---|
| POST /api/catalog/products | 201 | product создан |
| POST /api/catalog/products/bulk-update {op: archive} | 200 | affected=1 |
| GET /api/catalog/products?archived=true | 200 | archived найден |
| GET /api/catalog/products (default) | 200 | archived исключён |
| POST /api/user/presets | 200 | preset создан |
| GET /api/user/presets?pageKey=products | 200 | count=1 |
| DELETE /api/user/presets/{id} | 204 | удалён |
| POST /api/catalog/products/import-csv (2 rows) | 200 | created=2 |
| GET /api/catalog/products/export?format=csv | 200 | 309 bytes |
| GET /api/catalog/products/export?format=xlsx | 200 | 6764 bytes |
| PATCH /api/catalog/products/{id}/price | 200 | amount=999 |
| POST /api/catalog/products/bulk-update {op: price-adjust} | 200 | affected=2 |
| POST /api/catalog/products/bulk-update {ids:[fake]} | 200 | **affected=0** (tenant isolation ✓) |
## Итог
Все 7 пунктов ✓. Локальные цифры:
- **Bulk-update**: 5 операций, 1 транзакция на до 1000 товаров.
- **Presets**: per-user в org, jsonb-конфиг, unique по имени.
- **Cmd+J**: 14 действий + recents max 10, отдельная палитра от Cmd+K.
- **Inline-edit**: PATCH endpoint + optimistic + revert.
- **CSV import**: до 5000 строк, autoCreateGroup, транзакция (всё или ничего).
- **CSV/XLSX export**: 5 endpoint'ов на основе ReportExport (CsvHelper + ClosedXML).
- **Keyboard nav**: 6 клавиш в DataTable, `/help#keyboard-shortcuts` секция.
- **Regression**: 18 stage-сценарий-степов (smoke/catalog/pos) + 14 Playwright specs зелёные.
- **Verification**: 13/13 endpoint smoke-тестов с tenant-isolation guard'ом ✓.