大宗物料销售出库 — 核心业务流程图

✍️ 作者:wr 📋 版本:1.0
基于《大宗物料销售出库项目需求v4.0》第5-10章绘制

一、整体流程概览

flowchart TD subgraph PC端["🖥️ PC端(结算中心)"] A[新建登记单] --> B[选择U8发货单] B --> C[系统拉取预填数据] C --> D[保存] D --> E[生成登记单号+二维码+路线] E --> F[打印纸质登记单] F --> G[交付司机/装卸工] end subgraph 小程序["📱 小程序(装卸工/成品库/地磅室)"] G --> H[步骤② 扫码称皮重] H --> I[步骤③ 装车扫码] I --> J[步骤④ 称毛重+确认出库] end subgraph PC审核["🖥️ PC端(结算中心)"] J --> K[步骤⑤ 审核] K --> L[保存U8出库单] L --> M[审核U8出库单] M --> N[开具出门证] N --> O[完成] end style A fill:#4CAF50,color:#fff style H fill:#2196F3,color:#fff style I fill:#FF9800,color:#fff style J fill:#FF9800,color:#fff style K fill:#9C27B0,color:#fff style O fill:#4CAF50,color:#fff

二、步骤①:创建登记单 + 打印

flowchart TD A["结算中心点击「新建登记单」"] --> B[调用U8获取发货单列表] B --> B1["POST /api/Consignment/GetPage
条件: 已保存未完成出库"] B1 --> C{发货单列表} C -->|有数据| D[选择发货单] C -->|无数据| C1["提示「无可用发货单」"] D --> E[调用U8获取发货单详情] E --> E1["POST /api/Consignment/GetDetail
返回: 表头+明细行"] E1 --> F[系统自动预填] subgraph 预填数据["自动预填"] F1["表头: 客户/部门/车牌号/日期"] F2["表体: 存货编码/名称/规格/钢号/标准/数量"] F3["存储U8关联字段: dlid/cDLcode/ccuscode等"] end F --> G["点击「保存」"] G --> H[系统自动处理] subgraph 自动处理["系统自动处理"] H1["生成登记单号: yyyyMMdd-6位随机码"] H2["生成二维码 (QRCodeUtils)"] H3[查询库位计算装车路线] H4["状态 → PENDING_TARE"] H5["保存 dzwl_outbound_header + body"] end H --> I[打印纸质登记单] I --> I1[后端返回二维码base64 + 登记单HTML] I1 --> I2["前端渲染 → window.print()"] I2 --> J[纸质单交付司机/装卸工] style A fill:#4CAF50,color:#fff style G fill:#4CAF50,color:#fff style J fill:#2196F3,color:#fff

三、步骤②:称皮重

flowchart TD A[操作者打开小程序] --> B[扫码获取登记单] B --> C{校验1: 二维码有效?} C -->|无效| C1["提示「二维码无效或已过期」"] C -->|有效| D{校验2: 状态=PENDING_TARE?} D -->|否| D1["提示「当前状态不允许此操作」"] D -->|是| E{校验3: 操作者有角色?} E -->|否| E1["提示「无操作权限」"] E -->|是| F[打开称皮重界面] F --> G[核对车牌号] G --> H[引导车辆上磅] H --> I["点击「获取皮重」"] I --> I1["POST /warehouse/weigh/getWeight
→ IWeighService → 地磅硬件
https://www.kingpipe.com:17601/process_number"] I1 --> I2[实时显示当前重量] I2 -->|等待稳定| I3["点击「绑定为皮重」"] I3 --> J[系统记录] subgraph 系统记录["自动记录"] J1["tare_operator_id / name"] J2["tare_weight = 当前重量"] J3["tare_operation_time = 当前时间"] end J --> K["状态: PENDING_TARE → TARE_DONE"] K --> L[纸质单还给司机/操作者] style B fill:#2196F3,color:#fff style I3 fill:#FF9800,color:#fff style K fill:#4CAF50,color:#fff

四、步骤③:装车扫码

flowchart TD A["操作者(装卸工/成品库人员)在小程序扫码"] --> B{校验} B -->|二维码/状态/角色| B1["状态=TARE_DONE ✓"] B1 --> C[打开装车扫码界面] C --> D[逐件装车+立即扫合格证码] D --> E{校验合格证} E -->|无效| E1["提示「合格证无效」"] E -->|已出库| E2["提示「该产品已出库(时间:XXX)」"] E -->|合同号不匹配| E3["提示「合同号不匹配」"] E -->|校验通过| F["向 dzwl_outbound_scan_record 插入记录"] subgraph 扫描记录["scan_record 字段"] F1["header_id: 登记单ID"] F2["body_id: 表体ID"] F3["inbound_body_id: 入库表体ID"] F4["track_number: 合格证码"] F5["operator_id / operator_name: 当前操作人"] F6["scan_time: 扫码时间"] F7["inbound_weight: 该件入库重量"] F8["inbound_pieces: 该件支数"] F9["warehouse_code: 库位编码(冗余)"] end F --> G[更新装车进度] G --> H[前端实时汇总] subgraph 实时汇总["显示"] H1["已绑: X 件"] H2["入库重量合计: XX.XX 吨"] H3["多人协作: 各自名下独立记录"] end H --> I{是否装车完毕?} I -->|继续装车| D I -->|完毕| J[装车完成] J --> K[纸质单还给司机/操作者] style D fill:#FF9800,color:#fff style F fill:#4CAF50,color:#fff style I fill:#9C27B0,color:#fff

五、步骤④:称毛重 + 确认出库

flowchart TD A[司机开车回地磅] --> B[操作者扫码进入界面] B --> B1["状态=TARE_DONE ✓"] B1 --> C[核对已绑定列表] C --> D["点击「获取毛重」
调用 IWeighService"] D --> E[系统自动计算] subgraph 自动计算["系统自动计算"] E1["毛重 gross_weight = 地磅读数"] E2["净重 net_weight = 毛重 - 皮重"] E3["差值 weight_diff = 净重 - 入库重量合计"] end E --> F{"差值 ≤ 0.2吨?"} F -->|否❌| F1["差值: X.XX吨 (红色醒目显示)"] F1 --> F2["「确认出库」按钮置灰"] F2 --> F3["提示「重量差异过大(X.XX吨),请检查装车产品或合格证」"] F3 --> F4[返回成品库核对] F4 --> D F -->|是✅| G["差值: X.XX吨 (绿色醒目显示)"] G --> H["「确认出库」按钮可用"] H --> I["点击「确认出库」"] I --> J[二次确认弹窗] J -->|取消| H J -->|确认| K[系统执行确认操作] subgraph 确认操作["确认出库操作"] K1["分配净重到每件产品
(按入库重量比例分配)"] K2["标记 is_delivered = 1
dzwl_inbound_body 每件记录"] K3["回写U8发货单
POST /api/Consignment/save
(callU8Api, 3次重试)"] K4["记录 confirm_operator_*"] K5["状态: TARE_DONE → PENDING_REVIEW"] end K --> L[操作完成] style D fill:#2196F3,color:#fff style F fill:#9C27B0,color:#fff style I fill:#FF5722,color:#fff style K5 fill:#4CAF50,color:#fff

六、步骤⑤:审核生成U8出库单

flowchart TD A["结算中心筛选「待审核」"] --> B[查看登记单详情] B --> C[确认数据完整] C --> D["点击「审核」"] D --> E{数据完整性检查} E -->|不完整| E1["提示「请完善XXX信息」"] E -->|完整| F["第一步: 保存U8销售出库单"] F --> F1["POST /api/SaleOut/save
callU8Api (3次重试)"] F1 --> F2{保存成功?} F2 -->|失败| F3["U8RetryHandler重试
3次×1秒间隔"] F3 --> F4{最终结果?} F4 -->|仍失败| F5["提示「U8保存失败,请稍后重试」
不阻塞审核,记录待补推"] F2 -->|成功| G["获取 u8SaleOutId
记录到 U8_saleout_id"] F4 -->|成功| G G --> H["第二步: 审核U8销售出库单"] H --> H1["POST http://www.kingpipe.com:9004
/api/saleout/Verify
?accnum={accNum}&id={u8SaleOutId}
Header: Auth = u8_integration.auth"] H1 --> H2{审核成功?} H2 -->|失败| H3["提示「U8审核失败: XXX」
记录日志,支持手动重审"] H2 -->|成功| I[审核完成] I --> I1["状态: PENDING_REVIEW → COMPLETED"] I1 --> I2["二维码失效"] I2 --> I3["开具出门证"] I3 --> J[完成] style D fill:#9C27B0,color:#fff style F fill:#2196F3,color:#fff style H fill:#2196F3,color:#fff style J fill:#4CAF50,color:#fff

七、库提拆件流程

flowchart TD A["成品库人员扫原有合格证码"] --> B[获取该件产品信息] B --> C{原有件 is_split?} C -->|已拆件| C1["提示「该件已拆件」"] C -->|未拆件| D[进入拆件界面] D --> E["填写拆出数量
支数/重量"] E --> F[系统自动生成新合格证码] F --> F1["格式: 原TrackNumber-S{序号}
例: ZS001-S1, ZS001-S2"] F1 --> G[生成两笔临时记录] subgraph 拆件记录["两笔临时记录"] G1["出库件 → dzwl_tep_outbound_body
重量 = 拆出重量
打印新合格证"] G2["剩件 → dzwl_tep_inbound_body
source_type = 'SPLIT'
重量 = 原重量 - 拆出重量
打印新合格证"] end G --> H["原有件 is_split = 1"] H --> I["成品库人员执行存盘"] I --> I1["出库存盘 → U8产成品出库单"] I --> I2["入库存盘 → U8产成品入库单"] I1 --> J[完成] I2 --> J style A fill:#FF9800,color:#fff style H fill:#F44336,color:#fff style J fill:#4CAF50,color:#fff

八、作废与重新打印

flowchart TD A[结算中心] --> B{触发场景} B -->|场景1: 作废| C[选择登记单] C --> C1{状态判断} C1 -->|已完成| C2["提示「已完成登记单不可作废」"] C1 -->|非终态| D["作废操作
状态 → CANCELLED"] D --> D1["二维码失效"] B -->|场景2: 纸质单丢失| E["重新打印"] E --> E1["原二维码自动失效"] E1 --> E2["QRCodeUtils 生成新二维码"] E2 --> E3["更新 dzwl_outbound_header.QR_code"] E3 --> E4["前端渲染 → window.print()"] style D fill:#F44336,color:#fff style E3 fill:#2196F3,color:#fff

九、异常处理分支

flowchart TD subgraph 称重异常["⚠️ 称重异常"] W1["磅差 > 0.2t"] --> W1a["提示检查产品/合格证"] W1a --> W1b[返回成品库核对] W2[地磅连接失败] --> W2a["显示「地磅连接失败」"] W2a --> W2b[手动入口 + 求助于地磅室] end subgraph 扫码异常["⚠️ 扫码异常"] S1[合格证已出库] --> S1a["提示「已出库(时间XXX)」"] S1a --> S1b[换未出库产品] S2[合同号不匹配] --> S2a["提示差异详情"] S2a --> S2b[换正确产品] S3["二维码被多人同时扫"] --> S3a["Redis锁(30s过期)"] S3a --> S3b["后扫者提示「正在被XXX操作中」"] end subgraph U8异常["⚠️ U8异常"] U1[U8超时] --> U1a["提示「U8暂不可用,本地已保存」"] U1a --> U1b[继续操作不中断] U1b --> U1c["U8RetryHandler: 3次×1秒"] U1c --> U1d{最终成功?} U1d -->|否| U1e["记录补推日志,待后续补同步"] U1d -->|是| U1f[操作继续] end subgraph 纸质单异常["⚠️ 纸质单异常"] P1[司机找不到成品库] --> P1a["纸质单上有库位编号+路线指引"] P1b[现场引导牌指引] P2[纸质单途中丢失] --> P2a["结算中心重新打印"] P2a --> P2b["旧码失效 → 新码生效"] end subgraph LocError[库位异常] C1[部分产品未指定库位] --> C1a["提示「无法计算装车路线」"] C1a --> C1b[联系成品库人员补录warehouse_code] end

十、U8完整交互时序

sequenceDiagram participant PC as 结算中心PC participant MES as MES后端 participant U8 as U8 ERP participant Scale as 地磅硬件 participant Mini as 小程序 Note over PC,U8: 阶段1 创建登记单 PC->>MES: 新建登记单 MES->>U8: 调用 GetPage 接口 U8-->>MES: 返回发货单列表 MES->>U8: 调用 GetDetail 接口 U8-->>MES: 返回发货单详情 MES->>MES: 生成登记单号与二维码 MES->>MES: 写入 dzwl_outbound 表 MES->>MES: 状态置为 PENDING_TARE MES-->>PC: 返回登记单详情与二维码 PC->>PC: 浏览器打印 Note over Mini,Scale: 阶段2 称皮重 Mini->>MES: 扫码获取登记单 MES->>MES: 校验二维码 状态 角色 MES-->>Mini: 返回登记单详情 Mini->>MES: 请求获取皮重 MES->>Scale: 调用地磅接口 Scale-->>MES: 返回重量 MES-->>Mini: 实时重量 Mini->>MES: 绑定皮重 MES->>MES: 记录操作人与皮重 MES->>MES: 状态置为 TARE_DONE Note over Mini: 阶段3 装车扫码 loop 逐件装车 Mini->>MES: 提交合格证扫描 MES->>MES: 校验有效性 已出库 合同号 MES->>MES: 写入扫描记录表 MES-->>Mini: 返回扫描结果 end Note over Mini,Scale: 阶段4 称毛重并确认出库 Mini->>MES: 获取实时数据 MES->>Scale: 调用地磅接口 Scale-->>MES: 返回毛重 MES->>MES: 计算净重与差值 MES-->>Mini: 返回重量汇总 Mini->>MES: 确认出库请求 MES->>MES: 分配净重并标记已出库 MES->>U8: 回写发货单重量 U8-->>MES: 保存成功 MES->>MES: 记录确认操作人 MES->>MES: 状态置为 PENDING_REVIEW MES-->>Mini: 确认成功 Note over PC,U8: 阶段5 审核 PC->>MES: 提交审核 MES->>MES: 幂等检查 MES->>U8: 保存销售出库单 U8-->>MES: 返回出库单ID MES->>U8: 审核销售出库单 U8-->>MES: 审核成功 MES->>MES: 状态置为 COMPLETED MES-->>PC: 审核成功 并生成出门证

状态流转总图

stateDiagram-v2 [*] --> DRAFT: PC端新建 DRAFT --> PENDING_TARE: 保存+生成二维码+计算路线 DRAFT --> CANCELLED: 结算中心作废 PENDING_TARE --> TARE_DONE: 扫码称皮重(小程序) PENDING_TARE --> CANCELLED: 结算中心作废 TARE_DONE --> PENDING_REVIEW: 装车扫码+称毛重+确认出库(小程序) TARE_DONE --> CANCELLED: 结算中心作废 PENDING_REVIEW --> COMPLETED: 结算中心审核(PC) COMPLETED --> [*]: 二维码失效+出门证+归档 CANCELLED --> [*]: 二维码失效+归档

角色与操作对照

步骤 角色 终端 操作 关键记录
结算中心 PC 建登记单 → 打印 登记单号+二维码+路线
装卸工/成品库人员/地磅室(任一人) 小程序 扫码 → 称皮重 → 绑定 tare_operator_*
装卸工/成品库人员(多人) 小程序 扫码 → 逐件装车 → 扫合格证 scan_record(每件独立)
装卸工/成品库人员/地磅室(任一人) 小程序 扫码 → 称毛重 → 确认出库 confirm_operator_* + 回写U8发货单
结算中心 PC 审核 保存+审核U8出库单

关键校验规则汇总

校验点 规则 不通过处理
扫码权限 二维码有效 + 状态匹配 + 操作者有角色 提示无权限
合格证有效性 合格证存在 + 未出库 + 未拆件 提示具体原因
合同号匹配 合格证合同号 = 登记单合同号 提示不匹配
重量校验 |净重 - 入库重量合计| ≤ 0.2吨 返回成品库核对
并发扫码 Redis锁30s,同一登记单同一时间仅1人操作 后扫者提示被占用
审核幂等 @Idempotent(expireTime=10) 防止重复生成U8出库单
U8回写重试 U8RetryHandler: 3次×1秒 失败不阻塞,记录补推
一、整体流程概览 二、步骤①:创建登记单 + 打印 三、步骤②:称皮重 四、步骤③:装车扫码 五、步骤④:称毛重 + 确认出库 六、步骤⑤:审核生成U8出库单 七、库提拆件流程 八、作废与重新打印 九、异常处理分支 十、U8完整交互时序 十一、状态流转总图 十二、角色与操作对照 十三、关键校验规则汇总