docs(stock): прогресс negative-stock — что сделано/отложено
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
9ba1edb236
commit
2d1cdd8519
|
|
@ -25,28 +25,45 @@
|
||||||
инвентаризации по минусовым товарам), с авто-закрытием при возврате остатка ≥ 0 и эскалацией.
|
инвентаризации по минусовым товарам), с авто-закрытием при возврате остатка ≥ 0 и эскалацией.
|
||||||
(Источник по МойСкладу: dev.moysklad.ru/doc/api/remap/1.2 report/stock stockMode; webhooks — на сущности.)
|
(Источник по МойСкладу: dev.moysklad.ru/doc/api/remap/1.2 report/stock stockMode; webhooks — на сущности.)
|
||||||
|
|
||||||
## План / статус
|
## План / статус (легенда: [x] готово · [~] частично/заложено · [ ] отложено)
|
||||||
0. [ ] Сверка с МойСкладом (отчёт/вебхуки/разрешение минуса).
|
0. [x] Сверка с МойСкладом (см. выше): у них — только фильтр отчёта `stockMode=negativeOnly`, push/события нет.
|
||||||
1. [ ] Событие при проведении документа → остаток < 0: создать/обновить предупреждение
|
1. [x] Событие при проведении документа → остаток < 0: `NegativeStockAlert` (товар, склад, остаток,
|
||||||
(товар, склад, остаток, документ-причина). Остаток ≥ 0 → закрыть автоматически.
|
документ-причина: тип/номер/автор/время), единая точка — `StockService.ApplyMovementAsync`.
|
||||||
2. [ ] Подсказка причины: есть непроведённая приёмка/черновик → «возможно, не проведена приёмка П-…».
|
Остаток ≥ 0 → закрывается автоматически. Миграция Phase39, частичный уникальный индекс.
|
||||||
3. [ ] Без спама: агрегация (1 уведомление/склад/N мин, по умолч. 15), тихие часы, получатели
|
2. [x] Подсказка причины: API списка отдаёт `hint` «возможно, не проведена приёмка П-… от <поставщик>»
|
||||||
Администратор + Кладовщики склада, вкл/выкл в настройках орг и профиле.
|
(если по товару есть черновик приёмки).
|
||||||
4. [ ] Действие «Пересчитать эти товары»: черновик инвентаризации по складу с этими товарами.
|
3. [~] Без спама: счётчик/баннер — реалтайм-запрос (poll 60с), не спамит. Поля `NotifiedAt`/`EscalatedAt`
|
||||||
5. [ ] Каналы: веб (колокольчик + центр уведомлений + Web Push/VAPID), Telegram (бот),
|
в сущности заложены под фоновую агрегацию/рассылку. **Отложено:** фоновая job (email/telegram
|
||||||
мобильное API (GET /api/notifications, read, создать инвентаризацию), отчёт «Отрицательные».
|
одним сообщением на склад, тихие часы, получатели по ролям/привязке, тумблеры в настройках).
|
||||||
APNs — только заглушка (device tokens + IPushSender), без платного Apple Dev.
|
4. [x] «Пересчитать эти товары»: `POST /api/negative-stock/recount` → черновик инвентаризации по складу
|
||||||
6. [ ] Тесты unit/integration/e2e; деплой; скриншоты.
|
ровно с минусовыми товарами (BookQty = текущий отрицательный остаток), открывается из баннера.
|
||||||
7. [ ] Снять блокировку продажи в минус: касса/POS-синк/офлайн, розница веб, опт, списание,
|
5. [~] Каналы: **веб** — постоянный баннер + фильтр/пометка в остатках ✓; отчёт «Отрицательные» (фильтр
|
||||||
перемещение — проведение в минус РАЗРЕШЕНО (убрать 409 oversell; деньги — счёт в минус запрещён).
|
`negativeOnly`) ✓. **Мобильное API** — `GET /api/negative-stock` + `/count` готовы (iOS читает) ✓.
|
||||||
8. [ ] Касса: предупреждение в строке («на остатке 2 шт — уйдёт в минус»), жёлтый индикатор в шапке
|
**Отложено:** центр уведомлений (realtime-событие NegativeStock), Telegram-рассылка, Web Push
|
||||||
«N товаров в минусе», офлайн по локальным остаткам.
|
(VAPID + SW), APNs-заглушка (device tokens + IPushSender).
|
||||||
9. [ ] Админка: постоянный баннер «N товаров в минусе — проведите инвентаризацию» + «Пересчитать»;
|
6. [~] Тесты: integration **2/2** (минус разрешён → алерт → recount → авто-закрытие; фильтр negativeOnly) ✓;
|
||||||
красная пометка в списках товаров/остатков.
|
full-chain шаг 9/13 переписаны (oversell/отмена приёмки → проведено + предупреждение) ✓.
|
||||||
10. [ ] Мобильное API/iOS: счётчик + список в /api/me или /api/notifications.
|
**Отложено:** unit на агрегацию/дебаунс (нет job), e2e в браузере на баннер. Деплой/скрины — ниже.
|
||||||
11. [ ] Эскалация: минус не закрыт за N часов (по умолч. 24) → повторное уведомление владельцу/админу;
|
7. [x] Снята блокировка продажи в минус: розница, касса (POS-синк), опт, списание, перемещение,
|
||||||
на главной — «Просроченные минусы».
|
возврат поставщику, отмена приёмки. Деньги (минус счёта) — не трогали (другое правило).
|
||||||
12. [~] ОТЛОЖЕНО (поправка владельца) — предварительная себестоимость НЕ делаем.
|
8. [ ] **Отложено** (десктопная Avalonia-касса): предупреждение в строке + жёлтый индикатор в шапке +
|
||||||
|
офлайн по локальным остаткам. (Отдельная поверхность; iOS/касса — Mac-Claude.)
|
||||||
|
9. [x] Админка: постоянный баннер «N товаров в минусе — нужна инвентаризация» (сворачивается, крестиком
|
||||||
|
не закрыть) + «Пересчитать эти товары»; в остатках — красная пометка + фильтр «Только минусы».
|
||||||
|
10. [~] Мобильное API/iOS: `/api/negative-stock/count` + список готовы. Баннер в приложении — Mac-Claude.
|
||||||
|
11. [~] Эскалация: в API есть флаг `overdue` (минус висит дольше N часов, по умолч. 24). **Отложено:**
|
||||||
|
фоновое повторное уведомление владельцу/админу + блок «Просроченные минусы» на главной.
|
||||||
|
12. [ ] ОТЛОЖЕНО (поправка владельца 09.10) — предварительная себестоимость НЕ делаем.
|
||||||
|
|
||||||
|
## Что сделано в этой сессии (ядро, оттестировано и выложено)
|
||||||
|
Разрешение минуса + детекция/авто-закрытие предупреждений + API (список/счётчик/recount/фильтр) +
|
||||||
|
веб-баннер и пометки в остатках + integration-тесты 2/2 + full-chain 9/13. Деплой на стенд.
|
||||||
|
|
||||||
|
## Что отложено (заложен фундамент, нужен отдельный проход)
|
||||||
|
Фоновая рассылка (email/telegram, агрегация/тихие часы/получатели/настройки), эскалация-job и
|
||||||
|
«просроченные минусы», центр уведомлений (realtime-событие), Web Push (VAPID), APNs-заглушка
|
||||||
|
(device tokens + IPushSender), индикаторы в десктопной Avalonia-кассе (в т.ч. офлайн).
|
||||||
|
**DONE не ставим — не все пункты закрыты.**
|
||||||
|
|
||||||
## Что НЕ трогаем
|
## Что НЕ трогаем
|
||||||
Прод, shared-postgres, global.json, gateway nginx, sklad. Расчёт себестоимости (п.12 отложен).
|
Прод, shared-postgres, global.json, gateway nginx, sklad. Расчёт себестоимости (п.12 отложен).
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue