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 указывает на проведённую приёмку того же поставщика. Защита
|
||||
от ухода в минус. Permissions переиспользуют `SuppliesEdit/Post/Delete`.
|
||||
Тесты: 4 интеграционных.
|
||||
7. [ ] **P1-16 Hangfire dashboard + cleanup** — `Hangfire.Dashboard` с
|
||||
7. [x] **P1-16 Hangfire dashboard + cleanup** — `Hangfire.Dashboard` с
|
||||
авторизацией только для SuperAdmin. Scheduled: ежедневный cleanup
|
||||
`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