CameraScanner (components/CameraScanner.tsx) — порт из sklad'a @zxing/
browser + @zxing/library. Непрерывное сканирование: окно не закрывается
между сканами, EAN13/EAN8/UPC/Code128/ITF. Подавление повтора 1.5с (в
кадре товар распознаётся десятки раз в секунду). Вибрация 40мс + flash
зелёный/красный + анимация scanPop/scanRing.
SupplyScanPage (/purchases/supplies/scan):
- Выбор поставщика (search по /counterparty-search), склада, валюты.
- Кнопка 'Сканировать камерой' → <CameraScanner /> на полный экран.
- Alt: аппаратный сканер — <input> в details-блоке, Enter = +1.
- Каждый скан: GET /product-by-barcode → если нашёлся, +1 к
существующей строке или новая сверху. Цена подставляется last-
purchase-price (из последней Posted supply-line по этому товару).
- Неизвестный штрихкод: feedback 'Нет в каталоге', вибрация ошибки.
Товар создавать — отдельный переход на /products/new (future wiring).
- Прогресс сохраняется в localStorage ('fm.supply-scan.rows') —
перезагрузка не теряет; очищается после успешного сохранения.
- Save → POST /api/purchases/supplies (существующий endpoint), статус
Draft; редирект в /purchases/supplies/:id для проверки/проведения.
InvoicesController.ProductByBarcode теперь возвращает ещё и
lastPurchasePrice (из последней Posted supply-line).
@zxing/browser@0.1.5 + @zxing/library@0.23.0 добавлены в deps.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
58 lines
3.8 KiB
Markdown
58 lines
3.8 KiB
Markdown
# Supply + Inventory mobile — прогресс
|
||
|
||
Задача: добавить в food-market два мобильных варианта приёмки (по фото
|
||
накладной + сканированием штрихкодов) и инвентаризацию с телефона с
|
||
офлайн-режимом. Образец логики — `~/ref/sklad/sklad/` (read-only); но
|
||
документы создаются в НАШЕЙ базе (Supply/Inventory), а не черновиками
|
||
в МойСклад.
|
||
|
||
Все три фичи — основные (видны в простом режиме), доступны Admin +
|
||
Storekeeper.
|
||
|
||
## Чек-лист
|
||
|
||
### Приёмка
|
||
|
||
- [x] 1. **Приёмка по фото/PDF накладной** — загрузка, фоновое
|
||
распознавание через Claude CLI (`claude -p --output-format json`,
|
||
промпт из `ClaudeCliInvoiceExtractor.cs`), запуск локально
|
||
или через ssh на RemoteHost. Статусы: `queued → extracting →
|
||
review | failed`. Платные API-ключи не заводим.
|
||
- [x] 2. **Экран проверки накладной.** Редактируемые строки, помощь в
|
||
сопоставлении с товаром (barcode → saved-mapping → ручной), создание
|
||
товара прямо из строки, проверка «итого», предложение создать
|
||
контрагента. Коммит → наш Supply (Draft).
|
||
- [x] 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]`.
|