Files
solution-erp/docs/architecture.md
pqhuy1987 fe7ad8e4a3 [CLAUDE] Phase4: Report MVP + Docs Consolidation (rules, architecture, schema-diagram)
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>
2026-04-21 12:42:46 +07:00

14 KiB

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.

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"

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 Debug chuyển phase, 403, mã HĐ, bypass CĐT
form-engine Render template, upload, placeholder không replace
permission-matrix 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