docs(sprint2): P1-16 done — все 7 пунктов выполнены, итог
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
a74fa114d8
commit
a7b82eea86
|
|
@ -56,9 +56,62 @@ query filter. Stock-инвариант: после каждого Post/Unpost
|
||||||
что reference указывает на проведённую приёмку того же поставщика. Защита
|
что reference указывает на проведённую приёмку того же поставщика. Защита
|
||||||
от ухода в минус. Permissions переиспользуют `SuppliesEdit/Post/Delete`.
|
от ухода в минус. Permissions переиспользуют `SuppliesEdit/Post/Delete`.
|
||||||
Тесты: 4 интеграционных.
|
Тесты: 4 интеграционных.
|
||||||
7. [ ] **P1-16 Hangfire dashboard + cleanup** — `Hangfire.Dashboard` с
|
7. [x] **P1-16 Hangfire dashboard + cleanup** — `Hangfire.Dashboard` с
|
||||||
авторизацией только для SuperAdmin. Scheduled: ежедневный cleanup
|
авторизацией только для SuperAdmin. Scheduled: ежедневный cleanup
|
||||||
`StockMovement` старше 2 лет, audit-log старше 90 дней.
|
`StockMovement` старше 2 лет, audit-log старше 90 дней.
|
||||||
|
✅ `Hangfire.PostgreSql` storage на ConnectionStrings:Default. Сервер
|
||||||
|
стартует только если `Hangfire:Enabled=true` (по умолчанию). Dashboard
|
||||||
|
`/hangfire` гейтит `SuperAdminHangfireFilter`. Recurring: `prune-stock-movements`
|
||||||
|
(03:30 UTC, 730 дней) и `prune-audit-log` (03:45 UTC, 90 дней) —
|
||||||
|
`HousekeepingJobs` с `IgnoreQueryFilters` (межтенантно). Тесты:
|
||||||
|
1 unit + 1 интеграционный.
|
||||||
|
|
||||||
|
## Итог
|
||||||
|
|
||||||
|
**Все 7 пунктов выполнены.** Спринт 2 (складские документы P1) завершён 2026-05-28.
|
||||||
|
|
||||||
|
Сводка:
|
||||||
|
- **P1-1 Enter** — оприходование без поставщика (`/api/inventory/enters`, миграция
|
||||||
|
`Phase6a_Enters`); 4 интеграционных теста.
|
||||||
|
- **P1-2 Loss** — списание с enum `LossReason` (`/api/inventory/losses`,
|
||||||
|
`Phase6b_Losses`); 3 интеграционных.
|
||||||
|
- **P1-3 Transfer** — атомарное перемещение пара TransferOut + TransferIn
|
||||||
|
(`/api/inventory/transfers`, `Phase6c_Transfers`); 4 интеграционных, включая
|
||||||
|
проверку «после Post ровно 2 движения, после Unpost ровно 4».
|
||||||
|
- **P1-4 Inventory** — пересчёт с auto-load остатков (`/api/inventory/inventories`,
|
||||||
|
`Phase6d_Inventories`); 3 интеграционных, импорт CSV в UI.
|
||||||
|
- **P1-6 CustomerReturn** — `RetailSale.IsReturn` + `ReferenceSaleId` +
|
||||||
|
`RetailSaleLine.QtyReturned`, эндпоинт `POST /create-return`
|
||||||
|
(`Phase6e_RetailSaleReturns`); 3 интеграционных.
|
||||||
|
- **P1-7 SupplierReturn** — зеркало Supply (`/api/purchases/supplier-returns`,
|
||||||
|
`Phase6f_SupplierReturns`); 4 интеграционных, валидация совпадения поставщика
|
||||||
|
при ссылке на приёмку.
|
||||||
|
- **P1-16 Hangfire** — `Hangfire.PostgreSql` storage, dashboard `/hangfire`
|
||||||
|
с `SuperAdminHangfireFilter`, recurring jobs `prune-stock-movements` (730 дней)
|
||||||
|
и `prune-audit-log` (90 дней); 1 unit + 1 интеграционный.
|
||||||
|
|
||||||
|
**Сборка:** зелёная (`dotnet build src/food-market.api`).
|
||||||
|
**Тесты:** 24 unit + 32 integration = **56 зелёных**.
|
||||||
|
**Web:** `pnpm build` зелёный (5 новых пар list+edit страниц + расширение RetailSale).
|
||||||
|
|
||||||
|
### Новые таблицы
|
||||||
|
`enters`, `enter_lines`, `losses`, `loss_lines`, `transfers`, `transfer_lines`,
|
||||||
|
`inventories`, `inventory_lines`, `supplier_returns`, `supplier_return_lines`
|
||||||
|
+ колонки `retail_sales.IsReturn/ReferenceSaleId`, `retail_sale_lines.QtyReturned`.
|
||||||
|
|
||||||
|
### Новые permissions
|
||||||
|
`TransferEdit` добавлен в `RolePermissions` (Enter/Loss/Inventory/Supplies* —
|
||||||
|
переиспользованы существующие). `All()` обновлён.
|
||||||
|
|
||||||
|
### Stock-инвариант
|
||||||
|
Каждый документ при Post создаёт явные `StockMovement` через `IStockService`
|
||||||
|
в Serializable-транзакции. Post→Unpost — обратные движения тем же документ-id
|
||||||
|
(reversal-маркер в `DocumentType`). Проверка «не уйти в минус» на:
|
||||||
|
- Enter Unpost (товар уже мог быть продан),
|
||||||
|
- Loss Post (нельзя списать сверх остатка),
|
||||||
|
- Transfer Post (FromStore) и Unpost (ToStore),
|
||||||
|
- Inventory Unpost (излишек мог уйти),
|
||||||
|
- SupplierReturn Post (нельзя вернуть сверх остатка).
|
||||||
|
|
||||||
## Лог
|
## Лог
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue