NOTEBackend Engineering

物流系统 Bug 为什么反复出现:把业务规则放到真正改变状态的位置

本文结论

四类看似无关的物流系统缺陷,实际都来自同一个问题:业务规则只写在页面或接口入口,没有覆盖真正改变状态和数据的共同操作。

物流系统中的小 Bug 经常反复出现,不一定是规则没有写,而是规则只写在某个按钮、页面或异常分支里,没有覆盖真正改变业务状态和数据的入口。

下面四类缺陷来自不同功能,但中心问题相同:业务规则必须放到真正改变状态或数据的共同操作中,并让所有入口返回一致的处理结果。

编辑权限必须约束动作,而不只是按钮

费用详情只允许在 NEWREJECTED 状态编辑。页面隐藏了部分按钮,但表格事件仍能打开编辑框,导致已经进入财务流程的数据存在被修改的风险。

修复不能停在视觉层。编辑动作的统一入口必须先检查状态,后端也需要拒绝越权更新。验证时不仅点击可见按钮,还要覆盖行事件、快捷操作和直接请求。

这说明权限和状态规则必须保护“执行编辑”这个动作,而不只是控制“显示按钮”。

批量接口必须以单条记录为业务边界

一个车辆批量接口原本在任意一条数据失败时终止整个请求。调用方只能看到批次失败,却不知道哪些记录已经有效、哪些需要修正。

当业务允许部分成功时,系统应按单条记录处理:

  • 每条记录独立校验和处理;
  • 单条异常不终止后续记录;
  • 响应返回逐条成功、失败和可操作原因;
  • 重试只针对失败项,避免重复处理已成功数据。

HTTP 200 只能说明批次请求完成,不能代替每条业务记录的真实结果。

计算规则必须覆盖所有数据入口

订单可能从接口导入,也可能由页面手工创建。净重和体积需要优先使用包装单位配置,缺失时才回退到 SKU 基础字段。

如果只修页面或只修导入接口,同一业务对象会因为入口不同得到不同结果。可靠的实现应把计算规则放进共享领域逻辑,并同时验证接口录入、页面录入、包装配置存在和缺失四种场景。

这条规则应放在“生成订单重量和体积”的共同计算中,而不是只放在某个页面或接口里。

外部错误必须在安全范围内保留诊断意义

SAP 或 OpenAPI 已经返回明确失败原因时,统一替换成“调用失败”会切断排障证据。用户无法判断问题属于网络、数据关系、字段映射还是外部状态。

正确做法也不是原样暴露底层堆栈。响应需要保留经过筛选的业务错误、关联标识和失败类别,同时去掉密钥、内部路径和敏感数据。

错误信息是否合格,应看下一位处理者能否据此采取行动,而不只是看程序有没有捕获异常。

用同一组问题检查规则放置位置

这些缺陷可以用一组问题提前发现:

  1. 哪个动作真正改变状态或数据?
  2. 页面、批量接口、导入和重试是否都经过同一规则?
  3. 失败应影响整批、单条记录,还是单个外部调用?
  4. 响应能否区分业务失败、传输失败和未知失败?
  5. 验证是否覆盖绕过按钮、重复请求和备用入口?

多数反复出现的 Bug 不是缺少复杂算法,而是同一规则散落在多个入口。把规则放到真正改变状态或数据的共同操作中,再从用户动作和最终数据验证,修复才不会依赖某一个页面恰好按预期工作。

遇到类似系统问题?

先说明系统,再说明症状

如果需要生产排障、DevOps 交付或物流系统集成协作,请提供当前表现、预期结果、受影响环境、可用日志或数据样例,以及发布限制。我会从现有证据开始判断。

通过邮件开始