'use strict'; // 聚水潭「加工单查询」接入自检脚本 // // 用法: // cd backend // node scripts/jst-manufacture-probe.js # 查最近 7 天 // node scripts/jst-manufacture-probe.js 14 # 查最近 14 天(内部按 7 天分段) // node scripts/jst-manufacture-probe.js 7 904533 # 额外按指定加工单号探测 // // 作用: // 1. 校验 JST_APP_KEY / JST_APP_SECRET / JST_ACCESS_TOKEN 是否可用 // 2. 自动探测 4 种签名变体,告诉你 JST_SIGN_VARIANT 该填哪个 // 3. 打印首屏加工单原始结构(含 items 明细的 sku_id / qty / io_qty),用于确认「在途数量」取值口径 const path = require('path'); require('dotenv').config({ path: path.resolve(__dirname, '../.env') }); const jushuitan = require('../src/services/jushuitanClient'); const MANUFACTURE_PATH = '/open/jushuitan/manufacture/query'; const PAGE_SIZE = 50; function pad(value) { return String(value).padStart(2, '0'); } function formatDateTime(date) { return ( `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ` + `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}` ); } function printConfig() { const info = jushuitan.describeConfig(); console.log('== 凭证 =='); console.log(` API 地址 : ${info.baseUrl}`); console.log(` app_key : ${info.appKey}`); console.log(` app_secret : ${info.appSecret}`); console.log(` access_token : ${info.accessToken}`); console.log(` 当前签名变体 : ${info.signVariant}`); console.log(` 是否已配置完整: ${info.configured}`); console.log(''); if (!info.configured) { console.log('✗ 凭证不完整,请先在 backend/.env 里补上 JST_APP_KEY / JST_APP_SECRET / JST_ACCESS_TOKEN'); return false; } return true; } function buildParams({ startTime, endTime, pageIndex = 1, poId = null }) { const params = { page_index: pageIndex, page_size: PAGE_SIZE, date_type: 2, // 2 = 加工日期 start_time: startTime, end_time: endTime, }; if (poId) { delete params.start_time; delete params.end_time; params.po_id = poId; } return params; } function summarizePage(payload) { const data = payload && payload.data ? payload.data : payload; const list = (data && (data.datas || data.items || data.list)) || []; console.log(` 返回条数: ${Array.isArray(list) ? list.length : '未知'}`); if (!Array.isArray(list) || list.length === 0) return; const first = list[0]; console.log(' 首条加工单字段:', Object.keys(first).join(', ')); console.log(' 首条摘要:', JSON.stringify({ po_id: first.po_id, po_date: first.po_date, seller: first.seller, status: first.status, sub_type: first.sub_type, wms_co_id: first.wms_co_id, receipt_wms_co_id: first.receipt_wms_co_id, })); const items = first.items || first.items_json || []; if (Array.isArray(items) && items.length) { console.log(' items 字段:', Object.keys(items[0]).join(', ')); console.log(' 首条 items 前 2 项:', JSON.stringify(items.slice(0, 2))); } else { console.log(' ⚠️ 首条没有 items 数组,完整结构如下(截断 800 字):'); console.log(JSON.stringify(first).slice(0, 800)); } } async function main() { console.log('=== 聚水潭「加工单查询」自检 ===\n'); if (!printConfig()) process.exitCode = 1; const days = Math.max(1, Number.parseInt(process.argv[2] || '7', 10) || 7); const poId = (process.argv[3] || '').trim() || null; const end = new Date(); const start = new Date(end.getTime() - days * 24 * 60 * 60 * 1000); const startTime = formatDateTime(start); const endTime = formatDateTime(end); console.log(`== 查询窗口 == ${startTime} ~ ${endTime}(date_type=2 加工日期)\n`); console.log('== 签名变体探测 =='); let result; try { result = await jushuitan.probeSignVariants( MANUFACTURE_PATH, buildParams({ startTime, endTime, pageIndex: 1 }) ); } catch (error) { console.log(`✗ 调用异常: ${error.message}`); process.exitCode = 1; return; } for (const attempt of result.attempts) { const mark = attempt.ok ? '✓ 成功' : '✗ 失败'; console.log(` ${attempt.variant.padEnd(11)} ${mark} ${attempt.error ? `- ${attempt.error}` : ''}`); } if (!result.variant) { console.log('\n✗ 4 种签名变体全部失败,请检查:app_key/app_secret 是否正确、access_token 是否过期、应用是否有「加工单查询」权限'); process.exitCode = 1; return; } console.log(`\n✓ 有效签名变体: ${result.variant}`); console.log(` 请在 backend/.env 写入: JST_SIGN_VARIANT=${result.variant}\n`); console.log('== 数据预览 =='); summarizePage(result.payload); console.log(''); if (poId) { console.log(`== 按加工单号探测 po_id=${poId} ==`); try { const byId = await jushuitan.callApi(MANUFACTURE_PATH, { page_index: 1, page_size: PAGE_SIZE, po_id: poId, }); summarizePage(byId); } catch (error) { console.log(` ✗ ${error.message}`); } console.log(''); } console.log('== 下一步 =='); console.log(' 1) 把有效签名变体写入 backend/.env 的 JST_SIGN_VARIANT'); console.log(' 2) 确认 items 里的 qty / io_qty 口径(在途 ≈ qty - io_qty)'); console.log(' 3) 告诉我结果,我接上库存明细表的「采购在途数」并做定时同步'); } main().catch((error) => { console.error(`脚本异常: ${error && error.stack ? error.stack : error}`); process.exitCode = 1; });