[CLAUDE] Workflow: KHKK 8 panel nhóm mirror DuyetNcc + BE guards (0-mig)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 6m24s

YC-013 (S182/L13). 8 leaf "Duyệt KHKK — Nhóm 1..8" ra đúng khuôn trang
DuyetNcc: slice per-Code + lockedCode + Sửa-tại-chỗ/Tạo-version/Ghim/Xoá.
D3=C (YC-014): 6 ô chưa-wire disabled-giữ-state-thật + tooltip trên label
(Chromium không hiện title trên input disabled — MAJOR-1); ô #4 thêm chữ
nhìn thấy được; #7 giữ; #8 Finalize 0-chạm (prod 8/88 dựa nó); ô CEO
disable type-10 + POST null.

BE 5 guard (0 migration):
- W1a deactivate-per-Code cho type-10 (Code+Type+IsActive — cấm regex);
  Code normalize Trim().ToUpperInvariant() tại đường ghi + IgnoreCase belt
  trong GroupCodePattern (MAJOR-2: SQLite test case-sensitive nguoc prod
  CI_AS collation)
- W1b ContractSigningPlanWorkflowGuards (public static, Application) —
  rào nhóm 3 cửa Create/UpdateDraft/Submit, giữ cho-qua-code-ngoài-họ
- W1b2 (D6) pin-check IsActive+IsUserSelectable 2 cửa, 2 message tách
- W1c changelog PUT type-10 vào ContractSigningPlanChangelogs
- W1d DELETE usage-check 409 đích danh (8 module pin, IgnoreQueryFilters
  cho PE/Contract/KHKK; 5 module office pin loose-0FK — guard là rào duy
  nhất chống dangling) + 404 NotFoundException + D5 rào version-cuối nhóm
  (+ ApplicableType — MINOR-3)

Test 645 → 660 (+14 spec + T15 D6-Create MAJOR-3); MINOR-1 pin nguyên câu
thứ-tự 1 ca. File test thứ 3 (GroupAndCatalog) đổi 1 assertion theo câu
409 mới của W1b — spec-change, không phải nới bar.

Khai accepted (reviewer PASS_WITH_FIXES 0C/3M+6m, đã vá 3M+2m):
- MINOR-4: panel nhóm tạo-version-mới ⇒ 6 cờ khoá đóng băng default FE
  (vô hại — BE không đọc 6 cờ đó cho type-10)
- MINOR-5: bỏ ghim/bỏ active bản cuối nhóm = đóng cửa tạo phiếu nhóm đó
  (răng thật của nút Ghim — không rào đợt này)
- race 2-admin cùng Code → 2601/500 thô (UNIQUE đỡ data, chấp nhận)

Evidence: .claude/workflows/runs/2026-08-08-S182-khkk-awf-mirror-ncc/
(3 fable-invest + 2 fable-review + spec FINAL + 4 lane + precheck prod
12 phiếu/pin-lệch-0 + reviewer pre-commit)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-08-08 12:14:37 +07:00
parent 18f8f76bac
commit 706134daa9
13 changed files with 1604 additions and 89 deletions

View File

@ -1,6 +1,7 @@
using Microsoft.EntityFrameworkCore;
using SolutionErp.Application.Common.Exceptions;
using SolutionErp.Application.Common.Interfaces;
using SolutionErp.Application.ContractSigningPlans; // ContractSigningPlanWorkflowGuards (rào nhóm dùng chung 3 site)
using SolutionErp.Application.ContractSigningPlans.Services;
using SolutionErp.Application.Notifications;
using SolutionErp.Domain.ApprovalWorkflowsV2;
@ -186,6 +187,15 @@ public class ContractSigningPlanWorkflowService(
throw new ConflictException(
$"Có hạng mục không hợp lệ (đã xoá / không tồn tại) hoặc không thuộc nhóm duyệt của phiếu — mọi dòng phải cùng nhóm N{plan.ApprovalGroup}.");
// ── [S182 W1b] Rào NHÓM ⟷ QUY TRÌNH, site 3/3 (2 site kia ở đường tạo/sửa nháp).
// Cửa này là chốt CUỐI và là cửa DUY NHẤT bắt được phiếu pin lệch có TỪ TRƯỚC: hai
// rào kia chỉ chặn lúc GHI, nên phiếu tạo trước khi có rào (hoặc trước khi admin đổi
// mã quy trình) vẫn nằm sẵn trong DB với nhóm lệch. Đứng ngay trên `LoadStepsAsync`
// để phiếu lệch không kịp bước vào ChoDuyet rồi mới lộ.
// Thân luật + lý do "cho qua code ngoài họ": `ContractSigningPlanWorkflowGuards`.
await ContractSigningPlanWorkflowGuards.EnsureWorkflowGroupMatchAsync(
db, awId, plan.ApprovalGroup, ct);
var steps = await LoadStepsAsync(awId, ct);
var firstLevelGroup = steps[0].Levels.Where(l => l.Order == 1).ToList();
if (firstLevelGroup.Count == 0)