[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
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:
@ -30,6 +30,20 @@ export const MenuKeys = {
|
||||
ApprovalWorkflowsV2: 'ApprovalWorkflowsV2',
|
||||
AwV2_DuyetNcc: 'AwV2_DuyetNcc',
|
||||
AwV2_DuyetNccPhuongAn: 'AwV2_DuyetNccPhuongAn',
|
||||
// [W2e S182] 8 leaf Designer theo NHÓM DUYỆT của Kế hoạch ký kết HĐ.
|
||||
// Mirror BE `MenuKeys.cs:127-134` (8 key này VÀO `All` ⇒ 32 policy AwV2_KhkkN{n}.{R,C,U,D}).
|
||||
// ⚠️ Chép cho ĐỦ bảng đối chiếu FE↔BE, KHÔNG phải để dùng ở app này: toàn bộ họ
|
||||
// `AwV2_*` là màn CẤU HÌNH bên fe-admin — fe-user cố ý không có trang Designer,
|
||||
// cũng không có nhánh `AwV2_*` trong `Layout.tsx`. Đừng đọc mấy dòng này thành
|
||||
// "fe-user thiếu route" rồi đi thêm route.
|
||||
AwV2_KhkkN1: 'AwV2_KhkkN1',
|
||||
AwV2_KhkkN2: 'AwV2_KhkkN2',
|
||||
AwV2_KhkkN3: 'AwV2_KhkkN3',
|
||||
AwV2_KhkkN4: 'AwV2_KhkkN4',
|
||||
AwV2_KhkkN5: 'AwV2_KhkkN5',
|
||||
AwV2_KhkkN6: 'AwV2_KhkkN6',
|
||||
AwV2_KhkkN7: 'AwV2_KhkkN7',
|
||||
AwV2_KhkkN8: 'AwV2_KhkkN8',
|
||||
// [S61 Mig 50] Module Ngân sách cũ (Budgets + Bg_*) XÓA — thay bằng bảng
|
||||
// "Tổng hợp ngân sách trình ký" per (Dự án, Hạng mục) trong phiếu PE.
|
||||
// Module Hồ sơ Nhân sự (Mig 34 — Phase 10.1 G-H1 Session 33, 2026-05-26)
|
||||
|
||||
@ -59,6 +59,11 @@ interface WorkflowDto {
|
||||
code: string
|
||||
name: string
|
||||
isUserSelectable: boolean
|
||||
// [W2g S182] Cùng một mã `KHKK-N{n}` có NHIỀU phiên bản (admin bấm "Tạo phiên bản
|
||||
// mới" thì bản cũ chuyển sang lưu trữ). `history` mà BE trả về là DANH SÁCH ĐẦY ĐỦ
|
||||
// — cả bản đang áp dụng lẫn bản đã lưu trữ — nên thiếu cờ này thì màn tạo phiếu
|
||||
// không phân biệt được, xem thêm chỗ dùng bên dưới.
|
||||
isActive: boolean
|
||||
}
|
||||
|
||||
// 🧊 [S174] `firstFreeGroup()` ĐÃ GỠ cùng lúc bỏ ô chọn nhóm — nó chỉ tồn tại để tự nhảy
|
||||
@ -110,9 +115,15 @@ export function KhkkCreatePage() {
|
||||
// `var code = $"KHKK-N{n}"` (vòng `for n = 1..8`, seed idempotent per-Code).
|
||||
// Không khớp ⇒ KHÔNG tự rơi về quy trình khác: chặn tạo + nói rõ thiếu mã nào, vì gán
|
||||
// nhầm quy trình là phiếu đi sai đường duyệt — hỏng nặng hơn là không tạo được.
|
||||
// [W2g S182] 🔴 Phải lọc thêm `isActive`. Danh sách trả về gồm CẢ phiên bản đã lưu
|
||||
// trữ, mà `find` lấy phần tử ĐẦU TIÊN khớp mã — hễ admin tạo phiên bản mới cho nhóm
|
||||
// này là phiếu mới có thể bị gắn vào bản CŨ (thứ tự do BE trả, không do màn này
|
||||
// quyết), đi theo đội hình duyệt đã bị thay. Gắn sai quy trình thì lúc phát hiện
|
||||
// phiếu đã chạy được vài trạm rồi. Ràng buộc `isUserSelectable` ở query trên vẫn giữ
|
||||
// (admin ghim bản nào thì user mới được dùng bản đó).
|
||||
const wantWorkflowCode = `KHKK-N${approvalGroup}`
|
||||
const autoWorkflow = workflows.data?.find(
|
||||
(w) => (w.code ?? '').trim().toUpperCase() === wantWorkflowCode,
|
||||
(w) => w.isActive && (w.code ?? '').trim().toUpperCase() === wantWorkflowCode,
|
||||
) ?? null
|
||||
|
||||
// Phiếu đang XEM — chỉ tải khi thật sự có cái để xem.
|
||||
@ -125,7 +136,11 @@ export function KhkkCreatePage() {
|
||||
const create = useMutation({
|
||||
mutationFn: async () => {
|
||||
if (!purchaseEvaluationId) throw new Error('Vui lòng chọn phiếu Duyệt NCC nguồn')
|
||||
if (!autoWorkflow) throw new Error(`Chưa có quy trình duyệt ${wantWorkflowCode}`)
|
||||
// [W2g S182] Câu này nói ĐIỀU KIỆN, không nói "không tồn tại": quy trình có thể
|
||||
// đang nằm đó nhưng ở phiên bản đã lưu trữ hoặc chưa được ghim.
|
||||
if (!autoWorkflow) {
|
||||
throw new Error(`Chưa có quy trình duyệt ${wantWorkflowCode} đang áp dụng và được ghim cho user chọn`)
|
||||
}
|
||||
const body: CreateKhkkInput = {
|
||||
peId: purchaseEvaluationId, // [F-2] BE Command field = PeId
|
||||
approvalWorkflowId: autoWorkflow.id,
|
||||
@ -349,9 +364,10 @@ export function KhkkCreatePage() {
|
||||
</div>
|
||||
{!workflows.isLoading && !autoWorkflow ? (
|
||||
<p className="mt-1 text-[11px] text-amber-700">
|
||||
⚠ Chưa có quy trình mã <strong>{wantWorkflowCode}</strong> (hoặc chưa được ghim
|
||||
cho user chọn). Nhờ admin mở trong màn Quy trình duyệt rồi quay lại — hệ thống
|
||||
KHÔNG tự dùng quy trình của nhóm khác.
|
||||
⚠ Chưa dùng được quy trình mã <strong>{wantWorkflowCode}</strong>: phải có
|
||||
phiên bản <strong>đang áp dụng</strong> và <strong>đã ghim</strong> cho user chọn.
|
||||
Nhờ admin mở trong màn Quy trình duyệt rồi quay lại — hệ thống KHÔNG tự dùng
|
||||
phiên bản đã lưu trữ, cũng KHÔNG tự dùng quy trình của nhóm khác.
|
||||
</p>
|
||||
) : (
|
||||
<p className="mt-1 text-[11px] text-slate-500">
|
||||
|
||||
Reference in New Issue
Block a user