Enterprise Resource Planning Blogs by Members
Gain new perspectives and knowledge about enterprise resource planning in blog posts from community members. Share your own comments and ERP insights today!
cancel
Showing results for 
Search instead for 
Did you mean: 
geert-janklaps
Active Contributor

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.



Lock entry when creating a draft instance:



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:



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.



Lock entries when creating a draft instance:


Implementing deletion logic


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



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.



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



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



In the next part we'll cover the most essential part of our application, creating and changing Sales Orders.

 

Quick navigation


2 Comments
Labels in this area