process.env.CANGKU_SKIP_BOOTSTRAP = '1'; const fs = require('fs'); const path = require('path'); const XLSX = require('xlsx'); const cloudDb = require('../src/config/cloudDatabase'); // 表格的 12 个流水列 → 配置字段名 const FLOW_FIELDS = [ ['加工进仓', 'processIn'], ['采购退货', 'purchaseReturn'], ['采购进仓', 'purchaseIn'], ['其它进仓', 'otherIn'], ['其它退货', 'otherReturn'], ['销售出仓', 'salesOut'], ['盘点', 'stocktaking'], ['加工出仓', 'processOut'], ['调拨出', 'transferOut'], ['销售退货', 'salesReturn'], ['调拨入', 'transferIn'], ['其它出库', 'otherOut'], ]; (async () => { const wb = XLSX.readFile('C:/Users/15018737611/Desktop/库存监控.xlsx'); const rows = XLSX.utils.sheet_to_json(wb.Sheets['Sheet1'], { header: 1, defval: '' }); const h = rows[0]; const idx = Object.fromEntries(h.map((c, i) => [String(c).trim(), i])); const level1 = String(rows[1][idx['一级功能按键']]).trim(); const level2 = String(rows[1][idx['二级功能按键']]).trim(); console.log('一级功能:', level1, '| 二级功能:', level2); const whs = await cloudDb.query(`SELECT name, wms_co_id FROM rpt.jst_warehouseInfo`); const byName = new Map(whs.map((w) => [String(w.name).trim(), w.wms_co_id])); const records = []; const missing = []; for (const r of rows.slice(1)) { const sheetName = String(r[idx['仓库']] || '').trim(); if (!sheetName) continue; const base = sheetName.replace(/主仓$/, ''); const wmsCoId = byName.get(base) ?? byName.get(sheetName) ?? null; if (wmsCoId == null) missing.push(sheetName); const num = (k) => { const v = r[idx[k]]; return typeof v === 'number' ? v : Number(String(v || '').replace(/,/g, '')) || 0; }; const flows = Object.fromEntries(FLOW_FIELDS.map(([cn, en]) => [en, num(cn)])); const openExtra = r[idx['期初']]; // 第二个「期初」列,索引会与「期初数量」冲突,单独处理 records.push({ warehouse: sheetName, dbWarehouse: base, wmsCoId, openingQty: num('期初数量'), openingQtyExtra: typeof openExtra === 'number' ? openExtra : Number(openExtra) || 0, ...flows, }); } console.log('记录数:', records.length, '| 缺 wms_co_id:', missing.length, missing.join(',') || '(无)'); const FLOW_COLUMNS_DEF = FLOW_FIELDS.map(([cn, en]) => ({ label: cn, field: en })); const out = `/** * 每日进销存 —— 2026-09-22 进销存基准流水 * * 来源:桌面《库存监控.xlsx》(聚水潭 22 号进销存导出) * 用途:业务库 JSReportReplica 没有按天的历史库存结存表,也缺少调拨/盘点/加工/其它出入库 * 单据表,期初与各流水列无法从业务库还原,故以该导出作为 22 号基准值。 * * 口径约定: * - openingQty 与 12 个流水列:22 号基准值(本文件静态存储) * - 期末数量:运行时取 jst_inventoryInfo 实时库存(与本文件基准期末一致,24/25 精确) * - 库存周转天数 / 四级库存量:运行时由 pm_stockMonitor 计算 */ /** 一级/二级菜单名(取自表格) */ const DAILY_INVENTORY_LEVEL1 = '${level1}'; const DAILY_INVENTORY_LEVEL2 = '${level2}'; /** 基准数据日期 */ const BASELINE_DATE = '2026-09-22'; /** 12 个流水列的中文表头与字段映射(顺序与表格一致) */ const FLOW_COLUMNS = ${JSON.stringify(FLOW_COLUMNS_DEF, null, 2)}; /** 25 个仓库的 22 号基准流水 */ const DAILY_INVENTORY_BASELINE = ${JSON.stringify(records, null, 2)}; module.exports = { DAILY_INVENTORY_LEVEL1, DAILY_INVENTORY_LEVEL2, BASELINE_DATE, FLOW_COLUMNS, DAILY_INVENTORY_BASELINE, }; `; const target = path.join(__dirname, '../src/config/dailyInventoryBaseline.js'); fs.writeFileSync(target, out, 'utf8'); console.log('已生成:', target); console.log('\n前 2 条预览:'); console.log(JSON.stringify(records.slice(0, 2), null, 1)); process.exit(0); })().catch((e) => { console.log('ERR', e.message); process.exit(1); });