SAP_ABAP_接口技术_RFC远程函数实践总结

SAP ABAP顾问能力模型梳理_企业数字化建设者的博客-CSDN博客SAP Abap顾问能力模型,ALV/REPORT|SMARTFROM|SCREEN|OLE|BAPI|BDC|PI|IDOC|RFC|API|WEBSERVICE|Enhancement|UserExits|Badi|Debughttps://blog.csdn.net/java_zhong1990/article/details/132469977一、实现步骤

1.1 SE37-->创建函数-->创建输入输出参数-->编写代码

1.2 启用远程的函数模块

SAP_ABAP_接口技术_RFC远程函数实践总结_第1张图片

1.3 代码样例

FUNCTION zfm_mm_140.
*"----------------------------------------------------------------------
*"*"本地接口:
*"  IMPORTING
*"     VALUE(IH) TYPE  ZSMM140HEADER
*"  EXPORTING
*"     VALUE(STATUS) TYPE  CHAR2
*"     VALUE(MESSAGE) TYPE  CHAR255
*"  TABLES
*"      ITAB STRUCTURE  ZSMM140ITEM
*"----------------------------------------------------------------------
*程序名:
*程序描述:MM-140_采购订单收货退货接口
*----------------------------------------------------------------------
*创建日期        ABAP开发顾问    业务顾问
*2019.09.17.             

  zlog_save1 'ZFM_MM_330'.
  zlog_save2 'B'.
*-----------------------------------------------------------------------

  DATA ls_gh TYPE bapi2017_gm_head_01.
  DATA ls_gi TYPE bapi2017_gm_item_create.
  DATA lt_gi TYPE TABLE OF bapi2017_gm_item_create.

  DATA ls_poitem TYPE bapimepoitem.
  DATA lt_poitem TYPE TABLE OF bapimepoitem.
  DATA ls_poitemx TYPE bapimepoitemx.
  DATA lt_poitemx TYPE TABLE OF bapimepoitemx.
  DATA ls_return TYPE bapiret2.
  DATA lt_return TYPE TABLE OF bapiret2.

  DATA gr_ebeln TYPE RANGE OF ekpo-ebeln. "采购订单号
  DATA gw_ebeln LIKE LINE OF gr_ebeln.

  DATA lv_message_str(255) TYPE c.

  IF itab[] IS NOT INITIAL.

    "1.==========为检查逻辑所需要准备的数据源

    CLEAR itab.
    LOOP AT itab[] INTO itab.
      gw_ebeln-sign = 'I'.
      gw_ebeln-option = 'EQ'.
      gw_ebeln-low = itab-po_number.
      gw_ebeln-high = ''.
      APPEND gw_ebeln TO gr_ebeln.
    ENDLOOP.
    DELETE ADJACENT DUPLICATES FROM gr_ebeln COMPARING low.

    SELECT ekpo~ebeln,"采购订单号
           ekpo~ebelp,"项次
           ekpo~retpo,"采购退货订单标识 X:采购退货订单
           ekpo~werks "工厂
       FROM ekpo
       WHERE ekpo~ebeln IN @gr_ebeln
      INTO TABLE @DATA(lt_ekpo).

    "查找未打删除标识的来料单号
    SELECT
      ztmm_incom_list~incom,   "来料单号
      ztmm_incom_list~item,   "来料单项次
      ztmm_incom_list~ebeln,  "采购凭证
      ztmm_incom_list~ebelp,   "项目
      ztmm_incom_list~loekz
      FROM ztmm_incom_list WHERE ztmm_incom_list~loekz IS INITIAL AND ztmm_incom_list~incom = @ih-incom
      INTO TABLE @DATA(lt_incom_list).

    "取工厂和库存地点
    SELECT
      t001l~werks,
      t001l~lgort
      FROM t001l
       INTO TABLE @DATA(lt_t001l).

    "取物料过账日志表
    SELECT
      ztmm_140~incom,
      ztmm_140~item,
      ztmm_140~mblnr "物料凭证编号
      FROM ztmm_140 WHERE ztmm_140~incom = @ih-incom
      INTO TABLE @DATA(lt_ztmm_140).

    "2.==========接口传入参数进行检查

    LOOP AT itab[]  ASSIGNING FIELD-SYMBOL().
      "  传入的采购订单及项次若为空,则返回错消息“采购订单、项次不能为空”;
      IF -po_number IS INITIAL OR -po_item IS INITIAL.
        -type = 'E'.
        -message = '采购订单、项次不能为空'.
        CONTINUE.
      ENDIF.

      "根据传入采购订单及项次取退货标识(EKPO-RETPO),EKPO-RETPO =‘X’为退货采购订单;若采购订单及项次不是退货采购订单,
      "则传入的来料单(INCOM)及来料单项次ITEM不为空,否则提示“非采购退货单,来料单及项次不能为空”
      READ TABLE lt_ekpo INTO DATA(ls_ekpo) WITH KEY ebeln = -po_number ebelp = -po_item.
      IF sy-subrc = 0.
        IF ls_ekpo-retpo = 'X'.
          "EKPO-RETPO =‘X’退货采购订单
          -retpo = 'X'.
          "根据传入的的采购订单及项次从EKPO取RETPO,若RETPO = ‘X’,则给161;其他情况给101
          -move_type = '161'."移动类型
        ELSE.
          "采购订单
          -move_type = '101'."移动类型
          "若采购订单及项次不是退货采购订单,"则传入的来料单(INCOM)及来料单项次ITEM不为空,否则提示“非采购退货单,来料单及项次不能为空”
          IF -item IS INITIAL OR ih-incom IS INITIAL .
            -type = 'E'.
            -message = '及来料单以及项次ITEM不为空'.
            CONTINUE.
          ENDIF.
        ENDIF.
      ELSE.
        -type = 'E'.
        -message = '采购订单以及行项目不存在'.
        CONTINUE.
      ENDIF.

      "若库存地点为空,则返回错误消息“库存地点不能为空;
      IF -stge_loc IS INITIAL.
        -type = 'E'.
        -message = '库存地点不能为空'.
        CONTINUE.
      ENDIF.

      "根据传入的采购订单号及项次从EKPO取 工厂(EKPO-WERKS);根据传入的库存地点及刚取到的PO 工厂判断在table T001l 是否存在,不存在返回错误消息“库存地XXX在工厂YYY 不存”
      READ TABLE lt_ekpo INTO DATA(ls_ekpo_werks) WITH KEY ebeln = -po_number ebelp = -po_item.
      IF sy-subrc = 0.
        READ TABLE lt_t001l INTO DATA(ls_t001l) WITH KEY werks = ls_ekpo_werks-werks lgort = -stge_loc.
        IF sy-subrc <> 0.
          -type = 'E'.
          -message = '库存地'&& -stge_loc &&'在工厂'&& ls_ekpo_werks-werks &&'不存'.
          CONTINUE.
        ENDIF.
      ELSE.
        -type = 'E'.
        -message = '传入的采购订单和项次在采购订单表 ekpo中,不存在'.
        CONTINUE.
      ENDIF.

      "若未税价格(NETPR)为空或价格基数PEINH为空或购买税代码(MWSKZ)空,则返回错误消息“未税价格,价格基数及税代码都不能为空”;
      IF -netpr IS INITIAL OR -peinh IS INITIAL OR -mwskz IS INITIAL.
        -type = 'E'.
        -message = '未税价格,价格基数及税代码都不能为空'.
        CONTINUE.
      ENDIF.

      "若传入的来料单(INCOM)及来料单项次ITEM不为空,则根据来料单、项次 及ZTMM_INCOM_LIST-LOEKZ 等于空,判断来料单及项次在ztable ZTMM_INCOM_LIST 是否存在,不存在,则返回错误消息“来料单XXXXX 项次YY在SAP 不存在”
      READ TABLE lt_incom_list INTO DATA(ls_incom_list)  WITH KEY incom = ih-incom item = -item.
      IF sy-subrc <> 0.
        -type = 'E'.
        -message = '传入的来料单号已经项次在 ZTMM_INCOM_LIST表中不存在'.
        CONTINUE.

      ELSE.
        "根据传入的来料单(INCOM)及来料单项次ITEM 及ZTMM_INCOM_LIST-LOEKZ 等于空条件,
        "从table ZTMM_INCOM_LIST取采购订单号(EBELN)及项次(EBELP),如果取到的采购订单号及项次与接口传入的订单号及项次不一致,
        "则返回错误消息“来料单XXXXX 项次YY 对应的采购订单号及项次不匹配”;
        IF ls_incom_list-ebeln = -po_number AND ls_incom_list-ebelp = -po_item.
          "相等通过
        ELSE.
          "不相等
          -type = 'E'.
          -message = '来料单'&& ih-incom &&'项次' && -po_item && '对应的采购订单号及项次不匹配'.
          CONTINUE.
        ENDIF.
      ENDIF.

      "若传入的来料单(INCOM)及来料单项次ITEM不为空,根据传入的来料单(INCOM)及来料单项次和上述新建ztable Zpo_gr
      "能取到不为空的物料凭证(MBLNR),则提示“来料单XXX 项次之前已经入库”的错误消息
      READ TABLE lt_ztmm_140 INTO DATA(ls_ztmm_140) WITH KEY incom = ih-incom item = -item.
      IF sy-subrc = 0.
        IF ls_ztmm_140-mblnr IS NOT INITIAL.
          -type = 'E'.
          -message = '来料单'&& ih-incom &&'项次'&& -item &&'之前已经入库'.
          CONTINUE.
        ENDIF.
      ENDIF.
    ENDLOOP.

    "3.==========对检查通过的记录进行业务处理

    LOOP AT itab[] ASSIGNING FIELD-SYMBOL() WHERE type <> 'E' .
      IF -retpo = 'X'. "退货订单,直接过账
      ELSE. "非采购订单,更改PO价格在过账
        ls_poitem-po_item = -po_item." 行项目
        ls_poitemx-po_item = -po_item." 行项目
        ls_poitemx-po_itemx = 'X'." 行项目
        ls_poitem-net_price = -netpr ."净价
        ls_poitemx-net_price = 'X'.
        ls_poitem-price_unit = -peinh."价格单位
        ls_poitemx-price_unit = 'X'.
        ls_poitem-tax_code = -mwskz."税码
        ls_poitemx-tax_code = 'X'.
        APPEND ls_poitem TO lt_poitem.
        APPEND ls_poitemx TO lt_poitemx.

        CALL FUNCTION 'BAPI_PO_CHANGE'
          EXPORTING
            purchaseorder = -po_number
          TABLES
            return        = lt_return
            poitem        = lt_poitem
            poitemx       = lt_poitemx.
        IF sy-subrc = 0.
          READ TABLE lt_return INTO ls_return INDEX 1.
          IF sy-subrc = 0.
            -type = ls_return-type.
            -id = ls_return-id.
            -number = ls_return-number.
            -message = ls_return-message.
            -log_no = ls_return-log_no.
            -log_msg_no = ls_return-log_msg_no.
            -message_v1 = ls_return-message_v1.
            -message_v2 = ls_return-message_v2.
            -message_v3 = ls_return-message_v3.
            -message_v4 = ls_return-message_v4.
            -parameter = ls_return-parameter.
            -row = ls_return-row.
            -field = ls_return-field.
            -system = ls_return-system.
          ENDIF.
          CLEAR ls_return.
          IF lines( lt_return ) > 1.
            lv_message_str = ''.
            LOOP AT lt_return INTO ls_return.
              lv_message_str = lv_message_str && ls_return-type && ls_return-message && ','.
            ENDLOOP.
            -message = lv_message_str.
          ENDIF.
          IF -type = 'S'.
            CALL FUNCTION 'BAPI_TRANSACTION_COMMIT' "BAPI事务提交
              EXPORTING
                wait = 'X'.
          ELSE.
            CONTINUE.
          ENDIF.
           "20190927 zhongjz add : ---------------------------------------------------------------------------------------------strat
          "   根据当前记录的采购订单及行项目从EKPO取最新的价格(EKPO-NETPR)、价格基数(EKPO-PEINH)和税码(EKPO-MWSKZ),
          "只要有一个字段的值和对应传入的值不相等,则说明价格更新更新失败,继续下一条,否则继续当前采购订单收货
          SELECT ekpo~ebeln  FROM ekpo
            WHERE ekpo~ebeln =  @-po_number
            AND ekpo~ebelp = @-po_item
            AND ekpo~netpr =  @-netpr
            AND ekpo~peinh = @-peinh
            AND ekpo~mwskz = @-mwskz
            INTO TABLE @DATA(lt_ekpo_update_success).
          IF sy-subrc = 0 AND lt_ekpo_update_success IS NOT INITIAL.
            "po价格等更新检查通过
            clear lt_ekpo_update_success.
          ELSE.
            "po价格等更新检查未通过
            -type = 'E'.
            -message = '价格更新失败'.
            CONTINUE.
          ENDIF.
          "20190927 add : ---------------------------------------------------------------------------------------------end.
        ELSE.
          -type = 'E'.
          -message = '价格更新失败'.
          CLEAR ls_poitem.
          REFRESH lt_poitem.
          CLEAR ls_poitemx.
          REFRESH lt_poitemx.
          CONTINUE.
        ENDIF.
        CLEAR ls_poitem.
        REFRESH lt_poitem.
        CLEAR ls_poitemx.
        REFRESH lt_poitemx.
      ENDIF.
      "过账。
      CLEAR ls_return.
      REFRESH lt_return.
      ls_gh-pstng_date = ih-pstng_date."过帐日期
      ls_gh-doc_date = ih-doc_date."凭证日期
      ls_gh-ref_doc_no = ih-incom."参考凭证编号 -来料单号
      ls_gh-bill_of_lading = ih-bill_of_lading."收货时提单号
      ls_gh-header_txt = ih-header_txt."凭证抬头文本

      ls_gi-material_long = -material."物料编号
      ls_gi-plant = -plant."工厂
      ls_gi-stge_loc = -stge_loc."库存地点
      ls_gi-batch = -batch. "批号
      ls_gi-move_type = -move_type. "移动类型
      ls_gi-entry_qnt = -entry_qnt."以录入项单位表示的数量

      CALL FUNCTION 'CONVERSION_EXIT_CUNIT_INPUT'
        EXPORTING
          input    = -entry_uom
          language = sy-langu
        IMPORTING
          output   = -entry_uom.
      ls_gi-entry_uom = -entry_uom."条目单位

      ls_gi-po_number = -po_number. "采购订单号
      ls_gi-po_item = -po_item. "采购凭证的项目编号
      ls_gi-item_text = -item."项目文本
      ls_gi-mvt_ind = 'B'. "移动标识 fix value B 表示采购订单收货
      APPEND ls_gi TO lt_gi.
      CALL FUNCTION 'BAPI_GOODSMVT_CREATE'
        EXPORTING
          goodsmvt_header  = ls_gh
          goodsmvt_code    = '01'
        IMPORTING
          materialdocument = -materialdocument  "物料凭证编号
          matdocumentyear  = -matdocumentyear   "物料凭证年度
        TABLES
          goodsmvt_item    = lt_gi
          return           = lt_return.
      IF sy-subrc = 0.
        IF -materialdocument IS NOT INITIAL.
          -type = 'S'.
        ENDIF.
        READ TABLE lt_return INTO ls_return INDEX 1.
        IF sy-subrc = 0.
          -type = ls_return-type.
          -id = ls_return-id.
          -number = ls_return-number.
          -message = ls_return-message.
          -log_no = ls_return-log_no.
          -log_msg_no = ls_return-log_msg_no.
          -message_v1 = ls_return-message_v1.
          -message_v2 = ls_return-message_v2.
          -message_v3 = ls_return-message_v3.
          -message_v4 = ls_return-message_v4.
          -parameter = ls_return-parameter.
          -row = ls_return-row.
          -field = ls_return-field.
          -system = ls_return-system.
          CLEAR ls_return.
          IF lines( lt_return ) > 1.
            lv_message_str = ''.
            LOOP AT lt_return INTO ls_return.
              lv_message_str = lv_message_str && ls_return-type && ls_return-message && ','.
            ENDLOOP.
            -message = lv_message_str.
          ENDIF.

        ENDIF.
        IF -type = 'S'.
          CALL FUNCTION 'BAPI_TRANSACTION_COMMIT' "BAPI事务提交
            EXPORTING
              wait = 'X'.
            "20190927 zhongjz update :注释ELSE.CONTINUE. 代码如下:
*        ELSE.
*          CONTINUE.
        ENDIF.
      ELSE.
        -type = 'E'.
        -message = '过账失败'.
        CLEAR ls_gh.
        CLEAR ls_gi.
        REFRESH lt_gi.
        CLEAR ls_return.
        REFRESH lt_return.
        CONTINUE.
      ENDIF.
      CLEAR ls_gh.
      CLEAR ls_gi.
      REFRESH lt_gi.
      CLEAR ls_return.
      REFRESH lt_return.
    ENDLOOP.

    "==============4.对过账成功的记录 记录log到ztmm_140.
    DATA ls_tlog TYPE ztmm_140.
    DATA lt_tlog TYPE TABLE OF ztmm_140.
    DATA lv_date LIKE sy-datum.
    DATA lv_time LIKE sy-uzeit.
    DATA lv_tzone LIKE  tzonref-tzone.
    DATA lv_tstamp LIKE tzonref-tstamps.
    lv_date = sy-datum.
    lv_time = sy-uzeit.
    CONVERT DATE lv_date TIME lv_time INTO TIME STAMP lv_tstamp TIME ZONE lv_tzone.
    "20190927 zhongjz upate : "不仅仅是成功的记录存入log table, 所有成功或者失败的都需要存入log table"
*    LOOP AT itab ASSIGNING FIELD-SYMBOL() WHERE materialdocument IS NOT INITIAL AND type = 'S'.
    LOOP AT itab ASSIGNING FIELD-SYMBOL().
      ls_tlog-z_tiwmstamp = lv_tstamp. "时间搓
      ls_tlog-incom = ih-incom."来料单号
      ls_tlog-item = -item."项次
      ls_tlog-ebeln = -po_number."采购凭证编号
      ls_tlog-ebelp = -po_item."采购凭证的项目编号
      ls_tlog-budat = ih-pstng_date."凭证中的过账日期
      ls_tlog-bldat = ih-doc_date."凭证中的凭证日期
      ls_tlog-frbnr = ih-bill_of_lading."收货时提单号
      ls_tlog-bktxt = ih-header_txt."凭证抬头文本
      ls_tlog-werks = -plant."工厂
      ls_tlog-matnr = -material."物料编号
      ls_tlog-lgort = -stge_loc."库存地点
      ls_tlog-charg = -batch."批号
      ls_tlog-erfmg = -entry_qnt."以录入项单位表示的数量
      ls_tlog-z_erfme = -entry_uom."条目单位
      ls_tlog-netpr = -netpr."净价
      ls_tlog-mwskz = -mwskz."销售/购买税代码
      ls_tlog-peinh = -peinh."价格单位
      ls_tlog-mblnr = -materialdocument."物料凭证编号
      ls_tlog-mjahr = -matdocumentyear."物料凭证的年份
      ls_tlog-z_type = -type."单字符标记
      ls_tlog-z_wmssage = -message."Char255
      APPEND ls_tlog TO lt_tlog.
    ENDLOOP.
    MODIFY ztmm_140 FROM TABLE lt_tlog.
    CLEAR ls_tlog.
    REFRESH lt_tlog.

*    status = 'S'.
*    message = ''.

  ELSE.

    status = 'E'.
    message = '行项目不能为空!'.

  ENDIF.

*-----------------------------------------------------------------------
  zlog_save2 'R'.
ENDFUNCTION.

你可能感兴趣的:(SAP,Abap实战篇,经验分享)