
简介面向大物流仓储运营、WMS实施与供应链流程设计人员的流程梳理课件以PPT形式系统讲解LWMS四级流程定义与五级流程变更点识别。内容先界定分仓规划、园区车辆调度、销售出库、调拨出库、中转退货、出库异常管理等模块的业务定义与目标再逐条对照现状与TO BE方案涵盖入园预约、到园管控、园区规划与管理、B2B内销与外销出库、B2C波次计划与二次分拣、新增称重模块、前置与后置打印、发货确认、调拨出库及B2B中转退货红冲差异处理等要点。包内仅1个PPT文件约4.87MB目录按两级流程分两大部分展开结构清晰便于按流程节点查阅、内部培训引用与变更点复盘。已有42人学习适合需要理解WMS流程分层、识别系统变更点并推动流程落地的物流与信息化从业者参考。1. WMS 流程分层先定四级再谈系统怎么配仓库门口排四台车调度靠微信群喊装卸口空着一半另一半在等库位——这是不少大物流仓在 WMS 上线前的常态。这份《632大物流之 WMS 流程》给出的顺序正好反过来先把 LWMS 的流程层级定死WMS 下设二级流程 1 个、三级流程 5 个、四级流程 19 个每个四级流程都必须写清定义、业务目标和责任岗位再往下才是五级流程里每一步的系统动作和变更点。四级流程管的是分仓规划、园区车辆调度、销售出库、调拨出库、中转退货、出库异常管理这些必须有人背指标的事五级流程管的是入园预约、到园确认、分库并打印这类具体动作。做仓储系统实施、流程梳理的人可以把它当分层模板用——定义和目标写不清的四级流程落到系统里就是一堆没人点的按钮。2. LWMS 四级流程建模19 个流程怎么变成流程树和配置表2.1 流程分层字典二级到五级分别存什么分层不是为了画得好看。二级流程只有 1 个代表 WMS 这个业务域本身三级流程 5 个是仓储作业域的划分四级流程 19 个是真正要落到岗位和考核指标上的一层五级流程按需展开对应系统里的具体功能点比如入园预约、到园、园区规划、园区管理、分库并打印。判断某个环节该放四级还是五级有个简单标准有独立定义和考核目标的是四级只是四级流程里的一个动作或状态跳转的是五级。层级数量典型内容关键落库字段维护人二级1WMS 业务域process_code流程 owner三级5仓储作业域划分parent_code业务负责人四级19分仓规划、园区车辆调度、销售出库、调拨出库、中转退货、出库异常管理definition、business_goal、owner_role流程 owner五级按需入园预约、到园、分库并打印、扫码发货as_is_desc、to_be_desc实施顾问表的做法是宽表分层一张表存全部层级用 parent_code 自关联避免每层一张表带来的跨表查指标麻烦。四级流程的定义和目标必须是非空字段五级流程允许定义为空只有执行动作描述。CREATE TABLE lwms_process_def ( process_code VARCHAR(24) PRIMARY KEY, -- 流程编码如 WMS.03.05 process_name VARCHAR(64) NOT NULL, -- 流程名称 proc_level TINYINT NOT NULL, -- 层级2/3/4/5 parent_code VARCHAR(24), -- 上级流程编码二级为 NULL definition VARCHAR(512), -- 流程定义四级必填 business_goal VARCHAR(512), -- 业务目标四级必填 owner_role VARCHAR(64), -- 责任岗位 status TINYINT DEFAULT 1, -- 1 启用 0 停用 KEY idx_parent (parent_code), KEY idx_level (proc_level) ); INSERT INTO lwms_process_def VALUES (WMS.03.05,销售出库,4,WMS.03,产品从仓库流通到客户的过程, 通过产品核对及运输、装卸管控确保质量数量、账账账实一致,出库主管,1);参数说明process_code 用点分三段第一段是系统、第二段是三级域序号、第三段是四级序号好处是拿到一个单据能直接反推归属的流程域。owner_role 是岗位而不是人名人员轮岗时不用改表。definition 和 business_goal 分开存是因为考核口径会变、定义不会变两者混在一个字段里流程评审时很难分辨谁改了哪部分。2.2 用递归查询把四级流程挂到三级域上层级表最容易出的问题是挂错父节点导致同一流程既在出库域又在园区域下。写递归查询时顺手加一层校验插入前用触发器或应用层断言 proc_level parent.proc_level 1。WITH RECURSIVE tree AS ( SELECT process_code, process_name, proc_level, parent_code, CAST(process_name AS CHAR(255)) AS path FROM lwms_process_def WHERE parent_code IS NULL UNION ALL SELECT c.process_code, c.process_name, c.proc_level, c.parent_code, CONCAT(t.path, / , c.process_name) FROM lwms_process_def c JOIN tree t ON c.parent_code t.process_code WHERE t.proc_level c.proc_level - 1 IS NULL -- 只沿层级向下展开 ) SELECT proc_level, process_code, path FROM tree WHERE proc_level IN (3,4) ORDER BY path;递归 CTE 的起点是二级流程逐层向下拼路径。实际项目里更常用的是把整棵树缓存在 Redis 里做菜单渲染数据库只承担变更写入读多写少的情况下没必要每次点菜单都跑递归。路径字段 path 建议物化到表里配合 LIKE WMS.03% 就能筛出某个三级域下的全部四级流程比反复递归省事。2.3 五级流程的 AS-IS / TO-BE 变更点登记五级流程的价值不在流程图而在「变更点识别」。原始资料里「目前流程缺失」这句话在入园预约、到园、园区规划与管理三个环节反复出现这类条目要按 change_typeNEW 单独标出来排期时归到新建流程而不是改造流程两者的工作量估算方式完全不同。CREATE TABLE lwms_process_change ( id BIGINT AUTO_INCREMENT PRIMARY KEY, process_code VARCHAR(24) NOT NULL, -- 关联五级流程 change_type VARCHAR(16) NOT NULL, -- NEW/MODIFY/MOVE/ADD_MODULE as_is_desc VARCHAR(512), -- 现状描述 to_be_desc VARCHAR(512), -- 目标描述 impact_module VARCHAR(64) -- 影响的系统模块 ); INSERT INTO lwms_process_change(process_code,change_type,as_is_desc,to_be_desc,impact_module) VALUES (WMS.03.05.02,NEW,目前流程缺失,建立入园预约流程提前获知到车时间合理安排作业,园区调度), (WMS.03.05.09,MOVE,分库在仓库内执行,分库前移至分车之后分车与分库同岗位WMS 仅操作分库位,出库管理);change_type 的四个取值对应四类工作量NEW 要从零开发页面和接口MODIFY 只改规则MOVE 是把已有逻辑挪到上游系统ADD_MODULE 是加独立功能模块。这条区分直接决定实施排期里「要不要停在客户现场」——MOVE 类变更如果没和上游系统的负责人对齐联调阶段一定返工。3. 销售出库落地B2B 分车分库与 B2C 波次二次分拣3.1 B2B 内销/外销把分库从前端调整到分车之后B2B 出库的完整链路是发货通知、订单解析、订单集拼、分仓、下达运力任务、运力检讨、分配车辆、派送调度、分库并打印、园区管理、分库位、生成出库通知单、仓库拣货、扫码发货、安排装车、发货单据交接、发货确认、生成财务单据、装车确认、生成并打印运输合同、发车确认、运输跟踪、回单签收、回单上传。其中最值得说的一处变更是分库位置的调整分库从仓库环节前移到分车之后而且是分车与分库同岗位执行WMS 只负责操作分库位库位单可以灵活选择是否打印。这样做的直接收益是减少运作单据代价是 WMS 不再掌握完整的分库决策需要在接口上把车次信息传全。from collections import defaultdict def split_bin_by_vehicle(tasks, stock_rank, bin_avail): tasks : [(车次号, 出库单号, 商品编码, 需求数量, 可用库位列表)] stock_rank : {商品编码: [库位...]} 按拣货路径由近到远排序 bin_avail : {库位: 可用件数} 来自库存服务实时快照 返回 : {车次号: {出库单号: [(商品编码, 库位, 数量)]}} plan defaultdict(lambda: defaultdict(list)) for task_no, so_no, sku, qty, bins in tasks: left qty for bin_code in stock_rank.get(sku, []): if bin_code not in bins or left 0: continue take min(left, bin_avail.get(bin_code, 0)) if take 0: continue plan[task_no][so_no].append((sku, bin_code, take)) left - take if left 0: raise RuntimeError(f库存不足车次 {task_no} 出库单 {so_no} {sku} 缺口 {left}) return plan逻辑上先按车次分组再在车次内部按出库单拆库位。stock_rank 保证同一商品优先从离装卸门近的库位取货bin_avail 每次分库前要重新拉一次否则并发分车时会出现两个车次抢同一个库位。缺口不静默丢弃而是抛异常是因为在分车后分库的模式下缺货意味着车已经派了但装不满必须当异常走人工处理不能自动改派。3.2 B2C 波次把手工分配换成规则驱动B2C 出库的变化点之一是波次生成从手动改为规则驱动规则可配置、波次单可灵活打印。波次规则通常围绕承运商、时效要求、库区三个维度聚合命中同一组的订单合并成一个波次超过行数上限再拆波避免合拣单过厚导致分拣台压单。规则字段示例值作用承运商快递A/快递B同一承运商订单合波便于集包时效当日/次日/普通高时效订单单独成波优先下发库区A区/B区跨库区订单不进同一波减少行走最大行数200超过即拆波是否前置打印是/否控制发票与快递单打印时机def build_wave(orders, max_lines200): 按承运商时效库区聚合波次超行数上限自动拆波 buckets {} for od in orders: key (od[carrier], od[时效], od[库区]) buckets.setdefault(key, []).append(od) waves [] for key, group in buckets.items(): group.sort(keylambda o: o[下单时间]) # 先下单先出避免老单沉底 cur, lines [], 0 for od in group: n len(od[明细]) if lines n max_lines and cur: waves.append({key: key, orders: cur}) cur, lines [], 0 cur.append(od[order_no]) lines n if cur: waves.append({key: key, orders: cur}) return waves这里有两个容易踩的点。一是排序必须放在聚合之后按分组内部做全局排序会把不同承运商的单混在一起集包时反而增加摊分成本。二是最大行数按明细行数而不是订单数计算因为真正影响分拣效率的是行数一单十件和一单一件的作业量差距很大。3.3 二次分拣与前置后置打印的取舍初次拣货时把多个订单混拣成一张合拣单再到分拣台按订单拆分这就是二次分拣。系统里如果缺这个环节现场就只能靠人工记忆分单效率低且容易错。前置和后置打印的选择则跟品类强相关大电、服装类多用前置打印小电类多用后置打印判断依据是包裹体积和是否需要先贴单再打包。4. 园区车辆调度与分仓规划预约叫号、库门匹配与面积测算4.1 分仓面积测算把临时增仓变成可预测输入原始资料里现状描述的一条是「客户无法准确预测仓储面积需求临时性增仓较多无法合理规划」另一条是租仓时过度考虑成本导致仓库分散、硬件不完善。这两条其实是同一个问题面积需求没有量化输入。常见做法是用近三个月出库量的 P90 作为日均出库基准乘目标周转天数得到峰值库存再按品类实测的堆存密度折算面积。def storage_area(daily_out_qty, turnover_days, stack_density, space_util0.65): daily_out_qty : 日均出库件数建议取 P90 而非均值 turnover_days : 客户承诺的目标周转天数 stack_density : 每平米可堆存件数需分品类实测 space_util : 面积利用率含通道与作业区0.6~0.7 peak_qty daily_out_qty * turnover_days return round(peak_qty / (stack_density * space_util))参数上最容易拍脑袋的是 stack_density。同一仓库里大电和小电的堆存密度能差三倍以上用统一值算出来的面积到了旺季一定不够用。space_util 取 0.65 是个偏保守的经验值通道窄、叉车转弯半径大的仓库要到 0.55。测算结果再叠加租仓成本上限做约束求解才能同时满足「硬件条件达标」和「成本可控」两个目标。4.2 入园预约与到园时效字段怎么设计才能管住车辆入园预约、到园、园区规划与管理这三个五级流程在原资料中都是「目前流程缺失」属于从零新建。设计上不要只存一个预约时间而要存计划时间、实际时间两组字段中间差值是唯一的考核依据。CREATE TABLE park_vehicle_appointment ( appt_no VARCHAR(24) PRIMARY KEY, supplier_code VARCHAR(32) NOT NULL, -- 供应商编码 vehicle_no VARCHAR(16) NOT NULL, -- 车牌号 plan_arrive DATETIME NOT NULL, -- 预约到园时间 actual_arrive DATETIME, -- 实际到园时间 plan_gate VARCHAR(8), -- 预约装卸门 queue_no INT, -- 排队叫号序号 load_start DATETIME, -- 开始装车 load_end DATETIME, -- 装车完成 status TINYINT DEFAULT 0 -- 0 已预约 1 已到园 2 作业中 3 已离园 );字段设计的重点是 status 状态机要能在系统里跑通而不是靠人工改。实际到园时间由门岗扫码写入装车开始和结束由装卸工在终端确认四个时间点齐全后「到车准点率」和「单车装卸时长」两个指标就能自动算出来不需要额外做报表取数。排队叫号系统的序号要在到园时才生成预约阶段就发号会导致爽约车辆占号让真正到场的车排不上。4.3 库门指派评分货物、库位、门的匹配原资料提到要通过订单货物与库位情况寻找最优装卸库门提升装卸劳效。落地时一般做成评分函数对每个候选门算一个代价分取最小值的门。def gate_score(gate, task, gate_state, distance, w(0.5, 0.3, 0.2)): gate : 候选装卸门编号 task : {bins: [库位...], urgent: 是否加急} gate_state : {门: {queue: 排队车数, avg_min: 单车平均占用分钟}} distance : {库位: {门: 搬运距离(米)}} w : (距离权重, 排队权重, 加急权重) bins task[bins] avg_dist sum(distance[b][gate] for b in bins) / max(len(bins), 1) wait gate_state[gate][queue] * gate_state[gate][avg_min] urgent_penalty 0 if task[urgent] else 30 return w[0] * avg_dist w[1] * wait w[2] * urgent_penalty三个权重里距离权重调大会更偏向就近卸货、减少叉车行走排队权重调大会更偏向均衡各门负载。加急惩罚项是个软约束非加急任务被扣 30 分只有在所有门都排队时才可能分到最紧张的门避免普通任务挤占加急通道。distance 表要按实际仓库测一次填好靠人工估的距离值算出来的指派结果现场司机是不会认的。5. 变更点识别与对账排错中转退货红冲与出库异常回溯5.1 中转退货为什么一定产生红冲单中转退货的现状链路是返修订单、制定中转单、中转确认、分仓库位、扫码发货、条码验证、中转运输、签收确认、出库确认、条码存储。问题出在「中转确认时并未实际发车」导致实际出库数量与原单据不一致必须等工厂收货完毕后用红冲单处理差异。红冲单积压账实就不一致财务风险随之上升。改造方向是把中转确认和出库确认解耦库存扣减只挂在出库确认上中转确认仅做单据流转。排错时用下面这条 SQL 先找出所有确认数量与实发数量不一致且尚未红冲的单据。SELECT t.transfer_no, t.factory_code, t.confirm_qty, s.outbound_qty, t.confirm_qty - IFNULL(s.outbound_qty,0) AS diff_qty, t.confirm_time, s.outbound_time FROM wms_transfer_confirm t LEFT JOIN wms_outbound_confirm s ON s.source_no t.transfer_no WHERE s.outbound_qty IS NULL OR t.confirm_qty s.outbound_qty ORDER BY t.confirm_time DESC;diff_qty 为正说明单据已确认但货未实际发出为负说明实发多于单据。用 LEFT JOIN 而不是 INNER JOIN是为了把「有确认无出库」这类最危险的情况一并捞出来——这批单据在旧流程里正是靠红冲兜底的新流程下不能再让它产生。5.2 出库异常的分类与回溯字段原资料把出库异常分成发货错误、盘盈亏、窜货、少发、多发、状态或批次异常几类每一类需要的回溯字段并不相同。异常类型主要比对对象关键回溯字段发货错误出库单与发货单客户编码、收货地址、车次号少发/多发拣货明细与实发数量拣货人、扫码时间、库位窜货商品条码与订单商品条码、批次、经销商编码状态/批次异常库存批次与先进先出规则批次号、生产日期、库位状态盘盈亏账面库存与实盘数量盘点单号、盈亏库位、复核人少发和多发优先看拣货明细与扫码流水的差值因为扫码是逐件产生的能定位到具体哪一次扫描漏了还是多扫了。窜货要落到条码和批次上单靠商品编码查不出来。盘盈亏则必须和盘点单绑定脱离盘点批次谈盈亏没有意义。实际排错顺序建议先跑数量比对、再看条码批次、最后看时间线这样能避免一上来就翻操作日志。数量比对定位到单据条码定位到实物时间线定位到人和动作三层都指向同一个环节时才动手改流程配置。中转退货这条链路里把出库确认时间与装车完成时间做一次差值排序差值明显偏大的单据往往就是那批「确认了但没发车」的老问题值得优先拎出来单独核对。本文还有配套的精品资源点击获取