# PROJECT-MAP — Bản đồ toàn cảnh > Đọc file này nếu cần deep context (~15 phút). Nếu chỉ cần snapshot → đọc [`STATUS.md`](STATUS.md). ## Module map (hiện trạng post-Tier-3) ``` ┌─────────────────────────────────────────────────────────────────┐ │ SOLUTION_ERP │ │ 🌐 Prod live: api/admin/user.huypham.vn (HTTPS Let's Encrypt) │ └─────────────────────────────────────────────────────────────────┘ ╔════════════════╗ ╔════════════════╗ ╔════════════════╗ ║ IDENTITY ║ ║ DANH MỤC ║ ║ QUẢN LÝ HĐ ║ ║ (Phase 1) ✅ ║ ║ (Phase 1) ✅ ║ ║ (Phase 1-3) ✅ ║ ╠════════════════╣ ╠════════════════╣ ╠════════════════╣ ║ User (+Mgmt) ║ ║ Supplier ║ ║ Contract ║ ║ Role (12 seed) ║ ║ Project ║ ║ + WorkflowDefId║ ║ Permission ║ ║ Department ║ ║ Approval ║ ║ (3-panel UI) ║ ║ + seed demo ║ ║ Comment ║ ║ MenuKey ║ ║ ContractClause ║ ║ Attachment ✅ ║ ║ + nested tree ║ ║ ║ ║ (E2E upload) ║ ╚════════════════╝ ╚════════════════╝ ╚════════════════╝ ╔════════════════╗ ╔════════════════╗ ╔════════════════╗ ║ FORM ENGINE ║ ║ WORKFLOW ║ ║ BÁO CÁO ║ ║ (Phase 2) ✅ ║ ║ (Phase 3) ✅ ║ ║ (Phase 4) ✅ ║ ╠════════════════╣ ╠════════════════╣ ╠════════════════╣ ║ Template CRUD ║ ║ StateMachine ║ ║ Dashboard ║ ║ DynamicForm ✅ ║ ║ Transition ║ ║ ExcelExport ║ ║ (DOCX/XLSX) ║ ║ SlaTimer ║ ║ MyDashboard ✅ ║ ║ FieldSpec JSON ║ ║ SlaExpiryJob ✅ ║ ║ (role-aware) ║ ║ PDF export ✅ ║ ║ CodeGen RG-001 ║ ║ ║ ║ (LibreOffice) ║ ║ **Versioned ✅**║ ║ ║ ║ .doc auto-conv ║ ║ (admin design)║ ║ ║ ╚════════════════╝ ╚════════════════╝ ╚════════════════╝ ╔════════════════╗ ╔════════════════╗ ╔════════════════╗ ║ NOTIFICATION ║ ║ ATTACHMENT ║ ║ BRANDING ║ ║ (Tier 3) ✅ ║ ║ (Tier 3) ✅ ║ ║ (Tier 3) ✅ ║ ╠════════════════╣ ╠════════════════╣ ╠════════════════╣ ║ Notification ║ ║ IFileStorage ║ ║ #1F7DC1 palette║ ║ SignalR Hub ║ ║ LocalFileStore ║ ║ Be Vietnam Pro ║ ║ Auto-push ║ ║ Path traversal ║ ║ Solutions logo ║ ║ interceptor ║ ║ guard ║ ║ ERP shell ║ ║ Toast + Bell ║ ║ 3 endpoint ║ ║ (TopBar + Bell║ ║ badge ║ ║ REST + FE ║ ║ + UserMenu) ║ ║ Email (TODO) ║ ║ drag-drop ║ ║ ║ ╚════════════════╝ ╚════════════════╝ ╚════════════════╝ ╔════════════════════════════════════════════════════════════╗ ║ INFRA / DEVOPS (Phase 5) ✅ ║ ╠════════════════════════════════════════════════════════════╣ ║ IIS 3 sites (Api/Admin/User) + URL Rewrite + ARR ║ ║ win-acme 3 Let's Encrypt cert + auto-renew ║ ║ Gitea Actions CI/CD (Windows self-hosted runner) ║ ║ SQL Server 2019 SQLEXPRESS + scripts/backup-sql.ps1 ║ ║ LibreOffice 25.8.6 headless (PDF/docx converter) ║ ║ Health check /health/live + /health/ready ║ ║ Serilog file rolling daily retention 30d ║ ║ Security headers + HSTS + rate limit 300/min global ║ ╚════════════════════════════════════════════════════════════╝ ``` ## Domain entities chính (implemented) ``` User ────< UserRoles >──── Role ────< Permission (Role × MenuKey × CRUD) MenuItem ─┬─ Parent-child tree (Contracts → Ct_MuaBan_* → ...) ├─ 28 Ct_* leaves (7 type × 3 action + 7 group) └─ 7 Wf_* leaves for workflow admin Supplier (NCC / NTP / TD / DVDV / CDT) Project (Dự án) Department (9 phòng từ QT docx) Contract ├── Type: HĐTP | HĐGK | NCC | HĐDV | HĐ Mua bán | Nguyên tắc NCC | Nguyên tắc DV ├── Phase (9 state) ├── WorkflowDefinitionId (pinned policy at create-time) ├── Supplier, Project, Drafter, Template ├── MaHopDong (gen theo RG-001 khi DangDongDau) ├── SlaDeadline + SlaWarningSent flag ├── Approvals[] (history) ├── Comments[] (thread) └── Attachments[] (scan + upload) WorkflowDefinition (versioned per ContractType) ├── Code (QT-MB, QT-TP, ...) + Version (v01, v02, ...) ├── IsActive (max 1 per ContractType) └── Steps[] ├── Order + Phase + Name + SlaDays └── Approvers[] (Kind=Role|User + AssignmentValue) WorkflowTypeAssignment (legacy admin override — fall back khi chưa có WorkflowDefinition) ContractTemplate (FormCode + ContractType + FieldSpec JSON + StoragePath) ContractClause (điều khoản chung FO-002.04) ContractCodeSequence (Prefix → LastSeq, atomic gen) Notification (RecipientUserId + Type + Title + Body + Link + IsRead) ``` ## API namespace (implemented) ``` /api/auth — login, refresh, me, logout /api/users — CRUD + assign roles + reset password + unlock + toggle active /api/roles — list (CRUD Create/Rename/Delete: TODO) /api/menus — /me tree với inherit Contracts/Workflows /api/suppliers — CRUD NCC /api/projects — CRUD dự án /api/departments — CRUD phòng ban /api/permissions — get matrix + bulk upsert /api/contracts — CRUD + query by phase/supplier/project/type + pendingMe /api/contracts/inbox — HĐ chờ role tôi /api/contracts/{id} — detail + pinned WorkflowDefinition policy /api/contracts/{id}/transitions — state machine action (role guard + versioned policy) /api/contracts/{id}/comments — thread góp ý /api/contracts/{id}/attachments — upload (multipart) + download stream + delete /api/forms — CRUD templates (upload/update/delete + render + PDF export) /api/forms/templates/{id}/export-pdf — LibreOffice conversion /api/workflows — admin GET overview + POST create new version /api/workflows/{type} — per-type definition + history /api/notifications — list + unread count + mark-read + mark-all-read /api/reports/dashboard — KPI tổng hợp /api/reports/my-dashboard — role-aware user-specific stats /api/reports/export — Excel download /hubs/notifications — SignalR hub (JWT qua ?access_token=) /health/live + /health/ready — health check ``` ## FE screens (implemented) ### fe-admin (:8082) — cho Admin + Role quản lý - `/login` - `/dashboard` — MyDashboard row (4 card) + KPI + charts - `/master/suppliers|projects|departments` — CRUD - `/system/users` — Users Mgmt (create/reset/unlock/assign-roles/toggle-active) - `/system/permissions` — **3-panel layout** (Role list | Menu×CRUD matrix | Granted stats) - `/system/workflows` — landing 7-card grid per ContractType - `/system/workflows/:typeCode` — Definition card (active + history) + Designer modal - `/forms` — list + upload + update + delete + render dialog (Form↔JSON toggle) + Tải PDF - `/contracts` — list full + filter phase/supplier/project/type - `/contracts/new` — Create (pre-select from `?type=X`) - `/contracts/:id` — detail + timeline + action dialog + **Attachments section** + WorkflowSummaryCard - `/reports` — filter + export Excel Sidebar: nested menu + `filterForAdmin` hide `Ct_*`, keep `Wf_*` for admin ### fe-user (:8080) — cho Drafter, TBP, PD/PM, BOD, CCM, HRA, ... - `/login` - `/inbox` — HĐ chờ role tôi xử lý (lọc theo `?type=X`) - `/my-contracts` — HĐ tôi đã tạo/tham gia (lọc theo `?type=X`) - `/contracts/new` — tạo HĐ draft (pre-select type) - `/contracts/:id` — detail + duyệt/comment + Attachments drag-drop Sidebar: nested 3-level, `filterForUser` hide admin items, hiển thị 7 ContractType × 3 action ## Flow chính (Phase 3 end-to-end, Tier 3 versioned) ``` Drafter (QS/NV.PB) ← pin WorkflowDefinitionId = v02 active ├─ [POST /api/contracts] tạo draft Phase=DangSoanThao, pin v02 ├─ [POST /api/forms/templates/{id}/render] fill FieldSpec + preview ├─ (upload scan đính kèm qua /attachments) ├─ [POST /api/contracts/{id}/transitions] DangSoanThao → DangGopY │ BE: load wfDef v02 → FromDefinition → Registry policy → guard (role + from/to) │ → Notification push tới all PD/PM/PRO/CCM/FIN/ACT + SignalR toast │ PD/PM/PRO/CCM/FIN/ACT (song song) └─ [POST /api/contracts/{id}/comments] góp ý → Notification push Drafter Drafter ├─ [PATCH /api/contracts/{id}] revise ├─ [POST .../transitions] DangGopY → DangDamPhan → DangInKy │ (BypassProcurementAndCCM=true → skip CCM → DangInKy → DangTrinhKy) │ NTP/NCC/TĐ (external — Drafter update thay) └─ upload scan có chữ ký đối tác Drafter → [transitions] → DangKiemTraCCM CCM → [transitions] → DangTrinhKy BOD → [transitions] → DangDongDau └─ BE: ContractCodeGenerator SERIALIZABLE → gen MaHopDong RG-001 HRA → [transitions] → DaPhatHanh (final) ``` ## External dependencies (hiện trạng) - **SQL Server** — prod SQLEXPRESS trên VPS, dev LocalDB hoặc Docker - **IIS** — Windows Server (VPS shared VIETREPORT), URL Rewrite + ARR + WebSockets module - **Gitea** — https://git.baocaogiaoduc.vn (self-hosted, shared runner) - **win-acme** — Let's Encrypt auto-renew - **LibreOffice 25.8.6** — PDF / docx / xlsx conversion (soffice headless) - **DocumentFormat.OpenXml** — render .docx (Phase 2) - **ClosedXML** — render .xlsx + Excel export (Phase 4) - **MediatR 12.4.1** — CQRS mediator (pin, 14 breaking) - **@microsoft/signalr 8.0.7** — FE realtime client - **Be Vietnam Pro** — Google Fonts (Vietnamese diacritics) ## Non-goals (KHÔNG làm) - ❌ Python AI service (user đã quyết gác vô thời hạn) - ❌ Mobile app (React Native) — Phase 6+ - ❌ Multi-tenant (1 instance / 1 công ty) - ❌ Tích hợp e-signature (VNPT/FPT CA) — Phase 6+ - ❌ Tích hợp SAP/Bravo ERP — Phase 6+ - ❌ Public API / external webhooks ## Architectural wins (Tier 3) 1. **Versioned workflow via Contract.WorkflowDefinitionId pin** — zero-cost immutability guarantee. HĐ cũ protected from policy changes by REFERENCE (FK restrict), không phải snapshot copy. 2. **Permission inheritance via menu ancestry** — Contracts + Workflows roots inherit CanRead xuống descendant Ct_* / Wf_* nodes. Không cần per-leaf permission rows → Permissions table nhỏ gọn. 3. **3-project clean-arch split cho cross-cutting services** (SignalR realtime + LibreOffice converter): - Abstraction ở Application (`IRealtimeNotifier`, `IDocumentConverter`) - Implementation ở Api / Infrastructure - Caller (Application handlers) KHÔNG depend transport / framework 4. **SaveChangesInterceptor auto-push notifications** — `NotificationPushInterceptor` capture Added Notifications ở SavingChanges, push via `IRealtimeNotifier` ở SavedChanges. Zero caller changes khi CQRS handler chỉ `db.Notifications.Add(n)`. 5. **URL-driven admin UI (workflows per-type)** — thay tabs bằng sidebar menu items + URL param. Linkable, bookmarkable, mỗi type có permission leaf riêng qua `Wf_`.