Artificial Intelligence and Machine Learning Blogs
Explore AI and ML blogs. Discover use cases, advancements, and the transformative potential of AI for businesses. Stay informed of trends and applications.
cancel
Showing results for 
Search instead for 
Did you mean: 
Golla_rusitha
Explorer
1,209

ODATA DRAFT SCENARIOS 

 What is Draft? 

A draft is the state of the business object when its data is not persisted in the actual tables but is stored in some temporary tables which can be quickly retrieved to continue working (from the place left) in case the work is left in the middle due to some reason. Draft Management Process Flow: 

Golla_rusitha_0-1727435348021.png

Consider an application with Sales Order (SO) Header and Item data. The data can be displayed and updated or new SOs can be created. 

Drafts play no role in Display functionality. It is when any user either enters into an update mode or a create mode drafts are involved. 

A Draft can be: 

  • Created when the user enters into update mode – all actual table data is copied for temporary tables/draft tables and then data is presented on the screen for the user to update. 
  • Created when the user enters into create mode- table entries with draft keys are created in draft tables. 
  • Updated when the user enters data in any field, changes a tab on the screen, on any clicks, the press of a button, or at a set time depending on the requirement of the application. Any one of the trigger points or a combination of these trigger points can be used to implement this part. 
  • Deleted when a draft is discarded by the user, or when the data is saved to actual tables. 

Implement Draft Management: 

Create Draft tables to store the data temporarily. In this case, draft tables will be require for Header and Item data. 

Tables for draft data: 

Golla_rusitha_1-1727435490099.png

Golla_rusitha_2-1727435518253.png

Steps to create Entity types: 

Go to SAP Gateway Service Builder(SEGW). 

Golla_rusitha_3-1727435579074.png

 

Click on create project node. 

Golla_rusitha_4-1727435579075.png

 

Provide the project name, description, package name and click on Continue. 

Golla_rusitha_73-1727438920605.png

 

Select the Data model and Right click on data model. 

Golla_rusitha_6-1727435579077.png

 

Select Import and click on DDIC Structures node. 

Provide the entity name and DDIC table name which table you want to import. 

Golla_rusitha_7-1727435579078.png

Click on Next. 

Select the required fields which you want to display/perform operations. 

Golla_rusitha_8-1727435579080.png

Click on Next. 

Golla_rusitha_9-1727435579082.png

 

Select the atleast one key fields from that structure and click on finish. 

Golla_rusitha_10-1727435579083.png

Golla_rusitha_11-1727435579084.png

Golla_rusitha_12-1727435579085.png

Create one more entity type for Item details. 

Click on Save. 

Golla_rusitha_13-1727435579086.png

 

Click on Generate Runtime Objects node. 

Golla_rusitha_14-1727435579086.png

 

By default/Implicitly 4 classes, one technical model and one technical service is created. 

Golla_rusitha_15-1727435579087.png

Click on continue. 

In addition to this one more entity with just a text field is defined to be used as the return type 

Create one return type structure. 

Golla_rusitha_16-1727435579088.png

Add one return type. 

Golla_rusitha_17-1727435579089.png

Golla_rusitha_18-1727435579090.png

Golla_rusitha_19-1727435579091.png

Golla_rusitha_20-1727435579092.png

Steps to create Association : 

Right click on Data model. 

Golla_rusitha_21-1727435579094.png

 

Select Create and click on Association node. 

Provide the Association name, Principle name as Header entity name, Dependent name as Item entity name and provide the cardinality for displaying the item details and provide the navigation property name. 

Golla_rusitha_22-1727435579094.png

Click on Next. 

Provide dependent property name as common field name for both header and item entity. 

Golla_rusitha_23-1727435579095.png

Click on next. 

Golla_rusitha_24-1727435579096.png

Click on Finish. 

Golla_rusitha_25-1727435579097.png

Create one deep structure in MPC_EXT class. 

Golla_rusitha_26-1727436367424.png

Provide Navigation property name for item details like as shown in below 

Golla_rusitha_27-1727436367426.png

 

Steps to create Function Import: 

3 function imports, CreateDraft, DeleteDraft, and SaveOrder are created to achieve the functionality. All use the Return Type as the entity type Return. 

Right click on Data model. 

Golla_rusitha_28-1727436367427.png

 

Select the create and Click on Function import. 

Provide the Function import name, Click on continue. 

Golla_rusitha_29-1727436367428.png

Provide the return type kind as Entity type, Return type as Return entity name, pass the cardinality and select the HTTP method as post. 

Golla_rusitha_30-1727436367428.png

Like this create 2 more function import for DeleteDraft, and SaveOrder. 

Golla_rusitha_31-1727436367430.png

Provide the parameter for function import. 

Golla_rusitha_32-1727436367432.png

Golla_rusitha_33-1727436367434.png

Golla_rusitha_34-1727436367436.png

Code Reference from ZCL_ZGR_ODATA_DRAFT_SC_DPC_EXT 

Golla_rusitha_35-1727436367438.png

 

Read and Query Operations: 

These operations usually will refer to the actual tables/Standard BAPI etc., to get data.

Golla_rusitha_36-1727436696582.png

 

 

method SO_HEADERSET_GET_ENTITY. 
  
    DATA : lv_vbeln TYPE vbak-vbeln. 
  
    DATA(it_keys) = io_tech_request_context->get_keys( ). 
  
    lv_vbeln = VALUE #( it_keys[ name = 'VBELN' ]-value optional ). 
     lv_vbeln = |{ lv_vbeln ALPHA = IN }|. 
  
    select SINGLE  FROM vbak 
                   FIELDS vbeln, 
                          erdat, 
                          erzet, 
                          ernam, 
                          netwr, 
                          waerk, 
                          vkorg, 
                          vtweg, 
                          spart, 
                          kunnr 
                     WHERE vbeln = _vbeln 
                   INTO CORRESPONDING FIELDS OF _entity. 
  
  endmethod.

 

 

Golla_rusitha_37-1727436753714.png

 

 

method SO_HEADERSET_GET_ENTITYSET. 
  
    SELECT FROM vbak 
     FIELDS vbeln, erdat, erzet, ernam, netwr, 
            waerk, vkorg, vtweg, spart, kunnr 
     INTO CORRESPONDING FIELDS OF TABLE _entityset 
     UP TO 20 ROWS. 
  
  endmethod. 

 

 

Read/ Get Item data: 

Golla_rusitha_38-1727436806209.png

 

 

method SO_ITEMSET_GET_ENTITY. 
  
    DATA ls_keys TYPE zcl_zgr_odata_draft_sc_mpc=>ts_so_item. 
  
    io_tech_request_context->get_converted_keys( 
       IMPORTING 
         es_key_values = ls_keys                 " Entity Key Values - converted 
     ). 
  
     SELECT SINGLE FROM vbap 
                    FIELDS vbeln, posnr, matnr, arktx, zmeng, meins, 
                           netwr, waerk, werks, lgort, vstel, route 
                     WHERE vbeln = _keys-vbeln 
                           AND   posnr = _keys-posnr 
                     INTO CORRESPONDING FIELDS OF _entity. 
   endmethod. 

 

 

Golla_rusitha_39-1727436860559.png

 

 

METHOD so_itemset_get_entityset. 
  
    DATA lv_vbeln TYPE vbak-vbeln. 
  
    IF io_tech_request_context->get_source_entity_type_name( ) = 'SO_Header'. 
  
      DATA(It_Keys) = io_tech_request_context->get_source_keys( ). 
  
      lv_vbeln = VALUE #( it_keys[ name = 'Vbeln' ]-value OPTIONAL ). 
       lv_vbeln = |{ lv_vbeln ALPHA = IN }|. 
  
      SELECT FROM vbap 
       FIELDS vbeln, posnr, matnr, arktx, zmeng, meins, 
          netwr, waerk, werks, lgort, vstel, route 
       WHERE vbeln = _vbeln 
       INTO CORRESPONDING FIELDS OF TABLE _entityset. 
  
    ELSE. 
  
      SELECT FROM vbap 
              FIELDS vbeln, posnr, matnr, arktx, zmeng, meins, 
                     netwr, waerk, werks, lgort, vstel, route 
               INTO CORRESPONDING FIELDS OF TABLE _entityset. 
  
    ENDIF. 
  
  ENDMETHOD. 

 

 

CREATE_DRAFT Method: 

An additional method is created in the DPC_EXT class with importing parameter VBELN i.e., Order Number and Exporting parameter Return which is the same type as extra entity. 

This method will check weather the draft exists for the order. If it does and it is by another user, it will return an error text. Otherwise, the method will copy the data from the standard table to custom draft tables ZGR_T_SOH_DRAFT and ZGR_T_SOI_DRAFT. 

To Keep the logic simple, the method uses incremental logic to generate a key. In an actual scenario, we will either use a hash generator or number range to create the draft key. 

Note: Create_Draft method is a custom method which is have importing and Returning parameter. 

Golla_rusitha_40-1727436940357.png

Golla_rusitha_41-1727436975958.png

Golla_rusitha_42-1727436975959.png

Golla_rusitha_43-1727436975960.png

 

 

  method CREATE_DRAFT. 
  
    "Check if draft exists 
     SELECT SINGLE FROM zgr_t_soh_draft 
                   FIELDS * 
                   INTO (ls_draft). 
  
      IF sy-subrc EQ 0. "Draft exist 
  
        IF sy-uname = ls_draft-ernam. "Draft by same user 
  
          RETURN = VALUE zgr_s_return( test = 'S Draft success' ). 
  
          ELSE. 
  
            RETURN-test = |E Draft user : { ls_draft-ernam }|. 
  
        ENDIF. 
  
      ELSE. "No Draft 
  
        SELECT SINGLE FROM vbak 
                       FIELDS vbeln, erdat, erzet, ernam, netwr, 
                              waerk, vkorg, vtweg, spart, kunnr 
                       WHERE vbeln = @vbeln 
                       INTO (ls_vbak). 
  
          IF sy-subrc EQ 0. 
  
            ls_draft = CORRESPONDING #( ls_vbak ). 
             ls_draft-ernam = sy-uname. 
  
            INSERT zgr_t_soh_draft FROM ls_draft. 
  
            IF sy-subrc EQ 0. 
  
              RETURN-test = 'S Draft Success'. 
  
              ELSE. 
                 RETURN-test = 'S Draft Failed'. 
  
 
            ENDIF. 
  
          ENDIF. 
  
          "Add items to the draft 
  
          SELECT  FROM vbap 
                  FIELDS mandt, vbeln, posnr, matnr, arktx, zmeng, meins, 
                         netwr, waerk, werks, lgort, vstel, route 
                  WHERE vbeln = @vbeln 
                  INTO TABLE (lt_items). 
  
            IF sy-subrc EQ 0. 
  
              INSERT zgr_t_soi_draft FROM TABLE _items. 
  
            ENDIF. 
  
      ENDIF. 
  
  endmethod. 

 

 

CREATE Operation: 

Create Operation should be called only for item data. For header data instead of create, created draft should be called. Item create operation, actually only creates an entry in the draft table. 

Golla_rusitha_44-1727437087754.png

 

 

method SO_ITEMSET_CREATE_ENTITY. 
  
  DATA:  ls_Final TYPE zcl_zgr_odata_draft_sc_mpc_ext=>TY_FINAL, 
          ls_item type zcl_zgr_odata_draft_sc_mpc=>ts_so_item. 
  
  io_data_provider->read_entry_data( 
     IMPORTING 
       es_data = ls_final 
   ). 
  
  ls_item = CORRESPONDING #( ls_final ). 
  
  INSERT zgr_t_soi_draft FROM ls_item. 
  
  IF Sy-subrc EQ 0. 
  
    er_entity = ls_item. 
  
  ENDIF. 
  
  endmethod.

 

 

UPDATE Operation: 

Update operation for header and item entities will update the draft tables. 

Update Operation For Header Data:

Golla_rusitha_45-1727437163679.png

 

 

  method SO_HEADERSET_UPDATE_ENTITY. 
  
    DATA: ls_final TYPE zcl_zgr_odata_draft_sc_mpc_ext=>ty_final, 
           ls_header TYPE zcl_zgr_odata_draft_sc_mpc_ext=>ts_so_header. 
  
    io_data_provider->read_entry_data( 
       IMPORTING 
         es_data = ls_final 
     ). 
  
    ls_header = CORRESPONDING #( ls_final ). 
  
    IF sy-subrc Eq 0. 
  
      MODIFY zgr_t_soh_draft FROM ls_header. 
  
        er_entity = ls_header. 
  
    ENDIF. 
  
  endmethod. 

 

 

Update operation for Item data: 

Golla_rusitha_46-1727437223840.png

 

 

 method SO_ITEMSET_UPDATE_ENTITY. 
  
    DATA: ls_final TYPE zcl_zgr_odata_draft_sc_mpc_ext=>ty_final, 
           ls_item TYPE zcl_zgr_odata_draft_sc_mpc_ext=>ts_so_item. 
  
    io_data_provider->read_entry_data( 
       IMPORTING 
         es_data = ls_final 
     ). 
  
    ls_item = CORRESPONDING #( ls_final ). 
  
    IF sy-subrc EQ 0. 
  
      MODIFY zgr_t_soi_draft FROM ls_item. 
  
    ENDIF. 
  
  endmethod.

 

 

DELETE Operation: 

In this case, a delete operation is not implemented as a Sales Order can not be deleted from the system. Usually, it will be set as all items rejected etc., which can be done in an update operation. 

Function Import Implementation: 

Method /IWBEP/IF_MGW_APPL_SRV_RUNTIME~EXECUTE_ACTION is redefined to implement the function imports. 

CreateDraft: 

  • Call the method Create_draft with the Sales order number. 

Golla_rusitha_47-1727437312431.png

DeleteDraft: 

  • Delete the draft data from the header and item draft tables. 

Golla_rusitha_48-1727437312432.png

SaveOrder: 

  • Check if the order number exists. If it does, it is a change mode, else it is a create mode. 
  • Get data from draft tables. 
  • Call create/change BAPI. 
  • Return the Message with order number. 

Golla_rusitha_49-1727437312433.png

Golla_rusitha_50-1727437312434.png

 

Golla_rusitha_51-1727437312435.png

Golla_rusitha_52-1727437312435.png

 

Golla_rusitha_53-1727437312436.png

Golla_rusitha_54-1727437312437.png

Golla_rusitha_55-1727437312438.png

Function Import implementation:

 

 

  METHOD /iwbep/if_mgw_appl_srv_runtime~execute_action. 
  
    DATA : lv_vbeln_out TYPE vbeln. 
     DATA : ls_header_in TYPE bapisdhd1, 
            lt_items_in  TYPE STANDARD TABLE OF bapisditm, 
            lt_partners  TYPE STANDARD TABLE OF bapiparnr, 
            lt_return    TYPE STANDARD TABLE OF bapiret2. 
  
    CASE iv_action_name. 
       WHEN 'CreateDraft'. 
  
        TRY. 
  
          DATA(lt_pars) = io_tech_request_context->get_parameters( ). 
           DATA(lv_vbeln) = VALUE vbeln_va( lt_pars[ name = 'SALESORDER' ]-value OPTIONAL ). 
  
          lv_vbeln = |{ lv_vbeln ALPHA = IN }|. 
           DATA(ls_return) = create_draft( vbeln = lv_vbeln  ). 
  
        CATCH cx_sy_itab_line_not_found. 
  
          "Error 
  
          ls_return-test = 'E Invalid call'. 
  
        ENDTRY. 
  
        copy_data_to_ref( 
           EXPORTING 
             is_data = ls_return 
           CHANGING 
             cr_data = er_data 
         ). 
  
      WHEN 'DeleteDraft'. 
          
         TRY. 
           lt_pars = io_tech_request_context->get_parameters( ). 
           lv_vbeln = VALUE vbeln_va( lt_pars[ name = 'SALESORDER' ]-value ). 
           lv_vbeln = |{ lv_vbeln ALPHA = IN }|. 
           DELETE FROM zgr_t_soh_draft WHERE vbeln = _vbeln. 
           IF sy-subrc EQ 0. 
  
            DELETE FROM zgr_t_soi_draft WHERE vbeln = _vbeln. 
  
            ls_return-test = 'S draft deleted'. 
  
          ENDIF. 
  
        CATCH cx_sy_itab_line_not_found. 
           "Error 
           ls_return-test = 'E Invalid call'. 
  
        ENDTRY. 
         copy_data_to_ref( 
           EXPORTING 
             is_data = ls_return 
           CHANGING 
             cr_data = er_data 
         ). 
  
      WHEN 'SaveOrder'. 
  
        TRY. 
  
          lt_pars = io_tech_request_context->get_parameters( ). 
           lv_vbeln = VALUE vbeln_va( lt_pars[ name = 'SALESORDER' ]-value OPTIONAL ). 
           lv_vbeln = |{ lv_vbeln ALPHA = IN }|. 
  
          select SINGLE vbeln FROM vbak into (lv_vbeln_Test) 
                   WHERE vbeln = _vbeln. 
  
            IF sy-subrc NE 0. 
  
              CLEAR lv_vbeln_test. 
  
            ENDIF. 
  
            SELECT SINGLE FROM zgr_t_soh_draft 
                       FIELDS * 
                       WHERE vbeln = _vbeln 
                       INTO (ls_header). 
  
              IF sy-subrc NE 0. 
  
                ls_return-test = 'E Sales order not found'. 
  
                ELSE. 
  
                  "Fetch draft items 
  
                  SELECT FROM zgr_t_soi_draft 
                          FIELDS * 
                          WHERE vbeln = _vbeln 
                          INTO TABLE (lt_item). 
  
                    IF lv_vbeln_test IS NOT INITIAL. "Change mode 
  
                      DATA : ls_headerx_in TYPE bapisdh1x, 
                              ls_uheader_in TYPE bapisdhd1, 
                              lt_itemsx_in TYPE STANDARD TABLE OF bapisditmx. 
  
                      lt_items_in = VALUE #( FOR  ls_item IN lt_item 
                                           ( itm_number = ls_item-posnr 
                                             short_text = ls_item-arktx 
                                            ) 
                                           ). 
  
 
                      lt_itemsx_in = VALUE #( FOR ls_item IN lt_item 
                                            ( itm_number = ls_item-posnr 
                                              updateflag = 'U' 
                                              short_text = 'X' 
                                            ) 
                                           ). 
  
                      ls_headerx_in-updateflag = 'U'. 
                       lv_vbeln_out = lv_vbeln_test. 
  
                      CALL FUNCTION 'BAPI_SALESORDER_CHANGE' 
                         EXPORTING 
                           salesdocument               = lv_vbeln_test 
                           order_header_inx            = ls_headerx_in 
                         TABLES 
                           return                      = lt_return 
                           ORDER_ITEM_IN               = lt_items_in 
                           ORDER_ITEM_INX              = lt_itemsx_in 
                                 . 
                      ELSE. 
  
                       ls_header_in-doc_type = 'ZOR1'. 
                        ls_header_in-doc_date = ls_header-erdat. 
                        ls_header_in-created_by = ls_header-ernam. 
                        ls_header_in-currency = ls_header-waerk. 
                        ls_header_in-sales_org = ls_header-vkorg. 
                        ls_header_in-distr_chan = ls_header-vtweg. 
                        ls_header_in-division = ls_header-spart. 
  
                       lt_partners = VALUE #( ( partn_role = 'AG' 
                                                 partn_numb = ls_header-kunnr ) ). 
                        lt_items_in = VALUE #( FOR LS_ITEM IN lt_item 
                                            ( itm_number = ls_item-posnr 
                                              material = ls_item-matnr 
                                              short_text = ls_item-arktx 
                                              target_qty = ls_item-zmeng 
                                              target_qu = ls_item-meins 
                                              plant = ls_item-werks 
                                              store_loc = ls_item-lgort 
                                              ship_point = ls_item-vstel 
                                              route = ls_item-route 
                                             ) 
                                            ). 
  
                       CALL FUNCTION 'BAPI_SALESORDER_CREATEFROMDAT2' 
                          EXPORTING 
                            order_header_in               = ls_header_in 
                         IMPORTING 
                           SALESDOCUMENT                 = lv_vbeln_out 
                          tables 
                           RETURN                        = lt_return 
                           ORDER_ITEMS_IN                = lt_items_in 
                           order_partners                = lt_partners 
                                  . 
                     ENDIF. 
  
                    IF NOT line_exists( lt_return[ type = 'E' ] ). 
  
                      "Update FM to delete the draft 
                       CALL FUNCTION 'BAPI_TRANSACTION_COMMIT' 
 *                       EXPORTING 
 *                         WAIT          = 
 *                       IMPORTING 
 *                         RETURN        = 
                                 . 
  
                      "Delete Draft 
  
                      delete FROM zgr_t_soh_draft WHERE vbeln = lv_vbeln. 
                       delete FROM zgr_t_soi_draft WHERE vbeln = lv_vbeln. 
                       ls_return-test = lv_vbeln_out. 
  
                    ELSE. 
  
                      ls_return-test = 'E Error in Bapi Call'. 
  
                    ENDIF. 
  
              ENDIF. 
  
 
        CATCH cx_sy_itab_line_not_found. 
  
          "Error 
           ls_return-test = 'E Invalida call'. 
  
        ENDTRY. 
  
        me->copy_data_to_ref( 
           EXPORTING 
             is_data = ls_return 
           CHANGING 
             cr_data = er_data 
         ). 
     ENDCASE. 
   ENDMETHOD. 

 

 

Steps to Register the Services: 

Goto SAP Gateway services (/IWFND/MAINT_SERVICES). 

Golla_rusitha_56-1727437695962.png

 

Click on Add Services node. 

Golla_rusitha_57-1727437695962.png

 

Provide the System Alias and Technical service name which is generated while generating the OData services. 

Golla_rusitha_58-1727437695964.png

Click on Get services node. 

Golla_rusitha_59-1727437695965.png

 

Select the services and click on Add Selected Services. 

Golla_rusitha_60-1727437695966.png

Golla_rusitha_61-1727437695968.png

 

Provide the Package name and click on continue. 

Golla_rusitha_72-1727438564844.png

Select the services by using Filter. 

Golla_rusitha_63-1727437695971.png

Golla_rusitha_64-1727437695971.png

Golla_rusitha_65-1727437695974.png

Click on SAP Gateway Client. 

Golla_rusitha_66-1727437695976.png

Some basic scenarios output: 

Golla_rusitha_67-1727438473508.png

Golla_rusitha_68-1727438473511.png

Golla_rusitha_69-1727438473515.png

Golla_rusitha_70-1727438473518.png

Golla_rusitha_71-1727438473521.png

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2 Comments
wridgeu
Participant
0 Kudos

Hey there, great blog post!

I appreciate the images (including the diagrams) and the code samples as well as the layout! Sure still SEGW and V2 as others may want to point out but I'm not here for that. You may want to untick the checkbox "Create Default Entity Set" when creating your EntityType for the return type of your function import/service operation as you probably don't want or need it. 

Other than that, nice example of building draft yourself (stitching the things together). 🙂

Siva_sankar_225
Discoverer
0 Kudos

Thank you Rushitha,
It was helped me alot!

Labels in this area