[CLAUDE] Contract: W2 BE-DTO nền GĐ3 — ContractSourceDto reverse-join KHKK + CurrentWorkflowStepIndex + WorkflowSteps cây thô khuôn KHKK; types ×2 app khớp tên JSON BE (vá reviewer F-1/F-2)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@ -170,6 +170,67 @@ export type ContractDetail = {
|
||||
approvalWorkflowId: string | null
|
||||
currentApprovalLevelOrder: number | null
|
||||
levelOpinions: ContractLevelOpinion[] | null
|
||||
|
||||
// ========= [W2 S187 · YC-023 GĐ3] Nguồn gốc KHKK + cây quy trình V2 (3 field) ==========
|
||||
// 🔴 Khai `?` KÈM `| null` CÓ CHỦ ĐÍCH — 2 nghĩa KHÁC NHAU, đừng gộp:
|
||||
// • `undefined` (vắng key) = payload đến từ API/bundle CHƯA có W2, hoặc cache TanStack cũ;
|
||||
// • `null` = BE đã trả lời "HĐ này KHÔNG có nguồn KHKK / chưa pin quy trình".
|
||||
// BE append 3 field này ở CUỐI `ContractDetailDto` với default null (hôm nay field cuối là
|
||||
// `LevelOpinions` — `ContractDtos.cs:64`) ⇒ wire cũ không vỡ. Nơi đọc PHẢI null-check,
|
||||
// TUYỆT ĐỐI không suy "vắng field ⇒ HĐ tạo tay".
|
||||
/** HĐ kế thừa từ phiếu KHKK đã duyệt (bridge K7). HĐ tạo tay ⇒ null, FE không render card. */
|
||||
source?: ContractSource | null
|
||||
/** INDEX 0-based vào mảng `workflowSteps` (KHÔNG phải `order`) — mirror khuôn KHKK. */
|
||||
currentWorkflowStepIndex?: number | null
|
||||
/** Cây quy trình THÔ (xem `ContractWorkflowStep`). */
|
||||
workflowSteps?: ContractWorkflowStep[] | null
|
||||
}
|
||||
|
||||
// [W2 S187 · YC-023] Khối "Nguồn gốc KHKK" — BE reverse-join `ContractSigningPlanLines
|
||||
// WHERE ContractId = id` → phiếu KHKK + hạng mục + Σ tiền (spec `§2 W2(a)`). Link nằm ở
|
||||
// `ContractSigningPlanLine.ContractId`, KHÔNG có con-trỏ ngược trên `Contract` ⇒ HĐ 0 dòng
|
||||
// nối trả null.
|
||||
// ✅ FLAG-A ĐÓNG @S188 (reviewer F-1): BE đặt `Source` (`ContractDtos.cs:87`) đúng AC spec ⇒ FE
|
||||
// rename khớp JSON BE từng tên: `contractSource`→`source` · `tenHangMuc`→`tenHangMucs` ·
|
||||
// `totalApprovedAmount`→`approvedAmountTotal` (JSON bind theo TÊN; System.Text.Json camelCase).
|
||||
export type ContractSource = {
|
||||
/** Mã phiếu KHKK, vd `KHKK/2026/001`. null khi phiếu cha đã xoá mềm (F-2 — BE trả null qua global filter). */
|
||||
maKeHoach: string | null
|
||||
planId: string
|
||||
/** Nhóm duyệt N1–N8 của phiếu (Mig 71). null = phiếu không mang nhóm. */
|
||||
approvalGroup?: number | null
|
||||
/** Tên các hạng mục của phiếu đã nối sang HĐ này (có thể rỗng). */
|
||||
tenHangMucs: string[]
|
||||
/** Σ `ApprovedAmount` các dòng nối — số đã đóng băng tại choke-point finalize của phiếu. */
|
||||
approvedAmountTotal?: number | null
|
||||
/** Phiếu Duyệt NCC gốc — chuỗi PE → KHKK → HĐ. */
|
||||
purchaseEvaluationId?: string | null
|
||||
}
|
||||
|
||||
// [W2 S187] Cây quy trình THÔ do BE trả — mirror khuôn KHKK (`types/khkk.ts:275-296`, BE
|
||||
// `ContractSigningPlanFeatures.cs:131-152`).
|
||||
// 🔴 KHÁC PE: BE **KHÔNG** precompute `status` Done/Current/Pending. FE tự suy từ CẶP con-trỏ
|
||||
// `currentWorkflowStepIndex` (INDEX 0-based vào mảng steps) + `currentApprovalLevelOrder`
|
||||
// (GIÁ TRỊ `level.order`, KHÔNG phải index).
|
||||
export type ContractWorkflowLevel = {
|
||||
id: string
|
||||
order: number
|
||||
name: string | null
|
||||
approverUserId: string
|
||||
approverFullName: string | null
|
||||
/** Cờ per-Cấp "được KẾT THÚC quy trình tại cấp này" — spec `§2 W2(b)` gọi là "cờ per-level". */
|
||||
allowApproverFinalize: boolean
|
||||
}
|
||||
|
||||
export type ContractWorkflowStep = {
|
||||
id: string
|
||||
order: number
|
||||
name: string
|
||||
levels: ContractWorkflowLevel[]
|
||||
// 2 field dưới có trong khuôn KHKK nhưng spec W2 KHÔNG nêu tên ⇒ khai `?` để nơi đọc buộc
|
||||
// null-check, thay vì hứa một field payload có thể không mang (bài học `khkk.ts:403-407`).
|
||||
departmentId?: string | null
|
||||
departmentName?: string | null
|
||||
}
|
||||
|
||||
// [Plan B S29 2026-05-22 Chunk E3] Mirror BE ContractLevelOpinionDto 12 fields.
|
||||
|
||||
Reference in New Issue
Block a user