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)其他说明,参考代码注释。