Backend-pipeline по образцу ~/ref/sklad/sklad/Invoices/, но документы
создаются в НАШЕЙ базе (Supply), не в МойСкладе.
Домен (food-market.domain/Purchases/InvoiceUpload.cs):
- InvoiceUpload: файл + статус (pending/parsing/needs_review/applied/failed)
+ распознанная шапка + ParsedJson (jsonb) + ссылка на созданный Supply.
- InvoiceAlias: запомненное соответствие (SupplierKey, SourceCode|
SourceNameNorm) → ProductId. Два частично-уникальных индекса (filter
SourceCode/SourceNameNorm IS NOT NULL).
Миграция Phase31a (идемпотентная ADD/CREATE IF NOT EXISTS; [Migration]+
[DbContext]).
Infrastructure/Invoices/:
- IInvoiceExtractor + ParsedInvoice/InvoiceLine DTO.
- ClaudeCliInvoiceExtractor — порт из sklad: 'claude -p --output-format
json', промпт один-в-один (копировать все строки, null если не читается,
barcode != supplier_code, сверка с «Итого»). Поддерживает local и
Invoices:ClaudeCli:RemoteHost (ssh+scp+cleanup).
- InvoiceMatcher — barcode → alias → none. По названию НЕ ищем
(sklad-урок: 2-5 ошибок из 10, подмена хуже пустой строки).
- InvoiceProcessor + InvoiceWorker (BackgroundService):
pending → parsing → needs_review | failed. SweepAsync раз в час
удаляет файлы старше Invoices:KeepFilesDays (default 7); строки
остаются. Multi-tenant через IgnoreQueryFilters + явный OrgId.
Controller api/purchases/invoices:
- POST /upload (SuppliesEdit, 60 MB max): файлы в uploads/invoices/{yyyy-
MM}/, запись в pending.
- GET /, GET /{id} — список + детали со строками.
- GET /{id}/file — отдать файл.
- DELETE /{id} — удалить запись + файл.
- PUT /{id}/lines — правки шапки + строк + авто-upsert InvoiceAlias
для каждой строки с MatchedBy=manual|alias (два ключа: по code и по
name_norm).
- POST /{id}/apply — создать Supply (Draft) с данным поставщиком/
складом/валютой, статус → applied, SupplyId ссылается, файл удаляется.
- GET /product-by-barcode, /counterparty-search — помощь UI.
Build зелёный. Web + тесты — следующими шагами.
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-ключи не заводим.
|
||
- [ ] 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]`.
|