Commit Graph

20 Commits

Author SHA1 Message Date
52999f33fa [CLAUDE] Docs: chốt session 5 — Budget FE + PE feature complete + Tests Phase 1-2 + CI gate
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Failing after 22s
Session 5 (29/04) — 6 commit feature + 1 chốt MD này.

==== Stats sau session 5 ====
- 52 DB tables (+1 PEDeptOpinions)
- 15 migrations (+`AddPurchaseEvaluationDepartmentOpinions`)
- ~128 API endpoints (+4)
- ~31 FE pages (+5 Budget + 1 PeWorkflowsPage)
- 71 unit test pass (54 Domain + 17 Infra) — CI gate live, fail → no deploy
- ~13050 BE LOC (+1300)
- 30 demo user, 38 gotchas, 6 skill (no change)

==== MD touched ====
- STATUS.md: header Phase 8 + 6 row Recently Done session 5 + cumulative cột S5 + In Progress S6 (Hard blockers + Optional polish + Tests Phase 3-5 + Ops)
- HANDOFF.md: TL;DR 6 milestone S5 + Cảnh báo S6 (CI test gate workflow mới) + Priority 0 S6 (UAT + Ops focus) + Phase status table cập nhật
- migration-todos.md: Phase 8 done với A/B/C/D/E (FE Budget / PE-HD integration / PE WF Designer / Ý kiến 4 PB / Tests Phase 1-2) + Phase 9 active (UAT + Ops + carry over)
- architecture.md: §11 Testing strategy mới (test pyramid bottom-heavy + stack + CI gate + phased priority + quy tắc bổ sung mỗi feature)
- database/schema-diagram.md: Migration 15 row + total 52 tables + §13 PE Department Opinion (1 bảng UNIQUE PEId+Kind + Upsert behavior + SQL DDL)
- ef-core-migration SKILL: migration 15 entry + 52 tables total + Phase 8 update note
- CLAUDE.md (root): modules table + Tests row + scope `Tests` + Tests section mới + count update 15/52
- docs/CLAUDE.md: 7 module bullet + ERD 52 bảng + Roadmap Phase 8 done + Phase 9 active S6
- memory project_solution_erp.md: Phase 8 summary + Session 6 priority + workflow user mới (dotnet test → commit → push)
- session log 2026-04-29-chot-session-5-budget-fe-pe-tests.md (NEW — 10+ section detail)

==== Verify ====
- dotnet test SolutionErp.slnx → 71 pass / 2s
- git status clean sau commit này

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 13:50:54 +07:00
e0b4e7f096 [CLAUDE] Docs: chốt session 4 — Budget BE module + 14 Solutions users
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m53s
- STATUS.md: header Phase 7 + 3 row Recently Done (Budget BE / 14 users / Docs cleanup) + cumulative cột mới (51 tables / 14 mig / ~124 endpoints)
- HANDOFF.md: TL;DR session 4 (2 milestone Budget BE + 14 users) + Cảnh báo session 5 + Priority 0 (FE Budget + PE/HD integration + PE feature gap) + Credentials 30 user
- migration-todos.md: Phase 7 thêm section D Budget done + Phase 8 mới (FE Budget pages + integration) + pending migrations Budget
- architecture.md: §10 Budget module mới (ERD + state machine + auto-recompute + integration roadmap)
- database/schema-diagram.md: migration history rows 13+14 + §12 Budget ERD chi tiết
- ef-core-migration SKILL: migration 14 entry + Phase 8 pending Budget refinement
- CLAUDE.md root + docs: modules table thêm Budget row + scope Budget + count 51 bảng / 14 mig
- Session log 2026-04-28-chot-session-4-budget.md (10+ section detailed)

Stats: 51 tables (+4 Budget), 14 migrations (+AddBudgets), ~124 endpoints (+11 Budget),
30 demo user (16 sample + 14 Solutions thật), 38 gotchas, ~340 LOC Budget CQRS.
FE Budget pages chưa làm — Priority 0 session 5.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 12:36:31 +07:00
e71e0eba65 [CLAUDE] Docs: tai cau truc cleanup — archive raw, compact migration-todos, update CLAUDE+flows
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m53s
User request: 'review cap nhat va tai cau truc lai MD sao cho phu hop
voi hien tai, cac phan thua va da dieu chinh co the bo ra luon hoac
cap nhat lai'.

Cleanup highlights:
1. Archive 2 file Phase 0 raw dump → docs/_archive/ (forms-spec-raw 657
   line + workflow-raw 62 line). Update link reference 2 file goc.
2. Compact migration-todos.md 386 → 114 line (-71%). Collapse Phase 0-5
   + Tier 3 + Sessions detailed thanh 1 bang summary. Detail xem session
   logs. Phase 6 iter 1+2 + Phase 7 active checklist.
3. Compact STATUS.md In Progress: bo ~17 row  done (giu chỉ 5+ task
   pending: 3 PE feature gap + 4 optional polish + 2 Ops). Recently Done
   table giu day du history.
4. Update flows/README — tat ca 6 flow  Implemented + them PE row
   reference architecture.md §9.
5. Update docs/CLAUDE.md — project layout co PurchaseEvaluations, _archive,
   skills 6 (3 dom + 3 ops). Roadmap them Phase 6  + Phase 7 WIP. Lien
   he them prod URL solutions.com.vn + SSH config + login admin.
6. Skill ef-core-migration: 13 migration label.

Net delta: -800 line docs (chu yeu archive + collapse migration-todos).
2026-04-25 14:17:53 +07:00
c48ac2116d [CLAUDE] PurchaseEvaluation: demo seed 4 phieu + MaPhieu atomic sequence + Pe_* perm defaults
Polish session tiep cua PE module skeleton (commit 2c6f0ca..3990066):
3 task A (MISSING in MVP) khac STATUS.md In Progress:

1. Demo PE data seed (SeedDemoPurchaseEvaluationsAsync)
   - 4 phieu varied A/B x phase: A-001 DangSoanThao (mo), A-002
     ChoCEODuyetNCC (winner+9 quotes), A-003 DaDuyet (chua tao HD,
     PaymentTerms JSON), B-001 ChoDuAn (5-step giua chung).
   - Idempotent: skip-if-[DEMO]-exists.
   - Approval history dung policy A (3-step) hoac B (5-step).

2. MaPhieu atomic sequence — Migration 13
   - Format PE/{YYYY}/{TypeLetter}/{Seq:D3} (vd PE/2026/A/001).
   - PurchaseEvaluationCodeSequence entity (Prefix PK).
   - IPurchaseEvaluationCodeGenerator + impl SERIALIZABLE
     transaction (mirror ContractCodeGenerator 1:1).
   - Replace Random.Shared trong CreatePurchaseEvaluationCommandHandler.
   - Migration AddPurchaseEvaluationCodeSequences (1 bang).

3. Pe_* permission defaults
   - SeedPurchaseEvaluationPermissionDefaultsAsync — 7 role business x 9 menu key.
   - Drafter/DeptManager/Procurement: R+C+U; CostControl/PM/Director/AuthorizedSigner: R+U.
   - DeptManager them Delete (xoa nhap).
   - Idempotent per-(roleId x menuKey).

Build: 0 error, 2 warning (pre-existing DocxRenderer).

Files: 4 new + 8 modified (1 migration + entity + generator + DI + 2 ctx + 2 features).

Resolves: STATUS.md In Progress §A — 3 item PE MISSING.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 10:41:17 +07:00
7ca6c914fa [CLAUDE] Docs: chốt session 2 — PE skeleton + G-084 + skill audit
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m55s
User feedback: "phần Duyệt NCC chưa xong đâu đấy nhé, còn chỉnh nhiều"
→ mark PE module skeleton (not feature-complete), liệt kê chi tiết chức
năng/UX/edge-case còn missing cho session tiếp.

Update 7 file:
 - STATUS.md — phase = "PE skeleton + refinement WIP", In Progress liệt
   kê 4 nhóm: A Chức năng MISSING (9 item), B UX/Polish (6 item),
   C Edge case (4 item), D Deploy/Ops (1 item). +G-084 row Recently Done.
 - HANDOFF.md — TL;DR "PE skeleton, còn chỉnh nhiều" + Priority 0 section
   cho session tiếp (9 task PE refinement) + cảnh báo runner + G-084.
 - migration-todos.md — Phase 7 checklist (A/B/C/D nhóm) trước Phase 8
   post-launch. Pending migrations: PaymentTermFields + DepartmentOpinions
   + CodeSequences.
 - architecture.md — Section 9 PurchaseEvaluation module (ERD + workflow
   A/B + kế thừa HĐ flow).
 - CLAUDE.md (root) — 5 file đọc đầu (thêm HANDOFF), Modules table, 12
   migration 46 bảng, +PurchaseEvaluation commit scope.
 - .claude/skills/ — 4 skill cross-ref Phase 6:
   * README: trạng thái updated với Phase 6 note
   * contract-workflow: note PE workflow tách table riêng
   * permission-matrix: +Pe_*/PeWf_* menu keys + TODO grant non-admin
   * ef-core-migration: 12 migration history + Phase 7 pending
 - docs/changelog/sessions/2026-04-23-2359-chot-session-pe-skeleton.md —
   session log full commits + MD files updated + session tiếp priorities
   + notes (PE là skeleton, runner check, G-084 rule, MaPhieu format).
2026-04-23 17:46:41 +07:00
aaf03be8d7 [CLAUDE] Docs: chốt Phase 6 — Module Duyệt NCC E2E
Update 5 file:
 - STATUS.md: phase hiện tại + recently done 4 entry + cumulative stats
   (46 tables, ~110 endpoints, 12 migrations, ~26 FE pages)
 - HANDOFF.md: TL;DR + thêm row "Module Duyệt NCC E2E" 
 - changelog/migration-todos.md: thêm Phase 6 section với checklist
   done/optional (PE Workflow admin UI + Attachments + Auto-map
   Details skip MVP)
 - database/schema-diagram.md: Migration 12 row + section 11 "PurchaseEvaluation
   module" full (10 bảng + state machine + kế thừa HĐ flow)
 - changelog/sessions/2026-04-23-2300-purchase-evaluations.md: session
   log đầy đủ (user input + design + 4 commit + stats + skip MVP notes)
2026-04-23 17:01:53 +07:00
a7ea6ad3d6 [CLAUDE] Docs: chốt session 2026-04-23 tối — UAT-ready 100%
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m48s
5 commit feature work session 2 (072ad6dbcdc007) — clear hết task
pending high-impact, sẵn sàng UAT.

## Session log mới

`docs/changelog/sessions/2026-04-23-2200-roles-demo-pending-cleanup.md`
~270 dòng — outcome A→G (RolesPage + 7 demo HĐ + User-kind guard +
Warning SLA + Edit detail + Master expand + Deps script), stats,
architectural notes, next priority.

## STATUS.md

- Last updated 2026-04-23 22:30 — UAT-ready 100%
- Header phase: "Pending tasks cleared — UAT-ready"
- 5 Recently Done row mới (RolesPage, demo HĐ, user-kind+SLA, edit
  detail+deps, master expand+backfill)
- Cumulative table thêm cột "+RolesPg+Demo+Pending":
  - LOC ~7800 → ~8800
  - Endpoints ~80 → ~93
  - FE pages ~22 → ~23 (RolesPage)
  - Scripts 4 → 5 (deps-audit.ps1)
  - Demo data 5+3 → 15+8+7+13+4 (NCC/Project/HĐ/User/Catalogs)
  - Commits ~47 → ~52
- Session log link mới
- Skills count = 14 file

## HANDOFF.md

- TL;DR cập nhật: UAT-ready 100%, demo data đầy đủ inventory
- Phase table thêm 6 row Done (RolesPage, demo HĐ, user-kind+SLA,
  edit detail, master expand, deps script)
- Git state 8 commit gần nhất

## migration-todos.md

- Section "Session 2026-04-23 (tối)" với 8 ticked checkbox + commit refs
- 3 Roles CRUD checkbox legacy → ticked với commit 072ad6d ref

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 16:07:20 +07:00
ff5e35f279 [CLAUDE] Docs: chốt session 2026-04-23 chiều — toolkit + 4-bảng + master + roles VN
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m47s
11 commit feature work (b75448eae59cfe) → docs sync.

## STATUS.md

- Last updated 2026-04-23 16:00
- Phase header: Tier 3 + 4-bảng + master catalogs + roles VN
- 7 Recently Done row mới (3-panel layout, 4-bảng overhaul, Thao tác
  2-panel, Mã HĐ gen Create, master catalogs, roles VN demo users)
- Cumulative table thêm cột "+Toolkit/Catalogs/Roles" (DB 36, endpoints
  ~80, migrations 11, commits ~47)
- Session log link mới
- Skill list count = 13 file

## HANDOFF.md

- TL;DR cập nhật: 36 tables, 80 endpoints, 11 migrations
- Phase table thêm 5 row Done (3-panel, 4-bảng, mã HĐ, master, roles)
- Git state 18 commit gần nhất
- Credentials block thêm 13 demo user (User@123456) — warn rotate trước UAT

## migration-todos.md

Section "Session 2026-04-23 (chiều)" với 14 ticked checkbox + commit refs.

## schema-diagram.md

- Header: 24 → 36 bảng
- Migration table thêm row 9-11 (highlighted)
- Section 8bis mới: chi tiết 7 Details + ContractChangelogs + 4 Catalogs +
  Role.ShortName + User.DepartmentId/Position

## Session log mới

`docs/changelog/sessions/2026-04-23-1500-toolkit-data-roles.md` (~270
dòng) — outcome A→I, stats cumulative, 6 architectural decisions, next
session priority.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 14:39:48 +07:00
b904a25dc1 [CLAUDE] Skill: governance + audit định kỳ hàng tháng
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m48s
- rules.md §9 mới: liệt kê 6 skill (3 domain + 3 ops) với trigger,
  nguyên tắc tạo skill project-specific (không clone generic),
  format SKILL.md bắt buộc, audit workflow §9.4 chi tiết 7 bước,
  4 anti-patterns
- CLAUDE.md (root): block "🛠️ Skills" callout 6 skill + audit cadence
  + commit scope thêm `Skill`
- HANDOFF.md: section A1 — định kỳ audit, lần kế tiếp 2026-05-01
- migration-todos: section "Skill governance (recurring)" với checkbox
  audit hàng tháng

Cron task tạo qua scheduled-tasks (ID: solution-erp-skill-audit-
monthly): chạy 9:00 AM ngày 1 mỗi tháng. Self-contained prompt cold-
start để session tự audit + log vào docs/changelog/skill-audit-
{YYYY-MM}.md. Auto-refresh stale skill nhỏ, đề xuất add/archive cho
human approve.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 00:12:54 +07:00
fbca83264c [CLAUDE] Docs: chốt session Tier 3 feature-complete + versioned workflow
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>
2026-04-22 10:25:02 +07:00
1b5ef2ed51 [CLAUDE] Phase5.1/3.2: IDOR filter + SLA auto-approve job + admin password warning
IDOR filter ContractsController:
- ListContractsQueryHandler + ICurrentUser: non-admin chi thay HD minh la Drafter hoac role eligible phase hien tai
- GetContractQueryHandler + ICurrentUser: throw ForbiddenException neu truy cap HD khong lien quan
- GetEligiblePhases() internal static trong ListContractsQueryHandler — mirror GetMyInboxQueryHandler.PhaseActorRoles (Drafter/DeptManager → DangSoanThao/DangDamPhan/DangInKy, ProjectManager+PRO+CCM+FIN+ACT+EQU → DangGopY, CostControl → DangKiemTraCCM, Director+AuthorizedSigner → DangTrinhKy, HrAdmin → DangDongDau)

SLA Expiry BackgroundService (Phase 3 iteration 2 partial):
- Infrastructure/HostedServices/SlaExpiryJob MOI: BackgroundService moi 15 phut (delay 30s startup)
- Query Contracts WHERE SlaDeadline < UtcNow AND Phase NOT IN (DaPhatHanh, TuChoi)
- Map phase → next (happy path). Goi IContractWorkflowService.TransitionAsync voi actorUserId=null + Decision=AutoApprove + comment 'AUTO: het SLA phase X (Nh qua han)'
- Try-catch tung contract, 1 fail khong block batch
- Log structured: 'SlaExpiryJob: auto-approved contract {Id} {From} → {To}'
- Package Microsoft.Extensions.Hosting added to Infrastructure
- DI register AddHostedService<SlaExpiryJob>

Admin password warning (Phase 5.1):
- DbInitializer.WarnDefaultAdminPasswordAsync: check CheckPasswordAsync voi AdminPassword default → log WRN '⚠️  Admin user vẫn dùng password mặc định. ĐỔI NGAY trong production!'
- Chain vao InitializeAsync sau cac seed

E2E verified:
- Admin GET /contracts → total 1 (see all)
- Drafter GET /contracts → total 0 (IDOR filter, chua tao HD nao)
- API startup log: '⚠️  Admin user admin@solutionerp.local vẫn dùng password mặc định'
- Build + TS check → pass

Docs:
- STATUS.md: Phase 5.1 hau nhu xong (IDOR + admin warning + SLA job tick), cumulative BE 3900 LOC
- migration-todos.md: tick Phase 5.1 IDOR + admin warning, Phase 3 iter 2 SlaExpiryJob + E2E non-admin + admin warning
- session log 2026-04-21-1730-idor-sla-job.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 13:15:14 +07:00
11e61c9c39 [CLAUDE] Phase5.1: Security headers + account lockout + Users management
Security hardening:
- Api/Middleware/SecurityHeadersMiddleware MOI: remove server fingerprint (Server, X-Powered-By, ...), add X-Content-Type-Options:nosniff, X-Frame-Options:DENY, Referrer-Policy:strict-origin-when-cross-origin, Permissions-Policy (disable geolocation/mic/cam/payment), X-Permitted-Cross-Domain-Policies:none, CSP (default-src 'self' + img data: + style inline for Tailwind + frame-ancestors 'none'). Skip CSP tren /swagger (dung inline script).
- Program.cs wire UseMiddleware SecurityHeadersMiddleware first in pipeline
- Infrastructure/DependencyInjection Identity options:
  - Password.RequiredLength config-driven (Identity:Password:RequiredLength, default 8 dev, override 12+ prod)
  - Lockout: DefaultLockoutTimeSpan (15min), MaxFailedAccessAttempts (5), AllowedForNewUsers=true — all config-driven
- LoginCommandHandler: IsLockedOutAsync check truoc → throw voi deadline message, AccessFailedAsync khi sai password, ResetAccessFailedCountAsync khi login thanh cong

Users management:
- Application/Users/UserFeatures.cs: 8 CQRS (ListUsersQuery paging+search, GetUserQuery, CreateUserCommand + Validator, UpdateUserCommand voi self-disable protection, AssignRolesCommand voi self-demote protection (khong tu go Admin), ResetPasswordCommand (invalidate refresh token + unlock), UnlockUserCommand)
- UserDto: Id, Email, FullName, IsActive, IsLocked (computed tu LockoutEnd), CreatedAt, Roles
- Api/Controllers/UsersController: 7 endpoint (Users.Read/Create/Update policies):
  - GET / (list paged), GET /{id}, POST /, PUT /{id}, PUT /{id}/roles, POST /{id}/reset-password, POST /{id}/unlock
- using alias ValidationException = Application.Common.Exceptions.ValidationException (fix ambiguity voi FluentValidation)

Frontend fe-admin:
- types/users.ts MOI: User type + AVAILABLE_ROLES 12 role (match BE AppRoles.cs) + RoleLabel Vietnamese
- pages/system/UsersPage.tsx MOI:
  - DataTable columns: Email (mono), FullName, Roles (badge chips voi Vietnamese label), IsActive (CheckCircle/XCircle), IsLocked (KeyRound red), CreatedAt
  - Actions per row (PermissionGuard Users.Update wrap): Gan role (Shield icon → Dialog grid 12 checkbox), Reset password (KeyRound → Dialog voi warning user se bi logout), Unlock (Unlock icon, chi hien khi isLocked), Toggle active (XCircle/CheckCircle)
  - Create user dialog: email + fullName + password (min 8) + grid 12 role checkbox
- Route /system/users vao App.tsx

E2E verified:
- Security headers present tren moi response (check qua curl -I)
- POST /api/users voi roles: [Drafter] → 201 + id
- GET /api/users → paged voi 2 user (admin + new test.drafter)
- TS check fe-admin → pass
- dotnet build → 0 errors

Docs:
- docs/STATUS.md: Phase 5.1 xong, cumulative BE 3700 LOC, 42 endpoints, 17 FE pages
- docs/HANDOFF.md: phase table update row Phase 5.1, last updated timestamp
- docs/changelog/migration-todos.md: tick 6 items Phase 5.1 + 4 items remaining (IDOR, deps scan, admin warning, Roles CRUD)
- docs/changelog/sessions/2026-04-21-1630-phase5-1-security-users.md: session log

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
2026-04-21 13:06:46 +07:00
46a2cab788 [CLAUDE] Docs: tick Phase 5 Prep items in migration-todos
Follow-up: migration-todos Phase 5 section update bi miss trong commit truoc (Edit bi block boi system reminder). Apply lai:
- Tick 14 items Prep xong
- Split 'Deploy that (can Gitea URL)' va 'Phase 5.1 Security hardening'

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 12:58:08 +07:00
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
7e957a7654 [CLAUDE] Phase3: Workflow MVP — 9-phase state machine + code gen + FE Inbox/Detail
Backend Contracts domain (5 entities):
- Contract aggregate: Phase (9 enum), SlaDeadline, MaHopDong, BypassProcurementAndCCM, DraftData, SlaWarningSent
- ContractApproval: FromPhase → ToPhase, ApproverUserId (null = system auto-approve), Decision, Comment
- ContractComment: thread theo Phase current
- ContractAttachment: FileName + StoragePath + Purpose (DraftExport/ScannedSigned/SealedCopy)
- ContractCodeSequence: Prefix PK + LastSeq — atomic gen

EF configs:
- Unique MaHopDong filtered [MaHopDong] IS NOT NULL
- Indexes: Phase+IsDeleted, SupplierId, ProjectId, SlaDeadline, ContractId+ApprovedAt, ContractId+CreatedAt
- Cascade delete Approvals/Comments/Attachments khi Contract xoa
- Query filter IsDeleted
- Migration AddContractsWorkflow (DB 19 tables)

Workflow service:
- IContractWorkflowService.TransitionAsync:
  - Adjacency check qua Transitions Dict<(from,to), roles[]> (12 transitions)
  - Role guard: user phai co role ∈ allowed
  - Admin bypass (role Admin pass moi check)
  - System bypass (userId=null + Decision=AutoApprove → cho SLA job sau nay)
  - Bypass CCM: BypassProcurementAndCCM=true cho phep DangInKy → DangTrinhKy skip phase 6
  - Gen ma HD khi chuyen DangDongDau (idempotent — khong gen lai neu da co)
  - Reset SlaDeadline = UtcNow + PhaseSla
  - Insert ContractApproval row

Code generator (RG-001):
- 7 format theo ContractType: HDTP / HDGK / NCC / HDDV / MB + 2 framework (year prefix)
- BeginTransactionAsync(Serializable) + ContractCodeSequences UPSERT → atomic
- Idempotent: neu MaHopDong da co thi skip

CQRS (8 feature, ContractFeatures.cs):
- CreateContractCommand + Validator + Handler (set SlaDeadline = +7d)
- UpdateContractDraftCommand (chi khi Phase=DangSoanThao)
- TransitionContractCommand (delegate → WorkflowService)
- AddCommentCommand (phase = hien tai)
- ListContractsQuery (PagedResult + filter phase/supplier/project/search)
- GetMyInboxQuery (map Phase → actor roles, filter theo role user)
- GetContractQuery (detail + approvals + comments + attachments + resolve user names)
- DeleteContractCommand (soft, block > DangInKy)

Controller:
- ContractsController 8 endpoint: GET list/inbox/detail, POST create/transition/comment, PUT update, DELETE

Frontend fe-admin (2 page moi):
- types/contracts.ts: ContractPhase const + Label + Color maps + types
- components/PhaseBadge.tsx
- pages/contracts/ContractsListPage.tsx: filter phase + search + click → detail
- pages/contracts/ContractDetailPage.tsx: 2-col layout (info+comments | timeline), action dialog select target phase + comment

Frontend fe-user (4 page moi + 14 file shared):
- cp 14 file shared tu fe-admin (menuKeys, types/*, DataTable, PhaseBadge, Dialog, Textarea, Select, apiError, usePermission, PermissionGuard)
- AuthContext update: load menu tu /menus/me + cache
- Layout: menu fixed 3 muc + user info + roles display
- InboxPage: list HD cho role user xu ly (sort theo SLA)
- ContractCreatePage: form chon loai + template + NCC + du an + gia tri + bypass CDT
- ContractDetailPage: duplicate fe-admin pattern (convention)
- MyContractsPage: list HD cua toi
- App.tsx: 4 route moi

E2E verified:
- Setup Supplier + Project
- POST /contracts → 201 + phase=2
- POST /contracts/{id}/transitions x7 → di het 9 phase
- Final: MaHopDong = "FLOCK 01/HĐGK/SOL&PVL2026/01" dung format RG-001
- Approvals: 7 rows audit day du

Docs:
- .claude/skills/contract-workflow/SKILL.md: placeholder → full spec voi state machine, SLA table, role matrix, 7 code format, code pointers, API, E2E workflow, pitfalls
- docs/changelog/sessions/2026-04-21-1330-phase3-workflow.md: session log
- docs/STATUS.md: Phase 3 MVP done, next Phase 4
- docs/HANDOFF.md: update phase status + file tree + commit log + testing points
- docs/changelog/migration-todos.md: tick Phase 3 MVP items + add iteration 2 list

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 12:26:09 +07:00
5113e4c771 [CLAUDE] Phase2: Form Engine MVP + docs (gotchas, skill, handoff)
Backend Forms:
- Domain/Forms: ContractTemplate (FormCode, Name, ContractType, FileName, StoragePath, Format, FieldSpec JSON, IsActive) + ContractClause
- EF config voi unique FormCode + query filter IsDeleted
- DbSets + IApplicationDbContext update
- Migration AddForms (bang 14 total)
- Packages: DocumentFormat.OpenXml 3.x + ClosedXML 0.105+
- Application/Forms:
  - IFormRenderer interface + RenderResult record
  - FormFeatures.cs: List/Get/Render CQRS
  - IWebHostEnvironmentLocator (abstract IWebHostEnvironment)
- Infrastructure/Forms:
  - DocxRenderer: OpenXml-based placeholder {{field}} replace, handle split runs (gom text tat ca <w:t> trong paragraph, replace, gan lai text dau + clear rest)
  - XlsxRenderer: ClosedXML cell value replace
  - FormRenderer router theo format docx/xlsx
- Api:
  - FormsController: GET /templates (filter type, onlyActive), GET /templates/{id}, POST /templates/{id}/render (return file)
  - WebHostEnvironmentLocator impl
- DbInitializer SeedContractTemplatesAsync: seed 8 template metadata, IsActive=true chi khi file ton tai

Templates vat ly:
- Copy 5 .docx/.xlsx tu FORM/ sang wwwroot/templates/
- 3 .doc (FO-002.02/03/06) chua convert: IsActive=false (Word COM bi stuck luc test, can retry voi DisplayAlerts=0 hoac LibreOffice)
- scripts/convert-doc-to-docx.ps1 (Word COM automation)

Frontend fe-admin:
- types/forms.ts: ContractTemplate + ContractTypeLabel
- pages/forms/FormsPage.tsx: list templates + Render dialog (paste JSON data → download .docx/.xlsx)
- Route /forms them vao App.tsx

Bug fix:
- SpaceProcessingModeValues namespace: wrap EnumValue<> full path
- SaveAs2($path, 16) thay vi SaveAs([ref], [ref]) — PowerShell type issue
- Word COM stuck: kill process, skip .doc cho MVP

Docs (theo yeu cau user):
- docs/gotchas.md MOI: 17 pitfalls nhom theo tech stack / EF Core / OpenXml / JSON / dev workflow
- .claude/skills/form-engine/SKILL.md: placeholder → full spec (algorithm + code pointers + API + limitations)
- .claude/skills/permission-matrix/SKILL.md: placeholder → full spec (BE policy + FE guard + seed + pitfalls)
- docs/HANDOFF.md MOI: brief 5 phut cho session sau (run quickstart + where we are + next steps + file tree + gotchas ref)
- docs/STATUS.md: update cumulative stats + next up Phase 3
- docs/changelog/migration-todos.md: tick Phase 2 iteration 1 items + add iteration 2 list
- docs/changelog/sessions/2026-04-21-1200-phase2-form-engine.md: session log
- CLAUDE.md root: them reference den gotchas + HANDOFF

E2E verified:
- GET /api/forms/templates (onlyActive=false) → 8 templates
- POST /api/forms/templates/{FO-002.05}/render voi data dict → HTTP 200 + file .docx 482KB (Microsoft Word 2007+ OK)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 12:01:11 +07:00
54d6c9ba52 [CLAUDE] Phase1.2: CRUD Master + Permission Matrix + FE admin pages
Backend:
- Domain/Master: Supplier (+ SupplierType 5 loai), Project, Department (AuditableEntity)
- Domain/Identity: MenuItem, Permission, MenuKeys const (12 menu)
- EF Configurations voi unique Code + query filter IsDeleted
- DbSets + IApplicationDbContext interface update
- Application: PagedResult + PagedRequest generic
- Application/Master CQRS CRUD 3 entity (Create/Update/Delete/Get/List voi paging search sort)
- Application/Permissions: GetMyMenuTree (union OR role, filter tree), ListMenuItems, ListPermissionsByRole, UpsertPermission (guard admin khong tu giam quyen), ListRoles
- Api/Authorization: MenuPermissionRequirement + Handler (Admin bypass, query DB)
- Program.cs: register 48 policy {menu}.{action} tu MenuKeys x Actions
- Api/Controllers: Suppliers, Projects, Departments, Menus, Roles, Permissions
- DbInitializer: seed 12 menu + admin full CRUD permissions
- Migration AddMasterData + AddPermissions

Frontend (fe-admin):
- Types: menuKeys.ts const, menu.ts (MenuNode/Role/Permission), master.ts (Supplier/Project/Department + SupplierType const-object)
- AuthContext: load menu from /menus/me, cache localStorage, refreshMenu()
- usePermission hook + PermissionGuard component (wrap button)
- UI kit them: Dialog (modal overlay), Textarea, Select
- Generic: DataTable (column config, sortable, loading, empty) + Pagination
- PageHeader component
- apiError helper extract message tu ProblemDetails
- Layout rewrite: render menu dong tu AuthContext.menu (MenuGroup collapsible + NavLink + lucide icon map)
- Pages: master/Suppliers, master/Projects, master/Departments (CRUD + search + sort + paging + Dialog form)
- Page system/Permissions: ma tran Role x MenuKey x CRUD checkbox (tick tu dong PUT upsert)
- App.tsx them 4 route moi

Bug fix:
- MenuPermissionHandler: EF expression tree khong support switch expression -> tach switch ra ngoai AnyAsync
- TS erasableSyntaxOnly khong cho enum -> SupplierType const-object pattern (typeof[keyof])

E2E verified via Vite proxy:
- GET /menus/me -> 6 root + 6 child nodes (12 menus)
- GET /roles -> 12 roles
- POST/GET/PUT/DELETE /suppliers -> full CRUD, soft delete OK
- tsc -b fe-admin pass

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 11:30:14 +07:00
49a5f57a50 [CLAUDE] Docs: database-guide + 6 flow diagrams
docs/database/database-guide.md:
- Conventions (naming, data types, audit fields, soft delete)
- Schema hien tai (Identity tables sau migration Init) + seed 12 role + admin
- Schema planned: Phase 1 dot 2 (Supplier/Project/Department + Permission Matrix)
- Schema planned: Phase 3 (Contract + Approval + Comment + Attachment + Template + Clause + CodeSequence)
- Mermaid ERD cho tung phase
- Migration workflow (create/apply/revert)
- Index strategy + unique indexes
- Backup/restore SQL
- Common pitfalls + SQL cheatsheet

docs/flows/ — 6 flow documentation:
- README.md: index
- auth-flow.md: login/refresh/me/logout (IMPLEMENTED, sequence + edge cases + security checklist)
- permission-flow.md: Phase 1 dot 2 - Role x MenuKey x CRUD resolution + FE guard + BE policy
- contract-creation-flow.md: Phase 2 - Drafter flow chon template -> fill -> preview -> save draft
- contract-approval-flow.md: Phase 3 - state machine 9 phase chi tiet + reject flow + timeline UI
- form-render-flow.md: Phase 2 - OpenXml + ClosedXML + LibreOffice PDF convert
- sla-expiry-flow.md: Phase 3 - BackgroundService auto-approve qua SLA + warning notify

Update references:
- CLAUDE.md (root): them 2 row Tai lieu quan trong
- docs/CLAUDE.md: update project layout voi flows/ + database/
- docs/STATUS.md: log docs addition
- docs/changelog/migration-todos.md: tick Phase 0 docs items

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 11:15:28 +07:00
702411fcc8 [CLAUDE] Phase1: foundation - BE Clean Arch + Identity + JWT + 2 FE React + login E2E
Backend (.NET 10):
- Domain: BaseEntity/AuditableEntity, ContractType/Phase/ApprovalDecision enums, User/Role (Identity<Guid>), AppRoles (12 const)
- Application: IApplicationDbContext/ICurrentUser/IDateTime/IJwtTokenService, custom exceptions, ValidationBehavior (MediatR pipeline), Auth CQRS (Login/Refresh/Me), DependencyInjection
- Infrastructure: ApplicationDbContext (IdentityDbContext), AuditingInterceptor (auto audit + soft delete), DbInitializer (seed 12 role + admin), DesignTimeDbContextFactory, JwtTokenService, DateTimeService, DI
- Api: CurrentUserService, GlobalExceptionMiddleware (ProblemDetails), AuthController, Program.cs rewrite (Serilog + JWT + CORS + Swagger), appsettings + launchSettings (port 5443)
- Migration Init applied to SolutionErp_Dev LocalDB

Frontend (React 19 + Vite 8 + Tailwind 4):
- fe-admin (:8082 blue) + fe-user (:8080 emerald) - shared structure, khac menu + brand color
- Tailwind 4 via @tailwindcss/vite plugin, theme brand colors
- AuthContext (localStorage token), ProtectedRoute, Layout (sidebar + header)
- UI kit: Button/Input/Label (CVA + Tailwind)
- LoginPage voi toast error, DashboardPage/InboxPage placeholder
- Axios interceptor: auto Bearer + 401 redirect
- TanStack Query client, React Router 7, Sonner toast

Package downgrades (do .NET 10 / TS 6 compat):
- MediatR 14 -> 12.4.1 (v14 breaking changes)
- Swashbuckle 10 -> 6.9.0 (v10 khong tuong thich OpenApi 2)
- Removed Microsoft.AspNetCore.OpenApi (conflict voi Swashbuckle)

E2E verified: POST /api/auth/login qua Vite proxy ca 2 FE -> JWT + user info

Credentials seed: admin@solutionerp.local / Admin@123456

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 10:59:44 +07:00
25dad7f36f [CLAUDE] Scaffold: khoi tao SOLUTION_ERP Phase 0
- .NET 10 Clean Architecture: Domain/Application/Infrastructure/Api (4 project)
- 2 React + Vite + TS app: fe-admin (:8082), fe-user (:8080) voi proxy /api
- Node engines >=20, .nvmrc = 20 cho CI (bai hoc NamGroup)
- SQL Server 2022 qua docker-compose (dev)
- Parse 8 FORM -> docs/forms-spec.md (catalog + ma HD format RG-001)
- Parse QUY_TRINH -> docs/workflow-contract.md (9 phase state machine + role matrix)
- docs: CLAUDE.md, STATUS.md, PROJECT-MAP.md, migration-todos.md (roadmap 5 phase)
- .claude/skills: 3 placeholder (contract-workflow, form-engine, permission-matrix)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 10:37:34 +07:00