Files
solution-erp/docs/changelog/sessions/2026-05-07-2300-pe-hd-manual-budget-mig17.md
pqhuy1987 bf177408b0
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m17s
[CLAUDE] Docs: chốt Session 11 — Migration 17 manual budget fields PE + HĐ
Chunk 5/5 — close session log + STATUS Recently Done + HANDOFF TL;DR Session 11
+ migration-todos tick + 6 cảnh báo Session 12+. KHÔNG update skill (per §9.5
— defer cron audit 2026-06-01 nhỏ enough). KHÔNG update schema-diagram count
55→55 (không bảng mới, chỉ +4 column).

Files:
  ~ docs/STATUS.md       — Last updated S11 + Phase summary 16→17 mig + Recently Done row
  ~ docs/HANDOFF.md      — TL;DR Session 11 prepend + 6 cảnh báo + giữ S10 narrative
  + docs/changelog/sessions/2026-05-07-2300-pe-hd-manual-budget-mig17.md
  ~ docs/changelog/migration-todos.md — Session 11 done block

Validation per §6.5: KHÔNG cắt narrative, chỉ thêm rows + sections mới.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 12:43:00 +07:00

7.4 KiB
Raw Blame History

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/Amountcontract 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)