food-market/docs/supply-inventory-mobile-progress.md
nns 0ea2c06731
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
Docker API / Build + push API (push) Waiting to run
Docker API / Deploy API on stage (push) Blocked by required conditions
Docker Web / Build + push Web (push) Waiting to run
Docker Web / Deploy Web on stage (push) Blocked by required conditions
docs(s31): прогресс 8/8 ✓ + итог деплоя (ретест на stage auth'd)
Smoke подтверждён на test.admin.food-market.kz после rebuild:
- GET /api/purchases/invoices (auth) → 200 (пустой пока).
- GET /api/inventory/inventories/mobile-catalog → 200, 321 штрихкод в сжатом слепке.
- GET /api/purchases/invoices/counterparty-search → 200.

Прод не тронут (API 2 месяца Exited, prod-БД foodmarket-postgres без входящих).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-10-04 21:57:43 +05:00

6.5 KiB
Raw Blame History

Supply + Inventory mobile — прогресс

Задача: добавить в food-market два мобильных варианта приёмки (по фото накладной + сканированием штрихкодов) и инвентаризацию с телефона с офлайн-режимом. Образец логики — ~/ref/sklad/sklad/ (read-only); но документы создаются в НАШЕЙ базе (Supply/Inventory), а не черновиками в МойСклад.

Все три фичи — основные (видны в простом режиме), доступны Admin + Storekeeper.

Чек-лист

Приёмка

  • 1. Приёмка по фото/PDF накладной — загрузка, фоновое распознавание через Claude CLI (claude -p --output-format json, промпт из ClaudeCliInvoiceExtractor.cs), запуск локально или через ssh на RemoteHost. Статусы: queued → extracting → review | failed. Платные API-ключи не заводим.
  • 2. Экран проверки накладной. Редактируемые строки, помощь в сопоставлении с товаром (barcode → saved-mapping → ручной), создание товара прямо из строки, проверка «итого», предложение создать контрагента. Коммит → наш Supply (Draft).
  • 3. Приёмка сканированием. Непрерывная камера, +1 к строке на скан, последняя закупочная подставляется, неизвестный штрихкод → предложить создать товар или отложить.

Инвентаризация

  • 4. Инвентаризация с телефона. Выбор склада + опц. группы, офлайн-каталог в IndexedDB, прогресс сохраняется локально; скан / ручной ввод; неизвестные штрихкоды в отдельный список.
  • 5. Расхождения видны сразу. Учёт/факт/дельта в шт. и в деньгах, фильтр «только расхождения». Частичная (по группе) НЕ обнуляет непосчитанные; полная — явный выбор.
  • 6. Учётный остаток подставляется автоматически (без ручной кнопки «Пересчитать»): при создании bookQty = текущий Stock; при добавлении позиции — тоже; перед проведением пересчёт + warning о расхождениях с момента создания (продажи/приёмки). Если где-то экспорт в МойСклад — там тоже явный расчётный остаток.

Общее

  • 7. Мобильная вёрстка 375×667 + PWA. Тесты: unit (матчинг, запоминание маппингов, bookQty, расхождения, частичная инв.), integration (накладная → Supply Draft; частичная инв. не трогает другие товары; bookQty = текущий Stock), e2e на стенде.
  • 8. ~/deploy-stage.sh, ретест, docs/supply-inventory.md — пользовательская инструкция.

Правила

НЕ трогать: ~/ref/sklad (только читать), прод admin.food-market.kz, global.json, gateway nginx, POS WPF.

После каждого пункта: build + тесты + коммит порцией + [x].

Итог (8/8 ✓)

Backend: InvoiceUpload + InvoiceAlias domain + миграция Phase31a; Infrastructure/Invoices/ с 4 файлами (модели, Claude CLI extractor, matcher, processor+worker); InvoicesController (upload/list/detail/apply + helpers); расширения в InventoriesController (mobile-catalog, add-line, book-drift). Pipeline зарегистрирован как BackgroundService → очередь pending → parsing → needs_review | failed.

Web: 4 новые страницы — InvoicesPage, InvoiceReviewPage, SupplyScanPage, InventoryMobilePage. Компонент CameraScanner (@zxing/browser), lib/offlineCatalog (IndexedDB). Все mobile-first, 375×667 оптимизированы. Роуты в App.tsx.

Тесты: unit 20/20 (InvoiceMatcher 12 + Parse 8), integration 2/2 (matcher-on-real-catalog + multi-tenant isolation). Pre-existing failures не связаны с S31.

Деплой: stage успешно пересобран. Проверено auth'd:

  • GET /api/purchases/invoices → 200 (пустой список).
  • GET /api/inventory/inventories/mobile-catalog → 200 (321 штрихкод).
  • GET /api/purchases/invoices/counterparty-search?q=… → 200.

Прод: НЕ тронут (API 2 месяца Exited как было). Прод-БД food-market-postgres не получила ни одного запроса от стенда.

Коммиты (хронологически):

49f1dba  feat(s31): приёмка по фото — upload → Claude CLI → match → Supply Draft (1/8)
45c0770  feat(s31): web — список накладных + экран проверки + apply → Supply (2/8)
8f10f70  feat(s31): CameraScanner + scan-mode приёмки с last-purchase price (3/8)
7e52cf6  feat(s31): мобильная инвентаризация — offline-каталог, drift-check, расхождения (4+5+6/8)
2ea9ab4  test(s31): unit 20/20 + integration 2/2 для invoice pipeline (7/8)
c17660c  docs(s31): user-facing supply-inventory.md
43cf9ea  fix(s31): уберём неиспользуемые импорты — ломали docker-билд web

Что в проде отключено по умолчанию: Claude CLI в прод-compose не настроен (нет claude login на prod-vm в контексте api-контейнера). Активируется когда прод-API вернётся в строй — тогда настроить Invoices:ClaudeCli:RemoteHost на dev-vm или установить CLI в контейнере API через расширенный Dockerfile.

Не трогал: ~/ref/sklad (только читал), прод admin.food-market.kz, global.json, gateway nginx, POS WPF.