Wednesday, September 22, 2010

Adding default values to a search screen

Often, users have to search the system for objects such as customers, activities, opportunities, orders, products etc. 

In many cases, users would like to have some values defaulted when the screen opens. This article describes how you can add default values per user group.

In this example, the assignment of the values to the fields is hardcoded. You can of course make the logic more flexible by selecting information from a customizing table, and using this to add the values to the fields.

1. Determine the component and view to be changed.
In the CRM webclient navigate to the search screen to be adjusted, click in a field and press <F2>. Note the component and the viewname.
 
2. Enhance the component and view
First enhance the component and enhance the view. How to enhance a component and a view can be found here.
 
3. Redefine the method DO_INIT_CONTEXT.
Redefine the DO_INIT_CONTEXT Remember to always call the super class. How to redefine a method can be found here.
 
4. Do the coding
First we will be reading the name of the current profile. This enables us to have different default values per profile. After that, in the case statement, we assign default values to one or more profiles.

The trick is to first remove the fields from the screen, and after that insert them with the new values. This way, we will also add the fields if they are not customized, or if the user has deleted them from the screen himself. This also enables us to add a field more then once, resulting in OR statements in the query.
 
Explanation of the coding:
 
* First we do the data declaration

DATA: lv_profile TYPE REF TO IF_CRM_UI_PROFILE,
          lv_profile_name TYPE BSP_DLC_OBJECT_TYPE,
          lv_selection_parameter type ref to if_bol_bo_property_access,
          lr_qs TYPE REF TO cl_crm_bol_dquery_service,
          lv_iterator type ref to if_bol_bo_col_iterator,
          lr_col_params TYPE REF TO if_bol_bo_col,
          lv_value type string,
          lv_cnode type ref to cl_bsp_wd_context_node_asp.
 
* Then we read the current user profile
 
LV_PROFILE = CL_CRM_UI_PROFILE=>GET_INSTANCE( ).
LV_PROFILE_NAME = LV_PROFILE->GET_PROFILE( ).
 
* Then, using the case statement we add different values 
* for different profiles. In case you would like to do 
* the more flexible solution, this is where you 
* would enter the select statement to select 
* the fields and values based on the component, 
* view and profile values.
* We do not want to do this for all profiles.
 
me->set_init_qs( abap_true ). "Initialise the query

CASE LV_PROFILE_NAME.
     when '[PROFILE_NAME]', '[PROFILE_NAME2]', '[...ETC]'.
 

* We read the current information from the 
* screen as well as the query information

* check if QS already exist
lv_cnode = get_dquery_cnode( ).
lr_qs ?= lv_cnode->collection_wrapper->get_first( ).
if lr_qs is not bound.

* add empty QS in order to allow application to prefill values
    assign lv_cnode->('BASE_ENTITY_NAME') to <gs_name>.
    lr_qs = cl_crm_bol_dquery_service=>get_instance(
<gs_name> ).
    lv_cnode->collection_wrapper->add( lr_qs ).
endif.

lr_col_params = lr_qs->get_selection_params( ).

lv_selection_parameter = LR_COL_PARAMS->get_first( ).
IF lv_selection_parameter is bound.
    EH_ONCLEAR( ). "CLEAR the screen.
 

* Delete the fields that we will be adding from the screen to avoid doubles. 
 WHILE lv_selection_parameter is not initial.
  DATA: lv_low type ref to string,
         lv_name type ref to name_komp,
         lv_operator type ref to bapioption.
 

     lv_name ?= lv_selection_parameter->get_property( 'ATTR_NAME' ).
     IF lv_name->* = '[FIELDNAME1]'
     OR lv_name->* = '[FIELDNAME2]'
     OR lv_name->* = '[... etc]'.
         lr_col_params->remove( lv_selection_parameter ).
         lv_selection_parameter = LR_COL_PARAMS->get_current( ).
     ELSE.
         lv_selection_parameter = LR_COL_PARAMS->get_next( ).
     ENDIF.

 ENDWHILE.
ENDIF.
DATA: new_selection_parameter type ref to if_bol_selection_param,
         lv_index type sytabix value 1.
 

* Now we add fields per profile (or several profiles)

CASE LV_PROFILE_NAME.
WHEN [PROFILE_NAME].
    new_selection_parameter =
    lr_qs->insert_selection_param( iv_attr_name = '[FIELDNAME1]'
    iv_sign = 'I'
    iv_option = '[EQ|NE|BT|NB|CP|NP|LT|LE|GT|GE]'
    iv_low = '[VALUE]'
    iv_index = lv_index ). add 1 to lv_index.
    new_selection_parameter =
    lr_qs->insert_selection_param( iv_attr_name = '[FIELDNAME2]'
    iv_sign = 'I'
    iv_option = '[EQ|NE|BT|NB|CP|NP|LT|LE|GT|GE]'
    iv_low = '[VALUE]'
    iv_index = lv_index ). add 1 to lv_index.

WHEN [PROFILE_NAME2], [...ETC].
   new_selection_parameter =
    ...
WHEN OTHERS.
    ...
ENDCASE.

* We call the super class.
call method super->DO_INIT_CONTEXT.
 

ENDMETHOD.

Additional comments
Of course, any variants on this can be implemented. For instance you can calculate a date (for instance one year back) in a search screen for activities. This way you can create a default search screen for activities created in the last year.
You can also read from the BDC. By doing so, you can add for instance the customer number of the last viewed customer into a search screen.
You can also read the username of the current user. This could be used for instance in the search employee view if users would particularly searching for their own user. This could particularly be the case for account management, where they can view their customer portfolio on their own employee screen.
If you wish to have a customizing table where you define the default values, I would recommend the following table layout:
• Component
• View
• Profile
• Fieldname
• Fieldsign
• Fieldoption
• Fieldvalue_low
• Fieldvalue_high

All fields should be part of the key of the table, as you might want to add a field more than once to a certain screen in order to get the 'OR' statement in the searchquery.
You would now be able to implement standard coding that reads the table, and then loops over the found items. First per field, you should delete them from the searchquery, then per line, add the fields including the default values.

5 comments:

  1. Pieter, this is nice but I have another case. Suppose I have a field called Currency which takes the values for instance as EUR or USD etc...
    I can easily write code in the GET_CURRENCY method to default the currency. However, the SAP CRM (we are running 7.0) system when you are creating say an opportunity thinks no value is selected even though I have it set as a default. It has a little message that says "Select a currency" even though the field has the value say USD. I have to actually click the little box to open the dialog and re-select the currency field to make this message go away. Why does this happen and how do I get rid of this message?

    ReplyDelete
  2. Jon,

    If you call the set_currency method after the code you have written, this should remove the message if I am not mistaking...

    So in your case...

    set_currency( EXPORTING ATTRIBUTE_PATH = ATTRIBUTE_PATH
    iterator = iterator
    value = value ).

    Regards,
    Pieter

    ReplyDelete
  3. Pieter ok so currently I have written a get_currency method which calls the super class and then does a simple if condition to set the currency to either USD or EUR. So what you are saying is immediately after this if condition I should call set_currency with those parameters? I will try this when I get back into work. Tomorrow. I originally thought that once you save the opportunity that it would of seen the default value and simply set the currency field. Instead it throws an error message, it still saves the opportunity however there is a small pop up on the top right of the web browser that has a red x that says you must select a currency. Thanks I'll let you know if this works tomorrow

    ReplyDelete
  4. @Pieter Thanks that really did do the trick. I simply called SET_CURRENCY right after the setting of the value and to my surprise the error message was no longer present. Cheers, I owe you a drink :).

    ReplyDelete
  5. Set default values in the parameters of an advanced search page for all users in a specific role:

    Note 2045936 - Default Values for Advanced Search Pages

    ReplyDelete