SAP BOM的操作

这个程序是根据条件把某些工厂的某些物料的某些BOM,Copy到别外的工厂,当目标工厂存在要复制的BOM的时候,用源BOM代替目标BOM,当目标BOM不存在的时候,就根据源BOM创建目标BOM。

这个程序用到了BOM的一些常用Function和BAPI
BAPI_MATERIAL_BOM_GROUP_CREATE
CSAP_MAT_BOM_READ
CSAP_MAT_BOM_OPEN
CSAP_BOM_ITEM_MAINTAIN
CSAP_MAT_BOM_CLOSE

REPORT  zppinf1001.

INCLUDE <icon>.

*----------------------------------------------------------------------*
*       变量定义
*----------------------------------------------------------------------*
TABLES mast.
TYPES: ty_tab_matnr TYPE mara-matnr OCCURS 0,
       ty_tab_plant TYPE marc-werks OCCURS 0,
       ty_tab_stpo2 TYPE stpo_api02 OCCURS 0,
       ty_tab_stko2 TYPE stko_api02 OCCURS 0,
       ty_tab_s_mat TYPE s_matnr OCCURS 0.
TYPES: BEGIN OF ty_mast,
        matnr TYPE mast-matnr,
        werks TYPE mast-werks,
        stlan TYPE mast-stlan,
        stlnr TYPE mast-stlnr,
        stlal TYPE mast-stlal,
       END OF ty_mast.
TYPES: BEGIN OF ty_material,
        matnr TYPE mara-matnr,
        werks TYPE marc-werks,
       END OF ty_material.
TYPES ty_tab_mast TYPE ty_mast OCCURS 0.
TYPES ty_tab_messages TYPE messages OCCURS 0.
TYPES ty_tab_material TYPE ty_material OCCURS 0.
DATA: g_valid_from TYPE csap_mbom-datuv.

*----------------------------------------------------------------------*
*       选择屏幕设计
*----------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK blk WITH FRAME TITLE text-000.
SELECT-OPTIONS: s_matnr  FOR mast-matnr,
                s_stlan  FOR mast-stlan NO-EXTENSION NO INTERVALS OBLIGATORY,
                s_stlal  FOR mast-stlal NO-EXTENSION NO INTERVALS OBLIGATORY,
                s_source FOR mast-werks NO-EXTENSION NO INTERVALS OBLIGATORY.
SELECTION-SCREEN SKIP.
SELECT-OPTIONS: s_target FOR mast-werks,
                s_stlan2 FOR mast-stlan NO-EXTENSION NO INTERVALS OBLIGATORY,
                s_stlal2 FOR mast-stlal NO-EXTENSION NO INTERVALS OBLIGATORY.
PARAMETERS p_exist TYPE c AS CHECKBOX.
SELECTION-SCREEN END OF BLOCK blk.

*----------------------------------------------------------------------*
*       CLASS lcl_bom DEFINITION
*----------------------------------------------------------------------*
*       BOM的处理类定义
*----------------------------------------------------------------------*
CLASS lcl_bom DEFINITION FINAL.
  PUBLIC SECTION.
    METHODS write_header_text  "输出结果列表的选择条件的相关信息
      IMPORTING
        pt_plant TYPE ty_tab_plant.
    METHODS check_exist_bom     "检验指定条件的物料是否存在BOM
      IMPORTING
        p_material    TYPE csap_mbom-matnr  "料号
        p_plant       TYPE csap_mbom-werks  "工厂
        p_bom_usage   TYPE csap_mbom-stlan  "BOM Usage
        p_alternative TYPE csap_mbom-stlal  "Alternative BOM
        pt_target     TYPE ty_tab_mast
      RETURNING
        value(p_flag) TYPE char01.        "检查结果返回标识,X代表存在
    METHODS get_data                      "根据条件查询数据
      EXPORTING
        value(pt_source) TYPE ty_tab_mast
        value(pt_target) TYPE ty_tab_mast.
    METHODS get_target_plant
      RETURNING
        value(pt_plant) TYPE ty_tab_plant.
    METHODS check_matnr                    "检查指定的物料是否在指定的工厂存在
      IMPORTING
        p_matnr       TYPE mast-matnr
        p_plant       TYPE mast-werks
      RETURNING
        value(p_flag) TYPE char01.
    METHODS check_component                "检查指定的组件是否在指定的工厂存在
      IMPORTING
        p_matnr       TYPE mast-matnr
        p_plant       TYPE mast-werks
        pt_stpo       TYPE ty_tab_stpo2
      RETURNING
        value(p_flag) TYPE char01.
    METHODS set_log.                        "设置Log,可以事务码SLG1查看
    METHODS get_current_log                 "取得当前Log信息
      RETURNING
        value(pt_messages) TYPE ty_tab_messages.
    METHODS read_bom                        "查看BOM信息
      IMPORTING
        p_material     TYPE csap_mbom-matnr
        p_plant        TYPE csap_mbom-werks
        p_bom_usage    TYPE csap_mbom-stlan
        p_alternative  TYPE csap_mbom-stlal
        p_valid_from   TYPE csap_mbom-datuv
      EXPORTING
        value(pt_stpo) TYPE ty_tab_stpo2
        value(pt_stko) TYPE ty_tab_stko2
        value(p_flag)  TYPE char01.
    METHODS create_bom                      "创建BOM
        IMPORTING
          p_material    TYPE csap_mbom-matnr
          p_plant       TYPE csap_mbom-werks
          pt_stpo       TYPE ty_tab_stpo2
          pt_stko       TYPE ty_tab_stko2
        RETURNING
          value(p_flag) TYPE char01.
    METHODS maintain_bom                      "维护BOM
        IMPORTING
          p_material    TYPE csap_mbom-matnr
          p_plant       TYPE csap_mbom-werks
          p_usage       TYPE csap_mbom-stlan
          p_alternative TYPE csap_mbom-stlal
          p_valid       TYPE csap_mbom-datuv
          pt_stpo       TYPE ty_tab_stpo2
          pt_stko       TYPE ty_tab_stko2
        RETURNING
          value(p_flag) TYPE char01.
    METHODS constructor.                      "构造方法
    "类的全局变量
    DATA: BEGIN OF lwa_mat_wer,
            matnr TYPE mara-matnr,
            werks TYPE marc-werks,
          END OF lwa_mat_wer.
    DATA: lt_mat_wer2  LIKE TABLE OF lwa_mat_wer.
  PRIVATE SECTION.
    DATA: lt_mat_wer  LIKE TABLE OF lwa_mat_wer.
ENDCLASS.                    "lcl_bom DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_bom IMPLEMENTATION
*----------------------------------------------------------------------*
*       BOM的处理类实现
*----------------------------------------------------------------------*
CLASS lcl_bom IMPLEMENTATION.
*输出结果列表的选择条件的相关信息
  METHOD write_header_text.
    DATA: l_temp TYPE i VALUE 1,
          l_plant TYPE marc-werks.
    FORMAT COLOR 1 ON.
    IF s_matnr IS INITIAL.
      WRITE: 'BOM Material: All'.
    ELSEIF s_matnr-low IS NOT INITIAL AND s_matnr-high IS NOT INITIAL.
      WRITE: / 'BOM Material:',s_matnr-low,'To',s_matnr-high.
    ELSEIF s_matnr-high IS INITIAL.
      WRITE: / 'BOM Material:',s_matnr-low.
    ENDIF.
    WRITE: / 'Source Plant:',s_source-low.
    WRITE: / 'BOM Usage:',s_stlan-low.
    WRITE: / 'Alternative BOM:',s_stlal-low.
    SKIP.
    WRITE / 'Target Plant:'.
    LOOP AT pt_plant INTO l_plant.
      IF l_temp > 15.
        WRITE /16 l_plant.
        l_temp = 2.
        CONTINUE.
      ENDIF.
      WRITE l_plant.
      l_temp = l_temp + 1.
    ENDLOOP.
    WRITE: / 'BOM Usage:',s_stlan2-low.
    WRITE: / 'Alternative BOM:',s_stlal2-low.
    IF p_exist = 'X'.
      WRITE / 'Skip if target plant exist'.
    ENDIF.
    FORMAT COLOR OFF.
    ULINE.
  ENDMETHOD.                    "wwrite_header_text

*检验指定条件的物料是否存在BOM
  METHOD check_exist_bom.
    DATA l_alternative LIKE p_alternative.

    READ TABLE pt_target WITH KEY matnr = p_material
                                  werks = p_plant
                                  stlan = p_bom_usage
                                  stlal = p_alternative
                         TRANSPORTING NO FIELDS.
    IF sy-subrc = 0.
      p_flag = 'X'.
    ENDIF.
  ENDMETHOD.                    "check_exist_bom

*根据条件取得所有要复制到其他工厂的BOM的物料
  METHOD get_data.
    "取得表MAST的数据
    SELECT DISTINCT matnr
                    werks
                    stlan
                    stlnr
                    stlal
    INTO TABLE pt_source FROM mast
    WHERE matnr IN s_matnr.

    pt_target = pt_source.

    DELETE pt_source WHERE NOT ( werks IN s_source AND stlan IN s_stlan AND stlal IN s_stlal ).
    DELETE pt_target WHERE NOT ( werks IN s_target AND stlan IN s_stlan2 AND stlal IN s_stlal2 ).
  ENDMETHOD.                    "get_data

*根据条件取得目标工厂
  METHOD get_target_plant.
    SELECT werks INTO TABLE pt_plant FROM t001w
                 WHERE werks IN s_target.
  ENDMETHOD.                    "get_target_plant

*判断指定的料号在指定的工厂是否存在
  METHOD check_matnr.
    "根据条件取得物料和工厂的内表
    IF lt_mat_wer IS INITIAL.
      SELECT mara~matnr
             marc~werks
      INTO TABLE lt_mat_wer
      FROM mara
      INNER JOIN marc ON mara~matnr = marc~matnr
      WHERE mara~matnr IN s_matnr
        AND marc~werks IN s_target.
    ENDIF.

    "查询内表,判断指定料号是否在指定的工厂里
    READ TABLE lt_mat_wer WITH KEY matnr = p_matnr
                                   werks = p_plant
                          TRANSPORTING NO FIELDS.
    "存在
    IF sy-subrc = 0.
      p_flag = 'X'.
    ENDIF.
  ENDMETHOD.                    "check_matnr

*检查指定的组件是否在指定的工厂存在
  METHOD check_component.
    DATA: l_matnr TYPE mara-matnr,
          lt_matnr LIKE RANGE OF l_matnr,
          lwa_matnr LIKE LINE OF lt_matnr,
          lwa_stpo LIKE LINE OF pt_stpo.
    "组织选择内表
    LOOP AT pt_stpo INTO lwa_stpo.
      lwa_matnr-sign   = 'I'.
      lwa_matnr-option = 'EQ'.
      CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
        EXPORTING
          input  = lwa_stpo-component
        IMPORTING
          output = lwa_stpo-component.
      lwa_matnr-low    = lwa_stpo-component.
      lwa_matnr-high   = ''.
      APPEND lwa_matnr TO lt_matnr.
    ENDLOOP.
    "根据条件取得物料和工厂的内表
    IF lt_mat_wer2 IS INITIAL.
      SELECT mara~matnr
             marc~werks
      INTO TABLE lt_mat_wer2
      FROM mara
      INNER JOIN marc ON mara~matnr = marc~matnr
      WHERE mara~matnr IN lt_matnr
        AND marc~werks = p_plant.
    ENDIF.

    "查询内表,判断指定料号是否在指定的工厂里
    READ TABLE lt_mat_wer2 WITH KEY matnr = p_matnr
                           TRANSPORTING NO FIELDS.
    "存在
    IF sy-subrc = 0.
      p_flag = 'X'.
    ENDIF.
  ENDMETHOD.                    "check_component

*设置Log,可以用事务码SLG1查看
  METHOD set_log.
    CALL FUNCTION 'CALO_INIT_API'
      EXCEPTIONS
        log_object_not_found     = 1
        log_sub_object_not_found = 2
        other_error              = 3
        OTHERS                   = 4.
  ENDMETHOD.                    "set_log

*取得当前Log信息
  METHOD get_current_log.
    CALL FUNCTION 'CALO_LOG_READ_MESSAGES'
      TABLES
        messages_and_parameters = pt_messages
      EXCEPTIONS
        warning                 = 1
        error                   = 2
        OTHERS                  = 3.
  ENDMETHOD.                    "get_current_log

*读取指定的BOM
  METHOD read_bom.
    "调用FM查看指定的物料的BOM
    CALL FUNCTION 'CSAP_MAT_BOM_READ'
      EXPORTING
        material    = p_material
        plant       = p_plant
        bom_usage   = p_bom_usage
        alternative = p_alternative
        valid_from  = p_valid_from
      TABLES
        t_stpo      = pt_stpo
        t_stko      = pt_stko
      EXCEPTIONS
        error       = 1.
    "判断是否查看bom数据成功
    IF sy-subrc = 0.
      p_flag = 'X'.
    ELSE.
      p_flag = ''.
    ENDIF.
  ENDMETHOD.                    "read_bom

*创建BOM
  METHOD create_bom.
    DATA: lwa_bomgroup TYPE bapi1080_bgr_c,
          lt_bomgroup  LIKE TABLE OF lwa_bomgroup,
          lwa_variant  TYPE bapi1080_bom_c,
          lt_variant   LIKE TABLE OF lwa_variant,
          lwa_items    TYPE bapi1080_itm_c,
          lt_items     LIKE TABLE OF lwa_items,
          lwa_mbm      TYPE bapi1080_mbm_c,
          lt_mbm       LIKE TABLE OF lwa_mbm,
          lwa_itemass  TYPE bapi1080_rel_itm_bom_c,
          lt_itemass   LIKE TABLE OF lwa_itemass,
          lwa_return   TYPE bapiret2,
          lt_return    LIKE TABLE OF lwa_return.
    DATA: l_alternative TYPE stpo_api02-bom_alt,
          l_component   TYPE stpo_api02-component,
          l_error       TYPE string.
    CONSTANTS: bom_group_identification TYPE bapi1080_bgr_c-bom_group_identification
                                        VALUE 'BAPI_SMP_COL4',
               object_id TYPE bapi1080_bgr_c-object_id VALUE 'SIMPLE1'.
    FIELD-SYMBOLS: <fs_stko> LIKE LINE OF pt_stko,
                   <fs_stpo> LIKE LINE OF pt_stpo.

    "循环内表pt_stpo
    LOOP AT pt_stpo ASSIGNING <fs_stpo>.
      "在Component前面添零
      CLEAR l_component.
      CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
        EXPORTING
          input  = <fs_stpo>-component
        IMPORTING
          output = l_component.

      "添加BOM Items
      CLEAR lwa_items.
      lwa_items-bom_group_identification = bom_group_identification.
      lwa_items-object_type = 'ITM'.
      lwa_items-object_id = object_id.
      lwa_items-item_no = <fs_stpo>-item_no.
      lwa_items-item_cat = <fs_stpo>-item_categ.
      lwa_items-component = l_component.
      lwa_items-comp_qty = <fs_stpo>-comp_qty.
      lwa_items-comp_unit = <fs_stpo>-comp_unit.
      lwa_items-valid_from_date = sy-datum.
      APPEND lwa_items TO lt_items.
    ENDLOOP.

    "循环内表
    LOOP AT pt_stko ASSIGNING <fs_stko>.
      "添加BOM Group信息
      CLEAR lwa_bomgroup.
      lwa_bomgroup-bom_group_identification = bom_group_identification.
      lwa_bomgroup-object_type = 'BGR'.
      lwa_bomgroup-object_id = object_id.
      lwa_bomgroup-bom_usage = s_stlan2-low.
      lwa_bomgroup-bom_group = <fs_stko>-bom_group.
      lwa_bomgroup-created_in_plant = p_plant.
      lwa_bomgroup-auth_group = <fs_stko>-auth_group.
      lwa_bomgroup-technical_type = ' '.
      lwa_bomgroup-ltxt_lang = sy-langu.
      lwa_bomgroup-bom_text = <fs_stko>-bom_text.
      APPEND lwa_bomgroup TO lt_bomgroup.

      "添加Variant信息
      CLEAR lwa_variant.
      lwa_variant-bom_group_identification = bom_group_identification.
      lwa_variant-object_type = 'BOM'.
      lwa_variant-object_id = object_id.
      lwa_variant-alternative_bom = s_stlal2-low.
      lwa_variant-bom_status = <fs_stko>-bom_status.
      lwa_variant-deletion_ind = <fs_stko>-delete_ind.
      lwa_variant-base_qty = <fs_stko>-base_quan.
      lwa_variant-base_unit = <fs_stko>-base_unit.
      lwa_variant-lab_design = <fs_stko>-laboratory.
      lwa_variant-ltxt_lang = sy-langu.
      lwa_variant-alt_text = <fs_stko>-alt_text.
      lwa_variant-valid_from_date = sy-datum.
      lwa_variant-change_no = <fs_stko>-chg_no.
      lwa_variant-function = 'NEW'.
      APPEND lwa_variant TO lt_variant.
    ENDLOOP.

    CLEAR lwa_mbm.
    lwa_mbm-bom_group_identification = bom_group_identification.
    lwa_mbm-material = p_material.
    lwa_mbm-bom_usage = s_stlan2-low.
    lwa_mbm-plant = p_plant.
    lwa_mbm-alternative_bom = s_stlal2-low.
    APPEND lwa_mbm TO lt_mbm.

    CLEAR lwa_itemass.
    lwa_itemass-bom_group_identification = bom_group_identification.
    lwa_itemass-sub_object_type = 'ITM'.
    lwa_itemass-sub_object_id = object_id.
    lwa_itemass-super_object_type = 'BOM'.
    lwa_itemass-super_object_id = object_id.
    lwa_itemass-valid_from_date = sy-datum.
    lwa_itemass-function = 'NEW'.
    APPEND lwa_itemass TO lt_itemass.

    "调用BAPI创建BOM
    CALL FUNCTION 'BAPI_MATERIAL_BOM_GROUP_CREATE'
      EXPORTING
        all_error         = 'X'
      TABLES
        bomgroup          = lt_bomgroup
        variants          = lt_variant
        items             = lt_items
        materialrelations = lt_mbm
        itemassignments   = lt_itemass
        return            = lt_return.

    p_flag = 'X'.
    LOOP AT lt_return INTO lwa_return WHERE type = 'A' OR type = 'E'.
      p_flag = ''.
      l_error = lwa_return-message.
      EXPORT p1 = l_error TO MEMORY ID 'CREATE'.
      EXIT.
    ENDLOOP.

    IF p_flag = 'X'.
      CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'.
    ELSE.
      CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
    ENDIF.

    FREE: lt_bomgroup,
          lt_variant,
          lt_items,
          lt_mbm,
          lt_itemass,
          lt_return.
  ENDMETHOD.                    "create_bom

*维护BOM
  METHOD maintain_bom.
    DATA: lwa_stpo      LIKE LINE OF pt_stpo,
          l_material    LIKE p_material,
          lt_stpo2      TYPE ty_tab_stpo2,
          lt_stpo2_temp TYPE ty_tab_stpo2,
          lt_messages   TYPE ty_tab_messages,
          lwa_messages  LIKE LINE OF lt_messages,
          l_error       TYPE string.
    FIELD-SYMBOLS <fs_stpo> LIKE LINE OF pt_stpo.
    "补0
    CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
      EXPORTING
        input  = p_material
      IMPORTING
        output = l_material.

    p_flag = 'X'.

    "Log
    CALL METHOD me->set_log.
    "打开BOM维护
    CALL FUNCTION 'CSAP_MAT_BOM_OPEN'
      EXPORTING
        material    = l_material
        plant       = p_plant
        bom_usage   = p_usage
        alternative = p_alternative
        valid_from  = p_valid
      TABLES
        t_stpo      = lt_stpo2
      EXCEPTIONS
        error       = 1.

    IF sy-subrc = 0.
      "先把所有目标工厂的BOM数据打上删除标记
      lwa_stpo-fldelete = 'X'.
      MODIFY lt_stpo2 FROM lwa_stpo TRANSPORTING fldelete WHERE fldelete <> 'X'.

      LOOP AT pt_stpo INTO lwa_stpo.
        READ TABLE lt_stpo2 ASSIGNING <fs_stpo> WITH KEY component = lwa_stpo-component.
        IF sy-subrc = 0.
          "找到则是需要修改的
          lwa_stpo-itm_ident  = <fs_stpo>-itm_ident.
          lwa_stpo-bom_no     = <fs_stpo>-bom_no.
          lwa_stpo-item_node  = <fs_stpo>-item_node.
          lwa_stpo-item_count = <fs_stpo>-item_count.
          lwa_stpo-valid_from = p_valid.
          APPEND lwa_stpo TO lt_stpo2_temp.
          "删除lt_stpo3里修改的记录,剩下的就是删除的
          DELETE lt_stpo2 WHERE itm_ident = <fs_stpo>-itm_ident.
        ELSE.
          "找不到的则是新增的
          lwa_stpo-itm_ident = ''.
          lwa_stpo-bom_no = ''.
          lwa_stpo-item_node = ''.
          lwa_stpo-item_count = ''.
          lwa_stpo-valid_from = p_valid.
          APPEND lwa_stpo TO lt_stpo2_temp.
        ENDIF.
      ENDLOOP.
      "把lt_stpo2剩下的,即是删除的添加内表lt_stpo2_temp
      APPEND LINES OF lt_stpo2 TO lt_stpo2_temp.
    ELSE.
      p_flag = ''.
      lt_messages = me->get_current_log( ).
      LOOP AT lt_messages INTO lwa_messages WHERE msg_type = 'E'
                                            OR msg_type = 'A'.
        l_error = lwa_messages-msg_txt.
        EXPORT p1 = l_error TO MEMORY ID 'MAINTAIN'.
        EXIT.
      ENDLOOP.
      EXIT.
    ENDIF.

    "循环处理BOM Item
    LOOP AT lt_stpo2_temp INTO lwa_stpo.
      "补零
      CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
        EXPORTING
          input  = lwa_stpo-component
        IMPORTING
          output = lwa_stpo-component.
      CALL FUNCTION 'CSAP_BOM_ITEM_MAINTAIN'
        EXPORTING
          i_stpo = lwa_stpo
        EXCEPTIONS
          error  = 1.
      IF sy-subrc <> 0.
        p_flag = ''.
        lt_messages = me->get_current_log( ).
        LOOP AT lt_messages INTO lwa_messages WHERE msg_type = 'E'
                                              OR msg_type = 'A'.
          EXPORT p1 = lwa_messages-msg_txt TO MEMORY ID 'MAINTAIN'.
          EXIT.
        ENDLOOP.
        EXIT.
      ENDIF.
    ENDLOOP.
    "关闭BOM维护
    CALL FUNCTION 'CSAP_MAT_BOM_CLOSE'
      EXCEPTIONS
        error = 1.
    IF sy-subrc <> 0.
      p_flag = ''.
      EXIT.
    ENDIF.

    FREE: lt_stpo2,
          lt_stpo2_temp.
  ENDMETHOD.                    "maintain_bom

*构造方法
  METHOD constructor.
    "格式化有限日期
    CONCATENATE sy-datum+6(2)
                sy-datum+4(2)
                sy-datum+0(4)
    INTO g_valid_from SEPARATED BY '.'.
  ENDMETHOD.                    "contructor

ENDCLASS.                    "lcl_bom IMPLEMENTATION

*&---------------------------------------------------------------------*
*&      Form  f_set_clock
*&---------------------------------------------------------------------*
*       程序处理时状态栏显示的小时钟
*----------------------------------------------------------------------*
*      -->P_PERCENTAGE  时钟显示的百分比
*----------------------------------------------------------------------*
FORM f_set_clock USING p_percentage.
  CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
    EXPORTING
      percentage = p_percentage.
ENDFORM.                    "f_set_clock

*&---------------------------------------------------------------------*
*&      Form  f_main
*&---------------------------------------------------------------------*
*       子程序。整合所有方法,执行并输出结果
*----------------------------------------------------------------------*
FORM f_main.
  DATA: lt_source TYPE ty_tab_mast,
        lwa_source LIKE LINE OF lt_source,
        lt_target  TYPE ty_tab_mast,
        lwa_target LIKE LINE OF lt_target,
        lt_plant   TYPE ty_tab_plant,
        lt_stpo2   TYPE ty_tab_stpo2,
        lwa_stpo2  LIKE LINE OF lt_stpo2,
        lt_stko2   TYPE ty_tab_stko2.
  DATA: l_flag,
        l_error  TYPE string,
        l_count  TYPE string,
        l_count1 TYPE i,    "成功的记录数
        l_count2 TYPE i,    "失败的记录数
        l_werks  LIKE LINE OF lt_plant.
  DATA: lr_bom   TYPE REF TO lcl_bom.

*创建类LCL_BOM对象
  CREATE OBJECT lr_bom.

*筛选选择的物料
  CALL METHOD lr_bom->get_data
    IMPORTING
      pt_source = lt_source
      pt_target = lt_target.

  PERFORM f_set_clock USING 10.

*取得目标工厂内表
  lt_plant = lr_bom->get_target_plant( ).

  IF lt_source IS INITIAL
    OR lt_plant IS INITIAL.
    MESSAGE s003(zmm).
    EXIT.
  ENDIF.
  PERFORM f_set_clock USING 50.
*输出选择条件文本
  lr_bom->write_header_text( lt_plant ).

  SORT lt_source BY werks.

  "按工厂处理BOM
  LOOP AT lt_plant INTO l_werks.
    CLEAR: l_count1,l_count2.
    "如果源BOM和目标BOM相同,跳过
    IF s_source-low = l_werks
      AND s_stlan-low = s_stlan2-low
      AND s_stlal-low = s_stlal2-low.
      CONTINUE.
    ENDIF.
    WRITE:/ 'Start plant',l_werks.
    "循环源物料内表,处理指定工厂的物料
    LOOP AT lt_source INTO lwa_source.
      "查看BOM数据
      CALL METHOD lr_bom->read_bom
        EXPORTING
          p_material    = lwa_source-matnr
          p_plant       = s_source-low
          p_bom_usage   = s_stlan-low
          p_alternative = s_stlal-low
          p_valid_from  = g_valid_from
        IMPORTING
          pt_stpo       = lt_stpo2
          pt_stko       = lt_stko2
          p_flag        = l_flag.
      "查得数据成功
      IF sy-subrc = 0 AND l_flag = 'X'.
        "如果BOM的Item为空
        IF lt_stpo2 IS INITIAL.
          FORMAT COLOR 6 ON.
          WRITE: /3 icon_cancel AS ICON,
                    'Material',
                    lwa_source-matnr+10(8),
                    'BOM Usage',
                    s_stlan-low,
                    'not found in source plant',
                    s_source-low.
          FORMAT COLOR 6 OFF.
          l_count2 = l_count2 + 1.
          CONTINUE.
        ENDIF.

        "判断当前物料是否在目标工厂中存在
        l_flag = lr_bom->check_matnr(
          p_matnr = lwa_source-matnr
          p_plant = l_werks
        ).
        "物料不在目标工厂就跳过
        IF l_flag <> 'X'.
          WRITE: /3 icon_skip AS ICON,
                    'Material',
                    lwa_source-matnr+10(8),
                    'not found in target plant',
                    l_werks.
          l_count2 = l_count2 + 1.
          CONTINUE.
        ENDIF.

        " 判断组件是否在目标工厂中存在
        CLEAR lr_bom->lt_mat_wer2.
        LOOP AT lt_stpo2 INTO lwa_stpo2.
          "补零
          CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
            EXPORTING
              input  = lwa_stpo2-component
            IMPORTING
              output = lwa_stpo2-component.
          l_flag = lr_bom->check_component(
            p_matnr = lwa_stpo2-component
            p_plant = l_werks
            pt_stpo = lt_stpo2
          ).
          IF l_flag <> 'X'.
            WRITE: /3 icon_skip AS ICON,
                      'Component',
                      lwa_stpo2-component+10(8),
                      'not found in target plant',
                      l_werks.
            l_count2 = l_count2 + 1.
            EXIT.
          ENDIF.
        ENDLOOP.
        "如果组件在目标工厂不存在,跳过
        CHECK l_flag = 'X'.

        "判断目标BOM是否存在
        l_flag = lr_bom->check_exist_bom(
          p_material    = lwa_source-matnr
          p_plant       = l_werks
          p_bom_usage   = s_stlan2-low
          p_alternative = s_stlal2-low
          pt_target     = lt_target
        ).
        "目标BOM存在
        IF l_flag = 'X'.
          "存在是否跳过
          IF p_exist <> 'X'.
            "维护BOM
            l_flag = lr_bom->maintain_bom(
                p_material = lwa_source-matnr
                p_plant = l_werks
                p_usage = s_stlan2-low
                p_alternative = s_stlal2-low
                p_valid = g_valid_from
                pt_stpo = lt_stpo2
                pt_stko = lt_stko2
             ).
            IF l_flag = 'X'.
*              WRITE: /3 icon_okay AS ICON,
*                        'Material',
*                        lwa_source-matnr+10(8),
*                        'copy success to plant',
*                        l_werks.
              l_count1 = l_count1 + 1.
            ELSE.
              "从内存取得错误文本
              IMPORT p1 = l_error FROM MEMORY ID 'MAINTAIN'.
              IF sy-subrc = 0.
                FORMAT COLOR 6 ON.
                WRITE: /3 icon_cancel AS ICON,l_error.
                FORMAT COLOR 6 OFF.
                FREE MEMORY ID 'MAINTIAN'.
                l_count2 = l_count2 + 1.
                CONTINUE.
              ENDIF.
            ENDIF.
          ELSE.
            WRITE: /3 icon_skip AS ICON,
                      'Material',
                      lwa_source-matnr+10(8),
                      'BOM exists and skip copy to plant',
                      l_werks.
            l_count2 = l_count2 + 1.
          ENDIF.
        ELSE.
          "BOM不存在,创建BOM
          l_flag = lr_bom->create_bom(
              p_material = lwa_source-matnr
              p_plant = l_werks
              pt_stpo = lt_stpo2
              pt_stko = lt_stko2
          ).
          IF l_flag = 'X'.
*            "输出成功创建BOM的信息
*            WRITE: /3 icon_okay AS ICON,
*                      'Material',
*                      lwa_source-matnr+10(8),
*                      'copy success to plant',
*                      l_werks.
            l_count1 = l_count1 + 1.
          ELSE.
            IMPORT p1 = l_error FROM MEMORY ID 'CREATE'.
            IF sy-subrc = 0.
              FORMAT COLOR 6 ON.
              WRITE: /3 icon_cancel AS ICON,
                        l_error.
              FREE MEMORY ID 'CREATE'.
              l_count2 = l_count2 + 1.
            ENDIF.

            FORMAT COLOR 6 OFF.
            CONTINUE.
          ENDIF.
        ENDIF.
      ENDIF.
    ENDLOOP.
    l_count = l_count1.
    WRITE:/ l_count,'material copied success'.
    l_count = l_count2.
    WRITE:/ l_count,'material copied fail'.
    SKIP.
  ENDLOOP.
  WRITE / '-- End of Report --'.

  FREE: lt_source,
        lt_target,
        lt_plant,
        lt_stpo2,
        lt_stko2.
ENDFORM.                    "f_main

*----------------------------------------------------------------------*
*       执行事件
*----------------------------------------------------------------------*
START-OF-SELECTION.
  PERFORM f_main.
<think>好的,我现在需要帮助用户了解SAP中的物料清单(BOM)概念及其配置方法。首先,我应该回顾一下用户提供的引用内容,确保回答准确。 根据引用[3],BOM是Variant Configuration的主数据之一,特别是提到了Super BOM,这说明在变式配置中,BOM的结构可能比较复杂,需要处理多种变体。然后引用[2]提到在配置文件中定义过滤器可以限制BOM项的范围,从而提高系统性能,尤其是在展开BOM时。这可能是配置BOM时的一个关键点。 用户可能想知道BOM的基本概念,包括用途、类型以及如何配置。我需要先解释BOM是什么,在SAP中的作用,比如生产、物料需求计划等。然后,分类型介绍,比如生产BOM、销售BOM、超级BOM,特别是变式配置中的超级BOM,因为引用里提到了Super BOM。 接下来,配置方法部分需要详细步骤。用户提到的交易码,如CS01,应该包括创建BOM操作步骤。同时,需要提到对象依赖,比如引用[3]中的对象依赖,可能包括预条件、选择条件等,这些在配置BOM时用于控制组件的选择。此外,配置配置文件(Configuration Profile)也是关键,引用[2]中的过滤器就是在配置文件中设置的,需要说明如何应用过滤器优化性能。 性能优化方面,引用[2]中的过滤器是重点,应该详细说明如何设置过滤器,以及它在不同场景下的应用。可能还需要提到其他优化方法,比如简化BOM结构或使用分类系统(引用[1]中的分类事务CT04可能相关)。 最后,注意事项部分需要涵盖版本控制、权限、依赖管理等方面,确保用户了解实际应用中的要点。相关问题部分需要生成几个相关问题,帮助用户进一步学习,比如如何创建BOM,变式配置中的BOM应用,性能优化方法等。 需要确保使用正确的中文术语,比如“物料清单”、“变式配置”、“对象依赖”等。同时,按照用户的系统级指令,数学公式用$...$,但这里可能用不上,但行内的技术术语如交易码需要用正确格式。检查是否有遗漏的引用内容,确保每个引用都恰当使用,比如引用[1]提到的分类事务可能在特性管理部分相关。 现在需要组织这些信息,结构清晰,分点说明,同时自然融入引用内容。确保回答真实可靠,基于提供的引用和SAP的一般知识。</think>### SAP物料清单(BOM)概念与配置方法 #### 一、BOM基础概念 物料清单(Bill of Materials, BOM)是SAP中定义产品组成结构的核心数据,涵盖原材料、半成品、组件及其数量关系。在**变式配置(Variant Configuration)**场景中,通过**超级BOM(Super BOM)**[^3]支持多产品变体,例如同一型号汽车的不同配置版本。 #### 二、BOM类型与用途 1. **生产BOM** 用于生产计划(PP模块),包含工序、工作中心及物料需求,通过事务码`CS01`创建。 2. **销售BOM** 在SD模块中管理组合销售产品(如套餐),支持按层级拆分订单。 3. **超级BOM** 结合特性(Characteristic)和对象依赖(Object Dependencies),动态筛选组件,适用于可配置产品。 #### 三、BOM配置步骤 1. **创建BOM** - 事务码`CS01`进入创建界面,输入物料编号、工厂、用途(如生产)。 - 添加组件物料及数量,设置有效性日期。 ```abap 示例路径:Logistics > Production > Master Data > Bills of Material > Bill of Material > Material BOM > Create ``` 2. **对象依赖配置** - **预条件(Preconditions)**:控制组件是否被选中,例如根据特性值`颜色=红色`。 - **选择条件(Selection Conditions)**:动态修改组件数量,例如`IF 温度>30 THEN 数量=2`。 3. **配置配置文件(Configuration Profile)** - 通过过滤器限制BOM展开范围,提升性能(例如仅加载特定客户需求的组件)[^2]。 - 路径:在物料主数据中关联配置参数文件,激活变式配置逻辑。 #### 四、性能优化方法 1. **过滤器设置** 在配置文件中定义筛选规则,避免全量BOM展开,适用于高层级配置和结果导向型BOM。 2. **分类系统辅助** 使用特性(CT04事务码[^1])和类(Class)管理可配置参数,确保BOM组件与特性逻辑绑定。 3. **依赖简化** 避免复杂嵌套依赖,采用表约束(Table Constraints)或全局依赖优化执行效率。 #### 五、注意事项 1. **版本控制** BOM需设置有效期,避免历史数据干扰生产。 2. **权限管理** 通过工单类型和工厂参数限制BOM修改权限。 3. **依赖测试** 使用`CU50`事务码模拟配置,验证组件筛选逻辑是否正确。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值