128 lines
4.3 KiB
JavaScript
128 lines
4.3 KiB
JavaScript
'use strict';
|
||
|
||
const express = require('express');
|
||
const {
|
||
getMkhBomList,
|
||
getMkhBomDetail,
|
||
listMkhBomExportRows,
|
||
clearMkhBomCache,
|
||
} = require('../services/mkhBomService');
|
||
const {
|
||
getMkhReplenishAlertAdminConfig,
|
||
resetMkhReplenishAlertState,
|
||
saveMkhReplenishAlertConfig,
|
||
} = require('../services/mkhReplenishAlertSettings');
|
||
const { checkMkhReplenishAlerts } = require('../jobs/mkhReplenishAlertJob');
|
||
const {
|
||
saveYydNotificationCenterConfig,
|
||
} = require('../services/yydNotificationCenterSettings');
|
||
|
||
const router = express.Router();
|
||
|
||
function sendError(res, error, fallback) {
|
||
const status = Number(error?.statusCode) || 500;
|
||
console.error('[MkhBom]', {
|
||
message: error?.message || fallback,
|
||
code: error?.code || null,
|
||
status,
|
||
});
|
||
res.status(status).json({ success: false, error: error.message || fallback });
|
||
}
|
||
|
||
function buildSyncQuery(query = {}) {
|
||
return { ...query, live: '1', fresh: '1' };
|
||
}
|
||
|
||
// MKH-BOM 资料列表(模块化组合商品 + 配件汇总)
|
||
router.get('/list', async (req, res) => {
|
||
try {
|
||
res.set('Cache-Control', 'no-store');
|
||
res.json({ success: true, data: await getMkhBomList(req.query || {}) });
|
||
} catch (error) {
|
||
sendError(res, error, '加载 MKH-BOM 资料列表失败');
|
||
}
|
||
});
|
||
|
||
// 单个 MKH 组合商品的 BOM 配件明细(打印用)
|
||
router.get('/detail', async (req, res) => {
|
||
try {
|
||
const skuId = req.query?.skuId || req.query?.comboSkuId;
|
||
res.set('Cache-Control', 'no-store');
|
||
res.json({ success: true, data: await getMkhBomDetail(skuId) });
|
||
} catch (error) {
|
||
sendError(res, error, '加载 MKH-BOM 明细失败');
|
||
}
|
||
});
|
||
|
||
// 导出:当前筛选条件下的全部数据(不分页)
|
||
// mode=products(默认)→ 商品清单;mode=components → 配件明细摊平
|
||
router.get('/export', async (req, res) => {
|
||
try {
|
||
res.json({ success: true, data: await listMkhBomExportRows(req.query || {}) });
|
||
} catch (error) {
|
||
sendError(res, error, '导出 MKH-BOM 资料失败');
|
||
}
|
||
});
|
||
|
||
// 补货预警推送设置(接收人 / 开关 / 推送范围)
|
||
router.get('/alert-config', async (req, res) => {
|
||
try {
|
||
res.json({ success: true, data: await getMkhReplenishAlertAdminConfig() });
|
||
} catch (error) {
|
||
sendError(res, error, '加载补货预警推送设置失败');
|
||
}
|
||
});
|
||
|
||
// 保存补货预警推送设置
|
||
router.put('/alert-config', async (req, res) => {
|
||
try {
|
||
const data = await saveMkhReplenishAlertConfig(req.body || {});
|
||
res.json({ success: true, data });
|
||
} catch (error) {
|
||
sendError(res, error, '保存补货预警推送设置失败');
|
||
}
|
||
});
|
||
|
||
// 立即检查并推送(dryRun: 只预览不发送;force: 忽略「只推新增」推全量;reset: 先清空已推送记录)
|
||
router.post('/alert-check', async (req, res) => {
|
||
try {
|
||
const body = req.body || {};
|
||
if (body.reset === true) await resetMkhReplenishAlertState();
|
||
const result = await checkMkhReplenishAlerts({
|
||
dryRun: body.dryRun === true,
|
||
force: body.force === true,
|
||
});
|
||
res.json({ success: true, data: result });
|
||
} catch (error) {
|
||
sendError(res, error, '执行补货预警推送失败');
|
||
}
|
||
});
|
||
|
||
// 保存统一通知中心凭据(补货预警的推送通道)
|
||
router.put('/notification-center', async (req, res) => {
|
||
try {
|
||
await saveYydNotificationCenterConfig(req.body || {});
|
||
res.json({ success: true, data: await getMkhReplenishAlertAdminConfig() });
|
||
} catch (error) {
|
||
sendError(res, error, '保存统一通知中心配置失败');
|
||
}
|
||
});
|
||
|
||
// 手动同步:先清空本页服务端缓存(BOM / 补货索引 / 加工单 / 待发货 / 配件库存 / 仓位),
|
||
// 再在同一次请求中直连副本库读取新快照。这样不会被同步前尚未完成的旧列表请求覆盖。
|
||
router.post('/sync', async (req, res) => {
|
||
try {
|
||
const cache = clearMkhBomCache();
|
||
// fresh=1 是真正重读库存 / 加工单 / 待发货数据的协议。
|
||
// 只清缓存再传 live=1 会落到旧快照,导致按钮显示“同步成功”却数值不变。
|
||
const snapshot = await getMkhBomList(buildSyncQuery(req.body?.query));
|
||
res.set('Cache-Control', 'no-store');
|
||
res.json({ success: true, data: { cache, snapshot } });
|
||
} catch (error) {
|
||
sendError(res, error, '同步 MKH-BOM 数据失败');
|
||
}
|
||
});
|
||
|
||
module.exports = router;
|
||
module.exports._private = { buildSyncQuery };
|