SAP MR21/MR22物料价格修改&汇差调整凭证生成接口(BAPI批量模式)

==> 前言

  • 此接口暂适用开启物料分类账的系统,未开启物料分类账的系统请根据自行修正代码

==> 标准程序位置

  • SE38->RCKM_MR21I01 (MR21的位置)
    1
  • SE38->RCKM_MR22I02 (MR22的位置)
    2

1. 接口Z_FI_MATVAL_MR22

  • 代码:
    FUNCTION z_fi_matval_mr22.
    *"----------------------------------------------------------------------
    *"*"本地接口:
    *"  IMPORTING
    *"     VALUE(IV_KONGR) TYPE  CKML_KONGR DEFAULT 'BS1'
    *"     REFERENCE(IV_BUKRS) TYPE  BUKRS
    *"     REFERENCE(IV_BUDAT) TYPE  BUDAT
    *"     REFERENCE(IV_BKTXT) TYPE  BKTXT
    *"  EXPORTING
    *"     REFERENCE(EV_BELNR) TYPE  BELNR_D
    *"     REFERENCE(ES_OUTPUT) TYPE  ZSIF_FI_I003_RES_0003
    *"  TABLES
    *"      IT_ALLCURR TYPE  ZTFI_MR22_ALLCURR
    *"----------------------------------------------------------------------
    
      "Data Define
      TYPES: BEGIN OF ty_ckmpr_f_mat_price,
               pp         LIKE cki_pae_pp,
               cr         TYPE ckmpr_curtp_prices,
               ckmlpr     TYPE t_ckmlpr,
               keko       TYPE t_keko,
               prkeph_old TYPE mlccs_t_prkeph,
               prkeph_new TYPE mlccs_t_prkeph,
               prkeko_old TYPE mlccs_t_prkeko,
               prkeko_new TYPE mlccs_t_prkeko,
               keph_delta TYPE mlccs_t_keph,
               delta_ccs  TYPE c,  "Indicator that a non-zero delta CCS is available
               duv_prctr  TYPE prctr,
               duv_2prod  TYPE c,
               duv_index  TYPE i,                               " 2845514
             END OF ty_ckmpr_f_mat_price.
    
      DATA: lt_matpr TYPE TABLE OF ty_ckmpr_f_mat_price,
            ls_matpr TYPE ty_ckmpr_f_mat_price,
            ls_matcr TYPE cki_pae_cr.
    
      DATA: ls_komok TYPE ckmpr_f_account_det.
    
      DATA: lv_index   LIKE sy-tabix,
            lv_runref  TYPE ml4h_runref,
            lv_num_msg TYPE i,
            lt_msg     TYPE STANDARD TABLE OF cmfmsg,
            ls_msg     TYPE cmfmsg.
    
      DATA: lv_bdatj TYPE bdatj,
            lv_poper TYPE poper,
            lv_hrkft TYPE hrkft.
    
      DATA: lt_ckmpr_mat_price    TYPE ckmpr_mat_price,
            ls_ckmpr_mat_price    LIKE LINE OF lt_ckmpr_mat_price,
            ls_price_prop_ctrl    TYPE price_prop_ctrl,
            ls_ckmpr_curtp_prices TYPE cki_pae_cr.
    
      DATA: lv_msgtext TYPE string,
            ls_ckmlkon TYPE ckmlkon.
    
      "取科目修改配置
      SELECT SINGLE * FROM ckmlkon INTO ls_ckmlkon WHERE tcode = 'MR22' AND kongr = iv_kongr.
    
      "年度期间
      lv_bdatj = iv_budat+0(4).
      lv_poper = iv_budat+4(2).
      lv_hrkft = iv_kongr.
    
      "输入值转换到BAPi参数
      LOOP AT it_allcurr[] ASSIGNING FIELD-SYMBOL(<fs_allcurr>).
        LOOP AT <fs_allcurr>-one_curr ASSIGNING FIELD-SYMBOL(<fs_one_curr>).
          READ TABLE lt_matpr INTO ls_matpr WITH KEY pp-matnr = <fs_one_curr>-matnr
                                                     pp-bwkey = <fs_one_curr>-bwkey
                                                     pp-bwtar = <fs_one_curr>-bwtar
                                                     pp-vbeln = <fs_one_curr>-vbeln
                                                     pp-posnr = <fs_one_curr>-posnr
                                                     pp-pspnr = <fs_one_curr>-pspnr.
          IF sy-subrc <> 0.
            MOVE-CORRESPONDING <fs_one_curr> TO ls_matpr-pp.
            ls_matpr-pp-poper = lv_poper.      "期间
            ls_matpr-pp-bdatj = lv_bdatj.     "年度
            CLEAR lv_index.
            REFRESH ls_matpr-cr.
          ELSE.
            lv_index = sy-tabix.
          ENDIF.
          MOVE-CORRESPONDING <fs_one_curr> TO ls_matcr.
          ls_matcr-zuumb = - ls_matcr-zuumb.              "标准执行金额反转
          IF <fs_one_curr>-vprsv = 'V'.
            ls_matcr-newpvprs = <fs_one_curr>-newvalpr.
            ls_matcr-pvprs    = <fs_one_curr>-valpr.
          ELSE.
            ls_matcr-newstprs = <fs_one_curr>-newvalpr.
            ls_matcr-stprs    = <fs_one_curr>-valpr.
          ENDIF.
    
          APPEND ls_matcr TO ls_matpr-cr.
          IF lv_index IS INITIAL.
            APPEND ls_matpr TO lt_matpr.
          ELSE.
            MODIFY lt_matpr FROM ls_matpr INDEX lv_index.
          ENDIF.
        ENDLOOP.
      ENDLOOP.
    
      "init log
      CALL FUNCTION 'CM_F_INITIALIZE'
        EXPORTING
          refresh_old_log = abap_true.
    
      "Refresh Code
      CALL FUNCTION 'CKML_BUFFER_REFRESH_ALL'
        EXPORTING
          i_called_by = 'MR22  '.
    
      "reson Code
      CALL FUNCTION 'CKML_SET_REASON_CODE_MR22'
        EXPORTING
          iv_origin_group = lv_hrkft
          iv_reason_code  = iv_kongr
          iv_kdm_flag     = ''.
    
    * Sofern variable KOMOK vorgesehen, wird der KOMOK an Prices_Change
    * mitgegeben. Ansonsten herkömmlicher Aufruf.
      IF ls_ckmlkon IS NOT INITIAL.
        ls_komok = VALUE #( my_bustw = '' komok_bestd = '' komok_prdif = ls_ckmlkon-komok komok_umdif = ls_ckmlkon-komok ).
        CALL FUNCTION 'CKML_SET_REASON_CODE_MR22'
          EXPORTING
            iv_origin_group = ls_ckmlkon-hrkft
            iv_reason_code  = ls_ckmlkon-kongr
            iv_kdm_flag     = ls_ckmlkon-flg_kdm.
      ENDIF.
    
      "Change
      CALL FUNCTION 'PRICES_CHANGE'
        EXPORTING
          actual_bdatj         = lv_bdatj
          actual_poper         = lv_poper
          bukrs                = iv_bukrs
          budat                = iv_budat
          xblnr                = ''         "参考
          account_modification = ls_komok
          acc_principle        = ''
          subs_dbt             = 'X'
          flg_kdm              = '' "note 2741604
          flg_ein              = '' "note 2741604
        TABLES
          t_matpr              = lt_matpr.
    
      CALL FUNCTION 'CM_F_INFO'
        IMPORTING
          e_msg_counter_pro = lv_num_msg.
    
      IF lv_num_msg > 0.
        ROLLBACK WORK.
        CALL FUNCTION 'CM_F_MESSAGES_GET'
          TABLES
            e_msgprot = lt_msg.
    
        es_output-zpost_type = 'E'.
        LOOP AT lt_msg INTO ls_msg.
          CALL FUNCTION 'MESSAGE_TEXT_BUILD'
            EXPORTING
              msgid               = ls_msg-arbgb
              msgnr               = ls_msg-msgnr
              msgv1               = ls_msg-msgv1
              msgv2               = ls_msg-msgv2
              msgv3               = ls_msg-msgv3
              msgv4               = ls_msg-msgv4
            IMPORTING
              message_text_output = lv_msgtext.
          IF es_output-zpost_message IS INITIAL.
            es_output-zpost_message =  ls_msg-arbgb && ls_msg-msgnr && ':' && lv_msgtext.
          ELSE.
            es_output-zpost_message = es_output-zpost_message && '##' && ls_msg-arbgb && ls_msg-msgnr && ':' && lv_msgtext.
          ENDIF.
          CLEAR:lv_msgtext.
        ENDLOOP.
    
      ELSE.
        IF ls_ckmlkon IS NOT INITIAL.
          IF ls_ckmlkon-acc_principle IS NOT INITIAL.
            CALL FUNCTION 'FCML0_GET_RUNREF_FROM_ACC_PRIN'
              EXPORTING
                i_acc_principle = ls_ckmlkon-acc_principle
                i_bukrs         = iv_bukrs
              IMPORTING
                e_runref        = lv_runref.
          ENDIF.
    
          CALL FUNCTION 'PRICES_POST'
            EXPORTING
              i_bktxt         = iv_bktxt
              bukrs           = iv_bukrs
              subs_dbt        = 'X'
              lis_update      = 'X'
              i_kongr         = iv_kongr
              i_acc_principle = ls_ckmlkon-acc_principle
              i_runref        = lv_runref
            TABLES
              t_matpr         = lt_matpr.
        ELSE.
          CALL FUNCTION 'PRICES_POST'
            EXPORTING
              i_bktxt    = iv_bktxt
              bukrs      = iv_bukrs
              subs_dbt   = 'X'
              lis_update = 'X'
            TABLES
              t_matpr    = lt_matpr.
        ENDIF.
    
    
        CALL FUNCTION 'CM_F_INFO'
          IMPORTING
            e_msg_counter_pro = lv_num_msg.
    
        IF lv_num_msg > 0.
          ROLLBACK WORK.
          CALL FUNCTION 'CM_F_MESSAGES_GET'
            TABLES
              e_msgprot = lt_msg.
    
          es_output-zpost_type = 'E'.
          LOOP AT lt_msg INTO ls_msg.
            CALL FUNCTION 'MESSAGE_TEXT_BUILD'
              EXPORTING
                msgid               = ls_msg-arbgb
                msgnr               = ls_msg-msgnr
                msgv1               = ls_msg-msgv1
                msgv2               = ls_msg-msgv2
                msgv3               = ls_msg-msgv3
                msgv4               = ls_msg-msgv4
              IMPORTING
                message_text_output = lv_msgtext.
            IF es_output-zpost_message IS INITIAL.
              es_output-zpost_message =  ls_msg-arbgb && ls_msg-msgnr && ':' && lv_msgtext.
            ELSE.
              es_output-zpost_message = es_output-zpost_message && '##' && ls_msg-arbgb && ls_msg-msgnr && ':' && lv_msgtext.
            ENDIF.
            CLEAR:lv_msgtext.
          ENDLOOP.
        ELSE.
          COMMIT WORK.
          CALL FUNCTION 'CM_F_MESSAGES_GET'
            TABLES
              e_msgprot = lt_msg.
    
          READ TABLE lt_msg INTO ls_msg INDEX 1.
          es_output-zmr22_doc = ls_msg-msgv1.
          es_output-zpost_type = 'S'.
          "同时输出凭证编号到EV_BELNR
          CONDENSE es_output-zmr22_doc NO-GAPS.
          ev_belnr = es_output-zmr22_doc.
          es_output-zpost_type = 'S'.
          es_output-zpost_message = 'MR22汇差凭证创建成功!'.
        ENDIF.
      ENDIF.
    ENDFUNCTION.
    

2. MR22 数据表结构

2
9

3. MR22过账数据生成逻辑

  • 代码:
    FUNCTION z_fi_invoice_post_exchange.
    *"----------------------------------------------------------------------
    *"*"本地接口:
    *"  IMPORTING
    *"     REFERENCE(IS_INPUT) TYPE  ZSIF_FI_I003_REQ_0003 OPTIONAL
    *"  EXPORTING
    *"     REFERENCE(ES_OUTPUT) TYPE  ZSIF_FI_I003_RES_0003
    *"  RAISING
    *"      CX_INVALID_DATE
    *"----------------------------------------------------------------------
    
      DATA: lv_material            TYPE bapi_matval_key-material,
            lv_valuationarea       TYPE bapi_matval_key-val_area,
            lv_valuationtype       TYPE bapi_matval_key-val_type,
            lv_wbselement          TYPE bapi_matval_key-wbs_element,
            lv_pricedate           TYPE bapi_matval_pricedate,
            lv_pricechangedocument TYPE bapi_pricechange_document.
    
      DATA: lt_prices TYPE STANDARD TABLE OF bapi_matval_prices,
            lt_return TYPE STANDARD TABLE OF bapiret2.
    
      DATA: lv_bukrs TYPE bukrs,
            lv_budat TYPE budat,
            lv_bktxt TYPE bktxt,
            lv_bdatj TYPE bdatj,
            lv_poper TYPE poper.
    
      DATA: lt_allcurr    TYPE ztfi_mr22_allcurr,
            ls_mr22_input TYPE cki_mr22_input,
            ls_allcurr    TYPE zsfi_mr22_allcurr.
    
      DATA: lt_ckmpr_mat_price TYPE ckmpr_mat_price,
            ls_ckmpr_mat_price LIKE LINE OF lt_ckmpr_mat_price,
            ls_price_prop_ctrl TYPE price_prop_ctrl,
            ls_ckmpr_pae_cr    TYPE cki_pae_cr.
    
      DATA: lv_tabix    LIKE sy-tabix,
            lv_valuated TYPE xfeld.
    
      DATA: lv_zuumb TYPE ckmpc_zuumb,
            lv_menge TYPE ckmpc_menge,
            lv_matnr TYPE string.
    
      DATA: lo_invalid_date TYPE REF TO cx_invalid_date.
    
      DATA: ls_t001k TYPE t001k.
    
      lv_bukrs = is_input-header-company_code.
      TRY.
          lv_budat = zcl_abap_comm=>convert_date_to_internal( is_input-header-invoice_date ).
        CATCH cx_invalid_date INTO lo_invalid_date.
          es_output-zpost_type = 'E'.
          es_output-zpost_message = lo_invalid_date->get_text( ).
          RETURN.
      ENDTRY.
      lv_bktxt = is_input-header-source_num.
    
      "年度期间
      lv_bdatj = lv_budat+0(4).
      lv_poper = lv_budat+4(2).
    
      lt_allcurr = VALUE #( ( icurtp = '10' )     "公司层级
                            ( icurtp = '31' ) ).  "集团层级
    
      IF gt_ekpo[] IS INITIAL.
        es_output-zpost_type = 'E'.
        es_output-zpost_message = TEXT-t08.
        RETURN.
      ENDIF.
    
      LOOP AT gt_ekpo ASSIGNING FIELD-SYMBOL(<fs_wa>) GROUP BY ( key1 = <fs_wa>-matnr key2 = <fs_wa>-ps_psp_pnr ) ASSIGNING FIELD-SYMBOL(<fs_group>).
        CLEAR:lv_menge,lv_zuumb,lv_matnr.
        LOOP AT GROUP <fs_group> ASSIGNING FIELD-SYMBOL(<fs_ekpo>).
    
          "汇总汇差金额和数量
          lv_matnr = |{ <fs_ekpo>-matnr ALPHA = OUT }|.
          CONDENSE lv_matnr NO-GAPS.
    
          LOOP AT is_input-invoice_lines ASSIGNING FIELD-SYMBOL(<fs_invoice_line>) WHERE attribute18 = <fs_ekpo>-zorder_p2p_po
                                                                                    AND attribute3 = <fs_ekpo>-zp2pline_no_po
                                                                                    AND attribute19 = lv_matnr AND exchange_amount NE 0.
            lv_zuumb = lv_zuumb + <fs_invoice_line>-exchange_amount.
            lv_menge = lv_menge + <fs_invoice_line>-invoice_count.
          ENDLOOP.
        ENDLOOP.
    
        "检查是否开启物料分类账
        SELECT COUNT(*)
          FROM ckmlv
          WHERE bwkey = <fs_ekpo>-werks
          AND mlbwi = 'X'.
        IF sy-subrc EQ 0.
          "检查是否开启物料价值更新
          SELECT wertu
            FROM mara AS a
            LEFT JOIN t134m AS b ON b~bwkey = @<fs_ekpo>-werks AND b~mtart = a~mtart
            INTO @lv_valuated
            WHERE a~matnr = @<fs_ekpo>-matnr
            AND b~wertu = 'X'.
          ENDSELECT.
          IF lv_valuated = 'X'.
            "BY Group Process
            "Propose Data
            CLEAR: lt_ckmpr_mat_price,ls_ckmpr_mat_price.
            APPEND VALUE #( pp-matnr = <fs_ekpo>-matnr
                            pp-bwkey = <fs_ekpo>-werks
                            pp-pspnr = <fs_ekpo>-ps_psp_pnr ) TO lt_ckmpr_mat_price.
    
            CALL FUNCTION 'PRICES_PROPOSE'
              EXPORTING
                actual_bdatj      = lv_bdatj
                actual_poper      = lv_poper
                bukrs             = lv_bukrs
                subs_dbt          = 'X'
                s_price_prop_ctrl = ls_price_prop_ctrl
                i_acc_principle   = ''
              TABLES
                t_matpr           = lt_ckmpr_mat_price
              EXCEPTIONS
                data_error        = 1
                OTHERS            = 2.
            IF sy-subrc <> 0.
              es_output-zpost_type = 'E'.
              es_output-zpost_message = |读取物料 { <fs_ekpo>-matnr } 时出错!|.
              RETURN.
            ENDIF.
    
            READ TABLE lt_ckmpr_mat_price INTO ls_ckmpr_mat_price  INDEX 1.
    * material data
            LOOP AT ls_ckmpr_mat_price-cr INTO ls_ckmpr_pae_cr.
              MOVE-CORRESPONDING ls_ckmpr_pae_cr TO ls_mr22_input.
    
              "store entries
              IF ls_ckmpr_mat_price-pp-vprsv = 'V'.
                ls_mr22_input-valpr    = ls_ckmpr_pae_cr-pvprs.
                ls_mr22_input-newvalpr = ls_ckmpr_pae_cr-pvprs.
                ls_mr22_input-pstxt    = '移动平均价'.
                ls_mr22_input-vprsv = 'V'.
              ELSE.
                ls_mr22_input-valpr    = ls_ckmpr_pae_cr-stprs.
                ls_mr22_input-newvalpr = ls_ckmpr_pae_cr-stprs.
                ls_mr22_input-pstxt    = '标准价格'.
                ls_mr22_input-vprsv = 'S'.
              ENDIF.
    
              ls_mr22_input-matnr = <fs_ekpo>-matnr.
              ls_mr22_input-pspnr = <fs_ekpo>-ps_psp_pnr.
              ls_mr22_input-bwkey = <fs_ekpo>-werks.
              ls_mr22_input-zuumb = lv_zuumb.
              MOVE-CORRESPONDING ls_ckmpr_mat_price-pp TO ls_mr22_input.
              ls_mr22_input-meins = <fs_ekpo>-meins.
              ls_mr22_input-menge = lv_menge.
    
    *  Change input table t_allcurr
              READ TABLE lt_allcurr INTO ls_allcurr WITH KEY icurtp = ls_mr22_input-curtp.
              lv_tabix = sy-tabix.
              APPEND ls_mr22_input TO ls_allcurr-one_curr.
              MODIFY lt_allcurr FROM ls_allcurr INDEX lv_tabix.
              CLEAR: ls_mr22_input.
            ENDLOOP.
          ENDIF.
        ENDIF.
      ENDLOOP.
    
      CALL FUNCTION 'Z_FI_MATVAL_MR22'
        EXPORTING
          iv_kongr   = 'HL1'
          iv_bukrs   = lv_bukrs
          iv_budat   = lv_budat
          iv_bktxt   = lv_bktxt
        IMPORTING
          es_output  = es_output
    *     ev_belnr   = lv_belnr
        TABLES
          it_allcurr = lt_allcurr.
    
    ENDFUNCTION.
    

4. 接口Z_FI_MATVAL_MR21

  • 代码:
    FUNCTION z_fi_matval_mr21.
    *"----------------------------------------------------------------------
    *"*"本地接口:
    *"  IMPORTING
    *"     REFERENCE(IV_BUKRS) TYPE  BUKRS
    *"     REFERENCE(IV_BUDAT) TYPE  BUDAT
    *"     REFERENCE(IV_BKTXT) TYPE  BKTXT
    *"  EXPORTING
    *"     REFERENCE(EV_BELNR) TYPE  BELNR_D
    *"  TABLES
    *"      IT_ALLCURR TYPE  ZTFI_MR21_ALLCURR
    *"      IT_MSGPROT STRUCTURE  CMFMSG
    *"----------------------------------------------------------------------
    
      "Data Define
      TYPES: BEGIN OF ty_ckmpr_f_mat_price,
               pp         LIKE cki_pae_pp,
               cr         TYPE ckmpr_curtp_prices,
               ckmlpr     TYPE t_ckmlpr,
               keko       TYPE t_keko,
               prkeph_old TYPE mlccs_t_prkeph,
               prkeph_new TYPE mlccs_t_prkeph,
               prkeko_old TYPE mlccs_t_prkeko,
               prkeko_new TYPE mlccs_t_prkeko,
               keph_delta TYPE mlccs_t_keph,
               delta_ccs  TYPE c,  "Indicator that a non-zero delta CCS is available
               duv_prctr  TYPE prctr,
               duv_2prod  TYPE c,
               duv_index  TYPE i,                               " 2845514
             END OF ty_ckmpr_f_mat_price.
    
      DATA: lt_matpr TYPE TABLE OF ty_ckmpr_f_mat_price,
            ls_matpr TYPE ty_ckmpr_f_mat_price,
            ls_matcr TYPE cki_pae_cr.
    
      DATA: ls_komok TYPE ckmpr_f_account_det.
    
      DATA: lv_index   LIKE sy-tabix,
            lv_num_msg TYPE i,
            ls_msg     TYPE cmfmsg.
    
      DATA: lv_bdatj TYPE bdatj,
            lv_poper TYPE poper.
    
      DATA: lt_ckmpr_mat_price    TYPE ckmpr_mat_price,
            ls_ckmpr_mat_price    LIKE LINE OF lt_ckmpr_mat_price,
            ls_price_prop_ctrl    TYPE price_prop_ctrl,
            ls_ckmpr_curtp_prices TYPE cki_pae_cr.
    
      DATA: lv_msgtext TYPE string,
            ls_ckmlkon TYPE ckmlkon.
    
      "取科目修改配置
      SELECT SINGLE * FROM ckmlkon INTO ls_ckmlkon WHERE tcode = 'MR21' AND flg_def = abap_true.
    
      "年度期间
      lv_bdatj = iv_budat+0(4).
      lv_poper = iv_budat+4(2).
    
      "输入值转换到BAPi参数
      LOOP AT it_allcurr[] ASSIGNING FIELD-SYMBOL(<fs_allcurr>).
        LOOP AT <fs_allcurr>-one_curr ASSIGNING FIELD-SYMBOL(<fs_one_curr>).
          READ TABLE lt_matpr INTO ls_matpr WITH KEY pp-matnr = <fs_one_curr>-matnr
                                                     pp-bwkey = <fs_one_curr>-bwkey
                                                     pp-bwtar = <fs_one_curr>-bwtar
                                                     pp-vbeln = <fs_one_curr>-vbeln
                                                     pp-posnr = <fs_one_curr>-posnr
                                                     pp-pspnr = <fs_one_curr>-pspnr.
          IF sy-subrc <> 0.
            MOVE-CORRESPONDING <fs_one_curr> TO ls_matpr-pp.
            ls_matpr-pp-poper = lv_poper.      "期间
            ls_matpr-pp-bdatj = lv_bdatj.     "年度
            CLEAR lv_index.
            REFRESH ls_matpr-cr.
          ELSE.
            lv_index = sy-tabix.
          ENDIF.
          MOVE-CORRESPONDING <fs_one_curr> TO ls_matcr.
          IF <fs_one_curr>-vprsv = 'V'.
            ls_matcr-newpvprs = <fs_one_curr>-newvalpr.
            ls_matcr-stprs = <fs_one_curr>-stapr.
            ls_matcr-newpvprs = <fs_one_curr>-newvalpr.
            ls_matcr-pvprs    = <fs_one_curr>-valpr.
          ELSE.
            ls_matcr-newstprs = <fs_one_curr>-newvalpr.
            ls_matcr-stprs = <fs_one_curr>-valpr.
            ls_matcr-newpvprs = <fs_one_curr>-newstapr.
            ls_matcr-pvprs    = <fs_one_curr>-stapr.
          ENDIF.
    
          APPEND ls_matcr TO ls_matpr-cr.
          IF lv_index IS INITIAL.
            APPEND ls_matpr TO lt_matpr.
          ELSE.
            MODIFY lt_matpr FROM ls_matpr INDEX lv_index.
          ENDIF.
        ENDLOOP.
      ENDLOOP.
    
    * Anreichern der LT_MATPR mit den zukünftigen Preis und
    * Kalkulationsdaten, falls Plankalkulationen existieren
      PERFORM kalk_enrich CHANGING
                lt_matpr.
    
      "init log
      CALL FUNCTION 'CM_F_INITIALIZE'
        EXPORTING
          refresh_old_log = abap_true.
    
      "Refresh Code
      CALL FUNCTION 'CKML_BUFFER_REFRESH_ALL'
        EXPORTING
          i_called_by = 'MR21  '.
    
    * Falls Customizing für variable KOMOKs gepflegt, wird hier der KOMOK
    * bestimmt und an Prices Change übergeben.
      IF ls_ckmlkon IS NOT INITIAL.
        ls_komok = VALUE #( komok_umdif = ls_ckmlkon-komok ).
      ENDIF.
    
      "Change
      CALL FUNCTION 'PRICES_CHANGE'
        EXPORTING
          actual_bdatj         = lv_bdatj
          actual_poper         = lv_poper
          bukrs                = iv_bukrs
          budat                = iv_budat
          xblnr                = ''         "参考
          account_modification = ls_komok
        TABLES
          t_matpr              = lt_matpr.
    
      CALL FUNCTION 'CM_F_INFO'
        IMPORTING
          e_msg_counter_pro = lv_num_msg.
    
      IF lv_num_msg > 0.
        ROLLBACK WORK.
        CALL FUNCTION 'CM_F_MESSAGES_GET'
          TABLES
            e_msgprot = it_msgprot[].
      ELSE.
        CALL FUNCTION 'PRICES_POST'
          EXPORTING
            i_bktxt    = iv_bktxt
            bukrs      = iv_bukrs
            lis_update = 'X'
            i_kongr    = ls_ckmlkon-kongr
          TABLES
            t_matpr    = lt_matpr.
    
        CALL FUNCTION 'CM_F_INFO'
          IMPORTING
            e_msg_counter_pro = lv_num_msg.
    
        IF lv_num_msg > 0.
          ROLLBACK WORK.
          CALL FUNCTION 'CM_F_MESSAGES_GET'
            TABLES
              e_msgprot = it_msgprot[].
        ELSE.
          COMMIT WORK.
          CALL FUNCTION 'CM_F_MESSAGES_GET'
            TABLES
              e_msgprot = it_msgprot[].
    
          READ TABLE it_msgprot[] INTO ls_msg INDEX 1.
          "输出凭证编号到EV_BELNR
          CONDENSE ls_msg-msgv1 NO-GAPS.
          ev_belnr = ls_msg-msgv1.
        ENDIF.
      ENDIF.
    ENDFUNCTION.
    

5. MR21 数据表结构

8
10

6. MR21 全局变量&子程序

  • TOP
    * Datentyp für CKMLPR
    TYPES:
      BEGIN OF ty_matcb,
        kalnr  LIKE mbew-kaln1,
        ckmlpr TYPE t_ckmlpr,
      END OF ty_matcb,
      ty_matcb_tbl TYPE SORTED TABLE OF ty_matcb
                    WITH UNIQUE KEY
                    kalnr.
    
    * Kontrollblock-Tabellle
    DATA:
      gd_matcb_tbl  TYPE ty_matcb_tbl.
    
    * Datentyp für KEKO
    TYPES:
      BEGIN OF ty_kekocb,
        kalnr LIKE mbew-kaln1,
        keko  TYPE t_keko,
      END OF ty_kekocb,
      ty_kekocb_tbl TYPE SORTED TABLE OF ty_kekocb
                    WITH UNIQUE KEY
                    kalnr.
    
    * Kontrollblock-Tabellle
    DATA:
      gd_kekocb_tbl  TYPE ty_kekocb_tbl.
    
  • INCLUDE
    *&---------------------------------------------------------------------*
    *&      Form  kalk_enrich
    *&---------------------------------------------------------------------*
    *       Die Untertabelle CKMLPR aus dem globalen Kontrollblock
    *       GD_MATCB_TBL sowie die Untertabelle KEKO aus dem globalen
    *       Kontrollbrlock GD_KEKOCB_TBL
    *       wird in die Struktur R_MATPR übertragen, falls es
    *       zu dem Material eine Plankalkulation existiert.
    *----------------------------------------------------------------------*
    *      <--> R_MATPR  Liste der Materialien
    *----------------------------------------------------------------------*
    FORM kalk_enrich CHANGING
              r_matpr   TYPE ckmpr_mat_price.
    
    * Datentyp für CKMLPR
      TYPES:
        BEGIN OF ty_matcb,
          kalnr  LIKE mbew-kaln1,
          ckmlpr TYPE t_ckmlpr,
        END OF ty_matcb.
    
    * Datentyp für KEKO
      TYPES:
        BEGIN OF ty_kekocb,
          kalnr LIKE mbew-kaln1,
          keko  TYPE t_keko,
        END OF ty_kekocb.
    
      FIELD-SYMBOLS:
        <r_matpr> LIKE LINE OF r_matpr,
        <matcr>   TYPE LINE OF ckmpr_curtp_prices,
        <pr>      TYPE ckmlpr.
    
      DATA:
        ld_costing_to_release TYPE boole_d,
        ld_wa_matcb           LIKE LINE OF gd_matcb_tbl,
        ld_wa_kekocb          LIKE LINE OF gd_kekocb_tbl.
    
      LOOP AT r_matpr ASSIGNING <r_matpr>.
    
    *   Existiert zu irgendeiner Währung eine Plankalkulation?
        CLEAR ld_costing_to_release.
        LOOP AT <r_matpr>-cr ASSIGNING <matcr>.
          IF  <matcr>-erzkalk = abap_true.
            ld_costing_to_release = abap_true.
          ENDIF.
        ENDLOOP.
        UNASSIGN <matcr>.
        CHECK NOT ld_costing_to_release IS INITIAL.
    
    *   Übertragen der Tabelle für die zukünftigen Preise
    *   aus dem globalen Kontrollblock in die T_MATPR
        READ TABLE gd_matcb_tbl INTO ld_wa_matcb
             WITH TABLE KEY kalnr = <r_matpr>-pp-kaln1.
        IF sy-subrc EQ 0.
          <r_matpr>-ckmlpr[] = ld_wa_matcb-ckmlpr[].
          LOOP AT <r_matpr>-ckmlpr ASSIGNING <pr>. " Adjust new CKMLPR to changed price unit if necessary (otherwise CKMLPR-PEINH is not set to NEWPEINH in PRICES_CHANGE)
            READ TABLE <r_matpr>-cr WITH KEY curtp = <pr>-curtp ASSIGNING <matcr>.
            CHECK <matcr>-peinh <> <matcr>-newpeinh.
            <pr>-lplpr = <pr>-lplpr * <matcr>-newpeinh / <matcr>-peinh.
            <pr>-lplpx = <pr>-lplpx * <matcr>-newpeinh / <matcr>-peinh.
            <pr>-vplpr = <pr>-vplpr * <matcr>-newpeinh / <matcr>-peinh.
            <pr>-vplpx = <pr>-vplpx * <matcr>-newpeinh / <matcr>-peinh.
            <pr>-eiprice = <pr>-eiprice * <matcr>-newpeinh / <matcr>-peinh.
            <pr>-peinh = <matcr>-newpeinh.
          ENDLOOP.
        ENDIF.
    *   Übertragen der Tabelle für die Kalkulationsdaten
    *   aus dem globalen Kontrollblock in die T_MATPR
        READ TABLE gd_kekocb_tbl INTO ld_wa_kekocb
             WITH TABLE KEY kalnr = <r_matpr>-pp-kaln1.
        IF sy-subrc EQ 0.
          <r_matpr>-keko[] = ld_wa_kekocb-keko[].
        ENDIF.
      ENDLOOP.
      UNASSIGN <r_matpr>.
    
    ENDFORM.                    " kalk_enrich
    
    *&---------------------------------------------------------------------*
    *&      Form  gd_cb_tbl_insert
    *&---------------------------------------------------------------------*
    *       Die CKMLPR-Daten zu einem Material werden in die globale
    *       Kontrollblockstruktur eingefuegt
    *       Die KEKO-Daten zu einem Material werden in die globale
    *       Kontrollblockstruktur eingefuegt
    *----------------------------------------------------------------------*
    *      -->P_F_MATPR  text
    *----------------------------------------------------------------------*
    FORM gd_cb_tbl_insert USING
              r_matpr   TYPE ckmpr_f_mat_price.
    
      DATA:
        ld_wa_matcb  LIKE LINE OF gd_matcb_tbl,
        ld_wa_kekocb LIKE LINE OF gd_kekocb_tbl.
    
      CHECK NOT r_matpr-pp-kaln1 IS INITIAL.
    * CKMLPR-Daten
      READ TABLE gd_matcb_tbl INTO ld_wa_matcb
           WITH TABLE KEY kalnr = r_matpr-pp-kaln1.
      IF sy-subrc EQ 0.
        ld_wa_matcb-ckmlpr[] = r_matpr-ckmlpr[].
        MODIFY TABLE gd_matcb_tbl FROM ld_wa_matcb.
      ELSE.
        CLEAR ld_wa_matcb.
        ld_wa_matcb-kalnr = r_matpr-pp-kaln1.
        ld_wa_matcb-ckmlpr[] = r_matpr-ckmlpr[].
        INSERT ld_wa_matcb INTO TABLE gd_matcb_tbl.
      ENDIF.
    * CKMLPR-Daten
      READ TABLE gd_kekocb_tbl INTO ld_wa_kekocb
           WITH TABLE KEY kalnr = r_matpr-pp-kaln1.
      IF sy-subrc EQ 0.
        ld_wa_kekocb-keko[] = r_matpr-keko[].
        MODIFY TABLE gd_kekocb_tbl FROM ld_wa_kekocb.
      ELSE.
        CLEAR ld_wa_kekocb.
        ld_wa_kekocb-kalnr = r_matpr-pp-kaln1.
        ld_wa_kekocb-keko[] = r_matpr-keko[].
        INSERT ld_wa_kekocb INTO TABLE gd_kekocb_tbl.
      ENDIF.
    
    ENDFORM.                    " gd_cb_tbl_insert
    

7. MR21过账数据生成逻辑

  • 代码
    FUNCTION z_mm_material_price_change.
    *"----------------------------------------------------------------------
    *"*"本地接口:
    *"  IMPORTING
    *"     REFERENCE(IV_BUKRS) TYPE  BUKRS
    *"     REFERENCE(IV_BUDAT) TYPE  BUDAT
    *"     REFERENCE(IV_BKTXT) TYPE  BKTXT
    *"  EXPORTING
    *"     REFERENCE(EV_BELNR) TYPE  BELNR_D
    *"  TABLES
    *"      IT_MSGPROT STRUCTURE  CMFMSG
    *"      IT_MR21 STRUCTURE  CKI_MR21_0250
    *"  RAISING
    *"      CX_INVALID_DATE
    *"----------------------------------------------------------------------
    
      FIELD-SYMBOLS: <fs_mr21> TYPE cki_mr21_0250.
    
      CHECK it_mr21[] IS NOT INITIAL.
    
      DATA: lv_bdatj TYPE bdatj,
            lv_poper TYPE poper.
    
      DATA: lt_allcurr TYPE ztfi_mr21_allcurr,
            ls_allcurr TYPE zsfi_mr21_allcurr.
    
      DATA: lt_ckmpr_mat_price TYPE ckmpr_mat_price,
            ls_mr21_input      TYPE cki_mr21_input,
            ls_ckmpr_mat_price LIKE LINE OF lt_ckmpr_mat_price,
            ls_ckmpr_pae_cr    TYPE cki_pae_cr.
    
      DATA: lv_valuated             TYPE xfeld,
            lv_index                TYPE sy-tabix,
            ls_t001k                TYPE t001k,
            lv_is_pure_peinh_change TYPE xfeld.
    
      "年度期间
      lv_bdatj = iv_budat+0(4).
      lv_poper = iv_budat+4(2).
    
      lt_allcurr = VALUE #( ( icurtp = '10' )     "公司层级
                            ( icurtp = '31' ) ).  "集团层级
    
      "检查物料是否重复
      DATA(lt_mr21_cache) = it_mr21[].
      SELECT SINGLE COUNT( a~matnr ) AS count
        FROM @lt_mr21_cache AS a
        GROUP BY matnr
        HAVING COUNT( a~matnr ) >= 2
        INTO @DATA(lv_count) ##ITAB_KEY_IN_SELECT ##ITAB_DB_SELECT.
      IF lv_count IS NOT INITIAL.
        APPEND VALUE #( arbgb = 'ZMM01' msgv1 = '存在重复的物料!' ) TO it_msgprot[].
        RETURN.
      ENDIF.
    
      LOOP AT it_mr21[] ASSIGNING <fs_mr21>.
        CLEAR: lv_valuated.
        "check mandatory
        IF <fs_mr21>-waers IS INITIAL.
          APPEND VALUE #( arbgb = 'ZMM01' msgv1 = 'WAERS字段必输!' ) TO it_msgprot[].
        ENDIF.
    
        IF <fs_mr21>-matnr IS INITIAL.
          APPEND VALUE #( arbgb = 'ZMM01' msgv1 = 'MATNR字段必输!' ) TO it_msgprot[].
        ENDIF.
    
        IF <fs_mr21>-bwkey IS INITIAL.
          APPEND VALUE #( arbgb = 'ZMM01' msgv1 = 'BWKEY字段必输!' ) TO it_msgprot[].
        ENDIF.
    
        IF <fs_mr21>-newvalpr IS INITIAL.
          APPEND VALUE #( arbgb = 'ZMM01' msgv1 = 'NEWVALPR字段(新价格)必输!' ) TO it_msgprot[].
        ENDIF.
    
        IF it_msgprot[] IS NOT INITIAL.
          RETURN.
        ENDIF.
    
        "检查是否开启物料分类账
        SELECT COUNT(*)
          FROM ckmlv
          WHERE bwkey = <fs_mr21>-bwkey
          AND mlbwi = 'X'.
        IF sy-subrc EQ 0.
          "检查是否开启物料价值更新
          SELECT wertu
            FROM mara AS a
            LEFT JOIN t134m AS b ON b~bwkey = @<fs_mr21>-bwkey AND b~mtart = a~mtart
            INTO @lv_valuated
            WHERE a~matnr = @<fs_mr21>-matnr
            AND b~wertu = 'X'.
          ENDSELECT.
          IF lv_valuated = 'X'.
    
            "Propose Data
            CLEAR: lt_ckmpr_mat_price,ls_ckmpr_mat_price.
            APPEND VALUE #( pp-matnr = <fs_mr21>-matnr
                            pp-bwkey = <fs_mr21>-bwkey ) TO lt_ckmpr_mat_price.
    
            CALL FUNCTION 'PRICES_PROPOSE'
              EXPORTING
                actual_bdatj = lv_bdatj
                actual_poper = lv_poper
                bukrs        = iv_bukrs
              TABLES
                t_matpr      = lt_ckmpr_mat_price
              EXCEPTIONS
                data_error   = 1
                OTHERS       = 2.
            IF sy-subrc <> 0.
              APPEND VALUE #( arbgb = 'ZBC01' msgty = 'E' msgnr = '001' msgv1 = 'PRICES_PROPOSE 异常!' ) TO it_msgprot[].
              RETURN.
            ENDIF.
    
            TRY.
                READ TABLE lt_ckmpr_mat_price INTO ls_ckmpr_mat_price  INDEX 1.
    * material data
                LOOP AT ls_ckmpr_mat_price-cr INTO ls_ckmpr_pae_cr.
                  CLEAR: lv_is_pure_peinh_change.
                  MOVE-CORRESPONDING ls_ckmpr_pae_cr TO ls_mr21_input.
    
                  IF ls_mr21_input-newpeinh NE <fs_mr21>-newpeinh.
                    IF ls_mr21_input-newvalpr NE <fs_mr21>-newvalpr.
                      ls_mr21_input-newvalpr = ls_mr21_input-newvalpr * ls_mr21_input-newpeinh
                                           / <fs_mr21>-newpeinh.
                      lv_is_pure_peinh_change = abap_true.
                    ENDIF.
                    IF ls_mr21_input-newstapr NE <fs_mr21>-newstapr.
                      ls_mr21_input-newstapr = ls_mr21_input-newstapr * ls_mr21_input-newpeinh
                                           / <fs_mr21>-newpeinh.
                      lv_is_pure_peinh_change = abap_true.
                    ENDIF.
    
                    ls_mr21_input-newpeinh = <fs_mr21>-newpeinh.
                    ls_mr21_input-manpae_v = 'X'.
                    ls_mr21_input-manpae_s = 'X'.
                    CLEAR: ls_mr21_input-zukbew, ls_mr21_input-erzkalk.
                  ENDIF.
    
                  "store entries
                  IF ls_ckmpr_mat_price-pp-vprsv = 'V'.
                    ls_mr21_input-valpr    = ls_ckmpr_pae_cr-pvprs.
                    ls_mr21_input-newvalpr = ls_ckmpr_pae_cr-pvprs.
                    ls_mr21_input-vprsv = 'V'.
                    ls_mr21_input-pstxt    = '移动平均价'.
                  ELSE.
                    ls_mr21_input-valpr    = ls_ckmpr_pae_cr-stprs.
                    ls_mr21_input-newvalpr = ls_ckmpr_pae_cr-stprs.
                    ls_mr21_input-vprsv = 'S'.
                    ls_mr21_input-pstxt    = '标准价格'.
                  ENDIF.
    
                  IF ls_mr21_input-vprsv = 'V'.
                    IF ls_mr21_input-newvalpr NE <fs_mr21>-newvalpr.
                      ls_mr21_input-newvalpr = <fs_mr21>-newvalpr.
                      ls_mr21_input-manpae_v = 'X'.
    
                      IF lv_is_pure_peinh_change = abap_false.
                        ls_mr21_input-is_no_auto_curr_conv = abap_true.
                      ENDIF.
                    ENDIF.
                    IF ls_mr21_input-newstapr NE <fs_mr21>-newstapr.
                      ls_mr21_input-newstapr = <fs_mr21>-newstapr.
                      ls_mr21_input-manpae_s = 'X'.
                      CLEAR ls_mr21_input-erzkalk.
    
                      IF lv_is_pure_peinh_change = abap_false.
                        ls_mr21_input-is_no_auto_curr_conv = abap_true.
                      ENDIF.
                    ENDIF.
                  ELSE.
                    IF ls_mr21_input-newvalpr NE <fs_mr21>-newvalpr.
                      ls_mr21_input-newvalpr = <fs_mr21>-newvalpr.
                      ls_mr21_input-manpae_s = 'X'.
                      CLEAR: ls_mr21_input-zukbew, ls_mr21_input-erzkalk.
    
                      IF lv_is_pure_peinh_change = abap_false.
                        ls_mr21_input-is_no_auto_curr_conv = abap_true.
                      ENDIF.
                    ENDIF.
                    IF ls_mr21_input-newstapr NE <fs_mr21>-newstapr
                    AND cl_fins_ml_customizing_util=>statistical_map_is_obsolete( ) = abap_false.
                      ls_mr21_input-newstapr = <fs_mr21>-newstapr.
                      ls_mr21_input-manpae_v = 'X'.
    
                      IF lv_is_pure_peinh_change = abap_false.
                        ls_mr21_input-is_no_auto_curr_conv = abap_true.
                      ENDIF.
                    ENDIF.
                  ENDIF.
    
                  MOVE-CORRESPONDING ls_ckmpr_mat_price-pp TO ls_mr21_input.
    
    *  Change input table t_allcurr
                  READ TABLE lt_allcurr INTO ls_allcurr WITH KEY icurtp = ls_mr21_input-curtp.
                  lv_index = sy-tabix.
                  APPEND ls_mr21_input TO ls_allcurr-one_curr.
                  MODIFY lt_allcurr FROM ls_allcurr INDEX lv_index.
                  CLEAR: ls_mr21_input.
                ENDLOOP.
              CATCH cx_sy_arithmetic_overflow.
                MESSAGE w071(ckprch).
            ENDTRY.
    
            READ TABLE lt_ckmpr_mat_price INTO ls_ckmpr_mat_price  INDEX 1.
    * Übergeben der Materialinfo in die Kontrollblock-Tabellen
            PERFORM gd_cb_tbl_insert USING ls_ckmpr_mat_price.
    
          ENDIF.
        ENDIF.
      ENDLOOP.
    
    
      CALL FUNCTION 'Z_FI_MATVAL_MR21'
        EXPORTING
          iv_bukrs   = iv_bukrs
          iv_budat   = iv_budat
          iv_bktxt   = iv_bktxt
        IMPORTING
          ev_belnr   = ev_belnr
        TABLES
          it_allcurr = lt_allcurr
          it_msgprot = it_msgprot[].
    
    ENDFUNCTION.
    
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值