47 lines
3.3 KiB
Markdown
47 lines
3.3 KiB
Markdown
# Спринт 5 — оптовые продажи, email, аудит, надёжность import-job
|
||
|
||
Автономная работа. После каждого пункта: `dotnet build` (SDK 8.0.126),
|
||
unit + integration тесты, коммит порцией, отметка `[x]`, коммит прогресса.
|
||
|
||
Multi-tenant: все новые сущности — `TenantEntity` с `OrganizationId` +
|
||
query filter. E2E на изоляцию A vs B где применимо.
|
||
|
||
## Чек-лист
|
||
|
||
1. [x] **P1-5 Оптовая отгрузка (Demand)** — Domain `Demand`+`DemandLine`
|
||
(CounterpartyId юрлица, способ оплаты нал/безнал, цена опт., НДС). EF +
|
||
миграция. Контроллер CRUD + Post/Unpost. Web `/sales/demands`.
|
||
`StockMovement` тип `WholesaleSale`. Multi-tenant. Тесты.
|
||
✅ Зеркалит RetailSale без RetailPoint/Cashier; `DemandPayment.Credit`
|
||
(постоплата/дебиторка), `PaidAmount` для отслеживания. Permissions
|
||
переиспользуют существующие `DemandsEdit/Post`. Метрики
|
||
`documents_posted{type="demand"}`. 3 интеграционных теста.
|
||
2. [x] **P1-18 Аудит мутаций tenant'а** — Domain `OrgAuditLog` (как
|
||
`SuperAdminAuditLog`, но per-org). Hook через EF SaveChangesInterceptor
|
||
на Supply/Sale/Demand/Product/Counterparty. UI: `/audit-log` для админа.
|
||
Multi-tenant строго. Тесты.
|
||
✅ `OrgAuditInterceptor` снимает diff на `SavingChanges` (до commit) —
|
||
атомарно с мутацией. ChangesJson: `{"field":{"before":X,"after":Y}}`.
|
||
Белый список типов: Supply/SupplierReturn/RetailSale/Demand/Product/
|
||
ProductPrice/ProductBarcode/Counterparty. Web `/audit-log` с фильтрами
|
||
и diff-viewer'ом. Tenant-isolation через query-filter. 3 интеграционных.
|
||
3. [x] **P1-22 Email-шаблоны** — расширить MailKit-сервис:
|
||
`Resources/EmailTemplates/*.html`. Шаблоны: приглашение сотрудника с
|
||
временным паролем (sendInvite=true), еженедельный summary владельцу
|
||
(Hangfire recurring), low-stock alert (Hangfire daily). Тесты рендеринга.
|
||
✅ `IEmailSender.SendHtmlAsync` (multipart/alternative с plain fallback);
|
||
`EmailTemplateRenderer` (mustache-light: `{{key}}` escape, `{{{raw}}}`,
|
||
`{{#key}}…{{/key}}` условие); `EmailTemplates` загружает embedded
|
||
`Resources/EmailTemplates/*.html` (Subject: первой строкой). Шаблоны:
|
||
invite/weekly-summary/low-stock. Hangfire: weekly понедельник 07:00,
|
||
low-stock ежедневно 08:00. 8 unit-тестов.
|
||
4. [ ] **TD-5 ImportJobRegistry в БД** — сейчас in-memory `ConcurrentDictionary`,
|
||
теряется при рестарте. Перевод на таблицу `ImportJobs` (Id, OrgId, Status,
|
||
Progress, Total, StartedAt, FinishedAt, Errors JSON). Миграция.
|
||
`MoySkladImportController` использует. Тесты.
|
||
|
||
## Лог
|
||
|
||
- Каждый пункт: build + тесты + коммит порцией + отметка [x] + коммит прогресса.
|
||
- Все правки на `main` (origin Forgejo), без коммита `global.json`.
|