# 销售发货出库流程 - API接口与字段汇总 ## 流程图 ``` ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ 销售订单 │───>│ 发货通知单 │───>│ 销售出库单 │───>│ 出库完成 │ │ (ERP模块) │ │ (MES模块) │ │ (MES模块) │ │ 状态回写 │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ │ ▼ ▼ ▼ ▼ 出库状态同步 出库状态同步 执行出库 状态回写上游 ``` --- ## 一、销售订单 (ERP模块) **文件路径:** `src/api/erp/sale/order/index.ts` ### 查询接口 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/erp/sale-order/page` | 分页查询 | | GET | `/erp/sale-order/get?id={id}` | 详情查询 | | GET | `/erp/sale-order/item/list-by-order-id?orderId={orderId}` | 查询订单明细列表 | ### 接口定义 ```typescript export namespace ErpSaleOrderApi { /** 销售订单信息 */ export interface SaleOrder { id?: number; // 订单ID no: string; // 销售订单号 customerId: number; // 客户ID customerName?: string; // 客户名称 orderTime: Date; // 订单时间 totalCount: number; // 合计数量 totalPrice: number; // 合计金额 status: number; // 状态:10-未审核, 20-已审核, 30-已作废 outStatus?: number; // 出库状态:0-未出库, 1-部分出库, 2-全部出库 outCount: number; // 销售出库数量 inCount?: number; // 采购入库数量 returnCount: number; // 销售退货数量 items?: SaleOrderItem[]; // 销售订单明细 } /** 销售订单明细 */ export interface SaleOrderItem { id?: number; // 明细ID seq?: number; // 序号 orderId?: number; // 订单ID productId?: number; // 产品ID productName?: string; // 产品名称 productBarCode?: string; // 产品条码 productUnitName?: string; // 单位 productPrice?: number; // 单价 count?: number; // 数量 outCount?: number; // 出库数量 taxPercent?: number; // 税率 taxPrice?: number; // 税额 remark?: string; // 备注 } } ``` ### 状态枚举 ```typescript // 销售订单状态 const SaleOrderStatus = { UN_AUDITED: 10, // 未审核 AUDITED: 20, // 已审核 CANCELLED: 30, // 已作废 } // 销售订单出库状态 const SaleOrderOutStatus = { NONE: 0, // 未出库 PARTIAL: 1, // 部分出库 ALL: 2, // 全部出库 } ``` --- ## 二、发货通知单 (MES模块) **文件路径:** `src/api/mes/wm/salesnotice/index.ts` ### 查询接口 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/mes/wm/sales-notice/page` | 分页查询 | | GET | `/mes/wm/sales-notice/get?id={id}` | 详情查询 | | POST | `/mes/wm/sales-notice/create` | 创建 | | PUT | `/mes/wm/sales-notice/update` | 修改 | | DELETE | `/mes/wm/sales-notice/delete?id={id}` | 删除 | | PUT | `/mes/wm/sales-notice/submit?id={id}` | 提交 | | POST | `/mes/wm/sales-notice/generate-from-sale-order` | 从销售订单生成 | | POST | `/mes/wm/sales-notice/generate-product-sales` | 生成销售出库单 | ### 接口定义 ```typescript export namespace MesWmSalesNoticeApi { /** 发货通知单 */ export interface SalesNotice { id?: number; // 通知单ID code?: string; // 通知单号 name?: string; // 通知单名称 saleOrderId?: number; // 销售订单ID saleOrderCode?: string; // 销售订单号 clientId?: number; // 客户ID clientName?: string; // 客户名称 salesDate?: Date; // 发货日期 recipientName?: string; // 收货人 recipientTelephone?: string; // 联系方式 recipientAddress?: string; // 收货地址 status?: number; // 单据状态:0-草稿, 20-待出库, 30-已完成 outStatus?: number; // 出库状态:0-未出库, 1-部分出库, 2-全部出库 remark?: string; // 备注 createTime?: Date; // 创建时间 } /** 创建/修改请求 */ export interface SalesNoticeSaveReq { id?: number; // 通知单ID(修改时必填) code: string; // 通知单号 name: string; // 通知单名称 clientId: number; // 客户ID saleOrderId?: number; // 销售订单ID saleOrderCode?: string; // 销售订单号 salesDate: Date; // 发货日期 recipientName?: string; // 收货人 recipientTelephone?: string; // 联系方式 recipientAddress?: string; // 收货地址 remark?: string; // 备注 } } /** 查询分页 */ export function getSalesNoticePage(params: PageParam): Promise> /** 查询详情 */ export function getSalesNotice(id: number): Promise /** 创建发货通知单 */ export function createSalesNotice(data: SalesNoticeSaveReq): Promise /** 修改发货通知单 */ export function updateSalesNotice(data: SalesNoticeSaveReq): Promise /** 删除发货通知单 */ export function deleteSalesNotice(id: number): Promise /** 提交发货通知单 */ export function submitSalesNotice(id: number): Promise /** 从销售订单生成发货通知单 */ export function generateFromSaleOrder(saleOrderId: number): Promise /** 从发货通知单生成销售出库单 */ export function generateProductSales(id: number): Promise ``` ### 行表接口 **文件路径:** `src/api/mes/wm/salesnotice/line/index.ts` | 方法 | 路径 | 说明 | |------|------|------| | GET | `/mes/wm/sales-notice-line/page` | 分页查询 | | GET | `/mes/wm/sales-notice-line/get?id={id}` | 详情查询 | | POST | `/mes/wm/sales-notice-line/create` | 创建 | | PUT | `/mes/wm/sales-notice-line/update` | 修改 | | DELETE | `/mes/wm/sales-notice-line/delete?id={id}` | 删除 | ```typescript export namespace MesWmSalesNoticeLineApi { /** 发货通知单行 */ export interface SalesNoticeLine { id?: number; // 行ID noticeId?: number; // 通知单ID saleOrderItemId?: number; // 销售订单明细ID itemId?: number; // 物料ID itemCode?: string; // 物料编码 itemName?: string; // 物料名称 specification?: string; // 规格型号 unitMeasureName?: string; // 单位 batchId?: number; // 批次ID batchCode?: string; // 批次号 quantity?: number; // 发货数量 outCount?: number; // 已出库数量 oqcCheckFlag?: boolean; // 是否检验 remark?: string; // 备注 createTime?: Date; // 创建时间 } /** 创建/修改请求 */ export interface SalesNoticeLineSaveReq { id?: number; // 行ID(修改时必填) noticeId: number; // 通知单ID saleOrderItemId?: number; // 销售订单明细ID itemId: number; // 物料ID batchId?: number; // 批次ID batchCode?: string; // 批次号 quantity: number; // 发货数量 oqcCheckFlag?: boolean; // 是否检验 remark?: string; // 备注 } } ``` ### 状态枚举 ```typescript // 发货通知单状态 const MesWmSalesNoticeStatusEnum = { PREPARE: 0, // 草稿 APPROVED: 20, // 待出库(已审核) FINISHED: 30, // 已完成 } // 发货通知单出库状态 const MesWmSalesNoticeOutStatusEnum = { NONE: 0, // 未出库 PARTIAL: 1, // 部分出库 ALL: 2, // 全部出库 } ``` --- ## 三、销售出库单 (MES模块) **文件路径:** `src/api/mes/wm/productsales/index.ts` ### 查询接口 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/mes/wm/product-sales/page` | 分页查询 | | GET | `/mes/wm/product-sales/get?id={id}` | 详情查询 | | POST | `/mes/wm/product-sales/create` | 创建 | | PUT | `/mes/wm/product-sales/update` | 修改 | | DELETE | `/mes/wm/product-sales/delete?id={id}` | 删除 | | PUT | `/mes/wm/product-sales/submit?id={id}` | 提交 | | PUT | `/mes/wm/product-sales/stock?id={id}` | 执行拣货 | | PUT | `/mes/wm/product-sales/shipping` | 填写运单 | | PUT | `/mes/wm/product-sales/finish?id={id}` | 执行出库 | | PUT | `/mes/wm/product-sales/cancel?id={id}` | 取消 | | GET | `/mes/wm/product-sales/check-quantity?id={id}` | 校验数量 | ### 接口定义 ```typescript export namespace MesWmProductSalesApi { /** 销售出库单 */ export interface ProductSales { id?: number; // 出库单ID code?: string; // 出库单号 name?: string; // 出库单名称 noticeId?: number; // 发货通知单ID noticeCode?: string; // 发货通知单号 saleOrderId?: number; // 销售订单ID salesOrderCode?: string; // 销售订单号 clientId?: number; // 客户ID clientName?: string; // 客户名称 salesDate?: Date; // 出库日期 contactName?: string; // 联系人 contactTelephone?: string; // 联系电话 contactAddress?: string; // 收货地址 carrier?: string; // 承运商 shippingNumber?: string; // 运输单号 status?: number; // 单据状态 remark?: string; // 备注 createTime?: Date; // 创建时间 } /** 创建/修改请求 */ export interface ProductSalesSaveReq { id?: number; // 出库单ID(修改时必填) code: string; // 出库单号 name: string; // 出库单名称 clientId: number; // 客户ID noticeId?: number; // 发货通知单ID saleOrderId?: number; // 销售订单ID salesOrderCode?: string; // 销售订单号 salesDate?: Date; // 出库日期 contactName?: string; // 联系人 contactTelephone?: string; // 联系电话 contactAddress?: string; // 收货地址 remark?: string; // 备注 } /** 填写运单请求 */ export interface ProductSalesShippingReq { id: number; // 出库单ID carrier: string; // 承运商 shippingNumber: string; // 运输单号 } } /** 查询分页 */ export function getProductSalesPage(params: PageParam): Promise> /** 查询详情 */ export function getProductSales(id: number): Promise /** 创建销售出库单 */ export function createProductSales(data: ProductSalesSaveReq): Promise /** 修改销售出库单 */ export function updateProductSales(data: ProductSalesSaveReq): Promise /** 删除销售出库单 */ export function deleteProductSales(id: number): Promise /** 提交 */ export function submitProductSales(id: number): Promise /** 执行拣货 */ export function stockProductSales(id: number): Promise /** 填写运单 */ export function shippingProductSales(data: ProductSalesShippingReq): Promise /** 执行出库 */ export function finishProductSales(id: number): Promise /** 取消 */ export function cancelProductSales(id: number): Promise /** 校验数量 */ export function checkProductSalesQuantity(id: number): Promise ``` ### 行表接口 **文件路径:** `src/api/mes/wm/productsales/line/index.ts` | 方法 | 路径 | 说明 | |------|------|------| | GET | `/mes/wm/product-sales-line/page` | 分页查询 | | GET | `/mes/wm/product-sales-line/get?id={id}` | 详情查询 | | POST | `/mes/wm/product-sales-line/create` | 创建 | | PUT | `/mes/wm/product-sales-line/update` | 修改 | | DELETE | `/mes/wm/product-sales-line/delete?id={id}` | 删除 | ```typescript export namespace MesWmProductSalesLineApi { /** 销售出库单行 */ export interface ProductSalesLine { id?: number; // 行ID salesId?: number; // 出库单ID noticeLineId?: number; // 发货通知单行ID saleOrderItemId?: number; // 销售订单明细ID itemId?: number; // 物料ID itemCode?: string; // 物料编码 itemName?: string; // 物料名称 specification?: string; // 规格型号 unitMeasureName?: string; // 单位 quantity?: number; // 出库数量 batchId?: number; // 批次ID batchCode?: string; // 批次号 oqcCheckFlag?: boolean; // 是否检验 oqcId?: number; // 出厂检验单ID qualityStatus?: number; // 质量状态 remark?: string; // 备注 createTime?: Date; // 创建时间 } /** 创建/修改请求 */ export interface ProductSalesLineSaveReq { id?: number; // 行ID(修改时必填) salesId: number; // 出库单ID noticeLineId?: number; // 发货通知单行ID saleOrderItemId?: number; // 销售订单明细ID itemId: number; // 物料ID quantity: number; // 出库数量 batchId?: number; // 批次ID batchCode?: string; // 批次号 oqcCheckFlag?: boolean; // 是否检验 remark?: string; // 备注 } } ``` ### 明细表接口(拣货信息) **文件路径:** `src/api/mes/wm/productsales/detail/index.ts` | 方法 | 路径 | 说明 | |------|------|------| | GET | `/mes/wm/product-sales-detail/page` | 分页查询 | | GET | `/mes/wm/product-sales-detail/get?id={id}` | 详情查询 | | POST | `/mes/wm/product-sales-detail/create` | 创建 | | PUT | `/mes/wm/product-sales-detail/update` | 修改 | | DELETE | `/mes/wm/product-sales-detail/delete?id={id}` | 删除 | ```typescript export namespace MesWmProductSalesDetailApi { /** 销售出库明细(拣货信息) */ export interface ProductSalesDetail { id?: number; // 明细ID lineId?: number; // 出库单行ID salesId?: number; // 出库单ID itemId?: number; // 物料ID itemCode?: string; // 物料编码 itemName?: string; // 物料名称 specification?: string; // 规格型号 unitMeasureName?: string; // 单位 quantity?: number; // 拣货数量 materialStockId?: number; // 库存记录ID batchId?: number; // 批次ID batchCode?: string; // 批次号 warehouseId?: number; // 仓库ID warehouseName?: string; // 仓库名称 locationId?: number; // 库区ID locationName?: string; // 库区名称 areaId?: number; // 库位ID areaName?: string; // 库位名称 remark?: string; // 备注 createTime?: Date; // 创建时间 } /** 创建/修改请求 */ export interface ProductSalesDetailSaveReq { id?: number; // 明细ID(修改时必填) lineId: number; // 出库单行ID salesId: number; // 出库单ID itemId: number; // 物料ID quantity: number; // 拣货数量 materialStockId?: number; // 库存记录ID batchId?: number; // 批次ID batchCode?: string; // 批次号 warehouseId: number; // 仓库ID locationId: number; // 库区ID areaId: number; // 库位ID remark?: string; // 备注 } } ``` ### 状态枚举 ```typescript // 销售出库单状态 const MesWmProductSalesStatusEnum = { PREPARE: 0, // 草稿 CONFIRMED: 10, // 待检测 APPROVING: 20, // 待拣货 SHIPPING: 25, // 待填写运单 APPROVED: 30, // 待执行出库 FINISHED: 40, // 已完成 CANCELLED: 50, // 已取消 } // 质量状态 const MesWmQualityStatusEnum = { PENDING: 0, // 待检验 PASS: 1, // 合格 FAIL: 2, // 不合格 } ``` --- ## 四、字段映射关系 ### 4.1 销售订单 → 发货通知单 | 销售订单字段 | 发货通知单字段 | 说明 | |-------------|---------------|------| | `id` | `saleOrderId` | 销售订单ID | | `no` | `saleOrderCode` | 销售订单号 | | `customerId` | `clientId` | 客户ID | | `customerName` | `clientName` | 客户名称 | ### 4.2 发货通知单 → 销售出库单 | 发货通知单字段 | 销售出库单字段 | 说明 | |---------------|---------------|------| | `id` | `noticeId` | 发货通知单ID | | `code` | `noticeCode` | 发货通知单号 | | `saleOrderId` | `saleOrderId` | 销售订单ID | | `saleOrderCode` | `salesOrderCode` | 销售订单号 | | `clientId` | `clientId` | 客户ID | | `clientName` | `clientName` | 客户名称 | | `recipientName` | `contactName` | 收货人→联系人 | | `recipientTelephone` | `contactTelephone` | 联系电话 | | `recipientAddress` | `contactAddress` | 收货地址 | | `salesDate` | `salesDate` | 出库日期 | ### 4.3 发货通知单行 → 销售出库单行 | 发货通知单行字段 | 销售出库单行字段 | 说明 | |-----------------|-----------------|------| | `id` | `noticeLineId` | 发货通知单行ID | | `saleOrderItemId` | `saleOrderItemId` | 销售订单明细ID | | `itemId` | `itemId` | 物料ID | | `quantity` | `quantity` | 出库数量 | | `batchId` | `batchId` | 批次ID | | `batchCode` | `batchCode` | 批次号 | | `oqcCheckFlag` | `oqcCheckFlag` | 是否检验 | --- ## 五、状态流转 ### 5.1 单据状态流转 ``` 销售订单:未审核 → 已审核 → [出库状态同步] ↓ 发货通知单:草稿 → 待出库 → [部分出库/全部出库] → 已完成 ↓ 销售出库单:草稿 → 提交 → 拣货 → 发货 → 执行出库 ↓ [状态回写上游] ``` ### 5.2 出库状态更新时机 | 触发动作 | 更新单据 | 更新内容 | |---------|---------|---------| | 销售出库单执行出库 | 发货通知单行 | `outCount` 累加 | | 销售出库单执行出库 | 发货通知单 | `outStatus` 更新 | | 销售出库单执行出库 | 销售订单行 | `outCount` 累加 | | 销售出库单执行出库 | 销售订单 | `outStatus` 更新 | ### 5.3 销售出库单完整状态流转 ``` ┌─────────────────────────────────────────────────────────────────────┐ │ 销售出库单状态流转 │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ 草稿(PREPARE:0) │ │ │ │ │ │ 提交 │ │ ▼ │ │ ┌───┴───┐ │ │ │ │ │ │ │ │ 有OQC检验行 ───► 待检测(CONFIRMED:10) │ │ │ │ │ │ │ │ │ │ OQC检验完成 │ │ │ │ ▼ │ │ │ │ 待拣货(APPROVING:20) ◄──┐ │ │ │ │ │ │ │ │ │ 无OQC检验行 ──────────────────────────────┘ │ │ │ │ │ │ └───┬───┘ │ │ │ │ │ │ 执行拣货 │ │ ▼ │ │ 待填写运单(SHIPPING:25) │ │ │ │ │ │ 填写运单 │ │ ▼ │ │ 待执行出库(APPROVED:30) │ │ │ │ │ │ 执行出库 │ │ ▼ │ │ 已完成(FINISHED:40) │ │ │ │ 任意状态 ──取消──► 已取消(CANCELLED:50) │ │ │ └─────────────────────────────────────────────────────────────────────┘ ``` --- ## 六、前端页面路径 | 页面 | 路径 | 文件 | |------|------|------| | 销售订单列表 | `/erp/sale/order` | `src/views/erp/sale/order/index.vue` | | 发货通知单列表 | `/wls/sales-notice` | `src/views/wls/salesnotice/index.vue` | | 销售出库单列表 | `/wls/product-sales` | `src/views/wls/productsales/index.vue` | --- ## 七、生成接口调用链 ```typescript // 1. 销售订单生成发货通知单 const noticeId = await generateFromSaleOrder(saleOrderId); // 2. 发货通知单生成销售出库单 const productSalesId = await generateProductSales(noticeId); // 3. 销售出库单提交 await submitProductSales(productSalesId); // 4. 执行拣货(需要先添加拣货明细) await stockProductSales(productSalesId); // 5. 填写运单 await shippingProductSales({ id: productSalesId, carrier: '顺丰', shippingNumber: 'SF123' }); // 6. 执行出库(会自动回写状态到发货通知单和销售订单) await finishProductSales(productSalesId); ``` --- ## 八、关键业务规则 ### 8.1 生成规则 | 场景 | 规则 | |------|------| | 发货通知单生成条件 | 销售订单状态为"已审核" | | 销售出库单生成条件 | 发货通知单状态为"待出库" | | 生成后状态 | 均为"草稿"状态,需要提交后才能流转 | ### 8.2 出库完成后的状态回写 | 回写对象 | 回写内容 | |---------|---------| | 发货通知单行 | `outCount += 实际出库数量` | | 发货通知单 | `outStatus = 计算结果(0/1/2)` | | 发货通知单 | 如果 `outStatus === 2`(全部出库),则 `status = 30`(已完成) | | ERP销售订单行 | `outCount += 实际出库数量` | | ERP销售订单 | `outStatus = 计算结果(0/1/2)` | ### 8.3 出库数量计算逻辑 ```typescript // 计算出库状态 function calculateOutStatus(lines: SalesNoticeLine[]): number { let allOut = true; let anyOut = false; for (const line of lines) { const quantity = line.quantity || 0; const outCount = line.outCount || 0; if (outCount > 0) anyOut = true; if (outCount < quantity) allOut = false; } if (allOut) return 2; // 全部出库 if (anyOut) return 1; // 部分出库 return 0; // 未出库 } ```