按需开发,实现plm同步bom数据至sap,实现覆盖式增删改
核心逻辑,bom bapi修改和创建是不一致的,创建的时候需要将组创建出来的,对应bapi也不一致,通过读取标准表是否生成数据来判断是否创建/修改
其中接口框架不建议参考,无奈之举,反馈都改了N次,反正常思维,其中自建表存储就不列举了
接口搭建
功能实现
FUNCTION ZFM_PLM_003.
*"----------------------------------------------------------------------
*"*"本地接口:
*" IMPORTING
*" VALUE(INPUT) TYPE ZSTPLM_003_INPUT
*" EXPORTING
*" VALUE(OUTPUT) TYPE ZSTPLM_003_OUTPUT
*"----------------------------------------------------------------------
*--init
PERFORM frm_init USING 'ZFM_PLM_003'.
*--json in
gv_json_in = zcl_common=>abap_to_json( input ).
*--if active check
PERFORM frm_check_active USING gc_i.
IF gv_active EQ abap_true.
*--input check
IF input[] IS INITIAL.
APPEND VALUE #( code = 'E' msg = '输入数据为空,请检查!') TO output.
gv_type = gc_e.
ELSE.
PERFORM frm_bom_handle TABLES input output.
ENDIF.
ELSE.
PERFORM frm_003_ret_e TABLES input output.
ENDIF.
*--json out
gv_json_out = zcl_common=>abap_to_json( output ).
*--set log
PERFORM frm_set_log USING gc_i.
ENDFUNCTION.
核心框架
*&---------------------------------------------------------------------*
*& Form FRM_BOM_HANDLE
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> INPUT
*& --> OUTPUT
*&---------------------------------------------------------------------*
FORM frm_bom_handle TABLES pt_input TYPE zstplm_003_input
pt_output TYPE zstplm_003_output.
DATA: lv_tabix TYPE sy-tabix,
lv_msg TYPE string.
DATA: ls_marc TYPE marc.
LOOP AT pt_input.
CLEAR:lv_tabix,lv_msg.
"初始化反馈
APPEND INITIAL LINE TO pt_output ASSIGNING FIELD-SYMBOL(<fs_output>).
<fs_output>-matnr = pt_input-matnr.
material_input pt_input-matnr.
"工厂子表必输校验
IF pt_input-it_werks IS INITIAL.
PERFORM frm_set_bom_ret TABLES <fs_output>-ot_werks
USING gc_e
'工厂数据必输,请检查'
CHANGING <fs_output>.
CONTINUE.
ENDIF.
"工厂层级循环
LOOP AT pt_input-it_werks INTO DATA(ls_werks).
"初始化工厂反馈
APPEND INITIAL LINE TO <fs_output>-ot_werks ASSIGNING FIELD-SYMBOL(<fs_owerks>).
<fs_owerks>-werks = ls_werks-werks.
CLEAR:ls_marc.
"工厂层级数据检查
PERFORM frm_bom_input_check_01 USING pt_input ls_werks ls_marc CHANGING <fs_owerks>.
IF ls_marc-beskz EQ 'E' OR ls_marc-beskz EQ 'X' OR ( ls_marc-beskz EQ 'F' AND ls_marc-sobsl EQ '30' ).
"检查反馈处理
IF <fs_owerks>-code NE gc_e.
READ TABLE <fs_owerks>-ot_bom INTO DATA(ls_obom) WITH KEY code = gc_e.
IF sy-subrc EQ 0.
<fs_owerks>-code = gc_e.
<fs_owerks>-msg = ls_obom-msg.
"组件无可选物料,不反馈 <fs_owerks>-ot_bom
IF ls_obom-zmatnr IS INITIAL.
MODIFY <fs_owerks>-ot_bom FROM VALUE #( matnr = '' zmatnr = '' code = '' msg = '')
TRANSPORTING matnr zmatnr code msg
WHERE matnr IS NOT INITIAL
OR zmatnr IS NOT INITIAL
OR code IS NOT INITIAL
OR msg IS NOT INITIAL .
ENDIF.
ENDIF.
ENDIF.
"继续执行则情况bom检查,方便后续bapi执行结果写入
IF <fs_owerks>-code NE gc_e.
"CLEAR:<fs_owerks>-ot_bom .
ELSE.
CONTINUE.
ENDIF.
"获取工厂物料 bom 清单
PERFORM frm_get_mast USING ls_werks pt_input.
PERFORM frm_bom_maintain USING ls_werks pt_input CHANGING <fs_owerks>.
READ TABLE <fs_owerks>-ot_bom INTO ls_obom INDEX 1.
"组件无可选物料,不反馈 <fs_owerks>-ot_bom
IF ls_obom-zmatnr IS INITIAL.
CLEAR:<fs_owerks>-ot_bom .
ENDIF.
ELSE.
<fs_owerks>-code = gc_s.
<fs_owerks>-msg = |采购类型为{ ls_marc-beskz },特殊采购类为{ ls_marc-sobsl }无需扩展BOM|.
ENDIF.
ENDLOOP.
READ TABLE <fs_output>-ot_werks INTO DATA(ls_ot_werks) WITH KEY code = gc_e.
IF sy-subrc EQ 0.
<fs_output>-code = ls_ot_werks-code.
<fs_output>-msg = ls_ot_werks-msg.
ELSE.
<fs_output>-code = gc_s.
<fs_output>-msg = '物料BOM维护成功'.
ENDIF.
ENDLOOP.
READ TABLE pt_output TRANSPORTING NO FIELDS WITH KEY code = gc_e.
IF sy-subrc EQ 0.
gv_type = gc_e.
ELSE.
gv_type = gc_s.
ENDIF.
ENDFORM.
定义
CONSTANTS:gc_i TYPE zietype VALUE 'I',
gc_o TYPE zietype VALUE 'O',
gc_w TYPE zietype VALUE 'W',
gc_e TYPE zietype VALUE 'E',
gc_s TYPE zietype VALUE 'S'.
DATA: gv_sysid TYPE ze_sysid01,
gv_id TYPE ze_zid01,
gv_zname TYPE rs38l_fnam,
gv_guid TYPE sysuuid_c,
gv_active TYPE c,
gv_msg TYPE string,
gv_type TYPE c,
gv_json_in TYPE string,
gv_json_out TYPE string.
DATA:gv_matnr TYPE char18.
*--003
DATA:gt_bomgroup TYPE TABLE OF bapi1080_bgr_c,
gs_bomgroup TYPE bapi1080_bgr_c,
gt_variants TYPE TABLE OF bapi1080_bom_c,
gs_variants TYPE bapi1080_bom_c,
gt_items TYPE TABLE OF bapi1080_itm_c,
gs_items TYPE bapi1080_itm_c,
gt_materialrelations TYPE TABLE OF bapi1080_mbm_c,
gs_materialrelations TYPE bapi1080_mbm_c,
gt_itemassignments TYPE TABLE OF bapi1080_rel_itm_bom_c,
gs_itemassignments TYPE bapi1080_rel_itm_bom_c,
gs_testrun TYPE bapiflag,
gt_return TYPE TABLE OF bapiret2,
gs_return TYPE bapiret2.
DATA:gt_stko_old TYPE STANDARD TABLE OF stko_api02,
gt_stpo_old TYPE STANDARD TABLE OF stpo_api02.
DATA:gt_stpo_new TYPE STANDARD TABLE OF stpo_api03,
gs_stko_new TYPE stko_api01.
DATA:gv_stlal TYPE numc2,
gv_tabix TYPE sy-tabix.
DATA:gt_zplm_t_007 TYPE STANDARD TABLE OF zplm_t_007,
gt_zplm_t_006 TYPE STANDARD TABLE OF zplm_t_006,
gt_zplm_t_001 TYPE STANDARD TABLE OF zplm_t_001
子例程
*&---------------------------------------------------------------------*
*& Form FRM_BOM_HANDLE
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> INPUT
*& --> OUTPUT
*&---------------------------------------------------------------------*
FORM frm_bom_handle TABLES pt_input TYPE zstplm_003_input
pt_output TYPE zstplm_003_output.
DATA: lv_tabix TYPE sy-tabix,
lv_msg TYPE string.
DATA: ls_marc TYPE marc.
LOOP AT pt_input.
CLEAR:lv_tabix,lv_msg.
"初始化反馈
APPEND INITIAL LINE TO pt_output ASSIGNING FIELD-SYMBOL(<fs_output>).
<fs_output>-matnr = pt_input-matnr.
material_input pt_input-matnr.
"工厂子表必输校验
IF pt_input-it_werks IS INITIAL.
PERFORM frm_set_bom_ret TABLES <fs_output>-ot_werks
USING gc_e
'工厂数据必输,请检查'
CHANGING <fs_output>.
CONTINUE.
ENDIF.
"工厂层级循环
LOOP AT pt_input-it_werks INTO DATA(ls_werks).
"初始化工厂反馈
APPEND INITIAL LINE TO <fs_output>-ot_werks ASSIGNING FIELD-SYMBOL(<fs_owerks>).
<fs_owerks>-werks = ls_werks-werks.
CLEAR:ls_marc.
"工厂层级数据检查
PERFORM frm_bom_input_check_01 USING pt_input ls_werks ls_marc CHANGING <fs_owerks>.
IF ls_marc-beskz EQ 'E' OR ls_marc-beskz EQ 'X' OR ( ls_marc-beskz EQ 'F' AND ls_marc-sobsl EQ '30' ).
"检查反馈处理
IF <fs_owerks>-code NE gc_e.
READ TABLE <fs_owerks>-ot_bom INTO DATA(ls_obom) WITH KEY code = gc_e.
IF sy-subrc EQ 0.
<fs_owerks>-code = gc_e.
<fs_owerks>-msg = ls_obom-msg.
"组件无可选物料,不反馈 <fs_owerks>-ot_bom
IF ls_obom-zmatnr IS INITIAL.
MODIFY <fs_owerks>-ot_bom FROM VALUE #( matnr = '' zmatnr = '' code = '' msg = '')
TRANSPORTING matnr zmatnr code msg
WHERE matnr IS NOT INITIAL
OR zmatnr IS NOT INITIAL
OR code IS NOT INITIAL
OR msg IS NOT INITIAL .
ENDIF.
ENDIF.
ENDIF.
"继续执行则情况bom检查,方便后续bapi执行结果写入
IF <fs_owerks>-code NE gc_e.
"CLEAR:<fs_owerks>-ot_bom .
ELSE.
CONTINUE.
ENDIF.
"获取工厂物料 bom 清单
PERFORM frm_get_mast USING ls_werks pt_input.
PERFORM frm_bom_maintain USING ls_werks pt_input CHANGING <fs_owerks>.
READ TABLE <fs_owerks>-ot_bom INTO ls_obom INDEX 1.
"组件无可选物料,不反馈 <fs_owerks>-ot_bom
IF ls_obom-zmatnr IS INITIAL.
CLEAR:<fs_owerks>-ot_bom .
ENDIF.
ELSE.
<fs_owerks>-code = gc_s.
<fs_owerks>-msg = |采购类型为{ ls_marc-beskz },特殊采购类为{ ls_marc-sobsl }无需扩展BOM|.
ENDIF.
ENDLOOP.
READ TABLE <fs_output>-ot_werks INTO DATA(ls_ot_werks) WITH KEY code = gc_e.
IF sy-subrc EQ 0.
<fs_output>-code = ls_ot_werks-code.
<fs_output>-msg = ls_ot_werks-msg.
ELSE.
<fs_output>-code = gc_s.
<fs_output>-msg = '物料BOM维护成功'.
ENDIF.
ENDLOOP.
READ TABLE pt_output TRANSPORTING NO FIELDS WITH KEY code = gc_e.
IF sy-subrc EQ 0.
gv_type = gc_e.
ELSE.
gv_type = gc_s.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_SET_BOM_RET
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> <FS_OUTPUT>_IT_WERKS
*& --> <FS_OUTPUT>_OT_BOM
*& --> <FS_OUTPUT>_CODE
*& --> <FS_OUTPUT>_MSG
*& <-- <FS_OUTPUT>
*&---------------------------------------------------------------------*
FORM frm_set_bom_ret TABLES pt_owerks TYPE zstplm_003_owerks
USING ps_code
ps_msg
CHANGING cs_output TYPE zsplm_003_output.
IF pt_owerks[] IS NOT INITIAL.
cs_output-ot_werks = pt_owerks[].
ENDIF.
IF ps_code IS NOT INITIAL.
cs_output-code = ps_code.
ENDIF.
IF ps_msg IS NOT INITIAL.
cs_output-msg = ps_msg.
ENDIF.
"总体接口记录标识
IF gv_type NE gc_e AND cs_output-code IS NOT INITIAL.
gv_type = cs_output-code.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_BOM_INPUT_CHECK_01
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> LS_WERKS
*& <-- <FS_OWERKS>
*&---------------------------------------------------------------------*
FORM frm_bom_input_check_01 USING ps_input TYPE zsplm_003_input
ps_iwerks TYPE zsplm_003_iwerks
ps_marc TYPE marc
CHANGING cs_owerks TYPE zsplm_003_owerks.
CLEAR:ps_marc.
"工厂代码必输
IF ps_iwerks-werks IS INITIAL.
cs_owerks = VALUE #( code = gc_e msg = '工厂代码必输,请检查' ).
RETURN.
ENDIF.
"新增/修改标识
"IF ps_iwerks-wflag IS INITIAL.
" cs_owerks = VALUE #( code = gc_e msg = '新增/修改标识必输,请检查' ).
" RETURN.
"ENDIF.
SELECT SINGLE * FROM marc INTO ps_marc WHERE matnr EQ ps_input-matnr AND werks EQ ps_iwerks-werks.
IF ps_marc IS INITIAL.
cs_owerks = VALUE #( code = gc_e msg = '物料:' && |{ ps_input-matnr ALPHA = OUT }| && '不存在于工厂:' && ps_iwerks-werks ).
RETURN.
ENDIF.
"BOM子表必输校验
IF ps_input-it_bom IS INITIAL.
cs_owerks = VALUE #( code = gc_e msg = 'BOM信息必输,请检查' ).
RETURN.
ELSE.
"BOM数据校验
LOOP AT ps_input-it_bom ASSIGNING FIELD-SYMBOL(<fs_ibom>).
APPEND INITIAL LINE TO cs_owerks-ot_bom ASSIGNING FIELD-SYMBOL(<fs_obom>).
<fs_obom>-matnr = <fs_ibom>-matnr.
"物料编号必输
IF <fs_ibom>-matnr IS INITIAL.
<fs_obom> = VALUE #( code = gc_e msg = '物料编号必输,请检查' ).
RETURN.
ELSE.
material_input <fs_ibom>-matnr.
ENDIF.
"用途必输
IF <fs_ibom>-stlan IS INITIAL.
<fs_obom> = VALUE #( code = gc_e msg = '用途必输,请检查' ).
RETURN.
ELSE.
ENDIF.
"可选的 BOM必输
IF <fs_ibom>-stlal IS INITIAL.
<fs_obom> = VALUE #( code = gc_e msg = 'BOM必输,请检查' ).
RETURN.
ELSE.
PERFORM frm_inzero USING 'CHAR2' CHANGING <fs_ibom>-stlal.
ENDIF.
"物料版本
IF <fs_ibom>-materev IS INITIAL.
<fs_obom> = VALUE #( code = gc_e msg = '物料版本必输,请检查' ).
RETURN.
ENDIF.
"基本数量必输
IF <fs_ibom>-bmeng IS INITIAL.
<fs_obom> = VALUE #( code = gc_e msg = '基本数量必输,请检查' ).
RETURN.
ENDIF.
"组件可选物料回写
READ TABLE <fs_ibom>-i_item INTO DATA(ls_bom_item) WITH KEY zsfkx = 'Y'.
IF sy-subrc EQ 0.
<fs_obom>-zmatnr = ls_bom_item-idnrk.
ENDIF.
"行项目-BOM 组件 校验
READ TABLE <fs_ibom>-i_item TRANSPORTING NO FIELDS WITH KEY idnrk = space.
IF sy-subrc EQ 0.
<fs_obom> = VALUE #( code = gc_e msg = 'BOM组件物料必输,请检查' ).
RETURN.
ELSE.
LOOP AT <fs_ibom>-i_item ASSIGNING FIELD-SYMBOL(<fs_item>).
CLEAR gv_matnr.
gv_matnr = |{ <fs_item>-idnrk ALPHA = IN }|.
SELECT SINGLE * FROM marc INTO @DATA(ls_marc) WHERE matnr EQ @gv_matnr AND werks EQ @ps_iwerks-werks.
IF sy-subrc NE 0 OR ls_marc IS INITIAL.
<fs_obom> = VALUE #( code = gc_e msg = '组件物料:' && <fs_item>-idnrk && '不存在于工厂:' && ps_iwerks-werks ).
RETURN.
ELSE.
"财务冻结
IF <fs_item>-postp EQ 'L' AND ls_marc-mmsta EQ '03'.
<fs_obom> = VALUE #( code = gc_e msg = '组件物料:' && <fs_item>-idnrk && '于工厂:' && ps_iwerks-werks && '财务冻结,创建BOM失败' ).
RETURN.
ELSE.
<fs_item>-idnrk = gv_matnr.
ENDIF.
ENDIF.
CLEAR ls_marc.
ENDLOOP.
ENDIF.
"行项目-组件数量
READ TABLE <fs_ibom>-i_item TRANSPORTING NO FIELDS WITH KEY menge = space.
IF sy-subrc EQ 0.
<fs_obom> = VALUE #( code = gc_e msg = 'BOM组件物料数量必输,请检查' ).
RETURN.
ENDIF.
ENDLOOP.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_MATERIAL_DEL_SINGLE
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> LS_MARC_WERKS
*& <-- CS_OUTPUT
*&---------------------------------------------------------------------*
FORM frm_inzero USING p_type CHANGING cv_field TYPE string.
DATA: dyn_data TYPE REF TO data,
lv_cd TYPE i,
lv_str TYPE string,
lv_pyl TYPE i.
FIELD-SYMBOLS: <fs_data> TYPE any.
CREATE DATA dyn_data TYPE (p_type).
ASSIGN dyn_data->* TO FIELD-SYMBOL(<fs_field>).
CHECK <fs_field> IS ASSIGNED.
DATA(lv_len) = strlen( p_type ).
lv_pyl = lv_len - 4.
lv_cd = p_type+4(lv_pyl).
IF strlen( cv_field ) GT lv_cd.
lv_str = cv_field+0(lv_cd).
ELSE.
lv_str = cv_field.
ENDIF.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
input = lv_str
IMPORTING
output = <fs_field>.
cv_field = <fs_field>.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GET_MAST
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM frm_get_mast USING ps_iwerks TYPE zsplm_003_iwerks
ps_input TYPE zsplm_003_input.
DATA:lt_matnr TYPE STANDARD TABLE OF mast.
CLEAR:gt_mast.
lt_matnr = CORRESPONDING #( ps_input-it_bom ).
CHECK lt_matnr[] IS NOT INITIAL.
SELECT *
FROM mast
INTO TABLE gt_mast
FOR ALL ENTRIES IN lt_matnr
WHERE matnr EQ lt_matnr-matnr
AND werks EQ ps_iwerks-werks.
SORT gt_mast BY matnr werks stlan stlnr stlal.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_bom_maintain
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> PT_INPUT
*& <-- PT_OUTPUT
*&---------------------------------------------------------------------*
FORM frm_bom_maintain USING ps_iwerks TYPE zsplm_003_iwerks
ps_input TYPE zsplm_003_input
CHANGING cs_owerks TYPE zsplm_003_owerks.
DATA:lv_msg TYPE string,
lv_tabix_crt TYPE sy-tabix.
LOOP AT ps_input-it_bom ASSIGNING FIELD-SYMBOL(<fs_bom>).
"与检查时写入数据保持index 一致
DATA(lv_tabix) = sy-tabix.
PERFORM frm_bom_refresh.
"获取历史行
PERFORM frm_get_bom_item USING ps_iwerks <fs_bom> .
"001 / 006 SAVE
PERFORM frm_set_bom_t001 USING ps_iwerks <fs_bom> .
IF gt_stko_old IS NOT INITIAL."修改
"写bapi 行
PERFORM frm_chg_bom_item USING ps_iwerks <fs_bom> .
"bapi 修改
PERFORM frm_bom_bapi_chg USING ps_iwerks lv_tabix CHANGING cs_owerks.
ELSE."创建
lv_tabix_crt = lv_tabix_crt + 1.
"抬头写入
PERFORM frm_set_bom_head USING ps_iwerks <fs_bom> lv_tabix_crt.
"行项目写入
PERFORM frm_set_bom_item USING ps_iwerks <fs_bom> lv_tabix_crt.
"新组写入
PERFORM frm_set_bom_group USING ps_iwerks <fs_bom>.
"bapi 创建
PERFORM frm_bom_bapi_crt USING ps_iwerks CHANGING cs_owerks.
ENDIF.
ENDLOOP.
READ TABLE cs_owerks-ot_bom INTO DATA(ls_obom) WITH KEY code = gc_e.
IF sy-subrc EQ 0.
cs_owerks-code = ls_obom-code.
cs_owerks-msg = ls_obom-msg.
ELSE.
"PLM未传输可选bom删除
PERFORM frm_del_mast CHANGING cs_owerks.
IF cs_owerks-code IS INITIAL.
cs_owerks-code = gc_s.
cs_owerks-msg = 'BOM维护成功'.
ENDIF.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_BOM_REFRESH
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM frm_bom_refresh .
CLEAR:gv_stlal,gv_tabix.
CLEAR:gt_bomgroup ,
gt_variants ,
gt_items ,
gt_materialrelations ,
gt_itemassignments ,
gs_itemassignments ,
gt_stpo_old ,
gt_stko_old ,
gt_stpo_new ,
gs_stko_new ,
gs_return ,
gt_return.
CLEAR:gt_zplm_t_001,
gt_zplm_t_006,
gt_zplm_t_007.
CLEAR:gs_mast.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GET_BOM_ITEM
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> PS_INPUT
*&---------------------------------------------------------------------*
FORM frm_get_bom_item USING ps_iwerks TYPE zsplm_003_iwerks
ps_ibom TYPE zsplm_003_ibom.
"读取可选BOM 是否存在
gs_mast = VALUE #( matnr = ps_ibom-matnr
werks = ps_iwerks-werks
stlan = ps_ibom-stlan
stlal = ps_ibom-stlal
).
SELECT SINGLE stlnr FROM mast INTO gs_mast-stlnr WHERE matnr = ps_ibom-matnr AND werks = ps_iwerks-werks.
CHECK sy-subrc EQ 0.
CALL FUNCTION 'CSAP_MAT_BOM_READ'
EXPORTING
material = gs_mast-matnr
plant = gs_mast-werks
bom_usage = gs_mast-stlan
alternative = gs_mast-stlal
" valid_from = sy-datum
" valid_to = sy-datum
TABLES
t_stpo = gt_stpo_old
t_stko = gt_stko_old
EXCEPTIONS
error = 1
OTHERS = 2.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_SET_BOM_T001
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> PS_IBOM
*& --> PS_IWERKS
*&---------------------------------------------------------------------*
FORM frm_set_bom_t001 USING ps_iwerks TYPE zsplm_003_iwerks
ps_ibom TYPE zsplm_003_ibom.
TYPES: BEGIN OF typ_marc,
matnr TYPE marc-matnr,
END OF typ_marc,
BEGIN OF typ_item,
idnrk TYPE marc-matnr,
END OF typ_item.
DATA:lt_marc TYPE SORTED TABLE OF typ_marc WITH UNIQUE KEY matnr,
lt_idnrk TYPE STANDARD TABLE OF typ_item,
lt_001 TYPE STANDARD TABLE OF zplm_t_001 WITH HEADER LINE.
"读取是否组件行是否包含包装物料
lt_idnrk[] = CORRESPONDING #( ps_ibom-i_item ).
CHECK lt_idnrk[] IS NOT INITIAL.
SELECT marc~matnr
FROM marc
INNER JOIN mara
ON mara~matnr EQ marc~matnr
AND mara~mtart EQ 'LD22'
INTO TABLE lt_marc
FOR ALL ENTRIES IN lt_idnrk
WHERE marc~matnr EQ lt_idnrk-idnrk
"AND marc~beskz EQ 'E'
"AND marc~sobsl EQ '50'
AND marc~werks EQ ps_iwerks-werks.
IF lt_marc IS NOT INITIAL.
"筛选处理数据
lt_001[] = CORRESPONDING #( ps_ibom-i_item ).
lt_001[] = FILTER #( lt_001[] IN lt_marc WHERE idnrk EQ matnr ).
IF lt_001[] IS NOT INITIAL.
lt_001 = VALUE #( BASE CORRESPONDING #( ps_ibom ) werks = ps_iwerks-werks ).
MODIFY lt_001 TRANSPORTING matnr werks stlan stlal WHERE matnr EQ space.
APPEND LINES OF lt_001 TO gt_zplm_t_001.
ENDIF.
ENDIF.
"PLM->SAP BOM抬头-版本储存表
APPEND INITIAL LINE TO gt_zplm_t_006 ASSIGNING FIELD-SYMBOL(<fs_006>).
<fs_006> = VALUE #( BASE CORRESPONDING #( ps_ibom )
werks = ps_iwerks-werks
zenable = abap_true ).
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_CHG_BOM_ITEM
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM frm_chg_bom_item USING ps_iwerks TYPE zsplm_003_iwerks
ps_ibom TYPE zsplm_003_ibom.
DATA lv_item_no TYPE char4.
gt_stpo_new = CORRESPONDING #( gt_stpo_old ) .
MODIFY gt_stpo_new FROM VALUE #( fldelete = abap_true ) TRANSPORTING fldelete WHERE fldelete EQ space.
LOOP AT ps_ibom-i_item INTO DATA(ls_item) WHERE zbxbs EQ space.
"item no 按照每个 可选bom 独立排序
lv_item_no = lv_item_no + 10. CONDENSE lv_item_no NO-GAPS.
APPEND INITIAL LINE TO gt_stpo_new ASSIGNING FIELD-SYMBOL(<fs_stpo>).
<fs_stpo> = VALUE #( item_no = |{ lv_item_no ALPHA = IN }|
component = ls_item-idnrk
comp_qty = ls_item-menge
item_categ = 'L'
rel_cost = abap_true
sortstring = ls_item-sortf
).
APPEND INITIAL LINE TO gt_zplm_t_007 ASSIGNING FIELD-SYMBOL(<fs_007>).
<fs_007> = VALUE #( idnrk = ls_item-idnrk
postp = ls_item-postp
posnr = lv_item_no
zversion_s = ls_item-zversion_s
materev_s = ls_item-materev_s
zjtzbc_s = ls_item-zjtzbc_s
matnr = ps_ibom-matnr
werks = ps_iwerks-werks
stlan = ps_ibom-stlan
stlal = ps_ibom-stlal
zversion = ps_ibom-zversion
materev = ps_ibom-materev
zjtzbc = ps_ibom-zjtzbc
zenable = abap_true ).
ENDLOOP.
gs_stko_new = VALUE #( BASE CORRESPONDING #( VALUE #( gt_stko_old[ 1 ] OPTIONAL ) )
base_quan = ps_ibom-bmeng
bom_text = ps_ibom-ztext
alt_text = ps_ibom-ztext
).
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_BOM_BAPI_CHG
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> PS_INPUT
*& <-- CS_OUTPUT
*&---------------------------------------------------------------------*
FORM frm_bom_bapi_chg USING ps_iwerks TYPE zsplm_003_iwerks
pv_tabix
CHANGING cs_owerks TYPE zsplm_003_owerks.
"删除本次传输修改数据
DELETE gt_mast WHERE matnr = gs_mast-matnr
AND werks = gs_mast-werks
AND stlan = gs_mast-stlan
AND stlal = gs_mast-stlal.
"有效起始日期转外部
DATA(lv_datum) = zcl_common=>date_out( ).
CALL FUNCTION 'CSAP_MAT_BOM_MAINTAIN'
EXPORTING
material = gs_mast-matnr
plant = gs_mast-werks
bom_usage = gs_mast-stlan
alternative = gs_mast-stlal
i_stko = gs_stko_new
valid_from = lv_datum
* FL_BOM_CREATE = 'X'
fl_new_item = 'X'
fl_complete = 'X'
fl_default_values = 'X'
TABLES
t_stpo = gt_stpo_new
EXCEPTIONS
error = 1
OTHERS = 2.
DATA(lv_type) = COND char1( WHEN sy-subrc EQ 0 THEN gc_s ELSE gc_e ).
MODIFY cs_owerks-ot_bom FROM VALUE #( code = lv_type
msg = COND #( WHEN sy-subrc NE 0 THEN zcl_common=>write_message( ) ELSE 'BOM修改成功' )
)
INDEX pv_tabix TRANSPORTING code msg.
zcl_common=>bapi_commit( lv_type ).
CHECK lv_type EQ gc_s.
"保存数据
PERFORM frm_bom_save USING ps_iwerks gs_mast-stlnr.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_BOM_SAVE
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> PS_INPUT
*& --> LV_STLNR
*&---------------------------------------------------------------------*
FORM frm_bom_save USING ps_iwerks TYPE zsplm_003_iwerks
pv_stlnr TYPE mast-stlnr.
*--包装方案储存表
IF gt_zplm_t_001 IS NOT INITIAL.
MODIFY gt_zplm_t_001 FROM VALUE #( stlnr = pv_stlnr ) TRANSPORTING stlnr WHERE stlnr IS INITIAL.
"删除历史存储数据
LOOP AT gt_zplm_t_001 INTO DATA(ls_001).
DELETE FROM zplm_t_001 WHERE matnr EQ ls_001-matnr
AND werks EQ ls_001-werks
AND stlan EQ ls_001-stlan
AND stlal EQ ls_001-stlal.
IF sy-subrc EQ 0.
COMMIT WORK AND WAIT.
ENDIF.
ENDLOOP.
"保存数据
MODIFY zplm_t_001 FROM TABLE gt_zplm_t_001.
IF sy-subrc EQ 0.
COMMIT WORK AND WAIT.
ENDIF.
ENDIF.
*--PLM->SAP BOM抬头-版本储存表
IF gt_zplm_t_006 IS NOT INITIAL.
MODIFY gt_zplm_t_006 FROM VALUE #( stlnr = pv_stlnr ) TRANSPORTING stlnr WHERE stlnr IS INITIAL.
"更新其他版本为非启用
LOOP AT gt_zplm_t_006 INTO DATA(ls_006).
UPDATE zplm_t_006 SET zenable = space
WHERE matnr EQ ls_006-matnr
AND werks EQ ls_006-werks
AND stlan EQ ls_006-stlan
AND stlnr EQ ls_006-stlnr
AND stlal EQ ls_006-stlal.
IF sy-subrc EQ 0.
COMMIT WORK AND WAIT.
ENDIF.
ENDLOOP.
"保存数据
MODIFY zplm_t_006 FROM TABLE gt_zplm_t_006.
IF sy-subrc EQ 0.
COMMIT WORK AND WAIT.
ENDIF.
ENDIF.
*--PLM->SAP BOM项目-版本储存表
IF gt_zplm_t_007 IS NOT INITIAL.
MODIFY gt_zplm_t_007 FROM VALUE #( stlnr = pv_stlnr ) TRANSPORTING stlnr WHERE stlnr IS INITIAL.
"更新其他版本为非启用
LOOP AT gt_zplm_t_007 INTO DATA(ls_007).
UPDATE zplm_t_007 SET zenable = space
WHERE matnr = ls_007-matnr
AND werks = ls_007-werks
AND stlan = ls_007-stlan
AND stlnr = ls_007-stlnr
AND stlal = ls_007-stlal.
IF sy-subrc EQ 0.
COMMIT WORK AND WAIT.
ENDIF.
ENDLOOP.
"保存数据
MODIFY zplm_t_007 FROM TABLE gt_zplm_t_007.
IF sy-subrc EQ 0.
COMMIT WORK AND WAIT.
ENDIF.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_SET_BOM_HEAD
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> PS_INPUT
*& --> PV_INDEX
*&---------------------------------------------------------------------*
FORM frm_set_bom_head USING ps_iwerks TYPE zsplm_003_iwerks
ps_ibom TYPE zsplm_003_ibom
pv_tabix ."TYPE sy-tabix.
SELECT SINGLE * FROM mara INTO @DATA(ls_mara) WHERE matnr EQ @ps_ibom-matnr.
APPEND INITIAL LINE TO gt_variants ASSIGNING FIELD-SYMBOL(<fs_variants>).
<fs_variants> = VALUE #( bom_group_identification = 'BOMGROUP2'
object_type = 'BOM'
object_id = |SIMPLE{ pv_tabix ALPHA = IN }| "bom head object_id,存在创建多个 bom可选清单,按照汇总下创建多个可选bom累加拼接
bom_status = '01'
alternative_bom = ps_ibom-stlal "备选物料清单
base_qty = ps_ibom-bmeng "父项基本数量
base_unit = ls_mara-meins "父项基本计量单位
valid_from_date = sy-datum "有效起始日期
alt_text = ps_ibom-ztext "物料清单描述
function = 'NEW' "创建
).
APPEND INITIAL LINE TO gt_materialrelations ASSIGNING FIELD-SYMBOL(<fs_materialrelations>).
<fs_materialrelations> = VALUE #( bom_group_identification = 'BOMGROUP2'
material = ps_ibom-matnr "父项物料编码
material_long = ps_ibom-matnr "父项物料编码
bom_usage = ps_ibom-stlan " BOM 用途
alternative_bom = ps_ibom-stlal "可选BOM
plant = ps_iwerks-werks"工厂
).
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_SET_BOM_ITEM
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> PS_INPUT
*&---------------------------------------------------------------------*
FORM frm_set_bom_item USING ps_iwerks TYPE zsplm_003_iwerks
ps_ibom TYPE zsplm_003_ibom
pv_tabix ."TYPE tabix.
DATA lv_item_no TYPE char4.
LOOP AT ps_ibom-i_item INTO DATA(ls_item) WHERE zbxbs EQ space.
gv_tabix = gv_tabix + 1.
"item no 按照每个 可选bom 独立排序
lv_item_no = lv_item_no + 10. CONDENSE lv_item_no NO-GAPS.
"item object_id 按照所有item 行累加拼接 SIMPLE
DATA(lv_object_id) = |SIMPLE{ gv_tabix }|. CONDENSE lv_object_id NO-GAPS.
"item item_id 按照所有item 行累加
DATA(lv_item_id) = CONV cs_itmid( gv_tabix ). CONDENSE lv_item_id NO-GAPS.
lv_item_id = |{ lv_item_id ALPHA = IN }|.
APPEND INITIAL LINE TO gt_items ASSIGNING FIELD-SYMBOL(<fs_item>).
<fs_item> = VALUE #( bom_group_identification = 'BOMGROUP2'
object_type = 'ITM'
object_id = lv_object_id
item_no = |{ lv_item_no ALPHA = IN }|
item_id = lv_item_id
item_cat = 'L'"COND #( WHEN ps_input-zkxbs EQ 'Y' THEN 'T' ELSE 'L' )"BOM行项目类别
component = ls_item-idnrk
component_long = ls_item-idnrk
comp_qty = ls_item-menge
ltxt_lang = sy-langu
valid_from_date = sy-datum
cost_rel = abap_true
sort_string = ls_item-sortf
).
APPEND INITIAL LINE TO gt_itemassignments ASSIGNING FIELD-SYMBOL(<fs_itemassignments>).
<fs_itemassignments> = VALUE #( bom_group_identification = 'BOMGROUP2'
sub_object_type = 'ITM'
sub_object_id = lv_object_id
super_object_type = 'BOM'
super_object_id = |SIMPLE{ pv_tabix ALPHA = IN }| "bom head object_id
valid_from_date = sy-datum"有效起始日期
function = 'NEW'
).
APPEND INITIAL LINE TO gt_zplm_t_007 ASSIGNING FIELD-SYMBOL(<fs_007>).
<fs_007> = VALUE #( idnrk = ls_item-idnrk
postp = ls_item-postp
posnr = lv_item_no
zversion_s = ls_item-zversion_s
materev_s = ls_item-materev_s
matnr = ps_ibom-matnr
werks = ps_iwerks-werks
stlan = ps_ibom-stlan
stlal = ps_ibom-stlal
zversion = ps_ibom-zversion
zenable = abap_true
).
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_SET_BOM_GROUP
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> PS_INPUT
*&---------------------------------------------------------------------*
FORM frm_set_bom_group USING ps_iwerks TYPE zsplm_003_iwerks
ps_ibom TYPE zsplm_003_ibom.
APPEND INITIAL LINE TO gt_bomgroup ASSIGNING FIELD-SYMBOL(<fs_bomgroup>).
<fs_bomgroup> = VALUE #( bom_group_identification = 'BOMGROUP2' "标识物料单组
object_type = 'BGR' "BOM 组中的对象类型
object_id = |SIMPLE1| "BOM 组中对象的标识 "bom group object_id,只创建一个组,所以写死
technical_type = 'M' "技术类型
ltxt_lang = sy-langu
bom_usage = ps_ibom-stlan "BOM 用途
created_in_plant = ps_iwerks-werks"工厂
bom_text = ps_ibom-ztext "物料清单描述
).
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_BOM_BAPI_CRT
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& <-- CS_OUTPUT
*&---------------------------------------------------------------------*
FORM frm_bom_bapi_crt USING ps_iwerks TYPE zsplm_003_iwerks
CHANGING cs_owerks TYPE zsplm_003_owerks.
DATA:lv_stlnr TYPE mast-stlnr,
ls_bom TYPE zsplm_003_ibom.
CALL FUNCTION 'BAPI_MATERIAL_BOM_GROUP_CREATE'
EXPORTING
all_error = 'X'
TABLES
bomgroup = gt_bomgroup
variants = gt_variants
items = gt_items
materialrelations = gt_materialrelations
itemassignments = gt_itemassignments
return = gt_return.
LOOP AT gt_return INTO DATA(ls_return) WHERE type = 'E' OR type = 'A'.
gs_return-message = gs_return-message && '/' && ls_return-message.
gs_return-type = gc_e.
ENDLOOP.
gs_return-type = COND #( WHEN gs_return-type EQ space THEN gc_s ELSE gs_return-type ).
zcl_common=>bapi_commit( gs_return-type ).
LOOP AT gt_return INTO ls_return WHERE message CS '创建' AND message_v1 EQ 'BOMGroup'.
lv_stlnr = ls_return-message_v2+0(8).
EXIT.
ENDLOOP.
cs_owerks-code = gs_return-type.
cs_owerks-msg = COND #( WHEN gs_return-type = gc_s THEN 'BOM创建成功' ELSE 'BOM创建失败:' && gs_return-message ).
MODIFY cs_owerks-ot_bom FROM VALUE #( code = cs_owerks-code
msg = cs_owerks-msg )
TRANSPORTING code msg WHERE code IS INITIAL.
CHECK gs_return-type EQ gc_s.
CHECK lv_stlnr IS NOT INITIAL.
"数据保存
PERFORM frm_bom_save USING ps_iwerks lv_stlnr.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_DEL_MAST
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& <-- CS_OWERKS
*&---------------------------------------------------------------------*
FORM frm_del_mast CHANGING cs_owerks TYPE zsplm_003_owerks.
CHECK gt_mast IS NOT INITIAL.
LOOP AT gt_mast INTO DATA(ls_mast).
CALL FUNCTION 'CSAP_MAT_BOM_DELETE'
EXPORTING
material = ls_mast-matnr
plant = ls_mast-werks
bom_usage = ls_mast-stlan
alternative = ls_mast-stlal
fl_commit_and_wait = 'X'
EXCEPTIONS
error = 1
OTHERS = 2.
IF sy-subrc <> 0.
cs_owerks-code = gc_e.
cs_owerks-msg = |可选bom| && ls_mast-stlal && |移除失败:| && zcl_common=>write_message( ).
EXIT.
ENDIF.
ENDLOOP.
ENDFORM.
涉及公共方法
zcl_common=>abap_to_json
ABAP TYPE ANY 输入abap数据
PRETTY_NAME TYPE CHAR1 OPTIONAL j输出json格式
value( JSON ) TYPE STRING 输出json数据
METHOD abap_to_json.
TRY.
json = /ui2/cl_json=>serialize( data = abap pretty_name = pretty_name ).
CATCH cx_root INTO DATA(lr_root).
DATA(l_str) = lr_root->get_text( ).
MESSAGE l_str TYPE 'S'.
ENDTRY.
ENDMETHOD.
zcl_common=>abap_to_json
ABAP TYPE ANY 输入abap数据
PRETTY_NAME TYPE CHAR1 OPTIONAL j输出json格式
value( JSON ) TYPE STRING 输出json数据
METHOD abap_to_json.
TRY.
json = /ui2/cl_json=>serialize( data = abap pretty_name = pretty_name ).
CATCH cx_root INTO DATA(lr_root).
DATA(l_str) = lr_root->get_text( ).
MESSAGE l_str TYPE 'S'.
ENDTRY.
ENDMETHOD.
zcl_common=>get_guid
METHOD get_guid.
TRY.
rv_guid = cl_system_uuid=>create_uuid_c32_static( ).
CATCH cx_uuid_error.
rv_guid = cl_fdt_uuid=>get_uuid( ).
ENDTRY.
ENDMETHOD.
zcl_common=>bapi_commit
METHOD bapi_commit.
IF type <> 'S'.
CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
ELSE.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
EXPORTING
wait = 'X'.
ENDIF.
ENDMETHOD.