Files
solution-erp/docs/changelog/sessions/2026-07-17-S133-pe-budget-freeze-daduyet.md

47 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# S133 — PE freeze ngân sách phiếu DaDuyet (2026-07-17, closeout @S134 `/tiep`)
**Commit:** `d4fbced` (16 file, +7831/63) PUSHED `9e874ca..d4fbced` · **CI:** Run **#398** VERDICT **GO 5/5** · **Test:** 509→**520** (45D+475I, 0 fail) · **Mig:** 66→**67** · **Bundle:** admin `3NCdyODe`/css `B--dUHcm` · user `CKsoiNCI`/css `BuntB63r` · **Lead:** Fable 5 (owner-choice) · HMW-ON · run-folder `.claude/workflows/runs/2026-07-17-S133-pe-budget-freeze-daduyet/`
## Đề bài (UAT anh Kiệt FDC — chat 2026-07-16 17:2417:27)
Cập nhật ngân sách (`PeWorkItemBudgets` live, per Dự án × Hạng mục) làm **phiếu ĐÃ DUYỆT đổi số theo** (retro-display). Yêu cầu chốt:
- **R1** — phiếu DaDuyet **bất biến**, không đổi gì hết.
- **R2** — ngân sách đúng nhất cho phiếu mới = bản cập nhật **gần nhất** (live giữ nguyên semantics).
- **R3** — "tức lại database tí là oki": DB delta nhỏ, **không sinh bảng mới** (snapshot AddColumn).
## Giải pháp ship
- **Mig 67 `AddPeApprovedBudgetSnapshot`** — 11 AddColumn snapshot budget-summary lên PE (`ApprovedBudgetSnapshotAt` + `ApprovedBudgetPro{InitialAmount,AdjustmentAmount,Note}` + `ApprovedBudgetCcm{InitialAmount,AdjustmentAmount,Note}` + `ApprovedBudgetPrev{SubmittedTotal,SubmittedCount,SelectedTotal,SelectedCount}`), reversible Down DropColumn ×11, **no new table (89 giữ)**.
- **Chốt tại choke-point:** helper `PeBudgetAccumulator` 4-site (`PurchaseEvaluationFeatures/Service :862/:901/:934/:1109`) — mọi nhánh vào DaDuyet (CEO-final · level-finalize · CCM-threshold) đi qua cùng snapshot logic.
- **Backfill** `Sql()` OUTER APPLY khớp accumulator cho phiếu DaDuyet cũ — prod **18/18, chua=0** (không phiếu nào sót).
- **Display-gate `budgetFrozen`:** phiếu DaDuyet đọc snapshot + badge **🔒 "Ngân sách chốt tại thời điểm duyệt"** tại "Tổng hợp ngân sách trình ký" (FE 2-app SHA-mirror `5534addb`, `PeDetailTabs :1352`); phiếu chưa duyệt đọc live (R2).
- **+2 terminal-guard:** chặn sửa "NS kỳ này (CCM)" / "Điều chỉnh ngân sách" trên phiếu đã kết thúc — lỗi rõ nghĩa, **chặn cả Admin**.
## Pipeline (6 stage — engine-đắt H21 + hmw staged)
1. **`/fable-real invest`** `wf_348f6155-167` — ⚠️ #53 return-fail, **disk sub-file 22.5KB cứu trọn** (`sub-investigator-codebase-0.md`); lead verify 7/7 claim PASS.
2. **Spec + errata**`spec-pe-budget-freeze-daduyet-17-07-2026.md` (errata: query = `GetPurchaseEvaluationQuery` bundle prop `BudgetSummary`).
3. **hmw implement Opus MAX ×3 invocation staged:**
- **INV-A** (`wf_d9639faa-97a`, 0-garble): **T0 RED thật** (`Failed 1/1` — found 999tr @`PeBudgetFreezeTests.cs:184`, prod sạch) + FE 4 file badge amber, npm build ×2 PASS.
- **INV-B** (`wf_4bef08b8-730`, #53 ×2): lane xong 6 file + `PeBudgetAccumulator`**chết trước mig****em-main-solo Mig 67** (scaffold + backfill; apply 2 DB, Dev catch-up Mig 66 lag; build 0/0; filter 44/44 **T0 RED→GREEN**).
- **INV-C** (`wf_75c6bfd3-754`, #53 lần 3 → disk): +T1-T9 vào `PeBudgetFreezeTests` (9 vị trí `:426``:821`); full suite 519/0.
4. **Reviewer pre-commit** (`wf_f9c0b939-181`, return sạch): **PASS_WITH_FIXES 0M/2S/2N** — 2 SHOULD = **#81-EXT indirect-assignment**: admin-override `PurchaseEvaluationWorkflowService.cs:308` (`= targetPhase`) + seeder `DbInitializer:1323` (`= current`) gán Phase thẳng **bypass choke-point** → phiếu vào DaDuyet không snapshot. Lead FIX cả 2 + test `AdminOverride` site-5 + comment `[S133 site 5]` → filter **11/11**, FULL **520/0**, npm ×2 PASS.
5. **Commit + push** `d4fbced`.
6. **cicd-monitor** (`wf_4eadbcf6-c25`, return sạch — verdict về SAU `/pause`, lead harvest-liền): **VERDICT GO 5/5** — Run #398 success gate 520 · Mig 67 prod (history-top + 11 cột + backfill 18/18 chua=0 + 89 bảng) · bundle rotate ×2 (CSS cũng rotate — badge sinh utility-class mới, benign #69) · byte-verify #77 `budgetFrozen`=1 + VN-string 🔒=1, old-control 0 · smoke 4×200 + PE 401.
## Closeout @S134 `/tiep` (phiên kế — S133 `/pause` giữa chờ cicd)
- **Sàn-3:** flag ①orphan run-folder — chưa synthesis) + ④ (wal-commit chạm `runs/`) — cả 2 trỏ đúng mạch S133 đang dở, nhất quán WAL (không phải sổ-trống-giả-sạch).
- **Re-verify độc lập verdict GO 4/4 KHỚP** (mục 8 WAL dặn spot-check vì harvest-liền chưa re-verify): mig prod top = `20260717032812_AddPeApprovedBudgetSnapshot` (ssh sqlcmd) · health/live 200 · bundle-hash ×2 app khớp byte (curl index.html) · `dotnet test --filter PeBudgetFreeze` **11/11**.
- **Docs closeout:** STATUS (Mig 67 · 520 · Recently-Done S133 · bundle hoist S117→S133) + HANDOFF (segment S133, re-stamp 9 carry, UAT script) + gotchas **#81-EXT** (giữ count 83) + root CLAUDE.md (row PE + lịch sử mig) + session-log này + `close-synthesis.md` đóng orphan.
## ⚠️ #53 events (×3 + 1 overwrite-lesson) — 0 mất việc
- fable-real invest + INV-B ×2 + INV-C: đều **recover từ disk sub-file** (ghi-đĩa-trong-lúc-làm).
- **Lesson MỚI:** 2 invocation cùng role+index chung run → `sub-<role>-0.md` bị **OVERWRITE** (file INV-A bị INV-C đè). Multi-invocation chung run-folder phải đánh index/tên riêng per-invocation.
## Carry
- 🆕 **UAT freeze-NS** `[carry:uat-s133-budget-freeze]` — script 3 bước trong HANDOFF (badge 🔒 / phiếu mới số MỚI / guard sửa-NS lỗi rõ nghĩa).
- **hook-cap bắn ×2 phiên này** (inv-cb 19.7KB · reviewer 20.4KB — đều dưới cap anh 25.6K/30.7K ⇒ em không tự nén theo S122) `[carry:hook-vs-budget-cap]`.