4.6 KiB
4.6 KiB
SPEC WAVE-5 — Cầu KHKK→Hợp đồng + pin V2 (GĐ2→GĐ3, sửa bridge cũ 1 file)
Nguồn: spec cũ §2.5 + §③ WAVE-5 (
:397-403) + lane-2 §2 (chi tiết nhất). Anh ĐÃ MỞ gate chạm HĐ @S160 (run.md ④). Defaults plan cha #2 (giá KH thắng) + #3 (Q11 cảnh báo mềm). Chạy SAU W3 + W6.
① TÍNH NĂNG / ĐỀ BÀI
Từ phiếu KHKK DaDuyet, tạo HĐ per-winner với giá = ApprovedAmount của đúng NCC (thay SUM báo giá PE), HĐ pin workflow V2 để trình được ngay (hết kẹt ConflictException). SỬA BRIDGE CŨ — KHÔNG đẻ endpoint mới (lane-2 §2c: 2 endpoint cùng nghĩa = lớp lỗi 2-site S155).
② CÁCH IMPLEMENT
- Gate 5-anchor (§③-A).
CreateContractFromEvaluationFeatures.cs(file DUY NHẤT phía BE logic): (a) đọc planDaDuyetcủa PE (Plans.Where(PurchaseEvaluationId==peId && Phase==DaDuyet)) — CÓ:giaTri = line.ApprovedAmountkhớpw.SupplierIdthaySUM :88-90, ghi ContextNote lệch "giá KH x vs SUM-PE y" vào changelog (khuôn:121-140, bài D4 S134); KHÔNG có: giữ SUM + cảnh báo mềm trong response (Q11 default). (b)+param ApprovalWorkflowId?vào command + body recordPurchaseEvaluationsController.cs:379-382(🔴 record-count controller == command — bài 10-point checklist) → pin V2 cho HĐ tạo ra; không truyền → fallback hiện trạng V1 + warning. 🔴 GIỮ guardApplicableType==Contract(review F-B6): cửa-1 chống forge đã cóContractFeatures.cs:84-86+ comment:77-78(chặn attacker forge PE-workflow-id type 1/2); pin ở bridge phải qua CÙNG guard đó — CẤM pin thẳng workflow type 1/2/10 vào HĐ. Test canhCreateContractCommandApplicableTypeTests(đã có) + ca ÂM mới. (c) 🆕 ghi ngượcLine.ContractId = contract.Idper-winner trong vòng lặp:82-115(cột C6 sẵn từ W1). (d) GIỮ nguyên: guard:53-60· idempotencype.ContractId :145· atomic codegen:78-82· mapping:101-107.- FE ×2 app: màn KHKK Detail (phiếu DaDuyet) thêm nút "Tạo Hợp đồng" deep-link gọi CÙNG endpoint
POST /api/purchase-evaluations/{peId}/create-contract(+field chọn workflow V2 cho HĐ). Màn PE giữ nút cũ (2 đường song song — Q11 default). - Test-before 4 test (§③-B) + build ×2 + commit. ⚠️ Đây là commit CHẠM module Contract đầu tiên — cicd verify kỹ (endpoint 401-control-404, khuôn đợt-5).
③ CHECKLIST
A. Gate 5-anchor: CreateContractFromEvaluationFeatures.cs:53-60 (guard) · :68-71 (pin V1-only) · :88-90 (SUM) · :145 (idempotency) · ContractWorkflowService.cs:115-116 (ConflictException kẹt V2-less).
B. Acceptance (lane-2 §7-W7 + spec cũ W5):
- 5 test tồn tại ĐÚNG TÊN (khuôn repo English-predicate) trong
ContractSigningPlanBridgeTests:CreateContract_WithApprovedPlan_SetsGiaTri_ToApprovedAmountPerSupplier·CreateContract_NoPlan_KeepsSumOfPeQuotes_AndWarnsSoft·CreateContract_PinsV2Workflow_ContractReachesLevelOneOnSubmit·CreateContract_WritesBackLineContractId_PerWinner·CreateContract_ForgePeWorkflowId_ThrowsApplicableTypeGuard(ca ÂM forge — F-B6). dotnet testPASS 0 fail, số-sau ≥ baseline + 5;CreateContractFromEvaluationMultiWinnerTests+CreateContractCommandApplicableTypeTests(ĐÃ TỒN TẠI) VẪN XANH — chống hồi quy multi-winner + forge.- TÍNH-CHẤT: PE có W winner + plan DaDuyet →
POST create-contracttrả đúng W contractId; MỖI HĐgiaTri == ApprovedAmountcủa Line cùng supplierId; tổng W HĐ == SUM(ApprovedAmount) toàn plan. - 🔴 Prod curl (ZZTEST) — CHẠY TỚI LƯỢT DUYỆT, KHÔNG dừng ở trình (review F-B5: nhánh trình
ContractWorkflowService.cs:70-89KHÔNG đọc workflow ⇒ "204 KHÔNG 409" PASS SẴN, 0-bit): HĐ tạo vớiApprovalWorkflowIdV2 →GET /{id}cócurrentApprovalLevelOrder=1(vế có răng — chứng pin V2 ăn); → Cấp-1 approverPOST /{id}/transitionsduyệt → tiến Bước 2. HĐ tạo KHÔNG workflow → trình vẫn 204 (đường cũ) nhưngcurrentApprovalLevelOrder=null. - Changelog có ContextNote chứa CẢ 2 số khi giá KH ≠ SUM-PE.
- FE build ×2 · cicd 3-chân-kiềng.
C. Rủi ro: [ ] KHÔNG sửa lệch phép SUM cũ cho PE-không-plan (đường cũ phải y nguyên — test #2 canh) · [ ] body record lệch count controller↔command (silent 400) · [ ] 🔴 dry-run CẤM tạo HĐ
HopDongMuaBan— không mã "MB" nào được sinh (anh bỏ MB @S161, plan cha default #7; codegen giữ nguyên chờ format thay).