Skip to Content
Technical Articles
Author's profile photo Yogesh Vijay

Using Standard BOPF Object for CRUD Operations – Single/Multiple

What you will learn in this blog?

In this blog, you will learn to use SAP delivered standard BOPF object for CRUD operations in Custom Application.

 

My scenario / Example to Understand

For my use case, I have to create an excel upload utility to update/create multiple Service Entry Sheets in one go – Header & Item. There is a Standard Fiori Application that exists for creating Service Entry Sheet one by one. This application uses a BOPF object to perform CRUD operation along with draft functionality. For my use case I need to upload multiple Service Entry Sheet in one go-to standard tables so that they are visible to Standard Application and for this, I have few options:

  • Use Standard BAPI provided so that few validations can be performed automatically
    • Downside – BAPI should be there and not all validations, determinations, etc. will be there.
  • Write custom code for Validations, save, etc.
    • Time-consuming and sometimes as a custom development you don’t get time to figure out each validation
  • Use the BOPF object used to create an actual application that handles all the validations, determinations, actions, etc.

 

I found that using the 3rd approach I almost save 80% of my time. Let me share your steps that how I used existing BOPF to simply perform CRUD operations.

 

Steps:

  1. For Upload of Excel, I have used standard API and classes which I will share in another blog, however for I have store data in two internal tables Header and Item after upload. Till this time I have only validated the format of data for ex. Date column should have a valid date, number column should have a number, etc. NO BUSINESS VALIDATIONS.

2. Now I have to use standard BOPF to perform CRUD operations with my data. To show an example I am performing Create as of now

3. Standard BO used – I_SERVICEENTRYSHEETTP (How to find Standard BO ?) – Usually, if a BOPF is a CDS based BOPF then the name of CDS views and BOPF will be same otherwise you can find it in Gateway project.

 

 

 

 

 

 

 

 

4. Now let’s see the actual coding part wherein we will use this standard BOPF object to update records. But before this to give a heads-up when BOPF framework is used then records are saved with three basic keys – Node Key, Parent Key and Root Key ( this you can understand in BOPF concepts ).

5. BOPF has two parts Transactional Buffer and Save Sequence. First lets fill transactional buffer using BOPF service manager MODIFY method. In above screenshot mo_svc_mngr is initiated for Service Entry Sheet BOPF object using Keys present in constant class of BO object

6. Constant class IF_I_SERVICEENTRYSHEETTP_C gets created when BOPF object was created.

7. Now at step 2 (screenshot) LT_MOD is an internal table passed to IT_MODIFICATION, Now let’s see how LT_MOD is being prepared.

In above screenshot modification data needs few mandatory details:

  1. Node – Constant node key for Service Entry sheet header/item
  2. Change_mode – in above screenshot create is mentioned
  3. Key – generated key for Header record (random key)
  4. Root_key – since this is a header and the root, it is same (at item we will put root key as Header key)
  5. Data – here data reference is there.

 

8. Now fill LT_MOD with all the data reference in LOOP for multiple records and then execute MODIFY method. Once method is called data will be stored in buffer and all the validations and determinations will be executed and if there are any issues the messages will be raised in eo_message.

9. To map messages with input records, in output messages key will be there for records which has issues

In above screenshot to get the messages use method get( ) and then to map the record key use ms_origin_location-key

10. Now let’s do the same process for items. In this particular BO object once modify for Header is executed then it automatically create Item record with pre-determined fields.

Use method retrieve_by_association to fetch item records created by Header modify and then fill rest of the columns imported by Excel

11. Now use modify method for Items but before that we need to prepare modification table for Items

In items we need to mention 3 things differently from what we mentioned at header

  1. Change mode – update
  2. Association – association constant from header to item
  3. Changed fields – whatever fields we updated, their node key need to be mentioned here (constant need to be mentioned)

12. Again if there are any messages then eo_messages will be updated.

13. Once modify is executed successfully it means all the validations (business validations) are already executed.

14. Now use SAVE method of Transaction Manager object.

15. For above mentioned BO data is saved in Draft table, now we need to save data in Service Entry Sheet Standard Tables. For this we will use ACTIVATION action of this BOPF object.

With above mentioned action we will be able to save data in actual tables. In IT_KEY input parameter we just need to pass Service Entry Sheet Header Keys which we used in MODIFY method of Header.

16. Once this is executed successfully data will be save to Standard Service Entry Sheet tables.

 

I hope you will be able to get some understanding of using Standard BOPF object for a Custom Application CRUD operations. In case of any questions of comments do let me know in below comments section.

 

Thanks,

Assigned Tags

      11 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Rajesh Sahukari
      Rajesh Sahukari

      Hi Yogesh,

      Thank for the blog. I have similar requirement in my project. I can able to create draft entries. But when I call Activation method (to convert draft to active) , data is not being saved in Active table, still I can see the draft entries in draft table.

      Can you please help me with more details.

      Thanks,

      Rajesh.

      Author's profile photo Yogesh Vijay
      Yogesh Vijay
      Blog Post Author

      Hi Rajesh,

      Sure I can help here, If activation is not happening it means either activation is not implemented which is very less likely. you can connect me on Teams and then let me know which BO you are using. We can check if there is anything missing or not.

      Thanks,

      Yogesh Vijay

      Author's profile photo Juan David Lopez
      Juan David Lopez

      Hi Yogesh,

      Thank you for the blog. I have a question. I have created an application for create Purchase Orders (the standard application did not meet the requirements). I already have the BOPF objects created.

      But how can I redefine the Activation action to implement the standard BAPI call to create the PO?

      Can you please help me with more details.

      Thanks,

      Juan L..

      Author's profile photo Yogesh Vijay
      Yogesh Vijay
      Blog Post Author

      Hi Juan,

       

      If I understood you correctly  - You have created new BOPF objects for Customized PO Creation? Right? or you are using existing BOPF objects (standard) for PO Creation.

      In case of a customized BO, you can implement your own Activation actions, however, if it is a standard application and you wish to create Extention then for existing action you have an option with pre/post action enhancements.

      In order to create a pre/post action enhancement, the target action definition in the super BO must have its “Action Can Be Enhanced” flag set (see below). Assuming that the flag is set, then we can proceed through the corresponding wizard process in much the same way we would if we were creating a custom action from scratch. Indeed, as is the case with regular actions, the implementation class(es) for pre/post action enhancements must implement the /BOBF/IF_FRW_ACTION interface.

       

      Regards,

      Yogesh Vijay

       

       

       

      Author's profile photo Juan David Lopez
      Juan David Lopez

      Hi Yogest,

      In my case, I created custom CDS and BOPF views for this application.

      Following your instructions, do I need to create an action for this creation? I have the following actions in my BOPF. But I don't have the action of creating the object. I guess it's the Activation. I can't change implementation class to a Custom one. Do you have a guide on how to carry out this process?

      BOPF%20Actions

      BOPF Actions

      Thanks for your help.

      Best regards,

      Juan Lopez

      Author's profile photo Maria Pisareva
      Maria Pisareva

      Hi Yogesh!

      Could you help me please? What if the super BO action have “Action Can Be Enhanced” flag EMPTY. But I need to put some logic into action.

      What should I do?

      Author's profile photo Yogesh Vijay
      Yogesh Vijay
      Blog Post Author

      If Action's Action can be Enhanced flag is unticked, it means this action is not extensible (modification free).

      Author's profile photo Yogesh Vijay
      Yogesh Vijay
      Blog Post Author

      Hi Juan,

       

      I don't have any guide as such, as far I understand you need to enhance ACTIVATION action. You can check this blog

      https://blogs.sap.com/2013/02/22/navigating-the-bopf-part-5-enhancement-techniques/

      Here you may get some help. In case you need more help on this, we can connect separately.

       

      Regards,

      Yogesh

      Author's profile photo lakshmi chinta
      lakshmi chinta

      Hi Yogesh  i want to delete some personS(FIELD)  from many locations (LOCATION NODE) in EHSM module  .These persons will be entered in the selection screen .Please guide.

      Kind Regrads

      Lakshmi

      Author's profile photo Sanjay Kumar A M
      Sanjay Kumar A M

      Hi Yogesh,

      I have a doubt. We are trying to use the existing BOPF logic in our classes using Service manager and transaction manager by adding few more validations in our code. We want to clear the draft data whenever there is error in validation which we are not able to do using cleanup method in transaction manager.

      Is there any way we can clear the data in draft tables?

      Thanks,

      Sanjay

      Author's profile photo Sean Jorden
      Sean Jorden

      If you are struggling with this topic and blog, I suggesting looking at sample program /BOBF/R_DEMO_CUSTOMER_TEST which cleared things right up for me.

      The sequence of events I used to successfully create I_DEFECT_TP objects (which are draft enabled) was

      • Service Manager / Modify
      • Service Manager / Do Action "activation"
      • Transaction Manager / Save

      My source is here, which is adapted from /BOBF/R_DEMO_CUSTOMER_TEST

      DATA lo_txm       TYPE REF TO /bobf/if_tra_transaction_mgr.
      DATA lo_defect_conf TYPE REF TO /bobf/if_frw_configuration.
      DATA lo_defect      TYPE REF TO /bobf/if_tra_service_manager.
      DATA ls_defect_root      TYPE REF TO isdefect_tp.
      DATA lt_activation_keys TYPE /bobf/t_frw_key.
      DATA lo_chg       TYPE REF TO /bobf/if_tra_change.
      DATA lo_msg       TYPE REF TO /bobf/if_frw_message.
      DATA lt_mod TYPE /bobf/t_frw_modification.
      DATA lv_err       TYPE abap_bool.
      DATA lx_bopf      TYPE REF TO /bobf/cx_frw.
      
      FIELD-SYMBOLS   <ls_mod> LIKE LINE OF lt_mod.
      
      TRY.
          lo_txm         = /bobf/cl_tra_trans_mgr_factory=>get_transaction_manager( ).
          lo_defect        = /bobf/cl_tra_serv_mgr_factory=>get_service_manager( if_i_defect_tp_c=>sc_bo_key ).
          lo_defect_conf   = /bobf/cl_frw_factory=>get_configuration( if_i_defect_tp_c=>sc_bo_key ).
      
      *     <Create ROOT>
          APPEND INITIAL LINE TO lt_mod ASSIGNING <ls_mod>.
          <ls_mod>-node            = if_i_defect_tp_c=>sc_node-i_defect_tp.
          <ls_mod>-change_mode     = /bobf/if_frw_c=>sc_modify_create.
          <ls_mod>-key             = /bobf/cl_frw_factory=>get_new_key( ).
          CREATE DATA ls_defect_root.
          <ls_mod>-data            = ls_defect_root.
          ls_defect_root->key             = <ls_mod>-key.
          ls_defect_root->defectcategory     = 'Z1'.
          ls_defect_root->defecttext       = 'test'.
          ls_defect_root->zz1_responsibledepartm_nit = '101'.
          ls_defect_root->zz1_capasourcecategory_nit = '101'.
          ls_defect_root->zz1_regulatoryagency_nit = '101'.
      
          " -------------------------------------------------------
          "   call modify - this will create a draft (but not saved)
          CALL METHOD lo_defect->modify
            EXPORTING
              it_modification = lt_mod
            IMPORTING
              eo_change       = lo_chg
              eo_message      = lo_msg.
      
          PERFORM output_messages USING lo_msg CHANGING lv_err.
      
          IF lv_err = abap_true.
            WRITE: / 'Modify Failed'.                             "#EC NOTEXT
            EXIT.
          ELSE.
            WRITE: / 'Modify Successful'.                             "#EC NOTEXT
          ENDIF.
      
      
          " -------------------------------------------------------
          " call activate - this will move from draft to non draft, but not saved
          " validations will be performed
          APPEND VALUE /bobf/s_frw_key( key = ls_defect_root->key ) TO lt_activation_keys.
      
          CALL METHOD lo_defect->do_action
            EXPORTING
              iv_act_key = if_i_defect_tp_c=>sc_action-i_defect_tp-activation
              it_key     = lt_activation_keys
            IMPORTING
              eo_message = lo_msg.
      
          PERFORM output_messages USING lo_msg CHANGING lv_err.
      
          IF lv_err = abap_true.
            WRITE: / 'Activation Failed'.                         "#EC NOTEXT
            EXIT.
          ELSE.
            WRITE: / 'Activation Successful'.
          ENDIF.
      
          " -------------------------------------------------------
          " call save - this will create in database
          CALL METHOD lo_txm->save
            IMPORTING
              eo_message  = lo_msg
              ev_rejected = lv_err.
      
          PERFORM output_messages USING lo_msg CHANGING lv_err.
      
          IF lv_err = abap_true.
            WRITE: / 'Second Save Failed'.                               "#EC NOTEXT
            EXIT.
          ELSE.
            WRITE: / 'Second Save Successful'.
          ENDIF.
      
          WRITE: / 'Saved successfully'.                          "#EC NOTEXT
        CATCH /bobf/cx_frw INTO lx_bopf.
          PERFORM output_errors USING lx_bopf.
      ENDTRY.
      
      WRITE: / 'got to here'.
      
      
      *----------------------------------------------------------------------*
      FORM output_messages
        USING
          io_msg TYPE REF TO /bobf/if_frw_message
        CHANGING
          ev_has_errors TYPE abap_bool.
        DATA:
          lt_msg TYPE /bobf/t_frw_message_k,
          ls_msg LIKE LINE OF lt_msg,
          lv_txt TYPE string.
      
        CHECK io_msg IS BOUND.
        ev_has_errors = abap_false.
        io_msg->get_messages( IMPORTING et_message = lt_msg ).
        IF lt_msg IS NOT INITIAL.
          WRITE: / 'Messages:'.                                   "#EC NOTEXT
          LOOP AT lt_msg INTO ls_msg.
            lv_txt = ls_msg-message->get_text( ).
            WRITE: / ls_msg-severity, ' ', lv_txt.
            CASE ls_msg-severity.
              WHEN /bobf/cm_frw=>co_severity_error OR
                   /bobf/cm_frw=>co_severity_abend.
                ev_has_errors = abap_true.
            ENDCASE.
          ENDLOOP.
        ENDIF.
      ENDFORM.                   "output_messages
      
      *----------------------------------------------------------------------*
      FORM output_errors
        USING
          ix_frw TYPE REF TO /bobf/cx_frw.
        DATA:
          lv_tx   TYPE string,
          lx_root TYPE REF TO cx_root.
        lx_root = ix_frw.
      
        WRITE: / 'Runtime Errors'.                                "#EC NOTEXT
        WHILE lx_root IS BOUND.
          lv_tx = lx_root->get_text( ).
          WRITE: / lv_tx.
          lx_root = lx_root->previous.
        ENDWHILE.
      ENDFORM.                    "output_errors
      *----------------------------------------------------------------------*