Files
solution-erp/docs/STATUS.md
pqhuy1987 29dbac2051
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m38s
[CLAUDE] Docs: STATUS update cho versioned workflow + nested menu user
2026-04-22 09:37:53 +07:00

147 lines
13 KiB
Markdown
Raw 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.

# STATUS — Snapshot hiện tại
> **Update rule:** trước khi bắt đầu 1 task → ghi row vào `🔥 In Progress`. Xong → chuyển sang `✅ Recently Done`.
**Last updated:** 2026-04-21 15:30 (post-prod-deploy)
## 📍 Phase hiện tại: **Đã go-live prod** — 3 domain HTTPS live, CI/CD xanh, Notifications module + ERP shell
### 🌐 Production URLs
- https://api.huypham.vn — API (Let's Encrypt, auto-renew via win-acme)
- https://admin.huypham.vn — Admin FE (HTTP→HTTPS auto-redirect)
- https://user.huypham.vn — User FE (HTTP→HTTPS auto-redirect)
- https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp — Gitea repo + Actions
- Default admin: `admin@solutionerp.local` / `Admin@123456` ⚠️ **RE-ROTATE sau login đầu**
## 🔥 In Progress
_(không có — chờ UAT + quyết Tier 3 tiếp theo)_
## ✅ Recently Done (newest on top)
| Ngày | Ai | Task | Commit |
|---|---|---|---|
| 2026-04-22 | Claude | **Versioned workflow per ContractType** — Domain: WorkflowDefinition (Code+Version+IsActive) + WorkflowStep + WorkflowStepApprover (Role/User). Contract.WorkflowDefinitionId pin tại create. EF migration AddVersionedWorkflows + AddWorkflowTypeAssignments. Seed v01 per 7 ContractType từ hardcoded policies. ContractWorkflowService.FromDefinition build policy runtime từ DB. Admin `/system/workflows` tabs per type, DefinitionCard + Designer modal (add/remove step, pick phase/SLA, +Role hoặc +User approvers). POST /api/workflows tạo v02 → v01 auto-archive (HĐ cũ vẫn chạy v01). E2E verified: seed 7 v01, create QT-MB-v02, new HĐ Mua bán pin v02 `policyName:"QT-MB-v02"` activePhases [2,3,7,8,9,99] | `e7e5f2d` + `355bbe3` |
| 2026-04-21 | Claude | **Nested sidebar menu fe-user** — 7 ContractType × 3 actions (Danh sách/Thao tác/Duyệt), nested 3-level. Admin hide Ct_*. Layout recursive MenuNodeRenderer. MyContracts + Inbox filter `?type=X` | `5e0f380` |
| 2026-04-21 | Claude | **Seed master data + MyDashboard widgets** — DbInitializer seed 9 departments từ QT docx (PM/QS/CCM/PRO/FIN/ACT/EQU/HRA/BOD) + 5 demo suppliers + 3 demo projects idempotent. MyDashboard endpoint `/api/reports/my-dashboard` role-aware: DraftsInProgress / PendingMyApproval / DueSoon / Overdue. FE DashboardPage "Của tôi" row 4 card hover-interactive, Admin auto-hide nếu = 0. E2E verified 9 dept seeded, endpoint trả data thật | `6197c84` |
| 2026-04-21 | Claude | **Dynamic workflow policy per ContractType** — Domain `WorkflowPolicy` + registry (Standard 8-phase cho Thầu phụ/Giao khoán/NCC; SkipCcm 7-phase cho Dịch vụ/Mua bán/Nguyên tắc). `ContractWorkflowService` dùng `policy.ForContract(c)` thay hardcoded dict. FE xóa `NEXT_PHASES` hardcoded, dùng `contract.workflow.nextPhases` từ BE. `WorkflowSummaryCard` timeline visual. E2E verified: HĐ Thầu phụ có phase 6 CCM, HĐ Mua bán skip. Gotcha #21 resolved | `cae4d84` |
| 2026-04-21 | Claude | **PDF export + .doc/.xls auto-convert + DynamicForm** — LibreOffice 25.8.6 install VPS, `IDocumentConverter` shell soffice `--convert-to pdf/docx/xlsx` với timeout+temp isolation, admin upload .doc auto-convert .docx. `DynamicForm` component render từ FieldSpec JSON (text/textarea/number/date/currency/select). FE Form↔JSON toggle. E2E verified PDF 488KB/126 pages | `e459097` + `6bbd894` |
| 2026-04-21 | Claude | **Form template builder CRUD** — Admin tự upload `.docx/.xlsx` templates qua UI (không cần dev). BE: UploadContractTemplate (multipart, 10MB, FormCode regex unique, FieldSpec JSON validation) + UpdateContractTemplate (metadata + FieldSpec + IsActive) + DeleteContractTemplate (soft via IsActive=false). File lưu vào `wwwroot/templates/{formCode}_{guid}.{ext}`. FE: FormsPage với upload dialog (file picker + FormCode + Loại HĐ + FieldSpec JSON textarea) + row actions 3 nút (render/edit/delete). E2E verified upload 200 + update 204 + delete 204 | `166d26c` |
| 2026-04-21 | Claude | **Fix Gitea 500 sau Install Web-WebSockets** — Feature install khóa section `<webSocket>` ở applicationHost.config → tất cả IIS site fail. Fix: `appcmd unlock config -section:system.webServer/webSocket`. Gotcha #25 | `c52186b` |
| 2026-04-21 | Claude | **SignalR realtime notifications E2E** — Clean-arch split (IRealtimeNotifier Application + SignalRNotifier Api + NotificationPushInterceptor Infrastructure). Hub `/hubs/notifications` JWT via `?access_token=` query (WebSocket headers limit). Interceptor SavedChangesAsync auto-push → zero caller changes. FE singleton connection với auto-reconnect + toast trên push + query invalidation. IIS WebSocket module enabled. Hub verified: negotiate 200 với JWT (WebSockets/SSE/LongPolling transports), 401 không auth | `ea9ab5e` |
| 2026-04-21 | Claude | **Attachment upload E2E** — IFileStorage abstraction + LocalFileStorage (path-traversal guard) + CQRS Upload/Download/Delete + 3 controller endpoints (multipart, File stream, DELETE) + FE ContractAttachmentsSection (drag-drop + purpose selector + icon-per-MIME + auth-blob download + confirm delete) + wired vào cả 2 ContractDetailPage. Unblock E2E workflow (scan HĐ ký/đóng dấu) | `c8d0070` + `dc3f09b` |
| 2026-04-21 | Claude | **Content polish** — typography (14px + leading 1.55 + tracking-tight, heading weights) + PageHeader (text-[22px] + border-b) + Button (shadow + active-press + ring-2) + Input/Select/Textarea (inset shadow + border/ring focus) + DataTable (rounded-xl + UPPERCASE tracking header + brand hover) | `346bd5d` |
| 2026-04-21 | Claude | **Brand identity từ Solutions logo** — pixel-sampled #1F7DC1 → full palette brand-50..900 + accent red + Be Vietnam Pro font (Vietnamese-first) + favicon chữ 'S' crop từ logo.png + apple-touch-icon + login page gradient brand + ERP subtitle | `4abb559` + `bf1fbe3` |
| 2026-04-21 | Claude | **Fix login Network Error** — SPA web.config thêm HTTP→HTTPS redirect rule (CORS chỉ allow https origin, user gõ bare domain bị block) | `397eb36` |
| 2026-04-21 | Claude | **Notifications module E2E** — Domain entity + EF migration + Infra service + CQRS (List/UnreadCount/MarkRead/MarkAllRead) + API controller + FE bells wire real endpoint + ContractWorkflowService emit notification cho Drafter khi phase transition. Foundation sẵn cho SignalR/email outbox | `49c0ddc` |
| 2026-04-21 | Claude | **PermissionsPage improved** — search, stats badge, bulk column toggle, empty state icon | `6c0e206` |
| 2026-04-21 | Claude | **ERP shell**: TopBar + NotificationBell + UserMenu (avatar + role badges). Layout tách `[sidebar] [topbar + content]` — foundation cho multi-module ERP | `2b6f91c` |
| 2026-04-21 | Claude | **Tier 1 UI polish** — SlaTimer (inline + full variant, 5 chỗ), Inbox stat cards, DataTable skeleton rows, EmptyState component + MyContracts CTA | `290936a`..`2e43799` |
| 2026-04-21 | Claude | **CI/CD deploy xanh E2E** — self-hosted Windows runner, single job build+deploy local, npm install fresh node_modules (Vite 8 rolldown binding), appsettings rendered từ secrets, /health/live 200 sau deploy | `b40da1e` |
| 2026-04-21 | Claude | **VPS prod setup** — SQL DB (SQLEXPRESS), IIS sites (SolutionErp-Api/Admin/User), win-acme 3 Let's Encrypt certs + auto-renew, shared gitea-runner với VIETREPORT | `169e268`..`519ba85` |
| 2026-04-21 | Claude | **IDOR + SLA Job + Admin warning** — ContractsController List/GetDetail filter theo role (non-admin chỉ thấy HĐ mình là Drafter hoặc role eligible phase). SlaExpiryJob BackgroundService auto-approve quá hạn mỗi 15min với Decision=AutoApprove. DbInitializer warn log khi admin vẫn dùng password default | `fba0754` |
| 2026-04-21 | Claude | **Phase 5.1 Security + Users Mgmt** — Security headers + Identity lockout + LoginHandler check + Users CQRS + UsersController + FE `/system/users` | `11e61c9` |
| 2026-04-21 | Claude | **Phase 5 Prep** — BE rate limit + health check + Serilog file + HSTS + scripts deploy-iis/backup-sql + .gitea/workflows/deploy.yml + 4 guides + FE refresh token queue pattern | `46a2cab` |
| 2026-04-21 | Claude | **Phase 4 Report MVP + Docs Consolidation** — Dashboard KPI + Excel export + rules.md + architecture.md + schema-diagram.md + gotchas update 26 pitfalls | `fe7ad8e` |
| 2026-04-21 | Claude | **Phase 3 Workflow MVP** — 9 phase state machine + gen mã HĐ RG-001 | `7e957a7` |
| 2026-04-21 | Claude | **Phase 2 Form Engine MVP** | `5113e4c` |
| 2026-04-21 | Claude | **Phase 1.2** — CRUD Master + Permission Matrix | `54d6c9b` |
| 2026-04-21 | Claude | **Docs addition** | `49a5f57` |
| 2026-04-21 | Claude | **Phase 1 foundation** | `702411f` |
| 2026-04-21 | Claude | **Phase 0** | `25dad7f` |
Session logs: [P0](changelog/sessions/2026-04-21-1045-phase0-scaffold.md) · [P1f](changelog/sessions/2026-04-21-1100-phase1-foundation.md) · [P1.2](changelog/sessions/2026-04-21-1130-phase1-cruds-permission.md) · [P2](changelog/sessions/2026-04-21-1200-phase2-form-engine.md) · [P3](changelog/sessions/2026-04-21-1330-phase3-workflow.md) · [P4](changelog/sessions/2026-04-21-1430-phase4-report.md) · [P5prep](changelog/sessions/2026-04-21-1530-phase5-prep.md)
**Docs entry points:**
- [`rules.md`](rules.md) · [`architecture.md`](architecture.md) · [`HANDOFF.md`](HANDOFF.md)
- [`workflow-contract.md`](workflow-contract.md) · [`forms-spec.md`](forms-spec.md)
- [`database/database-guide.md`](database/database-guide.md) · [`database/schema-diagram.md`](database/schema-diagram.md)
- [`flows/`](flows/) (7 file) · [`guides/`](guides/) (4 file) · [`gotchas.md`](gotchas.md)
- [`changelog/migration-todos.md`](changelog/migration-todos.md) · [`changelog/sessions/`](changelog/sessions/) (7 file)
## 🎯 Next up
### Phase 5 (prod go-live)
- [x] Gitea remote + push all commits
- [x] Gitea Actions runner (self-hosted Windows, shared VIETREPORT runner)
- [x] Secrets Gitea (JWT_SECRET, DB_CONNECTION — IIS_* deprecated sau rewrite workflow)
- [x] CI/CD workflow xanh end-to-end
- [x] Windows Server setup IIS (SolutionErp-Api/Admin/User)
- [x] HTTPS cert (win-acme 3 Let's Encrypt + auto-renew)
- [x] SQL Server prod (SQLEXPRESS) + vrapp db_owner
- [x] Smoke test E2E: /health/ready Healthy, login JWT thật, FE live
- [ ] **UAT 1 tuần 2-3 user thật** ← next
- [ ] SQL backup Task Scheduler (script đã có, chưa schedule)
- [ ] Rotate credentials (SA, vrapp, JWT, runner token) — 1 số đã post chat
### Tier 3 ERP roadmap còn (lớn, để dành session sau)
- [x] Attachment upload BE endpoint + FE drag-drop ✓
- [x] SignalR real-time push (auto-push interceptor + client auto-reconnect) ✓
- [x] Form template builder CRUD (admin upload .docx/.xlsx + FieldSpec JSON editor) ✓
- [x] Form builder iteration 2: DynamicForm render UI từ FieldSpec ✓
- [x] PDF export qua LibreOffice headless ✓
- [x] .doc → .docx auto-conversion khi upload template ✓
- [x] Dynamic workflow policy per ContractType (Standard/SkipCcm) ✓
- [ ] Email outbox cho Notification (MailKit, SMTP config — cần user config)
### Phase 5.1 Security — hầu như xong
- [x] Security headers middleware (X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy, CSP)
- [x] Identity account lockout (5 fail → 15min, config-driven)
- [x] Password policy config-driven
- [x] LoginHandler check lockout + AccessFailedAsync + reset on success
- [x] BE Users management + FE admin UsersPage
- [x] IDOR check ContractsController (non-admin chỉ thấy HĐ mình/role eligible)
- [x] Admin password warning log startup
- [x] SLA Expiry BackgroundService auto-approve
- [ ] Dependencies scan CI (`dotnet list package --vulnerable` + `npm audit`)
- [ ] Roles CRUD — optional
### Polish iterations
**Phase 2 iter 2:** convert .doc, field spec JSON + form builder, {{#loop}}, PDF convert
**Phase 3 iter 2:** SLA job auto-approve, email/in-app notify, attachment upload, RowVersion
**Phase 4 iter 2:** SLA overdue report, PDF HĐ export, dashboard user-specific
### Quick wins
- FE Users management + Roles CRUD (test permission non-admin)
- Filter Inbox theo phase FE
- Test refresh token flow manual (logout/login flow)
## 📊 Thông số cumulative
| | P0 | P1f | P1.2 | P2 | P3 | P4 | **P5 prep** |
|---|---:|---:|---:|---:|---:|---:|---:|
| BE LOC | 0 | ~400 | ~1500 | ~1900 | ~2700 | ~3100 | **~3300** |
| DB tables | 0 | 7 | 12 | 14 | 19 | 19 | 19 |
| API endpoints | 0 | 4 | 20 | 23 | 31 | 33 | **35** (+health) |
| Migrations | 0 | 1 | 3 | 4 | 5 | 5 | 5 |
| FE pages | 0 | 2 | 6 | 7 | 14 | 16 | 16 |
| Scripts PS | 0 | 0 | 0 | 1 (convert-doc) | 1 | 1 | **3** (+deploy-iis, backup-sql) |
| CI/CD workflow | 0 | 0 | 0 | 0 | 0 | 0 | **1** |
| Docs | 10 | 13 | 14 | 24 | 26 | 30 | **35** (+4 guides + session log) |
| Commits | 1 | 2 | 3 | 5 | 6 | 7 | **8** (sắp) |
## 🚨 Blockers / risks
-**Gitea remote URL** — ĐANG CẦN để push + setup CI/CD
- ⚠️ **Phase 5.1 security hardening** chưa làm (headers, account lockout, IDOR check)
- ⚠️ **3 file .doc chưa convert** (Phase 2 carryover)
- ⚠️ **SLA không tự auto-approve** (Phase 3.2)
- ⚠️ **Email/in-app notification** chưa có
- ⚠️ **FE Users management chưa có** — khó test permission non-admin
- ⚠️ **Rate limit global 300/min/IP** — OK cho dev, cần tăng cho prod nếu nhiều user
## Credentials + URLs
```
admin@solutionerp.local / Admin@123456
```
- API: http://localhost:5443 — Swagger `/swagger` (dev only) — Health `/health/live` + `/health/ready`
- Admin FE: http://localhost:8082 — `/dashboard`, `/contracts`, `/reports`, `/master/*`, `/forms`, `/system/permissions`
- User FE: http://localhost:8080 — `/inbox`, `/contracts/new`, `/my-contracts`