diff --git a/src/components/DoWorkbench/WorkbenchGoodPickExecutionDetail.tsx b/src/components/DoWorkbench/WorkbenchGoodPickExecutionDetail.tsx
index 0d22fbe..146bc59 100644
--- a/src/components/DoWorkbench/WorkbenchGoodPickExecutionDetail.tsx
+++ b/src/components/DoWorkbench/WorkbenchGoodPickExecutionDetail.tsx
@@ -1671,9 +1671,21 @@ const fetchAllCombinedLotData = useCallback(async (userId?: number, pickOrderIdO
processedQrCombinations,
)
) {
+ const itemRows = indexes.byItemId.get(scannedItemId) ?? [];
+ const errMsg =
+ itemRows.length === 0
+ ? t("QR code does not match any item in current orders.")
+ : t(
+ "No pending pick line left for this item. It may already be completed or fully processed.",
+ );
console.log(
` [SKIP] No pending stock-out line left for itemId=${scannedItemId}, stockInLineId=${scannedStockInLineId}`,
);
+ startTransition(() => {
+ setQrScanError(true);
+ setQrScanSuccess(false);
+ setQrScanErrorMsg(errMsg);
+ });
return;
}
@@ -2275,9 +2287,21 @@ const fetchAllCombinedLotData = useCallback(async (userId?: number, pickOrderIdO
)
) {
const mismatchCheckTime = performance.now() - mismatchCheckStartTime;
+ const itemRows = indexes.byItemId.get(scannedItemId) ?? [];
+ const errMsg =
+ itemRows.length === 0
+ ? t("QR code does not match any item in current orders.")
+ : t(
+ "No pending pick line left for this item. It may already be completed or fully processed.",
+ );
console.log(
` [SKIP] No pending stock-out line left for mismatch path (check time: ${mismatchCheckTime.toFixed(2)}ms)`,
);
+ startTransition(() => {
+ setQrScanError(true);
+ setQrScanSuccess(false);
+ setQrScanErrorMsg(errMsg);
+ });
return;
}
const mismatchCheckTime = performance.now() - mismatchCheckStartTime;
@@ -3395,6 +3419,7 @@ const handleStartScan = useCallback(() => {
lastConsumedQrValuesLengthRef.current = qrValues.length;
setQrScanError(false);
setQrScanSuccess(false);
+ setQrScanErrorMsg('');
const beforeStartScanTime = performance.now();
startScan();
@@ -3427,6 +3452,7 @@ const handleStartScan = useCallback(() => {
setIsManualScanning(false);
setQrScanError(false);
setQrScanSuccess(false);
+ setQrScanErrorMsg('');
stopScan();
resetScan();
lastConsumedQrValuesLengthRef.current = 0;
@@ -3850,7 +3876,10 @@ const handleSubmitAllScanned = useCallback(async () => {
@@ -4116,76 +4145,85 @@ paginatedData.map((row, index) => {
{lot.routerRoute || '-'}
-
-
-
-
- {lot.lotNo ? (
- rejectDisplay ? (
- <>
- {lot.lotNo}
-
- {rejectDisplay}
-
- >
- ) :
-
- lot.lotAvailability === 'expired' ? (
- <>
- {lot.lotNo}{' '}
- {t('is expired. Please check around have available QR code or not.')}
- >
- ) : isInventoryLotLineUnavailable(lot) ? (
- <>
- {lot.lotNo}{' '}
- {t('is unavable. Please check around have available QR code or not.')}
- >
- ) : (
- lot.lotNo
- )
- ) : (
-
- {rejectDisplay ||
+
+
+
+ {(() => {
+ const hasLotNo = Boolean(lot.lotNo);
+ const isExpired = lot.lotAvailability === 'expired';
+ const isUnavailable = isInventoryLotLineUnavailable(lot);
+ const isNoLotHint = !hasLotNo && !rejectDisplay; // 顯示「請檢查周圍…」那種
+ const isIssueText =
+ Boolean(rejectDisplay) || !hasLotNo || isExpired || isUnavailable;
+ const textColor =
+ isNoLotHint
+ ? 'error.main' // 或 'text.primary':固定黑,不受 handled / unavailable 影響
+ : rejectDisplay || isSolRejected || isUnavailable
+ ? 'error.main'
+ : isExpired
+ ? 'warning.main'
+ : 'inherit';
+ return (
+
+ {hasLotNo ? (
+ rejectDisplay ? (
+ <>
+ {lot.lotNo}
+
+ {rejectDisplay}
+
+ >
+ ) : isExpired ? (
+ <>
+ {lot.lotNo}{' '}
+ {t('is expired. Please check around have available QR code or not.')}
+ >
+ ) : isUnavailable ? (
+ <>
+ {lot.lotNo}{' '}
+ {t('is unavailable. Please check around have available QR code or not.')}
+ >
+ ) : (
+ lot.lotNo
+ )
+ ) : (
+ rejectDisplay ||
t(
"Please check around have QR code or not, may be have just now stock in or transfer in or transfer out.",
- )}
-
- )}
-
+ )
+ )}
+
+ );
+ })()}
- {Number(lot.stockOutLineId) > 0 && Number(lot.itemId) > 0 ? (
-
- ) : null}
-
-
+
+ {/* Lot QR Code Button */}
+ {Number(lot.stockOutLineId) > 0 && Number(lot.itemId) > 0 && (
+
+ )}
+
+
{(() => {
const requiredQty = lot.requiredQty || 0;
@@ -4219,22 +4257,14 @@ paginatedData.map((row, index) => {
}
// 過期批號:與 noLot 同類——視為已掃到/可處理(含 pending),顯示警示色勾選
- if (isLotAvailabilityExpired(lot) && status !== "rejected") {
- return (
-
-
-
- );
+ if (
+ isLotAvailabilityExpired(lot) &&
+ status !== "rejected" &&
+ status !== "completed" &&
+ status !== "partially_completed" &&
+ status !== "partially_complete"
+ ) {
+ return null;
}
// 正常 lot:已扫描(checked/partially_completed/completed)
diff --git a/src/components/JoWorkbench/newJobPickExecution.tsx b/src/components/JoWorkbench/newJobPickExecution.tsx
index 045a7ec..3458235 100644
--- a/src/components/JoWorkbench/newJobPickExecution.tsx
+++ b/src/components/JoWorkbench/newJobPickExecution.tsx
@@ -4274,31 +4274,12 @@ const JobPickExecution: React.FC = ({ filterArgs, onBackToList, printerCo
if (
isLotAvailabilityExpired(lot) &&
- status !== "rejected"
+ status !== "rejected" &&
+ status !== "completed" &&
+ status !== "partially_completed" &&
+ status !== "partially_complete"
) {
- return (
-
-
-
- );
+ return null;
}
if (
diff --git a/src/i18n/zh/pickOrder.json b/src/i18n/zh/pickOrder.json
index 160b098..9bfb9b4 100644
--- a/src/i18n/zh/pickOrder.json
+++ b/src/i18n/zh/pickOrder.json
@@ -12,6 +12,7 @@
"N/A": "不適用",
"Release Pick Orders": "放單",
"released": "已放單",
+ "is unavailable. Please check around have available QR code or not.": "不可用。請檢查周圍是否有可用的 QR 碼。",
"No lot rows. Select a pick order above.": "沒有批次行。請選擇一個提料單。",
"Loading...": "載入中...",
"Suggestion success": "建議成功",
@@ -506,7 +507,7 @@
"packaging": "提料中",
"No Stock Available": "沒有庫存可用",
"This lot is not available, please scan another lot.": "此批號不可用,請掃描其他批號。",
- "Please check around have QR code or not, may be have just now stock in or transfer in or transfer out.": "請檢查周圍是否有 QR 碼,可能有剛剛入庫、轉移入庫或轉移出庫的 QR 碼。",
+ "Please check around have QR code or not, may be have just now stock in or transfer in or transfer out.": "請檢查周圍是否有其他可用 QR 碼。",
"Lot is expired (expiry={{expiry}})": "掃描批號已過期(到期日={{expiry}})",
"Day After Tomorrow": "後日",
"Lot line is unavailable": "掃描批次不可用",
@@ -561,5 +562,6 @@
"Reject switch lot: picked {{picked}} already greater or equal required {{required}}": "換批被拒:已揀數量({{picked}})已達或超過建議量({{required}}),無法再拆分換批。",
"Lot status is unavailable. Cannot switch or bind; pick line was not updated.": "批號狀態為「不可用」,無法換批或綁定;揀貨行未更新。",
"No lot rows. Select a line in the table above.": "尚無批號資料。請在上方表格勾選一行提料單明細。",
- "No stock out line for this lot": "此批號尚無出庫行,無法提交。"
+ "No stock out line for this lot": "此批號尚無出庫行,無法提交。",
+ "No pending pick line left for this item. It may already be completed or fully processed.": "此貨品已無待揀行,可能已完成或不在本單可掃範圍。"
}
\ No newline at end of file