【SAP Abap】SAP采购订单创建 BAPI_PO_CREATE1 使用详解

SAP采购订单创建 BAPI_PO_CREATE1 使用详解

1、Demo代码

说明:Demo主要包含以下内容:
1、不同类型PO单的创建:供方采购订单、内部转储订单;
2、采购表头、行项目增强;
3、采购表头、行项目长文本维护;
4、同一BAPI COMMIT中多次调用注意事项;
5、BAPI字段与底表字段关系。

* ME21N-PO采购单创建(采购订单、转储订单)
FORM zfrm_bapi_po_create.
  " 必要参数
  DATA: ls_poheader     TYPE bapimepoheader,                                " PO抬头数据
        ls_poheaderx    TYPE bapimepoheaderx ,
        lt_return       TYPE TABLE OF bapiret2           WITH HEADER LINE,  "返回消息
        lt_poitem       TYPE TABLE OF bapimepoitem       WITH HEADER LINE,  "PO行项目
        lt_poitemx      TYPE TABLE OF bapimepoitemx      WITH HEADER LINE,
        lt_poschedule   TYPE TABLE OF bapimeposchedule   WITH HEADER LINE,  "PO计划行
        lt_poschedulex  TYPE TABLE OF bapimeposchedulx   WITH HEADER LINE.
  " 可选参数
  DATA: lt_pocond       TYPE TABLE OF bapimepocond       WITH HEADER LINE,  "PO条件
        lt_pocondx      TYPE TABLE OF bapimepocondx      WITH HEADER LINE,
        lt_poaccount    TYPE TABLE OF bapimepoaccount    WITH HEADER LINE,  "PO科目分配
        lt_poaccountx   TYPE TABLE OF bapimepoaccountx   WITH HEADER LINE,
        lt_potextitem   TYPE TABLE OF bapimepotext       WITH HEADER LINE.  "行文本
  " 增强参数
  DATA: lt_extensionin  TYPE TABLE OF bapiparex WITH HEADER LINE,
        ls_header_ext   TYPE bapi_te_mepoheader,
        ls_header_extx  TYPE bapi_te_mepoheaderx,
        ls_item_ext     TYPE bapi_te_mepoitem,
        ls_item_extx    TYPE bapi_te_mepoitemx,
        ls_account_ext  TYPE bapi_te_mepoaccounting,
        ls_account_extx TYPE bapi_te_mepoaccountingx.

  DATA: lv_error TYPE c,			" 出错标识
        lv_ebeln TYPE ekpo-ebeln,   " 采购单号
        lv_ebelp TYPE ekpo-ebelp.   " 采购行号

  " 演示结构,BAPI对应底表字段关系
  DATA: ls_dm_ekko TYPE ekko,  " 采购凭证抬头,
        ls_dm_ekpo TYPE ekpo,  " 采购凭证项目
        ls_dm_eket type eket.  " 计划协议计划行

  " 1、PO抬头数据
  ls_poheader-doc_date    = ls_dm_ekko-bedat.   " 采购凭证日期,sy-datum
  ls_poheader-doc_type    = ls_dm_ekko-bsart.   " 采购凭证类型
  " 当外部供应商采购时
  ls_poheader-vendor      = ls_dm_ekko-lifnr.   " 供应商帐户号
*  " 当公司间采购时
*  ls_poheader-suppl_plnt  = ls_dm_ekko-reswk.  " 供应工厂
  ls_poheader-comp_code   = ls_dm_ekko-bukrs.   " 公司代码
  ls_poheader-purch_org   = ls_dm_ekko-ekorg .  " 采购组织
  ls_poheader-pur_group   = ls_dm_ekko-ekgrp.   " 采购组
  "以下为可选字段
  ls_poheader-currency    = ls_dm_ekko-waers.   " 货币码,'CNY'
  ls_poheader-created_by  = ls_dm_ekko-ernam.   " 对象创建人姓名
  ls_poheader-creat_date  = ls_dm_ekko-aedat.   " 记录建立日期
  ls_poheader-langu       = ls_dm_ekko-spras.   " 语言
  ls_poheader-status      = ls_dm_ekko-statu.   " 采购凭证的状态,'I'
* ls_poheader-pmnttrms    = ls_dm_ekko-zterm.   " 收付条件代码
  ls_poheader-item_intvl  = ls_dm_ekko-pincr.   " 项目编号间隔,space
*  ls_poheader-r ef_1       = ls_dm_ekko-IHREZ.   " 您的参考
*  ls_poheader-OUR_REF      = ls_dm_ekko-unsez.     " 我们的参考

  ls_poheaderx-doc_date   = 'X'.
  ls_poheaderx-doc_type   = 'X'.
  ls_poheaderx-vendor     = 'X'.
*  ls_poheaderx-suppl_plnt  = 'X'.
  ls_poheaderx-comp_code  = 'X'.
  ls_poheaderx-purch_org  = 'X'.
  ls_poheaderx-pur_group  = 'X'.
  "以下为可选字段
  ls_poheaderx-currency   = 'X'.
  ls_poheaderx-created_by  ='X'.
  ls_poheaderx-creat_date  ='X'.
  ls_poheaderx-langu      = 'X'.
  ls_poheaderx-status     = 'X'.
*  ls_poheaderx-pmnttrms   = 'X'.
  ls_poheaderx-item_intvl = 'X'.
*  ls_poheaderx-ref_1      = 'X'.
*  ls_poheaderx-OUR_REF    = 'X'.


  " 2、PO行项目数据
  lv_ebelp = lv_ebelp + '10'.
  lt_poitem-po_item     = lv_ebelp.           " 采购凭证的项目编号
  lt_poitem-item_cat    = s_dm_ekpo-pstyp.    " 采购凭证中的项目类别
  lt_poitem-material    = ls_dm_ekpo-matnr.   " 物料代码
  lt_poitem-ematerial   = ls_dm_ekpo-matnr.   " 物料编号(多次调用一次提交时需传)
  lt_poitem-short_text  = ls_dm_ekpo-txz01.   " 短文本
  lt_poitem-plant       = ls_dm_ekpo-werks.   " 工厂
  lt_poitem-stge_loc    = ls_dm_ekpo-lgort.   " 库存地点
*  lt_poitem-suppl_stloc = ls_dm_ekpo-reslo.  " 供应库存地点
  lt_poitem-quantity    = ls_dm_ekpo-menge.   " 数量
  lt_poitem-po_unit     = ls_dm_ekpo-meins.   " 采购单位
  lt_poitem-tax_code    = ls_dm_ekpo-mwskz.   " 销售/购买税代码
  lt_poitem-acctasscat  = ls_dm_ekpo-knttp.   " 科目分配类别
  lt_poitem-matl_group  = ls_dm_ekpo-matkl.   " 物料组
  lt_poitem-net_price   = ls_dm_ekpo-netpr.   " 净价
  lt_poitem-price_unit  = ls_dm_ekpo-peinh.   " 价格单位
  lt_poitem-preq_no	    = ls_dm_ekpo-banfn.   " 采购申请单号
  lt_poitem-preq_item	= ls_dm_ekpo-bnfpo.   " 采购申请行号
  lt_poitem-trackingno  = ls_dm_ekpo-bednr.   " 需求跟踪号
*  lt_poitem-agreement   = ls_dm_ekpo-KONNR.  " 采购协议号
*  lt_poitem-agmt_item   = ls_dm_ekpo-KTPNR.  " 采购协议的项目编号
*  lt_poitem-ref_doc     = ''.                " 参考凭证号
*  lt_poitem-ref_item    = ''.                " 参考凭证的项目
*  lt_poitem-preq_name   = ls_dm_ekpo-AFNAM.   " 需求者/请求者姓名
*  lt_poitem-conf_ctrl   = ls_dm_ekpo-BSTAE.   " 确认控制代码
*  lt_poitem-ret_item    = ls_dm_ekpo-RETPO.   " 退货项目
  IF lt_poitem-material IS INITIAL OR lt_poitem-quantity IS INITIAL .
    CONTINUE.   "如果物料号为空或数量为0则不处理,则LOOP忽略此行
  ENDIF.
  APPEND lt_poitem.
  CLEAR  lt_poitem.


  lt_poitemx-po_item     = lv_ebelp.
  lt_poitemx-item_cat    = 'X'.
  lt_poitemx-material    = 'X'.
  lt_poitemx-ematerial   = 'X'.
  lt_poitemx-short_text  = 'X'.
  lt_poitemx-plant       = 'X'.
  lt_poitemx-stge_loc    = 'X'.
*  lt_poitemx-suppl_stloc = 'X'.
  lt_poitemx-quantity    = 'X'.
  lt_poitemx-po_unit     = 'X'.
  lt_poitemx-tax_code    = 'X'.
  lt_poitemx-acctasscat  = 'X'.
  lt_poitemx-matl_group  = 'X'.
  lt_poitemx-net_price   = 'X'.
  lt_poitemx-price_unit  = 'X'.
  lt_poitemx-preq_no     = 'X'.
  lt_poitemx-preq_item   = 'X'.
  lt_poitemx-trackingno  = 'X'.
*  lt_poitemx-agreement   = 'X'.
*  lt_poitemx-agmt_item   = 'X'.
*  lt_poitemx-ref_doc     = 'X'.
*  lt_poitemx-ref_item    = 'X'.
*  lt_poitemx-preq_name   = 'X'.
*  lt_poitemx-conf_ctrl   = 'X'.
*  lt_poitemx-ret_item    = 'X'.
  APPEND lt_poitemx.
  CLEAR  lt_poitemx.

  " 3、计划行数据
  lt_poschedule-po_item        = lv_ebelp.  " ls_dm_eket-EBELP    " 采购凭证的项目编号
  lt_poschedule-sched_line     = 1.         " ls_dm_eket-ETENR    " 交货计划行计数器
  lt_poschedule-del_datcat_ext = 'D'.       " ls_dm_eket-LPEIN    " 交货日期的类别
  lt_poschedule-delivery_date  = sy-datum.  " ls_dm_eket-EINDT    " 交货日期
  lt_poschedule-quantity       = 2.         " ls_dm_eket-menge.   " 已计划数量
*  lt_poschedule-preq_no        = ls_dm_eket-BANFN.               " 采购申请
*  lt_poschedule-preq_item      = ls_dm_eket-BNFPO.               " 采购申请行项目编号
  APPEND lt_poschedule.
  CLEAR  lt_poschedule.

  lt_poschedulex-po_item        = lv_ebelp.
  lt_poschedulex-sched_line     = 1.
  lt_poschedulex-del_datcat_ext = 'X'.
  lt_poschedulex-delivery_date  = 'X'.
  lt_poschedulex-quantity       = 'X'.
*  lt_poschedulex-preq_no        = 'X'.
*  lt_poschedulex-preq_item      = 'X'.
  APPEND lt_poschedulex.
  CLEAR  lt_poschedulex.

  "4 、采购订单中的条件   使用批导价格
  lt_pocond-itm_number  = lv_ebelp.
  lt_pocond-cond_type   = 'PBXX'.
  lt_pocond-cond_value  = '100'.  "<fs_data>-netpr.     "条件金额(价格)
  lt_pocond-cond_p_unt   = 1.     "<fs_data>-peinh.    "价格单位
  lt_pocond-cond_unit   = 'KG'.   "lv_unit.             "条件单位
  lt_pocond-currency    = 'CNY'.  "is_head-waers.       "货币码
  lt_pocond-change_id   = 'I'.                      "更改类型
  APPEND lt_pocond.
  CLEAR: lt_pocond.

  lt_pocondx-itm_number = lv_ebelp.
  lt_pocondx-cond_type  = 'X'.
  lt_pocondx-cond_value = 'X'.
  lt_pocondx-cond_p_unt = 'X'.
  lt_pocondx-cond_unit  = 'X'.
  lt_pocondx-currency   = 'X'.
  lt_pocondx-change_id  = 'X'.
  APPEND lt_pocondx.
  CLEAR: lt_pocondx.

  " 5、科目分配类别
  IF ls_dm_ekpo-knttp EQ 'K'.
    lt_poaccount-po_item     = lv_ebelp.
*    ls_poaccount-serial_no   = '01'.
    lt_poaccount-costcenter = ''.                 " 成本中心
    lt_poaccount-gl_account = ''.                 " 总帐科目
    lt_poaccount-co_area    = '1000'.             " 成本控制范围
*    lt_poaccount-asset_no   = is_dm_data-anln1.  " 主资产号
*    lt_poaccount-orderid    = is_dm_data-aufnr.  " 订单号
    APPEND lt_poaccount.
    CLEAR  lt_poaccount.

    lt_poaccountx-po_item     = lv_ebelp.
*    lt_poaccountx-serial_no   = '01'.
    lt_poaccountx-gl_account  = 'X'.
    lt_poaccountx-costcenter  = 'X'.
    lt_poaccountx-co_area     = 'X'.
*    lt_poaccount-asset_no     = 'X'.
*    lt_poaccount-orderid      = 'X'.
    APPEND lt_poaccountx.
    CLEAR lt_poaccountx.
  ENDIF.

  " 6、行项目文本
  lt_potextitem-po_item   = lv_ebelp.                 " 采购凭证的项目编号
  lt_potextitem-text_id   = 'F01'.                    " 文本 ID
  lt_potextitem-text_line = ''.  "is_dm_data-sgtxt.   " 文本行
  APPEND lt_potextitem.
  CLEAR: lt_potextitem.

  " 7、增强自定义字段
  " (1)采购订单抬头
  lt_extensionin-structure = 'BAPI_TE_MEPOHEADER'.
  lt_extensionin-valuepart1 = ls_header_ext.
  APPEND lt_extensionin.
  CLEAR: ls_header_ext.
  lt_extensionin-structure = 'BAPI_TE_MEPOHEADERX'.
  lt_extensionin-valuepart1 = ls_header_extx.
  APPEND lt_extensionin.
  CLEAR: ls_header_extx.

  " (2)采购订单行项目
  ls_item_ext-po_item = lv_ebelp.
*  ls_item_ext-zfield1 = ls_dm_ekpo-zfield1.
*  ls_item_ext-zfield2 = ls_dm_ekpo-zfield2.
  lt_extensionin-structure = 'BAPI_TE_MEPOITEM'.
  lt_extensionin-valuepart1 = ls_item_ext.
  APPEND lt_extensionin.
  CLEAR: ls_item_ext.
  ls_item_extx-po_item = lv_ebelp.
*  ls_item_extx-zfield1 = 'X'.
*  ls_item_extx-zfield2 = 'X'.
  lt_extensionin-structure = 'BAPI_TE_MEPOITEMX'.
  lt_extensionin-valuepart1 = ls_item_extx.
  APPEND lt_extensionin.
  CLEAR: ls_item_extx.

  " (3)采购订单科目分配
  ls_account_ext-po_item     = lv_ebelp.
*    ls_account_ext-serial_no   = '01'.
  lt_extensionin-structure = 'BAPI_TE_MEPOACCOUNTING'.
  lt_extensionin-valuepart1 = ls_account_ext.
  APPEND lt_extensionin.
  CLEAR: ls_header_ext.
  ls_account_extx-po_item     = lv_ebelp.
*    ls_account_extx-serial_no   = '01'.
  lt_extensionin-structure = 'BAPI_TE_MEPOACCOUNTINGX'.
  lt_extensionin-valuepart1 = ls_account_extx.
  APPEND lt_extensionin.
  CLEAR: ls_header_extx.

  " 8、调用BAPI
  CALL FUNCTION 'BAPI_PO_CREATE1'
    EXPORTING
      poheader                     = ls_poheader      " Header Data
      " 必须参数,接收抬头数据的结构
      poheaderx                    = ls_poheaderx     " Header Data (Change Toolbar)
      " 必要参数,指定poheader更新字段
*     POADDRVENDOR                 =                  " Address of Vendor
*     TESTRUN                      =                  " Test Indicator
*     MEMORY_UNCOMPLETE            =                  " Hold Purchase Order if Faulty
*     MEMORY_COMPLETE              =                  " Hold Purchase Order if NOT Faulty
*     POEXPIMPHEADER               =                  " Export Trade: Header Data
*     POEXPIMPHEADERX              =                  " Foreign Trade: Change Bar: Header Data
*     VERSIONS                     =                  " Version Management
*     NO_MESSAGING                 =                  " No message determination
*     NO_MESSAGE_REQ               =                  " No messages necessary
*     NO_AUTHORITY                 =                  " No Authorization Check
     no_price_from_po             = 'X'               " No Adoption of Price from Last Document
      " 建议参数,'X',禁止信息更新,见备注说明。
   IMPORTING
      exppurchaseorder             = lv_ebeln         " Purchasing Document Number
      " 建议参数,采购订单创建成功会返回一个采购订单号
*     EXPHEADER                    =                  " Header Data
*     EXPPOEXPIMPHEADER            =                  " Export Trade: Header Data
   TABLES
      return                       = lt_return        " Return Parameter
      " 建议参数,返回报错信息
      poitem                       = lt_poitem        " Item Data
      " 必要参数,接收行项目数据的表
      poitemx                      = lt_poitemx       " Item Data (Change Parameter)
      " 必要参数,PO行项目更新字段
*     POADDRDELIVERY               =                  " Addresses for Inward Delivery (Item)
      poschedule                   = lt_poschedule    " Delivery Schedule
      " 必要参数,接收计划行数据的表
      poschedulex                  = lt_poschedulex   " Schedule Lines (Change Parameter)
      " 必要参数,PO计划行更新字段
     poaccount                    = lt_poaccount      " Account Assignment Fields
*     POACCOUNTPROFITSEGMENT       =                  " Reservation Event Object: BAPI_PROFITABILITY_SEGMENT
     poaccountx                   = lt_poaccountx     " Account Assignment Fields (Change Parameter)
*     POCONDHEADER                 =                  " Conditions (Header)
*     POCONDHEADERX                =                  " Conditions (Header, Change Bar)
     pocond                       = lt_pocond         " Conditions (Items)
     pocondx                      = lt_pocondx        " Conditions (Items, Change Bar)
*     POLIMITS                     =                  " External Services: Limits
*     POCONTRACTLIMITS             =                  " External Services: Contract Limits
*     POSERVICES                   =                  " External Services: Service Lines
*     POSRVACCESSVALUES            =                  " External Services: Account Assignment Distribution for Service Lines
*     POSERVICESTEXT               =                  " External Services: Service Long Text
     extensionin                  = lt_extensionin    " Customer's Own Fields (Import Parameters)
*     EXTENSIONOUT                 =                  " Customer's Own Fields (Export Parameters)
*     POEXPIMPITEM                 =                  " Foreign Trade: Item Data
*     POEXPIMPITEMX                =                  " Foreign Trade: Change Bar: Item Data
*     POTEXTHEADER                 =                  " Header Texts
     potextitem                   = lt_potextitem     " Item Texts
*     ALLVERSIONS                  =                  " All Versions (Export Parameter)
*     POPARTNER                    =                  " Partner
*     POCOMPONENTS                 =                  " BAPI Structure for Components
*     POCOMPONENTSX                =                  " Update Information for Components in BUS2012 API
*     POSHIPPING                   =                  " BAPI Shipping Data for Stock Transport Orders
*     POSHIPPINGX                  =                  " BAPI Shipping Data Change Bar
*     POSHIPPINGEXP                =                  " Export Structure for Shipping Data
            .
            
  " 9、返回消息处理
  LOOP AT lt_return WHERE type = 'E' OR type = 'A'.
    lv_error = 'X'.
    CASE lt_return-parameter.
      WHEN 'POITEM'.
        READ TABLE lt_poitem INDEX lt_return-row.
        IF sy-subrc = 0.
*            lt_poitem_err-msg = lt_return-message. " 对应行错误消息
        ENDIF.
      WHEN 'POSCHEDULE'.
        READ TABLE lt_poschedule INDEX lt_return-row.
        IF sy-subrc = 0.
*            lt_poschedule_err-msg = lt_return-message. " 对应行错误消息
        ENDIF.
      WHEN OTHERS.

    ENDCASE.
  ENDLOOP.

  IF lv_error = 'X'.
    CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
  ELSE.
    CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
      EXPORTING
        wait = 'X'.

    " 10、在此处,可以为长文本赋值
    "(1)抬头长文本
    DATA: w_head TYPE thead,
          t_lines LIKE tline OCCURS 0 WITH HEADER LINE.
    CLEAR: w_head, t_lines, t_lines[].
    w_head-tdobject = 'EKKO'.   " 文本:应用程序对象
    w_head-tdname   = lv_ebeln. " 采购订单号
    w_head-tdid = 'F01'.        " Text ID
    w_head-tdspras = sy-langu.
    t_lines-tdformat = '*'.
    t_lines-tdline = '抬头文本'.  " 文本行
    APPEND t_lines.
    CALL FUNCTION 'SAVE_TEXT'
      EXPORTING
       client                = sy-mandt
        header                = w_head
       insert                = ' '
       savemode_direct       = 'X'
*       OWNER_SPECIFIED       = ' '
*       LOCAL_CAT             = ' '
*     IMPORTING
*       FUNCTION              =
*       NEWHEADER             =
      TABLES
        lines                 = t_lines
     EXCEPTIONS
       id                    = 1
       language              = 2
       name                  = 3
       object                = 4
       OTHERS                = 5.

    "(2)行项目长文本
    CLEAR: w_head, t_lines, t_lines[].
    w_head-tdobject = 'EKPO'.   " 文本:应用程序对象
    CONCATENATE lv_ebeln lv_ebelp INTO w_head-tdname. " 采购订单号、行项目号
    w_head-tdid = 'F01'.        " Text ID
    w_head-tdspras = sy-langu.
    t_lines-tdformat = '*'.
    t_lines-tdline = '行项目文本'.  " 文本行
    APPEND t_lines.
    CALL FUNCTION 'SAVE_TEXT'
      EXPORTING
       client                = sy-mandt
        header                = w_head
       insert                = ' '
       savemode_direct       = 'X'
*       OWNER_SPECIFIED       = ' '
*       LOCAL_CAT             = ' '
*     IMPORTING
*       FUNCTION              =
*       NEWHEADER             =
      TABLES
        lines                 = t_lines
     EXCEPTIONS
       id                    = 1
       language              = 2
       name                  = 3
       object                = 4
       OTHERS                = 5.

    WRITE:/ lv_ebeln, '订单创建成功'.
  ENDIF.
ENDFORM.                    "zfrm_bapi_po_create

2、说明

(1)创建 PO 时,如果勾选了“信息更新”,则该 PO 保存后相应的信息记录会把该 PO 更新为其最后的凭证,那么该 PO 的净价将会作为下次创建新 PO 时净价的默认值。也就是我们当前创建的 PO 单,设置的 net_price 的值(净价)在PO创建成功时自动更新为上一次的净价值,而自定义的值则无效。如果标记 no_price_from_po = ‘X’,则不会使用采购信息记录带过来的净价,而是使用用户输入的净价。

(2)lt_extensionin 对应的 bapiparex 结构中:STRUCTURE字段用来填写结构名字,这个结构里面就是自定义的增强字段,BAPI_PO_CREATE1中可供使用的结构名共有三组6个。VALUEPART1、VALUEPART2、VALUEPART3、VALUEPART4 中保存的是自定义字段值和对应更新字段标识。

(3)lt_poitem-ematerial,当在同一个 BAPI COMMIT 中多次调用 BAPI_PO_CREATE1 时,需要赋值该字段,否则会在第一次的BAPI调用中自动赋值等于 lt_poitem-material,并在后续调用中自动记忆该值,导致后续BAPI调用报错(实际遇到的问题,该字段具体用途还不明确)。

(4)其他说明,参考代码注释。

  • 8
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值