# 出库流通管理 - 前端联调方案 ## 涉及页面 - 销售出库单列表页 - 销售出库单新增/编辑页 - 销售出库拣货页 - 销售出库单详情页 - 托盘码/袋码流向追踪页(可在销售出库明细区域实现) ## 业务流程与数据带入 1. CRM 客户作为经销商主数据,创建销售出库单时通过 `clientId` 选择经销商。 2. 发货通知单生成销售出库单时,沿用发货通知单的 `clientId`,作为本次出库的经销商。 3. 销售出库单提交后进入待拣货状态,扫描托盘码或袋码调用扫码接口,系统自动解析码类型、定位生产批次和合格库存。 4. 扫码成功后生成销售出库明细,记录托盘码或袋码、批次、仓库、库区、库位和拣货数量。 5. 执行拣货后占用库存,执行最终出库时扣减库存并生成库存事务流水。 6. 出库完成时固化经销商名称、实际出库时间和执行出库操作人,作为历史流向快照。 7. 前端查询销售出库明细时,通过托盘码或袋码明细关联销售出库单,即可反查工厂、批次、经销商和实际出库信息。 ## API | 方法 | 路径 | 说明 | |------|------|------| | POST | `/mes/wm/product-sales/create` | 创建销售出库单 | | PUT | `/mes/wm/product-sales/update` | 修改草稿销售出库单 | | PUT | `/mes/wm/product-sales/submit` | 提交销售出库单 | | POST | `/mes/wm/product-sales/scan` | 扫描托盘码或袋码生成拣货明细 | | PUT | `/mes/wm/product-sales/stock` | 执行拣货并占用库存 | | PUT | `/mes/wm/product-sales/shipping` | 填写承运商和运输单号 | | PUT | `/mes/wm/product-sales/finish` | 执行最终出库、扣减库存并固化流向信息 | | GET | `/mes/wm/product-sales/page` | 分页查询销售出库单,支持实际出库时间范围筛选 | | GET | `/mes/wm/product-sales/get` | 查询销售出库单详情 | | GET | `/mes/wm/product-sales-detail/list-by-line` | 查询指定销售出库行的托盘/袋码明细 | | GET | `/mes/wm/transaction/page` | 查询出库库存流水 | ### 创建/修改请求参数 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | clientId | Long | 是 | CRM 客户编号,同时作为经销商编号 | | salesDate | DateTime | 是 | 计划或业务出库日期 | | noticeId | Long | 否 | 来源发货通知单编号 | | contactName | String | 否 | 收货人 | | contactTelephone | String | 否 | 联系电话 | | contactAddress | String | 否 | 收货地址 | | carrier | String | 否 | 承运商 | | shippingNumber | String | 否 | 运输单号 | ### 扫码请求参数 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | salesId | Long | 是 | 销售出库单编号 | | scanContent | String | 是 | 托盘码、袋码或可解析的追溯码 | | quantity | Decimal | 否 | 本次拣货数量;不传时按销售出库行数量处理 | ### 扫码响应重点字段 | 字段 | 类型 | 说明 | |------|------|------| | scanType | String | `PALLET` 托盘码,`BAG` 袋码 | | scanContent | String | 原始扫描内容 | | itemId | Long | 物料编号 | | batchId | Long | 仓库批次编号 | | batchCode | String | 仓库批次号 | | materialStockId | Long | 库存记录编号 | | warehouseId | Long | 仓库编号 | | locationId | Long | 库区编号 | | areaId | Long | 库位编号 | | scanQuantity | Decimal | 本次扫描数量 | | alreadyScanned | Boolean | 是否已扫描过 | | detailId | Long | 销售出库明细编号 | ### 销售出库单响应新增字段 | 字段 | 类型 | 说明 | |------|------|------| | clientName | String | 经销商名称快照;出库完成时固化 | | outboundTime | DateTime | 实际执行出库时间;未完成时为空 | | outboundUserId | Long | 执行最终出库操作人的用户编号;未完成时为空 | | outboundUserName | String | 执行最终出库操作人的名称;未完成或用户已删除时为空 | ## 字段展示规则 | 字段 | 展示位置 | 说明 | |------|----------|------| | clientName | 出库单列表、详情、流向追踪 | 展示出库完成时固化的经销商名称;草稿可展示 CRM 当前名称 | | outboundTime | 出库单列表、详情 | 仅已完成单据展示实际出库时间 | | outboundUserId | 出库单详情 | 操作人用户编号 | | outboundUserName | 出库单列表、详情、流向追踪 | 后端已通过系统用户接口转换为操作人名称,前端直接展示 | | scanType | 扫码结果、出库明细 | 区分托盘码和袋码 | | scanContent | 扫码结果、出库明细 | 展示实际扫描的追溯码 | | batchCode | 出库明细、流向追踪 | 展示生产批次号 | | warehouseName | 出库明细、流向追踪 | 展示出库仓库 | | quantity | 出库明细、库存流水 | 展示拣货数量;流水出库数量为负数 | | bizCode | 库存流水 | 关联销售出库单号 | ## 业务规则说明 | 场景 | 规则 | |------|------| | 经销商来源 | `clientId` 复用 CRM 客户编号,不新建重复的经销商主数据 | | 托盘码扫描 | 托盘必须已绑定生产批次,否则不允许销售出库 | | 袋码扫描 | 袋码必须能定位生产批次和合格库存 | | 重复扫描 | 返回 `alreadyScanned=true`,前端提示已扫描,不重复生成明细 | | 库存不足 | 扫码或拣货校验失败时,不生成出库明细或库存占用 | | 拣货 | 拣货阶段只占用库存,不减少实际在库数量 | | 最终出库 | 仅待出库状态允许执行,成功后扣减库存并写入库存流水 | | 出库快照 | 最终出库时保存经销商名称、实际出库时间和操作人编号,后续 CRM 改名不影响历史流向 | | 流向追踪 | 通过销售出库明细中的 `palletCodeId` 或 `bagCodeId` 反查出库单、批次、仓库和经销商 | | 取消单据 | 未完成单据可取消并释放库存占用;已完成单据不可取消 | ## 注意事项 - 部署前需执行 `sql/mysql/mes_wm_sales_outbound_traceability.sql`,为销售出库主表增加流向快照字段;脚本应在确认目标数据库后逐条执行。 - 该迁移脚本不包含 `tenant_id` 字段,符合当前项目数据库规范。 - 当前代码记录的是操作人用户编号,前端应通过系统用户信息接口显示操作人名称。 - `/mes/wm/product-sales/finish` 是实际扣库存和产生库存流水的时点,扫码成功不代表已经完成出库。 - 查询托盘码或袋码流向时,应优先使用出库明细中的码编号及销售出库单状态过滤,避免将已取消单据作为有效流向。