Skip to Content
0
Oct 30, 2019 at 01:23 PM

Proper way to create Documentary Batches programatically (how to use BAPI_GOODSMVT_CREATE?)

583 Views Last edit Oct 31, 2019 at 02:50 PM 4 rev

Better formatting on stackoverflow: https://stackoverflow.com/questions/58626204/proper-way-to-create-documentary-batches-programatically-how-to-use-bapi-goodsm


Solution at the bottom

Summary of the problem

Automatic Documentary Batch handling through custom ABAP code

My employer wishes to perform automatic documentary batch handling on some products from external vendors, and I'm trying to figure out how to set this up through Customizing and ABAP. It seems to me that Documentary Batches are only meant to be used through MIGO - in any case I'm unable to find a proper solution to assign them programatically, and any hacked-together solution I can come up with, seems insufficient and unstable. What avenues do I have to solve this issue?

Enhancing BAPI_GOODSMVT_CREATE?

Can I somehow do it through stuff like BAPI_GOODSMVT_CREATE?

Enhancing PPPI Message Destinations?

I also specifically need it to work for consumption messaging through PPPI, and I thought to build on top of the standard Message Destination 'PI04', FM 'COCI_CONFIRM_MATERIAL_CONS'. This FM creates a Material Document but does not go through the 'BAPI_GOODSMVT_CREATE' FM. It does however use 'MB_CREATE_GOODS_MOVEMENT'.

What I've already tried

MIGO Snapshot based Single Use hack solution

I made hack-solution for one area, where I watched which table-updates MIGO performed and with which data (through FM's 'VB_INSERT_BATCH' and 'VB_BATCH_WHERE_USED_LIST'), and then filled out these structures manually. However, providing all the needed info is not feasible for other implementation areas, as they do not have all the necessary values available, and it doesn't cover unforeseen situations where other parameters might be required.

Reading through BAPI_GOODSMVT_CREATE code

I've tried spying on whether BAPI_GOODSMVT_CREATE performs the same FM's but only found it accessing 'VB_BATCH_WHERE_USED_LIST'. It seems to be possible to activate this functionality by controlling Memory ID 'Documentary Batch #1', 'Documentary Batch #2', 'Documentary Batch #3' and 'Documentary Batch #5' (see FM 'VBDBDM_DATA_POST_IM'), but this requires filling out a lot data, including the structure name 'DOCUBATCH_SCREEN_FIELDS', which again makes it seem like this might not be the correct avenue of approach.

Regardless, this still doesn't allow me to maintain batch through tables MCHA and MCH1.

Hacked together solution based on MIGO snapshot

Here is how my hacked solution looks. Again, this is not a feasible way to go about the problem, as other implementation areas does not have the resulting Material Document immediately available:

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.

ENDFUNCTION.

Summary of why this isn't good enough, and what I need

This performs as a snapshot of MIGO configured with documentary batch handling, but doesn't necessarily cover all cases. It only works in the context of a Purchase Document, and doesn't cover other cases such as Orders and Sales Orders. Additionally I only have the necessary date because of the material document being created immediately above, which is not possible for all implementation cases.

I would like to know if there is an intended way to perform Documentary Batch handling from custom code.

Solution

Example call for Purchase Order Goods Receipt

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