编辑 | blame | 历史 | 原始文档

销售发货出库流程 - 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;              // 未出库
}