diff --git a/docs/uat-coverage-progress.md b/docs/uat-coverage-progress.md new file mode 100644 index 0000000..445e709 --- /dev/null +++ b/docs/uat-coverage-progress.md @@ -0,0 +1,77 @@ +# UAT — измеримое покрытие каждого элемента каждого экрана + +Цель: матрица покрытия, построенная ИЗ КОДА, + браузерный прогон → `docs/uat-coverage.html` +с % по экрану/приоритету/общим. Цели: P1–P3 ≥95%, P4 ≥70%. НЕ перепроверять уже покрытое. + +Легенда: [x] готово · [~] частично · [ ] не начато. + +## Инструменты +- `tests/e2e/tools/extract-controls.ts` — статически из `web/src/pages` достаёт все + интерактивные элементы экрана (поиск/фильтры/сортировки/пагинация/экспорт/тумблеры/ + действия) → `docs/uat-coverage.expected.json`. Фильтр списка отличается от поля формы + по `setPage` в обработчике. 36 экранов, 195 элементов. +- `tests/e2e/scenarios/stage-ui-uat-coverage.spec.ts` — браузерный прогон: задействует + каждый элемент, пишет `tests/e2e/reports/uat-covered.json`. +- `tests/e2e/tools/build-coverage.ts` — сводит → `docs/uat-coverage.{json,html}` с %. + +## Статус покрытия (на момент смены приоритета 09.10 — переход на ALL MARKET) +Цифры в `docs/uat-coverage.html` (и `uat-coverage.json`). Прогон на стенде, temp-орг с сидом. + +| Приоритет | Покрыто | Цель | +|---|---|---| +| **Общее** | **61% (119/195)** | — | +| P1 | 84% (27/32) | 95% | +| P2 | 86% (12/14) | 95% | +| P3 | 76% (48/63) | 95% | +| **P1–P3** | **80% (87/109)** | **95%** | +| P4 | 37% (32/86) | 70% | + +Прогресс по итерациям: базовый 50% → после доработки хендлеров (пагинация со сбросом +поиска, обобщённое создание/сохранение/удаление, период-фильтры, доп. сид: чек/приёмка/ +оприходование/списание/инвентаризация/возврат) → 61% (P1–P3 71%→80%, P4 24%→37%). + +### Что уже покрыто хорошо (из кода × браузер) +- По типам: **export 5/5, sort 60/77, toggle 2/2, search 18/25, filter (часть), pagination + (где есть данные)**. Действия create/save — частично (обобщённый CRUD-хендлер). +- Инструменты рабочие: экстрактор (195 элементов из 36 экранов), браузерный прогон, HTML с %. + +### Что НЕ успел (продолжить после перехода на ALL MARKET) +Цели (P1–P3 ≥95%, P4 ≥70%) НЕ достигнуты — осталось добрать ~22 элемента P1–P3 и ~28 P4: +- **Сортировки с динамическим/условным заголовком** (ProductsPage `systemPrice`→имя типа цены, + `vat`→колонка только при вкл. НДС): экстрактор доработан ловить строковый фолбэк + (`header: expr ?? 'Текст'`) — нужно перегенерировать expected и прогнать ещё раз. +- **Фильтры со СМЫСЛОМ** (правильные строки по известным данным): сейчас проверяется, что + контрол шлёт новый запрос; семантику части списков держит filters-sweep. Добить smысл для + продаж (период/оплата), приёмок (поставщик/склад/статус/оплата), движений (тип/товар/период), + денег (счёт/период/тип), отчётов (период/группировки/склад/группа на дату). +- **Действия документов** post/unpost на списках money/transactions, invoices (сейчас — наличие + элемента); довести до реального POST с проверкой 2xx. +- **P4 save/delete**: обобщённый хендлер покрывает простые CRUD-модалки; формы со множеством + обязательных полей (счета/точки/сотрудники/настройки) требуют адресного заполнения. +- **Пагинация** на экранах без сид-данных: отрисовывается только при total>0 — досидить или + считать покрытой по общему компоненту. +- nightly: добавить `stage-ui-uat-coverage` в ночной прогон (пока не добавлено). + +Запуск: `cd tests/e2e && pnpm exec tsx tools/extract-controls.ts` (матрица) → +`pnpm exec playwright test stage-ui-uat-coverage` (прогон) → `pnpm exec tsx tools/build-coverage.ts` (HTML). + +## Найдено Mac-Claude (быстрые фиксы — сделаны) +1. **«Проверка данных» на Демо — все 0, lastCheckedAt=null.** Hangfire-джоба `DataQualityJob` + зарегистрирована (ежедневный cron 02:20 UTC, идёт по всем активным орг), и `RecomputeAsync` + корректна — просто ночной прогон ещё не отрабатывал после пересева Демо. Фикс: разовый + `BackgroundJob.Enqueue(DataQualityJob)` при старте → считается сразу после деплоя/пересева. + **Реальные числа Демо (стенд, после фикса):** total 1276 · + без группы 0 · **без цены продажи 718** · без штрихкода 0 · дубль ШК 0 · + **возможный дубль (имя+ед.) 558** (включая 4× «"BIOBLAS" шампунь д/волос 360мл») · + товары в минусе 0. `lastCheckedAt` проставлен. +2. **Внутренний ШК с ведущим 0 («0201259508594»).** `InternalBarcode.PickPrefix` брал «02» + (ведущий 0 → зона UPC-A, риск совпасть с реальным товаром). Фикс: берём 2x из + restricted-circulation 20–29 (без ведущего нуля), не пересекаясь с весовыми префиксами + орг; «02» — крайний резерв. Для весовых — короткий «27+5» по настройке (отдельно). + **Проверка на стенде:** новые коды — `2021712729230`, `2043662520927`, `2084330808596` + (префикс 20, без ведущего нуля). Существующие коды НЕ мигрировали: смена ШК ломает + ссылки, а отличить ранее сгенерированный «02…» от реального невозможно; генератор + исправлен для всех НОВЫХ товаров. + +## Что НЕ трогаем +Прод, shared-postgres, global.json, gateway nginx, sklad. diff --git a/docs/uat-coverage.html b/docs/uat-coverage.html new file mode 100644 index 0000000..85c8e80 --- /dev/null +++ b/docs/uat-coverage.html @@ -0,0 +1,282 @@ +
| Пр. | Экран | % | Элементы (зелёные покрыты) | |
|---|---|---|---|---|
| P1 | +Здесь пока пусто /catalog/products |
+ 64% 7/11 |
+ + | ✓ search ✓ pagination ✓ export ✓ sort:name ✓ sort:packaging ✓ sort:cost ✗ sort:systemPrice ✗ sort:vat ✗ filter:все ✗ action:delete ✓ action:create | +
| P1 | +Остатки /inventory/stock |
+ 92% 11/12 |
+ + | ✓ search ✓ pagination ✓ export ✓ sort:name ✗ sort:store ✓ sort:unit ✓ sort:quantity ✓ sort:reserved ✓ sort:available ✓ filter:все-склады ✓ toggle:показать-нулевые ✓ toggle:только-минусы | +
| P1 | +Розничные продажи /sales/retail |
+ 100% 9/9 |
+ + | ✓ search ✓ pagination ✓ export ✓ sort:number ✓ sort:date ✓ sort:status ✓ sort:store ✓ sort:total ✓ action:create | +
| P2 | +Смены кассы /money/shifts |
+ 33% 1/3 |
+ + | ✗ pagination ✓ action:print ✗ action:save | +
| P2 | +Приёмки от поставщиков /purchases/supplies |
+ 100% 11/11 |
+ + | ✓ search ✓ pagination ✓ export ✓ sort:number ✓ sort:date ✓ sort:status ✓ sort:supplier ✓ sort:store ✓ sort:total ✓ filter:оплата-все ✓ action:create | +
| P3 | +Контрагенты /catalog/counterparties |
+ 89% 8/9 |
+ + | ✓ search ✓ pagination ✓ export ✓ sort:name ✓ sort:type ✓ sort:phone ✓ sort:country ✗ action:delete ✓ action:save | +
| P3 | +Проверка данных /catalog/data-quality |
+ 0% 0/1 |
+ + | ✗ action:delete | +
| P3 | +Оприходования /inventory/enters |
+ 88% 7/8 |
+ + | ✓ search ✓ pagination ✓ sort:number ✓ sort:date ✓ sort:status ✓ sort:store ✓ sort:total ✗ action:create | +
| P3 | +Инвентаризации /inventory/inventories |
+ 100% 6/6 |
+ + | ✓ search ✓ pagination ✓ sort:number ✓ sort:date ✓ sort:status ✓ action:create | +
| P3 | +Списания /inventory/losses |
+ 89% 8/9 |
+ + | ✓ search ✓ pagination ✓ sort:number ✓ sort:date ✓ sort:status ✓ sort:reason ✓ sort:store ✓ sort:total ✗ action:create | +
| P3 | +Движения /inventory/movements |
+ 88% 7/8 |
+ + | ✓ pagination ✓ sort:occurredAt ✓ sort:type ✓ sort:product ✗ sort:store ✓ sort:quantity ✓ sort:documentType ✓ filter:все-склады | +
| P3 | +Отчёт «Деньги» /money/report |
+ 0% 0/1 |
+ + | ✗ filter:period | +
| P3 | +Долги поставщикам /money/supplier-debts |
+ 0% 0/2 |
+ + | ✗ action:post ✗ action:save | +
| P3 | +Платежи и ордера /money/transactions |
+ 38% 3/8 |
+ + | ✓ search ✗ pagination ✓ filter:все-статусы ✓ filter:все-типы ✗ action:post ✗ action:unpost ✗ action:delete ✗ action:save | +
| P3 | +Накладные /purchases/invoices |
+ 100% 1/1 |
+ + | ✓ action:unpost | +
| P3 | +Возвраты поставщикам /purchases/supplier-returns |
+ 100% 8/8 |
+ + | ✓ search ✓ pagination ✓ sort:number ✓ sort:date ✓ sort:status ✓ sort:supplier ✓ sort:total ✓ action:create | +
| P3 | +Данных для отчёта нет /reports/sales |
+ 0% 0/1 |
+ + | ✗ filter:period | +
| P3 | +Остатки пусты /reports/stock |
+ 0% 0/1 |
+ + | ✗ filter:period | +
| P4 | +Импорт из МойСклад /admin/import/moysklad |
+ 0% 0/1 |
+ + | ✗ action:delete | +
| P4 | +Журнал изменений /audit-log |
+ 0% 0/6 |
+ + | ✗ search ✗ pagination ✗ filter:sel1 ✗ filter:sel2 ✗ filter:все ✗ filter:period | +
| P4 | +Типы цен /catalog/price-types |
+ 0% 0/6 |
+ + | ✗ search ✗ pagination ✗ sort:name ✗ sort:isRequired ✗ action:delete ✗ action:save | +
| P4 | +Группы товаров /catalog/product-groups |
+ 83% 5/6 |
+ + | ✓ search ✓ pagination ✓ sort:name ✓ sort:path ✗ action:delete ✓ action:save | +
| P4 | +Кассы /catalog/retail-points |
+ 89% 8/9 |
+ + | ✓ search ✓ pagination ✓ sort:name ✓ sort:code ✓ sort:store ✓ sort:address ✓ sort:isActive ✗ action:delete ✓ action:save | +
| P4 | +Склады /catalog/stores |
+ 89% 8/9 |
+ + | ✓ search ✓ pagination ✓ sort:name ✓ sort:code ✓ sort:address ✓ sort:isMain ✓ sort:isActive ✗ action:delete ✓ action:save | +
| P4 | +Единицы измерения /catalog/units |
+ 75% 3/4 |
+ + | ✓ search ✓ pagination ✓ sort:name ✗ action:delete | +
| P4 | +Инвентаризация с телефона /inventory/mobile |
+ 0% 0/1 |
+ + | ✗ action:post | +
| P4 | +Перемещения /inventory/transfers |
+ 0% 0/7 |
+ + | ✗ search ✗ pagination ✗ sort:number ✗ sort:date ✗ sort:status ✗ sort:total ✗ action:create | +
| P4 | +Карты лояльности /loyalty/cards |
+ 0% 0/3 |
+ + | ✗ search ✗ pagination ✗ sort:cardNumber | +
| P4 | +Программы лояльности /loyalty/programs |
+ 0% 0/5 |
+ + | ✗ search ✗ pagination ✗ sort:name ✗ action:delete ✗ action:save | +
| P4 | +Счета и кассы /money/accounts |
+ 25% 1/4 |
+ + | ✓ search ✗ pagination ✗ action:delete ✗ action:save | +
| P4 | +Статьи расходов /money/expense-items |
+ 75% 3/4 |
+ + | ✓ search ✓ pagination ✗ action:delete ✓ action:save | +
| P4 | +Акции и промокоды /promotions |
+ 0% 0/4 |
+ + | ✗ search ✗ pagination ✗ action:delete ✗ action:save | +
| P4 | +Оптовые отгрузки /sales/demands |
+ 0% 0/8 |
+ + | ✗ search ✗ pagination ✗ sort:number ✗ sort:date ✗ sort:status ✗ sort:customer ✗ sort:total ✗ action:create | +
| P4 | +Роли сотрудников /settings/employee-roles |
+ 50% 2/4 |
+ + | ✓ search ✓ pagination ✗ action:delete ✗ action:save | +
| P4 | +Сотрудники /settings/employees |
+ 50% 2/4 |
+ + | ✓ search ✓ pagination ✗ action:delete ✗ action:save | +
| P4 | +Настройки организации /settings/organization |
+ 0% 0/1 |
+ + | ✗ action:delete | +