Web 版 ERP 的 BOM 展开与 MRP 运算实现
BOM 展开和 MRP 运算是 ERP 生产模块的立身之本——也是天真实现在真实数据上崩盘的地方。一个十层 BOM 的产成品横跨几百张订单,展开就是几万行组件需求。本文完整走一遍我们使用的数据模型与算法,针对 Web 架构调校:计划员期望几秒内看到结果。
BOM 建模
BOM 是有向无环图,存为边表:(父项物料ID, 子项物料ID, 用量, 损耗率, 版本, 生效日期)。三个建模决策至关重要:
- 版本与生效日期——换料不能改写历史。每条 BOM 边带版本和生效区间;展开永远取"计划日期生效的那个版本"。
- 边上的损耗/良率——某道工序损耗 6% 所以要用 1.06 个,这是边的数据,不该让 MRP 去猜。
- 虚拟件——从不入库的半成品应标记
phantom并直接穿透展开,否则 MRP 会为一个没人单独生产的东西生成计划订单。
展开:递归、记忆化、防环
展开就是把用量沿树逐层相乘。两个不可妥协的护栏:
- 环检测——每条路径维护已访问集合;某物料在自己的路径上再次出现说明主数据出了问题,运算必须中止并报出环的名称,而不是递归到栈溢出。
- 记忆化——同一个半成品子件经常出现在很多分支里。按物料(以物料、版本、数量系数为键)缓存展开子树,运算复杂度从指数级坍缩到接近"不同物料数线性"。
实践中,触及 5000 个不同物料的展开在服务端一秒以内完成。结果存为快照,计划员可以审计 MRP 运行时到底看到了什么。
净需求:从毛需求到计划订单
经典的逐物料、逐计划期(通常按天或按周)净需求算法:
- 毛需求——展开需求之和,加独立需求(销售预测、备件)。
- 计划接收——该期到货的未结采购订单和已确认计划订单。
- 预计可用量——现存量减安全库存,按期滚动。
- 净需求——预计可用量变负时产生计划订单,按物料的批量规则(批对批、固定批量、最小批量)取值,并按提前期倒排。
按低阶码顺序处理物料(子件排在父项之后),保证父项需求全部已知后才对子件净需求。低阶码在每次 BOM 版本变更时算一次,不要每次 MRP 运行都算。
速度保障
- MRP 作为批处理运行,运行开始时刻对输入(库存、未结订单、BOM 版本)做快照。针对活数据的交互式运行结果不可复现,只会惹怒计划员。
- 增量再生——BOM 子树或需求变化时只重跑受影响的物料;每晚全量,日间按需增量。
- 结果即数据,不是魔法——每个计划订单可回溯到它的溯源信息(哪些父项订单驱动了它),计划员可以追数而不是盲信。
从计划订单到车间
计划订单经计划员确认后转为工单。工单携带自己的 BOM 快照(是拷贝不是引用——设计 BOM 会漂移)和工艺路线;领料与完工回写库存,库存变动走总账与业务单据一体化设计中描述的同一财务管线。报废与返工记到工单上,成本才反映现实。工单下达的审批复用可视化审批工作流引擎——一个引擎,多种单据。
结语
BOM 和 MRP 奖励无聊工程:带版本和生效日期的边表、带防环和记忆化的展开、逐层净需求加清晰溯源、对快照跑批处理。数据模型对了算法就很短;数据模型错了,多少界面 polish 都救不回生产模块。