diff --git a/src/components/FinishedGoodSearch/GoodPickExecutiondetail.tsx b/src/components/FinishedGoodSearch/GoodPickExecutiondetail.tsx index 19bba38..9675972 100644 --- a/src/components/FinishedGoodSearch/GoodPickExecutiondetail.tsx +++ b/src/components/FinishedGoodSearch/GoodPickExecutiondetail.tsx @@ -903,8 +903,24 @@ const fetchAllCombinedLotData = useCallback(async (userId?: number, pickOrderIdO // 将层级数据转换为平铺格式(用于表格显示) const flatLotData: any[] = []; - - mergedPickOrder.pickOrderLines.forEach((line: any) => { + + // 2/F 與後端 store_id 一致時需按 itemOrder;避免 API 未走 2F 分支時畫面仍亂序 + const doFloorKey = String(hierarchicalData.fgInfo.storeId ?? '') + .trim() + .toUpperCase() + .replace(/\//g, '') + .replace(/\s/g, ''); + const pickOrderLinesForDisplay = + doFloorKey === '2F' + ? [...(mergedPickOrder.pickOrderLines || [])].sort((a: any, b: any) => { + const ao = a.itemOrder != null ? Number(a.itemOrder) : 999999; + const bo = b.itemOrder != null ? Number(b.itemOrder) : 999999; + if (ao !== bo) return ao - bo; + return (Number(a.id) || 0) - (Number(b.id) || 0); + }) + : mergedPickOrder.pickOrderLines || []; + + pickOrderLinesForDisplay.forEach((line: any) => { // 用来记录这一行已经通过 lots 出现过的 lotId const lotIdSet = new Set(); @@ -2769,7 +2785,7 @@ const handleSubmitPickQtyWithQty = useCallback(async (lot: any, submitQty: numbe if (cumulativeQty >= lot.requiredQty) { newStatus = 'completed'; } else if (cumulativeQty > 0) { - newStatus = 'completed'; + newStatus = 'partially_completed'; } else { newStatus = 'checked'; // QR scanned but no quantity submitted yet } @@ -2786,18 +2802,12 @@ const handleSubmitPickQtyWithQty = useCallback(async (lot: any, submitQty: numbe await updateStockOutLineStatus({ id: lot.stockOutLineId, status: newStatus, - qty: cumulativeQty // Use cumulative quantity + // 后端 updateStatus 的 qty 是“增量 delta”,不能传 cumulativeQty(否则会重复累加导致 out/hold 大幅偏移) + qty: submitQty }); applyLocalStockOutLineUpdate(Number(lot.stockOutLineId), newStatus, cumulativeQty); - - if (submitQty > 0) { - await updateInventoryLotLineQuantities({ - inventoryLotLineId: lot.lotId, - qty: submitQty, - status: 'available', - operation: 'pick' - }); - } + // 注意:库存过账(hold->out)与 ledger 由后端 updateStatus 内部统一处理; + // 前端不再额外调用 updateInventoryLotLineQuantities(operation='pick'),避免 double posting。 // Check if pick order is completed when lot status becomes 'completed' if (newStatus === 'completed' && lot.pickOrderConsoCode) { diff --git a/src/components/FinishedGoodSearch/LotConfirmationModal.tsx b/src/components/FinishedGoodSearch/LotConfirmationModal.tsx index 405976c..8f18c79 100644 --- a/src/components/FinishedGoodSearch/LotConfirmationModal.tsx +++ b/src/components/FinishedGoodSearch/LotConfirmationModal.tsx @@ -42,7 +42,16 @@ const LotConfirmationModal: React.FC = ({ const { t } = useTranslation("pickOrder"); return ( - + {t("Lot Number Mismatch")} diff --git a/src/components/Jodetail/JobPickExecutionForm.tsx b/src/components/Jodetail/JobPickExecutionForm.tsx index c3b2e04..d6052d0 100644 --- a/src/components/Jodetail/JobPickExecutionForm.tsx +++ b/src/components/Jodetail/JobPickExecutionForm.tsx @@ -252,20 +252,16 @@ useEffect(() => { && (formData.badItemQty == null || formData.badItemQty === 0) && (badPackageQty === 0); - if (isNormalPick) { - if (onNormalPickSubmit) { - setLoading(true); - try { - console.log('Calling onNormalPickSubmit with:', { lot: selectedLot, submitQty: verifiedQty }); - await onNormalPickSubmit(selectedLot, verifiedQty); - onClose(); - } catch (error) { - console.error('Error submitting normal pick:', error); - } finally { - setLoading(false); - } - } else { - console.warn('onNormalPickSubmit callback not provided'); + if (isNormalPick && onNormalPickSubmit) { + setLoading(true); + try { + console.log('Calling onNormalPickSubmit with:', { lot: selectedLot, submitQty: verifiedQty }); + await onNormalPickSubmit(selectedLot, verifiedQty); + onClose(); + } catch (error) { + console.error('Error submitting normal pick:', error); + } finally { + setLoading(false); } return; } diff --git a/src/components/Jodetail/LotConfirmationModal.tsx b/src/components/Jodetail/LotConfirmationModal.tsx index de48da7..7fd61a1 100644 --- a/src/components/Jodetail/LotConfirmationModal.tsx +++ b/src/components/Jodetail/LotConfirmationModal.tsx @@ -42,7 +42,16 @@ const LotConfirmationModal: React.FC = ({ const { t } = useTranslation("pickOrder"); return ( - + {t("Lot Number Mismatch")} diff --git a/src/components/Jodetail/newJobPickExecution.tsx b/src/components/Jodetail/newJobPickExecution.tsx index 73360b9..470ddbe 100644 --- a/src/components/Jodetail/newJobPickExecution.tsx +++ b/src/components/Jodetail/newJobPickExecution.tsx @@ -861,8 +861,6 @@ const JobPickExecution: React.FC = ({ filterArgs, onBackToList }) => { try { if (!pickOrderId) { console.warn("⚠️ No pickOrderId provided, skipping API call"); - setJobOrderData(null); - setIssuePickedQtyBySolId({}); return; } @@ -1937,7 +1935,7 @@ const JobPickExecution: React.FC = ({ filterArgs, onBackToList }) => { if (cumulativeQty >= lot.requiredQty) { newStatus = "completed"; } else if (cumulativeQty > 0) { - newStatus = "completed"; + newStatus = "partially_completed"; } else { newStatus = "checked"; } @@ -1954,7 +1952,8 @@ const JobPickExecution: React.FC = ({ filterArgs, onBackToList }) => { await updateStockOutLineStatus({ id: lot.stockOutLineId, status: newStatus, - qty: cumulativeQty + // 后端 updateStatus 的 qty 是“增量 delta”,不能传 cumulativeQty(否则会重复累加导致 out/hold 大幅偏移) + qty: submitQty }); if (solId > 0) { setIssuePickedQtyBySolId((prev) => { @@ -1965,15 +1964,8 @@ const JobPickExecution: React.FC = ({ filterArgs, onBackToList }) => { }); setLocalSolStatusById(prev => ({ ...prev, [solId]: newStatus })); } - - if (submitQty > 0) { - await updateInventoryLotLineQuantities({ - inventoryLotLineId: lot.lotId, - qty: submitQty, - status: 'available', - operation: 'pick' - }); - } + // 注意:库存过账(hold->out)与 ledger 由后端 updateStatus 内部统一处理; + // 前端不再额外调用 updateInventoryLotLineQuantities(operation='pick'),避免 double posting。 // Check if pick order is completed when lot status becomes 'completed' if (newStatus === 'completed' && lot.pickOrderConsoCode) { @@ -2317,7 +2309,10 @@ const JobPickExecution: React.FC = ({ filterArgs, onBackToList }) => { setPickExecutionFormOpen(false); setSelectedLotForExecutionForm(null); - const pickOrderId = filterArgs?.pickOrderId ? Number(filterArgs.pickOrderId) : undefined; + const pickOrderId = + filterArgs?.pickOrderId + ? Number(filterArgs.pickOrderId) + : Number(selectedLotForExecutionForm?.pickOrderId || 0) || undefined; await fetchJobOrderData(pickOrderId); } catch (error) { console.error("Error submitting pick execution form:", error); @@ -3039,16 +3034,6 @@ const sortedData = [...sourceData].sort((a, b) => { }} pickOrderId={selectedLotForExecutionForm.pickOrderId} pickOrderCreateDate={new Date()} - onNormalPickSubmit={async (lot, submitQty) => { - console.log('onNormalPickSubmit called in newJobPickExecution:', { lot, submitQty }); - if (!lot) { - console.error('Lot is null or undefined'); - return; - } - const lotKey = `${lot.pickOrderLineId}-${lot.lotId}`; - handlePickQtyChange(lotKey, submitQty); - await handleSubmitPickQtyWithQty(lot, submitQty); - }} /> )}