[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>
This commit is contained in:
pqhuy1987
2026-04-28 12:36:31 +07:00
parent a05c57b081
commit e0b4e7f096
9 changed files with 575 additions and 110 deletions

View File

@ -1,6 +1,6 @@
--- ---
name: ef-core-migration name: ef-core-migration
description: Tạo/sửa/revert EF Core 10 migration cho SOLUTION_ERP. Dùng khi thêm entity mới, thay đổi schema, rollback migration, debug DesignTimeDbContextFactory fail. Đã có 13 migration sẵn (Init → AddPurchaseEvaluationCodeSequences). Snapshot + Designer + Migration 3-file rule bắt buộc commit đủ. description: Tạo/sửa/revert EF Core 10 migration cho SOLUTION_ERP. Dùng khi thêm entity mới, thay đổi schema, rollback migration, debug DesignTimeDbContextFactory fail. Đã có 14 migration sẵn (Init → AddBudgets). Snapshot + Designer + Migration 3-file rule bắt buộc commit đủ.
when-to-use: when-to-use:
- "thêm migration" - "thêm migration"
- "EF Core migration" - "EF Core migration"
@ -16,7 +16,7 @@ when-to-use:
> **Context:** .NET 10 + EF Core 10 + SQL Server. DbContext: `ApplicationDbContext` ở `Infrastructure/Persistence/`. Startup: `SolutionErp.Api`. > **Context:** .NET 10 + EF Core 10 + SQL Server. DbContext: `ApplicationDbContext` ở `Infrastructure/Persistence/`. Startup: `SolutionErp.Api`.
## Migration history (12 migration hiện có) ## Migration history (14 migration hiện có)
| # | Name | Tables added / changed | | # | Name | Tables added / changed |
|---|---|---| |---|---|---|
@ -33,13 +33,22 @@ when-to-use:
| 11 | `AddRoleShortNameAndUserDepartment` | +Role.ShortName + User.DepartmentId/Position (cột thêm, không bảng mới) | | 11 | `AddRoleShortNameAndUserDepartment` | +Role.ShortName + User.DepartmentId/Position (cột thêm, không bảng mới) |
| **12** | **`AddPurchaseEvaluations`** | **10 bảng module Duyệt NCC: PurchaseEvaluations + Suppliers + Details + Quotes + Approvals + Changelogs + Attachments + WorkflowDefinitions/Steps/StepApprovers** | | **12** | **`AddPurchaseEvaluations`** | **10 bảng module Duyệt NCC: PurchaseEvaluations + Suppliers + Details + Quotes + Approvals + Changelogs + Attachments + WorkflowDefinitions/Steps/StepApprovers** |
| **13** | **`AddPurchaseEvaluationCodeSequences`** | **1 bảng `PurchaseEvaluationCodeSequences` (Prefix PK, LastSeq) — atomic sequence cho MaPhieu format `PE/{YYYY}/{A\|B}/{Seq:D3}`** | | **13** | **`AddPurchaseEvaluationCodeSequences`** | **1 bảng `PurchaseEvaluationCodeSequences` (Prefix PK, LastSeq) — atomic sequence cho MaPhieu format `PE/{YYYY}/{A\|B}/{Seq:D3}`** |
| **14** | **`AddBudgets`** | **4 bảng module Ngân sách: Budgets + BudgetDetails + BudgetApprovals + BudgetChangelogs. + nullable FK index `Contracts.BudgetId` & `PurchaseEvaluations.BudgetId`** |
Total: **47 bảng** dbo + `__EFMigrationsHistory`. Xem `docs/database/schema-diagram.md` ERD đầy đủ. Total: **51 bảng** dbo + `__EFMigrationsHistory`. Xem `docs/database/schema-diagram.md` ERD đầy đủ.
**Phase 7 pending (session sau):** **Phase 7 pending:**
- `AddPePaymentTermFields` — tách `PurchaseEvaluations.PaymentTerms` JSON thành 6 column riêng - `AddPePaymentTermFields` — tách `PurchaseEvaluations.PaymentTerms` JSON thành 6 column riêng
- `AddPeDepartmentOpinions` — thêm 4 field Ý kiến phòng ban (Phê duyệt/CCM/MuaHàng/SM-PM) vào header hoặc table riêng - `AddPeDepartmentOpinions` — thêm 4 field Ý kiến phòng ban (Phê duyệt/CCM/MuaHàng/SM-PM) vào header hoặc table riêng
**Phase 8 pending (Budget refinement):**
- `AddBudgetCodeSequences` — atomic sequence khi format MaNganSach chốt (mirror Contract/PE pattern, hiện Random.Shared)
- `AddBudgetVersionedWorkflow` — nếu Solutions cần admin config UI (3 bảng `BudgetWorkflowDefinitions/Steps/StepApprovers` + `Budgets.WorkflowDefinitionId?`)
**Phase 7 update (2026-04-28):**
- Migration 14 `AddBudgets` — 4 bảng (Budgets/Details/Approvals/Changelogs) + 2 cột `BudgetId?` thêm vào Contracts & PurchaseEvaluations. Workflow hardcoded `BudgetPolicy.Default` (chưa versioned).
- 14 demo user thật `@solutions.com.vn` qua `SeedDemoUsersAsync` reconcile (PRO 5 + CCM 7 + ISO 1 + CEO 1).
**Phase 6 update (2026-04-24):** **Phase 6 update (2026-04-24):**
- Enum `PurchaseEvaluationAttachmentPurpose.ComparisonTable = 4` mới (file bảng so sánh tổng). - Enum `PurchaseEvaluationAttachmentPurpose.ComparisonTable = 4` mới (file bảng so sánh tổng).
Int column, không cần migration. Int column, không cần migration.

View File

@ -50,16 +50,17 @@ Kiến trúc: **.NET 10 Clean Architecture + 2 React FE (admin + user) + SQL Ser
- Audit fields: `CreatedAt`, `UpdatedAt`, `CreatedBy`, `UpdatedBy` (`BaseEntity`) - Audit fields: `CreatedAt`, `UpdatedAt`, `CreatedBy`, `UpdatedBy` (`BaseEntity`)
- Soft delete: `IsDeleted`, `DeletedAt`, `DeletedBy` (`AuditableEntity`) - Soft delete: `IsDeleted`, `DeletedAt`, `DeletedBy` (`AuditableEntity`)
- Migrations: `dotnet ef migrations add <Name> --project src/Backend/SolutionErp.Infrastructure --startup-project src/Backend/SolutionErp.Api` - Migrations: `dotnet ef migrations add <Name> --project src/Backend/SolutionErp.Infrastructure --startup-project src/Backend/SolutionErp.Api`
- **Hiện có 12 migration → 46 bảng** (Phase 6 thêm migration 12 `AddPurchaseEvaluations` — 10 bảng) - **Hiện có 14 migration → 51 bảng** (Phase 7 thêm migration 14 `AddBudgets` — 4 bảng + 2 cột `BudgetId?` nullable trên Contracts/PurchaseEvaluations)
### Modules ### Modules
| Module | Namespace | Migration | Trạng thái | | Module | Namespace | Migration | Trạng thái |
|---|---|---|---| |---|---|---|---|
| Contract (HĐ) | `Domain/Contracts/` | 1-11 | Feature-complete (7 ContractType × 9 phase) | | Contract (HĐ) | `Domain/Contracts/` | 1-11 | Feature-complete (7 ContractType × 9 phase) |
| PurchaseEvaluation (Duyệt NCC tiền-HĐ) | `Domain/PurchaseEvaluations/` | 12 | **Skeletoncòn chỉnh nhiều (Phase 7 WIP)** | | PurchaseEvaluation (Duyệt NCC tiền-HĐ) | `Domain/PurchaseEvaluations/` | 12, 13 | UX polish completefeature gap: Designer UI / Ý kiến 4 PB / Export PDF |
| **Budget (Ngân sách dự án)** | `Domain/Budgets/` | **14** | **BE done — FE pages chưa làm (Priority 0 session 5)** |
| Master (Supplier/Project/Department) | `Domain/Master/` | 2, 10 | Feature-complete | | Master (Supplier/Project/Department) | `Domain/Master/` | 2, 10 | Feature-complete |
| Identity (User/Role/Permission/MenuItem) | `Domain/Identity/` | 1, 3, 11 | Feature-complete | | Identity (User/Role/Permission/MenuItem) | `Domain/Identity/` | 1, 3, 11 | Feature-complete (30 demo user — 16 sample + 14 Solutions thật) |
| Forms (Template + Clause) | `Domain/Forms/` | 4 | Feature-complete | | Forms (Template + Clause) | `Domain/Forms/` | 4 | Feature-complete |
| Notifications | `Domain/Notifications/` | 6 | In-app + SignalR OK, email SMTP TODO | | Notifications | `Domain/Notifications/` | 6 | In-app + SignalR OK, email SMTP TODO |
@ -69,7 +70,7 @@ Kiến trúc: **.NET 10 Clean Architecture + 2 React FE (admin + user) + SQL Ser
[CLAUDE] <scope>: <imperative message> [CLAUDE] <scope>: <imperative message>
``` ```
**Scope:** `Contract` · `PurchaseEvaluation` · `Form` · `Workflow` · `Supplier` · `Auth` · `Admin` · `Api` · `App` · `Domain` · `Infra` · `FE-Admin` · `FE-User` · `Docs` · `CICD` · `Scripts` · `Skill` **Scope:** `Contract` · `PurchaseEvaluation` · `Budget` · `Form` · `Workflow` · `Supplier` · `Auth` · `Admin` · `Api` · `App` · `Domain` · `Infra` · `FE-Admin` · `FE-User` · `Docs` · `CICD` · `Scripts` · `Skill`
## 🛠️ Skills (.claude/skills/) — 6 skill PHẢI dùng khi task khớp ## 🛠️ Skills (.claude/skills/) — 6 skill PHẢI dùng khi task khớp
@ -97,7 +98,7 @@ Quy tắc: KHÔNG bulk-clone repo skill 3rd party. Chỉ thêm skill PROJECT-SPE
| [`docs/workflow-contract.md`](docs/workflow-contract.md) | State machine 9 phase HĐ + role matrix | | [`docs/workflow-contract.md`](docs/workflow-contract.md) | State machine 9 phase HĐ + role matrix |
| [`docs/forms-spec.md`](docs/forms-spec.md) | Catalog 8 form + quy định mã HĐ RG-001 | | [`docs/forms-spec.md`](docs/forms-spec.md) | Catalog 8 form + quy định mã HĐ RG-001 |
| [`docs/database/database-guide.md`](docs/database/database-guide.md) | DB conventions + migration workflow + cheatsheet | | [`docs/database/database-guide.md`](docs/database/database-guide.md) | DB conventions + migration workflow + cheatsheet |
| [`docs/database/schema-diagram.md`](docs/database/schema-diagram.md) | ⭐ ERD + luồng DB + data flow 46 table (+ §11 PE module) | | [`docs/database/schema-diagram.md`](docs/database/schema-diagram.md) | ⭐ ERD + luồng DB + data flow 51 table (+ §11 PE module + §12 Budget module) |
| [`docs/flows/README.md`](docs/flows/README.md) | Index 6 flow (auth, permission, contract, form, SLA) | | [`docs/flows/README.md`](docs/flows/README.md) | Index 6 flow (auth, permission, contract, form, SLA) |
| [`docs/gotchas.md`](docs/gotchas.md) | ⭐ 26 bẫy đã gặp — đọc trước khi debug tương tự | | [`docs/gotchas.md`](docs/gotchas.md) | ⭐ 26 bẫy đã gặp — đọc trước khi debug tương tự |
| [`.claude/skills/`](.claude/skills/README.md) | 6 skill: contract-workflow, form-engine, permission-matrix, dependency-audit-erp, ef-core-migration, iis-deploy-runbook | | [`.claude/skills/`](.claude/skills/README.md) | 6 skill: contract-workflow, form-engine, permission-matrix, dependency-audit-erp, ef-core-migration, iis-deploy-runbook |

View File

@ -10,6 +10,7 @@
3. Tự gen mã HĐ theo Quy định SOL-CCM-RG-001 3. Tự gen mã HĐ theo Quy định SOL-CCM-RG-001
4. Dashboard báo cáo HĐ theo NCC, dự án, trạng thái, giá trị 4. Dashboard báo cáo HĐ theo NCC, dự án, trạng thái, giá trị
5. **Module Duyệt NCC (Phase 6)** — phiếu trình duyệt so sánh giá tiền-HĐ, 2 quy trình A/B, kế thừa HĐ 1-click khi DaDuyet 5. **Module Duyệt NCC (Phase 6)** — phiếu trình duyệt so sánh giá tiền-HĐ, 2 quy trình A/B, kế thừa HĐ 1-click khi DaDuyet
6. **Module Ngân sách (Phase 7)** — 4 bảng quản lý ngân sách dự án, workflow simple 3-step, link nullable Contract & PE để đối chiếu chi phí
## 2. Kiến trúc tổng thể ## 2. Kiến trúc tổng thể
@ -59,13 +60,13 @@ SOLUTION_ERP/
│ ├── HANDOFF.md ⭐ brief 5 phút cho session tiếp │ ├── HANDOFF.md ⭐ brief 5 phút cho session tiếp
│ ├── PROJECT-MAP.md bản đồ tổng quan │ ├── PROJECT-MAP.md bản đồ tổng quan
│ ├── rules.md coding conventions │ ├── rules.md coding conventions
│ ├── architecture.md layered + PE module §9 │ ├── architecture.md layered + PE §9 + Budget §10
│ ├── gotchas.md 38 pitfall đã gặp │ ├── gotchas.md 38 pitfall đã gặp
│ ├── forms-spec.md 8 form catalog + RG-001 │ ├── forms-spec.md 8 form catalog + RG-001
│ ├── workflow-contract.md 9 phase HĐ + role matrix │ ├── workflow-contract.md 9 phase HĐ + role matrix
│ ├── database/ │ ├── database/
│ │ ├── database-guide.md conventions + migration workflow │ │ ├── database-guide.md conventions + migration workflow
│ │ └── schema-diagram.md ERD 47 bảng (+§11 PE) │ │ └── schema-diagram.md ERD 51 bảng (+§11 PE +§12 Budget)
│ ├── flows/ 6 sequence diagram (auth/permission/contract/form/sla + PE ref architecture) │ ├── flows/ 6 sequence diagram (auth/permission/contract/form/sla + PE ref architecture)
│ ├── guides/ setup, cicd, deploy, runbook, security │ ├── guides/ setup, cicd, deploy, runbook, security
│ ├── changelog/ │ ├── changelog/
@ -106,7 +107,7 @@ SOLUTION_ERP/
- **NamGroup** (`D:\Dropbox\CONG_VIEC\NAMGROUP\SOURCECODE_CÔNG_TY\NAMGROUP\`) — template 2 FE + IIS deploy + permission matrix - **NamGroup** (`D:\Dropbox\CONG_VIEC\NAMGROUP\SOURCECODE_CÔNG_TY\NAMGROUP\`) — template 2 FE + IIS deploy + permission matrix
- **DH_Y_DUOC** (`D:\Dropbox\CONG_VIEC\DAI_Y_DUOC\DH_Y_DUOC_SOURCECODE\DH_Y_DUOC\`) — template backend hiện đại (Clean Arch + CQRS + EF migrations) - **DH_Y_DUOC** (`D:\Dropbox\CONG_VIEC\DAI_Y_DUOC\DH_Y_DUOC_SOURCECODE\DH_Y_DUOC\`) — template backend hiện đại (Clean Arch + CQRS + EF migrations)
## 6. Roadmap (status 2026-04-24) ## 6. Roadmap (status 2026-04-28)
| Phase | Focus | Trạng thái | | Phase | Focus | Trạng thái |
|---|---|---| |---|---|---|
@ -118,8 +119,10 @@ SOLUTION_ERP/
| **5 Production** | CI/CD Gitea Actions + 3 IIS site + Let's Encrypt + Security headers + Users CRUD | ✅ Done | | **5 Production** | CI/CD Gitea Actions + 3 IIS site + Let's Encrypt + Security headers + Users CRUD | ✅ Done |
| **Tier 3** | Versioned WF + 3-panel layout + 4-bảng + 4 catalogs + 16 demo users + Brand identity | ✅ Done | | **Tier 3** | Versioned WF + 3-panel layout + 4-bảng + 4 catalogs + 16 demo users + Brand identity | ✅ Done |
| **6 Module Duyệt NCC** | PE iter 1 (skeleton) + iter 2 (UX polish) + Domain rebrand `.solutions.com.vn` | ✅ Done | | **6 Module Duyệt NCC** | PE iter 1 (skeleton) + iter 2 (UX polish) + Domain rebrand `.solutions.com.vn` | ✅ Done |
| **7 PE feature gap** | Designer UI + Ý kiến 4 phòng ban + Export PDF + UAT thật + SMTP | 📝 WIP | | **7 Budget BE + 14 Solutions users** | Migration 14 — 4 bảng Budget + workflow simple + 11 endpoint + 14 user thật | ✅ Done (Session 4) |
| **8+ Post-launch** | E-signature, Bravo/SAP, Mobile, AI OCR | 📝 Future | | **8 Budget FE + PE/HD integration** | FE Budget pages + link select Budget vào PE/Contract form | 📝 Active (Session 5) |
| **PE feature gap** | Designer UI + Ý kiến 4 phòng ban + Export PDF + UAT thật + SMTP | 📝 Carry over |
| **9+ Post-launch** | E-signature, Bravo/SAP, Mobile, AI OCR | 📝 Future |
Chi tiết atomic tasks: [`changelog/migration-todos.md`](changelog/migration-todos.md). Chi tiết atomic tasks: [`changelog/migration-todos.md`](changelog/migration-todos.md).
Session logs: [`changelog/sessions/`](changelog/sessions/). Session logs: [`changelog/sessions/`](changelog/sessions/).

View File

@ -1,42 +1,48 @@
# HANDOFF — Brief 5 phút cho session tiếp theo # HANDOFF — Brief 5 phút cho session tiếp theo
**Last updated:** 2026-04-24 chiều (Phase 6**PE polish iter 2 + domain rebrand hoàn tất, UAT-ready**) **Last updated:** 2026-04-28 (Phase 7**Module Ngân sách (Budget) BE + 14 demo users Solutions thật**)
## TL;DR ## TL;DR
**PE module UX polish gần complete.** Session 3 (24/04) apply 10 commit **Session 4 (28/04)** thêm 2 milestone lớn:
fix tất cả UX friction user báo:
- Rename menu "Phương Án" → "Giải pháp"
- Menu tree inheritance Pe_*/PeWf_* (fix bug children không hiện)
- Accordion mutex 2 PE group + sidebar w-72 nowrap label
- NavLink active check query string (fix 2 leaf cùng highlight)
- PE detail flat layout: Panel 2 = 4 section (Thông tin/NCC/Hạng mục/**Bảng so sánh**), Panel 3 thêm Duyệt + Lịch sử thay đổi
- Upload file đính kèm per-NCC (SupplierAttachmentsCell) + Bảng so sánh tổng
- readOnly mode cho menu "Duyệt" (pendingMe=1)
- HĐ: move Lịch sử điều chỉnh Panel 2 → Panel 3
- Demo email rebrand `@solutionerp.local → @solutions.com.vn` với backfill
**Domain migration (session 2):** 3 subdomain `.huypham.vn``.solutions.com.vn` ### A. Module Ngân sách (Budget) BE — migration 14, +4 bảng, +11 endpoint
live E2E — `api/admin/eoffice.solutions.com.vn`. Cert Let's Encrypt + CORS +
FE bundle VITE_API_BASE_URL đều đã apply.
**Tổng:** 47 DB tables, ~113 endpoints, 13 migrations, 33 gotchas, 20+ commit - 4 entity: `Budget` (Header) + `BudgetDetail` (flat row) + `BudgetApproval` (history) + `BudgetChangelog` (audit log).
session 3 push lên Gitea. - Enum `BudgetPhase` 5 state (DangSoanThao→ChoCCM→ChoCEO→DaDuyet + TuChoi).
- `BudgetPolicy.Default` hardcoded simple 3-step (Drafter→CCM→CEO) — chưa versioned (TODO khi user cần admin config UI).
-`NS-YYYYMM-XXXX` Random.Shared (chưa atomic — TODO khi format chính thức).
- Link nullable: `Contract.BudgetId?` + `PE.BudgetId?` đã có FK + index, FE chưa wire form.
- Menu seed `Budgets` root + 3 leaf (Bg_List/Bg_Create/Bg_Pending) order=27 icon Wallet.
- Application: 11 CQRS handler ~340 LOC (Create/UpdateDraft/Transition/List/GetDetail/Delete + Detail CRUD auto-recompute TongNganSach + ListChangelogs).
- Api: `BudgetsController` 11 endpoint REST.
- **FE chưa làm — Priority 0 session 5.**
## ⚠️ CẢNH BÁO session tiếp (Session 4) ### B. 14 demo user Solutions thật
1. **Chưa xóa binding cũ `.huypham.vn`** — vẫn active fallback. Sau 1-2 ngày - PRO 5 (TPB tra.bui + 4 NV) + CCM 7 (TPB ngocanh.huynh + 6 NV) + ISO 1 (chau.le) + CEO 1 (huy.duong).
- Pwd `User@123456`. Reconcile pattern (gotcha #38 4-field rename).
- Tổng 30 user (16 sample cũ giữ + 14 Solutions thật mới).
**Tổng:** 51 DB tables, ~124 endpoints, 14 migrations, 38 gotchas, 5+ commit
session 4 push lên Gitea.
## ⚠️ CẢNH BÁO session tiếp (Session 5)
1. **FE Budget pages CHƯA LÀM** — BE đã sẵn sàng nhưng chưa có page nào. Pattern: copy từ PE 3-panel List + Create + Detail tabs (Thông tin / Hạng mục) + WorkflowPanel timeline. Mirror sang fe-user. Thêm route `/budgets`, `/budgets/new`, `/budgets/:id`. Menu resolver `Bg_*` → URL.
2. **PE/Contract → Budget integration CHƯA WIRE** — BE đã có `BudgetId?` nullable FK trên cả 2 entity, FE form chưa thêm field "Ngân sách" select. Cần filter Budget theo `Phase=DaDuyet && NamNganSach=current && ProjectId match`. Tab Hạng mục có thể bonus cột "So với ngân sách".
3. **Chưa xóa binding cũ `.huypham.vn`** — vẫn active fallback. Sau 1-2 ngày
verify stable → `.\migrate-domains.ps1 -RemoveOld -SkipCert` trên VPS. verify stable → `.\migrate-domains.ps1 -RemoveOld -SkipCert` trên VPS.
2. **win-acme scheduled task "unhealthy"** — cert auto-renew có thể fail 4. **win-acme scheduled task "unhealthy"** — cert auto-renew có thể fail
khi gần 2026-06-18. Fix: mở `wacs.exe` interactive → Manage Renewals → khi gần 2026-06-18. Fix: mở `wacs.exe` interactive → Manage Renewals →
recreate task. recreate task.
3. **PE còn 3 task MISSING** cho feature-complete (xem STATUS §A): 5. **PE feature gap carry over** (xem STATUS §C):
- PE Workflow admin designer UI `/system/pe-workflows/:typeCode` - PE Workflow admin designer UI `/system/pe-workflows/:typeCode`
- Auto-map PE Details → Contract 7 per-type Details khi gen HĐ
- Section "Ý kiến 4 phòng ban" (Phê duyệt/CCM/MuaHàng/SM-PM) - Section "Ý kiến 4 phòng ban" (Phê duyệt/CCM/MuaHàng/SM-PM)
4. **Login email mới** `admin@solutions.com.vn` / `Admin@123456` — old - Export phiếu PDF/Excel
`@solutionerp.local` đã bị rename 401. 6. **Login email** `admin@solutionerp.local` / `Admin@123456` — domain default
5. **Chú ý G-084:** VPS shared với VietReport — mọi reverse proxy / backend chưa đổi sang `@solutions.com.vn` (chỉ demo user và rebrand cũ trong BackfillDemoEmail).
7. **Chú ý G-084:** VPS shared với VietReport — mọi reverse proxy / backend
service mới phải dùng `127.0.0.1` + bind loopback IPv4 explicit. service mới phải dùng `127.0.0.1` + bind loopback IPv4 explicit.
## ⭐ Skills (.claude/skills/) — PHẢI dùng khi task khớp ## ⭐ Skills (.claude/skills/) — PHẢI dùng khi task khớp
@ -76,7 +82,12 @@ session 3 push lên Gitea.
| **Master expand 15 NCC + 8 Project** + backfill demo HĐ diverse | ✅ Done | | **Master expand 15 NCC + 8 Project** + backfill demo HĐ diverse | ✅ Done |
| **Deps audit script** (`scripts/deps-audit.ps1`) | ✅ Done | | **Deps audit script** (`scripts/deps-audit.ps1`) | ✅ Done |
| **Module Duyệt NCC (tiền-HĐ) E2E** — 10 bảng + 2 workflow + Kế thừa HĐ | ✅ Done | | **Module Duyệt NCC (tiền-HĐ) E2E** — 10 bảng + 2 workflow + Kế thừa HĐ | ✅ Done |
| 6+ Post-launch (E-signature, Bravo/SAP, Mobile, AI) | 📝 Future | | **PE polish iter 2** — flat layout + per-NCC attachments + readOnly Duyệt + email rebrand | ✅ Done |
| **Domain rebrand huypham.vn → solutions.com.vn** — 3 subdomain + cert + CORS + FE bundle | ✅ Done |
| **Module Ngân sách BE** — 4 bảng + 11 endpoint + workflow simple + 30 user | ✅ Done (FE TODO) |
| **PE Workflow designer UI + Ý kiến 4 phòng ban + Export PDF** | 📝 Pending session 5+ |
| **FE Budget pages + PE/Contract → Budget integration** | 📝 Priority 0 session 5 |
| 8+ Post-launch (E-signature, Bravo/SAP, Mobile, AI) | 📝 Future |
## Run nhanh ## Run nhanh
@ -117,25 +128,41 @@ Login: `admin@solutionerp.local` / `Admin@123456`
## Cần làm kế tiếp ## Cần làm kế tiếp
### 🔥 Priority 0 — PE feature gap (session 4) ### 🔥 Priority 0 — Budget FE + PE/HD integration (session 5)
Xem **STATUS.md §🔥 In Progress** đầy đủ (nhóm A/B/C/D). 3 task MISSING cuối: Xem **STATUS.md §🔥 In Progress** đầy đủ (nhóm A/B/C/D/E). Tóm tắt:
1. **PE Workflow admin designer UI** `/system/pe-workflows/:typeCode` — mirror pattern `WorkflowsPage.tsx` + `WorkflowDesigner.tsx`. BE cần `PeWorkflowAdminFeatures.cs` (GetOverview + CreateNewVersion) + `PeWorkflowsController.cs`. Framework backend đã sẵn (3 bảng `PurchaseEvaluationWorkflow*` + `FromDefinition` builder), chỉ thiếu wire UI. **A. Budget FE pages — copy pattern PE:**
1. `fe-admin/src/types/budget.ts` (types + enums BudgetPhase + ApprovalDecision reuse)
2. `fe-admin/src/pages/budgets/BudgetsListPage.tsx` (3-panel `lg:grid-cols-[320px_1fr_360px]` — Panel 1 list + Panel 2 detail tabs + Panel 3 workflow timeline)
3. `fe-admin/src/pages/budgets/BudgetCreatePage.tsx` (form Header: tên/năm/dự án/phòng ban/người soạn)
4. `fe-admin/src/components/budgets/BudgetDetailTabs.tsx` (Thông tin / Hạng mục — flat row giống PE Details)
5. `fe-admin/src/components/budgets/BudgetWorkflowPanel.tsx` (Panel 3: timeline phase + ô comment + button Trình)
6. Mirror tất cả sang `fe-user/`
7. App.tsx routes `/budgets`, `/budgets/new`, `/budgets/:id` cả 2 app
8. Menu resolver `Bg_*` ở Layout: `Bg_List``/budgets`, `Bg_Pending``/budgets?phase=Pending`, `Bg_Create``/budgets/new`
**B. PE/Contract → Budget integration:**
1. **PE form** thêm field `Ngân sách` select Budget (filter `Phase=DaDuyet && NamNganSach=current && ProjectId=peProjectId`). Lưu `PE.BudgetId`.
2. **Contract form** tương tự — link sang Budget cho đối chiếu chi phí.
3. PE Detail tab có thể thêm cột "So với ngân sách" — compute từ `BudgetDetail` tương ứng (match GroupCode + ItemCode) nếu có Budget link.
**C. PE feature gap (carry over từ session 3):**
1. **PE Workflow admin designer UI** `/system/pe-workflows/:typeCode` — mirror pattern `WorkflowsPage.tsx` + `WorkflowDesigner.tsx`. BE cần `PeWorkflowAdminFeatures.cs` + `PeWorkflowsController.cs`. Framework backend đã sẵn (3 bảng `PurchaseEvaluationWorkflow*` + `FromDefinition`), chỉ thiếu wire UI.
2. **Ý kiến 4 phòng ban** (Phê duyệt / P.CCM / P.MuaHàng / SM-PM) — Excel form có, entity chưa map. Cần design: 4 text field + signoff date, hoặc dùng Approvals với role-kind. 2. **Ý kiến 4 phòng ban** (Phê duyệt / P.CCM / P.MuaHàng / SM-PM) — Excel form có, entity chưa map. Cần design: 4 text field + signoff date, hoặc dùng Approvals với role-kind.
3. **Export phiếu PDF/Excel** — tái dùng `IDocumentConverter` + template `PE-TrinhDuyet.docx`. 3. **Export phiếu PDF/Excel** — tái dùng `IDocumentConverter` + template `PE-TrinhDuyet.docx`.
4. **Payment terms tách field** từ JSON blob → 6 field riêng (optional UX polish).
5. **Auto-map PE Details → Contract Details** khi gen HĐ (optional nâng cấp).
**Đã xong trong session 3 (check STATUS Recently Done):** **D. Optional polish:**
- ~~PE Attachments upload~~ ✅ (per-NCC + Bảng so sánh tổng) - Budget MaNganSach atomic sequence (hiện Random.Shared, format chốt sau)
- ~~Menu tree inheritance Pe_*/PeWf_*~~ ✅ - Budget versioned workflow (admin config qua UI — hiện hardcoded `BudgetPolicy.Default`)
- ~~Accordion mutex + sidebar width + label nowrap~~ ✅ - Payment terms PE tách field
- ~~NavLink query active check~~ ✅ - Auto-map PE Details → Contract Details khi gen HĐ
- ~~PE detail flat layout + readOnly mode~~ ✅ - Matrix Quotes bulk paste từ Excel
- ~~HĐ move Lịch sử điều chỉnh → Panel 3~~ ✅
- ~~Menu rename Phương Án → Giải pháp~~ ✅ **Đã xong trong session 4 (check STATUS Recently Done):**
- ~~Demo email rebrand solutionerp.local → solutions.com.vn~~ ✅ - ~~Module Ngân sách BE — 4 bảng + 11 endpoint + workflow simple~~ ✅
- ~~14 demo user Solutions thật (PRO 5 + CCM 7 + ISO 1 + CEO 1)~~ ✅
- ~~Docs cleanup + tái cấu trúc MD~~ ✅
### A. Hard blockers (chờ user / ops) ### A. Hard blockers (chờ user / ops)
@ -195,7 +222,7 @@ Trigger: user nói "audit skill" hoặc tự chạy đầu Phase mới.
## Lưu ý kỹ thuật quan trọng ## Lưu ý kỹ thuật quan trọng
**Đọc [`gotchas.md`](gotchas.md) (26 bẫy) trước khi:** **Đọc [`gotchas.md`](gotchas.md) (38 bẫy) trước khi:**
- Thêm package mới → .NET 10 compat (MediatR 14 fail → dùng 12.4.1) - Thêm package mới → .NET 10 compat (MediatR 14 fail → dùng 12.4.1)
- Debug TS enum error → dùng const-object pattern (`erasableSyntaxOnly`) - Debug TS enum error → dùng const-object pattern (`erasableSyntaxOnly`)
@ -363,18 +390,23 @@ Remote: https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp.git
``` ```
admin@solutionerp.local / Admin@123456 ← Admin (QTV) admin@solutionerp.local / Admin@123456 ← Admin (QTV)
Demo users (User@123456): Demo users — 30 user (User@123456):
bod.huynh@solutionerp.local Tổng GĐ (BOD)
bod.le@solutionerp.local Phó GĐ NĐUQ ── 16 sample @solutionerp.local (giữ cho test legacy) ──
pm.nguyen@solutionerp.local GĐ Dự án FLOCK 01 (PM) bod.huynh, bod.le Tổng GĐ + Phó GĐ NĐUQ
ccm.tran@solutionerp.local TPB Kiểm soát chi phí (CCM + TPB) pm.nguyen GĐ Dự án FLOCK 01 (PM)
pro.pham@solutionerp.local TPB Cung ứng (PRO + TPB) ccm.tran, pro.pham, fin.do TPB CCM/PRO/FIN
fin.do@solutionerp.local TPB Tài chính (FIN + TPB) act.vu, equ.bui, hra.dang Kế toán trưởng / TPB EQU / TPB HRA
act.vu@solutionerp.local Kế toán trưởng (ACT + TPB)
equ.bui@solutionerp.local TPB Thiết bị (EQU + TPB)
hra.dang@solutionerp.local TPB HRA (HRA + TPB)
qs.hoang, qs.ngo QS công trường (NV.PB) qs.hoang, qs.ngo QS công trường (NV.PB)
nv.cao, nv.dinh NV Cung ứng/Tài chính (NV.PB) nv.cao, nv.dinh, nv.truong NV Cung ứng/Tài chính/CCM (NV.PB)
bod.tran, pm.le Bonus NĐUQ + PM thứ 2
── 14 Solutions thật @solutions.com.vn (session 4) ──
PRO 5: tra.bui (TPB) + phuong.nguyen, binh.lethanh, danh.huynh, dat.tran (NV)
CCM 7: ngocanh.huynh (TPB) + ha.dao, cuong.do, long.le, ha.nguyen,
dung.nguyen, anh.nguyen (NV)
ISO 1: chau.le
CEO 1: huy.duong
⚠ Rotate ALL passwords trước UAT thật ⚠ Rotate ALL passwords trước UAT thật
``` ```

View File

@ -2,9 +2,9 @@
> **Update rule:** trước khi bắt đầu 1 task → ghi row vào `🔥 In Progress`. Xong → chuyển sang `✅ Recently Done`. > **Update rule:** trước khi bắt đầu 1 task → ghi row vào `🔥 In Progress`. Xong → chuyển sang `✅ Recently Done`.
**Last updated:** 2026-04-24 chiều (Phase 6**PE polish iter 2: rename/attachments/readOnly/comparison-table + email rebrand**) **Last updated:** 2026-04-28 (Phase 7**Module Ngân sách (Budget) BE + 14 demo users Solutions**)
## 📍 Phase hiện tại: **Module Duyệt NCC — UX polish hoàn thiện, UAT-ready** — 47 DB tables, ~113 endpoints (+3 PE attachments), 13 migrations. Tất cả tính năng session 3 yêu cầu đã apply prod. PE module live đầy đủ: Domain rebrand + layout 4-section + upload file per-NCC + bảng so sánh tổng + readOnly menu Duyệt + accordion mutex + NavLink query match + Lịch sử điều chỉnh HĐ move sang Panel 3 + email @solutions.com.vn. ## 📍 Phase hiện tại: **Module Ngân sách BE deployed** — 51 DB tables (+4 Budget), 14 migrations (+14 `AddBudgets`), ~124 endpoints (+11 Budget). PE module ổn định, Budget BE live (CQRS + Controller + Migration + Menu seed), FE Budget pages chưa làm. 30 demo users (16 sample + 14 Solutions thật: 5 PRO + 7 CCM + 1 ISO + 1 CEO).
### 🌐 Production URLs ### 🌐 Production URLs
@ -14,33 +14,57 @@
- https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp — Gitea repo + Actions - https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp — Gitea repo + Actions
- Default admin: `admin@solutionerp.local` / `Admin@123456` ⚠️ **RE-ROTATE sau login đầu** - Default admin: `admin@solutionerp.local` / `Admin@123456` ⚠️ **RE-ROTATE sau login đầu**
## 🔥 In Progress — Còn lại cho session 4 ## 🔥 In Progress — Còn lại cho session 5
### A. PE feature gap (3 task chưa làm) ### A. Budget — FE pages (BE đã xong)
- [ ] **PE Workflow admin designer UI** `/system/pe-workflows/:typeCode` — framework BE đã sẵn (3 bảng + `FromDefinition` builder + menu leaves). Chỉ thiếu: - [ ] **FE Budget pages** — copy pattern PE:
- BE `PeWorkflowAdminFeatures.cs` + `PeWorkflowsController.cs` (mirror Contract version) - `fe-admin/src/types/budget.ts` (types + enums)
- FE `PeWorkflowsPage.tsx` + `PeWorkflowDesigner.tsx` (copy `WorkflowsPage.tsx` + `WorkflowDesigner.tsx`) - `fe-admin/src/pages/budgets/BudgetsListPage.tsx` (3-panel List + Detail tabs)
- [ ] **Section "Ý kiến 4 phòng ban"** (Phê duyệt/P.CCM/P.MuaHàng/SM-PM) ở tab Thông tin — Excel form có, entity chưa map. Design: 4 text field + signoff date, hoặc dùng Approvals với role-kind. - `fe-admin/src/pages/budgets/BudgetCreatePage.tsx` (form Header)
- [ ] **Export phiếu PDF/Excel** — tái dùng `IDocumentConverter` + template `PE-TrinhDuyet.docx`. - `fe-admin/src/components/budgets/BudgetDetailTabs.tsx` (Thông tin / Hạng mục)
- `fe-admin/src/components/budgets/BudgetWorkflowPanel.tsx` (Panel 3 timeline + transition)
- Mirror fe-user
- App.tsx routes `/budgets`, `/budgets/new`, `/budgets/:id`
- Menu resolver `Bg_*``/budgets[?phase=Pending]`
### B. Optional polish ### B. PE/Contract → Budget integration
- [ ] **Auto-map PE Details → Contract 7 per-type Details** khi gen HĐ — hiện copy header + GiaTri only. - [ ] **PE form** thêm field **"Ngân sách"** select Budget của Project (filter Phase=DaDuyet, NamNganSach=current).
- [ ] **Payment terms tách field** từ JSON blob → 6 field riêng (Tạm ứng/TT tạm/Quyết toán/Bảo hành/Hạn mức/Đánh giá) theo Excel section D. - [ ] **Contract form** tương tự — link sang Budget cho đối chiếu chi phí.
- [ ] **Matrix Quotes bulk paste** từ Excel column giá. - [ ] PE Detail tab thêm cột "So với ngân sách" (compute từ BudgetDetail tương ứng nếu có).
- [ ] **fe-user Inbox** thêm section "Phiếu Duyệt NCC chờ tôi" (hoặc `/pe-inbox` riêng).
- [ ] Edge case: reject E2E, xóa phiếu khi có Contract kế thừa, admin tạo WF v02 sau khi có phiếu pin v01.
### C. Deploy / Ops chưa xong ### C. PE feature gap (carry over từ session 3)
- [ ] **Remove binding cũ `.huypham.vn`** sau 1-2 ngày verify stable: `ssh vietreport-vps ; cd C:\solution-erp\scripts ; .\migrate-domains.ps1 -RemoveOld -SkipCert` - [ ] **PE Workflow admin designer UI** `/system/pe-workflows/:typeCode`
- [ ] **win-acme scheduled task "unhealthy"** — auto-renew có thể fail trước cert expire 2026-06-18. Fix: `wacs.exe` interactive → Manage Renewals → recreate task. - [ ] **Section "Ý kiến 4 phòng ban"** (Phê duyệt/CCM/MuaHàng/SM-PM)
- [ ] **Export phiếu PDF/Excel** — tái dùng `IDocumentConverter`
### D. Optional polish
- [ ] Budget MaNganSach atomic sequence (hiện `NS-YYYYMM-XXXX` Random.Shared, chốt format chính thức sau)
- [ ] Budget versioned workflow (admin config qua UI — hiện hardcoded `BudgetPolicy.Default`)
- [ ] Payment terms tách field (PE)
- [ ] Auto-map PE Details → Contract Details khi gen HĐ
- [ ] Matrix Quotes bulk paste từ Excel
- [ ] fe-user Inbox thêm section "Phiếu Duyệt NCC chờ tôi"
### E. Deploy / Ops chưa xong
- [ ] **Remove binding cũ `.huypham.vn`** sau verify: `ssh vietreport-vps ; cd C:\solution-erp\scripts ; .\migrate-domains.ps1 -RemoveOld -SkipCert`
- [ ] **win-acme scheduled task "unhealthy"** — auto-renew fix trước 2026-06-18.
- [ ] UAT thật 1 tuần với 2-3 user (16 demo + 14 Solutions = 30 user)
- [ ] SMTP config → Email outbox
- [ ] Rotate creds (admin + 30 demo + SA + vrapp + JWT)
- [ ] Schedule SQL backup Task Scheduler
## ✅ Recently Done (newest on top) ## ✅ Recently Done (newest on top)
| Ngày | Ai | Task | Commit | | Ngày | Ai | Task | Commit |
|---|---|---|---| |---|---|---|---|
| 2026-04-28 | Claude | **Module Ngân sách (Budget) BE — 4 bảng + workflow simple 3-step** — Migration 14 `AddBudgets`. Domain: `Budget` (Header — MaNganSach `NS-YYYYMM-XXXX`, NamNganSach, ProjectId/DepartmentId, DrafterUserId, TongNganSach auto-sum, SlaDeadline) + `BudgetDetail` (flat row pattern: GroupCode/Name + ItemCode + NoiDung + DonViTinh + KhoiLuong/DonGia/ThanhTien) + `BudgetApproval` (workflow history reuse `ApprovalDecision`) + `BudgetChangelog` (`BudgetEntityType` Header/Detail/Workflow). Enum `BudgetPhase` 5 state (DangSoanThao→ChoCCM→ChoCEO→DaDuyet + TuChoi). `BudgetPolicy.Default` hardcoded 3-step (Drafter→CCM→CEO). Application: 11 CQRS handler (~340 LOC: Create/UpdateDraft/Transition/List/GetDetail/Delete + Detail CRUD auto-recompute TongNganSach + ListChangelogs). Api: `BudgetsController` 11 endpoint. Link: Contract.BudgetId? + PE.BudgetId? nullable FK + index. Menu seed `Budgets` root + 3 leaf (Bg_List/Create/Pending) order=27 icon Wallet. **FE chưa làm** (next session). | `a05c57b` |
| 2026-04-28 | Claude | **14 demo users Solutions company thật** — PRO 5 (TPB tra.bui + 4 NV: phuong/binh/danh/dat) + CCM 7 (TPB ngocanh.huynh + 6 NV: ha.dao/cuong.do/long.le/ha.nguyen/dung.nguyen/anh.nguyen) + ISO 1 (chau.le) + CEO 1 (huy.duong). Pattern reconcile per-user try-catch (gotcha #38 4-field rename). Pwd `User@123456`. Tổng 30 user (16 sample cũ + 14 Solutions thật). Test login E2E pass. | `8097892` |
| 2026-04-28 | Claude | **Docs cleanup + chốt session 3** — Tái cấu trúc MD: archive raw dump (forms-spec-raw, workflow-raw) → `_archive/`, compact `migration-todos.md` collapse Phase 0-5+Tier3 cũ, update `CLAUDE.md` modules table + skills 6 (3 domain + 3 ops), `flows/` thêm PE ref architecture, audit `gotchas.md` (38 pitfall — thêm #34 NavLink query string + #35 menu inheritance + #36 Vite env rebuild + #37 mutex accordion family + #38 Identity 4-field rename). Session log `2026-04-23-2200-roles-demo-pending-cleanup.md` + `2026-04-24-chot-session-3-pe-polish.md`. | `309dcd9` · `e71e0eb` · `e65578a` |
| 2026-04-24 | Claude | **PE polish — Demo seed + MaPhieu atomic + Pe_* perm defaults** — Migration 13 `AddPurchaseEvaluationCodeSequences` (Prefix PK, mirror ContractCodeSequences). `IPurchaseEvaluationCodeGenerator` + impl SERIALIZABLE — format `PE/{YYYY}/{A\|B}/{Seq:D3}`. Replace Random.Shared trong CreatePEHandler. `SeedDemoPurchaseEvaluationsAsync` 4 phiếu varied (A-001 DangSoanThao, A-002 ChoCEODuyetNCC + 9 quotes, A-003 DaDuyet PaymentTerms JSON, B-001 ChoDuAn 5-step). `SeedPurchaseEvaluationPermissionDefaultsAsync` 7 role × 9 menu key — Drafter/DeptManager/Procurement Create+Update, các role duyệt R+U, DeptManager thêm Delete. | `c48ac21` | | 2026-04-24 | Claude | **PE polish — Demo seed + MaPhieu atomic + Pe_* perm defaults** — Migration 13 `AddPurchaseEvaluationCodeSequences` (Prefix PK, mirror ContractCodeSequences). `IPurchaseEvaluationCodeGenerator` + impl SERIALIZABLE — format `PE/{YYYY}/{A\|B}/{Seq:D3}`. Replace Random.Shared trong CreatePEHandler. `SeedDemoPurchaseEvaluationsAsync` 4 phiếu varied (A-001 DangSoanThao, A-002 ChoCEODuyetNCC + 9 quotes, A-003 DaDuyet PaymentTerms JSON, B-001 ChoDuAn 5-step). `SeedPurchaseEvaluationPermissionDefaultsAsync` 7 role × 9 menu key — Drafter/DeptManager/Procurement Create+Update, các role duyệt R+U, DeptManager thêm Delete. | `c48ac21` |
| 2026-04-24 | Claude | **Rebrand 3 domain huypham.vn → solutions.com.vn E2E** — 18 file repo (FE env + scripts + CI/CD + docs + skill + code comments). Viết `scripts/migrate-domains.ps1` (ASCII-only gotcha #30) chạy trên VPS: 3 HTTP binding mới + 3 cert Let's Encrypt (HTTP-01 via SelfHosting) + auto HTTPS 443 + redirect. CI/CD auto-deploy commit `66c1a5c+b93dacf`: appsettings.Production.json CORS mới + FE bundle `VITE_API_BASE_URL=api.solutions.com.vn`. E2E verified: `/api/purchase-evaluations` 401, CORS preflight OK, FE dist có domain mới. URL cũ fallback. Claude SSH tự chạy (không cần user RDP). | `66c1a5c` · `b93dacf` | | 2026-04-24 | Claude | **Rebrand 3 domain huypham.vn → solutions.com.vn E2E** — 18 file repo (FE env + scripts + CI/CD + docs + skill + code comments). Viết `scripts/migrate-domains.ps1` (ASCII-only gotcha #30) chạy trên VPS: 3 HTTP binding mới + 3 cert Let's Encrypt (HTTP-01 via SelfHosting) + auto HTTPS 443 + redirect. CI/CD auto-deploy commit `66c1a5c+b93dacf`: appsettings.Production.json CORS mới + FE bundle `VITE_API_BASE_URL=api.solutions.com.vn`. E2E verified: `/api/purchase-evaluations` 401, CORS preflight OK, FE dist có domain mới. URL cũ fallback. Claude SSH tự chạy (không cần user RDP). | `66c1a5c` · `b93dacf` |
| 2026-04-23 | Claude | **SeedDemoUsersAsync robust reconcile + 16 demo users** — Reconcile pattern (per-user try-catch, fix drift dept/position/role nếu user existing). 13 → 16 demo (+bod.tran NĐUQ thứ 2, +pm.le PM thứ 2, +nv.truong NV CCM). Detailed log created/fixed/failed counts. Resolves prod issue: chỉ thấy admin user vì old skip-if-exists fail silent. | `a667665` | | 2026-04-23 | Claude | **SeedDemoUsersAsync robust reconcile + 16 demo users** — Reconcile pattern (per-user try-catch, fix drift dept/position/role nếu user existing). 13 → 16 demo (+bod.tran NĐUQ thứ 2, +pm.le PM thứ 2, +nv.truong NV CCM). Detailed log created/fixed/failed counts. Resolves prod issue: chỉ thấy admin user vì old skip-if-exists fail silent. | `a667665` |
@ -93,7 +117,7 @@
| 2026-04-21 | Claude | **Phase 1 foundation** + Docs addition | `702411f` + `49a5f57` | | 2026-04-21 | Claude | **Phase 1 foundation** + Docs addition | `702411f` + `49a5f57` |
| 2026-04-21 | Claude | **Phase 0** | `25dad7f` | | 2026-04-21 | Claude | **Phase 0** | `25dad7f` |
Session logs: [P0](changelog/sessions/2026-04-21-1045-phase0-scaffold.md) · [P1f](changelog/sessions/2026-04-21-1100-phase1-foundation.md) · [P1.2](changelog/sessions/2026-04-21-1130-phase1-cruds-permission.md) · [P2](changelog/sessions/2026-04-21-1200-phase2-form-engine.md) · [P3](changelog/sessions/2026-04-21-1330-phase3-workflow.md) · [P4](changelog/sessions/2026-04-21-1430-phase4-report.md) · [P5prep](changelog/sessions/2026-04-21-1530-phase5-prep.md) · [Tier 3](changelog/sessions/2026-04-22-0300-tier3-feature-complete.md) · [Skill gov](changelog/sessions/2026-04-23-0900-skill-governance.md) · [Toolkit+4-bảng+Roles VN](changelog/sessions/2026-04-23-1500-toolkit-data-roles.md) · [**Roles+Demo+Pending**](changelog/sessions/2026-04-23-2200-roles-demo-pending-cleanup.md) Session logs: [P0](changelog/sessions/2026-04-21-1045-phase0-scaffold.md) · [P1f](changelog/sessions/2026-04-21-1100-phase1-foundation.md) · [P1.2](changelog/sessions/2026-04-21-1130-phase1-cruds-permission.md) · [P2](changelog/sessions/2026-04-21-1200-phase2-form-engine.md) · [P3](changelog/sessions/2026-04-21-1330-phase3-workflow.md) · [P4](changelog/sessions/2026-04-21-1430-phase4-report.md) · [P5prep](changelog/sessions/2026-04-21-1530-phase5-prep.md) · [Tier 3](changelog/sessions/2026-04-22-0300-tier3-feature-complete.md) · [Skill gov](changelog/sessions/2026-04-23-0900-skill-governance.md) · [Toolkit+4-bảng+Roles VN](changelog/sessions/2026-04-23-1500-toolkit-data-roles.md) · [Roles+Demo+Pending](changelog/sessions/2026-04-23-2200-roles-demo-pending-cleanup.md) · [PE polish iter 2 + rebrand](changelog/sessions/2026-04-24-chot-session-3-pe-polish.md) · [**Budget BE + 14 Solutions users**](changelog/sessions/2026-04-28-chot-session-4-budget.md)
**Docs entry points:** **Docs entry points:**
@ -101,7 +125,7 @@ Session logs: [P0](changelog/sessions/2026-04-21-1045-phase0-scaffold.md) · [P1
- [`workflow-contract.md`](workflow-contract.md) · [`forms-spec.md`](forms-spec.md) - [`workflow-contract.md`](workflow-contract.md) · [`forms-spec.md`](forms-spec.md)
- [`database/database-guide.md`](database/database-guide.md) · [`database/schema-diagram.md`](database/schema-diagram.md) - [`database/database-guide.md`](database/database-guide.md) · [`database/schema-diagram.md`](database/schema-diagram.md)
- [`flows/`](flows/) (7 file) · [`guides/`](guides/) (4 file) · [`gotchas.md`](gotchas.md) - [`flows/`](flows/) (7 file) · [`guides/`](guides/) (4 file) · [`gotchas.md`](gotchas.md)
- [`changelog/migration-todos.md`](changelog/migration-todos.md) · [`changelog/sessions/`](changelog/sessions/) (14 file) - [`changelog/migration-todos.md`](changelog/migration-todos.md) · [`changelog/sessions/`](changelog/sessions/) (16 file)
- [`.claude/skills/README.md`](../.claude/skills/README.md) — 6 skill (3 domain + 3 ops) · audit định kỳ 1/tháng (cron `solution-erp-skill-audit-monthly` next 2026-05-01) - [`.claude/skills/README.md`](../.claude/skills/README.md) — 6 skill (3 domain + 3 ops) · audit định kỳ 1/tháng (cron `solution-erp-skill-audit-monthly` next 2026-05-01)
## 🎯 Next up ## 🎯 Next up
@ -138,19 +162,19 @@ Session logs: [P0](changelog/sessions/2026-04-21-1045-phase0-scaffold.md) · [P1
## 📊 Thông số cumulative ## 📊 Thông số cumulative
| | P0 | P1f | P1.2 | P2 | P3 | P4 | P5prep | Tier3 | +Toolkit | +RolesPg+Demo | **+PE module** | | | P0 | P1f | P1.2 | P2 | P3 | P4 | P5prep | Tier3 | +Toolkit | +RolesPg+Demo | +PE module | +PE polish | **+Budget+30 users** |
|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:| |---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|
| BE LOC | 0 | ~400 | ~1500 | ~1900 | ~2700 | ~3100 | ~3300 | ~4800 | ~7800 | ~8800 | **~11100** | | BE LOC | 0 | ~400 | ~1500 | ~1900 | ~2700 | ~3100 | ~3300 | ~4800 | ~7800 | ~8800 | ~11100 | ~11400 | **~11750** (+340 Budget) |
| DB tables | 0 | 7 | 12 | 14 | 19 | 19 | 19 | 24 | 36 | 36 | **46** (+10 PE) | | DB tables | 0 | 7 | 12 | 14 | 19 | 19 | 19 | 24 | 36 | 36 | 46 | 47 (+CodeSeq) | **51** (+4 Budget) |
| API endpoints | 0 | 4 | 20 | 23 | 31 | 33 | 35 | ~50 | ~80 | ~93 | **~110** (+17 PE) | | API endpoints | 0 | 4 | 20 | 23 | 31 | 33 | 35 | ~50 | ~80 | ~93 | ~110 | ~113 | **~124** (+11 Budget) |
| Migrations | 0 | 1 | 3 | 4 | 5 | 5 | 5 | 8 | 11 | 11 | **12** | | Migrations | 0 | 1 | 3 | 4 | 5 | 5 | 5 | 8 | 11 | 11 | 12 | 13 | **14** (`AddBudgets`) |
| FE pages | 0 | 2 | 6 | 7 | 14 | 16 | 16 | ~20 | ~22 | ~23 | **~26** (+3 PE pages × 2 app) | | FE pages | 0 | 2 | 6 | 7 | 14 | 16 | 16 | ~20 | ~22 | ~23 | ~26 | ~26 | ~26 (Budget FE TODO) |
| FE components | — | — | — | — | — | — | — | many | many+ | +EditRowDialog (refactor ActionBtns) | | FE components | — | — | — | — | — | — | — | many | many+ | +EditRowDialog | +PE 5-tab | +Compare section | (Budget FE TODO) |
| Scripts PS | 0 | 0 | 0 | 1 | 1 | 1 | 3 | 4 | 4 | **5** (+deps-audit.ps1) | | Scripts PS | 0 | 0 | 0 | 1 | 1 | 1 | 3 | 4 | 4 | 5 | 5 | **6** (+migrate-domains.ps1) | 6 |
| CI/CD workflow | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | | CI/CD workflow | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| Docs | 10 | 13 | 14 | 24 | 26 | 30 | 35 | ~40 | ~42 | **~44** (+session log) | | Docs | 10 | 13 | 14 | 24 | 26 | 30 | 35 | ~40 | ~42 | ~44 | ~46 | ~48 | **~50** (+session log + chốt) |
| Demo data | 0 | 0 | seed empty | 0 | 0 | 0 | 0 | 0 | 5+3 | **15+8+7+13+4** (NCC/Project/HĐ/User/Catalogs) | | Demo data | 0 | 0 | empty | 0 | 0 | 0 | 0 | 0 | 5+3 | 15+8+7+13+4 | +PE 4 phiếu | +rebrand email | **30 user** (16 sample + 14 Solutions thật) |
| Commits | 1 | 2 | 3 | 5 | 6 | 7 | 8 | ~25 | ~47 | **~52** | | Commits | 1 | 2 | 3 | 5 | 6 | 7 | 8 | ~25 | ~47 | ~52 | ~63 | ~70 | **~75** |
## 🚨 Blockers / risks ## 🚨 Blockers / risks

View File

@ -267,7 +267,49 @@ PurchaseEvaluation (Header) ─< PurchaseEvaluationSupplier (N:M × Supplier)
Chi tiết: [`database/schema-diagram.md §11`](database/schema-diagram.md). Chi tiết: [`database/schema-diagram.md §11`](database/schema-diagram.md).
## 10. Liên quan ## 10. Budget (Phase 7 — Module Ngân sách)
Module quản ngân sách dự án: header + chi tiết hạng mục + workflow simple 3-step + audit log. Liên kết nullable cả Contract PurchaseEvaluation để đối chiếu chi phí.
```
Budget (Header) ─< BudgetDetail (flat row hạng mục)
─< BudgetApproval (workflow history)
─< BudgetChangelog (audit log)
─> Project (FK Restrict)
─> Department? (FK Restrict)
─> User Drafter (FK Restrict)
Contract.BudgetId? ──────────► Budget (link đối chiếu chi phí HĐ)
PurchaseEvaluation.BudgetId? ─► Budget (link đối chiếu chi phí tiền-HĐ)
```
**Phase enum** (`BudgetPhase` 5-state):
```
DangSoanThao(1) ──Trình──► ChoCCM(2) ──Duyệt──► ChoCEO(3) ──Duyệt──► DaDuyet(4)
▲ │ │
└──Reject(99)───────────┴─────────────────────┘
```
**Workflow simple hardcoded** (`BudgetPolicy.Default`):
- Drafter / DeptManager: DangSoanThao ChoCCM (Trình) hoặc TuChoi (Hủy)
- CostControl (CCM): ChoCCM ChoCEO (Duyệt) hoặc DangSoanThao (Trả về)
- Director / AuthorizedSigner: ChoCEO DaDuyet (Duyệt) hoặc DangSoanThao (Trả về)
**Mã ngân sách** `NS-{YYYYMM}-{Random:4d}` hiện Random.Shared, sẽ chuyển atomic SERIALIZABLE khi format chốt chính thức (mirror Contract/PE pattern).
**Auto-recompute** `TongNganSach`:
- Sau Add/Update/Delete BudgetDetail handler tự sum `Sum(d.ThanhTien)` lại Header.
- Tránh state drift, đơn giản hơn trigger DB.
**Integration roadmap**:
- PE form select Budget (filter `Phase=DaDuyet && NamNganSach=current && ProjectId match`)
- Contract form tương tự
- Tab Hạng mục PE/HD compute "So với ngân sách" (match GroupCode + ItemCode)
Chi tiết: [`database/schema-diagram.md §12`](database/schema-diagram.md).
## 11. Liên quan
- [`rules.md`](rules.md) coding conventions - [`rules.md`](rules.md) coding conventions
- [`database/database-guide.md`](database/database-guide.md) DB schema chi tiết - [`database/database-guide.md`](database/database-guide.md) DB schema chi tiết

View File

@ -1,7 +1,7 @@
# Migration To-dos — Atomic Roadmap # Migration To-dos — Atomic Roadmap
> Tick `[x]` khi xong. Phase 0-5 + Tier 3 đã DONE — collapsed. Detail xem session > Tick `[x]` khi xong. Phase 0-5 + Tier 3 + Phase 6 đã DONE — collapsed. Detail xem session
> logs trong `docs/changelog/sessions/`. Active work: Phase 6 (đã ✅) + Phase 7 (WIP). > logs trong `docs/changelog/sessions/`. Active work: Phase 7 partial (Budget BE done, FE WIP) + Phase 8 (Budget refinement).
## ✅ Phase 0-5 + Tier 3 — Done (2026-04-21..22) ## ✅ Phase 0-5 + Tier 3 — Done (2026-04-21..22)
@ -57,9 +57,9 @@ Session log: `2026-04-24-chot-session-3-pe-polish.md`.
Sub: `api.solutions.com.vn` · `admin.solutions.com.vn` · `eoffice.solutions.com.vn`. Old `.huypham.vn` vẫn fallback (chưa remove). Sub: `api.solutions.com.vn` · `admin.solutions.com.vn` · `eoffice.solutions.com.vn`. Old `.huypham.vn` vẫn fallback (chưa remove).
## 📝 Phase 7 — PE feature gap + ops (Session 4) ## 📝 Phase 7 — PE feature gap + Budget BE (Session 4 partial done)
### A. PE feature gap (3 task MISSING) ### A. PE feature gap (3 task MISSING — carry over session 5)
- [ ] **PE Workflow admin designer UI** `/system/pe-workflows/:typeCode` - [ ] **PE Workflow admin designer UI** `/system/pe-workflows/:typeCode`
- BE `Application/PurchaseEvaluations/PeWorkflowAdminFeatures.cs` (mirror `WorkflowAdminFeatures.cs`) - BE `Application/PurchaseEvaluations/PeWorkflowAdminFeatures.cs` (mirror `WorkflowAdminFeatures.cs`)
@ -83,15 +83,53 @@ Sub: `api.solutions.com.vn` · `admin.solutions.com.vn` · `eoffice.solutions.co
- [ ] Remove binding cũ `.huypham.vn` sau verify stable: `ssh vietreport-vps ; cd C:\solution-erp\scripts ; .\migrate-domains.ps1 -RemoveOld -SkipCert` - [ ] Remove binding cũ `.huypham.vn` sau verify stable: `ssh vietreport-vps ; cd C:\solution-erp\scripts ; .\migrate-domains.ps1 -RemoveOld -SkipCert`
- [ ] win-acme scheduled task fix unhealthy (cert expire 2026-06-18) - [ ] win-acme scheduled task fix unhealthy (cert expire 2026-06-18)
- [ ] UAT thật 1 tuần với 2-3 user - [ ] UAT thật 1 tuần với 2-3 user (30 demo user — 16 sample + 14 Solutions thật)
- [ ] SMTP config → Email outbox - [ ] SMTP config → Email outbox
- [ ] Rotate credentials (admin + 16 demo + SA + vrapp + JWT) - [ ] Rotate credentials (admin + 30 demo + SA + vrapp + JWT)
- [ ] Schedule SQL backup Task Scheduler - [ ] Schedule SQL backup Task Scheduler
### Pending migrations ### D. Module Ngân sách (Budget) — Session 4 ✅ partial done
- [x] **Migration 14** `AddBudgets` — 4 bảng (Budgets/BudgetDetails/BudgetApprovals/BudgetChangelogs) + index BudgetId nullable trên Contract & PurchaseEvaluation
- [x] Domain — `Budget` (Header) + `BudgetDetail` (flat row) + `BudgetApproval` + `BudgetChangelog` + enum `BudgetPhase` 5-state + `BudgetEntityType` Header/Detail/Workflow
- [x] `BudgetPolicy.Default` hardcoded simple 3-step (Drafter→CCM→CEO + Reject từ ChoCCM/ChoCEO về DangSoanThao)
- [x] Application CQRS ~340 LOC — Create + UpdateDraft + Transition + List + GetDetail + Delete (only DangSoanThao/TuChoi) + Detail CRUD (auto-recompute TongNganSach) + ListChangelogs
- [x] `BudgetsController` 11 endpoint REST
- [x] Menu seed `Budgets` root + 3 leaf (Bg_List/Bg_Create/Bg_Pending) order=27 icon Wallet
- [x] **14 demo user Solutions thật** — PRO 5 + CCM 7 + ISO 1 + CEO 1 (pwd `User@123456`)
Session log: `2026-04-28-chot-session-4-budget.md`.
### E. Pending migrations
- [ ] `AddPePaymentTermFields` (nếu chốt UX tách field) - [ ] `AddPePaymentTermFields` (nếu chốt UX tách field)
- [ ] `AddPeDepartmentOpinions` (nếu chọn Option A header columns) - [ ] `AddPeDepartmentOpinions` (nếu chọn Option A header columns)
- [ ] `AddBudgetCodeSequences` (nếu chốt format MaNganSach atomic — hiện Random.Shared)
- [ ] `AddBudgetVersionedWorkflow` (nếu user cần admin config UI thay vì hardcoded `BudgetPolicy.Default`)
## 📝 Phase 8 — Budget FE + integration (Session 5 active)
### A. FE Budget pages — copy pattern PE
- [ ] `fe-admin/src/types/budget.ts` (types + enum BudgetPhase + ApprovalDecision reuse)
- [ ] `fe-admin/src/pages/budgets/BudgetsListPage.tsx` (3-panel `[320px_1fr_360px]`)
- [ ] `fe-admin/src/pages/budgets/BudgetCreatePage.tsx` (form Header)
- [ ] `fe-admin/src/components/budgets/BudgetDetailTabs.tsx` (Thông tin / Hạng mục)
- [ ] `fe-admin/src/components/budgets/BudgetWorkflowPanel.tsx` (Panel 3 timeline + transition + comment)
- [ ] Mirror tất cả sang `fe-user/`
- [ ] App.tsx routes `/budgets`, `/budgets/new`, `/budgets/:id` cả 2 app
- [ ] Menu resolver `Bg_*` (Bg_List → `/budgets`, Bg_Pending → `/budgets?phase=Pending`, Bg_Create → `/budgets/new`)
### B. PE/Contract → Budget integration
- [ ] **PE form** thêm field `Ngân sách` select Budget (filter Phase=DaDuyet, NamNganSach=current, ProjectId match)
- [ ] **Contract form** tương tự — link sang Budget cho đối chiếu chi phí
- [ ] PE Detail tab thêm cột "So với ngân sách" — compute từ BudgetDetail tương ứng (match GroupCode + ItemCode)
### C. Budget refinement (when needed)
- [ ] Budget MaNganSach atomic sequence — chốt format chính thức rồi thêm `AddBudgetCodeSequences` migration + `IBudgetCodeGenerator` SERIALIZABLE pattern (mirror Contract/PE)
- [ ] Budget versioned workflow — admin config UI nếu Solutions cần custom step approver beyond default 3-step
## 🔁 Skill governance (recurring) ## 🔁 Skill governance (recurring)
@ -104,7 +142,7 @@ Quy tắc: `docs/rules.md §9`. Audit định kỳ mỗi đầu tháng — workf
Cron task `solution-erp-skill-audit-monthly` fire 9:00 AM ngày 1 mỗi tháng. Cron task `solution-erp-skill-audit-monthly` fire 9:00 AM ngày 1 mỗi tháng.
## 📦 Post-launch (Phase 8+ — future) ## 📦 Post-launch (Phase 9+ — future)
- [ ] **Email outbox** (MailKit + SMTP) — blocked chờ SMTP config - [ ] **Email outbox** (MailKit + SMTP) — blocked chờ SMTP config
- [ ] E-signature integration (VNPT CA hoặc FPT CA) - [ ] E-signature integration (VNPT CA hoặc FPT CA)

View File

@ -0,0 +1,260 @@
# 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/`)
- `BudgetPhase` enum 5-state — DangSoanThao(1) → ChoCCM(2) → ChoCEO(3) → DaDuyet(4) + TuChoi(99)
- `Budget` aggregate 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
- `BudgetDetail` flat 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
- `BudgetApproval` workflow history (FromPhase/ToPhase/Decision reuse `ApprovalDecision`)
- `BudgetChangelog` audit log với enum `BudgetEntityType` (Header/Detail/Workflow)
- `BudgetPolicy` record + `BudgetPolicy.Default` hardcoded 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` + index
- `PurchaseEvaluation.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:
1. `CreateBudgetCommand` + Validator + Handler — gen MaNganSach, set Phase=DangSoanThao, log Changelog
2. `UpdateBudgetDraftCommand` — chỉ DangSoanThao, log field changes JSON
3. `TransitionBudgetCommand` — guard `BudgetPolicy.Default.IsTransitionAllowed`, append BudgetApproval, log Changelog Transition
4. `ListBudgetsQuery` — Page/Search/Filter Phase/ProjectId/NamNganSach
5. `GetBudgetQuery` — return `BudgetDetailBundleDto` (Header + Details + Approvals + Workflow summary)
6. `DeleteBudgetCommand` — chỉ DangSoanThao/TuChoi (soft delete)
7. `AddBudgetDetailCommand` — auto recompute `Sum(ThanhTien)` lại Header
8. `UpdateBudgetDetailCommand` — auto recompute
9. `DeleteBudgetDetailCommand` — auto recompute
10. `ListBudgetChangelogsQuery` — 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 icon `Wallet`
- 3 leaf:
- `Bg_List` "Danh sách ngân sách" → `/budgets`
- `Bg_Create` "Tạo ngân sách" → `/budgets/new`
- `Bg_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
| Email | 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
| Email | 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
| Email | Họ tên | Vai trò |
|---|---|---|
| chau.le@solutions.com.vn | Lê Bảo Châu | NV.ISO |
### CEO 1 user
| Email | 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+flows
- `309dcd9` — 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 user
- `docs/changelog/migration-todos.md` — Phase 7 thêm section D Budget done, Phase 8 mới (FE Budget pages + integration), pending migrations Budget
- `docs/architecture.md` — §10 Budget module mới (sơ đồ ERD + state machine + auto-recompute + integration roadmap), renumber §11 Liên quan
- `docs/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 refinement
- `CLAUDE.md` (root + docs/) — modules table thêm Budget row, scope `Budget`, 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.ts`
- `fe-admin/src/pages/budgets/BudgetsListPage.tsx` (3-panel)
- `fe-admin/src/pages/budgets/BudgetCreatePage.tsx`
- `fe-admin/src/components/budgets/BudgetDetailTabs.tsx`
- `fe-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ách` select Budget (filter `Phase=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
1. **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.Default` static + Random.Shared MaNganSach OK cho UAT, refine sau khi format chính thức chốt.
2. **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.
3. **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.
4. **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=DaDuyet` khi pick. Tránh chicken-and-egg khi roll-out module mới.
## H. Cảnh báo session 5
1. **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.
2. **PE/Contract chưa thấy field Ngân sách** — BE đã có FK nhưng FE chưa wire. Priority 1.
3. **Login email**`admin@solutionerp.local` vẫn dùng (chỉ rebrand demo + sample user). Update khi UAT thật.
4. **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`.
5. **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)
```

View File

@ -481,8 +481,10 @@ COMMIT;
| **10** | **`AddMasterCatalogs`** | **UnitsOfMeasure, MaterialItems, ServiceItems, WorkItems** | | **10** | **`AddMasterCatalogs`** | **UnitsOfMeasure, MaterialItems, ServiceItems, WorkItems** |
| **11** | **`AddRoleShortNameAndUserDepartment`** | **+Role.ShortName + User.DepartmentId/Position (cột thêm, không bảng mới)** | | **11** | **`AddRoleShortNameAndUserDepartment`** | **+Role.ShortName + User.DepartmentId/Position (cột thêm, không bảng mới)** |
| **12** | **`AddPurchaseEvaluations`** | **10 bảng module Duyệt NCC: PurchaseEvaluations + Suppliers + Details + Quotes + Approvals + Changelogs + Attachments + WorkflowDefinitions + WorkflowSteps + WorkflowStepApprovers** | | **12** | **`AddPurchaseEvaluations`** | **10 bảng module Duyệt NCC: PurchaseEvaluations + Suppliers + Details + Quotes + Approvals + Changelogs + Attachments + WorkflowDefinitions + WorkflowSteps + WorkflowStepApprovers** |
| **13** | **`AddPurchaseEvaluationCodeSequences`** | **PurchaseEvaluationCodeSequences (Prefix PK, atomic seq mirror ContractCodeSequences). Format MaPhieu PE/{YYYY}/{A\|B}/{Seq:D3}** |
| **14** | **`AddBudgets`** | **4 bảng module Ngân sách: Budgets + BudgetDetails + BudgetApprovals + BudgetChangelogs. + nullable FK index Contract.BudgetId & PurchaseEvaluation.BudgetId** |
Tổng: **46 bảng** (+ `__EFMigrationsHistory` hệ thống). Tổng: **51 bảng** (+ `__EFMigrationsHistory` hệ thống).
## 8bis. Bảng mới sau Migration 9-11 ## 8bis. Bảng mới sau Migration 9-11
@ -625,7 +627,61 @@ PE.Phase=DaDuyet && SelectedSupplierId && !ContractId
→ navigate /contracts/{newId} → navigate /contracts/{newId}
``` ```
## 12. Liên quan ## 12. Budget module (Migration 14 — 4 bảng mới)
Module quản lý ngân sách dự án. Liên kết nullable Contract & PurchaseEvaluation cho đối chiếu chi phí. Workflow simple 3-step (chưa versioned, hardcoded `BudgetPolicy.Default`).
### Core (4 bảng):
| Bảng | Mục đích |
|---|---|
| `Budgets` | Header. **MaNganSach** `NS-{YYYYMM}-{Random:4d}` UK filtered, **TenNganSach** required, Description, **NamNganSach** int (year), **ProjectId** FK Restrict, **DepartmentId?** FK Restrict, **DrafterUserId** FK Restrict, **Phase** enum (5-state), **TongNganSach** decimal(18,2) auto-recompute từ Sum(BudgetDetails.ThanhTien), **SlaDeadline** DateTime?, **SlaWarningSent** bool. AuditableEntity (soft delete). |
| `BudgetDetails` | Flat row pattern (giống PE Details, KHÔNG nested). **BudgetId** FK Cascade, **GroupCode** (50 char) + **GroupName** (200) — phân nhóm hạng mục, **ItemCode** (100), **NoiDung** (500) required, **DonViTinh** (50), **KhoiLuong** decimal(18,4), **DonGia** decimal(18,2), **ThanhTien** decimal(18,2), **Order** int, **GhiChu** (1000). Index (BudgetId, Order). |
| `BudgetApprovals` | Workflow history. FromPhase/ToPhase/Decision (reuse `ApprovalDecision` enum), ApproverUserId, Comment, ApprovedAt. Index (BudgetId, ApprovedAt). |
| `BudgetChangelogs` | Audit log unified. **EntityType** enum `BudgetEntityType` (1=Header, 2=Detail, 3=Workflow), EntityId Guid?, **Action** enum `ChangelogAction` (Insert/Update/Delete/Transition), PhaseAtChange enum?, UserId Guid? + UserName denorm, Summary (500), FieldChangesJson nvarchar(max), ContextNote (2000). Indexes (BudgetId, CreatedAt) + (BudgetId, EntityType). |
### Link nullable từ Contract & PE:
```sql
ALTER TABLE Contracts ADD BudgetId UNIQUEIDENTIFIER NULL;
ALTER TABLE PurchaseEvaluations ADD BudgetId UNIQUEIDENTIFIER NULL;
CREATE INDEX IX_Contracts_BudgetId ON Contracts (BudgetId);
CREATE INDEX IX_PurchaseEvaluations_BudgetId ON PurchaseEvaluations (BudgetId);
```
Không có FK constraint cứng → Budget có thể bị soft-delete mà không ảnh hưởng HĐ/PE đã link. App layer guard validate khi chọn Budget (filter `Phase=DaDuyet && !IsDeleted`).
### State machine BudgetPhase (5-state):
```
DangSoanThao(1) ──Trình──► ChoCCM(2) ──Duyệt──► ChoCEO(3) ──Duyệt──► DaDuyet(4)
▲ │ │
└──Trả về───────────────┘ │
└──Trả về─────────────────────────────────────┘
└──Hủy──► TuChoi(99)
Role mapping (BudgetPolicy.Default):
- Drafter / DeptManager: DangSoanThao → ChoCCM (Trình) hoặc TuChoi (Hủy)
- CostControl (CCM): ChoCCM → ChoCEO (Duyệt) hoặc DangSoanThao (Trả về)
- Director / AuthSigner: ChoCEO → DaDuyet (Duyệt) hoặc DangSoanThao (Trả về)
```
### Auto-recompute TongNganSach:
```csharp
// AddBudgetDetailHandler / UpdateBudgetDetailHandler / DeleteBudgetDetailHandler
budget.TongNganSach = budget.Details.Where(d => !d.IsDeleted).Sum(d => d.ThanhTien);
db.Budgets.Update(budget);
```
Không trigger DB → app layer tính lại sau mỗi mutation Detail. Đơn giản, debug dễ.
### Pending refinement (Phase 8):
- **`AddBudgetCodeSequences`** — atomic SERIALIZABLE sequence khi format chốt chính thức (mirror Contract/PE pattern).
- **`AddBudgetVersionedWorkflow`** — nếu Solutions cần admin config UI thay vì hardcoded policy. Pattern: `BudgetWorkflowDefinitions` + `Steps` + `StepApprovers` + `Budget.WorkflowDefinitionId?` pinned at create.
## 13. Liên quan
- [`database-guide.md`](database-guide.md) — conventions + migration workflow + cheatsheet đầy đủ - [`database-guide.md`](database-guide.md) — conventions + migration workflow + cheatsheet đầy đủ
- [`../architecture.md`](../architecture.md) — layered architecture + data flow - [`../architecture.md`](../architecture.md) — layered architecture + data flow