"use client"; import React, { useCallback, useEffect, useRef, useState } from "react"; import { Alert, Box, Button, Checkbox, Chip, CircularProgress, FormControlLabel, Paper, Stack, Tab, Table, TableBody, TableCell, TableHead, TableRow, Tabs, TextField, Typography, } from "@mui/material"; import { DateCalendar } from "@mui/x-date-pickers/DateCalendar"; import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; import { useTranslation } from "react-i18next"; import dayjs, { type Dayjs } from "dayjs"; import "dayjs/locale/zh-hk"; import "dayjs/locale/en"; import { fetchStockLedgerFixAdjPreview, runStockLedgerFixAdj, fetchStockLedgerFixDay, fetchStockLedgerFixInventory, fetchStockLedgerFixInventoryScope, fetchStockLedgerFixLotScope, runStockLedgerFixDay, runStockLedgerFixRange, runStockLedgerFixInventory, runStockLedgerFixInventoryScope, runStockLedgerFixLotScope, searchStockLedgerFixInventory, searchStockLedgerFixLot, downloadStockLedgerFixSql, type StockLedgerFixAdjPreview, type StockLedgerFixCheckPart, type StockLedgerFixDayDetail, type StockLedgerFixInventoryPreview, type StockLedgerFixScopeDetail, type StockLedgerFixSearchInventoryHit, type StockLedgerFixSearchLotHit, } from "@/app/api/stockLedgerFix/client"; const FIRST_LEDGER_DAY = dayjs("2026-03-01"); const DAY_FIX_STEPS = ["2.1", "2.2", "2.3", "2.4", "2.5", "2.6"] as const; type DayFixStep = (typeof DAY_FIX_STEPS)[number]; const ALL_DAY_STEPS: Record = { "2.1": true, "2.2": true, "2.3": true, "2.4": true, "2.5": true, "2.6": true, }; const DAY_STEP_I18N: Record = { "2.1": "step21", "2.2": "step22", "2.3": "step23", "2.4": "step24", "2.5": "step25", "2.6": "step26", }; /** Export SQL parts (aligned with fix steps + 1.0 / 2.7). */ const EXPORT_PARTS = ["1.0", "2.3", "ledger", "2.6", "2.7"] as const; type ExportPart = (typeof EXPORT_PARTS)[number]; const DEFAULT_EXPORT_PARTS: Record = { "1.0": false, "2.3": false, ledger: true, "2.6": true, "2.7": false, }; const FULL_EXPORT_PARTS: Record = { "1.0": true, "2.3": true, ledger: true, "2.6": true, "2.7": true, }; const EXPORT_PART_I18N: Record = { "1.0": "export10", "2.3": "export23", ledger: "exportLedger", "2.6": "export26", "2.7": "export27", }; function selectedExportParts(flags: Record): ExportPart[] { return EXPORT_PARTS.filter((p) => flags[p]); } function exportPartsPayload(flags: Record): string[] | undefined { const selected = selectedExportParts(flags); if (selected.length === 0) return undefined; // Always send explicit list so backend does not fall back to legacy default alone return selected; } function selectedDaySteps(flags: Record): DayFixStep[] { return DAY_FIX_STEPS.filter((s) => flags[s]); } function stepsPayload(flags: Record): string[] | undefined { const selected = selectedDaySteps(flags); if (selected.length === 0 || selected.length === DAY_FIX_STEPS.length) return undefined; return selected; } function apiErrorMessage(e: unknown, fallback: string): string { if (e && typeof e === "object" && "response" in e) { const data = (e as { response?: { data?: unknown } }).response?.data; if (typeof data === "string" && data.trim()) { return data.trim().slice(0, 400); } if (data && typeof data === "object") { const msg = (data as { message?: unknown }).message; if (typeof msg === "string" && msg.trim()) { return msg.trim().slice(0, 400); } } } if (e instanceof Error && e.message) return e.message; return fallback; } function partVerdict( part: StockLedgerFixCheckPart, ): "correct" | "miss" | "incorrect" | "over-issue" | "can-fix" | "cannot-fix" { if (part.group === "canFix") { return part.miss > 0 || part.incorrect > 0 ? "can-fix" : "correct"; } if (part.group === "cannotFix") { return part.miss > 0 || part.incorrect > 0 ? "cannot-fix" : "correct"; } if (part.key === "overIssue") { if (part.incorrect > 0 || part.miss > 0) return "over-issue"; return "correct"; } if (part.incorrect > 0) return "incorrect"; if (part.miss > 0) return "miss"; if (part.key === "dayTable" && part.ok === 0) return "miss"; return "correct"; } const VERDICT_LABEL: Record< ReturnType, "verdictCorrect" | "verdictMiss" | "verdictOverIssue" | "verdictCanFix" | "verdictCannotFix" | "verdictIncorrect" > = { correct: "verdictCorrect", miss: "verdictMiss", "over-issue": "verdictOverIssue", "can-fix": "verdictCanFix", "cannot-fix": "verdictCannotFix", incorrect: "verdictIncorrect", }; function CheckPartsTable({ parts }: { parts: StockLedgerFixCheckPart[] }) { const { t } = useTranslation("stockLedgerFix"); const field = parts.filter((p) => !p.group || p.group === "field"); const canFix = parts.filter( (p) => p.group === "canFix" && p.miss + p.incorrect > 0, ); const cannotFix = parts.filter( (p) => p.group === "cannotFix" && p.miss + p.incorrect > 0, ); const renderRows = (rows: StockLedgerFixCheckPart[]) => rows.map((p) => { const v = partVerdict(p); return ( {t(`part.${p.key}`, { defaultValue: p.label })} {p.ok} {p.miss} {p.incorrect} ); }); return ( {t("checkItem")} {t("checkStatus")} {t("checkCorrect")} {t("checkMiss")} {t("checkIncorrect")} {renderRows(field)}
{canFix.length > 0 && ( <> {t("canAutoFix")} {t("checkReason")} {t("checkStatus")} {t("checkCorrect")} {t("checkRows")} {t("checkDash")} {renderRows(canFix)}
)} {cannotFix.length > 0 && ( <> {t("cannotAutoFix")} {t("checkReason")} {t("checkStatus")} {t("checkCorrect")} {t("checkDash")} {t("checkRows")} {renderRows(cannotFix)}
)}
); } const StockLedgerFixPageClient: React.FC = () => { const { t, i18n } = useTranslation("stockLedgerFix"); const isZh = (i18n.language || "zh").startsWith("zh"); const listSep = isZh ? "、" : ", "; const [tab, setTab] = useState<"day" | "inventory" | "lot">("day"); const [selected, setSelected] = useState(() => dayjs().subtract(1, "day"), ); const [detail, setDetail] = useState(null); const [detailLoading, setDetailLoading] = useState(false); const [detailError, setDetailError] = useState(null); const [fixing, setFixing] = useState(false); const [fixError, setFixError] = useState(null); const [fixMessage, setFixMessage] = useState(null); const detailInFlight = useRef(false); const fixInFlight = useRef(false); const inventoryLoadInFlight = useRef(false); const inventoryRunInFlight = useRef(false); const searchInFlight = useRef(false); const scopeInFlight = useRef(false); const exportInFlight = useRef(false); const [chainFrom, setChainFrom] = useState("2026-03-15"); const [chainTo, setChainTo] = useState(() => dayjs().subtract(1, "day").format("YYYY-MM-DD"), ); const [chainRunning, setChainRunning] = useState(false); const [chainProgress, setChainProgress] = useState(null); const [daySteps, setDaySteps] = useState>(ALL_DAY_STEPS); const [exportFrom, setExportFrom] = useState("2026-03-15"); const [exportTo, setExportTo] = useState(() => dayjs().subtract(1, "day").format("YYYY-MM-DD"), ); const [exportParts, setExportParts] = useState>(DEFAULT_EXPORT_PARTS); const [exporting, setExporting] = useState(false); const [exportError, setExportError] = useState(null); const [inventoryPreview, setInventoryPreview] = useState(null); const [inventoryLoading, setInventoryLoading] = useState(false); const [inventoryRunning, setInventoryRunning] = useState(false); const [inventoryError, setInventoryError] = useState(null); const [inventoryMessage, setInventoryMessage] = useState(null); const adjLoadInFlight = useRef(false); const adjRunInFlight = useRef(false); const [adjPreview, setAdjPreview] = useState(null); const [adjLoading, setAdjLoading] = useState(false); const [adjRunning, setAdjRunning] = useState(false); const [adjError, setAdjError] = useState(null); const [adjMessage, setAdjMessage] = useState(null); /** Default yesterday; freeze-night dump set to today so ADJ lands on dump day. */ const [adjDate, setAdjDate] = useState(() => dayjs().subtract(1, "day").format("YYYY-MM-DD"), ); const [invQuery, setInvQuery] = useState(""); const [lotQuery, setLotQuery] = useState(""); const [invHits, setInvHits] = useState([]); const [lotHits, setLotHits] = useState([]); const [searchError, setSearchError] = useState(null); const [searching, setSearching] = useState(false); const [scope, setScope] = useState(null); const [scopeLoading, setScopeLoading] = useState(false); const loadInventory = useCallback(async () => { if (inventoryLoadInFlight.current) return; inventoryLoadInFlight.current = true; setInventoryLoading(true); setInventoryError(null); try { const data = await fetchStockLedgerFixInventory(); setInventoryPreview(data); } catch (e) { console.error(e); setInventoryError(t("inventory10LoadError")); setInventoryPreview(null); } finally { setInventoryLoading(false); inventoryLoadInFlight.current = false; } }, [t]); const loadDay = useCallback(async (date: string) => { if (detailInFlight.current) return; detailInFlight.current = true; setDetailLoading(true); setDetailError(null); setFixMessage(null); try { const data = await fetchStockLedgerFixDay(date); setDetail(data); } catch (e) { console.error(e); setDetailError(t("dayLoadError")); setDetail(null); } finally { setDetailLoading(false); detailInFlight.current = false; } }, [t]); const loadAdjPreview = useCallback(async () => { if (adjLoadInFlight.current) return; const d = adjDate.trim(); if (!d) { setAdjError(t("adjDateRequired")); return; } if (d > dayjs().format("YYYY-MM-DD")) { setAdjError(t("adjDateFuture")); return; } adjLoadInFlight.current = true; setAdjLoading(true); setAdjError(null); try { setAdjPreview(await fetchStockLedgerFixAdjPreview(d)); } catch (e) { console.error(e); setAdjError(apiErrorMessage(e, t("adjLoadError"))); setAdjPreview(null); } finally { setAdjLoading(false); adjLoadInFlight.current = false; } }, [adjDate, t]); useEffect(() => { void loadInventory(); }, [loadInventory]); useEffect(() => { if (tab === "day" && selected) { void loadDay(selected.format("YYYY-MM-DD")); } }, [selected, loadDay, tab]); const onFixDay = async () => { if (!selected || fixInFlight.current) return; const date = selected.format("YYYY-MM-DD"); if (selected.isAfter(dayjs(), "day")) { setFixError(t("cannotFixFuture")); return; } const picked = selectedDaySteps(daySteps); if (picked.length === 0) { setFixError(t("pickAtLeastOneStep")); return; } const steps = stepsPayload(daySteps); const stepLabel = steps?.join(listSep) ?? t("allSteps216"); if (steps) { const ok = window.confirm( t("confirmPartialSteps", { steps: stepLabel, date }), ); if (!ok) return; } fixInFlight.current = true; setFixing(true); setFixError(null); setFixMessage(null); try { const res = await runStockLedgerFixDay(date, steps); setFixMessage( t("fixDayDone", { date: res.date, steps: stepLabel, lot: res.filledLotLineId, uom: res.filledUomId, inventory: res.filledInventoryId, lotQty: res.filledLotQty, balance: res.filledBalance, dayRows: res.dayRowsWritten, }), ); await loadDay(date); } catch (e) { console.error(e); setFixError(apiErrorMessage(e, t("fixFailed"))); } finally { setFixing(false); fixInFlight.current = false; } }; const onInventory = async () => { if (inventoryRunInFlight.current) return; const ok = window.confirm(t("inventory10Confirm")); if (!ok) return; inventoryRunInFlight.current = true; setInventoryRunning(true); setInventoryError(null); setInventoryMessage(null); try { const res = await runStockLedgerFixInventory(); setInventoryMessage( t("inventory10Done", { patched: res.patchedStockUomId, inserted: res.inserted, orphans: res.orphansDeleted ?? 0, updated: res.updated, missingAfter: res.missingUomPairsAfter, nullAfter: res.nullStockUomIdAfter, }), ); await loadInventory(); } catch (e) { console.error(e); setInventoryError(apiErrorMessage(e, t("inventory10Fail"))); } finally { setInventoryRunning(false); inventoryRunInFlight.current = false; } }; const onAdjApply = async () => { if (adjRunInFlight.current) return; const d = adjDate.trim() || adjPreview?.adjDate; if (!d) { setAdjError(t("adjDateAndPreviewRequired")); return; } const ok = window.confirm( t("adjConfirm", { date: d, overIssueCount: adjPreview?.overIssueCount ?? 0, sumOverIssue: adjPreview?.sumOverIssue ?? "?", adjInCount: adjPreview?.adjInCount ?? 0, adjOutCount: adjPreview?.adjOutCount ?? 0, sumMissIn: adjPreview?.sumMissIn ?? "?", sumMissOut: adjPreview?.sumMissOut ?? "?", }), ); if (!ok) return; adjRunInFlight.current = true; setAdjRunning(true); setAdjError(null); setAdjMessage(null); try { const res = await runStockLedgerFixAdj(d); setAdjMessage( t("adjDone", { date: res.adjDate, overIssuePatched: res.overIssuePatched, insertedIn: res.insertedIn, insertedOut: res.insertedOut, filledLotQty: res.filledLotQty, filledBalance: res.filledBalance, dayRowsWritten: res.dayRowsWritten, }), ); await loadAdjPreview(); } catch (e) { console.error(e); setAdjError(apiErrorMessage(e, t("adjFail"))); } finally { setAdjRunning(false); adjRunInFlight.current = false; } }; const onSearchInventory = async () => { if (searchInFlight.current || !invQuery.trim()) return; searchInFlight.current = true; setSearching(true); setSearchError(null); try { const hits = await searchStockLedgerFixInventory(invQuery.trim()); setInvHits(hits); setScope(null); } catch (e) { console.error(e); setSearchError(apiErrorMessage(e, t("searchFailed"))); } finally { setSearching(false); searchInFlight.current = false; } }; const onSearchLot = async () => { if (searchInFlight.current || !lotQuery.trim()) return; searchInFlight.current = true; setSearching(true); setSearchError(null); try { const hits = await searchStockLedgerFixLot(lotQuery.trim()); setLotHits(hits); setScope(null); } catch (e) { console.error(e); setSearchError(apiErrorMessage(e, t("searchFailed"))); } finally { setSearching(false); searchInFlight.current = false; } }; const loadInventoryScope = async (id: number) => { if (scopeInFlight.current) return; scopeInFlight.current = true; setScopeLoading(true); setFixError(null); setFixMessage(null); try { setScope(await fetchStockLedgerFixInventoryScope(id)); } catch (e) { console.error(e); setFixError(apiErrorMessage(e, t("invLoadError"))); setScope(null); } finally { setScopeLoading(false); scopeInFlight.current = false; } }; const loadLotScope = async (id: number) => { if (scopeInFlight.current) return; scopeInFlight.current = true; setScopeLoading(true); setFixError(null); setFixMessage(null); try { setScope(await fetchStockLedgerFixLotScope(id)); } catch (e) { console.error(e); setFixError(apiErrorMessage(e, t("lotLoadError"))); setScope(null); } finally { setScopeLoading(false); scopeInFlight.current = false; } }; const onFixInventoryScope = async () => { if (!scope || scope.kind !== "inventory" || fixInFlight.current) return; const ok = window.confirm(t("invFixConfirm")); if (!ok) return; fixInFlight.current = true; setFixing(true); setFixError(null); setFixMessage(null); try { const res = await runStockLedgerFixInventoryScope(scope.id); setFixMessage( t("invFixDone", { id: scope.id, lot: res.filledLotLineId, uom: res.filledUomId, inventory: res.filledInventoryId, lotQty: res.filledLotQty, balance: res.filledBalance, dayRows: res.dayRowsWritten, }), ); await loadInventoryScope(scope.id); } catch (e) { console.error(e); setFixError(apiErrorMessage(e, t("fixFailed"))); } finally { setFixing(false); fixInFlight.current = false; } }; const onFixLotScope = async () => { if (!scope || scope.kind !== "lot" || fixInFlight.current) return; const ok = window.confirm(t("lotFixConfirm")); if (!ok) return; fixInFlight.current = true; setFixing(true); setFixError(null); setFixMessage(null); try { const res = await runStockLedgerFixLotScope(scope.id); setFixMessage( t("lotFixDone", { id: scope.id, lot: res.filledLotLineId, uom: res.filledUomId, inventory: res.filledInventoryId, lotQty: res.filledLotQty, dayRows: res.dayRowsWritten, }), ); await loadLotScope(scope.id); } catch (e) { console.error(e); setFixError(apiErrorMessage(e, t("fixFailed"))); } finally { setFixing(false); fixInFlight.current = false; } }; const canFixDay = Boolean(selected && !selected.isAfter(dayjs(), "day")); const onFixDayRange = async () => { if (fixInFlight.current) return; const from = chainFrom.trim(); const to = chainTo.trim(); const today = dayjs().format("YYYY-MM-DD"); if (!from || !to) { setFixError(t("rangeFromRequired")); return; } if (to < from) { setFixError(t("toMustBeGteFrom")); return; } if (from < FIRST_LEDGER_DAY.format("YYYY-MM-DD")) { setFixError(t("fromTooEarly", { date: FIRST_LEDGER_DAY.format("YYYY-MM-DD") })); return; } if (to > today) { setFixError(t("cannotFixFutureRange")); return; } const picked = selectedDaySteps(daySteps); if (picked.length === 0) { setFixError(t("pickAtLeastOneStep")); return; } const steps = stepsPayload(daySteps); const stepLabel = steps?.join(listSep) ?? t("allSteps216"); const ok = window.confirm( t("rangeConfirm", { from, to, steps: stepLabel }), ); if (!ok) return; fixInFlight.current = true; setChainRunning(true); setFixing(true); setFixError(null); setFixMessage(null); setChainProgress(t("rangeProgress", { from, to, steps: stepLabel })); try { const res = await runStockLedgerFixRange(from, to, steps); setFixMessage( t("rangeDone", { date: res.date, steps: stepLabel, lot: res.filledLotLineId, uom: res.filledUomId, inventory: res.filledInventoryId, lotQty: res.filledLotQty, balance: res.filledBalance, dayRows: res.dayRowsWritten, }), ); setSelected(dayjs(to)); setChainProgress(null); } catch (e) { console.error(e); setFixError(apiErrorMessage(e, t("rangeFail"))); } finally { setFixing(false); setChainRunning(false); fixInFlight.current = false; } }; const onExportSql = async () => { if (exportInFlight.current) return; const from = exportFrom.trim(); const to = exportTo.trim(); if (!from || !to) { setExportError(t("exportFromToRequired")); return; } if (to < from) { setExportError(t("toMustBeGteFrom")); return; } const picked = selectedExportParts(exportParts); if (picked.length === 0) { setExportError(t("exportPickAtLeastOne")); return; } if (exportParts["2.3"] && !exportParts["1.0"]) { const ok = window.confirm(t("export23Without10")); if (!ok) return; } const parts = exportPartsPayload(exportParts); exportInFlight.current = true; setExporting(true); setExportError(null); try { await downloadStockLedgerFixSql(from, to, parts); } catch (e) { console.error(e); const data = (e as { response?: { data?: unknown } })?.response?.data; if (data instanceof Blob) { try { const text = (await data.text()).trim().slice(0, 400); setExportError(text || t("exportFail")); } catch { setExportError(apiErrorMessage(e, t("exportFail"))); } } else { setExportError(apiErrorMessage(e, t("exportFail"))); } } finally { setExporting(false); exportInFlight.current = false; } }; return ( {t("inventory10Title")} {t("inventory10Description")} {inventoryError && {inventoryError}} {inventoryMessage && ( {inventoryMessage} )} {inventoryLoading && !inventoryPreview && } {inventoryPreview && ( {t("inventory10Preview", { rows: inventoryPreview.inventoryRows, lotPairs: inventoryPreview.lotUomPairs, missing: inventoryPreview.missingUomPairs, nullUom: inventoryPreview.nullStockUomId, })} )} {t("adjTitle")} {t("adjDescription")} { setAdjDate(e.target.value); setAdjPreview(null); setAdjMessage(null); }} disabled={adjLoading || adjRunning} InputLabelProps={{ shrink: true }} inputProps={{ max: dayjs().format("YYYY-MM-DD") }} /> {adjError && {adjError}} {adjMessage && {adjMessage}} {adjLoading && !adjPreview && } {adjPreview && ( {t("adjPreviewSummary", { date: adjPreview.adjDate, lotCount: adjPreview.lotCount, overIssueCount: adjPreview.overIssueCount, sumOverIssue: adjPreview.sumOverIssue, adjInCount: adjPreview.adjInCount, adjOutCount: adjPreview.adjOutCount, sumMissIn: adjPreview.sumMissIn, sumMissOut: adjPreview.sumMissOut, skuNet: adjPreview.skuNet, skuNetNote: adjPreview.skuNet !== "0" ? t("adjSkuNetNote") : "", revNote: adjPreview.skippedNegCount > 0 ? t("adjRevNote", { count: adjPreview.skippedNegCount }) : "", })} )} {adjPreview && adjPreview.rows.length > 0 && ( {t("adjColLotLineId")} {t("adjColItemCode")} {t("adjColLineInOut")} {t("adjColLedgerInOut")} {t("adjColMissIn")} {t("adjColMissOut")} {t("adjColOverIssue")} {adjPreview.rows.map((r) => ( {r.lotLineId} {r.itemCode ?? t("checkDash")} {r.lineIn} / {r.lineOut} {r.ledgerIn} / {r.ledgerOut} {r.missIn} {r.missOut} {r.overIssue} ))}
)}
{ setTab(v); setFixError(null); setFixMessage(null); setSearchError(null); }} > {tab === "day" && ( setSelected(v)} views={["year", "month", "day"]} openTo="day" minDate={FIRST_LEDGER_DAY} maxDate={dayjs()} /> {t("calendarHint")} {selected ? selected.format("YYYY-MM-DD") : t("selectDate")} {detailError && {detailError}} {fixError && {fixError}} {fixMessage && {fixMessage}} {chainProgress && {chainProgress}} {detailLoading && } {detail && !detailLoading && ( <> {t("dayLedgerCount", { cnt: detail.cnt })} )} {t("stepsTitle")} {t("stepsHint")} {DAY_FIX_STEPS.map((step) => ( setDaySteps((prev) => ({ ...prev, [step]: checked })) } /> } label={t(DAY_STEP_I18N[step])} /> ))} {t("rangeTitle")} {t("rangeHint")} setChainFrom(e.target.value)} disabled={chainRunning} InputLabelProps={{ shrink: true }} /> setChainTo(e.target.value)} disabled={chainRunning} InputLabelProps={{ shrink: true }} /> {t("exportTitle")} {t("exportHint")} {EXPORT_PARTS.map((part) => ( setExportParts((prev) => ({ ...prev, [part]: checked })) } /> } label={t(EXPORT_PART_I18N[part])} /> ))} {exportError && {exportError}} setExportFrom(e.target.value)} InputLabelProps={{ shrink: true }} /> setExportTo(e.target.value)} InputLabelProps={{ shrink: true }} /> )} {tab === "inventory" && ( {t("invTabHint")} setInvQuery(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") void onSearchInventory(); }} /> {searchError && {searchError}} {invHits.length > 0 && ( {t("colInventoryId")} {t("colItemCode")} {t("colUomId")} {t("colLedgerRows")} {invHits.map((h) => ( void loadInventoryScope(h.inventoryId)} sx={{ cursor: "pointer" }} > {h.inventoryId} {h.itemCode ?? t("checkDash")} {h.uomId ?? t("checkDash")} {h.ledgerCnt} ))}
)} {fixError && {fixError}} {fixMessage && {fixMessage}} {scopeLoading && } {scope?.kind === "inventory" && !scopeLoading && ( <> {t("invScopeSummary", { itemCode: scope.itemCode ?? "?", id: scope.id, uomId: scope.uomId ?? "?", firstDate: scope.firstDate, lastDate: scope.lastDate, cnt: scope.cnt, lastBalance: scope.lastBalance ?? t("checkDash"), })} )}
)} {tab === "lot" && ( {t("lotTabHint")} setLotQuery(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") void onSearchLot(); }} /> {searchError && {searchError}} {lotHits.length > 0 && ( {t("colLotLineId")} {t("colLotNo")} {t("colItemCode")} {t("colInventoryId")} {t("colLedgerRows")} {lotHits.map((h) => ( void loadLotScope(h.inventoryLotLineId)} sx={{ cursor: "pointer" }} > {h.inventoryLotLineId} {h.lotNo ?? t("checkDash")} {h.itemCode ?? t("checkDash")} {h.inventoryId ?? t("checkDash")} {h.ledgerCnt} ))}
)} {fixError && {fixError}} {fixMessage && {fixMessage}} {scopeLoading && } {scope?.kind === "lot" && !scopeLoading && ( <> {t("lotScopeSummary", { lotNo: scope.lotNo ?? "?", id: scope.id, itemCode: scope.itemCode ?? "?", firstDate: scope.firstDate, lastDate: scope.lastDate, cnt: scope.cnt, lastLotQtyAfter: scope.lastLotQtyAfter ?? t("checkDash"), })} )}
)}
); }; export default StockLedgerFixPageClient;