背景:
对于使用PLM系统 或 CAPP系统的企业,SAP 需要承接上游对于BOM的数据,包括 创建、更改、删除等操作。
因管理要求不同,SAP端更新逻辑由原先的 先删除,再创建,改成直接更改,实现SAP端的ECN管理。
目前SAP中可用变更BOM的函数只有 CSAP_MAT_BOM_MAINTAIN函数,但是在使用过程中出现一些莫名其妙的报错。
这里对函数CSAP_MAT_BOM_MAINTAIN规范使用做下总结。
官方文档:
(官方解释很重要,认真阅读可以少走很多弯路)
You can use function module CSAP_MAT_BOM_MAINTAIN to process simple material BOMs.
This function module is intended mainly as a tool for changing BOMs. However, it can also be used to create BOMs.If you only want to create BOMs, use function module CSAP_MAT_BOM_CREATE.
To change BOMs, you can also use the following function modules:
CSAP_MAT_BOM_OPEN
CSAP_BOM_ITEM_MAINTAIN
CSAP_MAT_BOM_CLOSEFor more information and examples, see the documentation of the individual function modules.
Restrictions:
- To date, you can only process one alternative or variant with this function module. This means that, if you do not enter an alternative for function module CSAP_MAT_BOM_MAINTAIN, the system assumes that you want to process alternative 01.
- To date, changes to the BOM header are not yet supported.
Please note:(Important)
- The item to be changed can be identified in two ways:
- via the fields item category, item number, sort string, and object (depending on the item category, this can be material, document data, or class data).
The names of these identifying fields begin with 'ID_' and are contained in structure CSIDENT_02. Structure CSIDENT_02 is part of structure STPO_API03.
You can use any combination of these fields to identify the item, provided the fields identify the item uniquely. Otherwise you see the error message 'Item cannot be identified uniquely'.
- via the BOM node and BOM item counter
These fields are only known to the system if you have read the BOM before. If you identify the item in this way, you should therefore use function modules CSAP_MAT_BOM_OPEN, CSAP_BOM_ITEM_MAINTAIN, or CSAP_MAT_BOM_CLOSE to change the BOM.
- If the error message 'Item cannot be changed' appears in the log, this can be for the following reasons:
- The item is not valid on the valid-from date - it becomes valid at a
later date.
- The item has already been changed on the same valid-from date
with a different change number.
- You cannot change the item category of an item that exists already in the system.
- To delete an item, you must identify it as described above for the change function and set the deletion indicator.
- FL_BOM_CREATE (default ' ')
If you set this indicator to 'X', the system creates a new BOM if it cannot find the BOM you want to change and there is no other error.
Items can only be created if sufficient data exists to do this.
The system ignores items with a deletion indicator when creating a BOM.
- FL_NEW_ITEM (default ' ')
If you set this indicator to 'X', the system creates a new item if it cannot find the item with the identification entered.
The system ignores items with a deletion indicator.
官方传参Demo:
Example
*---- BOM header data structure
data: begin of tstk2.
include structure stko_api02.
data: end of tstk2.
*---- BOM items table
data: begin of tstp3 occurs 0.
include structure stpo_api03.
data: end of tstp3.
*---- Object dependencies table
* Basis data
data: begin of tdep2_data occurs 0.
include structure dep_data.
data: end of tdep2_data.
* Description
data: begin of tdep2_descr occurs 0.
include structure dep_descr.
data: end of tdep2_descr.
* Source
data: begin of tdep2_source occurs 0.
include structure dep_source.
data: end of tdep2_source.
* Sequence
data: begin of tdep2_order occurs 0.
include structure dep_order.
data: end of tdep2_order.
* Documentation
data: begin of tdep2_doc occurs 0.
include structure dep_doc.
data: end of tdep2_doc.
data: flg_warning like capiflag-warning.
*- Initialize database log
call function 'CALO_INIT_API'
exceptions
log_object_not_found = 1
log_sub_object_not_found = 2
other_error = 3
others = 4.
*- Fill item data
* Exception: items that can be identified uniquely via their item
* number
* 1. Item 0010: change quantity
clear tstp3.
tstp3-id_item_no = '0010'. "Item identification
tstp3-comp_qty = '5.000'.
append tstp3.
* 2. Item 0020: delete
clear tstp3.
tstp3-id_item_no = '0020'. "Item identification.
tstp3-fldelete = 'X'.
append tstp3.
*- 3. New item 0030 (stock material)
* For new items, the ID_ fields, BOM nodes, and BOM item counters are
* initial unless they use
* FLG_NEW_ITEM
clear tstp3.
tstp3-item_no = '0030'.
tstp3-component = 'MAT200'.
tstp3-item_categ = 'L'.
tstp3-comp_qty = '1'.
tstp3-rel_prod = 'X'.
tstp3-sortstring = 'A1'.
append tstp3.
* 3. Item 0040: change component
clear tstp3.
tstp3-id_item_no = '0040'. "Item identification
tstp3-component = 'MAT500'.
append tstp3.
*- Change BOM
call function 'CSAP_MAT_BOM_MAINTAIN'
exporting
material = 'MAT100'
plant = '0001'
bom_usage = '1'
valid_from = '14.10.1996'
fl_bom_create = ' '
fl_new_item = ' '
i_stko = tstko
importing
fl_warning = flg_warning
o_stko = tstk2
tables
t_stpo = tstp3
exceptions
others = 1.
if sy-subrc eq 1.
*---- Error
* Please see log
endif.
if flg_warning eq 'X'.
*---- Please see log for information, warning messages, and success
* messages.
Endif.
实际案例:
本例中由外围系统全量同步完整BOM,但是一般仅修改个别行的某些信息,所以,添加了比对逻辑,无需变更的会跳过修改;同时,由于上游系统不传行的删除或新建标识,导致只能根据 行号、物料号为组合的识别ID判断(已存在的BOM信息),如果识别ID既没有被新物料占用,也没用在新的报文中出现,则认为被删除,标记上删除标识。
TYPES: BEGIN OF ty_bom_h,
activity TYPE string,
matnr TYPE marc-matnr,
werks TYPE marc-werks,
stlan TYPE mast-stlan,
stlal TYPE mast-stlal,
bmeng TYPE bicsk-bmeng,
bmein TYPE bicsk-bmein,
aennr TYPE string,
datuv TYPE string,
aetxt TYPE string,
aegru TYPE string,
ausss TYPE string,
stktx TYPE string, "可选文本
item LIKE lt_bom_i,
END OF ty_bom_h.
DATA: wa_bom_h TYPE ty_bom_h.
TYPES: BEGIN OF ty_bom_i,
posnr TYPE string,
postp TYPE string,
idnrk TYPE string,
menge TYPE bicsp-menge,
meins TYPE bicsp-meins,
ausch TYPE string,
lgort TYPE string,
alpgr TYPE string,
alprf TYPE string,
alpst TYPE string,
ewahr TYPE string,
sortf TYPE string,
potx1 TYPE string,
potx2 TYPE string,
ausss TYPE string,
zyzd1 TYPE string,
zyzd2 TYPE string,
zyzd3 TYPE string,
END OF ty_bom_i.
DATA: lt_bom_i TYPE TABLE OF ty_bom_i,
wa_bom_i TYPE ty_bom_i.
******* 以上为补充定义 *******
********************************************************
DATA: lv_comp_qty TYPE p LENGTH 15 DECIMALS 3,
lv_menge TYPE p LENGTH 15 DECIMALS 3,
lv_ausss TYPE p LENGTH 5 DECIMALS 2,
lv_tabix TYPE sy-tabix.
DATA:
lv_warning TYPE capiflag-flwarning, "出错标识
ls_mbom TYPE csap_mbom, "BOM key信息
ls_stko_i TYPE stko_api01, "BOM头部信息-输入
ls_stko_o TYPE stko_api02. "BOM头部信息-输出
DATA:
lv_datuv TYPE csap_mbom-datuv,
lv_aennr TYPE csap_mbom-aennr.
DATA:
lv_datum TYPE csap_mbom-datuv,
lv_base_quan TYPE p DECIMALS 3,
lv_bmeng TYPE p DECIMALS 3,
lt_stpo_read TYPE TABLE OF stpo_api02,
ls_stpo_read TYPE stpo_api02,
lt_stko_read TYPE TABLE OF stko_api02,
ls_stko_read TYPE stko_api02.
* wa_bom_h、lt_bom_i为接口报文传输数据,数据根据实际需求自行填充
CLEAR: lv_datum.
CALL FUNCTION 'CONVERT_DATE_TO_EXTERNAL'
EXPORTING
date_internal = sy-datum
IMPORTING
date_external = lv_datum
EXCEPTIONS
date_internal_is_invalid = 1
OTHERS = 2.
CLEAR:lt_stpo_read.
CALL FUNCTION 'CSAP_MAT_BOM_READ'
EXPORTING
material = wa_bom_h-matnr
plant = wa_bom_h-werks
bom_usage = wa_bom_h-stlan
alternative = wa_bom_h-stlal
valid_from = lv_datum
valid_to = lv_datum
* IMPORTING
* FL_WARNING =
TABLES
t_stpo = lt_stpo_read
t_stko = lt_stko_read
EXCEPTIONS
error = 1
OTHERS = 2.
READ TABLE lt_stko_read INTO ls_stko_read INDEX 1.
CLEAR :lv_base_quan,lv_bmeng.
PERFORM frm_units_string_convert USING ls_stko_read-base_quan CHANGING lv_base_quan .
PERFORM frm_units_string_convert USING wa_bom_h-bmeng CHANGING lv_bmeng .
IF lv_base_quan <> lv_bmeng OR ls_stko_read-base_unit <> wa_bom_h-bmein OR ls_stko_read-alt_text <> wa_bom_h-stktx .
ls_stko_i-base_quan = wa_bom_h-bmeng. "父项基本数量
ls_stko_i-base_unit = wa_bom_h-bmein. "基本单位
ls_stko_i-alt_text = wa_bom_h-stktx. "可选文本
ENDIF.
CLEAR:lv_datuv,lv_aennr.
lv_aennr = wa_bom_h-aennr.
IF wa_bom_h-datuv IS NOT INITIAL.
lv_datuv = wa_bom_h-datuv+0(4) && '-' && wa_bom_h-datuv+4(2) && '-' && wa_bom_h-datuv+6(2).
ENDIF.
LOOP AT wa_bom_h-item INTO wa_bom_i.
"检查行项目是否需要变更
READ TABLE lt_stpo_read INTO ls_stpo_read WITH KEY item_no = wa_bom_i-posnr
component = wa_bom_i-idnrk.
IF sy-subrc = 0.
"处理字符串型的数值
"IFUSER用户默认: 2,222.222 格式
REPLACE ALL OCCURRENCES OF ',' IN ls_stpo_read-comp_qty WITH space.
REPLACE ALL OCCURRENCES OF ',' IN ls_stpo_read-op_scrap WITH space.
"清楚字符串的空格
CONDENSE: ls_stpo_read-comp_qty,ls_stpo_read-op_scrap,ls_stpo_read-comp_unit,ls_stpo_read-comp_scrap,
ls_stpo_read-issue_loc,ls_stpo_read-ai_group,ls_stpo_read-ai_strateg,ls_stpo_read-sortstring,
ls_stpo_read-ai_prio,ls_stpo_read-usage_prob .
"转换格式
CLEAR: lv_comp_qty,lv_menge,lv_ausss.
lv_comp_qty = ls_stpo_read-comp_qty.
lv_menge = wa_bom_i-menge.
"比较行数据是否变更
IF lv_comp_qty = lv_menge AND ls_stpo_read-op_scrap = wa_bom_i-ausss AND
ls_stpo_read-comp_unit = wa_bom_i-meins AND ls_stpo_read-comp_scrap = wa_bom_i-ausch AND
ls_stpo_read-issue_loc = wa_bom_i-lgort AND ls_stpo_read-ai_group = wa_bom_i-alpgr AND
ls_stpo_read-ai_strateg = wa_bom_i-alpst AND
ls_stpo_read-sortstring = wa_bom_i-sortf AND ls_stpo_read-item_text1 = wa_bom_i-potx1.
IF ls_stpo_read-ai_prio = '00'.
CLEAR:ls_stpo_read-ai_prio.
ENDIF.
IF ls_stpo_read-ai_prio = wa_bom_i-alprf AND ls_stpo_read-usage_prob = wa_bom_i-ewahr.
CONTINUE.
ENDIF.
ENDIF.
CLEAR:lv_tabix.
ENDIF.
"原项目
ls_stpo-id_comp = wa_bom_i-idnrk. "识别ID-BOM 组件
ls_stpo-id_item_no = wa_bom_i-posnr. "识别ID-BOM 项目号
ls_stpo-id_itm_ctg = wa_bom_i-postp. "识别ID-BOM 项目类别
"已使用的识别号,不需要删除
READ TABLE lt_stpo_read INTO ls_stpo_read WITH KEY item_no = wa_bom_i-posnr
component = wa_bom_i-idnrk.
IF sy-subrc = 0.
lv_tabix = sy-tabix.
DELETE lt_stpo_read INDEX lv_tabix.
CLEAR:lv_tabix.
ENDIF.
"新项目
ls_stpo-item_no = wa_bom_i-posnr. "识别ID-BOM 项目号
ls_stpo-item_categ = wa_bom_i-postp. "项目类别
ls_stpo-component = wa_bom_i-idnrk. "组件物料号
ls_stpo-comp_qty = wa_bom_i-menge. "数量
IF wa_bom_i-ausss IS NOT INITIAL AND ls_stpo_read-op_scrap <> wa_bom_i-ausss.
ls_stpo-op_scrap = wa_bom_i-ausss. "装配报废率
ls_stpo-op_net_ind = 'X'. "净废品标识
ENDIF.
ls_stpo-comp_unit = wa_bom_i-meins. "单位
ls_stpo-comp_scrap = wa_bom_i-ausch. "损耗率
ls_stpo-issue_loc = wa_bom_i-lgort. "仓储地点
ls_stpo-rel_cost = 'X'. "标识:与成本核算相关的项目
ls_stpo-REL_PROD = 'X'. "标识:与生产相关项目
ls_stpo-ai_group = wa_bom_i-alpgr. "替代组
ls_stpo-ai_prio = wa_bom_i-alprf. "优先级
ls_stpo-ai_strateg = wa_bom_i-alpst . "策略
ls_stpo-usage_prob = wa_bom_i-ewahr . "使用比例
IF ls_stpo-usage_prob = '0'."在更改模式中,如果usage_prob等于0,则不会更新
CLEAR:ls_stpo-usage_prob.
ENDIF.
ls_stpo-sortstring = wa_bom_i-sortf. "排序字符串
ls_stpo-item_text1 = wa_bom_i-potx1. "项目文本
"新增关联关系,更新ITEM 的Change No.
ls_stpo-valid_from = lv_datuv. "项目文本
ls_stpo-change_no = lv_aennr. "变更编号
ls_stpo-identifier = wa_bom_i-posnr. "标识符
APPEND ls_stpo TO lt_stpo.
CLEAR: ls_stpo.
ENDLOOP.
"MDM BOM 全量下发,如果下发与系统中不一致,直接删除
IF lt_stpo_read[] IS NOT INITIAL.
LOOP AT lt_stpo_read INTO ls_stpo_read.
MOVE-CORRESPONDING ls_stpo_read TO ls_stpo.
ls_stpo-fldelete = 'X'.""'删除标识
APPEND ls_stpo TO lt_stpo.
CLEAR: ls_stpo.
ENDLOOP.
ENDIF.
"调用BAPI创建BOM
CALL FUNCTION 'CSAP_MAT_BOM_MAINTAIN'
EXPORTING
material = wa_bom_h-matnr
plant = wa_bom_h-werks
bom_usage = wa_bom_h-stlan
alternative = wa_bom_h-stlal
valid_from = lv_datuv
change_no = lv_aennr
i_stko = ls_stko_i
fl_commit_and_wait = 'X'
fl_bom_create = 'X'
fl_new_item = 'X'
fl_complete = 'X'
* fl_default_values = space
IMPORTING
fl_warning = lv_warning
o_stko = ls_stko_o
TABLES
t_stpo = lt_stpo
EXCEPTIONS
error = 1
OTHERS = 2.
IF sy-subrc <> 0.
gs_return-type = 'E'.
CALL FUNCTION 'MESSAGE_TEXT_BUILD'
EXPORTING
msgid = sy-msgid
msgnr = sy-msgno
msgv1 = sy-msgv1
msgv2 = sy-msgv2
msgv3 = sy-msgv3
msgv4 = sy-msgv4
IMPORTING
message_text_output = gs_return-message.
CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
ELSE.
gs_return-type = 'S'.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
EXPORTING
wait = 'X'.
gs_return-message = 'BOM修改成功'.
ENDIF.
*&---------------------------------------------------------------------*
*& Form frm_units_string_convert
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> LS_STKO_READ_BASE_QUAN
*& <-- LV_BASE_QUAN
*&---------------------------------------------------------------------*
FORM frm_units_string_convert USING pv_quan1
CHANGING pv_quan2.
DATA: lv_clabs TYPE p DECIMALS 3,
lv_dcpfm LIKE usr01-dcpfm.
SELECT SINGLE dcpfm INTO lv_dcpfm
FROM usr01
WHERE bname = sy-uname.
CLEAR lv_clabs.
CALL FUNCTION 'UNITS_STRING_CONVERT'
EXPORTING
units_string = pv_quan1
dcpfm = lv_dcpfm "此时为X
* MLLN = 'M'
* TSND = 'T'
IMPORTING
units = lv_clabs
EXCEPTIONS
invalid_type = 1
OTHERS = 2.
IF sy-subrc = 0.
pv_quan2 = lv_clabs.
ENDIF.
ENDFORM.
本例中使用行号、物料号为组合的识别ID,所以无需搭配CSAP_MAT_BOM_OPEN、CSAP_MAT_BOM_CLOSE。
如有问题,欢迎留言交流!