food-market/docs/sprint5-progress.md
nns c43f68c39b docs(sprint5): TD-5 done — все 4 пункта выполнены, итог
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 16:47:32 +05:00

78 lines
5.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Спринт 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. [x] **TD-5 ImportJobRegistry в БД** — сейчас in-memory `ConcurrentDictionary`,
теряется при рестарте. Перевод на таблицу `ImportJobs` (Id, OrgId, Status,
Progress, Total, StartedAt, FinishedAt, Errors JSON). Миграция.
`MoySkladImportController` использует. Тесты.
`Domain.Integrations.ImportJob` (TenantEntity); миграция `Phase8c_ImportJobs`.
`ImportJobRegistry` теперь IServiceScopeFactory-backed: `Create` пишет
строку немедленно, `SaveAsync` обновляет, `Get/RecentlyFinished` читают
из БД. Контроллер `MoySkladImportController.RunInBackgroundAsync` дополнен
periodic flush через Timer (каждые 2 сек) + финальный flush в finally —
UI видит реальный прогресс, terminal-state сохраняется через рестарт.
3 интеграционных теста (survives across scope, RecentlyFinished, tenant-isolation).
## Итог
**Все 4 пункта выполнены.** Спринт 5 завершён 2026-05-28.
Сводка:
- **P1-5 Demand** — оптовая отгрузка контрагенту-юрлицу с `DemandPayment.Credit`
и `PaidAmount`-полем; 3 интеграционных.
- **P1-18 OrgAuditLog** — per-tenant журнал через `SaveChangesInterceptor`,
atomic с мутацией, diff в jsonb; 3 интеграционных.
- **P1-22 Email** — `IEmailSender.SendHtmlAsync` (multipart) + mustache-light
renderer + 3 шаблона + 2 recurring Hangfire-джоба; 8 unit.
- **TD-5 ImportJob** — persistence в БД, переживает рестарт, periodic flush
для live-прогресса; 3 интеграционных.
**Сборка:** зелёная.
**Тесты:** 35 unit + 68 integration = **103 зелёных**.
### Что осталось вне scope
- ОФД-оператор (нужен внешний участник: `Транском`/`Касса24`);
- MoySklad webhook-токены прод;
- WPF/POS UI (Windows-SDK);
- Стейдж→прод-деплой;
- Real SMTP-сервер для прод (Mailgun/Sendgrid/etc).
## Лог
- Каждый пункт: build + тесты + коммит порцией + отметка [x] + коммит прогресса.
- Все правки на `main` (origin Forgejo), без коммита `global.json`.