From a1c83867120b7eb2edc6df2497310b842d36f36a Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Fri, 15 May 2026 13:09:57 +0700 Subject: [PATCH] =?UTF-8?q?[CLAUDE]=20Docs:=20Chunk=20O7=20=E2=80=94=20S23?= =?UTF-8?q?=20t5=20Plan=20O=20HOTFIX=20wrap:=20docs=20+=20session=20log=20?= =?UTF-8?q?+=20memory=205=20sites=20enum?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plan O cumulative 2 commits: - O1-O5 atomic (ae01ca5) BE fix 4 lookup sites + 3 regression test 111/111 PASS - O7 (this) docs + memory + session log Docs update: - docs/STATUS.md Last updated S23 t5 + stats 111 test (+3) - docs/HANDOFF.md TL;DR S23 t5 với 5 sites enumerate - docs/changelog/sessions/2026-05-15-s23-turn5-plan-o-cascade-4-lookup-sites.md Memory user-level update (1 entry CRITICAL HOTFIX S23 t5 section): - feedback_per_nv_permission_scope.md — 5 lookup sites enum SOLUTION_ERP PE module documented + audit grep `FirstOrDefault.*Order ==` checklist + Reviewer pre-commit guideline. 4× cumulative gap analysis 3× refactor (Mig 29 + 30 + 31) wire SAME bug toàn 5 sites → 2 sessions hotfix (Plan N + Plan O) catch hết. Memory entry reinforced 2 lần Plan N + Plan O. Pattern reusable cross-project: refactor schema 1-row-per-role (OR-of-N) + bug fix lookup site → BẮT BUỘC grep enum tất cả lookup sites cùng pattern, KHÔNG fix theo bug report mỗi lần. Pending Chunk O8: CICD Monitor post-deploy verify Plan O. Pending Bug 2 F2 follow-up: verify workflow v14 DB structure (BOD Bước 3 setup đúng?). F2 logic line 483-524 Service đã đúng (lastStepIdx + lastLevelMaxOrder). Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/HANDOFF.md | 4 +- docs/STATUS.md | 3 +- ...s23-turn5-plan-o-cascade-4-lookup-sites.md | 192 ++++++++++++++++++ 3 files changed, 197 insertions(+), 2 deletions(-) create mode 100644 docs/changelog/sessions/2026-05-15-s23-turn5-plan-o-cascade-4-lookup-sites.md diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index c99fa76..7badd69 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -1,6 +1,8 @@ # HANDOFF — Brief 5 phút cho session tiếp theo -**Last updated:** 2026-05-15 (Session 23 turn 4 — **🎯 Plan N HOTFIX: BE per-NV lookup site discrimination — bug critical UAT block**. Bro UAT screenshot phát hiện admin Designer tick 7 flag TRUE cho NV Test (UAT V2) nhưng dialog Duyệt/Trả lại KHÔNG có F1+F2+F3+F4 options. Investigator audit verify Hypothesis B: `PurchaseEvaluationFeatures.cs:765` `FirstOrDefault(Order==X)` thiếu `ApproverUserId == currentUser.UserId` discriminator. Schema Mig 29 OR-of-N: 4 row cùng Order → handler luôn lấy row đầu DB (Lê Văn Bính, Drafter only), bỏ qua admin tick per-NV. Bug PRESENT 2 ngày prod từ Mig 29 deploy 2026-05-13 — chỉ bộc lộ khi lần đầu admin tick selectively. Fix 5 LOC: thêm match `ApproverUserId == currentUser.UserId` + fallback row đầu cho admin/non-approver. Test regression `GetPurchaseEvaluationCurrentLevelOptionsTests` 2 method: 4 actor distinct flag profile + admin fallback. **108/108 PASS** (+2 từ 106). Multi-agent ROI: Investigator catch root cause 1 spawn ~80K — em main solo fix nhanh. Pattern reinforced: per-NV admin opt-in flag wire checklist **9 surface points** (thêm point 9 handler lookup site discrimination). Stats: **31 mig** · 59 tables · ~145 endpoints · 34 FE pages · **108 test (+2)** · 47 gotcha · 20 memory (1 entry reinforced) · 6 skills.) +**Last updated:** 2026-05-15 (Session 23 turn 5 — **🎯 Plan O HOTFIX: 4 lookup sites cùng pattern per-NV cascade — Plan N chỉ catch 1/5 sites**. Bro UAT sau Plan N: Actor NV Test trong OR-of-N click "Trả lại Người chỉ định" → "Không phải lượt bạn" mặc dù đúng slot. Em main grep audit phát hiện 5 lookup sites cùng bug, Plan N chỉ catch 1. Plan O fix 4 sites còn lại: Service.cs:201 (EnsureCanRejectV2Async = bug bro), Service.cs:248 (ApplyReturnModeAsync read Allow flag), DetailFeatures.cs:72 (F3 guard), Features.cs:311 (F4 AdjustBudget guard). ApplyReturnModeAsync signature +`Guid? actorUserId` 4th param + caller TransitionAsync:94 update. 3 regression test mới `PurchaseEvaluationPerNvLookupRegressionTests`. **111/111 PASS** (+3 từ 108). Pattern reinforced 5 sites checklist + audit grep `FirstOrDefault.*Order ==`. Bug 2 (F2 chỉ đến Phan Văn Chương) defer follow-up — F2 logic đúng, verify workflow v14 DB. Stats: **31 mig** · 59 tables · ~145 endpoints · 34 FE pages · **111 test (+3)** · 47 gotcha · 20 memory · 6 skills.) + +**Last updated S23 t4:** 2026-05-15 (Session 23 turn 4 — **🎯 Plan N HOTFIX: BE per-NV lookup site discrimination — bug critical UAT block**. Bro UAT screenshot phát hiện admin Designer tick 7 flag TRUE cho NV Test (UAT V2) nhưng dialog Duyệt/Trả lại KHÔNG có F1+F2+F3+F4 options. Investigator audit verify Hypothesis B: `PurchaseEvaluationFeatures.cs:765` `FirstOrDefault(Order==X)` thiếu `ApproverUserId == currentUser.UserId` discriminator. Schema Mig 29 OR-of-N: 4 row cùng Order → handler luôn lấy row đầu DB (Lê Văn Bính, Drafter only), bỏ qua admin tick per-NV. Bug PRESENT 2 ngày prod từ Mig 29 deploy 2026-05-13 — chỉ bộc lộ khi lần đầu admin tick selectively. Fix 5 LOC: thêm match `ApproverUserId == currentUser.UserId` + fallback row đầu cho admin/non-approver. Test regression `GetPurchaseEvaluationCurrentLevelOptionsTests` 2 method: 4 actor distinct flag profile + admin fallback. **108/108 PASS** (+2 từ 106). Multi-agent ROI: Investigator catch root cause 1 spawn ~80K — em main solo fix nhanh. Pattern reinforced: per-NV admin opt-in flag wire checklist **9 surface points** (thêm point 9 handler lookup site discrimination). Stats: **31 mig** · 59 tables · ~145 endpoints · 34 FE pages · **108 test (+2)** · 47 gotcha · 20 memory (1 entry reinforced) · 6 skills.) **Last updated S23 t3:** 2026-05-15 (Session 23 turn 3 — **🎯 Plan M: Fix F1.OneLevel/OneStep edge case Bước 1 → giữ ChoDuyet + FE label phase rename**. 3 commits Plan M `c2042ef..4dd6f9c` local (chưa push, chờ Reviewer verdict). Bro UAT post-Plan L deploy: "Hiện logic cũ là khi trả lại 1 cấp hoặc chỉ định hoặc edit là trạng thái draft → thay đổi lại". Investigator audit confirm 4 mode F1.OneLevel/Assignee + F2 + F3 + F4 main path đã giữ ChoDuyet đúng (Mig 28-31 cumulative). Edge case F1.OneLevel ở Bước 1 Cấp 1 + F1.OneStep ở Bước 1 còn fallback Drafter (Phase=TraLai) — gap "draft" bro phát hiện. Plan M fix: reset (0, 1) giữ Phase=ChoDuyet + audit log "không lùi được" + SLA reset 7d (no-op effective). M3 FE label phase Phase=TraLai badge "Trả lại" → "Cần chỉnh sửa lại" (rõ end-user). M2 add 2 edge case tests **106/106 PASS** (+2 từ 104). F1.Drafter mode 4 GIỮ NGUYÊN Phase=TraLai semantic (explicit role mode). Multi-agent ROI evidence: Investigator catch fact code main path đã đúng (avoid em main spam fix sai) + Implementer Case 2+3 cookie-cutter 2 spawns + Reviewer pre-commit pending. Memory user-level update 2 entry. Stats: **31 mig** · 59 tables · **~145 endpoints** · 34 FE pages · **106 test (+2)** · 47 gotcha · 20 memory (2 entry reinforced) · 6 skills · 4 sub-agents. CHƯA push remote.) diff --git a/docs/STATUS.md b/docs/STATUS.md index 626fe1c..1f88784 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -2,7 +2,8 @@ > **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-15 (Session 23 turn 4 — **🎯 Plan N: HOTFIX per-NV lookup site discrimination — BE bug critical UAT block**. 2 commits N1+N2 batch atomic + N4 docs. Bro UAT screenshot post-Plan M deploy: Admin Designer tick TRUE 7 flag cho NV Test (UAT V2) slot Bước 2 Cấp 1 workflow QT-DN-V2-001 v12/v13 (4 NV cùng Cấp) — actor login → dialog ✓ Duyệt KHÔNG có checkbox F2 skipToFinal + dialog ← Trả lại CHỈ 1 radio Drafter + KHÔNG có F3+F4 Edit options. 🟦 Investigator audit (~80K spawn) verify Hypothesis B: BE bug `PurchaseEvaluationFeatures.cs:765` `FirstOrDefault(l => l.Order == curLevelOrder)` thiếu discriminator `ApproverUserId == currentUser.UserId` — schema Mig 29 (S21 t5) refactor: 1 row per ApproverUserId (OR-of-N cùng Order) → handler luôn lấy row đầu DB (Lê Văn Bính — Drafter only), bỏ qua admin tick per-NV của actor. Bug PRESENT từ Mig 29 deploy 2026-05-13 nhưng chỉ bộc lộ khi lần đầu admin tick selectively per-NV. 👤 Chủ trì Solo fix N1 (5 LOC BE) + N2 regression test (~200 LOC test) + N4 docs — KHÔNG spawn Implementer vì bug fix reasoning chain. Fix: `var curLevel = curStep?.Levels.FirstOrDefault(l => l.Order == curLevelOrder && l.ApproverUserId == currentUser.UserId) ?? curStep?.Levels.FirstOrDefault(l => l.Order == curLevelOrder);` — actor match per-NV slot, admin/non-approver fallback row đầu (giữ behavior view detail). Test regression `GetPurchaseEvaluationCurrentLevelOptionsTests` 2 method: 4 actor distinct flag profile + admin fallback. dotnet test **108/108 PASS** (+2 từ 106). Pattern reinforced: **Per-NV admin opt-in flag** wire checklist phải bao gồm **9 surface points** (KHÔNG 8) — thêm point 9 "Handler lookup site `currentLevelOptions` MUST discriminate ApproverUserId". Cumulative Mig 29 + 30 + 31 đã wire 8 points đúng nhưng MISS point 9 — bug present 2 days production. Stats final S23 t4: **31 mig** · 59 tables · ~145 endpoints · 34 FE pages · **108 test pass (+2)** · 47 gotcha · 20 memory (1 entry reinforced narrative wire checklist 9 points) · 6 skills · 4 sub-agents (1 Investigator spawn). CHƯA push remote — chờ Reviewer/CICD verify.) +**Last updated:** 2026-05-15 (Session 23 turn 5 — **🎯 Plan O: HOTFIX 4 lookup sites cùng pattern per-NV cascade — Plan N point 9 chỉ catch 1/5 sites**. 2 commits Plan O atomic + docs. Bro UAT 2026-05-15 sau Plan N deploy phát hiện tiếp: Actor NV Test (UAT V2) trong OR-of-N slot 4 NV click "Trả lại Người chỉ định" → toast "Không phải lượt bạn" mặc dù NV Test đúng trong slot. Em main audit grep `FirstOrDefault.*Order ==` toàn project — discovered 5 lookup sites total: Plan N catch 1 (GetPe handler), 4 sites khác CÙNG BUG còn nguyên: (1) `Service.cs:201` `EnsureCanRejectV2Async` actor match guard ← Bug bro UAT ROOT CAUSE, (2) `Service.cs:248` `ApplyReturnModeAsync` read Allow flag từ row đầu, (3) `DetailFeatures.cs:72` F3 `EnsureEditableForDetailsAsync` cùng bug, (4) `Features.cs:311` F4 `AdjustBudgetCommand` cùng bug. 👤 Chủ trì Solo fix 4 sites surgical ~30 LOC + add `Guid? actorUserId` param vào `ApplyReturnModeAsync` (4 param signature change) + caller `TransitionAsync:94` update + 3 regression test mới `PurchaseEvaluationPerNvLookupRegressionTests` (Actor non-first-row OR-of-N trả lại / Outsider không slot ForbiddenException / Actor có flag while others don't AllowsMode). dotnet test **111/111 PASS** (+3 từ 108 baseline Plan N). Pattern reinforced: **5 lookup sites checklist** sau Mig 29 OR-of-N — Plan N chỉ catch 1/5. Memory `feedback_per_nv_permission_scope.md` CRITICAL HOTFIX S23 t5 section updated với 5 sites enum + audit grep checklist. Bug 2 (F2 Duyệt thẳng chỉ đến Phan Văn Chương thay vì Nguyễn Văn Trường BOD) defer follow-up — F2 logic line 483-524 đã đúng, cần verify workflow v14 DB structure thực tế. Stats final S23 t5: **31 mig** · 59 tables · ~145 endpoints · 34 FE pages · **111 test pass (+3)** · 47 gotcha · 20 memory (1 entry CRITICAL HOTFIX section reinforced 2 lần) · 6 skills · 4 sub-agents (em main solo Plan O — bug fix reasoning chain cross 4 sites). CHƯA push remote — chờ CICD verify.) +**Last updated S23 t4:** 2026-05-15 (Session 23 turn 4 — **🎯 Plan N: HOTFIX per-NV lookup site discrimination — BE bug critical UAT block**. 2 commits N1+N2 batch atomic + N4 docs. Bro UAT screenshot post-Plan M deploy: Admin Designer tick TRUE 7 flag cho NV Test (UAT V2) slot Bước 2 Cấp 1 workflow QT-DN-V2-001 v12/v13 (4 NV cùng Cấp) — actor login → dialog ✓ Duyệt KHÔNG có checkbox F2 skipToFinal + dialog ← Trả lại CHỈ 1 radio Drafter + KHÔNG có F3+F4 Edit options. 🟦 Investigator audit (~80K spawn) verify Hypothesis B: BE bug `PurchaseEvaluationFeatures.cs:765` `FirstOrDefault(l => l.Order == curLevelOrder)` thiếu discriminator `ApproverUserId == currentUser.UserId` — schema Mig 29 (S21 t5) refactor: 1 row per ApproverUserId (OR-of-N cùng Order) → handler luôn lấy row đầu DB (Lê Văn Bính — Drafter only), bỏ qua admin tick per-NV của actor. Bug PRESENT từ Mig 29 deploy 2026-05-13 nhưng chỉ bộc lộ khi lần đầu admin tick selectively per-NV. 👤 Chủ trì Solo fix N1 (5 LOC BE) + N2 regression test (~200 LOC test) + N4 docs — KHÔNG spawn Implementer vì bug fix reasoning chain. Fix: `var curLevel = curStep?.Levels.FirstOrDefault(l => l.Order == curLevelOrder && l.ApproverUserId == currentUser.UserId) ?? curStep?.Levels.FirstOrDefault(l => l.Order == curLevelOrder);` — actor match per-NV slot, admin/non-approver fallback row đầu (giữ behavior view detail). Test regression `GetPurchaseEvaluationCurrentLevelOptionsTests` 2 method: 4 actor distinct flag profile + admin fallback. dotnet test **108/108 PASS** (+2 từ 106). Pattern reinforced: **Per-NV admin opt-in flag** wire checklist phải bao gồm **9 surface points** (KHÔNG 8) — thêm point 9 "Handler lookup site `currentLevelOptions` MUST discriminate ApproverUserId". Cumulative Mig 29 + 30 + 31 đã wire 8 points đúng nhưng MISS point 9 — bug present 2 days production. Stats final S23 t4: **31 mig** · 59 tables · ~145 endpoints · 34 FE pages · **108 test pass (+2)** · 47 gotcha · 20 memory (1 entry reinforced narrative wire checklist 9 points) · 6 skills · 4 sub-agents (1 Investigator spawn). CHƯA push remote — chờ Reviewer/CICD verify.) **Last updated S23 t3:** 2026-05-15 (Session 23 turn 3 — **🎯 Plan M: Fix F1.OneLevel/OneStep edge case Bước 1 → giữ ChoDuyet (KHÔNG fallback Drafter) + FE label phase TraLai rename**. 3 commits Plan M `c2042ef..4dd6f9c` chuỗi M1→M3→M2: M1 (`c2042ef`) BE Service `ApplyReturnModeAsync` 2 edge case block (line 287-333) → reset (0, 1) giữ Phase=ChoDuyet thay vì fallback Phase=TraLai (semantic mới per bro chốt AskUserQuestion: "Cho phép nhưng vẫn giữ ChoDuyet, clear pointer thôi") + M3 (`508b17a`) FE × 2 app rename `PurchaseEvaluationPhaseLabel[98]` + `PeDisplayStatusLabel.TraLai` + 2 inline literal trong PeWorkflowPanel F1 dialog "Trả lại" → "Cần chỉnh sửa lại" (phase status badge, KHÔNG đụng action verb "← Trả lại" + mode picker "Trả về Người soạn thảo") + M2 (`4dd6f9c`) Tests add 2 edge case test `OneLevel_AtStep1Level1_ResetsToBuoc1Cap1_KeepsChoDuyet` + `OneStep_AtStep1_ResetsToBuoc1Cap1_KeepsChoDuyet` + helper `SeedWorkflowAsync` extend 2 param optional. Multi-agent execution: 🟦 Investigator audit pre-flight catch fact code main path đã đúng (F1.OneLevel/Assignee + F2 + F3 + F4 main path giữ ChoDuyet) chỉ edge case Bước 1 fallback sai + 🟨 Implementer 2 spawns Case 2+3 (M2 + M3) + 🟥 Reviewer pre-commit pending + 👤 Chủ trì M1+M4. Test final: **106/106 PASS** (+2 từ 104, 58 Domain + 48 Infra) — K7 Approver F2 NO cascade. F1.Drafter mode 4 GIỮ NGUYÊN Phase=TraLai semantic (explicit role mode). Memory user-level update 2 entry: `feedback_per_nv_permission_scope.md` reinforcement S23 t3 "edge case không lùi được KHÔNG fallback role khác" + `feedback_uat_skip_verify.md` Plan L lesson "Service refactor semantic BẮT BUỘC update test cùng commit". Stats final S23 t3: **31 mig** (no change) · 59 tables · **~145 endpoints** (no change) · 34 FE pages · **106 test pass (+2)** · 47 gotcha · 20 memory (2 entry reinforced) · 6 skills · 4 sub-agents. CHƯA push remote — chờ Reviewer verdict.) **Last updated S23 t1:** 2026-05-14 (Session 23 turn 1 — **🎯 Plan K: F2 refactor sang per-Approver-slot Mig 31** + UI consistency. 8 commits Plan K `56868bf..`: Chunk pre-A slot label rename → K1 Mig 31 schema swap (drop `Users.AllowDrafterSkipToFinal` + add `ApprovalWorkflowLevels.AllowApproverSkipToFinal` no BACKFILL) → K2 Service ApproveV2Async Approver F2 branch + DTO refactor → K3 Designer 7th checkbox + banner rewrite → K5 zombie endpoint cleanup + Reviewer Major #1+#2 + Minor #3+#4 → K6 Workspace × 2 app DROP Drafter + ADD Approver toggle → K7 tests regression 104/104 PASS (3 deleted + 3 added cancel) → K8 docs. Multi-agent execution: 🟦 Investigator K0 pre-flight + 🟨 Implementer K1+K3+K5+K7 (4 spawns Case 2+3) + 🟥 Reviewer K2 pre-commit (PASS 0 critical, 2 Major + 2 Minor) + 👤 Chủ trì K0-bis+K2+K6+K8. Bro decision: F2 semantic ĐỔI Drafter from Nháp → Approver during ChoDuyet skip thẳng Cấp cuối (mirror F3+F4 admin opt-in per slot) + setup ALL ở Workflow Designer (KHÔNG ở User Management). UI slot label "#NV {order}" → ApproverFullName. Stats final S23 t1: **31 mig (+1 Mig 31)** · 59 tables · **~145 endpoints (-1 backout /allow-skip-final)** · 34 FE pages · **104 test pass unchanged** (3 deleted + 3 added) · 47 gotcha unchanged · 20 memory (cumulative reinforce `feedback_per_nv_permission_scope` 3×) · 6 skills · **4 sub-agents active 4 spawns (Implementer Case 2+3) + 1 Reviewer**. 4 prod user lose `AllowDrafterSkipToFinal=true` value per Option A (admin re-config qua Designer). Pattern reinforced: per-NV admin opt-in flag 3× proven (Mig 29 F1+F3 + Mig 30 F4 + Mig 31 F2) — pattern ALSO applies cho refactor existing scope, KHÔNG chỉ greenfield. Plan B Contract V2 wire vẫn pending S23 t2+. CHƯA push remote — chờ bro confirm.) **S22 chốt cuối:** 2026-05-13 2200 (Session 22 CHỐT — **🎯 Bro chốt sub-agent solution OK**. 11 commits S22 pushed remote `3d725c4..b04a11a`. CICD Monitor Run #188 PASS verified. Highlights: Plan D F2 toggle + Plan C +20 test (test catch-up backlog) + Plan E strict V2 scope + Plan F ABORTED pre-flight (defer sau Plan B) + S22+1 fix disable 3 button bug + S22+2 seed 20 test user role-based naming + S22+3 rename users `{dept}.{level}@solutions.com.vn` + S22+4 attachment view inline PDF + Section "Điều chỉnh ngân sách" + S22+5 Mig 30 `AllowApproverEditBudget` per-NV opt-in (spec fix bro feedback). Stats final S22: **30 mig (+1 Mig 30)** · 59 tables · **~146 endpoints (+3)** · 34 FE pages · **104 test pass (+20: 5 reg #44 + 7 ReturnMode + 7 Guard + 1 V2 actor scope)** · **47 gotcha (+1 #47 paths-ignore agent-memory gap pending bro fix)** · 19 memory · 6 skills · **33 active users prod** (13 cũ + 20 mới role-based) · 4 sub-agents (CICD Monitor Run #188 PASS verify, 3 sub-agents seeds-only em main solo throughout S22). Pattern reinforced: per-NV admin opt-in flag 2× proven (Mig 29 + Mig 30) — anti-pattern default scope expansion. Memory `feedback_per_nv_permission_scope` reinforced S22+5 narrative.) diff --git a/docs/changelog/sessions/2026-05-15-s23-turn5-plan-o-cascade-4-lookup-sites.md b/docs/changelog/sessions/2026-05-15-s23-turn5-plan-o-cascade-4-lookup-sites.md new file mode 100644 index 0000000..e06e825 --- /dev/null +++ b/docs/changelog/sessions/2026-05-15-s23-turn5-plan-o-cascade-4-lookup-sites.md @@ -0,0 +1,192 @@ +# Session 23 turn 5 — 2026-05-15 — Plan O HOTFIX 4 lookup sites cascade + +**Dev:** Claude Opus 4.7 1M (em main solo — bug fix reasoning chain cross 4 sites) +**Duration:** ~1.5h +**Base commit:** `fb3c22c` (S23 t4 Plan N wrap) +**Final HEAD:** `` (Plan O atomic + docs) +**Total commits Plan O:** **2** (atomic O1-O5 + docs) + +## 🎯 Trigger session + +Bro UAT 2026-05-15 sau Plan N deploy phát hiện 2 bug mới: + +**Bug 1 — Trả lại Người chỉ định fail:** +- Phiếu PE/2026/A/029 workflow QT-DN-V2-001 v14 +- Actor NV Test (UAT V2) trong OR-of-N slot Bước 2 Cấp 1 (4 NV) +- Click ← Trả lại → Dialog mở (Plan N hotfix wire OK) +- Chọn "Trả lại Người chỉ định" + Bùi Lê Thủy Trà (Bước 1 Cấp 2) +- Click Xác nhận → **Toast: "Không phải lượt bạn — chỉ NV Cấp duyệt hiện tại mới được Trả lại / Từ chối phiếu"** + +**Bug 2 — F2 Duyệt thẳng KHÔNG đến Cấp cuối:** +- Click ✓ Duyệt + checkbox skipToFinal → pointer trỏ đến **Phan Văn Chương Bước 2 Cấp 2** thay vì **Nguyễn Văn Trường Bước 3 Cấp 1 (BOD)** +- F2 logic [Service.cs:483-524](src/Backend/SolutionErp.Infrastructure/Services/PurchaseEvaluationWorkflowService.cs:483) đã đúng (`lastStepIdx = steps.Count - 1` + `lastLevelMaxOrder`) +- **Defer follow-up** — cần verify workflow v14 DB structure (có thể workflow chưa setup Bước 3 đầy đủ) + +## 🔍 Em main audit grep — Phát hiện 5 lookup sites cùng bug Plan N + +```bash +grep -n "FirstOrDefault.*Order ==" src/Backend/**/*.cs +``` + +| # | File | Line | Purpose | Pre-Plan O | +|---|---|---|---|---| +| 1 | `PurchaseEvaluationWorkflowService.cs` | 201 | `EnsureCanRejectV2Async` actor match guard | ❌ Bug bro UAT | +| 2 | `PurchaseEvaluationWorkflowService.cs` | 248 | `ApplyReturnModeAsync` read Allow flag | ❌ Bug | +| 3 | `PurchaseEvaluationDetailFeatures.cs` | 72 | F3 `EnsureEditableForDetailsAsync` | ❌ Bug | +| 4 | `PurchaseEvaluationFeatures.cs` | 311 | F4 `AdjustBudgetCommand` ChoDuyet branch | ❌ Bug | +| 5 | `PurchaseEvaluationFeatures.cs` | 765 | GetPe handler currentLevelOptions | ✅ Plan N S23 t4 fixed | + +→ **Plan N S23 t4 chỉ catch 1/5 sites**. Plan O cần fix 4 sites còn lại cùng pattern. + +## 🌳 Plan O 2 chunk execution + +### Chunk O1-O5 — Atomic BE fix + regression tests (commit `ae01ca5`) + +👤 Chủ trì Solo (bug fix reasoning chain cross 4 sites — Implementer auto-refuse criteria #4). + +**O1 fix `EnsureCanRejectV2Async:201` (5 LOC):** + +```diff +- var currentLevel = step.Levels.FirstOrDefault(l => l.Order == curLvl); +- if (currentLevel?.ApproverUserId != actorId) ++ var currentLevel = step.Levels.FirstOrDefault(l => ++ l.Order == curLvl && l.ApproverUserId == actorId); ++ if (currentLevel is null) + throw new ForbiddenException("Không phải lượt bạn — ..."); +``` + +**O2 fix `ApplyReturnModeAsync:248` (signature change + caller cascade):** + +```diff + private async Task ApplyReturnModeAsync( + PurchaseEvaluation evaluation, + WorkflowReturnMode mode, + Guid? returnTargetUserId, ++ Guid? actorUserId, + bool isAdmin, + CancellationToken ct) + +- currentLevel = step.Levels.FirstOrDefault(l => l.Order == evaluation.CurrentApprovalLevelOrder); ++ currentLevel = step.Levels.FirstOrDefault(l => ++ l.Order == evaluation.CurrentApprovalLevelOrder ++ && l.ApproverUserId == actorUserId); +``` + +Caller `TransitionAsync:94` cũng update: `actorUserId` thêm vào call: +```diff +- ApplyReturnModeAsync(evaluation, effectiveMode, returnTargetUserId, isAdmin, ct); ++ ApplyReturnModeAsync(evaluation, effectiveMode, returnTargetUserId, actorUserId, isAdmin, ct); +``` + +Non-admin actor không match slot → currentLevel=null → validation block line 252 skip → mode logic switch proceed (KHÔNG dùng currentLevel object, chỉ dùng curStepIdx + curLevel int values). Admin bypass existing line 252. + +**O3 fix `EnsureEditableForDetailsAsync:72` (F3 guard, merge filter + collapse 3 throw → 2 throw):** + +```diff +- var level = step?.Levels.FirstOrDefault(lv => lv.Order == levelOrder); +- if (level is null) throw ConflictException("schema lỗi"); +- if (!level.AllowApproverEditDetails) throw ConflictException(...); +- if (level.ApproverUserId != actorUserId) throw ForbiddenException(...); ++ var level = step?.Levels.FirstOrDefault(lv => ++ lv.Order == levelOrder && lv.ApproverUserId == actorUserId); ++ if (level is null) throw ForbiddenException("Chỉ NV phụ trách..."); ++ if (!level.AllowApproverEditDetails) throw ConflictException(...); +``` + +**O4 fix `AdjustPurchaseEvaluationBudgetCommandHandler:311` (F4 ChoDuyet branch, cùng pattern):** + +```diff +- var level = step.Levels.FirstOrDefault(l => l.Order == curLvl); +- if (level is null) throw ConflictException("schema lỗi"); +- if (!level.AllowApproverEditBudget) throw ConflictException(...); +- if (level.ApproverUserId != actorId) throw ForbiddenException(...); ++ var level = step.Levels.FirstOrDefault(l => ++ l.Order == curLvl && l.ApproverUserId == actorId); ++ if (level is null) throw ForbiddenException("Chỉ NV phụ trách..."); ++ if (!level.AllowApproverEditBudget) throw ConflictException(...); +``` + +**O5 Regression test** (`PurchaseEvaluationPerNvLookupRegressionTests.cs` new file, 3 test): + +1. `TransitionReject_ActorD_LastInSlot_AllowsRejectViaDrafterMode` — Actor D (non-first-row in OR-of-N) trả lại Drafter mode → no throw. Pre-fix: throw "Không phải lượt bạn" vì handler chỉ check row đầu DB (Actor A). +2. `TransitionReject_Outsider_NotInSlot_ThrowsForbidden` — Outsider không trong slot → throw đúng intent (verify fix KHÔNG over-permissive). +3. `TransitionRejectOneLevel_ActorC_HasFlagWhileOthersDont_AllowsMode` — Actor C only tick AllowReturnOneLevel, 3 NV khác KHÔNG. Actor C click "Trả lại 1 Cấp" → mode allowed. Pre-fix: read flag từ row A (false) → throw ConflictException "không bật mode OneLevel". + +**Verify:** +- `dotnet build SolutionErp.slnx` clean (0 err, 2 warn pre-existing DocxRenderer) +- `dotnet test SolutionErp.slnx` **111/111 PASS** (+3 từ 108: 58 Domain + 53 Infra) +- 3 Plan O test individual PASS + +### Chunk O7 — Docs + memory + push (this commit) + +- `docs/STATUS.md` Last updated S23 t5 + stats 111 test (+3) +- `docs/HANDOFF.md` TL;DR S23 t5 với 5 sites enumerate +- Session log file này +- Memory user-level `feedback_per_nv_permission_scope.md` CRITICAL HOTFIX S23 t5 section: + - 5 sites checklist documented + - 4× cumulative gap analysis updated (3× refactor wire SAME bug toàn 5 sites — 2 sessions hotfix Plan N + Plan O) + - Audit checklist grep `FirstOrDefault.*Order ==` + - Reviewer pre-commit guideline grep enum lookup sites + +## 📊 Stats Plan O chốt + +| Metric | Trước (S23 t4) | Sau (S23 t5) | Δ | +|---|---|---|---| +| Migrations | 31 | 31 | 0 | +| Endpoints | ~145 | ~145 | 0 | +| FE pages | 34 | 34 | 0 | +| **Unit tests** | 108 | **111** | **+3** (3 site regression: OR-of-N actor + outsider + flag-only-1) | +| Gotchas | 47 | 47 | 0 | +| Memory entries | 20 | 20 | 0 (1 entry CRITICAL HOTFIX section reinforced 2 lần: S23 t4 + S23 t5) | +| Skills | 6 | 6 | 0 | +| Sub-agents | 4 | 4 (em main solo Plan O) | active | +| Commits Plan O | — | **2** (atomic O1-O5 + docs O7) | pending push | + +## 🎯 Multi-agent ROI evidence Plan O + +| Spawn | Agent | Cost | Output | Catch | +|---|---|---|---|---| +| Audit grep | 👤 Chủ trì | <1K | 5 lookup sites enum file:line | em main solo grep nhanh hơn spawn Investigator | +| O1-O4 fix | 👤 Chủ trì | ~self | 4 site fix surgical ~30 LOC BE | Pattern uniform sau Plan N | +| O5 tests | 👤 Chủ trì | ~self | 3 regression test new file ~210 LOC | First iter compile error (using missing) — fix add `SolutionErp.Application.PurchaseEvaluations.Services` namespace | +| O7 docs | 👤 Chủ trì | ~self | docs + memory update | — | +| CICD verify | 🟩 (pending spawn) | ~150K | post-deploy verify Plan O | TBD | + +**Total Plan O spawn cost (excl CICD):** ~0 sub-agent — em main solo cross 4 sites bug fix reasoning chain. Per directive Thứ 9: bug fix tightly coupled → em solo. Investigator catch root cause Plan N đã enough — Plan O = follow-up surgical fix. + +**Anti-pattern caught Plan N → Plan O:** + +Plan N S23 t4 fix 1 site (Plan N Investigator brief mention 9 surface points). Em main + Investigator + Reviewer ALL MISS enum 5 lookup sites — chỉ catch 1 GetPe handler. Bug regression 4 sites lại ở prod 1 ngày sau Plan N deploy → 4 sites bug present 2 ngày prod cumulative. + +**Pattern reinforced cross-project:** + +Khi refactor schema 1-row-per-role (OR-of-N) + bug fix lookup site → BẮT BUỘC grep enum tất cả lookup sites cùng pattern, KHÔNG fix theo bug report mỗi lần. Investigator pre-flight cho bug fix tightly coupled phải `grep -rn "FirstOrDefault.*Order =="` enumerate trước. + +## ⚠️ Pending S23 t6+ + +- 🟩 **CICD Monitor post-deploy verify Plan O** — spawn sau push +- 🔍 **Bug 2 F2 follow-up** — verify workflow v14 DB structure thực tế (BOD Bước 3 setup đúng?). Nếu DB OK + F2 logic line 483-524 đúng → có thể là FE timeline render issue +- 🟦 **Investigator follow-up gotcha #41/#48 candidate** controlled test paths-ignore (carry từ Plan M) +- 🟡 **Plan B Contract V2 wire (Mig 32+33)** — HIGH priority next +- ⛔ **Plan F drop V1** — defer +- 🟢 **Plan H PE PDF Export** — LOW priority +- 🟡 **Plan I RAG Hybrid setup** — defer +- 🔧 **Gotcha #47 paths-ignore agent-memory** — pending + +## 📋 Pattern reinforced Plan O + +1. **5 lookup sites enum SOLUTION_ERP PE module** sau Mig 29 OR-of-N — documented trong memory user-level `feedback_per_nv_permission_scope.md` CRITICAL HOTFIX S23 t5 section +2. **Grep `FirstOrDefault.*Order ==` audit checklist** cho future flag F5+ HOẶC migration mới có OR-of-N pattern +3. **Atomic commit BE fix + regression test** (per `feedback_uat_skip_verify` rule Plan L lesson) — Service refactor semantic BẮT BUỘC test cùng commit +4. **Em main solo cross-stack bug fix reasoning chain** — Implementer auto-refuse criteria #4 (bug fix involving reasoning chain). Investigator pre-flight Plan N đã enough — Plan O = follow-up surgical fix +5. **Method signature cascade** — Khi thêm param `Guid? actorUserId` vào helper internal, phải update ALL callers (1 caller trong này — TransitionAsync:94) + +## References + +- Memory user-level updated: `feedback_per_nv_permission_scope.md` CRITICAL HOTFIX S23 t5 section (5 sites enum + audit grep checklist) +- Files: + - [PurchaseEvaluationWorkflowService.cs:94,201,212-248](src/Backend/SolutionErp.Infrastructure/Services/PurchaseEvaluationWorkflowService.cs:201) (O1+O2) + - [PurchaseEvaluationDetailFeatures.cs:72](src/Backend/SolutionErp.Application/PurchaseEvaluations/PurchaseEvaluationDetailFeatures.cs:72) (O3) + - [PurchaseEvaluationFeatures.cs:311](src/Backend/SolutionErp.Application/PurchaseEvaluations/PurchaseEvaluationFeatures.cs:311) (O4) + - [PurchaseEvaluationPerNvLookupRegressionTests.cs](tests/SolutionErp.Infrastructure.Tests/Services/PurchaseEvaluationPerNvLookupRegressionTests.cs) (O5) +- Rules: §3.9 mirror 2 FE, §7 test timing test-before (regression bug), `feedback_per_nv_permission_scope` (S23 t5 5 sites enum), `feedback_uat_skip_verify` (Service refactor + test atomic)