|
|
|
@@ -93,7 +93,7 @@ const EXPORT_PART_LABEL: Record<ExportPart, string> = { |
|
|
|
"2.3": "2.3 inventoryId", |
|
|
|
ledger: "ledger lot/uom/lotQty/balance", |
|
|
|
"2.6": "2.6 日結", |
|
|
|
"2.7": "2.7 ADJ INSERT", |
|
|
|
"2.7": "2.7 ADJ+入出倉單", |
|
|
|
}; |
|
|
|
|
|
|
|
function selectedExportParts(flags: Record<ExportPart, boolean>): ExportPart[] { |
|
|
|
@@ -426,7 +426,7 @@ const StockLedgerFixPageClient: React.FC = () => { |
|
|
|
const onInventory = async () => { |
|
|
|
if (inventoryRunInFlight.current) return; |
|
|
|
const ok = window.confirm( |
|
|
|
"方案 A:保留現有 inventory.id,補缺 (itemId, uomId),並用 lot 的 in−out 重算全部數量。沒有 lot 的 UOM 會變成 0。不會改 inventory_lot_line。確定執行?", |
|
|
|
"方案 A:保留現有 inventory.id;從 lot 回填 stockUomId(舊 uomId 是 stock 則改回 base);補缺 (itemId, stockUomId);用 lot 的 in−out 重算 onHand/unavailable。不寫 onHoldQty、不改 inventory_lot_line。確定執行?", |
|
|
|
); |
|
|
|
if (!ok) return; |
|
|
|
inventoryRunInFlight.current = true; |
|
|
|
@@ -436,7 +436,7 @@ const StockLedgerFixPageClient: React.FC = () => { |
|
|
|
try { |
|
|
|
const res = await runStockLedgerFixInventory(); |
|
|
|
setInventoryMessage( |
|
|
|
`inventory 1.0 完成:新增 ${res.inserted} 列、重算 ${res.updated} 列、之後仍缺 UOM ${res.missingUomPairsAfter}`, |
|
|
|
`inventory 1.0 完成:回填 stockUomId ${res.patchedStockUomId} 列、新增 ${res.inserted} 列、重算 ${res.updated} 列、之後仍缺 UOM ${res.missingUomPairsAfter}、仍 NULL stockUomId ${res.nullStockUomIdAfter}`, |
|
|
|
); |
|
|
|
await loadInventory(); |
|
|
|
} catch (e) { |
|
|
|
@@ -456,7 +456,7 @@ const StockLedgerFixPageClient: React.FC = () => { |
|
|
|
return; |
|
|
|
} |
|
|
|
const ok = window.confirm( |
|
|
|
`會在 ${d} 新增 ADJ:入向 ${adjPreview?.adjInCount ?? 0} 筆、出向 ${adjPreview?.adjOutCount ?? 0} 筆(含反向調整)。缺入合計 ${adjPreview?.sumMissIn ?? "?"}、缺出合計 ${adjPreview?.sumMissOut ?? "?"}。目標:每 lot 最後 lotQtyAfter = line remain。已對齊的 lot 不會再動。確定?`, |
|
|
|
`會在 ${d} 先修超發 remain→0(${adjPreview?.overIssueCount ?? 0} 條 lot,合計 ${adjPreview?.sumOverIssue ?? "?"},會改 lot inQty)。再補 miss ADJ:入向 ${adjPreview?.adjInCount ?? 0} 筆、出向 ${adjPreview?.adjOutCount ?? 0} 筆。入向全部掛同一張入倉單、出向全部掛同一張出倉單(miss 不改 lot 數量)。缺入合計 ${adjPreview?.sumMissIn ?? "?"}、缺出合計 ${adjPreview?.sumMissOut ?? "?"}。確定?`, |
|
|
|
); |
|
|
|
if (!ok) return; |
|
|
|
adjRunInFlight.current = true; |
|
|
|
@@ -466,7 +466,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}:超發 remain→0 ${res.overIssuePatched}、入 ${res.insertedIn}、出 ${res.insertedOut}、lotQty ${res.filledLotQty}、balance ${res.filledBalance}、日結 ${res.dayRowsWritten}`, |
|
|
|
); |
|
|
|
await loadAdjPreview(); |
|
|
|
} catch (e) { |
|
|
|
@@ -631,7 +631,7 @@ const StockLedgerFixPageClient: React.FC = () => { |
|
|
|
const steps = stepsPayload(daySteps); |
|
|
|
const stepLabel = steps?.join("、") ?? "全部 2.1–2.6"; |
|
|
|
const ok = window.confirm( |
|
|
|
`一次修 ${from} → ${to}(步驟:${stepLabel})。2.1–2.5 整段一次算、2.6 仍依日寫日結。過程中無法中停。確定?`, |
|
|
|
`一次修 ${from} → ${to}(步驟:${stepLabel})。改為逐日跑(每天 commit)。中途失敗時已跑完的天會留下。確定?`, |
|
|
|
); |
|
|
|
if (!ok) return; |
|
|
|
|
|
|
|
@@ -724,7 +724,8 @@ const StockLedgerFixPageClient: React.FC = () => { |
|
|
|
<Typography variant="body2"> |
|
|
|
現有 inventory {inventoryPreview.inventoryRows} 列;lot 的 |
|
|
|
item+UOM {inventoryPreview.lotUomPairs} 組;缺{" "} |
|
|
|
{inventoryPreview.missingUomPairs} 組。 |
|
|
|
{inventoryPreview.missingUomPairs} 組;stockUomId 仍 NULL{" "} |
|
|
|
{inventoryPreview.nullStockUomId} 列。 |
|
|
|
</Typography> |
|
|
|
)} |
|
|
|
<Box> |
|
|
|
@@ -742,11 +743,13 @@ const StockLedgerFixPageClient: React.FC = () => { |
|
|
|
|
|
|
|
<Paper sx={{ p: 2 }}> |
|
|
|
<Stack spacing={1.5}> |
|
|
|
<Typography variant="h6">2.7 ADJ:line in/out 對齊 ledger</Typography> |
|
|
|
<Typography variant="h6">2.7 ADJ:超發 remain→0,再對齊 ledger</Typography> |
|
|
|
<Typography variant="body2" color="text.secondary"> |
|
|
|
請先選 ADJ 日期再預覽。預設昨天;freeze dump 夜可選今天(例如 31/8 23:17 寫 ADJ 到 |
|
|
|
31/8)。比對每 lot 的 line in/out 與 ledger 加總;有差就 ADJ。目標:最後一筆 |
|
|
|
lotQtyAfter = line remain。明細最多 20 列。 |
|
|
|
31/8)。先處理超發(line 入少於出):把該 lot 的 inQty 補到等於 outQty(remain=0,trigger |
|
|
|
重算 inventory)。再處理 miss:line 與 ledger 有差就 ADJ,掛既有 lot 的入/出倉行(不改 lot |
|
|
|
數量)。一次 Apply 共用一張入倉單、一張出倉單,下面多行;同一 ADJ 日期再跑會沿用這兩張單。 |
|
|
|
明細最多 20 列。 |
|
|
|
</Typography> |
|
|
|
<Stack direction="row" spacing={1} alignItems="center" flexWrap="wrap" useFlexGap> |
|
|
|
<TextField |
|
|
|
@@ -789,15 +792,16 @@ const StockLedgerFixPageClient: React.FC = () => { |
|
|
|
{adjLoading && !adjPreview && <CircularProgress size={24} />} |
|
|
|
{adjPreview && ( |
|
|
|
<Typography variant="body2"> |
|
|
|
ADJ 日期 {adjPreview.adjDate};可補 {adjPreview.lotCount} 條 |
|
|
|
lot(入 {adjPreview.adjInCount}、出 {adjPreview.adjOutCount});缺入合計{" "} |
|
|
|
ADJ 日期 {adjPreview.adjDate};可處理 {adjPreview.lotCount} 條 |
|
|
|
lot(超發 remain→0 {adjPreview.overIssueCount}、合計 {adjPreview.sumOverIssue};miss 入{" "} |
|
|
|
{adjPreview.adjInCount}、出 {adjPreview.adjOutCount});缺入合計{" "} |
|
|
|
{adjPreview.sumMissIn}、缺出合計 {adjPreview.sumMissOut};SKU 淨額{" "} |
|
|
|
{adjPreview.skuNet} |
|
|
|
{adjPreview.skuNet !== "0" ? "(非 0 表示有缺入沒有對應缺出)" : ""} |
|
|
|
{adjPreview.skippedNegCount > 0 |
|
|
|
? `;含反向 ADJ ${adjPreview.skippedNegCount} 條(ledger 多記)` |
|
|
|
: ""} |
|
|
|
。下列最多 20 列。 |
|
|
|
。下列最多 20 列(超發優先)。 |
|
|
|
</Typography> |
|
|
|
)} |
|
|
|
{adjPreview && adjPreview.rows.length > 0 && ( |
|
|
|
@@ -810,6 +814,7 @@ const StockLedgerFixPageClient: React.FC = () => { |
|
|
|
<TableCell align="right">ledger in/out</TableCell> |
|
|
|
<TableCell align="right">缺入</TableCell> |
|
|
|
<TableCell align="right">缺出</TableCell> |
|
|
|
<TableCell align="right">超發</TableCell> |
|
|
|
</TableRow> |
|
|
|
</TableHead> |
|
|
|
<TableBody> |
|
|
|
@@ -825,6 +830,7 @@ const StockLedgerFixPageClient: React.FC = () => { |
|
|
|
</TableCell> |
|
|
|
<TableCell align="right">{r.missIn}</TableCell> |
|
|
|
<TableCell align="right">{r.missOut}</TableCell> |
|
|
|
<TableCell align="right">{r.overIssue}</TableCell> |
|
|
|
</TableRow> |
|
|
|
))} |
|
|
|
</TableBody> |
|
|
|
@@ -949,7 +955,7 @@ const StockLedgerFixPageClient: React.FC = () => { |
|
|
|
區間修(2.1–2.6 一次) |
|
|
|
</Typography> |
|
|
|
<Typography variant="body2" color="text.secondary" sx={{ mb: 1 }}> |
|
|
|
使用上面勾的步驟,整段日期一次 API。2.1–2.5 用同一視窗算完;2.6 日結仍依日寫入。可含今天(freeze dump 夜)。最長約 20 分鐘。 |
|
|
|
使用上面勾的步驟,一次 API 但改為逐日(與單日修相同 SQL,每天 commit)。可含今天(freeze dump 夜)。前端最長約 20 分鐘;大區間仍建議匯出 SQL。 |
|
|
|
</Typography> |
|
|
|
<Stack direction="row" spacing={1} alignItems="center" flexWrap="wrap" useFlexGap> |
|
|
|
<TextField |
|
|
|
@@ -984,7 +990,7 @@ const StockLedgerFixPageClient: React.FC = () => { |
|
|
|
匯出已修 SQL(新庫用) |
|
|
|
</Typography> |
|
|
|
<Typography variant="body2" color="text.secondary" sx={{ mb: 1 }}> |
|
|
|
勾選要匯出的段落(同日修步驟)。套檔順序:1.0 → ledger(±2.3)→ 2.7 INSERT → |
|
|
|
勾選要匯出的段落(同日修步驟)。套檔順序:1.0 → ledger(±2.3)→ 2.7 入出倉單+ADJ INSERT → |
|
|
|
2.6。完整檔(含 1.0+2.3)且正式庫 freeze/id 同源時,可跳過正式庫 1.0/2.3。預設只匯 |
|
|
|
ledger+日結(舊行為)。 |
|
|
|
</Typography> |
|
|
|
|