|
|
|
@@ -43,6 +43,7 @@ import { |
|
|
|
type StockLedgerFixCheckPart, |
|
|
|
type StockLedgerFixDayDetail, |
|
|
|
type StockLedgerFixInventoryPreview, |
|
|
|
type StockLedgerFixRunResponse, |
|
|
|
type StockLedgerFixScopeDetail, |
|
|
|
type StockLedgerFixSearchInventoryHit, |
|
|
|
type StockLedgerFixSearchLotHit, |
|
|
|
@@ -70,10 +71,11 @@ const DAY_STEP_LABEL: Record<DayFixStep, string> = { |
|
|
|
}; |
|
|
|
|
|
|
|
/** 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; |
|
|
|
const EXPORT_PARTS = ["1.0", "2.1", "2.3", "ledger", "2.6", "2.7"] as const; |
|
|
|
type ExportPart = (typeof EXPORT_PARTS)[number]; |
|
|
|
const DEFAULT_EXPORT_PARTS: Record<ExportPart, boolean> = { |
|
|
|
"1.0": false, |
|
|
|
"2.1": false, |
|
|
|
"2.3": false, |
|
|
|
ledger: true, |
|
|
|
"2.6": true, |
|
|
|
@@ -81,6 +83,7 @@ const DEFAULT_EXPORT_PARTS: Record<ExportPart, boolean> = { |
|
|
|
}; |
|
|
|
const FULL_EXPORT_PARTS: Record<ExportPart, boolean> = { |
|
|
|
"1.0": true, |
|
|
|
"2.1": true, |
|
|
|
"2.3": true, |
|
|
|
ledger: true, |
|
|
|
"2.6": true, |
|
|
|
@@ -88,10 +91,11 @@ const FULL_EXPORT_PARTS: Record<ExportPart, boolean> = { |
|
|
|
}; |
|
|
|
const EXPORT_PART_LABEL: Record<ExportPart, string> = { |
|
|
|
"1.0": "1.0 inventory", |
|
|
|
"2.1": "2.1 軟刪流水帳+出倉列批號", |
|
|
|
"2.3": "2.3 inventoryId", |
|
|
|
ledger: "ledger lot/uom/lotQty/balance", |
|
|
|
"2.6": "2.6 日結", |
|
|
|
"2.7": "2.7 ADJ+入出倉單", |
|
|
|
"2.7": "2.7 ADJ+入出倉單+調整記錄", |
|
|
|
}; |
|
|
|
|
|
|
|
function selectedExportParts(flags: Record<ExportPart, boolean>): ExportPart[] { |
|
|
|
@@ -115,6 +119,16 @@ function stepsPayload(flags: Record<DayFixStep, boolean>): string[] | undefined |
|
|
|
return selected; |
|
|
|
} |
|
|
|
|
|
|
|
function lotLineFixNote(res: StockLedgerFixRunResponse): string { |
|
|
|
const deleted = res.deletedUnlinkedLot ?? 0; |
|
|
|
const matched = res.existingLotMatch ?? 0; |
|
|
|
const mismatched = res.existingLotMismatch ?? 0; |
|
|
|
const blankOut = res.deletedBlankOutLine ?? 0; |
|
|
|
const alignedOut = res.alignedOutLine ?? 0; |
|
|
|
if (deleted === 0 && matched === 0 && mismatched === 0 && blankOut === 0 && alignedOut === 0) return ""; |
|
|
|
return `、軟刪未連批號 ${deleted}、出倉列空而軟刪 ${blankOut}、出倉列已改跟帳本 ${alignedOut}、已有批號相符 ${matched}、不相符 ${mismatched}`; |
|
|
|
} |
|
|
|
|
|
|
|
function apiErrorMessage(e: unknown, fallback: string): string { |
|
|
|
if (e && typeof e === "object" && "response" in e) { |
|
|
|
const data = (e as { response?: { data?: unknown } }).response?.data; |
|
|
|
@@ -380,7 +394,7 @@ const StockLedgerFixPageClient: React.FC = () => { |
|
|
|
try { |
|
|
|
const res = await runStockLedgerFixDay(date, steps); |
|
|
|
setFixMessage( |
|
|
|
`已修 ${res.date}(${stepLabel}):lot ${res.filledLotLineId}、uom ${res.filledUomId}、inventory ${res.filledInventoryId}、lotQty ${res.filledLotQty}、balance ${res.filledBalance}、日結 ${res.dayRowsWritten}`, |
|
|
|
`已修 ${res.date}(${stepLabel}):lot ${res.filledLotLineId}、uom ${res.filledUomId}、inventory ${res.filledInventoryId}、lotQty ${res.filledLotQty}、balance ${res.filledBalance}、日結 ${res.dayRowsWritten}${lotLineFixNote(res)}`, |
|
|
|
); |
|
|
|
await loadDay(date); |
|
|
|
} catch (e) { |
|
|
|
@@ -429,7 +443,7 @@ const StockLedgerFixPageClient: React.FC = () => { |
|
|
|
return; |
|
|
|
} |
|
|
|
const ok = window.confirm( |
|
|
|
`會在 ${d} 對最後餘額不等於 onHandQty 的庫存桶各寫一筆 ADJ(入或出),掛在既有 lot 上。不改 lot line、不改 inventory。已對齊的桶不會再寫。確定?`, |
|
|
|
`會在 ${d} 對最後餘額不等於 onHandQty 的庫存桶各寫一筆 ADJ(入或出),掛在既有 lot 上,並寫入庫存調整記錄。不改 lot line、不改 inventory。已對齊的桶不會再寫;缺調整記錄的舊 ADJ 會補上。確定?`, |
|
|
|
); |
|
|
|
if (!ok) return; |
|
|
|
adjRunInFlight.current = true; |
|
|
|
@@ -439,7 +453,7 @@ const StockLedgerFixPageClient: React.FC = () => { |
|
|
|
try { |
|
|
|
const res = await runStockLedgerFixAdj(d); |
|
|
|
setAdjMessage( |
|
|
|
`ADJ ${res.adjDate}:入 ${res.insertedIn}、出 ${res.insertedOut}、lotQty ${res.filledLotQty}、balance ${res.filledBalance}、日結 ${res.dayRowsWritten}`, |
|
|
|
`ADJ ${res.adjDate}:入 ${res.insertedIn}、出 ${res.insertedOut}、調整記錄 ${res.adjustmentRecords ?? 0}、lotQty ${res.filledLotQty}、balance ${res.filledBalance}、日結 ${res.dayRowsWritten}`, |
|
|
|
); |
|
|
|
} catch (e) { |
|
|
|
console.error(e); |
|
|
|
@@ -535,7 +549,7 @@ const StockLedgerFixPageClient: React.FC = () => { |
|
|
|
try { |
|
|
|
const res = await runStockLedgerFixInventoryScope(scope.id); |
|
|
|
setFixMessage( |
|
|
|
`已修 inventory ${scope.id}:lot ${res.filledLotLineId}、uom ${res.filledUomId}、inventory ${res.filledInventoryId}、lotQty ${res.filledLotQty}、balance ${res.filledBalance}、日結 ${res.dayRowsWritten}`, |
|
|
|
`已修 inventory ${scope.id}:lot ${res.filledLotLineId}、uom ${res.filledUomId}、inventory ${res.filledInventoryId}、lotQty ${res.filledLotQty}、balance ${res.filledBalance}、日結 ${res.dayRowsWritten}${lotLineFixNote(res)}`, |
|
|
|
); |
|
|
|
await loadInventoryScope(scope.id); |
|
|
|
} catch (e) { |
|
|
|
@@ -560,7 +574,7 @@ const StockLedgerFixPageClient: React.FC = () => { |
|
|
|
try { |
|
|
|
const res = await runStockLedgerFixLotScope(scope.id); |
|
|
|
setFixMessage( |
|
|
|
`已修 lot ${scope.id}:lot ${res.filledLotLineId}、uom ${res.filledUomId}、inventory ${res.filledInventoryId}、lotQty ${res.filledLotQty}、日結 ${res.dayRowsWritten}`, |
|
|
|
`已修 lot ${scope.id}:lot ${res.filledLotLineId}、uom ${res.filledUomId}、inventory ${res.filledInventoryId}、lotQty ${res.filledLotQty}、日結 ${res.dayRowsWritten}${lotLineFixNote(res)}`, |
|
|
|
); |
|
|
|
await loadLotScope(scope.id); |
|
|
|
} catch (e) { |
|
|
|
@@ -616,7 +630,7 @@ const StockLedgerFixPageClient: React.FC = () => { |
|
|
|
try { |
|
|
|
const res = await runStockLedgerFixRange(from, to, steps); |
|
|
|
setFixMessage( |
|
|
|
`區間修完成 ${res.date}(${stepLabel}):lot ${res.filledLotLineId}、uom ${res.filledUomId}、inventory ${res.filledInventoryId}、lotQty ${res.filledLotQty}、balance ${res.filledBalance}、日結 ${res.dayRowsWritten}`, |
|
|
|
`區間修完成 ${res.date}(${stepLabel}):lot ${res.filledLotLineId}、uom ${res.filledUomId}、inventory ${res.filledInventoryId}、lotQty ${res.filledLotQty}、balance ${res.filledBalance}、日結 ${res.dayRowsWritten}${lotLineFixNote(res)}`, |
|
|
|
); |
|
|
|
setSelected(dayjs(to)); |
|
|
|
setChainProgress(null); |
|
|
|
@@ -907,8 +921,8 @@ const StockLedgerFixPageClient: React.FC = () => { |
|
|
|
匯出已修 SQL(新庫用) |
|
|
|
</Typography> |
|
|
|
<Typography variant="body2" color="text.secondary" sx={{ mb: 1 }}> |
|
|
|
勾選要匯出的段落(同日修步驟)。套檔順序:1.0 → ledger(±2.3)→ 2.7 入出倉單+ADJ INSERT → |
|
|
|
2.6。完整檔(含 1.0+2.3)且正式庫 freeze/id 同源時,可跳過正式庫 1.0/2.3。預設只匯 |
|
|
|
勾選要匯出的段落(同日修步驟)。套檔順序:1.0 → 2.1 → ledger(±2.3)→ 2.7 入出倉單+調整記錄+ADJ → |
|
|
|
2.6。完整檔且正式庫 freeze/id 同源、日期蓋過全部已修日子時,結果與已修庫相同。預設只匯 |
|
|
|
ledger+日結(舊行為)。 |
|
|
|
</Typography> |
|
|
|
<Stack direction="row" spacing={0} flexWrap="wrap" useFlexGap sx={{ mb: 1 }}> |
|
|
|
|