Skip to Content
Technical Articles
Author's profile photo Sandra Rossi

Throw-away code to test BAPI_RESERVATION_CREATE1

This is just an executable program to help developers quickly duplicate an existing reservation (transaction codes MB21, MB22, MB23), and see how parameters are filled. Just used it in ECC 6.0.

EDIT: the code is proposed in this GitHub repository. If you want to improve the code below, please contribute in GitHub.

EDIT: by default the custom fields are not considered (EXTENSIONOUT and EXTENSIONIN), I have added a chapter at the end to explain how to consider them.

REPORT zbapi_reservation_copy.

PARAMETERS p_rsnum TYPE rkpf-rsnum.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_rsnum.
  CALL FUNCTION 'MB_SELECT_RESERVATION'
    EXPORTING
      hilfe = 'HLPR'
    IMPORTING
      rsnum = p_rsnum.

START-OF-SELECTION.

  DATA: sl_header_detail TYPE bapi2093_res_head_detail,
        tl_postes_detail TYPE TABLE OF bapi2093_res_item_detail,
        tl_return        TYPE TABLE OF bapiret2,
        tl_extensionout  TYPE TABLE OF bapiparex.

  CALL FUNCTION 'BAPI_RESERVATION_GETDETAIL1'
    EXPORTING
      reservation        = p_rsnum
    IMPORTING
      reservation_header = sl_header_detail
    TABLES
      reservation_items  = tl_postes_detail
      return             = tl_return
      extensionout       = tl_extensionout.

  IF 0 = REDUCE i( INIT i = 0 FOR <m> IN tl_return WHERE ( type CA 'AEX' ) NEXT i = i + 1 ).

    DATA: sl_header      TYPE bapi2093_res_head,
          tl_postes      TYPE TABLE OF bapi2093_res_item,
          tl_segments    TYPE TABLE OF bapi_profitability_segment,
          tl_extensionin TYPE TABLE OF bapiparex,
          vl_reservation TYPE  bapi2093_res_key-reserv_no.

    sl_header = CORRESPONDING #( sl_header_detail ).
    tl_postes = CORRESPONDING #( tl_postes_detail MAPPING entry_qnt = quantity ).
    tl_extensionin = tl_extensionout.
    CALL FUNCTION 'BAPI_RESERVATION_CREATE1'
      EXPORTING
        reservationheader    = sl_header
      IMPORTING
        reservation          = vl_reservation
      TABLES
        reservationitems     = tl_postes
        profitabilitysegment = tl_segments " <======= ?
        return               = tl_return
        extensionin          = tl_extensionin.
    IF 0 = REDUCE i( INIT i = 0 FOR <m> IN tl_return WHERE ( type CA 'AEX' ) NEXT i = i + 1 ).

      DATA: sl_return TYPE bapiret2.
      CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
        EXPORTING
          wait   = 'X'
        IMPORTING
          return = sl_return.

    ENDIF.
  ENDIF.

  DATA(result) = COND string( WHEN 0 = REDUCE i( INIT i = 0 FOR <m> IN tl_return WHERE ( type CA 'AEX' ) NEXT i = i + 1 )
                        THEN |Created: { vl_reservation }|
                        ELSE 'Failed' ).

  cl_demo_output=>new( )->write_data( result )->write_data( tl_return )->write_data( sl_return )->display( ).

 

Custom fields (EXTENSIONOUT and EXTENSIONIN)

I’m talking about the custom fields you may add in the tables RKPF and RESB.

So that BAPI_RESERVATION_GETDETAIL1 returns the custom fields, I think that the BAdI MB_RES_BAPI_DETAIL1 was planned to implement that, but it doesn’t work in my ECC version, so I did an enhancement at the end of BAPI_RESERVATION_GETDETAIL1.

So that BAPI_RESERVATION_CREATE1 transfers the custom fields to the table, you must implement the BAdI MB_RES_BAPI_CREATE1.

The code below requires that you create the DDIC structures ZBAPI_TE_RKPF and ZBAPI_TE_RESB, with the custom columns that you have defined in the tables RKPF and RESB, and they should have the same names.

Be careful, when calling BAPI_RESERVATION_CREATE1, the sequence of the lines “ZBAPI_TE_RESB” in EXTENSIONIN must be the same as the sequence of the lines in RESERVATIONITEMS, it’s the only criteria I could find to make the match (RSPOS field is missing in RESERVATIONITEMS).

You can adapt the code if you want to work only with either RKPF or RESB.

Code at the end of BAPI_RESERVATION_GETDETAIL1:

TYPES: BEGIN OF zz_ty_valueparts,
  structure TYPE te_struc,
  BEGIN OF parts,
    _1 TYPE valuepart,
    _2 TYPE valuepart,
    _3 TYPE valuepart,
    _4 TYPE valuepart,
  END OF parts,
END OF zz_ty_valueparts.
DATA: zz_zbapi_te_rkpf       TYPE zbapi_te_rkpf,
      zz_table_zbapi_te_resb TYPE TABLE OF zbapi_te_resb.

SELECT SINGLE *
    FROM rkpf
    WHERE rsnum = @reservation
    INTO CORRESPONDING FIELDS OF @zz_zbapi_te_rkpf.
IF sy-subrc = 0.
  " ORDER BY is used to make "ZBAPI_TE_RESB" lines in EXTENSIONOUT ordered as 
  " RESERVATION_ITEMS lines, so that it's aligned with BAPI_RESERVATION_CREATE1 whose lines
  " "ZBAPI_TE_RESB" of EXTENSIONIN and RESERVATIONITEMS must respect the same logic.
  SELECT *
      FROM resb
      WHERE rsnum = @reservation
      ORDER BY PRIMARY KEY 
      INTO CORRESPONDING FIELDS OF TABLE @zz_table_zbapi_te_resb.
  IF sy-subrc = 0.
    extensionout[] = VALUE #(
        ( CONV #( VALUE zz_ty_valueparts(
          structure  = 'ZBAPI_TE_RKPF'
          parts      = CONV #( CORRESPONDING zbapi_te_rkpf( zz_zbapi_te_rkpf ) ) ) ) )
        ( LINES OF VALUE bapiparextab(
          FOR <zz_zbapi_te_resb> IN zz_table_zbapi_te_resb
          ( CONV #( VALUE zz_ty_valueparts(
            structure = 'ZBAPI_TE_RESB'
            parts     = CONV #( CORRESPONDING zbapi_te_resb( <zz_zbapi_te_resb> ) ) ) ) ) ) ) ).
  ENDIF.
ENDIF.

Implement the method EXTENSIONIN_TO_RESB of BAdI MB_RES_BAPI_CREATE1 with this code:

TYPES: BEGIN OF zz_ty_valueparts,
         structure TYPE te_struc,
         BEGIN OF parts,
           _1 TYPE valuepart,
           _2 TYPE valuepart,
           _3 TYPE valuepart,
           _4 TYPE valuepart,
         END OF parts,
       END OF zz_ty_valueparts.
DATA(resb_index) = 0.
LOOP AT it_extension_in ASSIGNING FIELD-SYMBOL(<extensionin>).
  CASE <extensionin>-structure.
    WHEN 'ZBAPI_TE_RKPF'.
      DATA(zbapi_te_rkpf) = CONV zbapi_te_rkpf( LET aux_valueparts = CONV zz_ty_valueparts( <extensionin> ) IN aux_valueparts-parts ).
      MOVE-CORRESPONDING zbapi_te_rkpf TO cs_rkpf.
    WHEN 'ZBAPI_TE_RESB'.
      DATA(zbapi_te_resb) = CONV zbapi_te_resb( LET aux_valueparts = CONV zz_ty_valueparts( <extensionin> ) IN aux_valueparts-parts ).
      ADD 1 TO resb_index.
      ASSIGN resb[ resb_index ] TO FIELD-SYMBOL(<resb>).
      IF sy-subrc = 0.
        MOVE-CORRESPONDING zbapi_te_resb TO <resb>.
      ENDIF.
  ENDCASE.
ENDLOOP.

 

Assigned Tags

      9 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Dominik Tylczynski
      Dominik Tylczynski

      Could not be more to the point :))

      Author's profile photo Andrea Borgia
      Andrea Borgia

      "no blabla" makes my day, thanks 😀

      Author's profile photo Shai Sinai
      Shai Sinai

      TBH, what caught my attention is the following line:

        IF 0 = REDUCE i( INIT i = 0 FOR <m> IN tl_return WHERE ( type CA 'AEX' ) NEXT i = i + 1 ).

      Wouldn't a small utility method (like IS_RETURN_WITH_ERROR) be more readable?

      Author's profile photo Jelena Perfiljeva
      Jelena Perfiljeva

      Most importantly, why is there no standard SAP method for this? Everyone needs this "check if errors in BAPI table" method. I've seen literally dozens of variations in Z code of your and Sandra's example. There are probably thousand methods for this in various SAP classes from different packages. Why is there no standard utility? This is insane...

      Author's profile photo Sandra Rossi
      Sandra Rossi
      Blog Post Author

      It was not the goal of my post to do clean code, it's just a test program which you can use to test the BAPI and you delete it after you have created your own program. But I have pushed the code to this repository, pull requests welcome.

      Author's profile photo Jelena Perfiljeva
      Jelena Perfiljeva

      Yes, more "No blabla", please. That's what we're here for! 🙂

      Author's profile photo Matthew Billingham
      Matthew Billingham

      Just in case you ask, if you want the code to be improved, you can copy the code and post your own post with fixed code,

      Ok... I won't say a word... 🙂 (Matt exits stage left muttering about Hungarian... ).

      Author's profile photo Sandra Rossi
      Sandra Rossi
      Blog Post Author

      It was not the goal of my post to do clean code, it's just a test program which you can use to test the BAPI and you delete it after you have created your own program. But I have pushed the code to this repository, pull requests welcome.

      Author's profile photo Matthew Billingham
      Matthew Billingham

      I know. i was just teasing a bit. 🙂