Backend Report: - Application/Reports/Dtos/DashboardStatsDto: 5 KPI + PhaseCount + SupplierCount + ProjectCount + MonthlyValue - Application/Reports/Queries/GetDashboardStats handler: total/active/overdue/published this month/totalValueActive + byPhase + top 5 NCC/du an + 12 thang monthly (fill zero khi thang empty) - Application/Reports/Services/IContractExcelExporter interface - Infrastructure/Reports/ContractExcelExporter: ClosedXML workbook 10 cot, header style bold+blue, number format #,##0, formula SUM, auto-fit, freeze header - Application/Reports/Commands/ExportContractsToExcelCommand: filter phase/supplier/project/date range - Api/Controllers/ReportsController: GET /reports/dashboard, GET /reports/contracts/export - DI register IContractExcelExporter (Scoped) Frontend fe-admin: - types/reports.ts: DashboardStats type - components/BarChart.tsx: generic horizontal bar chart — chi Tailwind, khong thu vien ngoai - pages/DashboardPage.tsx REWRITE: 5 KPI card (FileText/TrendingUp/AlertTriangle/CheckCircle2/Coins) + by-phase bar + monthly 12-month chart + top 5 NCC + top 5 du an + skeleton loader - pages/ReportsPage.tsx MOI: filter phase/fromDate/toDate → export Excel button - Route /reports vao App.tsx E2E verified: - GET /api/reports/dashboard → 200 voi day du KPI + monthly fill 12 thang - GET /api/reports/contracts/export → 200 xlsx 7229 bytes (Microsoft Excel 2007+) Docs consolidation (theo yeu cau user): - docs/rules.md MOI: 9 section coding conventions (ngon ngu UI/code/DB/docs, BE Clean Arch, CQRS+MediatR, Validation FluentValidation, Error handling, Async, Entity rules, DI, Package pinning, FE React/TS erasableSyntaxOnly, path alias, TanStack Query, Permission guard, Toast+error, DB convention, Git commit format, Docs structure, Testing, Security) - docs/architecture.md MOI: layered overview ASCII art, request lifecycle (1 POST/api/contracts qua 10 step), workflow state machine 9 phase, permission model, data flow sequence diagram 4 actor (Drafter/Manager/CCM/BOD/HRA), deployment architecture Phase 5, skill library, non-functional table - docs/database/schema-diagram.md MOI: full ERD 19 table mermaid + data flow diagram + vong doi 1 HD (create → 7 transition → gen ma → publish) + index strategy table + relationship cardinality + soft delete behavior + SQL queries (inbox/dashboard/gen ma) + migration history - docs/gotchas.md UPDATE: 17 → 26 pitfalls, them section "Claude Code harness quirks" (Edit File not read, DI build pass nhung runtime fail) + "Contract workflow" (ma HD gen 2 lan, BE-FE NEXT_PHASES sync, race condition) + "Permission matrix" (cache real-time, MenuKey typo) - docs/STATUS.md: Phase 4 MVP done, docs entry points section liet ke het, next Phase 5 Production - docs/HANDOFF.md: phase table them Phase 4 row, file tree update voi Reports, test points day du, git state commit 7 - docs/changelog/migration-todos.md: tick Phase 4 MVP items + them iteration 2 list - docs/changelog/sessions/2026-04-21-1430-phase4-report.md: session log voi thong so cumulative (BE 3100 LOC, 30 docs) - CLAUDE.md root: update Tai lieu quan trong section them rules.md, architecture.md, schema-diagram.md, .claude/skills (13 links now) Bug fix: - TS unused import ContractPhaseLabel trong DashboardPage - DI thieu register IContractExcelExporter — build pass but runtime would fail (added) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
251 lines
14 KiB
Markdown
251 lines
14 KiB
Markdown
# Architecture — SOLUTION_ERP
|
|
|
|
> Kiến trúc tổng thể + trách nhiệm từng layer + diagram luồng dữ liệu.
|
|
|
|
## 1. Layered overview
|
|
|
|
```
|
|
┌──────────────────────────────────────────────────────────────┐
|
|
│ CLIENT TIER │
|
|
│ ┌──────────────────┐ ┌──────────────────┐ │
|
|
│ │ fe-admin :8082 │ │ fe-user :8080 │ │
|
|
│ │ React 19 + Vite │ │ React 19 + Vite │ │
|
|
│ │ Tailwind 4 │ │ Tailwind 4 │ │
|
|
│ │ TanStack Query │ │ TanStack Query │ │
|
|
│ └────────┬─────────┘ └────────┬─────────┘ │
|
|
└───────────┼──────────────────────────┼───────────────────────┘
|
|
│ Vite dev proxy /api │
|
|
│ IIS URL Rewrite prod │
|
|
▼ ▼
|
|
┌──────────────────────────────────────────────────────────────┐
|
|
│ API LAYER (:5443) │
|
|
│ SolutionErp.Api — ASP.NET Core 10 Web API │
|
|
│ ┌────────────────────────────────────────────────────────┐ │
|
|
│ │ Controllers: Auth, Menus, Roles, Permissions, │ │
|
|
│ │ Suppliers, Projects, Departments, │ │
|
|
│ │ Forms, Contracts, Reports │ │
|
|
│ │ Middleware: GlobalException, Serilog, CORS, JWT │ │
|
|
│ │ Authorization: MenuPermissionHandler (policy-based) │ │
|
|
│ │ Services: CurrentUserService, WebHostEnvLocator │ │
|
|
│ │ wwwroot/templates/ (5 .docx/.xlsx) │ │
|
|
│ └────────────────────┬───────────────────────────────────┘ │
|
|
└───────────────────────┼──────────────────────────────────────┘
|
|
│ MediatR ISender.Send(cmd)
|
|
▼
|
|
┌──────────────────────────────────────────────────────────────┐
|
|
│ APPLICATION LAYER │
|
|
│ SolutionErp.Application │
|
|
│ │
|
|
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
|
|
│ │ Auth │ │ Master │ │ Permissions │ │
|
|
│ │ (Login/Me) │ │ (CRUD 3 │ │ (Menu tree + │ │
|
|
│ │ │ │ entity) │ │ matrix) │ │
|
|
│ └──────────────┘ └──────────────┘ └──────────────────┘ │
|
|
│ ┌──────────────┐ ┌──────────────────┐ │
|
|
│ │ Forms │ │ Contracts │ ┌──────────────┐ │
|
|
│ │ (Render │ │ (Workflow 9 │ │ Reports │ │
|
|
│ │ engine) │ │ phase, Inbox) │ │ (Dashboard + │ │
|
|
│ └──────────────┘ └──────────────────┘ │ Excel exp) │ │
|
|
│ └──────────────┘ │
|
|
│ ┌──────────────────────────────────────────────────────┐ │
|
|
│ │ Common: Exceptions, Behaviors (ValidationPipeline), │ │
|
|
│ │ Interfaces (IDbContext, ICurrentUser, ...), │ │
|
|
│ │ Models (PagedResult) │ │
|
|
│ └──────────────────────────────────────────────────────┘ │
|
|
└───────┬──────────────────────────────────────────┬───────────┘
|
|
│ depends on interface │ runs on
|
|
▼ ▼
|
|
┌──────────────────────┐ ┌───────────────────────────┐
|
|
│ DOMAIN LAYER │ │ INFRASTRUCTURE LAYER │
|
|
│ SolutionErp.Domain │ │ SolutionErp.Infrastructure│
|
|
│ │ │ │
|
|
│ Common/BaseEntity │ │ Persistence/ApplicationD │
|
|
│ Contracts/ │ │ bContext + Migrations │
|
|
│ Forms/ │ │ Identity/JwtTokenService │
|
|
│ Identity/ │ │ Forms/Docx+XlsxRenderer │
|
|
│ Master/ │ │ Services/ContractWorkflow│
|
|
│ │ │ + ContractCodeGenerator│
|
|
│ Enum + value object │ │ Reports/ExcelExporter │
|
|
└──────────────────────┘ │ Services/DateTimeService │
|
|
↑ └────────────┬──────────────┘
|
|
│ references │
|
|
└───────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌───────────────────────┐
|
|
│ DATA TIER │
|
|
│ SQL Server 2022 │
|
|
│ (dbo schema, 19 bảng)│
|
|
└───────────────────────┘
|
|
```
|
|
|
|
## 2. Request lifecycle (1 POST/api/contracts)
|
|
|
|
```
|
|
1. Browser → POST /api/contracts { type, supplierId, ... }
|
|
2. Vite → proxy tới :5443
|
|
3. JwtBearerMiddleware → validate token, set ClaimsPrincipal
|
|
4. Routing → ContractsController.Create(cmd)
|
|
5. MediatR.Send(CreateContractCommand)
|
|
6. ValidationBehavior (pipeline) → FluentValidation run
|
|
7. CreateContractCommandHandler
|
|
├─ check Supplier/Project exists (IApplicationDbContext)
|
|
├─ new Contract entity + set DrafterUserId (ICurrentUser)
|
|
├─ set SlaDeadline (IDateTime + IContractWorkflowService.GetPhaseSla)
|
|
├─ db.Contracts.Add(...)
|
|
└─ SaveChangesAsync
|
|
├─ AuditingInterceptor sets CreatedAt/CreatedBy
|
|
└─ EF Core INSERT → SQL Server
|
|
8. Return Guid id
|
|
9. Controller → 201 Created + Location header
|
|
10. Axios interceptor (FE) → TanStack Query invalidate + UI update
|
|
```
|
|
|
|
## 3. Workflow state machine (Phase 3)
|
|
|
|
Xem full ở [`workflow-contract.md`](workflow-contract.md).
|
|
|
|
```
|
|
DangChon → DangSoanThao → DangGopY → DangDamPhan → DangInKy →
|
|
→ DangKiemTraCCM → DangTrinhKy → DangDongDau → DaPhatHanh
|
|
|
|
Alternates: → TuChoi (từ DangSoanThao)
|
|
→ DangSoanThao (revise từ bất kỳ phase duyệt)
|
|
|
|
Bypass CĐT (BypassProcurementAndCCM=true):
|
|
DangInKy → DangTrinhKy (skip CCM)
|
|
```
|
|
|
|
**Code generator trigger:** khi `targetPhase = DangDongDau` + `MaHopDong IS NULL` → gen format RG-001 với transaction SERIALIZABLE.
|
|
|
|
## 4. Permission model
|
|
|
|
```
|
|
User ──(AspNetUserRoles)── Role ──(Permissions)── MenuItem
|
|
│
|
|
├── CanRead
|
|
├── CanCreate
|
|
├── CanUpdate
|
|
└── CanDelete
|
|
```
|
|
|
|
**Resolution:**
|
|
- Login → JWT chứa claims (sub, email, roles)
|
|
- `/api/menus/me` → query Permissions theo roleIds, **union OR** CRUD flags, filter tree theo CanRead
|
|
- FE cache menu trong `AuthContext` + localStorage
|
|
- Mỗi API action: `[Authorize(Policy = "{MenuKey}.{Action}")]` → `MenuPermissionHandler` check
|
|
|
|
**Admin bypass:** role `Admin` luôn pass mọi policy (seed default full CRUD).
|
|
|
|
## 5. Data flow — "tạo HĐ và chạy hết workflow"
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
actor D as Drafter
|
|
actor M as Manager (PD/PM)
|
|
actor C as CCM
|
|
actor B as BOD
|
|
actor H as HRA
|
|
|
|
participant FE as fe-user
|
|
participant API
|
|
participant WF as WorkflowService
|
|
participant CG as CodeGenerator
|
|
participant DB
|
|
|
|
D->>FE: POST /contracts/new
|
|
FE->>API: POST /api/contracts
|
|
API->>DB: INSERT Contracts (Phase=DangSoanThao, SLA=+7d)
|
|
API-->>FE: 201 {id}
|
|
|
|
D->>FE: Click "Submit → góp ý"
|
|
FE->>API: POST /contracts/{id}/transitions {target:3}
|
|
API->>WF: Transition(contract, 3, roles=[Drafter])
|
|
WF->>WF: Check adjacency + role
|
|
WF->>DB: INSERT ContractApproval + UPDATE Contract Phase=3
|
|
API-->>FE: 204
|
|
|
|
M->>FE: Inbox → click HĐ → góp ý + "Chuyển tiếp"
|
|
FE->>API: POST /transitions {target:4}
|
|
API->>WF: Transition → Phase 4
|
|
Note over WF: Chạy tương tự qua 5,6,7
|
|
|
|
B->>FE: Duyệt → target:8 DangDongDau
|
|
FE->>API: POST /transitions {target:8}
|
|
API->>WF: Transition
|
|
WF->>CG: GenerateAsync(contract, project, supplier)
|
|
CG->>DB: BEGIN TRAN SERIALIZABLE
|
|
CG->>DB: SELECT/UPDATE ContractCodeSequences
|
|
CG->>DB: COMMIT
|
|
CG-->>WF: "FLOCK 01/HĐGK/SOL&PVL/03"
|
|
WF->>DB: UPDATE Contract SET MaHopDong, Phase=8
|
|
API-->>FE: 204
|
|
|
|
H->>FE: Click đóng dấu → target:9
|
|
FE->>API: POST /transitions {target:9}
|
|
API->>WF: Transition (role HrAdmin)
|
|
WF->>DB: UPDATE Phase=9 (DaPhatHanh)
|
|
API-->>FE: 204
|
|
```
|
|
|
|
## 6. Deployment architecture (Phase 5 — planned)
|
|
|
|
```
|
|
┌─────────────────────────────┐
|
|
│ Internet / Corp LAN │
|
|
└──────────────┬──────────────┘
|
|
│
|
|
┌──────────▼──────────┐
|
|
│ IIS (Win Server) │
|
|
│ URL Rewrite / ARR │
|
|
└──────────┬──────────┘
|
|
┌─────────────┼─────────────┐
|
|
│ │ │
|
|
┌──────▼──────┐ ┌───▼────┐ ┌──────▼──────┐
|
|
│ fe-admin │ │ Api │ │ fe-user │
|
|
│ static files│ │ Kestrel│ │ static files│
|
|
│ (dist/) │ │ :5443 │ │ (dist/) │
|
|
└─────────────┘ └───┬────┘ └─────────────┘
|
|
│
|
|
┌────────▼────────┐
|
|
│ SQL Server │
|
|
│ (same host OR │
|
|
│ separate VM) │
|
|
└─────────────────┘
|
|
```
|
|
|
|
- IIS app pool riêng cho Api, Integrated Managed Pipeline, .NET CLR disabled (hosting .NET 10 OOP)
|
|
- Static files 2 FE deploy vào `C:\inetpub\wwwroot\solution-erp-admin\` + `...user\`
|
|
- HTTPS: Let's Encrypt qua win-acme (hoặc cert mua)
|
|
- Backup SQL: daily full + 15min log → D:\Backups
|
|
|
|
## 7. Skill library (AI agent support)
|
|
|
|
`.claude/skills/` có 3 skill chuyên biệt:
|
|
|
|
| Skill | Dùng khi |
|
|
|---|---|
|
|
| [`contract-workflow`](../.claude/skills/contract-workflow/SKILL.md) | Debug chuyển phase, 403, mã HĐ, bypass CĐT |
|
|
| [`form-engine`](../.claude/skills/form-engine/SKILL.md) | Render template, upload, placeholder không replace |
|
|
| [`permission-matrix`](../.claude/skills/permission-matrix/SKILL.md) | Access denied, menu không hiện, gán role |
|
|
|
|
Claude auto-invoke theo description matching.
|
|
|
|
## 8. Non-functional
|
|
|
|
| Aspect | Current | Phase 5 target |
|
|
|---|---|---|
|
|
| Availability | dev-only | 99.5% (IIS restart, SQL HA optional) |
|
|
| Latency | <200ms P95 local | <500ms P95 prod |
|
|
| Concurrency | unrestricted | rate limit 100 req/min/IP |
|
|
| Observability | Serilog console | + file rolling daily + Seq/ELK |
|
|
| Security | JWT + HTTPS dev | + rate limit + audit log + CSP |
|
|
|
|
## 9. Liên quan
|
|
|
|
- [`rules.md`](rules.md) — coding conventions
|
|
- [`database/database-guide.md`](database/database-guide.md) — DB schema chi tiết
|
|
- [`flows/`](flows/) — per-feature sequence diagrams
|
|
- [`workflow-contract.md`](workflow-contract.md) — state machine spec
|
|
- [`forms-spec.md`](forms-spec.md) — 8 form catalog
|