生产订单的批量创建和组件的批量修改

发布时间 2023-09-22 14:17:10作者: yangliu11223

生产订单批量创建

组件批量更改(先删除自带的,再添加上传的)

 

*----------------------------------------------------------------------*
* 模 块: PP
* 描 述: 生产订单批导
* 时 间: 2023-07-10
*----------------------------------------------------------------------*
* 修 改 标 记|修 改 时 间|修 改 人|修 改 原 因
* 1           2023-07-10       Create
*----------------------------------------------------------------------*
REPORT zppc004.

CLASS lcl_app DEFINITION DEFERRED.
TABLES:sscrfields.
DATA:app TYPE REF TO lcl_app.

*--------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK a1 WITH FRAME TITLE TEXT-t01 .
  SELECTION-SCREEN FUNCTION KEY 1 .
  PARAMETERS : p_file  TYPE localfile MODIF ID b1 MEMORY ID mi1.
SELECTION-SCREEN END OF BLOCK a1 .

SELECTION-SCREEN BEGIN OF BLOCK a2 WITH FRAME TITLE TEXT-t02 .
  PARAMETERS : r_hdr RADIOBUTTON GROUP r1 DEFAULT 'X' MODIF ID sc1,
               r_com RADIOBUTTON GROUP r1 MODIF ID sc1.
SELECTION-SCREEN END OF BLOCK a2 .
*--------------------------------------------------------------------*
CLASS lcl_app DEFINITION.
  PUBLIC SECTION.
    INTERFACES zif_handle_grid_event.

    DATA:
      mv_ucomm     TYPE sy-ucomm,        "grid ucomm
      mt_fieldcat  TYPE lvc_t_fcat,
      mt_excluding TYPE lvc_t_excl,
      mo_grid      TYPE REF TO cl_gui_alv_grid,
      mt_out       TYPE REF TO data.

    DATA:mv_structure TYPE string.
    TYPES:tt_component TYPE TABLE OF zpps004_com.

    METHODS:main,
      get_excel_data,
      modify_data,
      get_file,
      create_dynamic_table,
      create_grid CHANGING out_tab TYPE ANY TABLE,
      check_authority,
      call_bapi,
      call_bapi_production,
      call_bapi_component,

      delete_component IMPORTING iv_aufnr TYPE aufnr
                       EXPORTING ev_code  TYPE char01
                                 ev_msg   TYPE bapi_msg,
      add_component IMPORTING it_component TYPE tt_component
                    EXPORTING ev_code      TYPE char01
                              ev_msg       TYPE bapi_msg.
ENDCLASS.

INITIALIZATION.
  app = NEW lcl_app(  ) ##NEEDED.
  CONCATENATE icon_xls TEXT-002 INTO sscrfields-functxt_01.


AT SELECTION-SCREEN .
  CASE sscrfields-ucomm.
    WHEN'FC01'.
      zcl_abap_comm=>download_file_from_smw0( iv_objid    = 'ZPPC004'
                                              iv_filename = |未清生产订单上载模板_{ sy-datum }_{ sy-uzeit }| ).
  ENDCASE.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.
  app->get_file( ).

START-OF-SELECTION.
  app->main( ).

*---------------------------------------------------------------------*
* app IMPLEMENTATION
*---------------------------------------------------------------------*
CLASS lcl_app IMPLEMENTATION.

  METHOD main.

    check_authority( ).

    create_dynamic_table( ).

    get_excel_data( ).

    modify_data( ).

    CALL SCREEN 0100.

  ENDMETHOD.

  METHOD get_file.

    DATA:lv_rc        TYPE i,
         lt_filetable TYPE filetable.

    CALL METHOD cl_gui_frontend_services=>file_open_dialog
      EXPORTING
        window_title            = CONV #( '选择数据文件' )
        file_filter             = '(*.xlsx)|*.xlsx|(*.xls)|*.xls'
        multiselection          = space
      CHANGING
        file_table              = lt_filetable
        rc                      = lv_rc
      EXCEPTIONS
        file_open_dialog_failed = 1
        cntl_error              = 2
        error_no_gui            = 3
        not_supported_by_gui    = 4
        OTHERS                  = 5.

    IF sy-subrc = 0 AND lv_rc = 1.
      READ TABLE lt_filetable INTO p_file INDEX 1.
    ENDIF.

  ENDMETHOD.

  METHOD create_dynamic_table.

    IF r_hdr IS NOT INITIAL.
      mv_structure = 'ZPPS004_HDR'.
    ELSE.
      mv_structure = 'ZPPS004_COM'.
    ENDIF.

    CREATE DATA mt_out TYPE TABLE OF (mv_structure).
  ENDMETHOD.

  METHOD create_grid.
    DATA(container) = NEW cl_gui_docking_container( extension = 2050
                                                    side      = cl_gui_docking_container=>property_floating ).

    "Set display
    mt_fieldcat = zcl_abap_comm=>get_fieldcat( EXPORTING it_outtab = mt_out->* iv_structure = CONV #( mv_structure ) ).
    mo_grid = NEW #( i_parent = container ).
    mo_grid->set_table_for_first_display(
      EXPORTING
        i_save          = 'A'
        i_default       = 'X'
        is_layout       = VALUE #(
        zebra           = abap_true
        sel_mode        = 'B'
        cwidth_opt      = abap_true
        no_toolbar      = abap_false
        grid_title      = CONV lvc_title( |Entries:{ lines( out_tab ) }| ) )
      CHANGING
        it_fieldcatalog = mt_fieldcat
        it_outtab       = out_tab ).

    "SET HANDLER
    SET HANDLER zif_handle_grid_event~toolbar
                zif_handle_grid_event~user_command
                FOR mo_grid.
    mo_grid->set_toolbar_interactive( ).
  ENDMETHOD.

  METHOD check_authority.
*    AUTHORITY-CHECK OBJECT 'Z_WERKS'
*    ID 'WERKS'  FIELD p_werks.
*    IF sy-subrc <> 0.
*      MESSAGE '没有该工厂权限'(e01) TYPE 'S' DISPLAY LIKE 'E'.
*      LEAVE LIST-PROCESSING.
*    ENDIF.
  ENDMETHOD.

  METHOD get_excel_data.

    "excel 参数定义
    DATA: lo_reader TYPE REF TO zcl_excel_reader_2007.
    DATA: lo_excel TYPE REF TO zcl_excel.

    TRY.
        CREATE OBJECT lo_reader.
        lo_reader->zif_excel_reader~load_file(
          EXPORTING
            i_filename = CONV string( p_file )
          RECEIVING
            r_excel    = lo_excel ).
      CATCH zcx_excel.
        MESSAGE 'EXCEL文件正在被打开,请关闭后上传。'(001) TYPE 'E'.
    ENDTRY.

    lo_excel->get_worksheet_by_name(
      EXPORTING
        ip_sheet_name = COND #( WHEN r_hdr IS NOT INITIAL THEN '抬头'
                                WHEN r_com IS NOT INITIAL THEN '组件' )
      RECEIVING
        eo_worksheet  = DATA(lo_worksheet) ).


    ASSIGN mt_out->* TO FIELD-SYMBOL(<ft_table>).
    lo_worksheet->get_table(
      EXPORTING
        iv_skipped_rows           = 2
*       iv_skipped_cols           = 2
        iv_max_col                = 30
        iv_skip_bottom_empty_rows = abap_true
      IMPORTING
        et_table                  = <ft_table> ).


  ENDMETHOD.

  METHOD modify_data.
    FIELD-SYMBOLS:<fs_out_hdr> TYPE zpps004_hdr,
                  <fs_out_com> TYPE zpps004_com.

    IF r_hdr IS NOT INITIAL.
      LOOP AT mt_out->* ASSIGNING <fs_out_hdr>.
        IF <fs_out_hdr>-fname7 IS INITIAL.   "物料号
          SELECT SINGLE matnr meins INTO (<fs_out_hdr>-fname7,<fs_out_hdr>-fname12) FROM mara
            WHERE bismt = <fs_out_hdr>-fname6.
        ENDIF.

        CALL FUNCTION 'CONVERSION_EXIT_CUNIT_INPUT'
          EXPORTING
            input          = <fs_out_hdr>-fname12
          IMPORTING
            output         = <fs_out_hdr>-fname12
          EXCEPTIONS
            unit_not_found = 1
            OTHERS         = 2.

      ENDLOOP.

    ELSE.
      LOOP AT mt_out->* ASSIGNING <fs_out_com>.
        IF <fs_out_com>-fname5 IS INITIAL.   "物料号
          SELECT SINGLE matnr meins INTO (<fs_out_com>-fname5,<fs_out_com>-fname10) FROM mara
            WHERE bismt = <fs_out_com>-fname4.
        ENDIF.

        CALL FUNCTION 'CONVERSION_EXIT_CUNIT_INPUT'
          EXPORTING
            input          = <fs_out_com>-fname10
          IMPORTING
            output         = <fs_out_com>-fname10
          EXCEPTIONS
            unit_not_found = 1
            OTHERS         = 2.

      ENDLOOP.
    ENDIF.

  ENDMETHOD.

  METHOD zif_handle_grid_event~toolbar .
    DELETE e_object->mt_toolbar WHERE ( function = '&&SEP01'
                                     OR function = '&LOCAL&CUT'
                                     OR function = '&LOCAL&COPY'
                                     OR function = '&LOCAL&COPY_ROW'
                                     OR function = '&LOCAL&PASTE'
                                     OR function = '&LOCAL&UNDO'
                                     OR function = '&&SEP02'
                                     OR function = '&LOCAL&APPEND'
                                     OR function = '&LOCAL&INSERT_ROW'
                                     OR function = '&LOCAL&DELETE_ROW'
                                     OR function = 'LOCAL&COPY_ROW'
                                     OR function = '&CHECK'
                                     OR function = '&REFRESH'
                                     OR function = '&&SEP07'
                                     OR function = '&INFO').
*--------------------------------------------------------------------*
    e_object->mt_toolbar = VALUE #( BASE e_object->mt_toolbar ( butn_type = 3 ) ).
    e_object->mt_toolbar = VALUE #( BASE e_object->mt_toolbar ( icon      = icon_test
                                                                function  = 'RUN'
                                                                text      = '运行'
                                                                quickinfo = '运行'
                                                               ) ).

  ENDMETHOD.

  METHOD zif_handle_grid_event~user_command.
*    set_sel_col( ).

    CASE e_ucomm.
      WHEN 'RUN'.
        call_bapi( ).
      WHEN OTHERS.
    ENDCASE.
*--------------------------------------------------------------------*
    DATA(lv_ucomm) = CONV sy-ucomm( '&OPT' ).
    mo_grid->set_function_code( CHANGING c_ucomm = lv_ucomm ).
    mo_grid->refresh_table_display( is_stable = VALUE lvc_s_stbl( row = 'X' col = 'X') ).
  ENDMETHOD.

  METHOD call_bapi.
    IF r_hdr = 'X'.
      call_bapi_production( ).
    ELSE.
      call_bapi_component( ).
    ENDIF.
  ENDMETHOD.

  METHOD call_bapi_production.
    FIELD-SYMBOLS:<fs_out> TYPE zpps004_hdr.
    DATA:return       TYPE  bapiret2,
         order_number TYPE  bapi_order_key-order_number,
         order_type   TYPE  bapi_order_copy-order_type.
    DATA:lv_msg TYPE string.
    ASSIGN mt_out->* TO FIELD-SYMBOL(<ft_out>).

    LOOP AT <ft_out> ASSIGNING <fs_out>.

      DATA(ls_order) = VALUE bapi_pp_order_create(
        material         = zcl_abap_comm=>conv_matnr_internal( CONV #( <fs_out>-fname7 ) )           "订单的物料编号
        plant            = <fs_out>-fname3      "工厂
        order_type       = <fs_out>-fname5      "订单类型
        basic_start_date = <fs_out>-fname13     "基本开始日期
        basic_end_date   = <fs_out>-fname14     "基本完成日期
        quantity         = <fs_out>-fname11     "总订单数量
        prod_version     = <fs_out>-fname15     "生产版本
        unloading_point  = <fs_out>-fname1      "卸货点 (JDE工单号)
      ).

      CALL FUNCTION 'BAPI_PRODORD_CREATE'
        EXPORTING
          orderdata    = ls_order
        IMPORTING
          return       = return
          order_number = order_number
          order_type   = order_type.


      IF return-type CA 'EXA'.
        CALL FUNCTION 'MESSAGE_TEXT_BUILD'
          EXPORTING
            msgid               = return-id
            msgnr               = return-number
            msgv1               = return-message_v1
            msgv2               = return-message_v2
            msgv3               = return-message_v3
            msgv4               = return-message_v4
          IMPORTING
            message_text_output = <fs_out>-msg.

        <fs_out>-icon = icon_led_red.
        ROLLBACK WORK.
      ELSE.
        <fs_out>-msg = '成功'.
        <fs_out>-icon = icon_led_green.
        <fs_out>-fname2 = order_number.
          COMMIT WORK.
      ENDIF.
    ENDLOOP.


  ENDMETHOD.

  METHOD call_bapi_component.

    FIELD-SYMBOLS:<fs_out> TYPE zpps004_com.
    DATA:lt_component TYPE tt_component.
    DATA:ls_component LIKE LINE OF lt_component.

    ASSIGN mt_out->* TO FIELD-SYMBOL(<ft_out>).

    LOOP AT <ft_out> into ls_component GROUP BY ( aufnr = ls_component-fname2 ).

      "COXT函数组的一些函数使用时,需要执行CO_XT_ORDER_PREPARE_COMMIT预提交,正式提交后需要执行CO_XT_ORDER_INITIALIZE再次初始化
      delete_component( EXPORTING iv_aufnr = |{ CONV aufnr( ls_component-fname2 ) ALPHA = IN }|
                        IMPORTING ev_code = DATA(lv_code) ev_msg = DATA(lv_msg) ) .
      IF lv_code = 'E'.
        LOOP AT GROUP ls_component ASSIGNING <fs_out>.
          <fs_out>-icon = icon_led_red.
          <fs_out>-msg = lv_msg.
        ENDLOOP.
        CONTINUE.
      ENDIF.

      "CO_XT_COMPONENT_ADD这个函数每次只能处理一条数据。如果添加多条需要循环处理,都成功后统一预提交,再正式提交,清缓存。
      CLEAR lt_component.
      LOOP AT GROUP ls_component ASSIGNING <fs_out>.
        APPEND <fs_out> TO lt_component.
      ENDLOOP.
      add_component( EXPORTING it_component = lt_component
                     IMPORTING ev_code      = lv_code
                               ev_msg       = lv_msg ).

      LOOP AT GROUP ls_component ASSIGNING <fs_out>.
        IF lv_code = 'E'.
          <fs_out>-icon = icon_led_red.
          <fs_out>-msg = lv_msg.
        ELSE.
          <fs_out>-icon = icon_led_green.
          <fs_out>-msg = '成功'.
        ENDIF.
      ENDLOOP.

    ENDLOOP.
  ENDMETHOD.

  METHOD delete_component.
    DATA: lt_resbkeys   TYPE coxt_t_resbdel,
          lt_return     TYPE STANDARD TABLE OF bapiret2,
          ls_return     TYPE bapiret2,
          lv_error      TYPE flag,
          ls_bapireturn TYPE coxt_bapireturn.

* Fetch existing components of given Production Order
    SELECT rsnum, rspos INTO TABLE @DATA(lt_resb)
                        FROM resb
                        WHERE aufnr = @iv_aufnr.  " Previously created order
    IF sy-subrc EQ 0.
      lt_resbkeys = CORRESPONDING #( lt_resb ).
    ENDIF.

    IF NOT lt_resbkeys[] IS INITIAL.
* BAPI to delete the components of Production Order
      CALL FUNCTION 'CO_XT_COMPONENTS_DELETE'
        EXPORTING
          it_resbkeys_to_delete = lt_resbkeys
        IMPORTING
          e_error_occurred      = lv_error
        TABLES
          ct_bapireturn         = lt_return
        EXCEPTIONS
          delete_failed         = 1
          OTHERS                = 2.
      IF lv_error = space.
"刷新变量(必须)
PERFORM change_flag_set IN PROGRAM saplcozv. CALL FUNCTION 'CO_XT_ORDER_PREPARE_COMMIT' IMPORTING es_bapireturn = ls_bapireturn e_error_occurred = lv_error. IF ( ls_bapireturn-type = 'S' OR ls_bapireturn-type = 'W' OR ls_bapireturn-type = 'I' ) OR ls_bapireturn IS INITIAL. ev_code = 'S'. CALL FUNCTION 'BAPI_TRANSACTION_COMMIT' EXPORTING wait = 'X'. CALL FUNCTION 'CO_XT_ORDER_INITIALIZE'. ELSE. ev_code = 'E'. CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'. MESSAGE ID ls_bapireturn-id TYPE ls_bapireturn-type NUMBER ls_bapireturn-number WITH ls_bapireturn-message_v1 ls_bapireturn-message_v2 ls_bapireturn-message_v3 ls_bapireturn-message_v4 INTO ev_msg. ENDIF. ELSE. ev_code = 'E'. CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'. READ TABLE lt_return INTO ls_return WITH KEY type = 'E'. IF sy-subrc = 0. MESSAGE ID ls_return-id TYPE ls_return-type NUMBER ls_return-number WITH ls_return-message_v1 ls_return-message_v2 ls_return-message_v3 ls_return-message_v4 INTO ev_msg. ENDIF. ENDIF. ENDIF. ENDMETHOD. METHOD add_component. DATA: lv_aufnr TYPE coxt_ord_key, ls_requ TYPE coxt_s_quantity, ls_storage TYPE coxt_s_storage_location, ls_storagex TYPE coxt_s_storage_locationx, ls_return TYPE coxt_bapireturn, lt_return TYPE coxt_t_bapireturn, lv_msg TYPE string, lv_tabix TYPE sy-tabix, lv_postp TYPE postp, lv_operation TYPE co_aplzl, lv_sequence TYPE plnfolge, lv_material TYPE matnr, lv_positionno TYPE positionno, lv_error TYPE flag. TYPES: BEGIN OF ty_resb_bt. INCLUDE TYPE resbb. TYPES: indold LIKE sy-tabix, no_req_upd LIKE sy-datar, END OF ty_resb_bt. TYPES: lt_resb_bt TYPE TABLE OF ty_resb_bt. FIELD-SYMBOLS: <ft_resb_bt> TYPE lt_resb_bt, <fs_resb_bt> TYPE ty_resb_bt. READ TABLE it_component INTO DATA(ls_component) INDEX 1. lv_aufnr = |{ CONV aufnr( ls_component-fname2 ) ALPHA = IN }|. SELECT SINGLE werks FROM aufk WHERE aufnr = @lv_aufnr INTO @DATA(lv_werks). SELECT SINGLE aufnr, aufpl INTO @DATA(ls_afko) FROM afko WHERE aufnr = @lv_aufnr. IF sy-subrc EQ 0. * Fetch operation to which it has to be assigned SELECT SINGLE aufpl, aplzl, plnfl INTO @DATA(ls_afvc) FROM afvc WHERE aufpl = @ls_afko-aufpl. IF sy-subrc EQ 0. lv_operation = ls_afvc-aplzl. lv_sequence = ls_afvc-plnfl. ENDIF. ENDIF. LOOP AT it_component INTO ls_component. lv_tabix = sy-tabix. CLEAR: ls_requ,ls_storage,ls_storagex. ls_requ-quantity = ls_component-fname9. ls_requ-uom = ls_component-fname10. ls_storage-werks = lv_werks. * ls_storage-lgort = ls_component-lgpro. * ls_storagex-werks = 'X'. * ls_storagex-lgort = 'X'. lv_positionno = ls_component-fname3. lv_postp = 'L'. lv_material = zcl_abap_comm=>conv_matnr_internal( CONV #( ls_component-fname5 ) ). * BAPI to add components to Production Order CALL FUNCTION 'CO_XT_COMPONENT_ADD' EXPORTING is_order_key = lv_aufnr i_material = lv_material is_requ_quan = ls_requ i_operation = lv_operation i_sequence = lv_sequence is_storage_location = ls_storage is_storage_locationx = ls_storagex i_postp = lv_postp i_posno = lv_positionno IMPORTING es_bapireturn = ls_return e_error_occurred = lv_error. IF lv_error IS NOT INITIAL. EXIT. ENDIF. ENDLOOP. IF lv_error = space. CLEAR: lv_tabix, ls_return. * Modify POSNR via ASSIGN before DB update to correct the blank * item number in Components due to incompatible types of I_POSNO * (type CIF_R3RES-POSITIONNO) and RESB-POSNR ASSIGN ('(SAPLCOBC)RESB_BT[]') TO <ft_resb_bt>. LOOP AT it_component INTO ls_component. READ TABLE <ft_resb_bt> ASSIGNING <fs_resb_bt> INDEX sy-tabix. IF sy-subrc = 0. <fs_resb_bt>-posnr = ls_component-fname3. "行项目 <fs_resb_bt>-FMENG = ls_component-fname12. "固定数量 <fs_resb_bt>-RGEKZ = ls_component-fname11. "反冲 ENDIF. ENDLOOP. * LOOP AT <ft_resb_bt> ASSIGNING <fs_resb_bt>. * lv_tabix = sy-tabix * 10. * <fs_resb_bt>-posnr = lv_tabix. * CLEAR lv_tabix. * ENDLOOP. * Commit transaction CALL FUNCTION 'CO_XT_ORDER_PREPARE_COMMIT' IMPORTING es_bapireturn = ls_return e_error_occurred = lv_error. IF ( ls_return-type = 'S' OR ls_return-type = 'W' OR ls_return-type = 'I' ) OR ls_return IS INITIAL. * Commit data ev_code = 'S'. CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'. CALL FUNCTION 'CO_XT_ORDER_INITIALIZE'. ELSE. * Data Rollback ev_code = 'E'. CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'. IF ls_return-type = 'E'. MESSAGE ID ls_return-id TYPE ls_return-type NUMBER ls_return-number WITH ls_return-message_v1 ls_return-message_v2 ls_return-message_v3 ls_return-message_v4 INTO ev_msg. ENDIF. ENDIF. ELSE. * Data Rollback ev_code = 'E'. CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'. MESSAGE ID ls_return-id TYPE ls_return-type NUMBER ls_return-number WITH ls_return-message_v1 ls_return-message_v2 ls_return-message_v3 ls_return-message_v4 INTO ev_msg. ENDIF. ENDMETHOD. ENDCLASS. *&---------------------------------------------------------------------* *& Module STATUS_0100 OUTPUT *&---------------------------------------------------------------------* *& *&---------------------------------------------------------------------* MODULE status_0100 OUTPUT. IF app->mo_grid IS INITIAL. app->create_grid( CHANGING out_tab = app->mt_out->* ). ELSE. app->mo_grid->refresh_table_display( is_stable = VALUE lvc_s_stbl( row = 'X' col = 'X') ). ENDIF. SET PF-STATUS 'STATUS_0100' EXCLUDING app->mt_excluding. SET TITLEBAR 'TITLE_0100'. ENDMODULE. *&---------------------------------------------------------------------* *& Module USER_COMMAND_0100 INPUT *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* MODULE user_command_0100 INPUT. * data(l_ucomm) = ok_code. * CLEAR ok_code. * app->mo_grid->check_changed_data( IMPORTING e_valid = DATA(l_valid) ). CASE sy-ucomm. WHEN '&F03' OR '&F15' OR '&F12'. LEAVE TO SCREEN 0. WHEN OTHERS. ENDCASE. ENDMODULE.