- 后端新增 warehouse-logistics-exception 模块(Registry / Service / Api),
挂载 /api/warehouse-logistics-exception;前端新增独立页面并接入左侧栏
「仓储中心物流转运异常」(排在「仓储中心 24 小时发货时效」下面)。
- 核验口径:核验日 09:00 看**前一日已发货**订单的物流记录;12 个发货仓按仓库名
最长匹配归口(子仓并入主仓,「京仓-横林二仓京东云仓」排除)。
只统计揽收前的卡点:无物流单 / 未揽收 / 已揽收未中转 / 快递报异常 / 退回;
运输中、派送中、已签收一律正常(干线与中转轨迹本就不回传,不再按 24h 判停滞)。
明细按包裹、汇总按内部单号去重;结果缓存 5 分钟,force=1 可绕过。
- 剔除口径(业务 2026-10-21 / 10-22 定版,剔掉的既不算异常也不算发货分母):
· 承运商:顺丰系全部(唯品顺丰 / 顺丰干配 / 顺丰大件各账号)、武进安能、中铁、
壹米滴答、京喜京东(快递·快运)、自提、线下、商家配送;
· 有条件剔除:睢宁中通只在睢宁仓考核,其它仓异地打单的剔出;
· 订单已终止:状态含取消/作废,或标签含「发货后取消」「作废」「拦截」;
· 刷单 / 信誉单:订单标签含「刷单」「转空包」。
「武进安能」「京喜京东」均按精确粒度匹配,不泛化成「安能」「京东」,避免误剔
常州安能新、京东自营快递亿家达等正常账号。
- 时区:模块内统一用 Asia/Shanghai 取「今天」,避免生产容器 Etc/UTC 导致核验批次错位。
- 页面:分仓统计卡 + 异常类型筛选 + 明细(承运商 / 运单号 / 物流状态 / 异常标签 /
最后轨迹 / 发货时间 / 待处理小时),页脚展示剔除口径与本批剔除量;
物流快照停更按黄/红两级告警,并标注「历史批次按当前物流快照重算」。
验证(本地隔离环境,非生产库):
- node --test backend/test/warehouseLogisticsException.test.js → 24/24 通过
- npm --prefix frontend run check → 通过
- 本地真实数据接口实测:顺丰系、睢宁中通(异地仓)明细 0 条残留
57 lines
1.9 KiB
JavaScript
57 lines
1.9 KiB
JavaScript
'use strict';
|
||
|
||
/**
|
||
* 仓储中心物流转运异常 —— HTTP 路由(2026-10-21 新增)
|
||
* ────────────────────────────────────────────────────────────────────────────
|
||
* GET /api/warehouse-logistics-exception/list
|
||
* query:
|
||
* date 核验日 'YYYY-MM-DD'(默认:已过 09:00 用今天,否则用昨天)
|
||
* limit 明细条数上限(默认 500,最大 2000)
|
||
* force 1 = 绕过 5 分钟结果缓存
|
||
*
|
||
* 挂载见 src/index.js:`/api/warehouse-logistics-exception` + authMiddleware
|
||
*/
|
||
|
||
const express = require('express');
|
||
const { getLogisticsExceptions } = require('../services/warehouseLogisticsExceptionService');
|
||
const {
|
||
CENTERS, EXCEPTION_TYPES, LOOKBACK_DAYS, VERIFY_HOUR,
|
||
} = require('../services/warehouseLogisticsExceptionRegistry');
|
||
|
||
const router = express.Router();
|
||
|
||
function sendError(res, error, fallback) {
|
||
const status = Number(error?.statusCode) || 500;
|
||
console.error('[WarehouseLogisticsException]', {
|
||
message: error?.message || fallback,
|
||
code: error?.code || null,
|
||
status,
|
||
});
|
||
res.status(status).json({ success: false, error: error.message || fallback });
|
||
}
|
||
|
||
// 转运异常总览:12 个发货仓异常单量 + 明细
|
||
router.get('/list', async (req, res) => {
|
||
try {
|
||
const data = await getLogisticsExceptions(req.query || {});
|
||
res.json({ success: true, data });
|
||
} catch (error) {
|
||
sendError(res, error, '加载物流转运异常失败');
|
||
}
|
||
});
|
||
|
||
// 口径元数据(不查库,秒回):页面文案与图例用它,避免前后端各写一套
|
||
router.get('/meta', (_req, res) => {
|
||
res.json({
|
||
success: true,
|
||
data: {
|
||
verifyHour: VERIFY_HOUR,
|
||
lookbackDays: LOOKBACK_DAYS,
|
||
centers: CENTERS.map((c) => ({ key: c.key, name: c.name })),
|
||
exceptionTypes: EXCEPTION_TYPES,
|
||
},
|
||
});
|
||
});
|
||
|
||
module.exports = router;
|