From c2042ef95658dd2792b61294ce02386385e9d130 Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Fri, 15 May 2026 11:11:36 +0700 Subject: [PATCH] =?UTF-8?q?[CLAUDE]=20PurchaseEvaluation:=20Chunk=20M1=20?= =?UTF-8?q?=E2=80=94=20Fix=20F1.OneLevel/OneStep=20edge=20case=20B=C6=B0?= =?UTF-8?q?=E1=BB=9Bc=201=20=E2=86=92=20gi=E1=BB=AF=20ChoDuyet=20(KH=C3=94?= =?UTF-8?q?NG=20fallback=20Drafter)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bro UAT S23 t3: "Các tính năng trả lại 1 cấp hoặc chỉ định hoặc edit cho xử lý ở trạng thái đang gửi duyệt luôn, không về draft." Investigator audit confirm 4 mode F1.OneLevel/Assignee + F2 + F3+F4 main path đã giữ Phase=ChoDuyet (Mig 28-31 cumulative). Edge case duy nhất còn fallback Drafter (Phase=TraLai): - F1.OneLevel khi đang Bước 1 Cấp 1 (curStepIdx=0, curLevel=1) — no further back - F1.OneStep khi đang Bước 1 (curStepIdx=0) Logic cũ (line 303-310 OneLevel + 325-332 OneStep): ``` evaluation.Phase = PurchaseEvaluationPhase.TraLai; // 98 evaluation.CurrentWorkflowStepIndex = null; evaluation.CurrentApprovalLevelOrder = null; evaluation.SlaDeadline = null; return "Trả về Người soạn thảo (fallback — đang Bước 1 Cấp 1)"; ``` Logic mới — reset (0, 1) giữ ChoDuyet: ``` evaluation.CurrentWorkflowStepIndex = 0; evaluation.CurrentApprovalLevelOrder = 1; summary = "Action 'Trả lại 1 Cấp/Bước' không lùi được — phiếu reset về Approver Bước 1 Cấp 1"; // SLA reset 7d ở cuối hàm cho 3 mode còn lại ``` Semantic mới (per bro chốt AskUserQuestion Plan M): - Phase giữ ChoDuyet (KHÔNG TraLai=98) - Pointer reset về (0, 1) = chính Approver A hiện tại (effectively no-op) - SLA reset 7d (cuối hàm switch áp dụng cho cả 3 mode F1 non-Drafter) - Audit log rõ "không lùi được" để Drafter/Admin biết action không hiệu lực KHÔNG đụng: - F1.Drafter (line 268-275) giữ nguyên semantic Phase=TraLai - F1.Assignee (line 335-360) giữ nguyên throw nếu không match - F2 ApproveV2Async skipToFinal (line 483-524 Plan K L1 vừa fix) - F3 EnsureEditableForDetailsAsync (PurchaseEvaluationDetailFeatures.cs:42) - F4 AdjustBudgetCommand handler (PurchaseEvaluationFeatures.cs:272-329) Verify: - dotnet build src/Backend/SolutionErp.Infrastructure clean (0 err, 2 warn pre-existing DocxRenderer) - Service.cs 13+/13- LOC change (1 file, surgical edit) - Pending Chunk M2: 2 edge case test (Implementer Case 3 spawn) + verify K7 Approver F2 không cascade - Pending Chunk M3: FE label rename Phase=TraLai "Trả lại" → "Cần chỉnh sửa lại" (Implementer Case 2 spawn × 2 app) - Pending Chunk M4: docs + memory update + push + CICD verify Co-Authored-By: Claude Opus 4.7 (1M context) --- .../PurchaseEvaluationWorkflowService.cs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Backend/SolutionErp.Infrastructure/Services/PurchaseEvaluationWorkflowService.cs b/src/Backend/SolutionErp.Infrastructure/Services/PurchaseEvaluationWorkflowService.cs index 61f146c..b3f7518 100644 --- a/src/Backend/SolutionErp.Infrastructure/Services/PurchaseEvaluationWorkflowService.cs +++ b/src/Backend/SolutionErp.Infrastructure/Services/PurchaseEvaluationWorkflowService.cs @@ -286,7 +286,8 @@ public class PurchaseEvaluationWorkflowService( { case WorkflowReturnMode.OneLevel: // Lùi 1 Cấp trong cùng Step. Nếu đang Cấp 1 → lùi sang Bước trước - // Cấp cuối. Nếu đang Bước 1 Cấp 1 → fallback Drafter (no further). + // Cấp cuối. Nếu đang Bước 1 Cấp 1 → reset về (0, 1) giữ ChoDuyet + // (Plan M S23 t3 — KHÔNG fallback Drafter, phiếu giữ "đang duyệt"). if (curLevel > 1) { evaluation.CurrentApprovalLevelOrder = curLevel - 1; @@ -302,12 +303,12 @@ public class PurchaseEvaluationWorkflowService( } else { - // Bước 1 Cấp 1 — no further back. Fallback Drafter. - evaluation.Phase = PurchaseEvaluationPhase.TraLai; - evaluation.CurrentWorkflowStepIndex = null; - evaluation.CurrentApprovalLevelOrder = null; - evaluation.SlaDeadline = null; - return "Trả về Người soạn thảo (fallback — đang Bước 1 Cấp 1)"; + // Bước 1 Cấp 1 → reset về (0, 1) giữ Phase=ChoDuyet (no-op effective + // — Approver A hiện tại). Audit log rõ "không lùi được". SLA reset + // dưới cuối hàm cho approver giữ nguyên. + evaluation.CurrentWorkflowStepIndex = 0; + evaluation.CurrentApprovalLevelOrder = 1; + summary = "Action 'Trả lại 1 Cấp' không lùi được — phiếu reset về Approver Bước 1 Cấp 1"; } break; @@ -323,12 +324,11 @@ public class PurchaseEvaluationWorkflowService( } else { - // Đang Bước 1 → fallback Drafter - evaluation.Phase = PurchaseEvaluationPhase.TraLai; - evaluation.CurrentWorkflowStepIndex = null; - evaluation.CurrentApprovalLevelOrder = null; - evaluation.SlaDeadline = null; - return "Trả về Người soạn thảo (fallback — đang Bước đầu)"; + // Bước 1 → reset về (0, 1) giữ Phase=ChoDuyet (Plan M S23 t3 — + // KHÔNG fallback Drafter, phiếu giữ "đang duyệt"). + evaluation.CurrentWorkflowStepIndex = 0; + evaluation.CurrentApprovalLevelOrder = 1; + summary = "Action 'Trả lại 1 Bước' không lùi được — phiếu reset về Approver Bước 1 Cấp 1"; } break;