[CLAUDE] Docs: chốt session Tier 3 feature-complete + versioned workflow
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m33s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m33s
- Session log 2026-04-22-0300 (A→K): attachment, SignalR, form builder, PDF, dynamic + versioned workflow, nested menu, 3-panel permissions, seed master, brand identity, content polish, Gitea fix - STATUS: Tier 3 feature-complete snapshot + cumulative stats (24 tables, ~50 endpoints, 8 migrations); next-up = UAT + Email SMTP (blocked) + rotate creds + SQL backup schedule - HANDOFF: rewrite brief cho session mới — phase 5 prod done, Tier 3 đóng gói, quick sanity-check 2 app, versioned workflow quick ref, file active hiện trạng, git state - migration-todos: tick Tier 3 items (attachment/realtime/form builder/ PDF/dynamic+versioned workflow/nested menu) + thêm iter-3 versioned workflow section + post-launch list - schema-diagram: +5 table (Notifications, WorkflowTypeAssignments, WorkflowDefinitions, WorkflowSteps, WorkflowStepApprovers); indexes mới, cardinality FK restrict cho pinned policy, truy vấn tiêu biểu - workflow-contract: +section 7bis resolution order, 7ter admin designer flow, updated data model + code pointers Tier 3 - PROJECT-MAP: module map post-Tier-3 (3 box mới Notification/ Attachment/Branding + Infra/DevOps box), API namespace đầy đủ, architectural wins 5 điểm - contract-workflow skill: versioned workflow section, policy resolution code snippet, admin designer flow, code pointers Tier 3, tier 4+ backlog - gotchas +7 bẫy mới (#26-32): SignalR WebSocket headers, interceptor 2-phase pattern, LibreOffice mirror 404, PS 5.1 UTF-16 GITHUB_PATH, PS 5.1 diacritics parse, Dialog size TS, NavLink end query-params Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
171
docs/STATUS.md
171
docs/STATUS.md
@ -2,11 +2,12 @@
|
||||
|
||||
> **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)
|
||||
**Last updated:** 2026-04-22 03:00 (post-Tier-3-feature-complete + versioned workflow)
|
||||
|
||||
## 📍 Phase hiện tại: **Đã go-live prod** — 3 domain HTTPS live, CI/CD xanh, Notifications module + ERP shell
|
||||
## 📍 Phase hiện tại: **Tier 3 feature-complete** — Prod live, tất cả module lớn xong. Còn: UAT thật + Email outbox (chờ SMTP) + rotate creds.
|
||||
|
||||
### 🌐 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)
|
||||
@ -15,125 +16,106 @@
|
||||
|
||||
## 🔥 In Progress
|
||||
|
||||
_(không có — chờ UAT + quyết Tier 3 tiếp theo)_
|
||||
_(không có — Tier 3 đóng gói xong, chờ UAT để quyết Tier 4)_
|
||||
|
||||
## ✅ 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-22 | Claude | **PermissionsPage 3-panel layout** — Grid `lg:grid-cols-[280px_1fr_300px]`: Panel 1 Role list click-to-select (active ring-brand), Panel 2 Menu×CRUD matrix sticky thead + search + column bulk-toggle + brand-tinted hover, Panel 3 Granted progress bar + CRUD breakdown color badges (slate/emerald/amber/red) + Tip | `91b2da1` |
|
||||
| 2026-04-22 | Claude | **Admin Workflows tabs → sidebar menu items** — Seed 7 `Wf_<Code>` leaf dưới group `Workflows`. Layout resolvePath `Wf_<Code>` → `/system/workflows/<code>`. WorkflowsPage bỏ tab bar, URL param drives type selection. Landing 7-card grid khi click top-level `Quy trình HĐ`. Inheritance: `Workflows.Read` perm → tất cả 7 leaves auto-visible. | `f216169` |
|
||||
| 2026-04-22 | Claude | **Versioned workflow per ContractType** — 3 entity mới: WorkflowDefinition (Code+Version+IsActive+ContractType), WorkflowStep (Order+Phase+Name+SlaDays), WorkflowStepApprover (Role/User + AssignmentValue). Contract.WorkflowDefinitionId nullable FK pin tại create. Migration `AddVersionedWorkflows`. Seed v01 per 7 ContractType. `WorkflowPolicyRegistry.FromDefinition()` build runtime policy từ DB. ContractWorkflowService load pinned definition. Admin `/system/workflows/:typeCode` Designer modal (create new version, clone, add/remove step, +Role/+User approvers). POST /api/workflows auto-increment Version + deactivate old. Invariant: HĐ cũ pin v01 giữ nguyên khi v02 active. E2E verified: QT-MB-v02 active, HĐ cũ vẫn chạy v01. | `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` + `48e91fe` |
|
||||
| 2026-04-21 | Claude | **Seed master data + MyDashboard widgets** — DbInitializer seed 9 departments (PM/QS/CCM/PRO/FIN/ACT/EQU/HRA/BOD) + 5 demo suppliers + 3 demo projects idempotent. MyDashboard endpoint role-aware: DraftsInProgress / PendingMyApproval / DueSoon / Overdue / DraftsTotalValue. FE "Của tôi" row 4 card hover-interactive, admin auto-hide nếu = 0 | `6197c84` |
|
||||
| 2026-04-21 | Claude | **Dynamic workflow policy per ContractType** — Domain WorkflowPolicy record + 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). FE xóa NEXT_PHASES hardcoded, dùng contract.workflow.nextPhases BE trả. WorkflowSummaryCard timeline visual. Gotcha #21 resolved | `cae4d84` |
|
||||
| 2026-04-21 | Claude | **PDF export + .doc/.xls auto-convert + DynamicForm** — LibreOffice 25.8.6 VPS, IDocumentConverter shell soffice `--convert-to pdf/docx/xlsx` timeout+temp isolation. Admin upload .doc auto-convert .docx. DynamicForm parse FieldSpec JSON render inputs (text/textarea/number/date/currency/select). Form↔JSON toggle. E2E verified PDF 488KB/126 pages | `e459097` + `6bbd894` |
|
||||
| 2026-04-21 | Claude | **Form template builder CRUD** — Admin tự upload `.docx/.xlsx` qua UI (không cần dev). BE multipart + FormCode regex unique + FieldSpec JSON validation + soft delete via IsActive. FE FormsPage upload dialog + row actions render/edit/delete. E2E verified | `166d26c` |
|
||||
| 2026-04-21 | Claude | **Fix Gitea 500 sau Install Web-WebSockets** — appcmd unlock section webSocket. Gotcha #25 | `c52186b` |
|
||||
| 2026-04-21 | Claude | **SignalR realtime notifications E2E** — 3-project clean-arch: IRealtimeNotifier (App) + SignalRNotifier (Api) + NotificationPushInterceptor (Infra SaveChanges hook). Hub `/hubs/notifications` JWT `?access_token=` query (WebSocket headers limit). FE singleton lib/realtime.ts auto-reconnect + toast + query invalidation. IIS WebSocket module enabled | `ea9ab5e` |
|
||||
| 2026-04-21 | Claude | **Attachment upload E2E** — IFileStorage + LocalFileStorage (path-traversal guard) + CQRS Upload/Download/Delete + 3 endpoint (multipart, stream, DELETE) + FE ContractAttachmentsSection drag-drop + purpose selector + icon-per-MIME + auth-blob download + confirm delete. Wired 2 ContractDetailPage | `c8d0070` + `dc3f09b` |
|
||||
| 2026-04-21 | Claude | **Content polish** — typography 14px + leading 1.55 + tracking-tight + PageHeader border-b + Button shadow+active + Input inset shadow + DataTable rounded-xl UPPERCASE header brand hover | `346bd5d` |
|
||||
| 2026-04-21 | Claude | **Brand identity từ Solutions logo** — pixel-sampled #1F7DC1 → palette brand-50..900 + accent red + Be Vietnam Pro (Vietnamese-first) + favicon 'S' crop + apple-touch-icon + login gradient brand | `4abb559` + `bf1fbe3` |
|
||||
| 2026-04-21 | Claude | **Fix login Network Error** — SPA web.config HTTP→HTTPS redirect rule (CORS chỉ https) | `397eb36` |
|
||||
| 2026-04-21 | Claude | **Notifications module E2E** — Domain entity + EF migration + Infra service + CQRS + API controller + FE bells wire real endpoint + ContractWorkflowService emit notification cho Drafter khi phase transition | `49c0ddc` |
|
||||
| 2026-04-21 | Claude | **PermissionsPage iter 1** — search, stats badge, bulk column toggle, empty state | `6c0e206` |
|
||||
| 2026-04-21 | Claude | **ERP shell** — TopBar + NotificationBell + UserMenu (avatar + role badges). Layout `[sidebar] [topbar + content]` | `2b6f91c` |
|
||||
| 2026-04-21 | Claude | **Tier 1 UI polish** — SlaTimer (inline + full variant, 5 chỗ), Inbox stat cards, DataTable skeleton rows, EmptyState | `290936a`..`2e43799` |
|
||||
| 2026-04-21 | Claude | **CI/CD deploy xanh E2E** — self-hosted Windows runner, single job build+deploy, fresh node_modules (Vite 8 rolldown binding), appsettings 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 + auto-renew, shared gitea-runner với VIETREPORT | `169e268`..`519ba85` |
|
||||
| 2026-04-21 | Claude | **IDOR + SLA Job + Admin warning** — ContractsController filter theo role. SlaExpiryJob BackgroundService 15min auto-approve Decision=AutoApprove. DbInitializer warn khi admin vẫn 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 4 Report MVP** — Dashboard KPI + Excel export + rules.md + architecture.md + schema-diagram.md + gotchas 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 1 foundation** + Docs addition | `702411f` + `49a5f57` |
|
||||
| 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)
|
||||
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) · [**Tier 3**](changelog/sessions/2026-04-22-0300-tier3-feature-complete.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)
|
||||
- [`changelog/migration-todos.md`](changelog/migration-todos.md) · [`changelog/sessions/`](changelog/sessions/) (8 file)
|
||||
|
||||
## 🎯 Next up
|
||||
|
||||
### Phase 5 (prod go-live)
|
||||
### Hard blockers (chờ user / ops)
|
||||
|
||||
- [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
|
||||
- [ ] **UAT 1 tuần 2-3 user thật** — hard requirement từ roadmap Phase 5
|
||||
- [ ] **Email outbox** — MailKit + SMTP (BLOCKED chờ user cấp SMTP host/user/pass)
|
||||
- [ ] **Rotate credentials** — SA, vrapp, JWT secret, runner token (đã post chat)
|
||||
- [ ] **SQL backup daily** — Task Scheduler (script `scripts/backup-sql.ps1` đã có, chưa schedule)
|
||||
|
||||
### Tier 3 ERP roadmap còn (lớn, để dành session sau)
|
||||
### Optional polish (khi rảnh / UAT phát sinh)
|
||||
|
||||
- [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 ✓
|
||||
- [ ] Roles CRUD — admin tạo custom role ngoài 12 hardcoded (schema sẵn, chỉ cần CQRS + FE)
|
||||
- [ ] User-level approver targeting runtime — data model đã có (`WorkflowStepApprover.Kind=User`), chỉ cần wire User-kind vào `ContractWorkflowService.TransitionAsync` guard
|
||||
- [ ] PermissionsPage: grant `Workflows.Read` cho non-admin role → menu Wf_* visible
|
||||
- [ ] Warning notification khi còn 20% SLA (`SlaWarningSent` flag đã có, chỉ thiếu job emit)
|
||||
- [ ] E2E test reject → quay về DangSoanThao (multi-role)
|
||||
- [ ] Dependencies scan CI (`dotnet list package --vulnerable`, `npm audit`)
|
||||
|
||||
### Tier 3 ERP roadmap ✓ (close)
|
||||
|
||||
- [x] Attachment upload BE + FE ✓
|
||||
- [x] SignalR real-time push ✓
|
||||
- [x] Form template builder CRUD + DynamicForm ✓
|
||||
- [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)
|
||||
- [x] .doc/.xls → .docx/.xlsx auto-conversion ✓
|
||||
- [x] Dynamic workflow policy per ContractType ✓
|
||||
- [x] **Versioned workflow (WorkflowDefinition pinned per Contract)** ✓
|
||||
- [x] **Admin workflow designer UI (per-type, per-step approvers)** ✓
|
||||
- [x] **Nested sidebar menu per ContractType (fe-user) + menu split admin/user** ✓
|
||||
- [x] **PermissionsPage 3-panel layout** ✓
|
||||
- [ ] Email outbox for Notification (blocked — SMTP config)
|
||||
|
||||
## 📊 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) |
|
||||
| | P0 | P1f | P1.2 | P2 | P3 | P4 | P5prep | **Tier3** |
|
||||
|---|---:|---:|---:|---:|---:|---:|---:|---:|
|
||||
| BE LOC | 0 | ~400 | ~1500 | ~1900 | ~2700 | ~3100 | ~3300 | **~4800** |
|
||||
| DB tables | 0 | 7 | 12 | 14 | 19 | 19 | 19 | **24** (+Notifications, +WorkflowTypeAssignments, +WorkflowDefinitions, +WorkflowSteps, +WorkflowStepApprovers) |
|
||||
| API endpoints | 0 | 4 | 20 | 23 | 31 | 33 | 35 | **~50** (+notifications, +attachments, +forms CRUD, +pdf export, +workflows admin, +my-dashboard) |
|
||||
| Migrations | 0 | 1 | 3 | 4 | 5 | 5 | 5 | **8** (+AddNotifications, +AddWorkflowTypeAssignments, +AddVersionedWorkflows) |
|
||||
| FE pages | 0 | 2 | 6 | 7 | 14 | 16 | 16 | **~20** (admin Users/Workflows per-type + user nested menu) |
|
||||
| Scripts PS | 0 | 0 | 0 | 1 | 1 | 1 | 3 | **4** (+install-libreoffice) |
|
||||
| CI/CD workflow | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
|
||||
| Docs | 10 | 13 | 14 | 24 | 26 | 30 | 35 | **~40** (+session log + updated MDs) |
|
||||
| Commits | 1 | 2 | 3 | 5 | 6 | 7 | 8 | **~25** |
|
||||
|
||||
## 🚨 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
|
||||
- ⚠️ **Email SMTP chưa có** — blocker cho notification outbound
|
||||
- ⚠️ **UAT real user chưa chạy** — risk phát sinh bug edge-case quan trọng
|
||||
- ⚠️ **Credentials leaked trong chat** — cần rotate trước go-live thật
|
||||
- ⚠️ **SQL backup không auto** — risk data loss nếu VPS crash
|
||||
- ⚠️ **Permission `Workflows.Read` cho non-admin** — cần grant để họ thấy menu Wf_* (hiện chỉ admin thấy)
|
||||
- ⚠️ **User-kind approver chưa enable runtime** — designer cho chọn User nhưng guard fall back DeptManager
|
||||
|
||||
## Credentials + URLs
|
||||
|
||||
@ -141,6 +123,9 @@ Session logs: [P0](changelog/sessions/2026-04-21-1045-phase0-scaffold.md) · [P1
|
||||
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`
|
||||
- API prod: https://api.huypham.vn — Health `/health/live` + `/health/ready`
|
||||
- API dev: http://localhost:5443 — Swagger `/swagger`
|
||||
- Admin FE prod: https://admin.huypham.vn · dev `http://localhost:8082`
|
||||
- User FE prod: https://user.huypham.vn · dev `http://localhost:8080`
|
||||
- SQL prod: `.\SQLEXPRESS` / `SolutionErp` / `vrapp`
|
||||
- SQL dev: `(localdb)\MSSQLLocalDB` / `SolutionErp_Dev`
|
||||
|
||||
Reference in New Issue
Block a user