销售发货出库流程 - 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} |
查询订单明细列表 |
接口定义
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; // 备注
}
}
状态枚举
// 销售订单状态
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 |
生成销售出库单 |
接口定义
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<PageResult<SalesNotice>>
/** 查询详情 */
export function getSalesNotice(id: number): Promise<SalesNotice>
/** 创建发货通知单 */
export function createSalesNotice(data: SalesNoticeSaveReq): Promise<number>
/** 修改发货通知单 */
export function updateSalesNotice(data: SalesNoticeSaveReq): Promise<boolean>
/** 删除发货通知单 */
export function deleteSalesNotice(id: number): Promise<boolean>
/** 提交发货通知单 */
export function submitSalesNotice(id: number): Promise<boolean>
/** 从销售订单生成发货通知单 */
export function generateFromSaleOrder(saleOrderId: number): Promise<number>
/** 从发货通知单生成销售出库单 */
export function generateProductSales(id: number): Promise<number>
行表接口
文件路径: 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} |
删除 |
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; // 备注
}
}
状态枚举
// 发货通知单状态
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} |
校验数量 |
接口定义
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<PageResult<ProductSales>>
/** 查询详情 */
export function getProductSales(id: number): Promise<ProductSales>
/** 创建销售出库单 */
export function createProductSales(data: ProductSalesSaveReq): Promise<number>
/** 修改销售出库单 */
export function updateProductSales(data: ProductSalesSaveReq): Promise<boolean>
/** 删除销售出库单 */
export function deleteProductSales(id: number): Promise<boolean>
/** 提交 */
export function submitProductSales(id: number): Promise<boolean>
/** 执行拣货 */
export function stockProductSales(id: number): Promise<boolean>
/** 填写运单 */
export function shippingProductSales(data: ProductSalesShippingReq): Promise<boolean>
/** 执行出库 */
export function finishProductSales(id: number): Promise<boolean>
/** 取消 */
export function cancelProductSales(id: number): Promise<boolean>
/** 校验数量 */
export function checkProductSalesQuantity(id: number): Promise<boolean>
行表接口
文件路径: 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} |
删除 |
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} |
删除 |
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; // 备注
}
}
状态枚举
// 销售出库单状态
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 |
七、生成接口调用链
// 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 出库数量计算逻辑
// 计算出库状态
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; // 未出库
}