ABAP 委外采购收货调用过账bapi

相关的表:

ekko:采购凭证抬头表 用于判断是否委外
ekpo:采购凭证行项目表 用于判断是否委外以及委外采购的数量
resb:获取委外采购单中bom的相应预留
mseg:获取已经委外原材料出库给供应商的批次
mslb:获取提供给供应商的库存以及批次

bapi

BAPI_GOODSMVT_CREATE:过账bapi

相关移动类型

101:采购收货过账
541:委外原材料出库过账(这里的逻辑默认已经原料出库了)
543:消耗委外原材料出库到供应商的库存的数据

委外流程

创建委外采购单

委外采购单:4500000908

因为bom组件过多,我用作测试的话,就在采购订单中删除了很多bom组件,只留了两个

委外原材料过账

审批后进行委外过账,我这边也是通过接口过账的,也是用的BAPI_GOODSMVT_CREATE这个bapi,移动类型541
过账后你会在mmbe里查看物料的库存时发现有提供给供应商的库存

委外采购过账

因为涉及系统之间的传输,所以并不能完整给出代码,但是主体处理是没有问题的,部分参数我也写死了,根据自己需要改写即可

  DATA: ls_header LIKE  bapi2017_gm_head_01,
        lv_code   LIKE  bapi2017_gm_code VALUE '01',
        lv_doc    TYPE  bapi2017_gm_head_ret-mat_doc,
        lv_year   TYPE  bapi2017_gm_head_ret-doc_year,
        lt_item   LIKE  bapi2017_gm_item_create OCCURS 0 WITH HEADER LINE,
        lt_ret    LIKE  bapiret2 OCCURS 0 WITH HEADER LINE.

  DATA: lv_outfm TYPE mseg-menge,
        lv_outfz TYPE mseg-menge.

  DATA: lv_line_id    TYPE mseg-line_id    VALUE '000000',
        lv_parent_id  TYPE mseg-parent_id  VALUE '000000',
        lv_line_depth TYPE mseg-line_depth VALUE '00'.

"判断 是否是 委外采购订单收货
  SELECT
    FROM ekko
    INNER JOIN ekpo
    ON ekko~ebeln EQ ekpo~ebeln
  FIELDS
    ekko~ebeln,
    ekpo~ebelp,
    ekpo~matnr,
    ekko~bsart,
    ekpo~pstyp,
    ekpo~menge
  WHERE ekpo~ebeln EQ '4500000908'
    AND ekpo~ebelp EQ '00010'
    AND ekpo~matnr EQ '采购单上的物料号'
    AND ekko~bsart EQ 'Z003'
    AND ekpo~pstyp EQ '3'
  INTO TABLE @DATA(lt_outpo).

  IF lt_outpo IS NOT INITIAL. " 该采购单是委外采购单
    "获取委外采购单的相应bom预留 以及 对应批次
    SELECT
      FROM resb
      INNER JOIN mseg
      ON mseg~ebeln EQ resb~ebeln
      AND mseg~ebelp EQ resb~ebelp
      AND mseg~lifnr eq resb~lifnr
      AND mseg~matnr eq resb~matnr
    FIELDS
      mseg~matnr,
      resb~erfmg,
      resb~ebeln,
      resb~ebelp,
      mseg~werks,
      mseg~lgort,
      mseg~sobkz,
      mseg~charg,
      mseg~lifnr,
      resb~meins
    WHERE resb~ebeln EQ '4500000908'
      AND resb~ebelp EQ '00010'
      AND mseg~lifnr EQ '30108'
      AND mseg~sobkz = 'O'
    INTO TABLE @DATA(lt_outbom).

    "获取提供给的供应商库存
    SELECT
      FROM mslb
    FIELDS
      mslb~matnr,
      mslb~charg,
      mslb~werks,
      mslb~sobkz,
      mslb~lifnr,
      mslb~lblab,
      mslb~ersda
    WHERE mslb~lifnr EQ '30108'
    INTO TABLE @DATA(lt_outinv).

    SORT lt_outinv BY ersda ASCENDING.
  ENDIF.
 

  lt_item-po_number   = '4500000908'.
  lt_item-po_item     = '00010'.
  lt_item-material    = '采购单上的物料号'.
  lt_item-vendor      = '30108'.
  lt_item-entry_qnt   = '5'.
  lt_item-entry_uom   = '物料单位'.
  lt_item-plant       = '工厂'.
  lt_item-stge_loc    = '存储地点'.
  lt_item-move_type   = '101'.
  lt_item-vendrbatch  = '供应商批次'.
  lt_item-batch       = '内部批次'.
  lv_xchpf            = 'X'.
  lv_line_id         = lv_line_id + 1.
  lv_parent_id       = lv_line_id.
  lt_item-line_id    = lv_parent_id. " 父项目

  _conv_matnr: 'IN' lt_item-material.
  _conv_alpha: 'IN' lt_item-vendor.
  _conv_alpha: 'IN' lt_item-po_number.

  APPEND lt_item.
  CLEAR: lt_item.

  "上面的过账一般采购收货都是一样的 ,委外的区别就在下面这个循环,需要将bom组件的数据也写入
  IF lt_outpo IS NOT INITIAL. " 该采购单是委外采购单 需要填入明细数据 移动类型为543

      lv_outfz = '采购收货的数量'. " 过账的数量 用作分子

      READ TABLE lt_outpo INTO DATA(ls_outpo) WITH KEY ebeln = '4500000908' ebelp = '00010'.
      IF sy-subrc EQ 0.
        lv_outfm = ls_outpo-menge. " 找出采购单的数量 用作分母
      ENDIF.

      LOOP AT lt_outbom ASSIGNING FIELD-SYMBOL(<fs_outbom>) WHERE ebeln = '4500000908' AND ebelp = '00010'. " 获取bom预留
        lt_item-move_type = '543'.  " 移动类型
        lt_item-material = <fs_outbom>-matnr. " 物料号
        lt_item-plant = <fs_outbom>-werks. " 工厂
        lt_item-stge_loc = <fs_outbom>-lgort. " 存储字典
        lt_item-spec_stock = 'O'. " 特殊库存
        lt_item-batch = <fs_outbom>-charg. " 内部批次
        lt_item-entry_qnt = lv_outfz / lv_outfm * <fs_outbom>-erfmg. " 过账的成品数量 / 采购的成品数量 * BOM组件的数量
        lt_item-entry_uom = <fs_outbom>-meins. " 单位
        lt_item-parent_id = lv_parent_id. " 父项目编码
        lv_line_id = lv_line_id + 1. " 子项目编号
        lt_item-line_id = lv_line_id.
        lv_line_depth = '01'.
        lt_item-line_depth = lv_line_depth. "bom层次

        APPEND lt_item.

        CLEAR lt_item.
      ENDLOOP.
    ENDIF.

    clear it_item.

    CALL FUNCTION 'BAPI_GOODSMVT_CREATE'
    EXPORTING
      goodsmvt_header  = ls_header
      goodsmvt_code    = lv_code
    IMPORTING
      materialdocument = lv_doc
      matdocumentyear  = lv_year
    TABLES
      goodsmvt_item    = lt_item
      return           = lt_ret.

  IF lv_doc <> ''.
    CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
      EXPORTING
        wait = 'X'.

  ELSE.
    CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
  ENDIF.


posted @ 2023-02-23 13:39  otowa  阅读(2096)  评论(0)    收藏  举报