- 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>
13 KiB
Session log — 2026-04-28 (Phase 7 — Module Ngân sách BE + 14 Solutions users)
Topic: Module Ngân sách (Budget) BE chốt + 14 demo user Solutions thật + chốt MD session 4 → 5
Commits:
309dcd9·e71e0eb·e65578a— Docs cleanup từ session 3 (audit MD + tái cấu trúc + archive raw)8097892— Infra: 14 demo user Solutions company (PRO 5 + CCM 7 + ISO 1 + CEO 1)a05c57b— Domain+App+Api: Module Ngân sách (Budget) — 4 bảng + workflow simple 3-step- (Session log + chốt MD này — commit cuối session 4)
Migration: 14 AddBudgets — 4 bảng Budgets / BudgetDetails / BudgetApprovals / BudgetChangelogs + 2 cột nullable FK Contracts.BudgetId & PurchaseEvaluations.BudgetId.
A. Module Ngân sách BE
Domain (SolutionErp.Domain/Budgets/)
BudgetPhaseenum 5-state — DangSoanThao(1) → ChoCCM(2) → ChoCEO(3) → DaDuyet(4) + TuChoi(99)Budgetaggregate root (AuditableEntity):- MaNganSach
NS-{YYYYMM}-{Random:4d}(chưa atomic), TenNganSach required, Description - NamNganSach int (year), ProjectId FK Restrict, DepartmentId? FK Restrict, DrafterUserId FK Restrict
- Phase enum, TongNganSach decimal(18,2) auto-recompute, SlaDeadline?, SlaWarningSent
- Navigation: Details / Approvals / Changelogs collections
- MaNganSach
BudgetDetailflat row pattern — KHÔNG nested per-type:- GroupCode/GroupName (phân nhóm hạng mục), ItemCode, NoiDung, DonViTinh
- KhoiLuong dec(18,4), DonGia dec(18,2), ThanhTien dec(18,2), Order, GhiChu
BudgetApprovalworkflow history (FromPhase/ToPhase/Decision reuseApprovalDecision)BudgetChangelogaudit log với enumBudgetEntityType(Header/Detail/Workflow)BudgetPolicyrecord +BudgetPolicy.Defaulthardcoded simple 3-step:- Drafter/DeptManager: DangSoanThao → ChoCCM (Trình) hoặc TuChoi
- CostControl: ChoCCM → ChoCEO hoặc DangSoanThao (trả về)
- Director/AuthorizedSigner: ChoCEO → DaDuyet hoặc DangSoanThao
Modify Contract & PE
Contract.BudgetId? Guid+ indexPurchaseEvaluation.BudgetId? Guid+ index- Không có FK constraint cứng — app layer guard validate khi pick Budget
Application (SolutionErp.Application/Budgets/)
BudgetFeatures.cs ~340 LOC, 11 CQRS handler:
CreateBudgetCommand+ Validator + Handler — gen MaNganSach, set Phase=DangSoanThao, log ChangelogUpdateBudgetDraftCommand— chỉ DangSoanThao, log field changes JSONTransitionBudgetCommand— guardBudgetPolicy.Default.IsTransitionAllowed, append BudgetApproval, log Changelog TransitionListBudgetsQuery— Page/Search/Filter Phase/ProjectId/NamNganSachGetBudgetQuery— returnBudgetDetailBundleDto(Header + Details + Approvals + Workflow summary)DeleteBudgetCommand— chỉ DangSoanThao/TuChoi (soft delete)AddBudgetDetailCommand— auto recomputeSum(ThanhTien)lại HeaderUpdateBudgetDetailCommand— auto recomputeDeleteBudgetDetailCommand— auto recomputeListBudgetChangelogsQuery— order CreatedAt DESC
Api (SolutionErp.Api/Controllers/)
BudgetsController.cs 11 endpoint REST:
GET /api/budgets list paged
GET /api/budgets/{id} bundle
POST /api/budgets create
PUT /api/budgets/{id} update draft
POST /api/budgets/{id}/transitions phase transition
DELETE /api/budgets/{id} soft delete
POST /api/budgets/{id}/details add detail
PUT /api/budgets/{id}/details/{detailId} update detail
DELETE /api/budgets/{id}/details/{detailId} delete detail
GET /api/budgets/{id}/changelogs audit log
Menu seed (DbInitializer)
- Root
Budgets(MenuKeys.Budgets) order=27 iconWallet - 3 leaf:
Bg_List"Danh sách ngân sách" →/budgetsBg_Create"Tạo ngân sách" →/budgets/newBg_Pending"Ngân sách chờ duyệt" →/budgets?phase=Pending
- FE chưa wire route + menu resolver — Priority 0 session 5
B. 14 demo user Solutions company thật
SeedDemoUsersAsync thêm 14 user với reconcile pattern (per-user try-catch, gotcha #38 4-field Email/NormalizedEmail/UserName/NormalizedUserName).
PRO (Phòng Cung ứng) 5 user
| Họ tên | Vai trò | |
|---|---|---|
| tra.bui@solutions.com.vn | Bùi Lê Thủy Trà | TPB.PRO |
| phuong.nguyen@solutions.com.vn | Nguyễn Thị Bích Phượng | NV.PRO |
| binh.lethanh@solutions.com.vn | Lê Thanh Bình | NV.PRO |
| danh.huynh@solutions.com.vn | Huỳnh Tài Danh | NV.PRO |
| dat.tran@solutions.com.vn | Trần Văn Đạt | NV.PRO |
CCM (Phòng Kiểm soát chi phí) 7 user
| Họ tên | Vai trò | |
|---|---|---|
| ngocanh.huynh@solutions.com.vn | Huỳnh Thị Ngọc Ánh | TPB.CCM |
| ha.dao@solutions.com.vn | Đào Đức Hà | NV.CCM |
| cuong.do@solutions.com.vn | Đỗ Mạnh Cường | NV.CCM |
| long.le@solutions.com.vn | Lê Phụng Long | NV.CCM |
| ha.nguyen@solutions.com.vn | Nguyễn Thị Thu Hà | NV.CCM |
| dung.nguyen@solutions.com.vn | Nguyễn Phúc Dũng | NV.CCM |
| anh.nguyen@solutions.com.vn | Nguyễn Phước Tuấn Anh | NV.CCM |
ISO 1 user
| Họ tên | Vai trò | |
|---|---|---|
| chau.le@solutions.com.vn | Lê Bảo Châu | NV.ISO |
CEO 1 user
| Họ tên | Vai trò | |
|---|---|---|
| huy.duong@solutions.com.vn | Dương Quang Huy | BOD |
Pwd toàn bộ: User@123456. Tổng demo user = 30 (16 sample @solutionerp.local cũ + 14 Solutions thật @solutions.com.vn).
C. Docs cleanup từ session 3
3 commit dọn MD trước:
e65578a— chốt session 3 PE polish iter 2 + domain rebrand + 5 gotcha mới (#34-38)e71e0eb— tái cấu trúc cleanup: archive raw dump, compact migration-todos, update CLAUDE+flows309dcd9— chốt final session 3 audit MD + session log + minor fixes
D. Chốt MD session 4 → 5
Updated:
docs/STATUS.md— header + Recently Done 3 row mới (Budget BE / 14 users / Docs cleanup), cumulative table thêm cột "+Budget+30 users"docs/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 userdocs/changelog/migration-todos.md— Phase 7 thêm section D Budget done, Phase 8 mới (FE Budget pages + integration), pending migrations Budgetdocs/architecture.md— §10 Budget module mới (sơ đồ ERD + state machine + auto-recompute + integration roadmap), renumber §11 Liên quandocs/database/schema-diagram.md— Migration history rows 13+14, §12 Budget ERD chi tiết (4 bảng + state machine + auto-recompute + pending refinement), §13 Liên quan.claude/skills/ef-core-migration/SKILL.md— Migration 14 entry, total 51 bảng, Phase 8 pending Budget refinementCLAUDE.md(root + docs/) — modules table thêm Budget row, scopeBudget, count 51 bảng / 14 migration~/.claude/projects/.../memory/project_solution_erp.md— Phase 7 Budget BE + 14 user + tổng số mới + Session 5 priority
E. Session 5 carry-over
Priority 0 — FE Budget pages
Copy pattern PE:
fe-admin/src/types/budget.tsfe-admin/src/pages/budgets/BudgetsListPage.tsx(3-panel)fe-admin/src/pages/budgets/BudgetCreatePage.tsxfe-admin/src/components/budgets/BudgetDetailTabs.tsxfe-admin/src/components/budgets/BudgetWorkflowPanel.tsx- Mirror sang fe-user
- Routes
/budgets,/budgets/new,/budgets/:id - Menu resolver
Bg_*
Priority 1 — PE/Contract → Budget integration
- PE form thêm field
Ngân sáchselect Budget (filterPhase=DaDuyet && NamNganSach=current && ProjectId match) - Contract form tương tự
- PE Detail tab thêm cột "So với ngân sách" (compute từ BudgetDetail tương ứng)
Priority 2 — PE feature gap
- PE Workflow admin designer UI
/system/pe-workflows/:typeCode - Ý kiến 4 phòng ban (Phê duyệt/CCM/MuaHàng/SM-PM)
- Export phiếu PDF/Excel
Optional
- Budget MaNganSach atomic sequence (chốt format chính thức)
- Budget versioned workflow (admin config UI)
- Payment terms PE tách field
- Auto-map PE Details → Contract Details
- Matrix Quotes bulk paste
Ops
- Remove binding cũ
.huypham.vn - win-acme fix unhealthy
- UAT thật 1 tuần với 2-3 user (30 user demo)
- SMTP config Email outbox
- Rotate credentials
- Schedule SQL backup
F. Stats sau session 4
| Trước session 4 | Sau session 4 | |
|---|---|---|
| BE LOC | ~11400 | ~11750 (+340 Budget) |
| DB tables | 47 | 51 (+4 Budget) |
| API endpoints | ~113 | ~124 (+11 Budget) |
| Migrations | 13 | 14 (AddBudgets) |
| FE pages | ~26 | ~26 (Budget FE TODO) |
| Demo user | 16 | 30 (+14 Solutions thật) |
| Docs | ~48 | ~50 (+ session log + chốt MD) |
| Gotchas | 38 | 38 (no new) |
| Commits | ~70 | ~75 |
G. Lessons learned session 4
-
Workflow simple hardcoded chấp nhận được khi user yêu cầu "tạm thời chưa có" — không over-engineer versioned WF + atomic sequence ngay từ đầu. User confirm
BudgetPolicy.Defaultstatic + Random.Shared MaNganSach OK cho UAT, refine sau khi format chính thức chốt. -
Auto-recompute ở app layer thay vì DB trigger — đơn giản hơn, debug dễ. Mỗi handler Detail mutation gọi
budget.TongNganSach = budget.Details.Sum(d => d.ThanhTien). Trade-off: nếu N người sửa Detail concurrent thì cuối cùng còn đúng do tx wrap. -
Reconcile pattern per-user try-catch chính xác cho seed user — 1 user fail (gotcha #38 4-field rename) không kill toàn bộ seed. Drift dept/position/role tự fix nếu user đã tồn tại.
-
Link nullable thay vì required FK giữa Budget và Contract/PE — không bắt buộc tất cả HĐ phải có ngân sách → FE form optional + filter
Phase=DaDuyetkhi pick. Tránh chicken-and-egg khi roll-out module mới.
H. Cảnh báo session 5
- FE Budget chưa có gì — BE tested OK qua Swagger nhưng người dùng cuối chưa truy cập được. Đây là Priority 0.
- PE/Contract chưa thấy field Ngân sách — BE đã có FK nhưng FE chưa wire. Priority 1.
- Login email —
admin@solutionerp.localvẫn dùng (chỉ rebrand demo + sample user). Update khi UAT thật. - Atomic sequence Budget chưa chốt — Random.Shared race condition risk thấp nhưng không zero. Nếu Solutions cần serial number nghiêm túc → migration
AddBudgetCodeSequences+IBudgetCodeGenerator. - Versioned workflow Budget chưa có — nếu Solutions muốn admin config 5-step thay vì 3-step → migration
AddBudgetVersionedWorkflow(3 bảng + pin per Budget).
Files touched session 4
src/Backend/SolutionErp.Domain/Budgets/ (NEW — 5 file)
├── BudgetPhase.cs
├── Budget.cs
├── BudgetDetail.cs
├── BudgetApproval.cs
├── BudgetChangelog.cs
└── BudgetPolicy.cs
src/Backend/SolutionErp.Domain/Contracts/Contract.cs (mod: +BudgetId?)
src/Backend/SolutionErp.Domain/PurchaseEvaluations/PurchaseEvaluation.cs (mod: +BudgetId?)
src/Backend/SolutionErp.Domain/Identity/MenuKeys.cs (mod: +Budgets keys)
src/Backend/SolutionErp.Infrastructure/Persistence/Configurations/
├── BudgetConfiguration.cs (NEW — 4 entity config)
├── ContractConfiguration.cs (mod: +BudgetId index)
└── PurchaseEvaluationConfiguration.cs (mod: +BudgetId index)
src/Backend/SolutionErp.Infrastructure/Persistence/
├── ApplicationDbContext.cs (mod: +4 DbSet Budget*)
└── DbInitializer.cs (mod: +14 Solutions user + Budget menu seed)
src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/
└── 20260428043508_AddBudgets.cs (NEW — migration 14)
└── 20260428043508_AddBudgets.Designer.cs (NEW)
└── ApplicationDbContextModelSnapshot.cs (mod)
src/Backend/SolutionErp.Application/Common/Interfaces/IApplicationDbContext.cs (mod: +4 DbSet)
src/Backend/SolutionErp.Application/Budgets/ (NEW — 2 file)
├── BudgetFeatures.cs (~340 LOC, 11 CQRS handler)
└── Dtos/BudgetDtos.cs (6 DTO)
src/Backend/SolutionErp.Api/Controllers/BudgetsController.cs (NEW — 11 endpoint)
docs/STATUS.md (mod: header + Recently Done + cumulative)
docs/HANDOFF.md (mod: TL;DR + Priority 0 + creds)
docs/changelog/migration-todos.md (mod: Phase 7 partial + Phase 8 mới)
docs/architecture.md (mod: +§10 Budget)
docs/database/schema-diagram.md (mod: +migration 13+14, +§12 Budget)
docs/CLAUDE.md (mod: Phase 7 row + scope Budget)
CLAUDE.md (mod: modules table + scope)
.claude/skills/ef-core-migration/SKILL.md (mod: migration 14)
docs/changelog/sessions/2026-04-28-chot-session-4-budget.md (NEW — file này)
~/.claude/projects/.../memory/project_solution_erp.md (mod: Phase 7 + 14 user)