4. 预警阈值分级方法

保质期预警的核心不是“设一个天数”,而是把剩余保质期映射到一组有业务含义的状态上,并让不同品类、不同客户、不同仓储类型走不同的映射规则。阈值分级方法要解决三个问题:状态怎么划分、边界怎么定、差异怎么落地。本节围绕这三点展开,并给出可直接参考的配置样例。

一、状态划分:从剩余保质期到业务动作

仓储场景中,最常用的分级是四态:正常、临期、超期、禁售。四态不是按“过期与否”简单二分,而是把风险前移,让库内操作有提前量。判断依据统一采用剩余保质期天数 R,定义为:

R = 保质期截止日期 − 当前业务日期(按自然日计,不含当天则减 1)

约定 R 以“天”为单位、向下取整,且以仓库所在时区的业务日期为准,避免跨时区仓库出现边界漂移。四态的典型含义如下:

  • 正常:R 大于临期阈值,可正常出库、正常补货。
  • 临期:R 落在临期区间内,需触发促销、优先出库、调拨或客户协商。
  • 超期:R 小于等于 0 但尚未进入禁售判定,属于已过保质期、需隔离待处理。
  • 禁售:R 低于禁售阈值(通常为负值或 0),系统锁定库存,禁止销售出库,只能走报损、退货或销毁流程。

这里有一个容易混淆的点:超期与禁售不是同一件事。超期是“事实状态”,禁售是“处置状态”。有些品类(如部分冷冻食品)允许在超期后极短时间内走特殊审批,因此把两者拆开,才能让审批流和库存锁定解耦。

二、阈值边界:用“比例 + 绝对值”双约束

只按固定天数设阈值,会遇到长保质期品和短保质期品无法共用一套规则的问题。推荐采用比例阈值为主、绝对天数为兜底的双约束:

临期阈值天数 T_临期 = max(保质期总天数 × 临期比例, 临期最小天数)
禁售阈值天数 T_禁售 = min(保质期总天数 × 禁售比例, 禁售最大天数)  (通常取负值或 0)

举例(示例参数,非实测):某乳制品保质期 21 天,临期比例 30%、临期最小天数 3 天,则 T_临期 = max(21×0.3, 3) = 6.3,取整为 6 天;禁售比例 0%、禁售最大天数 0 天,则 T_禁售 = 0。于是 R≥7 为正常,1≤R≤6 为临期,R=0 为超期,R<0 为禁售。这样短保品不会被“最小天数”误伤,长保品也不会因为比例过大而提前太久预警。

比例阈值解决“相对紧迫度”,绝对天数解决“操作可行性”。两者取交集的边界,比单一维度更稳。

三、差异化设置:三个维度决定阈值

同一套阈值不可能适配所有库存。差异化主要来自三个维度,且优先级建议为客户 > 品类 > 仓储类型,即客户协议优先覆盖品类默认值,仓储类型作为环境修正项。

按品类:短保(烘焙、鲜奶、生鲜)临期比例高、最小天数小;长保(罐头、冻干)临期比例低、绝对天数可放大。品类阈值应作为基础模板,由质量或商品部门维护。

按客户:连锁商超常要求“到货时剩余保质期不低于 2/3”,而电商仓可能接受更低比例但要求更早预警。客户维度应支持在品类模板上做覆盖,例如某客户要求乳制品临期阈值从 6 天提前到 9 天。

按仓储类型:常温库、冷藏库、冷冻库的环境稳定性不同。冷冻库温度波动小,可适当放宽临期天数;常温库夏季风险高,可收紧。仓储类型通常以“修正系数”方式叠加,而不是完全重写阈值。

剩余保质期 R 的四态分级与阈值来源 R 增大(越安全) R 减小(越紧迫) 正常 R > T_临期 临期 T_禁售 < R ≤ T_临期 超期 R = 0 禁售 R < T_禁售 阈值来源(优先级:客户 > 品类 > 仓储类型) 品类基础模板 临期比例 / 最小天数 禁售比例 / 最大天数 短保收紧、长保放宽 客户协议覆盖 到货剩余比例要求 提前预警天数 覆盖品类默认值 仓储类型修正 常温 / 冷藏 / 冷冻 温度稳定性系数 叠加修正而非重写 生效阈值 = 客户覆盖 → 品类模板 → 仓储修正 按 SKU × 客户 × 仓库 生成唯一阈值记录 示例:乳制品 21 天,临期比例 30%、最小 3 天 → T_临期=6;客户要求提前至 9 天 → 覆盖为 9;冷冻库系数 1.2 → 最终 10 天。

四、配置落地:一条阈值记录长什么样

把上述规则落到系统里,最小配置单元应是“SKU × 客户 × 仓库”的一条阈值记录,而不是全局一个数字。建议字段包括:品类编码、客户编码、仓储类型、保质期总天数、临期比例、临期最小天数、禁售比例、禁售最大天数、生效优先级、生效日期。系统按优先级从高到低匹配,命中即停,未命中则回落到品类默认模板。

下面是一段可直接参考的配置样例(示例参数,非实测):

{
  "rule_id": "TH-RULE-0042",
  "scope": { "category": "DAIRY", "customer": "C-1007", "warehouse_type": "FROZEN" },
  "shelf_life_days": 21,
  "near_expiry": { "ratio": 0.30, "min_days": 3 },
  "ban_sale":    { "ratio": 0.00, "max_days": 0 },
  "priority": 20,
  "effective_from": "2025-06-01"
}

计算时先按比例与绝对值取边界,再叠加仓储修正系数,最后得到该记录下的 T_临期 与 T_禁售。注意:修正系数只作用于临期阈值,不改变禁售边界,因为禁售涉及合规,不能被环境系数放宽。

五、结果判读与常见问题

配置完成后,用一批真实库存做回放验证:取近 30 天出库记录,统计各状态占比与误报率。若临期占比长期高于 15%,说明阈值过宽或品类模板不适配;若禁售库存突然增多,优先检查客户覆盖规则是否把禁售边界写成了正值。另一个高频问题是“同一 SKU 在不同仓库状态不一致”,这通常不是 bug,而是仓储类型修正生效的正常结果,需要在报表中按仓库维度拆分展示,避免误判。

禁售阈值必须保持为 0 或负值,且不允许被客户规则覆盖为正值;否则会出现“已过期仍可售”的合规风险。

总结来说,阈值分级的关键在于:用 R 统一度量、用比例加绝对值定边界、用客户/品类/仓储三层优先级做差异化,并让每条阈值记录可追溯、可回放。这样预警才既有业务含义,又能在不同库存之间稳定复用。