diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index 4fb6780..baec5d9 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -1,6 +1,28 @@ # HANDOFF — Brief 5 phút cho session tiếp theo -**Last updated:** 2026-05-07 (Session 10 chốt — **PE "Thao tác" 2-panel workspace + Section 5 disabled. 2 commit per-chunk pushed. 83 test pass. Phase 9 còn lại = Hard blockers chờ user.**) +**Last updated:** 2026-05-07 (Session 11 chốt — **Migration 17 manual budget fields PE + HĐ + toggle "Nhập tay". 5 commit per-chunk. 83 test pass.**) + +## TL;DR Session 11 (07/05 — Migration 17 manual budget fields) + +**Output session 11** — UX improvement cho user nhập ngân sách không cần Budget entity approved: + +- ✅ **Migration 17** `AddManualBudgetFieldsToPeAndContract` — 4 ALTER (PE + HĐ × BudgetManualName nvarchar(200) + BudgetManualAmount decimal(18,2)). Applied LocalDB OK. Mirror logic PE ↔ HĐ (Q3 user chốt). +- ✅ **BE** Domain 2 entity (PE + Contract) +2 property + EF config HasMaxLength/HasPrecision. App CQRS Create/Update commands + DTO + Validator + diff log + carry-forward CreateContractFromEvaluation pe→contract. +- ✅ **FE** Toggle checkbox "Nhập tay (không link)" cạnh Label Ngân sách trong 4 chỗ: PeHeaderForm (workspace + /new page wrap), ContractCreatePage NewForm + EditForm. Khi ON: hide Select, show 2 input field grid 2-col (Tên + Số tiền formatted VND). Khi OFF (default): Select Budget approved cũ. Auto-detect manual mode khi load existing có manual data + !budgetId. Display fallback ở PeDetailTabs Section 1 "b. Ngân sách" + Contract EditForm read-only branch. +- ✅ **5 chunk per-commit** (build + 83 test pass mỗi chunk): C1 Domain+Infra Migration 17 (`ecd5f7e`) · C2 App CQRS (`0f7901c`) · C3 FE-Admin (`bab5031`) · C4 FE-User mirror (`14f8d9d`) · C5 Docs (current). + +**Validation Q2 chốt:** cả BudgetId + manual fields có thể cùng null (PE/HĐ chưa có ngân sách gì). KHÔNG XOR enforce — BE prefer link nếu có (Phase=DaDuyet guarantee), manual fallback only. + +**KHÔNG đụng:** Budget entity / Phase=DaDuyet validation (giữ invariant "PE/HĐ link Budget approved only"). Manual fields chỉ là note/display, KHÔNG join với Budget.Details cho per-row comparison ở PE matrix Section 4 (cột "So với ngân sách" vẫn require ev.budgetId — không có detail rows để compare). + +## ⚠️ CẢNH BÁO session tiếp (Session 12+) + +1. **UAT manual budget flow** — toggle ON/OFF + save + reload + verify auto-detect mode. Đặc biệt edit existing PE/HĐ có manual data → toggle phải auto-checked. Edit existing có Budget link → toggle auto-unchecked. +2. **Section 4 PE matrix "So với ngân sách"** vẫn require Budget link — manual amount KHÔNG render comparison column. Document giới hạn này nếu UAT thắc mắc. +3. **`docs/database/schema-diagram.md`** chưa cập nhật count 16→17 migration + 4 column mới. Defer cho audit định kỳ 2026-06-01 (per §6.4 cron) — nhỏ enough không phải selective rewrite. +4. **CreateContractFromEvaluation** đã carry forward manual fields PE→Contract. Verify khi UAT: PE có manual budget → tạo HĐ từ phiếu → HĐ inherit luôn. +5. **No new test added** (rule §7 — feature mới = test-after, soak UAT 2-3 tuần ổn → viết happy path). +6. **Schema fields nullable** — không phá HĐ/PE cũ (legacy null OK). Backward compatible. ## TL;DR Session 10 (07/05 — PE workspace 2-panel) diff --git a/docs/STATUS.md b/docs/STATUS.md index 5485506..fc5f4af 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -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`. -**Last updated:** 2026-05-07 (Session 10 chốt — **PE Thao tác 2-panel workspace + Section 5 disabled + 2 commit per-chunk pushed. 83 test pass.**) +**Last updated:** 2026-05-07 (Session 11 chốt — **Migration 17 manual budget fields PE + HĐ. 5 commit per-chunk. 83 test pass.**) -## 📍 Phase hiện tại: **Phase 9 active — UAT** — **55 DB tables, 16 migrations, ~133 API endpoints, 32 FE pages (+1 PE workspace 2-panel). 83 unit test pass** (54 Domain + 29 Infra: 17 codegen + 6 PE WF + 6 2-stage). 41 gotcha. 30 demo user. 6 skill. **7 file User Manual** (~86 KB compact end-user style). +## 📍 Phase hiện tại: **Phase 9 active — UAT** — **55 DB tables, 17 migrations, ~133 API endpoints, 32 FE pages. 83 unit test pass** (54 Domain + 29 Infra). 41 gotcha. 30 demo user. 6 skill. ### 🌐 Production URLs @@ -61,6 +61,7 @@ | Ngày | Ai | Task | Commit | |---|---|---|---| +| 2026-05-07 | Claude | **Migration 17 — manual budget fields fallback cho PE + HĐ (toggle "Nhập tay")** — User feedback: khi project chưa có Budget approved (Phase=DaDuyet eligible), user phải break flow đi tạo Budget + duyệt + quay lại link. UX kém. Solution: thêm fallback "Nhập tay" — checkbox toggle cạnh Label Ngân sách, khi ON → hide Select Budget, show 2 input field grid 2-col (Tên tham chiếu text + Số tiền number formatted VND). Lưu trên entity row, KHÔNG cần Budget entity. Q1-3 chốt: 1 = stick-toggle reveal 2 input fields; 2 = cả BudgetId + manual fields cùng null OK (KHÔNG XOR validate); 3 = mirror logic sang HĐ luôn (cả 7 ContractType qua ContractCreatePage). 5 chunk per-commit (build + 83 test pass mỗi chunk): C1 Migration 17 `AddManualBudgetFieldsToPeAndContract` 4 ALTER (PE + HĐ × Name nvarchar(200) + Amount decimal(18,2)) + Domain 2 entity + 2 EF config (HasMaxLength + HasPrecision) — applied LocalDB OK, 3-file rule. C2 App CQRS — CreatePurchaseEvaluationCommand + Update + DTO + Validator (>=0 when has value), CreateContractCommand + Update + DTO + diff log audit, CreateContractFromEvaluation carry forward pe.BudgetManualName/Amount → contract khi gen HĐ từ phiếu. C3 FE-Admin — types +2 field, PeHeaderForm toggle + 2 input + payload conditional (manual mode clear budgetId, link mode clear manual), PeDetailTabs Section "b. Ngân sách" fallback display "Tên · Số tiền + badge nhập tay" khi !budget + có manual data, refactor PurchaseEvaluationCreatePage wrap PeHeaderForm DRY (222→30 LOC), ContractCreatePage NewContractForm + EditContractForm cùng pattern + read-only display branch khi !isDraft. C4 fe-user mirror y hệt 6 file. C5 docs (this row + HANDOFF + session log). KHÔNG đụng Budget entity / Phase=DaDuyet validation (giữ invariant). | `ecd5f7e` (C1) · `0f7901c` (C2) · `bab5031` (C3) · `14f8d9d` (C4) · (current C5) | | 2026-05-07 | Claude | **PE "Thao tác" 2-panel workspace + Panel 1 read-only picker + Section 5 disabled** — User chỉ thị restructure leaf "Thao tác" (Pe_DuyetNcc_Create + Pe_DuyetNccPhuongAn_Create) từ page tạo header riêng (`/purchase-evaluations/new?type=N` — chỉ form Tên/Project/Địa điểm/Payment/Budget) sang workspace 2-panel mirror pattern HĐ Thầu phụ ContractCreatePage. 5 câu chốt spec trước code: Q1 Panel 2 KHÔNG render Workflow Panel + Approvals + History (chỉ data entry); Panel 1 = pure picker, KHÔNG inline edit/delete; Q2 mirror HĐ Thầu phụ pattern (sticky "+ Thêm mới" + Panel 2 transition new→edit form); Q3 leaf "Danh sách" + "Duyệt" giữ 3-panel hiện tại; Q4 route mới `/purchase-evaluations/workspace?type={1\|2}`; Q5 Section 5 Ý kiến 4PB disable trong workspace (vì người ta nhập khi duyệt, không phải lúc nhập liệu). 2 chunk per-commit (build + 83 test pass mỗi chunk): C1 fe-admin (3 file mới `PeListPanel.tsx` ~180 LOC pure picker reuse + `PeHeaderForm.tsx` ~210 LOC extract + `PurchaseEvaluationWorkspacePage.tsx` ~120 LOC, 3 file sửa `PeDetailTabs.tsx` thêm prop `mode?: 'detail' \| 'workspace'` + Section 5 hint banner amber + Layout.tsx resolver `Pe_*_Create`→`/workspace?type=N` + App.tsx route mới). C2 fe-user mirror y hệt 6 file (rule §3.9). KHÔNG đụng BE / migration / schema / endpoint. Route `/new` cũ giữ tồn tại cho deep-link "Sửa header" button. **Total +1142 LOC FE / 0 BE / 32 FE pages.** | `ee0d360` (C1) · `ecf3c59` (C2) · (current C3) | | 2026-05-04 | Claude | **User Manual 7 file rewrite compact cho end-user** — User feedback "ko cần quá đầy đủ chi tiết, cho end-user họ làm". Setup `package.json` + `npm install docx@9.5.0` + script `npm run gen:all`. Rewrite 7 generator scripts theo style end-user friendly: BỎ field validation table 5 cột (Tên field/Kiểu/Bắt buộc/Validation/Ví dụ), BỎ error troubleshoot table 3 cột (Lỗi/Nguyên nhân/Cách xử lý), BỎ FAQ chi tiết 8 câu (giữ 1 chương "Khi gặp lỗi" 4-5 bullet), BỎ phím tắt table. GIỮ: tổng quan ngắn 1-2 câu mỗi chức năng, numbered steps đơn giản 3-7 bước, note/warn/tip chỉ critical, bullet liệt kê. 7 file: 01-Bat-dau (12.1KB cũ 21.7KB ↓44%) / 02-Hop-dong / 03-Duyet-Workflow (mention 2-stage NV/TPB Mig 16) / 04-PE-Phieu-Duyet-NCC (A/B + 4PB + tạo HĐ) / 05-Budget / 06-7-Loai-HD-Cheatsheet / admin-02-Quan-ly-Users-Roles (mention bypass review S9). Refactor user-01 dùng `_helpers.js` shared (trước có helpers inline 793 dòng, giờ ~110 dòng). Tổng output ~86KB / 7 file (cũ ~123KB ↓30%). | `16c2c9c` | | 2026-05-04 | Claude | **Optional polish — fe-user Inbox thêm section "Phiếu Duyệt NCC chờ tôi"** — User chỉ thị "tiếp tục plan tổng" → pick task không blocked. useQuery thứ 2 cho `/purchase-evaluations/inbox` (endpoint có sẵn), peRows filter theo search. Stats overdue/dueSoon đếm cả PE rows (totalValue chỉ HĐ vì PE không có giá trị). Panel 1 chia 2 section sticky header: "Hợp đồng (N)" giữ behavior cũ click → inline detail Panel 2; "Phiếu Duyệt NCC (M)" click → navigate `/purchase-evaluations/:id` page riêng (PE entity shape khác Contract, không inline). EmptyState mới: "Không có HĐ hoặc Phiếu Duyệt NCC nào chờ". Chỉ fe-user (Drafter + TPB dùng Inbox) — fe-admin defer. Build pass. | `332a90f` | diff --git a/docs/changelog/migration-todos.md b/docs/changelog/migration-todos.md index 59648e2..5efe8f4 100644 --- a/docs/changelog/migration-todos.md +++ b/docs/changelog/migration-todos.md @@ -219,6 +219,18 @@ Session log: `2026-05-04-1230-chot-session-8-2-stage-dept-approval.md`. - [x] **Optional polish — fe-user Inbox PE section** (commit `332a90f`). HĐ + PE 2 section trong InboxPage. - [x] **User Manual 7 file rewrite compact** (commit `16c2c9c`). End-user style: bỏ field/error tables, giữ numbered steps đơn giản. ~86 KB total. +### ✅ Session 11 done (2026-05-07) — Migration 17 manual budget fields PE + HĐ + +User feedback: PE/HĐ link Budget Select chỉ Phase=DaDuyet → user phải break flow tạo Budget approved trước. Solution: toggle "Nhập tay" + 2 input field fallback (Tên text + Số tiền number) lưu trên entity, KHÔNG cần Budget entity. Mirror logic PE ↔ HĐ (Q3 chốt). + +- [x] **Chunk 1 Domain+Infra** (commit `ecd5f7e`) — Migration 17 `AddManualBudgetFieldsToPeAndContract` 4 ALTER + 2 entity property + 2 EF config (HasMaxLength + HasPrecision). Applied LocalDB. 3-file rule. +- [x] **Chunk 2 App CQRS** (commit `0f7901c`) — Create/Update PE + Contract commands + Validator (>=0 when has value) + Handlers + DTO + diff log audit + CreateContractFromEvaluation carry forward. +- [x] **Chunk 3 FE-Admin** (commit `bab5031`) — types +2 field, PeHeaderForm toggle + 2 input + payload conditional, PeDetailTabs Section "b. Ngân sách" fallback display + badge "nhập tay", refactor PurchaseEvaluationCreatePage wrap PeHeaderForm DRY (222→30 LOC), ContractCreatePage NewForm + EditForm cùng pattern + read-only branch khi !isDraft. +- [x] **Chunk 4 FE-User mirror** (commit `14f8d9d`) — 6 file y hệt content (rule §3.9). +- [x] **Chunk 5 Docs** (commit current) — STATUS row + HANDOFF TL;DR Session 11 + session log `2026-05-07-2300-pe-hd-manual-budget-mig17.md`. +- [x] **Verify**: dotnet build + 83 test pass mỗi chunk · npm build fe-admin + fe-user pass · LocalDB migration applied. +- [x] **KHÔNG đụng** Budget entity / Phase=DaDuyet validation (giữ invariant). Manual fields chỉ là fallback display/note, KHÔNG join với Budget.Details cho per-row comparison ở PE matrix Section 4. + ### ✅ Session 10 done (2026-05-07) — PE "Thao tác" 2-panel workspace User chỉ thị restructure menu PE: leaf "Thao tác" (Pe_*_Create) từ page Create header riêng `/new` sang workspace 2-panel mirror pattern HĐ Thầu phụ ContractCreatePage. Spec chốt 5 câu trước code (xem session log đầy đủ rationale). diff --git a/docs/changelog/sessions/2026-05-07-2300-pe-hd-manual-budget-mig17.md b/docs/changelog/sessions/2026-05-07-2300-pe-hd-manual-budget-mig17.md new file mode 100644 index 0000000..5d856c7 --- /dev/null +++ b/docs/changelog/sessions/2026-05-07-2300-pe-hd-manual-budget-mig17.md @@ -0,0 +1,116 @@ +# Session 2026-05-07 23:00 — Migration 17 manual budget fields PE + HĐ + +**Dev:** Claude +**Duration:** ~1.5h +**Base commit:** `d04bd88` (sau Session 10 PE workspace) + +## Bối cảnh + +User feedback: trong PE workspace + HĐ Create form, link Budget Select chỉ list ngân sách Phase=DaDuyet. Khi project chưa có Budget approved, user phải break flow đi tạo Budget → trình duyệt → quay lại link. UX đứt mạch. + +User chốt: thêm fallback "user tự nhập tiền vào, ko cần link ngân sách". Toggle reveal 2 input field (text Tên + number Số tiền). Mirror logic sang HĐ luôn (Q3). + +3 câu chốt spec: +- **Q1** Toggle cho hiện 2 input number/text field. Confirm "stick = toggle, xong cho input vào 2 field". +- **Q2** Cả 2 cùng null OK (BudgetId + manual fields). KHÔNG XOR validate — tạm thời cho phép cả 2 cùng có (BE prefer BudgetId nếu set vì Phase=DaDuyet guarantee, manual chỉ fallback). +- **Q3** Mirror sang HĐ Thầu phụ (cả 7 ContractType qua ContractCreatePage chung). + +## Làm được + +### Chunk 1 — Domain + Infra Migration 17 (commit `ecd5f7e`, +3674 LOC, 7 files) + +**Migration 17** `AddManualBudgetFieldsToPeAndContract` — 4 ALTER: +- `PurchaseEvaluations.BudgetManualName` nvarchar(200) NULL +- `PurchaseEvaluations.BudgetManualAmount` decimal(18,2) NULL +- `Contracts.BudgetManualName` nvarchar(200) NULL +- `Contracts.BudgetManualAmount` decimal(18,2) NULL + +3-file rule per `ef-core-migration` skill: `.cs` + `.Designer.cs` + ApplicationDbContextModelSnapshot.cs (auto-overwrite). + +**Files:** +- `Domain/PurchaseEvaluations/PurchaseEvaluation.cs` — 2 property mới (cmt rationale Mig 17 + Q2 validation note) +- `Domain/Contracts/Contract.cs` — 2 property mới +- `Infrastructure/Persistence/Configurations/PurchaseEvaluationConfiguration.cs` — HasMaxLength(200) + HasPrecision(18, 2) +- `Infrastructure/Persistence/Configurations/ContractConfiguration.cs` — same +- Migration 17 (3 file) + +**Verify:** `dotnet ef migrations add` clean output (4 AddColumn Up + 4 DropColumn Down). `dotnet ef database update` applied LocalDB. `dotnet test SolutionErp.slnx` 83 pass. + +### Chunk 2 — App CQRS (commit `0f7901c`, +36/-4 LOC, 5 files) + +- `CreatePurchaseEvaluationCommand` + Validator (MaximumLength(200) + GreaterThanOrEqualTo(0) when has value) + Handler wire entity +- `UpdatePurchaseEvaluationDraftCommand` + Handler wire entity +- `PurchaseEvaluationDetailBundleDto` +2 field +- `GetPurchaseEvaluationQuery` handler → DTO mapping pass entity values +- Mirror `CreateContractCommand` + `UpdateContractDraftCommand` + Validator + diff log audit thêm 2 field +- `ContractDetailDto` +2 field + GetContract handler mapping +- `CreateContractFromEvaluationFeatures.cs` — carry forward `pe.BudgetManualName/Amount` → `contract` khi gen HĐ từ phiếu (nếu PE đã có manual data, HĐ inherit luôn — không lose data khi gen HĐ). + +**Controllers KHÔNG đụng** — `[FromBody]` bind JSON body → record record optional fields gen auto null cho legacy callers. Backward compat. + +### Chunk 3 — FE-Admin (commit `bab5031`, +268/-260 LOC, 6 files) + +- `fe-admin/src/types/purchaseEvaluation.ts` PeDetailBundle +2 field +- `fe-admin/src/types/contracts.ts` ContractDetail +2 field +- `fe-admin/src/components/pe/PeHeaderForm.tsx` — toggle checkbox "Nhập tay (không link)" cạnh Label. ON: hide Select, show 2 input grid 2-col (Tên + Số tiền number formatted "≈ X đ" preview). OFF: Select Budget approved cũ. Payload conditional clear opposite mode. Auto-detect mode khi load existing. +- `fe-admin/src/components/pe/PeDetailTabs.tsx` — Section 2 "b. Ngân sách" fallback display khi !ev.budget + có manual data: render "Tên · Số tiền + badge nhập tay" thay vì "(chưa link)". +- `fe-admin/src/pages/pe/PurchaseEvaluationCreatePage.tsx` — refactor wrap PeHeaderForm DRY (222 LOC → 30 LOC). Auto-inherit toggle pattern, không drift. +- `fe-admin/src/pages/contracts/ContractCreatePage.tsx` — apply same toggle pattern cho NewContractForm + EditContractForm. EditForm thêm read-only display branch khi !isDraft + có manual data. + +### Chunk 4 — FE-User mirror (commit `14f8d9d`, +268/-260 LOC, 6 files) + +Y hệt Chunk 3 (rule §3.9). Copy 3 file mới + 3 file edit identical. + +### Chunk 5 — Docs (commit current) + +- STATUS.md Last updated + Phase summary count 16→17 migration + Recently Done row chi tiết. +- HANDOFF.md TL;DR Session 11 prepend + 6 cảnh báo Session 12+ + giữ Session 10 narrative. +- Session log (file này). +- KHÔNG update skill `ef-core-migration` table count — defer cron audit 2026-06-01 (small, không drift major). + +## E2E verified + +- `dotnet build` solution pass · `dotnet test SolutionErp.slnx` 83 pass · `dotnet ef database update` applied LocalDB. +- `npm run build` fe-admin pass — 1922 modules. +- `npm run build` fe-user pass — 1904 modules. +- Manual smoke: pending UAT user thử các flow sau: + - PE workspace tạo mới → toggle "Nhập tay" ON → nhập "Tạm tính T11/2025" + "1000000000" → save → Panel 2 detail tabs → Section 1 b. Ngân sách hiển thị "Tạm tính T11/2025 · 1.000.000.000 đ + badge nhập tay". + - Edit PE đã có Budget link → toggle off (auto-detected) → unlink → toggle on → nhập manual → save → reload → toggle vẫn ON. + - HĐ Thầu phụ /contracts/new → toggle "Nhập tay" trong NewContractForm → save → /contracts/:id → EditForm vẫn toggle ON, hiện 2 field giá trị cũ. + - HĐ DangSoanThao → DangGopY → reload → !isDraft branch hiển thị "Tên · Số tiền + badge nhập tay" read-only. + - PE DaDuyet → tạo HĐ từ phiếu → HĐ inherit manual fields (CreateContractFromEvaluation carry forward). + +## Bug gặp + fix + +| Bug | Fix | +|---|---| +| fe-user ContractCreatePage NewContractForm Edit thứ nhất (state declaration) lần đầu fail "File has not been read yet" do Edit chưa Read fe-user contracts.ts trước. Sau đó subsequent Edits đến mid-form fail TS2304 "Cannot find name 'budgetManual'" | Re-read file lần thứ 2 + Edit lại state declaration. Build pass sau khi state có đủ. | + +## Docs updates + +- STATUS.md (1 row Recently Done + count 17 migration) +- HANDOFF.md (TL;DR Session 11 prepend + cảnh báo) +- session log (file này) +- KHÔNG update skill (per §9.5 — không drift đáng audit, defer cho cron 2026-06-01) +- KHÔNG update gotchas (không phát sinh bẫy mới đáng cluster) +- Schema diagram count 55→55 (không bảng mới, chỉ 4 column mới) — defer audit định kỳ + +## Handoff + +Phase 9 active. Hard blockers user/ops vẫn pending. Manual budget feature mở ra "free pass" cho user tạo phiếu/HĐ nhanh không cần Budget workflow — ROI lớn cho UAT mà không phá invariant. + +Cron audit kế: 2026-06-01 (~25 ngày). + +## Thông số cumulative (sau Session 11) + +| | Trước S11 | Sau S11 | +|---|---:|---:| +| BE LOC | ~14400 | ~14450 (+50 — 2 entity property + 2 EF config + 4 command field + DTO field + carry forward) | +| API endpoints | ~133 | ~133 (no change) | +| Migrations | 16 | **17** (+1 `AddManualBudgetFieldsToPeAndContract`) | +| DB columns mới | 0 | +4 (PE + HĐ × Name + Amount) | +| FE pages | 32 | 32 (no change) | +| FE components | (existing) | (existing — refactor PeHeaderForm reuse + PurchaseEvaluationCreatePage wrap) | +| Tests | 83 | 83 (no change — feature mới = test-after rule §7) | +| Docs | ~53 | ~54 (+session log này) | +| Commits | (after S10) | +5 (C1 + C2 + C3 + C4 + C5) |