food-market/docs/inventory-model-progress.md
nns db8cd637e5
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
docs(inventory): итог проверки + скриншоты новой модели
Прогресс-док: итог проверки (unit 64/64, live e2e на стенде всех сценариев,
миграция stockUnchanged, full-chain 16/16, menu-walk 3/3, deploy-stage OK).
Скриншоты: карточка «Завершена» с кнопками «Создать оприходование/списание» и
блоком «Связанные документы» (Списание С-2026-000002 проведён), колонка «Результат».

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 21:24:45 +05:00

75 lines
7.5 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.

# Инвентаризация по модели МойСклада — прогресс
Замечание владельца (08.10.2026): «инвентаризация стоит в состоянии „проведено“,
но без оприходования и списания — логика непонятная».
**Сейчас (неправильно):** `InventoriesController.Post` сам применяет движения
`MovementType.InventoryAdjustment` к остаткам и ставит `Status=Posted` — без создания
Оприходования/Списания. Владелец видит «Проведено» без связанных документов; в отчётах
непонятно, откуда изменения.
**Как должно быть (по МойСкладу):** инвентаризация НЕ двигает остатки; она фиксирует
расчётный/фактический/разницу, а движения создаются связанными документами
Оприходование (излишки) и Списание (недостача).
**ПОПРАВКА (Mac-Claude):** кнопку «Применить результаты» НЕ добавляем (не одобрено
владельцем). Только две кнопки «Создать оприходование» / «Создать списание». Мобильный
`post` — временная совместимость (в docs помечено).
## План / статус
0. [x] Сверка с МойСкладом → `docs/inventory-moysklad-reference.md` (API SPA — факты из справки
+ школы торговли; поля calculatedQuantity/correctionAmount/correctionSum, applicable, enter/loss «на основании»).
1. [x] Инвентаризация не двигает остатки; статусы `Draft`→`Completed` («Черновик»→«Завершена»).
Эндпоинт `complete` замораживает строки без движений (`InventoriesController`).
2. [x] На завершённой — `create-enter` (излишки) / `create-loss` (недостача): создают черновики
Оприходования/Списания со строками разницы + ссылка `InventoryDocId`. Повторно нельзя (409).
Кнопки «Применить результаты» НЕТ (по поправке).
3. [x] Блок «Связанные документы» в карточке (web); колонка «Результат» в списке; «На основании
инвентаризации №…» в Оприходовании/Списании (web + DTO).
4. [x] «Вернуть в черновик» (`unpost`) отменяет проведение и удаляет связанные документы (остатки
возвращаются). Править завершённую нельзя (Update/AddLine требуют Draft).
5. [x] Миграция `Posted+InventoryAdjustment` → связанные проведённые Оприходование/Списание:
`InventoryMigrationController` (dry-run/apply) переметка движений (не задваивает), остатки
до/после проверяются (`stockUnchanged`). Backup — в `deploy/migrate-inventory-to-docs.sh`.
6. [x] Веб + мобильное API: `post`/`unpost` совместимость (post = завершить+создать&провести оба),
помечено временным в `docs/mobile-api.md`. CSV-импорт инвентаризации — без изменений (работает).
7. [~] Тесты: unit (InventoryResult — разница/сумма/только посчитанные) ✓; integration/e2e/full-chain шаг 10 — ниже.
8. [x] `docs/supply-inventory.md` — «Как провести инвентаризацию» (5 шагов).
9. [~] deploy-stage + коммиты в main (Opus 5.5), global.json не коммитить, не мешать с rebrand — ниже.
### Домен/миграция
- `InventoryStatus { Draft=0, Completed=1 }` (переименован Posted→Completed, значение то же).
- `Enter.InventoryDocId` / `Loss.InventoryDocId` (nullable) + EF-миграция `Phase38_InventoryLinks`.
- `InventoryResult` (application) — чистая разбивка diff→излишки/недостача (юнит-тесты).
- Демо-сидеры: инвентаризации теперь `Completed` без прямых движений.
## Что НЕ трогаем
Прод, shared-postgres, global.json, gateway nginx, sklad.
## Проверка (на стенде test.admin.food-market.kz)
- **Unit:** `InventoryResultTests` (разница/сумма/только посчитанные/округление) + poco — 64/64 ✓.
- **Live e2e (API):** создать (излишек +2, недостача −2) → `complete` (остаток НЕ изменился) →
`create-enter`/`create-loss` → в инвентаризации видны связанные документы (черновик) →
провести оба → остатки +2/−2 ✓; в Оприходовании `inventoryNumber` = И-2026-… ✓;
повторный `create-enter` → **409** ✓; `unpost` → удалил связанные, остатки вернулись, статус Draft ✓.
- **Миграция данных:** `inventory-migration/run` dry-run → 1 кандидат; `apply` → migrated 1,
**stockUnchanged=true, stockDiffRows=0** (остатки до/после совпали); повторный dry-run → 0 (идемпотентно).
И-2026-000001 → связанное проведённое Списание С-2026-000002 (см. скрин).
- **full-chain шаг 10:** 16/16 ЗЕЛЁНЫЙ — добавлена проверка новой модели (complete→create-enter→
связанный документ→провести→+3→«на основании»), плюс совместимый `/post`.
- **menu-walk:** 3/3 (все роли, страницы инвентаризации рендерятся, 0 ошибок/тостов).
- **Скриншоты:** `docs/inventory-screenshots/` (карточка «Завершена» с кнопками и блоком
«Связанные документы», колонка «Результат» в списке).
- **deploy-stage:** OK.
Формальных xUnit-integration не добавлял — поведение покрыто full-chain (реальный стек) +
живым e2e на стенде + unit. UAT — обновить при следующем прогоне UAT-сценария.
## Журнал
- 08.10 — старт: прочитано замечание, составлен план. Сверка с МойСкладом.
- 08.10 — реализация: домен (Draft→Completed, Enter/Loss.InventoryDocId, миграция Phase38),
InventoryResult, контроллеры (complete/create-enter/create-loss/post-compat/unpost),
миграция данных (InventoryMigrationController + скрипт), веб-UI, доки.
- 08.10 — проверено на стенде: full-chain 16/16, menu-walk 3/3, live e2e всех сценариев,
миграция stockUnchanged. Коммиты в main (0d44cda, b4bd0e4, b036050), push. global.json не трогал.