|
|
|
@@ -1,3 +1,4 @@ |
|
|
|
/* |
|
|
|
"use client"; |
|
|
|
|
|
|
|
import { |
|
|
|
@@ -52,7 +53,6 @@ import { |
|
|
|
fetchDoPickOrderDetail, // 必须添加 |
|
|
|
DoPickOrderDetail, // 必须添加 |
|
|
|
fetchFGPickOrdersByUserId, |
|
|
|
batchQrSubmit, |
|
|
|
batchSubmitList, // 添加:导入 batchSubmitList |
|
|
|
batchSubmitListRequest, // 添加:导入类型 |
|
|
|
batchSubmitListLineRequest, |
|
|
|
@@ -105,7 +105,7 @@ type LotConfirmRunContext = { |
|
|
|
selectedLotForQr: any; // 與現在一樣:含 pickOrderLineId, stockOutLineId, suggestedPickLotId, itemId… |
|
|
|
}; |
|
|
|
|
|
|
|
/** 同物料多行时,优先对「有建议批次号」的行做替换,避免误选「无批次/不足」行 */ |
|
|
|
/** 同物料多行时,优先对「有建议批次号」的行做替换,避免误选「无批次/不足」行 |
|
|
|
function pickExpectedLotForSubstitution( |
|
|
|
activeSuggestedLots: any[], |
|
|
|
): any | null { |
|
|
|
@@ -630,19 +630,19 @@ const ManualLotConfirmationModal: React.FC<{ |
|
|
|
); |
|
|
|
}; |
|
|
|
|
|
|
|
/** 過期批號(未換有效批前):與 noLot 類似——單筆/批量預設提交量為 0,除非 Issue 改數 */ |
|
|
|
/** 過期批號(未換有效批前):與 noLot 類似——單筆/批量預設提交量為 0,除非 Issue 改數 |
|
|
|
function isLotAvailabilityExpired(lot: any): boolean { |
|
|
|
return String(lot?.lotAvailability || "").toLowerCase() === "expired"; |
|
|
|
} |
|
|
|
|
|
|
|
/** inventory_lot_line.status = unavailable(API 可能用 lotAvailability 或 lotStatus) */ |
|
|
|
/** inventory_lot_line.status = unavailable(API 可能用 lotAvailability 或 lotStatus) |
|
|
|
function isInventoryLotLineUnavailable(lot: any): boolean { |
|
|
|
if (!lot) return false; |
|
|
|
if (lot.lotAvailability === "status_unavailable") return true; |
|
|
|
return String(lot.lotStatus || "").toLowerCase() === "unavailable"; |
|
|
|
} |
|
|
|
|
|
|
|
/** Issue「改數」未寫入 SOL,刷新/換頁後需靠 session 還原,否則 Qty will submit 會回到 req */ |
|
|
|
/** Issue「改數」未寫入 SOL,刷新/換頁後需靠 session 還原,否則 Qty will submit 會回到 req |
|
|
|
const FG_ISSUE_PICKED_KEY = (doPickOrderId: number) => |
|
|
|
`fpsms-fg-issuePickedQty:${doPickOrderId}`; |
|
|
|
|
|
|
|
@@ -768,7 +768,7 @@ const PickExecution: React.FC<Props> = ({ |
|
|
|
const [lotConfirmationError, setLotConfirmationError] = useState< |
|
|
|
string | null |
|
|
|
>(null); |
|
|
|
/** QR 静默换批失败时显示在对应行的 Lot# 列,key = stockOutLineId */ |
|
|
|
/** QR 静默换批失败时显示在对应行的 Lot# 列,key = stockOutLineId |
|
|
|
const [lotSwitchFailByStockOutLineId, setLotSwitchFailByStockOutLineId] = |
|
|
|
useState<Record<number, string>>({}); |
|
|
|
const [expectedLotData, setExpectedLotData] = useState<any>(null); |
|
|
|
@@ -1232,7 +1232,7 @@ const PickExecution: React.FC<Props> = ({ |
|
|
|
pickOrderLinesForDisplay.forEach((line: any) => { |
|
|
|
// 用来记录这一行已经通过 lots 出现过的 lotId |
|
|
|
const lotIdSet = new Set<number>(); |
|
|
|
/** 已由有批次建議分配的量(加總後與 pick_order_line.requiredQty 的差額 = 無批次列應顯示的數) */ |
|
|
|
/** 已由有批次建議分配的量(加總後與 pick_order_line.requiredQty 的差額 = 無批次列應顯示的數) |
|
|
|
let lotsAllocatedSumForLine = 0; |
|
|
|
|
|
|
|
// ✅ lots:按 lotId 去重并合并 requiredQty |
|
|
|
@@ -4255,7 +4255,7 @@ const PickExecution: React.FC<Props> = ({ |
|
|
|
handleStopScan(); |
|
|
|
} |
|
|
|
}, [combinedLotData.length, isManualScanning, handleStopScan]); |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
// Cleanup effect |
|
|
|
useEffect(() => { |
|
|
|
@@ -4337,9 +4337,9 @@ const PickExecution: React.FC<Props> = ({ |
|
|
|
successMessage={t("QR code verified.")} |
|
|
|
/> |
|
|
|
</Box> |
|
|
|
{/* DO Header */} |
|
|
|
{/* DO Header } |
|
|
|
|
|
|
|
{/* 保留:Combined Lot Table - 包含所有 QR 扫描功能 */} |
|
|
|
{/* 保留:Combined Lot Table - 包含所有 QR 扫描功能 } |
|
|
|
<Box> |
|
|
|
<Box |
|
|
|
sx={{ |
|
|
|
@@ -4355,7 +4355,7 @@ const PickExecution: React.FC<Props> = ({ |
|
|
|
</Typography> |
|
|
|
|
|
|
|
<Box sx={{ display: "flex", gap: 2, alignItems: "center" }}> |
|
|
|
{/* Scanner status indicator (always visible) */} |
|
|
|
{/* Scanner status indicator (always visible) } |
|
|
|
{/* |
|
|
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}> |
|
|
|
<QrCodeIcon |
|
|
|
@@ -4372,9 +4372,9 @@ const PickExecution: React.FC<Props> = ({ |
|
|
|
{isManualScanning ? t("Scanner Active") : t("Scanner Inactive")} |
|
|
|
</Typography> |
|
|
|
</Box> |
|
|
|
*/} |
|
|
|
} |
|
|
|
|
|
|
|
{/* Pause/Resume button instead of Start/Stop */} |
|
|
|
{/* Pause/Resume button instead of Start/Stop } |
|
|
|
{isManualScanning ? ( |
|
|
|
<Button |
|
|
|
variant="outlined" |
|
|
|
@@ -4397,7 +4397,7 @@ const PickExecution: React.FC<Props> = ({ |
|
|
|
</Button> |
|
|
|
)} |
|
|
|
|
|
|
|
{/* 保留:Submit All Scanned Button */} |
|
|
|
{/* 保留:Submit All Scanned Button } |
|
|
|
<Button |
|
|
|
variant="contained" |
|
|
|
color="success" |
|
|
|
@@ -4423,7 +4423,7 @@ const PickExecution: React.FC<Props> = ({ |
|
|
|
{fgPickOrders.length > 0 && ( |
|
|
|
<Paper sx={{ p: 2, mb: 2 }}> |
|
|
|
<Stack spacing={2}> |
|
|
|
{/* 基本信息 */} |
|
|
|
{/* 基本信息 } |
|
|
|
<Stack direction="row" spacing={4} useFlexGap flexWrap="wrap"> |
|
|
|
<Typography variant="subtitle1"> |
|
|
|
<strong>{t("Shop Name")}:</strong>{" "} |
|
|
|
@@ -4443,9 +4443,9 @@ const PickExecution: React.FC<Props> = ({ |
|
|
|
</Typography> |
|
|
|
</Stack> |
|
|
|
|
|
|
|
{/* 改进:三个字段显示在一起,使用表格式布局 */} |
|
|
|
{/* 改进:三个字段合并显示 */} |
|
|
|
{/* 改进:表格式显示每个 pick order */} |
|
|
|
{/* 改进:三个字段显示在一起,使用表格式布局 } |
|
|
|
{/* 改进:三个字段合并显示 } |
|
|
|
{/* 改进:表格式显示每个 pick order } |
|
|
|
<Box |
|
|
|
sx={{ |
|
|
|
p: 2, |
|
|
|
@@ -4844,7 +4844,7 @@ const PickExecution: React.FC<Props> = ({ |
|
|
|
status === 'completed' || |
|
|
|
(Number(lot.stockOutLineId) > 0 && actionBusyBySolId[Number(lot.stockOutLineId)] === true) |
|
|
|
} |
|
|
|
*/ |
|
|
|
|
|
|
|
disabled={true} |
|
|
|
sx={{ |
|
|
|
fontSize: "0.7rem", |
|
|
|
@@ -4889,7 +4889,7 @@ const PickExecution: React.FC<Props> = ({ |
|
|
|
lot.stockOutLineStatus === 'pending' || |
|
|
|
(Number(lot.stockOutLineId) > 0 && actionBusyBySolId[Number(lot.stockOutLineId)] === true) |
|
|
|
} |
|
|
|
*/ |
|
|
|
|
|
|
|
disabled={true} |
|
|
|
sx={{ |
|
|
|
fontSize: "0.75rem", |
|
|
|
@@ -4912,7 +4912,7 @@ const PickExecution: React.FC<Props> = ({ |
|
|
|
lot.lotAvailability === 'expired' || |
|
|
|
lot.stockOutLineStatus === 'completed' || |
|
|
|
(Number(lot.stockOutLineId) > 0 && actionBusyBySolId[Number(lot.stockOutLineId)] === true) |
|
|
|
}*/ |
|
|
|
} |
|
|
|
|
|
|
|
disabled={true} |
|
|
|
sx={{ |
|
|
|
@@ -4994,7 +4994,7 @@ const PickExecution: React.FC<Props> = ({ |
|
|
|
</Box> |
|
|
|
</Stack> |
|
|
|
|
|
|
|
{/* QR Code Scanner works in background - no modal needed */} |
|
|
|
{/* QR Code Scanner works in background - no modal needed } |
|
|
|
<ManualLotConfirmationModal |
|
|
|
open={manualLotConfirmationOpen} |
|
|
|
onClose={() => { |
|
|
|
@@ -5005,7 +5005,7 @@ const PickExecution: React.FC<Props> = ({ |
|
|
|
scannedLot={scannedLotData} |
|
|
|
isLoading={isConfirmingLot} |
|
|
|
/> |
|
|
|
{/* 保留:Lot Confirmation Modal */} |
|
|
|
{/* 保留:Lot Confirmation Modal } |
|
|
|
{lotConfirmationOpen && expectedLotData && scannedLotData && ( |
|
|
|
<LotConfirmationModal |
|
|
|
open={lotConfirmationOpen} |
|
|
|
@@ -5033,7 +5033,7 @@ const PickExecution: React.FC<Props> = ({ |
|
|
|
/> |
|
|
|
)} |
|
|
|
|
|
|
|
{/* 保留:Good Pick Execution Form Modal */} |
|
|
|
{/* 保留:Good Pick Execution Form Modal } |
|
|
|
{pickExecutionFormOpen && selectedLotForExecutionForm && ( |
|
|
|
<GoodPickExecutionForm |
|
|
|
open={pickExecutionFormOpen} |
|
|
|
@@ -5083,3 +5083,4 @@ const PickExecution: React.FC<Props> = ({ |
|
|
|
}; |
|
|
|
|
|
|
|
export default PickExecution; |
|
|
|
*/ |