Monday, 25 March 2019

Creating a draft enabled Sales Order Fiori App using the new ABAP Programming Model – Part 4: Implementing locking & delete functionality

Adding logic using BOPF


In the previous blogs we’ve prepared our virtual data model which we exposed using an OData service and created a Fiori Elements App on top of the OData service. We now have a very basic app up and running. Time to add additional functionality using ABAP and the BOPF framework to make our app fully functional!

In this part we’ll cover:

◈ Durable locking
◈ Deleting an existing Sales Order

Implementing durable locking


By default, when changing an existing Sales Order only the draft instance is locked. Which means someone can edit the sales order using both the standard VA02 transaction and our newly created app at the same time.

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Study Materials

Lock entry when creating a draft instance:

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Study Materials

To lock the actual Sales Order in the backend we’ll need to implement one of the generated classes. When we activated the virtual data model, the framework generated following class:

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Study Materials

Within this class, there is one method (/bobf/if_lib_lock_active~lock_active_entity) that we need to implement. Add following code to the method to enable locking the sales order in the backend.

METHOD /bobf/if_lib_lock_active~lock_active_entity.
  DATA: lt_header_data TYPE ztsdi_soheader,
        ls_failed_key  TYPE /bobf/s_frw_key.

* Read root node (Sales Order header)
  io_read->retrieve(
    EXPORTING
      iv_node                 = is_ctx-node_key
      it_key                  = it_key
    IMPORTING
      et_data                 = lt_header_data
      et_failed_key           = et_failed_key
  ).

* Read actual Sales Order header and lock Sales Order
  READ TABLE lt_header_data INTO DATA(ls_header_data) INDEX 1.
  IF sy-subrc EQ 0.
*   Call standard lock object
    CALL FUNCTION 'ENQUEUE_EVVBAKE'
      EXPORTING
        mode_vbak      = 'E'
        mandt          = sy-mandt
        vbeln          = ls_header_data-vbeln
        x_vbeln        = space
        _scope         = '2'
        _wait          = space
        _collect       = ' '
      EXCEPTIONS
        foreign_lock   = 1
        system_failure = 2
        OTHERS         = 3.
    IF sy-subrc <> 0.
      et_failed_key = it_key.
    ENDIF.
  ENDIF.
ENDMETHOD.

When opening a draft instance the Sales Order will be locked and can’t be changed in the backend anymore.

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Study Materials

Lock entries when creating a draft instance:

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Study Materials

Implementing deletion logic


When we activated the virtual data model, the framework generated a class to implement deletion logic.

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Study Materials

Implement following logic to get the actual Sales Order number from the GUID based key the framework works with and delete the Sales Order using the standard BAPI.

METHOD /bobf/if_lib_delete_active~delete_active_entity.
  DATA: lr_database_keys TYPE REF TO data,
        lt_messages       TYPE bapiret2_t,
        ls_headerx_change  TYPE bapisdh1x.
  FIELD-SYMBOLS: <ft_database_keys> TYPE ztk_sdi_soheader_active_entit,
                 <fs_database_key> TYPE zsk_sdi_soheader_active_entit.

* Get BOPF configuration
  DATA(lo_conf) = /bobf/cl_frw_factory=>get_configuration( iv_bo_key = is_ctx-bo_key ).
  lo_conf->get_node( EXPORTING iv_node_key = is_ctx-node_key
                     IMPORTING es_node     = DATA(ls_node_conf) ).

* Get key structure for active object
  lo_conf->get_altkey(
     EXPORTING
      iv_node_key    = is_ctx-node_key
      iv_altkey_name = /bobf/if_conf_cds_link_c=>gc_alternative_key_name-draft-active_entity_key
     IMPORTING
      es_altkey      = DATA(ls_altkey_active_key) ).


  CREATE DATA lr_database_keys TYPE (ls_altkey_active_key-data_table_type).
  ASSIGN lr_database_keys->* TO <ft_database_keys>.

* Map the GUID key to actual database key
  DATA(lo_dac_map) = /bobf/cl_dac_legacy_mapping=>get_instance( iv_bo_key = is_ctx-bo_key
                                                                iv_node_key = is_ctx-node_key ).

  lo_dac_map->map_keys_to_database(
    EXPORTING
      it_bopf_key_table     = it_key
    IMPORTING
      et_database_key_table = <ft_database_keys>
*        et_bopf_key_failed    =
  ).

  READ TABLE <ft_database_keys> ASSIGNING <fs_database_key> INDEX 1.
  IF sy-subrc <> 0.
    et_failed_key = it_key.
    RETURN.
  ELSE.
    IF <fs_database_key>-vbeln IS INITIAL.
      et_failed_key = it_key.
      RETURN.
    ENDIF.
  ENDIF.

* Set update flag to delete
  ls_headerx_change-updateflag = 'D'.

* Delete sales order
  CALL FUNCTION 'BAPI_SALESORDER_CHANGE'
    EXPORTING
      salesdocument         = <fs_database_key>-vbeln
      order_header_inx      = ls_headerx_change
    TABLES
      return                = lt_messages.

  IF line_exists( lt_messages[ type = 'E' ] ).
*   Rollback changes
    CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.

*   Set draft key as failed
    et_failed_key = it_key.

  ELSE.
*   Commit changes
    CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
      EXPORTING
        wait = abap_true.

  ENDIF.

* Create message object
  eo_message = /bobf/cl_frw_factory=>get_message( ).

* Pass messages from BAPI to BOPF framework
  LOOP AT lt_messages INTO DATA(ls_message).
    eo_message->add_message(
      EXPORTING
        is_msg       = VALUE #( msgty = ls_message-type
                                msgid = ls_message-id
                                msgno = ls_message-number
                                msgv1 = ls_message-message_v1
                                msgv2 = ls_message-message_v2
                                msgv3 = ls_message-message_v3
                                msgv4 = ls_message-message_v4 )
    ).

  ENDLOOP.
ENDMETHOD.

To test this functionality open the Fiori App again and search for a Sales Order. Select a Sales Order by using the radio button in front of the data and click the “Delete” button.

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Study Materials

The framework will show a popup in which you’ll need to confirm the actual deletion. Click “Delete” to actually delete the Sales Order.

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Study Materials

Because of the logic we implemented in the deletion method the framework will show the messages generated by the BAPI call.

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Study Materials

No comments:

Post a Comment