10 KiB
SPEC TỔNG QUÁT v2 — Chuỗi 4 GĐ theo SOL-CCM-SP-002 (B1a + B1b review, lead kết tinh @S164)
v1 = kết tinh từ
sub-invest-fable-b1a.md(spot-check 4/4). v2 = v1 + 14 vá từ B1b (b1b-review-synthesis.md— 3 lane reviewer 41 finding thô; lens2 xác nhận 6/6 claim chịu-lực ĐÚNG ⇒ nền giữ, vỏ vá). Yêu cầu gốc:draft-yeu-cau-owner.md.
① Tính năng / đề bài
Chuỗi 4 GĐ per-gói-thầu theo SOL-CCM-SP-002: GĐ1 Duyệt NCC (PE = CHA, đã chạy) → GĐ2 KHKK = duyệt HẠNG MỤC theo 8 NHÓM DUYỆT (trình ký số trạm-by-trạm y Duyệt NCC; ký nháy = mực trên bản cứng GĐ4) → GĐ3 điều khoản → GĐ4 bản cứng 1-mốc. Scope 5 mảnh: master-data danh mục · sidebar 8 nhóm × 6 leaf · cây mirror sidebar · admin thu gọn + 8 designer · dry-run E2E. 🔴 Luật khuôn: GIỐNG NHAU — CHỈ KHÁC FORM — ĐỪNG CHẾ THÊM. 🔸 Khai thẳng (B1b l3-F4): đợt này 8 nhóm = đơn vị HIỂN THỊ + luồng duyệt, KHÔNG phải đơn vị authz — mọi endpoint KHKK giữ 1 bộ policy KeHoachKyKet.{R,C,U,D} per-action (ContractSigningPlansController.cs:28+); authz-per-nhóm nếu anh muốn = wave riêng sau.
② Cách implement — 8 quyết định (v2)
- [OG-1] Cardinality "đưa vào loại HĐ" default GỘP theo cặp (NCC × dòng-danh-mục) — N line chung
ContractId(hợp khuônContractSigningPlanLine.cs:25, index không-uniqueConfiguration:26); đảo 1-1 được cùng máy. - Phiếu KHKK = per NHÓM (1 phiếu = 1 nhóm, N hạng mục). Lines per-hạng-mục: Mig +
CatalogEntryId Guid?+TenHangMuc, UNIQUE → (PlanId, SupplierId, CatalogEntryId) filtered. 🔴 +2 vá B1b: (a) đổi rào 1-PE-1-phiếu (ContractSigningPlanFeatures.cs:342-347+ picker:1201-1202) → (PeId, ApprovalGroup) [OG-7] — FE tree đã chịu N-phiếu/PE (usePipelineStages.ts:110-121); (b) bất-biến tiền:PeReferenceAmount= snapshot per-NCC-toàn-phiếu (Line.cs:6,:16-20) — repurpose per-hạng-mục PHẢI định nghĩa lại semantics + Σ trước == Σ sau mig, acceptance rà 16 consumer (10 BE.Lines+ 6 file FE — danh sách l3-F18). - Workflow = 1 type-10 + 8 Code
KHKK-N1..N8; only-ONE-active VÔ HẠI (chứng 2 mắt xích l2: create chỉ check type:209-220; overview không lọc IsActive:117-134, POST không đụng IsUserSelectable:341-353). 🔴 CộtApprovalGroupK2 là CHỦ DUY NHẤT (l3-F6) — K3 chỉ đọc (map Code↔group + validator phiếu-pin-đúng-nhóm). - Vai catalog = 2 tầng: danh mục lưu chuỗi vai TEXT (in khối ký GĐ4) ⟂ workflow Levels lưu NGƯỜI THẬT. 🔸 Khai limitation (l1-F12): TEXT không ràng buộc máy với người-duyệt-thật — chấp nhận đợt này, khai trong doc K1.
- NĐUQ = cột THAM KHẢO text [OG-3]; enforce (
CeoApprovalThreshold) = wave opt-in sau (0 consumer CỐ Ý —WorkflowService.cs:44). - Menu: GIỮ
Khkk_G1+ 6 leaf cũ, đổi LABEL = nhóm 1 (labelBackfill khuôn S155). Nhóm 2-8 = 42 leaf MỚI + 7 group-key mới (49 row menu mới; 48 leaf TỔNG) — sửa số l1-F8/l2-F5. 🔴 Phiếu cũ: backfillApprovalGroup = 1(l3-F5 — mirror bàiEvaluationTypekhông rỗng; acceptance đếmCOUNT(phiếu) == Σ COUNT 8 folder). - Admin ẩn = fe-admin
isAdminHiddenMỞ RỘNG TẬP KEY TƯỜNG MINH (giữ blacklist — KHÔNG đảo whitelist, tránh đổi default menu-mới; vá hội tụ l1-F2 ⨯ l3-F1/F2): ẩn thêm {Dashboard?→giữ, các root nghiệp vụ:DuyetNcc-root keys,KeHoachKyKet, HR/Office/Personal,Contracts(đã ẩnCt_*),HardCopies,Forms,Reports,Catalogs/Master,Workflows(:1795),PeWorkflows(:1798)} — CHỪA {System+ 4 leaf quản trị +ApprovalWorkflowsV2(:1801, con System) + subtree}. Danh sách key CHÍNH XÁC = việc B2-cụm-2 liệt từDbInitializerseed; acceptance = liệt kê đúng N mục lá còn thấy (l3-F2). - Nguồn danh mục: file đĩa
QUY_TRINH/QT TRINH KY HOP DONG TP-NCC.docx= ĐÚNG SOL-CCM-SP-002.v01 (mã ở word/header1.xml) NHƯNG bản 6-trang KHÔNG chứa bảng (lead đo). Nguồn bảng = 7 ảnh anh gửi @S164 (trang 5-9, trọn 5.1 A/B/C + 5.2 CEO) → transcribe → [OG-6] anh soát bảng seed trước land (hoặc anh gửi file 15-trang). "/" trong ô vai = OR-of-N.
③ Wave K1-K8 (v2 — PRE-gate + acceptance có răng)
Cụm 1 (nền):
- K1 Master-data danh mục — PRE: [OG-6]. BE entity+config+CQRS+controller per-action policy; Mig 70 (3-file rule) filtered-unique Code #57; seed per-Code idempotent; FE leaf Catalogs ×2 app. DoD: N dòng khớp ~85±5, lệch giải trình từng dòng (đối chứng ảnh) · tên VN+EN đủ · CRUD 200 · seed ×2 không nhân row · test ≥590+k, khai k.
- K2 Phiếu mang hạng-mục + nhóm — PRE: [OG-1] + [OG-7]. Mig 71 (3-file): plan +
ApprovalGroup intbackfill=1; Lines +2 cột + đổi UNIQUE; đổi rào (PeId)→(PeId,ApprovalGroup) 2 site:342-347/:1201-1202; list-query +paramgroup(ListContractSigningPlansQuery:622-625— K2 chủ, l3-F3) + DTOContractSigningPlanListItemDto:34+approvalGroup(sửa citation l2-F4) + FE types. DoD: phiếu nhóm 2 CÙNG PE → 201 · line khác nhóm → 409 · phiếu cũ ở folder nhóm 1,COUNT == Σ 8 folder· Σ tiền trước == sau mig · bảng rà 16 consumer ĐÃ-XỬ/KHÔNG-ĐỔI · test ≥590+k. - K3 8 workflow nhóm + designer — PRE: [OG-2] gật roster + verify đội hình LIVE (không phải archived). Seed 8 workflow
KHKK-N1..N8type-10 (khuôn:171) + validator pin-đúng-nhóm; 8 menu-con dướiApprovalWorkflowsV2+ mởresolvePathfe-adminLayout.tsx:166-172nhận code mới (leaf lạ rớt im lặng #50) + route designer per-workflow. DoD: API trả 8 · sidebar admin đếm được 8 designer, mở designer nhóm n load đúngKHKK-N{n}(l3-F10) · phiếu nhóm 3 pin workflow nhóm 5 → 409 · duyệt trọn trạm 1 phiếu → DaDuyet · test ≥590+k.
Cụm 2 (UI): (l3-F8: tách phụ thuộc thật — K4a chạy song song cụm 1 được)
- K4a Menu+grant (0 phụ thuộc): 49 row menu + grant 3 SITE (
:1780seed ·SeedKeHoachKyKetAccessAsync:2415·KhkkKeys():2185— site-3 l2-F6, comment:2204"quên 1 bên = quyền lệch"). K4b 4 leaf list + Thao tác (chờ K2 param). K4c leaf WfView/Create (chờ K3): WfView mang?group=lọc theo workflow Code nhóm (hiệnWorkflowMatrixViewPage:52-71chỉ lọc type — l2-F3). DoD: 48 leaf render đúng · leaf lọc đúng group kể cả WfView/Create · 2 chiều theo bảng kỳ-vọng 13 role (seeder hiện phủ 7 vai:2671-2675— 6 vai còn lại khai kỳ vọng TRƯỚC, l3-F13) · key cũ 0 mồ côi. - K5 Cây sub-folder: GĐ2 group-by
approvalGroup· GĐ3/4 group-byc.type(đã có:240); thêm tầnggroupsvàoPipelineStage(mở rộng khuôn — bẫycontentphải truyềncounttay:74-75). DoD: sub-folder khớp sidebar · 2 file đích danh SHA-identical ×2 app (usePipelineStages.ts+PipelineTreePanel.tsx— l3-F19) · build ×2 PASS. - K6 Admin thu gọn (độc lập NHƯNG l3-F9: kéo sớm TRƯỚC K3 thì 8 designer chưa tồn tại — nếu kéo sớm, acceptance "đếm 8 designer" dời sang sau K3): QĐ7 tập-key tường minh. DoD: liệt kê đúng N mục lá còn thấy (đủ tên, dư/thiếu 1 = FAIL) · fe-user KHÔNG đổi =
git diff --stat <base>..<head> -- fe-user/src= 0 file (KHÔNG đo bundle-hash #69 — l3-F12).
Cụm 3 (nối + chạy):
- K7 Cầu KHKK→HĐ — RE-ĐO 3 NẤC (l3-F11): (a) cột/index ✓ có (
Line.cs:25+Config:26); (b) write-site gánContractId= 0 hiện tại (lead xác nhận grep); (c) test E2E — ⇒ trạng thái NỬA-LAND, K7 build phần (b)+(c). Bridge đọcApprovedAmountper-Line + gộp theo OG-1 + pin workflow V2 + chọnContractTypelúc bắc cầu (ai chọn = câu nghiệp vụ, mặc định người bấm chọn trong dialog — l1-F15). DoD: KHKK DaDuyet → HĐ đúng số lượng OG-1 ·giaTri == Σ ApprovedAmountphạm-vi-gộp khai rõ, null → chặn với message (l1-F6) · approver V2 thấy + inbox · test bridge ≥590+k. - K8 DRY-RUN E2E từ
PE/2026/A/049. DoD (+3 dòng l3-F16): mọi bản ghi mới mang tiền tố ZZTEST · danh sách bản-ghi-không-xoá-được + cách sống chung (HĐ DaPhatHanh guard numeric) · tắt/dặn-team notification trước khi chạy · toàn trình hết trạm → HĐ · cây đủ 4 GĐ · screenshot + mã phiếu thật.
Mọi wave: cicd PASS; byte-verify #77 CHỈ wave có FE-ship — wave BE-only = smoke API (l3-F17); mig = 3-file rule.
④ [OWNER-GATE] — 4 cũ + 2 mới (nối vào PRE từng wave ở trên)
| OG | Câu hỏi | Trạng thái | Chặn wave |
|---|---|---|---|
| OG-1 | Gộp HĐ | ✅ CHỐT @S164 (verbatim: "thiết kế gộp nhưng giao diện thì cho 1-1 (Khi user đổi ý thì mình làm luôn)") ⇒ schema GỘP-capable (N line chung ContractId) + UI default 1-1 (bridge = 1 hàm nhận list-line, UI truyền 1 line; bung gộp = FE sau, 0 đổi máy) | K2, K7 |
| OG-2 | Roster 8 workflow | ✅ CHỐT @S164 ("Đúng đội hình cũ") — map đội hình QT-DN-V2-001, verify bản LIVE (không archived) trước seed |
K3 |
| OG-7 | 1 PE → N phiếu | ✅ CHỐT @S164 ("PE cho nhiều, nhưng… rào hiển thị 1-1 lại — User cần thì bung ra") ⇒ BE mở N-phiếu/PE (đổi rào 2 site :342/:1201 → (PeId, ApprovalGroup)) + UI default hướng-1: PE có phiếu rồi → hiện phiếu + nút phụ "Tạo thêm cho nhóm khác" (thay 409 chặn hẳn) | K2 |
| OG-3 | NĐUQ tham khảo (máy chưa enforce — ảnh 0 số ngưỡng; enforce = wave sau khi anh cho bảng số) | ⏳ đã giải thích, chờ anh gật | — |
| OG-6 | Soát bảng transcribe 86 dòng (gõ tay từ ảnh; 4 ô ⚠️ cuối file) HOẶC anh gửi file 15-trang | ⏳ đã giải thích, chờ anh soát | K1 (seed) |
| OG-8 | Authz per-nhóm: đợt này XEM/TẠO chung 1 bộ khóa module (duyệt vẫn đúng người theo luồng); khóa-xem-theo-nhóm = wave riêng | ⏳ đã giải thích, chờ anh | — |
| OG-5 | Extract mơ hồ → hỏi khi gặp | mở | K1 |
END spec v2 — 8 wave · 8 quyết định · 6 OG · 14 vá B1b áp đủ.