diff --git a/src/components/Qc/QcStockInModal.tsx b/src/components/Qc/QcStockInModal.tsx index b0c8c85..6d93615 100644 --- a/src/components/Qc/QcStockInModal.tsx +++ b/src/components/Qc/QcStockInModal.tsx @@ -42,6 +42,7 @@ import FgStockInForm from "../StockIn/FgStockInForm"; import LoadingComponent from "../General/LoadingComponent"; import { printFGStockInLabel, PrintFGStockInLabelRequest, fetchFGStockInLabel } from "@/app/api/jo/actions"; import { fetchItemForPutAway } from "@/app/api/stockIn/actions"; +import { fetchWarehouseListClient } from "@/app/api/warehouse/client"; const style = { position: "absolute", top: "50%", @@ -97,6 +98,7 @@ const QcStockInModal: React.FC = ({ const [isSubmitting, setIsSubmitting] = useState(false); // const [skipQc, setSkipQc] = useState(false); // const [viewOnly, setViewOnly] = useState(false); + const [itemLocationCode, setItemLocationCode] = useState(null); const printerStorageKey = useMemo( () => `qcStockInModal_selectedPrinterId_${session?.id ?? "guest"}`, @@ -340,10 +342,11 @@ const QcStockInModal: React.FC = ({ // } // Get QC data from the shared form context - const qcAccept = data.qcDecision == 1; + const qcAcceptLocal = data.qcDecision == 1; + // const qcAccept = data.qcAccept; - let acceptQty = Number(data.acceptQty); - const qcResults = data.qcResult?.filter((qc) => qc.escalationLogId === undefined) || []; // Remove old QC data + let acceptQtyLocal = Number(data.acceptQty); + const qcResultsLocal = data.qcResult?.filter((qc) => qc.escalationLogId === undefined) || []; // Remove old QC data // const qcResults = data.qcResult as PurchaseQcResult[]; // qcItems; // const qcResults = viewOnly? data.qcResult as PurchaseQcResult[] : qcItems; @@ -352,7 +355,7 @@ const QcStockInModal: React.FC = ({ // Check if failed items have failed quantity - const failedItemsWithoutQty = qcResults.filter(item => + const failedItemsWithoutQty = qcResultsLocal.filter(item => item.qcPassed === false && (!item.failQty || item.failQty <= 0) ); if (failedItemsWithoutQty.length > 0) { @@ -368,9 +371,9 @@ const QcStockInModal: React.FC = ({ // Check if accept quantity is valid if (data.qcDecision == 2) { - acceptQty = 0; + acceptQtyLocal = 0; } else { - if (acceptQty === undefined || acceptQty <= 0) { + if (acceptQtyLocal === undefined || acceptQtyLocal <= 0) { validationErrors.push("Accept quantity must be greater than 0"); } } @@ -383,7 +386,7 @@ const QcStockInModal: React.FC = ({ alert("請輸入到期日!"); return; } - if (!qcResults.every((qc) => qc.qcPassed) && qcAccept && stockInLineInfo?.status != StockInStatus.ESCALATED) { //TODO: fix it please! + if (!qcResultsLocal.every((qc) => qc.qcPassed) && qcAcceptLocal && stockInLineInfo?.status != StockInStatus.ESCALATED) { //TODO: fix it please! validationErrors.push("有不合格檢查項目,無法收貨!"); // submitDialogWithWarning(() => postStockInLineWithQc(qcData), t, {title:"有不合格檢查項目,確認接受收貨?", // confirmButtonText: t("confirm putaway"), html: ""}); @@ -391,7 +394,7 @@ const QcStockInModal: React.FC = ({ } // Check if all QC items have results - const itemsWithoutResult = qcResults.filter(item => item.qcPassed === undefined); + const itemsWithoutResult = qcResultsLocal.filter(item => item.qcPassed === undefined); if (itemsWithoutResult.length > 0 && stockInLineInfo?.status != StockInStatus.ESCALATED) { //TODO: fix it please! validationErrors.push(`${t("QC items without result")}`); @@ -412,13 +415,13 @@ const QcStockInModal: React.FC = ({ expiryDate : data.expiryDate ? (Array.isArray(data.expiryDate) ? arrayToDateString(data.expiryDate, "input") : data.expiryDate) : undefined, receiptDate : data.receiptDate ? (Array.isArray(data.receiptDate) ? arrayToDateString(data.receiptDate, "input") : data.receiptDate) : undefined, - qcAccept: qcAccept? qcAccept : false, - acceptQty: acceptQty? acceptQty : 0, + qcAccept: qcAcceptLocal ? qcAcceptLocal : false, + acceptQty: acceptQtyLocal ? acceptQtyLocal : 0, // For Job Order QC, allow updating received qty beyond demand/accepted. // Backend uses request.acceptedQty in QC flow, so we must send it explicitly. - acceptedQty: (qcAccept && isJobOrderSource) ? (acceptQty ? acceptQty : 0) : stockInLineInfo?.acceptedQty, + acceptedQty: (qcAcceptLocal && isJobOrderSource) ? (acceptQtyLocal ? acceptQtyLocal : 0) : stockInLineInfo?.acceptedQty, // qcResult: itemDetail.status != "escalated" ? qcResults.map(item => ({ - qcResult: qcResults.map(item => ({ + qcResult: qcResultsLocal.map(item => ({ // id: item.id, qcItemId: item.qcItemId, // code: item.code, @@ -462,22 +465,43 @@ const QcStockInModal: React.FC = ({ // submitDialogWithWarning(onOpenPutaway, t, {title:"Save success, confirm to proceed?", // confirmButtonText: t("confirm putaway"), html: ""}); // onOpenPutaway(); - const isJobOrderBom = (stockInLineInfo?.jobOrderId != null || printSource === "productionProcess") - && stockInLineInfo?.bomDescription === "WIP"; + const isJobOrderSource = (stockInLineInfo?.jobOrderId != null || printSource === "productionProcess"); + const isWipBom = isJobOrderSource && stockInLineInfo?.bomDescription === "WIP"; + const isFgBom = isJobOrderSource && stockInLineInfo?.bomDescription === "FG"; const isFaItem = (stockInLineInfo?.itemNo ?? "").toUpperCase().includes("FA"); - const shouldAutoPutaway = isJobOrderBom || isFaItem; + const shouldAutoPutaway = isWipBom || isFgBom || isFaItem; if (shouldAutoPutaway) { // Auto putaway to default warehouse - const defaultWarehouseId = stockInLineInfo?.defaultWarehouseId ?? 1141; - + const loc = (itemLocationCode ?? "").trim().toUpperCase(); + const warehouseListForLookup = + isFgBom && ((warehouse?.length ?? 0) === 0) + ? await fetchWarehouseListClient() + : (warehouse ?? []); + const matchedWarehouse = + isFgBom && loc.length > 0 + ? warehouseListForLookup.find((w) => (w.code ?? "").trim().toUpperCase().endsWith(loc)) + : undefined; + const resolvedWarehouseId = + (isFgBom ? matchedWarehouse?.id : undefined) + ?? stockInLineInfo?.defaultWarehouseId + ?? 1141; + + console.log("[AUTO_PUTAWAY_DEBUG]", { + silId: stockInLineInfo?.id, + bomDescription: stockInLineInfo?.bomDescription, + isJobOrderSource, + isWipBom, + isFgBom, + isFaItem, + itemLocationCode, + loc, + warehouseCount: warehouse?.length, + matchedWarehouse: matchedWarehouse ? { id: matchedWarehouse.id, code: matchedWarehouse.code } : null, + defaultWarehouseId: stockInLineInfo?.defaultWarehouseId, + resolvedWarehouseId, + }); // Get warehouse name from warehouse prop or use default - let defaultWarehouseName = "2F-W200-#A-00"; // Default warehouse name - if (warehouse && warehouse.length > 0) { - const defaultWarehouse = warehouse.find(w => w.id === defaultWarehouseId); - if (defaultWarehouse) { - defaultWarehouseName = `${defaultWarehouse.code} - ${defaultWarehouse.name}`; - } - } + // Create putaway data const putawayData = { @@ -485,19 +509,26 @@ const QcStockInModal: React.FC = ({ itemId: stockInLineInfo?.itemId, // Include Item ID purchaseOrderId: stockInLineInfo?.purchaseOrderId, // Include PO ID if exists purchaseOrderLineId: stockInLineInfo?.purchaseOrderLineId, // Include POL ID if exists - acceptedQty: acceptQty, // Keep in sync with QC acceptQty - acceptQty: acceptQty, // Putaway quantity - warehouseId: defaultWarehouseId, + acceptedQty: acceptQtyLocal, // Keep in sync with QC acceptQty + acceptQty: acceptQtyLocal, // Putaway quantity + warehouseId: resolvedWarehouseId, status: "received", // Use string like PutAwayModal productionDate: data.productionDate ? (Array.isArray(data.productionDate) ? arrayToDateString(data.productionDate, "input") : data.productionDate) : undefined, expiryDate: data.expiryDate ? (Array.isArray(data.expiryDate) ? arrayToDateString(data.expiryDate, "input") : data.expiryDate) : undefined, receiptDate: data.receiptDate ? (Array.isArray(data.receiptDate) ? arrayToDateString(data.receiptDate, "input") : data.receiptDate) : undefined, inventoryLotLines: [{ - warehouseId: defaultWarehouseId, - qty: acceptQty, // Putaway qty + warehouseId: resolvedWarehouseId, + qty: acceptQtyLocal, // Putaway qty }], } as StockInLineEntry & ModalFormInput; - + console.log("[AUTO_PUTAWAY]", { + isFgBom, + itemLocationCode, + loc, + warehouseCount: warehouse?.length, + matchedWarehouse: isFgBom ? warehouse?.find(w => (w.code ?? "").trim().toUpperCase().endsWith(loc)) : null, + resolvedWarehouseId, + }); try { // Use updateStockInLine directly like PutAwayModal does const res = await updateStockInLine(putawayData); @@ -510,6 +541,7 @@ const QcStockInModal: React.FC = ({ } } + closeWithResult(qcRes); // setTabIndex(1); // Need to go Putaway tab? } else { @@ -520,7 +552,15 @@ const QcStockInModal: React.FC = ({ return ; }, - [onOpenPutaway, formProps.formState.errors], + [ + stockInLineInfo, + printSource, + skipQc, + warehouse, + itemLocationCode, + closeWithResult, + t, + ], ); const postStockInLine = useCallback(async (args: ModalFormInput) => {