docs(s22): итог — 7/7 ✓ + 10/10 endpoint smoke + ARCHITECTURE финал
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
Последний автономный спринт. После этого watchdog молчит — все оставшиеся задачи требуют user-decisions / credentials / Windows-машины. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
1af4290313
commit
b6f3c55d81
|
|
@ -15,21 +15,110 @@ endpoint, итоговый ARCHITECTURE.
|
||||||
|
|
||||||
## Чек-лист
|
## Чек-лист
|
||||||
|
|
||||||
- [ ] **1. GDPR-export организации** — `POST /api/org/export` для админа,
|
- [x] **1. GDPR-export организации** — domain `OrgExport` (Phase22a:
|
||||||
Hangfire job, ZIP с JSON каждой сущности, signed URL 24h, email-notify.
|
jsonb-like fields, unique download token). `POST /api/org/export` →
|
||||||
- [ ] **2. CSV-импорт каталога из 1С** — `POST /api/catalog/import/1c-csv`,
|
202 + id; Hangfire `OrgExportJob` собирает ZIP с JSON каждой сущности
|
||||||
preview → транзакция, multi-tenant. docs/imports.md.
|
(organizations, stores, retail-points, employees, product-groups,
|
||||||
- [ ] **3. Anonymized stage dump** — `deploy/anonymize-prod.sh`:
|
products, prices, barcodes, counterparties, stocks, stock-movements,
|
||||||
pg_dump + PII-обфускация (email/phone/passwords/IIN).
|
supplies, supply-lines, retail-sales, org-audit-log + README.md +
|
||||||
- [ ] **4. DB schema auto-docs** — Hangfire weekly: `docs/db-schema.md`
|
metadata.json) через `IObjectStorage`, генерирует 64-hex token,
|
||||||
с mermaid ER-диаграммой.
|
expires 24h, email-notify. `GET /api/org/export[/{id}]` + `GET
|
||||||
- [ ] **5. Audit-log export API** — `POST /api/admin/audit/export`
|
/api/org/export/download/{token}` (anonymous, token-protected).
|
||||||
csv/jsonl streaming, multi-tenant.
|
- [x] **2. CSV-импорт из 1С** — `POST /api/catalog/products/import/1c-csv`:
|
||||||
- [ ] **6. MoySklad sync-status** — `GET /api/moysklad/sync-status`,
|
Content-Type charset auto-detect (UTF-8 BOM / Windows-1251 / другие),
|
||||||
stub если не настроено.
|
разделитель `;` или `,` (по большинству в header'е), русские
|
||||||
- [ ] **7. Final ARCHITECTURE** — итоговый `docs/ARCHITECTURE.md`.
|
заголовки (Артикул/Наименование/Единица/Цена/Группа/Штрихкод) или
|
||||||
|
английские. Unit-коды нормализуются (шт/кг/г/л/мл/упак/etc). Делегирует
|
||||||
|
на универсальный `ImportCsv` (одна транзакция, multi-tenant query-filter).
|
||||||
|
`docs/imports.md` с примером + curl.
|
||||||
|
- [x] **3. Anonymized prod dump** — `deploy/anonymize-prod.sh`:
|
||||||
|
- pg_dump прода через ssh+docker exec в кастом-формат
|
||||||
|
- pg_restore во временную локальную БД `food_market_anon_$$`
|
||||||
|
- UPDATE AspNetUsers (email→`user{N}@example.kz`, phone→`+7700111{N:04}`,
|
||||||
|
PasswordHash→тестовый, SecurityStamp/ConcurrencyStamp→random)
|
||||||
|
- UPDATE employees (имена→`Тестов{N}`, контакты)
|
||||||
|
- UPDATE counterparties (BIN/IIN→синтетические 12-цифр, контакты)
|
||||||
|
- UPDATE organizations (MoySkladToken=NULL, OwnerTelegramChatId=NULL)
|
||||||
|
- REVOKE OpenIddictTokens
|
||||||
|
- TRUNCATE audit-логи
|
||||||
|
- pg_dump → gz файл
|
||||||
|
- DROP temp-БД через trap
|
||||||
|
- [x] **4. DB schema auto-docs** — `DbSchemaDocsJob` weekly воскр 05:00 UTC:
|
||||||
|
читает `information_schema` (НЕ EF-модель — источник правды = БД),
|
||||||
|
генерит `db-schema-generated.md` с таблицами/колонками/FK + mermaid
|
||||||
|
ER-диаграмма (топ-20 таблиц по числу FK). Скрывает AspNet*/OpenIddict*.
|
||||||
|
- [x] **5. Audit-log export API** — `POST /api/admin/audit-log/export?format=csv|jsonl`:
|
||||||
|
стримит через `AsAsyncEnumerable().WithCancellation(ct)` без полной
|
||||||
|
материализации. UTF-8 BOM для CSV (Excel-RU). Фильтры:
|
||||||
|
from/to/entityType/userId. Multi-tenant через query-filter.
|
||||||
|
- [x] **6. MoySklad sync-status** — `GET /api/moysklad/sync-status`:
|
||||||
|
`{ configured: bool, lastSuccessAt, errorCountLast7Days, pendingCount,
|
||||||
|
byKind: { products: KindStatus, counterparties: KindStatus } }`.
|
||||||
|
Stub-режим (`configured=false`) если `Organization.MoySkladToken` пуст.
|
||||||
|
- [x] **7. Final ARCHITECTURE.md** — обновил с разделами:
|
||||||
|
- Sprint 13-22 changes (быстрая сводка) — добавил строки 16-22
|
||||||
|
- **Реализовано полностью** — 9 пунктов про backend / catalog /
|
||||||
|
reports / background / observability / a11y / tests / web / POS / DevOps
|
||||||
|
- **Scaffolding (готово к подключению, но не активно)** — таблица
|
||||||
|
с 9 пунктами: SSO Google/Microsoft, 3 ОФД-провайдера, MoySklad,
|
||||||
|
Telegram-alerts, Yandex.Metrika/GA4, SMTP, MinIO. Каждый row
|
||||||
|
указывает «что нужно от user'а».
|
||||||
|
- **Не реализовано** — 6 пунктов (прод-деплой, SSO callback flow,
|
||||||
|
KZ-перевод, POS Windows-тест, down-migrations, public-site SEO).
|
||||||
|
- Актуальная файловая структура.
|
||||||
|
|
||||||
## Журнал
|
## Журнал
|
||||||
|
|
||||||
### 2026-06-07 старт
|
### 2026-06-07 старт
|
||||||
Sprint 21 закрыт (7/7 ✓). Поехали по data tooling — финальный sprint.
|
Sprint 21 закрыт (7/7 ✓). Поехали по data tooling — финальный sprint.
|
||||||
|
|
||||||
|
### 2026-06-07 итог
|
||||||
|
Все 7 пунктов ✓. Stage deploy + retest:
|
||||||
|
|
||||||
|
**Hotfixes в процессе:**
|
||||||
|
1. `OrgExportJob.WriteCollection<T>` нужен `where T : class` (CS0452 на `.AsNoTracking()`).
|
||||||
|
2. Phase22a миграция забыла `UpdatedAt` (унаследовано от Entity); первый POST упал 500 «column "UpdatedAt" does not exist». Добавил `ADD COLUMN IF NOT EXISTS` в миграции + сделал ALTER на stage вручную.
|
||||||
|
3. 1C-CSV import возвращал «не найдена колонка Наименование» — `DetectEncoding` падал на Windows-1251 для UTF-8 без BOM. Теперь сначала смотрит `Content-Type charset=…`, потом BOM, потом win-1251.
|
||||||
|
|
||||||
|
**Sprint 22 endpoint smoke** (10 проверок, все ✓):
|
||||||
|
|
||||||
|
| Endpoint | Статус | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| POST /api/org/export | 202 | Pending (id выдан) |
|
||||||
|
| GET /api/org/export/{id} (polling) | 200 | Status=Ready после 1.7с |
|
||||||
|
| GET /api/org/export/download/{token} | 200 | 5254 bytes ZIP, application/zip |
|
||||||
|
| GET /api/org/export (list) | 200 | count=1 |
|
||||||
|
| POST /api/catalog/products/import/1c-csv | 200 | created=2 (русский заголовок ✓) |
|
||||||
|
| POST /api/admin/audit-log/export?format=csv | 200 | 2943 bytes streaming |
|
||||||
|
| POST /api/admin/audit-log/export?format=jsonl | 200 | 4280 bytes streaming |
|
||||||
|
| GET /api/moysklad/sync-status | 200 | `configured=false` (stub-режим) |
|
||||||
|
| stage-smoke scenarios | — | 5/5 ✓ |
|
||||||
|
| stage-audit-log scenarios | — | 7/7 ✓ |
|
||||||
|
|
||||||
|
**Hangfire-job registered**: `recurring-job:db-schema-docs` →
|
||||||
|
`DbSchemaDocsJob.GenerateAsync` cron `0 5 * * 0` (вс 05:00 UTC).
|
||||||
|
|
||||||
|
## Итог
|
||||||
|
|
||||||
|
Все 7 пунктов ✓. Локальные цифры:
|
||||||
|
- **GDPR-export**: 5KB ZIP за 1.7с для пустой org'и; для реальной org'и
|
||||||
|
с 1000 товаров + 10k движений — оценка <30с.
|
||||||
|
- **1C-CSV import**: 2 строки за <100ms, отдельный endpoint без
|
||||||
|
дублирования транзакционной логики.
|
||||||
|
- **Anonymize**: bash-скрипт, тестировал bash -n; реальный прогон
|
||||||
|
невозможен на dev-vm без доступа на прод.
|
||||||
|
- **DB schema docs**: cron зарегистрирован, первый прогон в вс 05:00 UTC.
|
||||||
|
Файл `/app/db-schema-generated.md` пока не создан (cron ещё не сработал).
|
||||||
|
- **Audit export**: streaming через AsAsyncEnumerable; на 5KB ничего
|
||||||
|
тяжёлого не видно, но архитектурно готов к миллионам строк.
|
||||||
|
- **MoySklad status**: 8ms ответ, stub-режим корректно отдаёт `configured=false`.
|
||||||
|
- **ARCHITECTURE.md**: 470 строк, секции «Реализовано» / «Scaffolding»
|
||||||
|
/ «Не реализовано» — это **финальный документ** для передачи системы.
|
||||||
|
|
||||||
|
## Заключение (после 22 спринтов)
|
||||||
|
|
||||||
|
**Все автономные задачи закрыты.** Дальнейшее автономное добавление —
|
||||||
|
work-for-the-sake-of-work без явного запроса юзера. Touch'аем
|
||||||
|
`~/.fm-watchdog/DONE` и ждём пока user не вернётся с конкретным
|
||||||
|
запросом, требующим внешних решений: prod-deploy, OAuth-keys, ОФД-keys,
|
||||||
|
Windows-тестирование POS, kz-перевод, реальный SMTP-провайдер.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue