Wednesday, August 23, 2017

Dynamic BI Reports in WebUI

In a previous blog (Graphical BI Reports in SAP CRM) we showed you the powerful option of displaying BI reports in SAP CRM WebUI. In order to realise this, it was required to enhance method WD_USAGE_INITIALIZE. In this method, the URL for retrieving the BI report was constructed.


Now, imagine a scenario in which you would like to call BI reports for Tasks. In the WebUI you usually  have a search-result screen in which you can search for tasks and select an individual task from the result list. With every different task you select from the result list, the 'focus' shifts. In this scenario WD_USAGE_INITIALIZE would only be called once at the beginning during initialization. So, also the URL contruction for retrieving the BI report, would occur only once eventhough the focus (the selected task) can change multiple times. So if we construct our BW report URL in WD_USAGE_INITIALIZE, it will be static in the sense that if we change the focus and select another task from our result list, the url parameters will not change accordingly. Imagine having parameters in the link that have a variable value, based on the specific BTAdmnH data, then whenever another task is selected, the link should be recontstructed and updated. Otherwise you will still be retrieving the BI report related to the first opened task.

The solution

To overcome the problem described above, we will creater a new value node called ‘DYNBIREPORT’ in the component controller of component BT125H_TASK. This node will contain the value attributes corresponding to the parameters in the URL (ADDPARAMETER, REPID, BISYSTEM). It is important to use these parameter names exactly because of the data binding we are going to use.

This context node we can update on Task level. This will be done in the ON_NEW_FOCUS method. But first we should bind our context node with the BIREPORT node from the GSBIRP component in method WD_USAGE_INITIALIZE (see also Graphical BI Reports in SAP CRM):
  WHEN 'CU_BI_<USAGE_NAME>'.           
               CREATE DATA lr_line_ref.
               CREATE OBJECT lr_node EXPORTING iv_data_ref = lr_line_ref. 
              ztyped_context->dynbireport->collection_wrapper->add( lr_node ).                
                iv_usage->bind_context_node(  iv_controller_type  =            cl_bsp_wd_controller=>co_type_component
                iv_name             = iv_usage->usage_name
                iv_target_node_name = 'DYNBIREPORT' " Node of the MAIN component                                                                            iv_node_2_bind      = 'BIREPORT' ). " Node of the embedded component
    CATCH cx_root.            

Now, we have our context node binding. The node BIREPORT in component GSBIRP is bound to our new context node. We implement the ON_NEW_FOCUS method for the created context value node. In this method the updated URL will be constructed: 

  method ON_NEW_FOCUS.
      DATA: lv_collection             TYPE REF TO if_bol_bo_col,  
entity                    TYPE REF TO cl_crm_bol_entity.    
   DATA: lr_wc_context           TYPE REF TO cl_bsp_wd_context_node.    
   DATA: lr_text_node             TYPE REF TO cl_gstext_text_cn00.    
   DATA: lr_url                          TYPE REF TO zcl_bi_if.    
   DATA: lv_bi_param                     TYPE string.    
   DATA: lv_parameter1                 TYPE string,               
               lv_parameter2                  TYPE string,               
               lv_parameter3                  TYPE string. 
*   get collection of dependent nodes    
      entity ?= focus_bo.    
     CHECK entity IS BOUND. 
    "Get parameter values (e.g. from BOL via entity ).    
    <arbitrary logic to retrieve parameter values> 
    lr_url->add_param( iv_param = 'PARAMETER1' iv_value = lv_parameter1 ).    
    lr_url->add_param( iv_param = 'PARAMETER2' iv_value = lv_org_unit ).    
    lr_url->add_param( iv_param = 'PARAMETER3' iv_value = lv_employee_id ). 
    lv_bi_param = lr_url->get_param( ). 
    DATA(lr_dynbirep_url) = me->collection_wrapper->get_current( ).    
    lr_dynbirep_url->set_property( exporting IV_ATTR_NAME = 'REPID' 
                         iv_value     =    '<REPORT_NAME>' ).    
    lr_dynbirep_url->set_property( exporting   IV_ATTR_NAME = 'BISYSTEM' 
                                    iv_value = '<SYSTEM_ALIAS>' ).                               
    lr_dynbirep_url->set_property( exporting IV_ATTR_NAME = 'ADDPARAMETER' 
                                         iv_value =         lv_bi_param ).   

Now we need to enhance the component controller class in method CONNECT_NODES. In this method we ensure that whenever a new task is selected the ON_NEW_FOCUS event is triggered:

    IF btadminh IS BOUND AND        me->dynbireport IS BOUND.       
       coll_wrapper = btadminh->get_collection_wrapper( ).       
       SET HANDLER me->dynbireport->on_new_focus FOR coll_wrapper ACTIVATION iv_activate.     

In the method CREATE_DYNBIREPORT we need to add the following to correctly set the focus when the node is corrected:
  method CREATE_SPMBIREPORT.      
DATA:       model                TYPE REF TO if_bsp_model,        
coll_wrapper    TYPE REF TO cl_bsp_wd_collection_wrapper,        
entity                 TYPE REF TO cl_crm_bol_entity,           
entity_col          TYPE REF TO if_bol_entity_col.    
model owner->create_model(
        class_name     = 'ZL_BT125H_T_BSPWDCOMPONEN_CN05'
        model_id       = 'DYNBIREPORT' ).
    DYNBIREPORT ?= model.     CLEAR model.      
coll_wrapper =      BTADMINH->get_collection_wrapper( ).     
        entity ?= coll_wrapper->get_current( ).       
  CATCH cx_sy_move_cast_error.     
IF entity IS BOUND.      
    DYNBIREPORT->on_new_focus(  focus_bo entity ).     

So in short...

In order to retrieve the BI report whenever the focus shifts, we build up the URL dynamically by:
  1. Creating a new context node in our component to hold the URL parameters.
  2. Binding our new context node with the BIREPORT node from component GSBIRP.
  3. Implement the ON_NEW_FOCUS method to retrieve the new parameter values whenever the focus shifts.
  4. Modify the CONNECT_NODES method to ensure the ON_NEW_FOCUS_METHOD is called when the corresponding event has been triggered.
  5. Modify the CREATE_DYNBIREPORT node to initialize the new focus properly.