Bladeren bron

lotlabelprintmodal update

MergeProblem1^2
Tommy\2Fi-Staff 13 uur geleden
bovenliggende
commit
181140738d
2 gewijzigde bestanden met toevoegingen van 74 en 16 verwijderingen
  1. +25
    -7
      src/components/FinishedGoodSearch/GoodPickExecutiondetail.tsx
  2. +49
    -9
      src/components/InventorySearch/LotLabelPrintModal.tsx

+ 25
- 7
src/components/FinishedGoodSearch/GoodPickExecutiondetail.tsx Bestand weergeven

@@ -77,7 +77,6 @@ import QrCodeIcon from "@mui/icons-material/QrCode";
import { useQrCodeScannerContext } from "../QrCodeScannerProvider/QrCodeScannerProvider";
import { useSession } from "next-auth/react";
import { SessionWithTokens } from "@/config/authConfig";
import { AUTH } from "@/authorities";
import { fetchStockInLineInfo } from "@/app/api/po/actions";
import GoodPickExecutionForm from "./GoodPickExecutionForm";
import FGPickOrderCard from "./FGPickOrderCard";
@@ -687,8 +686,6 @@ const PickExecution: React.FC<Props> = ({
const { t } = useTranslation("pickOrder");
const router = useRouter();
const { data: session } = useSession() as { data: SessionWithTokens | null };
const abilities = session?.abilities ?? session?.user?.abilities ?? [];
const isAdmin = abilities.some((a) => String(a).trim() === AUTH.ADMIN);
const [doPickOrderDetail, setDoPickOrderDetail] =
useState<DoPickOrderDetail | null>(null);
const [selectedPickOrderId, setSelectedPickOrderId] = useState<number | null>(
@@ -783,6 +780,25 @@ const PickExecution: React.FC<Props> = ({
useState<any | null>(null);
const [fgPickOrders, setFgPickOrders] = useState<FGPickOrderResponse[]>([]);
const [fgPickOrdersLoading, setFgPickOrdersLoading] = useState(false);
const lotFloorPrefixFilter = useMemo(() => {
const storeId = String(fgPickOrders?.[0]?.storeId ?? "")
.trim()
.toUpperCase()
.replace(/\s/g, "");
// e.g. "2/F" -> "2F-", "4/F" -> "4F-"
const floorKey = storeId.replace(/\//g, "");
return floorKey ? `${floorKey}-` : "";
}, [fgPickOrders]);
const defaultLabelPrinterName = useMemo(() => {
const storeId = String(fgPickOrders?.[0]?.storeId ?? "")
.trim()
.toUpperCase()
.replace(/\s/g, "");
const floorKey = storeId.replace(/\//g, "");
if (floorKey === "2F") return "Label機 2F A+B";
if (floorKey === "4F") return "Label機 4F 乾貨 C, D";
return undefined;
}, [fgPickOrders]);
// Add these missing state variables after line 352
const [isManualScanning, setIsManualScanning] = useState<boolean>(false);
// Track processed QR codes by itemId+stockInLineId combination for better lot confirmation handling
@@ -1690,7 +1706,7 @@ const PickExecution: React.FC<Props> = ({
return;
}

if (switchedToUnavailable && isAdmin) {
if (switchedToUnavailable) {
const itemId = Number(sel?.itemId ?? exp?.itemId);
const stockInLineId = Number(newStockInLineId);
if (Number.isFinite(itemId) && Number.isFinite(stockInLineId)) {
@@ -1745,7 +1761,6 @@ const PickExecution: React.FC<Props> = ({
resetScan,
clearLotConfirmationState,
t,
isAdmin,
],
);

@@ -2138,7 +2153,7 @@ const PickExecution: React.FC<Props> = ({
const byLotId = new Map<number, any>();
const byLotNo = new Map<string, any[]>();
const byStockInLineId = new Map<number, any[]>();
// Cache active lots separately to avoid filtering on every scan
const activeLotsByItemId = new Map<number, any[]>();
const rejectedStatuses = new Set(["rejected"]);
@@ -5055,9 +5070,12 @@ const PickExecution: React.FC<Props> = ({
setLotLabelPrintReminderText(null);
}}
initialPayload={lotLabelPrintInitialPayload}
defaultPrinterName="Label機 2F A+B"
defaultPrinterName={defaultLabelPrinterName}
hideScanSection
reminderText={lotLabelPrintReminderText ?? undefined}
statusTitleText="此批號的已用完/已過期"
warehouseCodePrefixFilter={lotFloorPrefixFilter}
hideTriggeredLot
/>
</FormProvider>
</TestQrCodeProvider>


+ 49
- 9
src/components/InventorySearch/LotLabelPrintModal.tsx Bestand weergeven

@@ -75,6 +75,12 @@ export interface LotLabelPrintModalProps {
hideScanSection?: boolean;
/** 額外提醒(顯示在最上方) */
reminderText?: string;
/** 額外標題(顯示在最上方,reminderText 之下) */
statusTitleText?: string;
/** 只顯示特定倉位前綴(例如 "2F-") */
warehouseCodePrefixFilter?: string;
/** 不顯示觸發視窗的批號(analysis.scanned) */
hideTriggeredLot?: boolean;
}

function safeParseScanPayload(raw: string): ScanPayload | null {
@@ -115,6 +121,9 @@ const LotLabelPrintModal: React.FC<LotLabelPrintModalProps> = ({
defaultPrinterName,
hideScanSection,
reminderText,
statusTitleText,
warehouseCodePrefixFilter,
hideTriggeredLot,
}) => {
const scanInputRef = useRef<HTMLInputElement | null>(null);
const [scanInput, setScanInput] = useState("");
@@ -126,6 +135,7 @@ const LotLabelPrintModal: React.FC<LotLabelPrintModalProps> = ({

const [analysisLoading, setAnalysisLoading] = useState(false);
const [analysis, setAnalysis] = useState<QrCodeAnalysisResponse | null>(null);
const [lastPayload, setLastPayload] = useState<ScanPayload | null>(null);

const [printQty, setPrintQty] = useState(1);
const [printingLotLineId, setPrintingLotLineId] = useState<number | null>(
@@ -234,6 +244,7 @@ const LotLabelPrintModal: React.FC<LotLabelPrintModalProps> = ({
return;
}

setLastPayload(payload);
setScanError(null);
setAnalysisLoading(true);
try {
@@ -279,6 +290,19 @@ const LotLabelPrintModal: React.FC<LotLabelPrintModalProps> = ({
await analyzePayload(payload);
}, [scanInput, analyzePayload]);

const handleRefreshLots = useCallback(async () => {
const payload = lastPayload ?? safeParseScanPayload(scanInput.trim());
if (!payload) {
setSnackbar({
open: true,
message: "請先掃碼或查詢一次,才可刷新批號清單。",
severity: "info",
});
return;
}
await analyzePayload(payload);
}, [analyzePayload, lastPayload, scanInput]);

useEffect(() => {
if (!open) return;
if (!initialPayload) return;
@@ -310,14 +334,22 @@ const LotLabelPrintModal: React.FC<LotLabelPrintModalProps> = ({
: null;

const merged = [
...(scannedLot ? [scannedLot] : []),
...(!hideTriggeredLot && scannedLot ? [scannedLot] : []),
...list
.filter((x) => x.inventoryLotLineId !== scannedLotLineId)
.map((x) => ({ ...x, _scanned: false as const })),
];

return merged;
}, [analysis]);
}, [analysis, hideTriggeredLot]);

const filteredLots = useMemo(() => {
const prefix = String(warehouseCodePrefixFilter ?? "").trim();
if (!prefix) return availableLots;
return availableLots.filter((lot) =>
String(lot.warehouseCode ?? "").startsWith(prefix),
);
}, [availableLots, warehouseCodePrefixFilter]);

const selectedPrinter = useMemo(() => {
if (selectedPrinterId === "") return null;
@@ -390,6 +422,14 @@ const LotLabelPrintModal: React.FC<LotLabelPrintModalProps> = ({
<DialogTitle>批號標籤列印</DialogTitle>
<DialogContent>
<Stack spacing={2} sx={{ mt: 1 }}>
{statusTitleText ? (
<Typography
variant="h6"
sx={{ fontWeight: 800, color: "error.main" }}
>
{statusTitleText}
</Typography>
) : null}
{reminderText ? (
<Alert severity="warning">{reminderText}</Alert>
) : null}
@@ -485,13 +525,13 @@ const LotLabelPrintModal: React.FC<LotLabelPrintModalProps> = ({

<Button
variant="outlined"
onClick={() => void loadPrinters()}
disabled={printersLoading}
onClick={() => void handleRefreshLots()}
disabled={analysisLoading}
>
{printersLoading ? (
{analysisLoading ? (
<CircularProgress size={18} />
) : (
"重新載入印表機"
"刷新批號清單"
)}
</Button>

@@ -512,13 +552,13 @@ const LotLabelPrintModal: React.FC<LotLabelPrintModalProps> = ({
品號:{analysis.itemCode} {analysis.itemName}
</Typography>

{availableLots.length === 0 ? (
{filteredLots.length === 0 ? (
<Alert severity="warning">
找不到可用批號(availableQty &gt; 0)。
找不到該樓層有可用批號(availableQty &gt; 0)。
</Alert>
) : (
<Stack spacing={1}>
{availableLots.map((lot) => {
{filteredLots.map((lot) => {
const isPrinting =
printingLotLineId === lot.inventoryLotLineId;
const loc = String(lot.warehouseCode ?? "").trim();


Laden…
Annuleren
Opslaan