feat: 新增「仓储中心物流转运异常」页面(12 发货仓 · 每日 09:00 核验前一日已发货物流) #71

Merged
yanhui merged 1 commits from codex/yanhui-wle-20261022-01 into main 2026-10-22 09:08:58 +08:00
Collaborator

目的与范围

  • 解决的问题:新增「仓储中心物流转运异常」页面 —— 每天 09:00 核验 12 个发货仓「前一日已发货」订单的物流记录,把卡在揽收前的单按仓归口,供仓储中心跟进。
  • 修改的模块/文件(11 个文件,+2198 行,全部为本任务新增/接线,无重构):
    • 后端新增:services/warehouseLogisticsExceptionRegistry.js、services/warehouseLogisticsExceptionService.js、api/warehouseLogisticsException.js、test/warehouseLogisticsException.test.js
    • 后端接线:src/index.js(挂载 /api/warehouse-logistics-exception,+3 行)
    • 前端新增:pages/WarehouseLogisticsException/{index.jsx,style.css}、api/warehouseLogisticsException.js
    • 前端接线:config/sidebarNavigation.js(左侧栏「仓储中心物流转运异常」,排在发货时效下面)、router/index.jsx、layouts/BasicLayout.jsx
  • 是否使用 AI 及负责开发者:AI 辅助开发,开发者 yanhui。

口径要点(业务 2026-10-21 / 10-22 定版)

  • 12 个发货仓:横林二仓 / 横林三仓 / 横林二仓品牌仓 / 崔桥工厂仓 / 崔桥工厂品牌仓 / 崔桥工厂半成品包装项目仓 / 新苏北仓 / 睢宁仓 / 山东青岗集仓 / 山东品牌仓 / 山东青岗集唯品仓 / 河南洛宁仓。按仓库名最长匹配归口,子仓并入主仓;京仓-横林二仓京东云仓 排除。
  • 只统计揽收前的卡点:无物流单 / 未揽收 / 已揽收未中转 / 快递报异常 / 退回。
    运输中、派送中、已签收 一律正常 —— 干线与中转轨迹本就不回传聚水潭,原先「24h 无新轨迹 = 运输停滞」已废弃。
  • 明细按包裹、汇总按内部单号去重(一单多包裹不会放大异常率);结果缓存 5 分钟,force=1 绕过。
  • 剔除(剔掉的既不算异常也不算发货分母):
    • 承运商:顺丰系全部(唯品顺丰 / 顺丰干配 / 顺丰大件各账号)、武进安能、中铁、壹米滴答、京喜京东(快递·快运)、自提、线下、商家配送;
    • 有条件剔除:睢宁中通只在睢宁仓考核,其它仓异地打单的剔出(同一面单账号,异地揽收不畅);
    • 订单已终止:状态含取消/作废,或标签含「发货后取消」「作废」「拦截」;
    • 刷单 / 信誉单:订单标签含「刷单」「转空包」。
    • 粒度防误剔:「武进安能」不泛化成「安能」(另有常州安能新),「京喜京东」不泛化成「京东」,「顺丰干配」不泛化成「顺丰」→ 本次已按业务要求改为顺丰系全剔。
  • 时区:模块内统一用 Asia/Shanghai 取「今天」,避免生产容器 Etc/UTC 导致核验批次错位(同 #70 的教训,未改容器 TZ)。

同步与兼容性

  • 起始基线 SHA:42f60eb0cef65264b9b5245fc622db1cd9e2a06f
  • 最近同步的 main SHA:42f60eb0cef65264b9b5245fc622db1cd9e2a06f(建 PR 时 0 落后 / 0 领先)
  • 待审核任务分支 SHA:db1ba79416cfa750bf2210d78f9f3c30ab0c1bd8
  • 并行 PR、共享接口、迁移/配置影响:无。不改数据库表结构、不加索引、不改权限与部署配置、不改 backend/.env;仅在 src/index.js 追加一条路由挂载。
  • 冲突及处理理由:无冲突(git diff origin/main...HEAD 仅含上述 11 个文件)。
  • 如何确认保留了其他开发者的已有行为:git status 确认未触碰他人未提交修改���git diff --stat origin/main 逐个复核,除 index.js +3 行外全部是新增文件;未改动 AGENTS.md / 仓库规范 / 部署规范。

验证

实际执行的命令及结果(本地隔离环境,非生产库;生产只读不改):

命令 结果
node --test backend/test/warehouseLogisticsException.test.js 24 / 24 pass
npm --prefix backend run check syntax 通过;node --test 448 tests / 446 pass / 2 fail(见下,与本任务无交集)
npm --prefix frontend run check EXIT=0(lint + test + vite build 全通过)
本地接口实测 /api/warehouse-logistics-exception/list?force=1 批次「10-22 09:00 核验 · 10-21 发货」,9886 单 / 144 异常(1.5%);顺丰系与睢宁中通(异地仓)明细各 0 条残留

未通过项说明(均不在本 PR 改动文件内,属既有/环境相关失败,单独复跑可稳定复现):

  • cloudDatabaseConfigCache.test.js → 负缓存带 TTL:TTL 内不重复解析,到期后必须重试(Missing expected rejection)。本地业务库可达,负缓存路径不触发;与本 PR 无交集。
  • resilientSecretStore.test.js → secret backup survives outside the repository with owner-only permissions(438 !== 384)。Windows 下文件权限位断言差异,仓库既有失败。

人工验证路径:本地起后端 4002 + 前端 5173,左侧栏「仓储中心物流转运异常」→ 选核验日 → 核对分仓统计卡、异常类型筛选、明细列、页脚剔除口径;物流快照停更时黄/红告警正常弹出。

风险与回退

  • 已知风险:
    1. 页面按当前物流快照计算,回看历史批次是「按现在的轨迹重算」,不是当时留档(页面已明确标注)。要留档 09:00 结论需另做快照落库(未在本 PR 范围)。
    2. 剔除口径是业务规则,随时间可能再调;关键词集中在 Registry 常量里,改一处即可,页脚会自动跟随。
    3. 单次查询约 15~40s(近 30 天可选),已加 5 分钟缓存与 force=1 手动刷新;数据量增长后需评估缓存命中率。
  • 回退方式:本 PR 全部为新增文件 + index.js 一条挂载,回退只需 git revert 该合并提交;不涉及数据库迁移,无数据兼容性问题(只读查询)。

合并授权记录(规范第 6 节 · 路径二)

  • 授权人:yanhui(仓库所有者,同时是本次提交的开发者)
  • 授权时间:2026-10-22 09:05 (GMT+8)
  • 授权原话:

    走PR和部署
    (上下文:AI 完成「顺丰系全部剔除」并经本地真实数据验证后,询问是否走 PR + 部署,用户直接给出该指令)

  • 授权范围:仅本 PR(codex/yanhui-wle-20261022-01 → main,11 文件 / +2198 行)的合并,以及该合并提交的生产部署;不含其他 PR、不含强推 main。
  • 授权时最终提交 SHA:db1ba79416cfa750bf2210d78f9f3c30ab0c1bd8
  • 说明:规范要求「至少一名非提交者审核」。本 PR 为 AI 辅助、开发者即 yanhui 本人,无第三方审核者可用;仓库所有者给出明确合并 + 部署指令,按规范 6.1 以所有者书面授权代替独立审核。AI 未自审自合,授权记录同步写入 PR 评论。
## 目的与范围 - **解决的问题**:新增「仓储中心物流转运异常」页面 —— 每天 09:00 核验 12 个发货仓「前一日已发货」订单的物流记录,把卡在揽收前的单按仓归口,供仓储中心跟进。 - **修改的模块/文件**(11 个文件,+2198 行,全部为本任务新增/接线,无重构): - 后端新增:`services/warehouseLogisticsExceptionRegistry.js`、`services/warehouseLogisticsExceptionService.js`、`api/warehouseLogisticsException.js`、`test/warehouseLogisticsException.test.js` - 后端接线:`src/index.js`(挂载 `/api/warehouse-logistics-exception`,+3 行) - 前端新增:`pages/WarehouseLogisticsException/{index.jsx,style.css}`、`api/warehouseLogisticsException.js` - 前端接线:`config/sidebarNavigation.js`(左侧栏「仓储中心物流转运异常」,排在发货时效下面)、`router/index.jsx`、`layouts/BasicLayout.jsx` - **是否使用 AI 及负责开发者**:AI 辅助开发,开发者 yanhui。 ### 口径要点(业务 2026-10-21 / 10-22 定版) - 12 个发货仓:横林二仓 / 横林三仓 / 横林二仓品牌仓 / 崔桥工厂仓 / 崔桥工厂品牌仓 / 崔桥工厂半成品包装项目仓 / 新苏北仓 / 睢宁仓 / 山东青岗集仓 / 山东品牌仓 / 山东青岗集唯品仓 / 河南洛宁仓。按仓库名**最长匹配**归口,子仓并入主仓;`京仓-横林二仓京东云仓` 排除。 - 只统计**揽收前**的卡点:`无物流单` / `未揽收` / `已揽收未中转` / `快递报异常` / `退回`。 `运输中`、`派送中`、`已签收` 一律正常 —— 干线与中转轨迹本就不回传聚水潭,原先「24h 无新轨迹 = 运输停滞」已废弃。 - 明细按包裹、汇总按内部单号去重(一单多包裹不会放大异常率);结果缓存 5 分钟,`force=1` 绕过。 - 剔除(剔掉的**既不算异常也不算发货分母**): - 承运商:**顺丰系全部**(唯品顺丰 / 顺丰干配 / 顺丰大件各账号)、武进安能、中铁、壹米滴答、京喜京东(快递·快运)、自提、线下、商家配送; - 有条件剔除:**睢宁中通只在睢宁仓考核**,其它仓异地打单的剔出(同一面单账号,异地揽收不畅); - 订单已终止:状态含取消/作废,或标签含「发货后取消」「作废」「拦截」; - 刷单 / 信誉单:订单标签含「刷单」「转空包」。 - 粒度防误剔:「武进安能」不泛化成「安能」(另有常州安能新),「京喜京东」不泛化成「京东」,「顺丰干配」不泛化成「顺丰」→ 本次已按业务要求改为顺丰系全剔。 - 时区:模块内统一用 `Asia/Shanghai` 取「今天」,避免生产容器 `Etc/UTC` 导致核验批次错位(同 #70 的教训,未改容器 TZ)。 ## 同步与兼容性 - 起始基线 SHA:`42f60eb0cef65264b9b5245fc622db1cd9e2a06f` - 最近同步的 main SHA:`42f60eb0cef65264b9b5245fc622db1cd9e2a06f`(建 PR 时 0 落后 / 0 领先) - 待审核任务分支 SHA:`db1ba79416cfa750bf2210d78f9f3c30ab0c1bd8` - 并行 PR、共享接口、迁移/配置影响:无。不改数据库表结构、不加索引、不改权限与部署配置、不改 `backend/.env`;仅在 `src/index.js` 追加一条路由挂载。 - 冲突及处理理由:无冲突(`git diff origin/main...HEAD` 仅含上述 11 个文件)。 - 如何确认保留了其他开发者的已有行为:`git status` 确认未触碰他人未提交修改���`git diff --stat origin/main` 逐个复核,除 `index.js` +3 行外全部是新增文件;未改动 `AGENTS.md` / 仓库规范 / 部署规范。 ## 验证 实际执行的命令及结果(本地隔离环境,非生产库;生产只读不改): | 命令 | 结果 | |---|---| | `node --test backend/test/warehouseLogisticsException.test.js` | **24 / 24 pass** | | `npm --prefix backend run check` | syntax 通过;`node --test` **448 tests / 446 pass / 2 fail**(见下,与本任务无交集) | | `npm --prefix frontend run check` | **EXIT=0**(lint + test + vite build 全通过) | | 本地接口实测 `/api/warehouse-logistics-exception/list?force=1` | 批次「10-22 09:00 核验 · 10-21 发货」,9886 单 / 144 异常(1.5%);**顺丰系与睢宁中通(异地仓)明细各 0 条残留** | 未通过项说明(**均不在本 PR 改动文件内,属既有/环境相关失败**,单独复跑可稳定复现): - `cloudDatabaseConfigCache.test.js` → `负缓存带 TTL:TTL 内不重复解析,到期后必须重试`(`Missing expected rejection`)。本地业务库可达,负缓存路径不触发;与本 PR 无交集。 - `resilientSecretStore.test.js` → `secret backup survives outside the repository with owner-only permissions`(`438 !== 384`)。Windows 下文件权限位断言差异,仓库既有失败。 人工验证路径:本地起后端 4002 + 前端 5173,左侧栏「仓储中心物流转运异常」→ 选核验日 → 核对分仓统计卡、异常类型筛选、明细列、页脚剔除口径;物流快照停更时黄/红告警正常弹出。 ## 风险与回退 - 已知风险: 1. 页面按**当前**物流快照计算,回看历史批次是「按现在的轨迹重算」,不是当时留档(页面已明确标注)。要留档 09:00 结论需另做快照落库(未在本 PR 范围)。 2. 剔除口径是业务规则,随时间可能再调;关键词集中在 `Registry` 常量里,改一处即可,页脚会自动跟随。 3. 单次查询约 15~40s(近 30 天可选),已加 5 分钟缓存与 `force=1` 手动刷新;数据量增长后需评估缓存命中率。 - 回退方式:本 PR 全部为新增文件 + `index.js` 一条挂载,回退只需 `git revert` 该合并提交;不涉及数据库迁移,无数据兼容性问题(只读查询)。 ## 合并授权记录(规范第 6 节 · 路径二) - **授权人**:yanhui(仓库所有者,同时是本次提交的开发者) - **授权时间**:2026-10-22 09:05 (GMT+8) - **授权原话**: > 走PR和部署 (上下文:AI 完成「顺丰系全部剔除」并经本地真实数据验证后,询问是否走 PR + 部署,用户直接给出该指令) - **授权范围**:仅本 PR(`codex/yanhui-wle-20261022-01` → `main`,11 文件 / +2198 行)的合并,以及该合并提交的生产部署;不含其他 PR、不含强推 main。 - **授权时最终提交 SHA**:`db1ba79416cfa750bf2210d78f9f3c30ab0c1bd8` - **说明**:规范要求「至少一名非提交者审核」。本 PR 为 AI 辅助、开发者即 yanhui 本人,无第三方审核者可用;仓库所有者给出明确合并 + 部署指令,按规范 6.1 以所有者书面授权代替独立审核。AI 未自审自合,授权记录同步写入 PR 评论。
yanhui added 1 commit 2026-10-22 09:08:36 +08:00
- 后端新增 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 条残留
Author
Collaborator

合并授权记录(规范第 6 节 · 路径二)

  • 授权人:yanhui(仓库所有者,同时是本 PR 的开发者)
  • 授权时间:2026-10-22 09:05 (GMT+8)
  • 授权原话:

    走PR和部署

  • 授权范围:仅本 PR #71(codex/yanhui-wle-20261022-01 → main,11 文件 / +2198 行)的合并,以及该合并提交的生产部署;不含其他 PR、不含强推 main。
  • 授权时最终提交 SHA:db1ba79416cfa750bf2210d78f9f3c30ab0c1bd8
  • 基线 main SHA:42f60eb0cef65264b9b5245fc622db1cd9e2a06f
  • 说明:本 PR 为 AI 辅助开发、开发者即仓库所有者本人,无第三方审核者可用;按规范 6.1,所有者书面合并指令可代替独立审核。AI 未自审自合。

合并前校验结果

  • git rev-list --count HEAD..origin/main = 0(基线未前进)
  • 本分支自测:node --test backend/test/warehouseLogisticsException.test.js → 24/24 pass
  • npm --prefix frontend run check → EXIT=0
  • npm --prefix backend run check → 446/448 pass,2 个失败均在未改动文件(配置负缓存 / Windows 权限位断言),已在 PR 正文说明
## 合并授权记录(规范第 6 节 · 路径二) - **授权人**:yanhui(仓库所有者,同时是本 PR 的开发者) - **授权时间**:2026-10-22 09:05 (GMT+8) - **授权原话**: > 走PR和部署 - **授权范围**:仅本 PR #71(`codex/yanhui-wle-20261022-01` → `main`,11 文件 / +2198 行)的合并,以及该合并提交的生产部署;不含其他 PR、不含强推 main。 - **授权时最终提交 SHA**:`db1ba79416cfa750bf2210d78f9f3c30ab0c1bd8` - **基线 main SHA**:`42f60eb0cef65264b9b5245fc622db1cd9e2a06f` - **说明**:本 PR 为 AI 辅助开发、开发者即仓库所有者本人,无第三方审核者可用;按规范 6.1,所有者书面合并指令可代替独立审核。AI 未自审自合。 ### 合并前校验结果 - `git rev-list --count HEAD..origin/main` = 0(基线未前进) - 本分支自测:`node --test backend/test/warehouseLogisticsException.test.js` → 24/24 pass - `npm --prefix frontend run check` → EXIT=0 - `npm --prefix backend run check` → 446/448 pass,2 个失败均在未改动文件(配置负缓存 / Windows 权限位断言),已在 PR 正文说明
yanhui merged commit 9cba2f8140 into main 2026-10-22 09:08:58 +08:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: lunanting/cangku#71
No description provided.