| @@ -584,7 +584,7 @@ const DoSearch: React.FC<Props> = ({ filterArgs, searchQuery, onDeliveryOrderSea | |||||
| ${currentSearchParams.code ? `${t("Code")}: ${currentSearchParams.code} ` : ""} | ${currentSearchParams.code ? `${t("Code")}: ${currentSearchParams.code} ` : ""} | ||||
| ${currentSearchParams.shopName ? `${t("Shop Name")}: ${currentSearchParams.shopName} ` : ""} | ${currentSearchParams.shopName ? `${t("Shop Name")}: ${currentSearchParams.shopName} ` : ""} | ||||
| ${currentSearchParams.estimatedArrivalDate ? `${t("Estimated Arrival")}: ${currentSearchParams.estimatedArrivalDate} ` : ""} | ${currentSearchParams.estimatedArrivalDate ? `${t("Estimated Arrival")}: ${currentSearchParams.estimatedArrivalDate} ` : ""} | ||||
| ${status ? `${t("Status")}: ${status} ` : ""} | |||||
| ${status ? `${t("Status")}: ${t(status)} ` : ""} | |||||
| </p> | </p> | ||||
| </div> | </div> | ||||
| `, | `, | ||||
| @@ -150,6 +150,20 @@ function hasPendingActiveRowForStockInLine( | |||||
| ); | ); | ||||
| } | } | ||||
| /** Any pending active SOL for this item (e.g. scan different location, same lot no → auto-switch). */ | |||||
| function hasPendingActiveRowForItem( | |||||
| indexes: { activeLotsByItemId: Map<number, any[]> }, | |||||
| itemId: number, | |||||
| processedByItemId: ProcessedStockOutLinesByItemId, | |||||
| ): boolean { | |||||
| const activeLots = indexes.activeLotsByItemId.get(itemId) ?? []; | |||||
| return activeLots.some( | |||||
| (lot) => | |||||
| isLotRowPending(lot) && | |||||
| !isStockOutLineAlreadyProcessed(processedByItemId, itemId, lot.stockOutLineId), | |||||
| ); | |||||
| } | |||||
| function findExactActiveMatchForStockInLine( | function findExactActiveMatchForStockInLine( | ||||
| stockInLineLots: any[], | stockInLineLots: any[], | ||||
| scannedItemId: number, | scannedItemId: number, | ||||
| @@ -1560,14 +1574,18 @@ const fetchAllCombinedLotData = useCallback(async (userId?: number, pickOrderIdO | |||||
| const scannedItemId = qrData.itemId; | const scannedItemId = qrData.itemId; | ||||
| const scannedStockInLineId = qrData.stockInLineId; | const scannedStockInLineId = qrData.stockInLineId; | ||||
| if ( | |||||
| !hasPendingActiveRowForStockInLine( | |||||
| indexes, | |||||
| scannedItemId, | |||||
| scannedStockInLineId, | |||||
| processedQrCombinations, | |||||
| ) | |||||
| ) { | |||||
| const hasPendingOnScannedSil = hasPendingActiveRowForStockInLine( | |||||
| indexes, | |||||
| scannedItemId, | |||||
| scannedStockInLineId, | |||||
| processedQrCombinations, | |||||
| ); | |||||
| const hasPendingOnItem = hasPendingActiveRowForItem( | |||||
| indexes, | |||||
| scannedItemId, | |||||
| processedQrCombinations, | |||||
| ); | |||||
| if (!hasPendingOnScannedSil && !hasPendingOnItem) { | |||||
| console.log( | console.log( | ||||
| ` [SKIP] No pending stock-out line left for itemId=${scannedItemId}, stockInLineId=${scannedStockInLineId}`, | ` [SKIP] No pending stock-out line left for itemId=${scannedItemId}, stockInLineId=${scannedStockInLineId}`, | ||||
| ); | ); | ||||
| @@ -271,7 +271,7 @@ type Props = { | |||||
| {items.length > 0 && ( | {items.length > 0 && ( | ||||
| <Typography variant="caption" color="text.secondary"> | <Typography variant="caption" color="text.secondary"> | ||||
| 將匯入 {items.length} 個 BOM | 將匯入 {items.length} 個 BOM | ||||
| {wipCount > 0 ? `,其中 ${wipCount} 個同時建立 WIP` : ""} | |||||
| {wipCount > 0 ? `,其中 ${wipCount} 個同時建立 半成品` : ""} | |||||
| {drinkCount > 0 ? `,${drinkCount} 個飲料` : ""} | {drinkCount > 0 ? `,${drinkCount} 個飲料` : ""} | ||||
| {powderMixtureCount > 0 ? `,${powderMixtureCount} 個箱料粉` : ""} | {powderMixtureCount > 0 ? `,${powderMixtureCount} 個箱料粉` : ""} | ||||
| </Typography> | </Typography> | ||||
| @@ -160,7 +160,16 @@ const StockIssueRecordTab: React.FC<Props> = ({ kind }) => { | |||||
| label: kind === "expiry" ? t("Expiry Item Qty") : t("Bad Item Qty"), | label: kind === "expiry" ? t("Expiry Item Qty") : t("Bad Item Qty"), | ||||
| renderCell: (row) => ( | renderCell: (row) => ( | ||||
| <> | <> | ||||
| {Number(row.qty).toFixed(2)} {row.uomDesc ?? ""} | |||||
| {Number(row.qty).toFixed(2)} | |||||
| </> | |||||
| ), | |||||
| }, | |||||
| { | |||||
| name: "uomDesc", | |||||
| label: t("UOM"), | |||||
| renderCell: (row) => ( | |||||
| <> | |||||
| {row.uomDesc ?? ""} | |||||
| </> | </> | ||||
| ), | ), | ||||
| }, | }, | ||||
| @@ -10,6 +10,10 @@ | |||||
| "Estimated Arrival To": "預計送貨日期至", | "Estimated Arrival To": "預計送貨日期至", | ||||
| "Status": "來貨狀態", | "Status": "來貨狀態", | ||||
| "Etra": "加單", | "Etra": "加單", | ||||
| "Loading": "正在加載...", | |||||
| "No delivery orders selected for batch release. Uncheck orders you want to exclude, or search again to reset selection.": "沒有選擇送貨訂單進行批量放單。取消勾選您想排除的訂單,或重新搜索以重置選擇。", | |||||
| "No Records": "沒有找到記錄", | |||||
| "OK": "確認", | |||||
| "Truck X": "車線-X", | "Truck X": "車線-X", | ||||
| "DO Workbench": "新版成品出倉", | "DO Workbench": "新版成品出倉", | ||||
| "Order Date From": "訂單日期", | "Order Date From": "訂單日期", | ||||
| @@ -48,8 +52,11 @@ | |||||
| "Supplier Name": "供應商名稱", | "Supplier Name": "供應商名稱", | ||||
| "Details": "詳情", | "Details": "詳情", | ||||
| "Pending": "待處理", | "Pending": "待處理", | ||||
| "pending": "待處理", | |||||
| "Receiving": "接收中", | "Receiving": "接收中", | ||||
| "receiving": "接收中", | |||||
| "Completed": "已完成", | "Completed": "已完成", | ||||
| "completed": "已完成", | |||||
| "Please wait": "請稍候", | "Please wait": "請稍候", | ||||
| "Selected Shop(s): ": "已選擇店舖數量: ", | "Selected Shop(s): ": "已選擇店舖數量: ", | ||||
| "Selected Item(s): ": "總貨品數量: ", | "Selected Item(s): ": "總貨品數量: ", | ||||