67 lines
5.6 KiB
Markdown
67 lines
5.6 KiB
Markdown
# Спринт 2 — складские документы (P1)
|
||
|
||
Автономная работа. После каждого пункта: `dotnet build` (SDK 8.0.126),
|
||
unit + integration + (где применимо) E2E тесты этого пункта, коммит порцией,
|
||
отметка `[x]` здесь, коммит прогресса.
|
||
|
||
Multi-tenant: все новые сущности — `TenantEntity` с `OrganizationId` +
|
||
query filter. Stock-инвариант: после каждого Post/Unpost
|
||
`Stock.Quantity ≡ Σ StockMovement` для (Product, Store).
|
||
|
||
## Чек-лист
|
||
|
||
1. [x] **P1-1 Оприходование (Enter)** — Domain `Enter`+`EnterLine`, EF, миграция,
|
||
контроллер CRUD + Post/Unpost (Stock + StockMovement тип `Enter`), Web
|
||
`/inventory/enters`. Без поставщика (источник — начальные остатки, излишек инвентаризации).
|
||
✅ Контроллер `api/inventory/enters`; миграция `Phase6a_Enters`; пункт «Оприходования»
|
||
в сайдбаре Admin/Storekeeper. Тесты: 4 интеграционных (post raise stock, unpost
|
||
откатывает, double post→409, tenant-изоляция, блокировка unpost при минусе).
|
||
2. [x] **P1-2 Списание (Loss)** — Domain `Loss`+`LossLine` + enum `LossReason`
|
||
(Defect/Expired/Damage/Shortage/Other). EF, миграция, контроллер, Web,
|
||
`StockMovement` тип `WriteOff`.
|
||
✅ Контроллер `api/inventory/losses` (CRUD + Post/Unpost) с проверкой
|
||
«не списать сверх остатка» (409). Миграция `Phase6b_Losses`. Web с
|
||
фильтром по причине и колонкой stockAtStore. Тесты: 3 интеграционных
|
||
(post снижает stock, over-write-off → 409, tenant-изоляция).
|
||
3. [x] **P1-3 Перемещение (Transfer)** — Domain `Transfer`+`TransferLine`
|
||
(FromStoreId → ToStoreId, обязательны и различны). Атомарная транзакция:
|
||
`TransferOut` из From + `TransferIn` в To. EF, миграция, контроллер + Post/Unpost,
|
||
Web. Кейс: post→unpost не оставляет orphan-движений.
|
||
✅ Пара движений (Out + In) в одной Serializable-транзакции; обратная пара
|
||
в Unpost. Проверка «not short» на FromStore при Post и ToStore при Unpost.
|
||
Permission `TransferEdit`. Тесты: 4 интеграционных, ключевой проверяет что
|
||
движений ровно 2 после Post и ровно 4 после Unpost (никаких orphan).
|
||
4. [x] **P1-4 Инвентаризация (Inventory)** — Domain `Inventory`+`InventoryLine`
|
||
(productId, bookQty, actualQty, diff). EF, миграция. Контроллер: создание
|
||
подгружает текущие остатки; Post создаёт `InventoryAdjustment` на diff. Web:
|
||
форма со списком товаров склада, импорт CSV факта.
|
||
✅ Доменная сущность `InventoryDoc` (имя чтобы не пересекаться с системным
|
||
неймспейсом). Create с пустыми lines подтягивает все товары склада;
|
||
Update пишет actualQty построчно. Post создаёт `InventoryAdjustment`
|
||
только по строкам с diff != 0 (400 если нет расхождений). Unpost блочит
|
||
при «излишек уже расходован». Web с CSV-импортом (productId|article;qty).
|
||
Тесты: 3 интеграционных.
|
||
5. [x] **P1-6 Возврат от покупателя (CustomerReturn)** — расширение `RetailSale`
|
||
опцией возврата (referenceSaleId или без). Контроллер: создание возврата из
|
||
проведённой продажи, `CustomerReturn` тип уже есть. Web: кнопка «Создать возврат».
|
||
✅ RetailSale.IsReturn + ReferenceSaleId; RetailSaleLine.QtyReturned
|
||
(агрегация для защиты от over-return). `POST /create-return` копирует
|
||
проведённый чек в Draft-возврат с qty = (Quantity - QtyReturned).
|
||
Post return через `CustomerReturn`-движение с +Quantity, инкрементит
|
||
QtyReturned на исходных строках. Запрещён unpost оригинала при активных
|
||
возвратах. Тесты: 3 интеграционных.
|
||
6. [x] **P1-7 Возврат поставщику (SupplierReturn)** — по аналогии для Supply.
|
||
Domain `SupplierReturn`+`Line` (referenceSupplyId). Контроллер. Web.
|
||
✅ Зеркалит Supply, но Post с -Quantity (тип `SupplierReturn`). Валидация
|
||
что reference указывает на проведённую приёмку того же поставщика. Защита
|
||
от ухода в минус. Permissions переиспользуют `SuppliesEdit/Post/Delete`.
|
||
Тесты: 4 интеграционных.
|
||
7. [ ] **P1-16 Hangfire dashboard + cleanup** — `Hangfire.Dashboard` с
|
||
авторизацией только для SuperAdmin. Scheduled: ежедневный cleanup
|
||
`StockMovement` старше 2 лет, audit-log старше 90 дней.
|
||
|
||
## Лог
|
||
|
||
- Каждый пункт: build + тесты + коммит порцией + отметка [x] + коммит прогресса.
|
||
- Все правки на ветке `main` (origin Forgejo), без коммита `global.json`.
|