import { TFunction } from "i18next"; import { createTraceLabelTranslator } from "./traceLabelUtils"; import { formatQty } from "./traceQtyUtils"; import type { JoPreludeGraphLabels } from "./buildJoPreludeGraphNodes"; import type { ProductionGraphLabels } from "./buildProductionGraphNodes"; import type { ExtendedTraceGraphLabels } from "./buildExtendedTraceGraphNodes"; import type { TraceGraphDetailLabels } from "./buildTraceGraphNodes"; export type TraceGraphCompileLabels = TraceGraphDetailLabels & JoPreludeGraphLabels & ProductionGraphLabels & ExtendedTraceGraphLabels & { flowDoGroupTitle?: (count: number) => string; flowPickGroupTitle?: (pickOrderCode: string, count: number) => string; }; export const buildTraceGraphLabels = ( t: TFunction, lotUom: string, ): TraceGraphCompileLabels => { const tr = createTraceLabelTranslator(t); return { tr, nodeQcPass: t("nodeQcPass"), nodeQcFail: t("nodeQcFail"), nodeReceipt: t("nodeReceipt"), nodePurchase: t("nodePurchase"), nodePutaway: t("nodePutaway"), nodePutawayTransfer: t("nodePutawayTransfer"), putawayTransferDetail: t("putawayTransferInboundDetail"), nodeStockTake: t("nodeStockTake"), nodeAdjustment: t("nodeAdjustment"), nodeTransfer: t("nodeTransfer"), nodeMaterialIn: t("nodeMaterialIn"), nodeJoCreated: t("nodeJoCreated"), nodeMaterialPick: t("nodeMaterialPick"), nodeProductionStep: t("nodeProductionStep"), nodeByproduct: t("nodeByproduct"), nodeScrap: t("nodeScrap"), nodeDefect: t("nodeDefect"), detailProcessOutputQty: t("processOutputQty"), detailProcessScrapQty: t("processScrapQty"), detailProcessDefectQty: t("processDefectQty"), nodeOpen: t("nodeOpen"), nodeFail: t("nodeFail"), nodeDoOut: t("nodeDoOut"), nodeReplenishmentCreated: t("nodeReplenishmentCreated"), nodeJoOut: t("nodeJoOut"), nodePoOut: t("nodePoOut"), doOutboundExtra: t("doOutboundExtra"), doOutboundReplenish: t("doOutboundReplenish"), detailDoOutboundKind: t("detailDoOutboundKind"), flowDoGroupTitle: (count: number) => t("flowDoGroupTitle", { count }), flowPickGroupTitle: (pickOrderCode: string, count: number) => t("flowPickGroupTitle", { pickOrderCode, count }), nodeReturn: t("nodeReturn"), nodeRepack: t("nodeRepack"), traceRepackLot: t("traceRepackLot"), nodeExpired: t("nodeExpired"), nodeDepleted: t("nodeDepleted"), directionIn: t("directionIn"), directionOut: t("directionOut"), formatQcSubtitle: (failQty: number, acceptedQty: number) => `${t("failQty")}: ${formatQty(failQty, lotUom)} / ${t("acceptedQty")}: ${formatQty(acceptedQty, lotUom)}`, detailQty: t("qty"), detailTime: t("timestamp"), detailHandler: t("handler"), detailStockTaker: t("stockTaker"), detailApprover: t("approver"), detailWarehouse: t("from"), detailRemarks: t("remarks"), detailFailCategory: t("detailFailCategory"), detailProcessDescription: t("detailProcessDescription"), detailType: t("type"), detailRef: t("ref"), detailStockTakeCode: t("stockTakeCode"), detailAdjustmentRef: t("detailAdjustmentRef"), detailReplenishmentCode: t("detailReplenishmentCode"), detailReason: t("detailReason"), detailReturnRef: t("detailReturnRef"), detailSourceDoc: t("detailSourceDoc"), detailPurchaseOrderNo: t("detailPurchaseOrderNo"), detailInboundRef: t("detailInboundRef"), detailInboundSiNo: t("detailInboundSiNo"), detailPutawayBin: t("detailPutawayBin"), detailDirection: t("detailDirection"), detailStatus: t("status"), detailSupplier: t("supplier"), detailMaterial: t("material"), detailItemCode: t("detailItemCode"), detailItemName: t("detailItemName"), detailLot: t("lotNo"), detailAcceptedQty: t("acceptedQty"), detailFailQty: t("failQty"), detailQcCriteria: t("detailQcCriteria"), detailQcType: t("detailQcType"), detailQcUnknownItem: t("detailQcUnknownItem"), detailFrom: t("from"), detailTo: t("to"), detailVariance: t("variance"), detailBefore: t("before"), detailAfter: t("after"), detailStockTakeFirstCount: t("stockTakeStageFirstCount"), detailStockTakeSecondCount: t("stockTakeStageSecondCount"), detailStockTakeApproverCount: t("stockTakeStageApproverCount"), detailScrapQty: t("scrapQty"), detailDefectQty: t("defectQty"), detailEquipment: t("equipment"), detailProcessStep: t("processStep"), detailStepMaterials: t("detailStepMaterials"), detailAssignedStep: t("detailAssignedStep"), detailPickTargetDate: t("detailPickTargetDate"), detailProductLotNo: t("productLotNo"), deliveryOrder: t("deliveryOrder"), deliveryNoteCode: t("deliveryNoteCode"), ticketNo: t("ticketNo"), pickOrder: t("pickOrder"), jobOrder: t("jobOrder"), expiryDate: t("expiryDate"), totalAvailable: t("totalAvailable"), itemCode: t("itemCode"), detailOrderQty: t("detailOrderQty"), detailPutAwayQty: t("detailPutAwayQty"), detailPurchaseUnit: t("detailPurchaseUnit"), detailSupplyTo: t("detailSupplyTo"), detailStockTakeRound: t("detailStockTakeRound"), detailStockTakeSection: t("detailStockTakeSection"), detailLocation: t("detailLocation"), categoryPurchase: t("categoryPurchase"), categoryProduction: t("categoryProduction"), categoryInbound: t("phaseInbound"), categoryReceipt: t("categoryReceipt"), categoryPutaway: t("phasePutaway"), categoryTransfer: t("phaseWarehouse"), categoryStockTake: t("phaseStockTake"), categoryOpen: t("categoryOpen"), categoryAdjustment: t("nodeAdjustment"), categoryPick: t("phaseMaterialPick"), categoryQc: t("phaseQc"), categoryOutbound: t("phaseOutbound"), categoryTerminal: t("categoryTerminal"), processingStatus: t("processingStatus"), matchStatus: t("matchStatus"), }; }; /** Minimal labels for unit tests (no i18n). */ export const createTestTraceGraphLabels = (): TraceGraphCompileLabels => { const identity = (s: string | null | undefined) => s?.trim() || "—"; const tr = { refType: identity, movementType: identity, direction: (c: string | null | undefined) => c?.toUpperCase() === "OUT" ? "Out" : c?.toUpperCase() === "IN" ? "In" : identity(c), stockInStatus: identity, adjustmentType: identity, usageType: identity, failType: identity, productionStatus: identity, pickStatus: identity, joStatus: identity, qcType: () => "IQC", qcPassed: (p: boolean) => (p ? "Pass" : "Fail"), putawayShelfStatus: (phase: "pending" | "completed") => phase === "completed" ? "Put away done" : "Pending put-away", processingStatus: identity, matchStatus: identity, lotLineStatus: identity, }; return { tr, nodeQcPass: "QC Pass", nodeQcFail: "QC Fail", nodeReceipt: "Receipt", nodePurchase: "Purchase", nodePutaway: "Putaway", nodePutawayTransfer: "Transfer inbound", putawayTransferDetail: "Inbound at target warehouse after transfer (auto-completed, not PO put-away queue)", nodeStockTake: "Stock take", nodeAdjustment: "Adjustment", nodeTransfer: "Transfer", nodeMaterialIn: "Material in", nodeJoCreated: "JO created", nodeMaterialPick: "Material pick", nodeProductionStep: "Production step", nodeByproduct: "Byproduct", nodeScrap: "Scrap", nodeDefect: "Defect", detailProcessOutputQty: "Process output", detailProcessScrapQty: "Scrap quantity", detailProcessDefectQty: "Defect quantity", nodeOpen: "Opening", nodeFail: "Pick fail", nodeDoOut: "DO PO", nodeReplenishmentCreated: "Replenishment created", nodeJoOut: "JO PO", nodePoOut: "PO pick", doOutboundExtra: "Add-on", doOutboundReplenish: "Replenishment", detailDoOutboundKind: "Outbound type", flowDoGroupTitle: (count) => `DO × ${count}`, flowPickGroupTitle: (code, count) => `Pick · ${code} × ${count}`, nodeReturn: "Return", nodeRepack: "Repack", traceRepackLot: "Trace lot", nodeExpired: "Expired", nodeDepleted: "Depleted", directionIn: "In", directionOut: "Out", formatQcSubtitle: (f, a) => `Fail ${f} / Accepted ${a}`, detailQty: "Qty", detailTime: "Time", detailHandler: "Handler", detailStockTaker: "First counter", detailApprover: "Approver", detailWarehouse: "Warehouse", detailRemarks: "Remarks", detailFailCategory: "Fail category", detailProcessDescription: "Step description", detailType: "Type", detailRef: "Doc no.", detailStockTakeCode: "Stock Take #", detailAdjustmentRef: "Adjustment #", detailReplenishmentCode: "Replenishment #", detailReason: "Reason", detailReturnRef: "Return #", detailSourceDoc: "Source doc #", detailPurchaseOrderNo: "PO no.", detailInboundRef: "Inbound SI", detailInboundSiNo: "Inbound SI no.", detailPutawayBin: "Bin", detailDirection: "Direction", detailStatus: "Status", detailSupplier: "Supplier", detailMaterial: "Material", detailItemCode: "Item code", detailItemName: "Item name", detailLot: "Lot", detailAcceptedQty: "Accepted", detailFailQty: "Fail", detailQcCriteria: "Criteria", detailQcType: "QC type", detailQcUnknownItem: "Unknown", detailFrom: "From", detailTo: "To", detailVariance: "Variance", detailBefore: "Book qty", detailAfter: "Accepted qty", detailStockTakeFirstCount: "First count", detailStockTakeSecondCount: "Re-count", detailStockTakeApproverCount: "Approver count", detailScrapQty: "Scrap", detailDefectQty: "Defect", detailEquipment: "Equipment", detailProcessStep: "Step", detailStepMaterials: "Step materials", detailAssignedStep: "Assigned step", detailPickTargetDate: "Target date", detailProductLotNo: "Product lot", deliveryOrder: "DO", deliveryNoteCode: "DN", ticketNo: "Ticket", pickOrder: "Pick", jobOrder: "Job order", expiryDate: "Expiry", totalAvailable: "Available", itemCode: "Item code", detailOrderQty: "Order qty", detailPutAwayQty: "Putaway qty", detailPurchaseUnit: "Purchase unit", detailSupplyTo: "Supply to", detailStockTakeRound: "Stock take round", detailStockTakeSection: "Stock take section", detailLocation: "Location", categoryPurchase: "Purchase", categoryProduction: "Production", categoryInbound: "Inbound", categoryReceipt: "Receipt", categoryPutaway: "Putaway", categoryTransfer: "Warehouse", categoryStockTake: "Stock take", categoryOpen: "Opening", categoryAdjustment: "Adjustment", categoryPick: "Pick", categoryQc: "QC", categoryOutbound: "Outbound", categoryTerminal: "Terminal", processingStatus: "Processing status", matchStatus: "Match status", }; };