# 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. `` chips. Применено к /reports/sales, /reports/stock, /reports/profit, /catalog/products. - [x] **3. Quick-actions (Cmd+J)** — `` отдельно от Cmd+K. 14 действий + recents из localStorage. ↑↓/Enter/Esc nav. - [x] **4. Inline-edit в таблицах** — `PATCH /api/catalog/products/{id}/price` (необяз. priceTypeId). `` с dblclick → input. Optimistic update + revert при ошибке. На странице товаров системная розничная цена редактируется. - [x] **5. Импорт CSV для товаров** — POST `/api/catalog/products/import-csv` с массивом rows. Клиент парсит CSV (auto-detect разделитель ,/;), сервер commit'ит одной транзакцией. autoCreateGroup создаёт новые группы. `` модалка с preview + подсветкой ошибок. - [x] **6. Экспорт CSV/XLSX** — endpoint'ы `/export` на 5 контроллерах: products, counterparties, stock, retail-sales, supplies. Reuse существующего `ReportExport.Csv/Xlsx` (CsvHelper + ClosedXML). `` 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'ом ✓.