Files
solution-erp/.claude/workflows/runs/2026-07-29-S161-khkk-w3-duyet/sub-implementer-frontend-1.md
2026-07-29 21:49:38 +07:00

3.7 KiB
Raw Blame History

sub-implementer-frontend-1 — W3 ĐỢT-1b: FE panel duyệt KHKK ×2 app (S161, 2026-07-29)

Ghi TỪNG MỤC trong lúc làm (chống #53). Task: panel KhkkWorkflowPanel.tsx + gắn DetailPage + types transitions, SHA-pair ×2 app, build ×2. BE logic W3 CHƯA có (task 1 skeleton song song) ⇒ bấm nút sẽ 404/500 — CHẤP NHẬN đợt này.

MỤC 0 — Baseline SHA (trước khi sửa)

340e64d0…  fe-user/src/types/khkk.ts            = fe-admin  (PAIR OK)
9b91606e…  fe-user/src/pages/khkk/KhkkDetailPage.tsx = fe-admin  (PAIR OK)

MỤC 1 — RECON: field THẬT của detail DTO (BE đĩa, KHÔNG suy)

Nguồn: src/Backend/SolutionErp.Application/ContractSigningPlans/ContractSigningPlanFeatures.cs

Cái Bằng chứng Ghi chú
ContractSigningPlanDetailDto :119-147 field CUỐI = List<ContractSigningPlanWorkflowStepDto> WorkflowSteps :147
ContractSigningPlanWorkflowStepDto(Id, Order, Name, DepartmentId, Levels) :112-117 KHÔNG có DepartmentName, KHÔNG có Status
ContractSigningPlanWorkflowLevelDto(Id, Order, Name, ApproverUserId, ApproverFullName) :105-110 KHÔNG có Status, KHÔNG có allowApproverFinalize (W1 rào type-10)
ContractSigningPlanLevelOpinionDto :93-103 ApproverUserId (:99) — FE types W2 THIẾU field này ⇒ bổ sung
con-trỏ đôi :136-137 CurrentWorkflowStepIndex + CurrentApprovalLevelOrder
Tree build :537-566 Steps sort Order, Levels sort Order, ApproverFullName join Users :549-552

🔴 KHÁC PE CĂN BẢN — đây là điểm dễ đứt nhất của wave này: PE trả approvalFlow đã có sẵn status: 'Done'|'Current'|'Pending' per Bước/Cấp (BE precompute). KHKK trả CÂY THÔ, KHÔNG status ⇒ FE phải tự suy trạng thái từ con-trỏ đôi. Không có field status nào để đọc.

🔴 Ngữ nghĩa con-trỏ (BE tự khai, :224-226): CurrentWorkflowStepIndexINDEX 0-based vào list Steps đã sort theo Order — KHÔNG phải Order. CurrentApprovalLevelOrderGIÁ TRỊ Level.Order. Luật so khớp OR-of-N canonical BE :259-260: steps[idx].Levels.Any(l => l.Order == CurrentApprovalLevelOrder && l.ApproverUserId == userId) ⇒ FE mirror ĐÚNG vị ngữ này (nhiều Level cùng Order = OR-of-N; lấy .some(), KHÔNG .find() 1 người).

Rào XEM BE :184-195 (EnsureCanViewAsync): Admin drafter (phase ≠ DangSoanThao ∧ approver-của-workflow-đã-pin). ⇒ phiếu Nháp approver KHÔNG đọc được; TraLai thì đọc được.

Endpoint transitions: CHƯA có trong controller (ContractSigningPlansController.cs grep HttpPost → chỉ /, /{id}/dossier-items, /{id}/attachments). Đúng như đề bài: đợt-1 FE đi trước BE.

MỤC 2 — Khuôn PE panel: cái GIỮ / cái BỎ

Nguồn fe-user/src/components/pe/PeWorkflowPanel.tsx (1063 dòng).

GIỮ (mirror): sơ đồ Bước→Cấp ✓/●/○ :381-478 · banner đến-lượt :489-508 (actorInV2Level/blockedByV2Level :109-114) · nút 3 màu emerald/amber/red :546-562 · Dialog + ô ý kiến :869-870 · useAuth() lấy actor :66-67 · qc.invalidateQueries + toast.error(getErrorMessage(e)) :288.

BỎ (đơn-giản-hoá theo lệnh): price-picker :794-820 · budget/pendingPriors :170-180 · file-đính-kèm-khi-duyệt :823-868 · 4 return-mode radio :635-713 (W3 = TraLai toàn phần, spec §②-3(c)) · skipToFinal/finalizeByCcm/ applyLevelFinalize :57-63 (spec §②-3(b): CẤM port 2 đường kết thúc sớm) · xóa-mềm-bởi-approver :295-312.