使用 BAPI_GOODSMVT_CREATE 以编程方式创建纪录片批次?

Creating documentary batches programmatically with BAPI_GOODSMVT_CREATE?

问题总结

通过自定义 ABAP 代码自动处理跟单批次

我的雇主希望对来自外部供应商的某些产品执行自动跟单批处理,我正在尝试弄清楚如何通过定制和 ABAP 进行设置。

在我看来,Documentary Batches 只能通过 MIGO 使用 - 在任何情况下,我都无法找到合适的解决方案来以编程方式分配它们,以及我可以想出的任何黑客组合解决方案,似乎不够,unstable.

我有什么途径可以解决这个问题?

增强BAPI_GOODSMVT_CREATE?

我可以通过 BAPI_GOODSMVT_CREATE 之类的东西来做吗?

增强 PPPI 消息目标?

我还特别需要它通过 PPPI 进行消费消息传递,我想在标准消息目标 PI04、FM COCI_CONFIRM_MATERIAL_CONS.

之上构建

此 FM 创建了一个 Material 文档,但没有通过 BAPI_GOODSMVT_CREATE FM。

但是它确实使用 MB_CREATE_GOODS_MOVEMENT

我已经尝试过的

基于 MIGO 快照的一次性黑客解决方案

我为一个区域制作了 hack-solution,在那里我观察了 MIGO 执行了哪些 table 更新以及使用哪些数据(通过 FM 的 VB_INSERT_BATCHVB_BATCH_WHERE_USED_LIST),然后填充手动输出这些结构。

但是,提供所有需要的信息对于其他实施领域是不可行的,因为它们没有所有必要的可用值,并且它不包括可能需要其他参数的不可预见的情况。

通读 BAPI_GOODSMVT_CREATE 代码

我试过监视 BAPI_GOODSMVT_CREATE 是否执行相同的 FM,但只发现它访问 VB_BATCH_WHERE_USED_LIST

似乎可以通过控制内存 ID Documentary Batch #1Documentary Batch #2Documentary Batch #3Documentary Batch #5 来激活此功能(参见 FM VBDBDM_DATA_POST_IM) ,但这需要填写大量数据,包括名为 DOCUBATCH_SCREEN_FIELDS 的结构,这再次让人觉得这可能不是正确的方法。

无论如何,这仍然不允许我通过 tables MCHA 和 MCH1 维护批次。

基于MIGO快照的破解方案

这是我的破解解决方案的样子。同样,这不是解决问题的可行方法,因为其他实施领域没有立即可用的结果 Material 文档:

    FUNCTION zproxy_mdr_goodsreceipt.
    *"----------------------------------------------------------------------
    *"*"Local Interface:
    *"  IMPORTING
    *"     VALUE(IS_GOODSRECEIPT_HEAD) TYPE  ZPROXY_GOODSREC_HEAD
    *"     VALUE(IT_GOODSRECEIPT_ITEM) TYPE  ZPROXY_GOODSREC_ITEM_T
    *"     REFERENCE(I_CREATE_TO_FROM_REQUIREMENTS) TYPE  FLAG DEFAULT '-'
    *"  EXPORTING
    *"     REFERENCE(E_GOODSMVT_MSG_IDNO) TYPE  CHAR23
    *"     REFERENCE(E_MBLNR) TYPE  MBLNR
    *"     REFERENCE(E_TO_CREATION_SUBRC) TYPE  SY-SUBRC
    *"     REFERENCE(E_LGNUM_ERROR) TYPE  LGNUM
    *"     REFERENCE(E_TBNUM_ERROR) TYPE  TBNUM
    *"     REFERENCE(E_DOCBATCH_SUBRC) TYPE  SY-SUBRC
    *"     REFERENCE(E_DOCBATCH_MSG_IDNO) TYPE  CHAR23
    *"     REFERENCE(E_CLASSNUM) TYPE  BAPI1003_KEY-CLASSNUM
    *"     REFERENCE(E_OBJKEY) TYPE  BAPI1003_KEY-OBJECT
    *"  EXCEPTIONS
    *"      GOODSMVT_FAILED
    *"      NO_TRANSFER_REQUIREMENTS
    *"      TRANSFER_ORDER_CREATION_ERROR
    *"----------------------------------------------------------------------

      FIELD-SYMBOLS: <return>         TYPE bapiret2,
                     <goods_rec_item> TYPE zproxy_goodsrec_item,
                     <mseg>           TYPE mseg,
                     <char_char>      TYPE bapi1003_alloc_values_char,
                     <ltap_creat>     TYPE LTAP_CREAT.

      DATA: ls_header   TYPE bapi2017_gm_head_01,
            ls_code     TYPE bapi2017_gm_code,
            ls_item     TYPE bapi2017_gm_item_create,
            lt_item     TYPE STANDARD TABLE OF bapi2017_gm_item_create,
            lt_return   TYPE STANDARD TABLE OF bapiret2,
            ls_headret  TYPE bapi2017_gm_head_ret,
            l_mblnr     LIKE bapi2017_gm_head_ret-mat_doc,
            l_docubatch TYPE charg_d,
            l_subrc     TYPE sy-subrc,
            lt_mseg     TYPE STANDARD TABLE OF mseg.

      CLEAR l_subrc.


    *     ############################## Create goods movement ##############################
    *     Build structures
      MOVE-CORRESPONDING is_goodsreceipt_head TO ls_header.
      ls_code-gm_code = '01'.

      LOOP AT it_goodsreceipt_item ASSIGNING <goods_rec_item>.
        MOVE-CORRESPONDING <goods_rec_item> TO ls_item.
        APPEND ls_item TO lt_item.
      ENDLOOP.

    *     BAPI call
      CALL FUNCTION 'BAPI_GOODSMVT_CREATE'
        EXPORTING
          goodsmvt_header  = ls_header
          goodsmvt_code    = ls_code
        IMPORTING
          goodsmvt_headret = ls_headret
          materialdocument = l_mblnr
        TABLES
          goodsmvt_item    = lt_item
          return           = lt_return.
    *     Check errors
      READ TABLE lt_return ASSIGNING <return> WITH KEY type = 'E'.
      IF sy-subrc = 0.
        e_goodsmvt_msg_idno = <return>-id && <return>-number.
        ROLLBACK WORK.
        RAISE goodsmvt_failed.
      ELSE.
        e_mblnr = l_mblnr.
        COMMIT WORK AND WAIT. "Wait for TO requirements to be created
      ENDIF.

    *     Only proceede if Material Document has been successfully posted
      CHECK l_subrc = 0 AND l_mblnr IS NOT INITIAL.

    *     ############################## Update with Documentary Batch ###################################

      DATA: lt_chvw      TYPE STANDARD TABLE OF chvw,
            ls_chvw      TYPE chvw,
            lt_mch1      TYPE STANDARD TABLE OF mch1,
            ls_mch1      TYPE mch1,
            lt_mcha      TYPE STANDARD TABLE OF mcha,
            ls_mcha      TYPE mcha,
            lt_mchb      TYPE STANDARD TABLE OF mchb,
            lt_mska      TYPE STANDARD TABLE OF mska,
            lt_mspr      TYPE STANDARD TABLE OF mspr,
            lt_char_num  TYPE STANDARD TABLE OF bapi1003_alloc_values_num,
            lt_char_char TYPE STANDARD TABLE OF bapi1003_alloc_values_char,
            lt_char_curr TYPE STANDARD TABLE OF bapi1003_alloc_values_curr,
            l_objkey     TYPE bapi1003_key-object,
            l_classnum   TYPE bapi1003_key-classnum,
            l_atnam      TYPE atnam.

      REFRESH lt_chvw.

    *     Get material document items
      SELECT *
          FROM mseg
          INTO TABLE lt_mseg
          WHERE mblnr = l_mblnr.

    *     Perpare docubatch registration data
      LOOP AT it_goodsreceipt_item ASSIGNING <goods_rec_item>.
    *       Generate class num and atnam from plant
        CONCATENATE 'PI_' <goods_rec_item>-plant INTO l_classnum.
        CONCATENATE 'Z_DOC_BATCH_' <goods_rec_item>-plant INTO l_atnam.

    *       Get material docubatch usage characteristic
        REFRESH: lt_return,
                 lt_char_num,
                 lt_char_char,
                 lt_char_curr.

        l_objkey(18) = <goods_rec_item>-material.
        CALL FUNCTION 'BAPI_OBJCL_GETDETAIL'
          EXPORTING
            objectkey       = l_objkey
            objecttable     = 'MARA'
            classnum        = l_classnum
            classtype       = '001'
          TABLES
            allocvaluesnum  = lt_char_num
            allocvalueschar = lt_char_char
            allocvaluescurr = lt_char_curr
            return          = lt_return.
        LOOP AT lt_return ASSIGNING <return> WHERE type = 'E'. "Check for errors
    *         Couldn't read characteristic, assume no docubatch handling
          e_docbatch_subrc = '1'.
          e_docbatch_msg_idno = <return>-id && <return>-number.
          e_classnum = l_classnum.
          e_objkey = l_objkey.
          CONTINUE.
        ENDLOOP.

        READ TABLE lt_char_char ASSIGNING <char_char> WITH KEY charact = l_atnam.
        IF sy-subrc <> 0 OR <char_char>-value_neutral = 0.
    *         No docubatch value
          CONTINUE.
        ENDIF.



    *       Get associated material document item
        READ TABLE lt_mseg ASSIGNING <mseg>
              WITH KEY mblnr = ls_headret-mat_doc
                       mjahr = ls_headret-doc_year
                       bwart = <goods_rec_item>-move_type
                       matnr = <goods_rec_item>-material
                       werks = <goods_rec_item>-plant
                       menge = <goods_rec_item>-entry_qnt
                       meins = <goods_rec_item>-entry_uom
                       hsdat = <goods_rec_item>-prod_date
                       kzbew = <goods_rec_item>-mvt_ind
                       lgort = <goods_rec_item>-stge_loc.
        IF sy-subrc <> 0.
    *         No associated material document item
          CONTINUE.
        ENDIF.

    *       Check docubatch type
        IF <char_char>-value_neutral <> 0.
    *         Perform basic docubatch actions (MCHA and MCH1)
    *         Verify that docubatch nr is assigned
          IF <goods_rec_item>-vendrbatch IS INITIAL.
    *            !!!!!!!!!!!!! Venderbatch not filled even though material is docubatch managed, what to do? !!!!!!!!!!!!!!!
            CONTINUE.
          ENDIF.

    *         Prepare data for docubatch registration
          CLEAR: ls_mch1,
                 ls_mcha.

          ls_mch1-matnr = <goods_rec_item>-material.
          ls_mch1-charg = <goods_rec_item>-vendrbatch.
          ls_mch1-ersda = sy-datum.
          ls_mch1-ernam = sy-uname.
          ls_mch1-ersda_tmstp = sy-datum && sy-uzeit.
          ls_mch1-ersda_tz_sys = sy-tzone.
          ls_mch1-ersda_tz_usr = sy-zonlo.

          MOVE-CORRESPONDING ls_mch1 TO ls_mcha. "Same fields from MCH1 are included in MCHA
          ls_mcha-werks = <goods_rec_item>-plant.

          APPEND: ls_mch1 TO lt_mch1,
                  ls_mcha TO lt_mcha.
        ENDIF.

        IF <char_char>-value_neutral = 2. "Also include batch where-used
    *         Perpare data for batch where-used registration
          CLEAR ls_chvw.
          ls_chvw-matnr = <goods_rec_item>-material.
          ls_chvw-werks = <goods_rec_item>-plant.
          ls_chvw-charg = <goods_rec_item>-vendrbatch.
          ls_chvw-ebeln = <goods_rec_item>-po_number.
          ls_chvw-ebelp = <goods_rec_item>-po_item.
          ls_chvw-mblnr = ls_headret-mat_doc.
          ls_chvw-mjahr = ls_headret-doc_year.
          ls_chvw-zeile = <mseg>-zeile.
          ls_chvw-budat = is_goodsreceipt_head-pstng_date.
          ls_chvw-shkzg = 'S'. "??? VALUE ???
          ls_chvw-bwart = <goods_rec_item>-move_type.
          ls_chvw-kzbew = <goods_rec_item>-mvt_ind. "Goods Movement for Purchase Order
          ls_chvw-menge = <goods_rec_item>-entry_qnt.
          ls_chvw-meins = <goods_rec_item>-entry_uom.
          APPEND ls_chvw TO lt_chvw.
        ENDIF.
      ENDLOOP.

    *     Perform batch registration
      CALL FUNCTION 'VB_INSERT_BATCH'
        TABLES
          zmch1         = lt_mch1
          zmcha         = lt_mcha
          zmchb         = lt_mchb
          zmska         = lt_mska
          zmspr         = lt_mspr
                .

    *     Perform batch where-used registration
      CALL FUNCTION 'VB_BATCH_WHERE_USED_LIST'
        TABLES
          xchvw = lt_chvw.

为什么这还不够好,我需要什么

这作为配置了记录批处理的 MIGO 的快照执行,但不一定涵盖所有情况。

它仅适用于采购单据的上下文,不涵盖其他情况,例如订单和销售订单。

此外,我只有必要的日期,因为 material 文档是在上面立即创建的,这对于所有实施案例都是不可能的。

我想知道是否有从自定义代码执行跟单批处理的预期方法。

引用自the documentation

If you work with RFID or TRM functions, or call IDocs/BAPIs, you can only book in documentary batches by calling up the RFC-capable function module VBDBDM_DATA_MAINTAIN_RFC beforehand or incorporating it into the process.

所以也许这个功能模块是关键? 但是,看来您可能不是第一个经历这种痛苦的人。该文档的评论如下:

Documentary Batch has a lot of constraints and it seems to be a semifinished product of SAP, since is missing a lot of features of real batches.

Be prepared to make a lot of custom enhancements...

来自社区的附录:下面是在这个答案两天后从原始发帖人那里得到的解决方案,从他的问题中移开。

解决方案

采购订单收货调用示例[​​=14=]

  LOOP AT it_goodsreceipt_item ASSIGNING <goods_rec_item>.

    CALL FUNCTION 'VBDBDM_DATA_MAINTAIN_RFC'
      EXPORTING
        i_matnr            = <goods_rec_item>-material
        i_werks            = <goods_rec_item>-plant
        i_quantity         = <goods_rec_item>-entry_qnt
        i_uom              = <goods_rec_item>-entry_uom
        i_docubatch_charg  = <goods_rec_item>-vendrbatch
*       IT_DOCUBATCHES     =
        i_process_id       = '01' "Goods Receipt for External Procurement
*       I_REPLACE_EXISTING_DATA       =
        i_ebeln            = <goods_rec_item>-po_number
        i_ebelp            = <goods_rec_item>-po_item
*       I_AUFNR            =
*       I_AUFPS            =
*       I_RSNUM            =
*       I_RSPOS            =
*       I_RSART            =
*       I_VBELN            =
*       I_POSNR            =
*       IS_DOCUBATCH_COM   =
*       I_LINE_ID          =
*       I_LGNUM            =
*       I_TANUM            =
*       I_TAPOS            =
      EXCEPTIONS
        parameter_error    = 1
        process_not_active = 2.
  ENDLOOP.

* Follow up by creating Material Document, for example through BAPI_GOODSMVT_CREATE