Wednesday, February 6, 2013

Enhancing Product Search with Business Role dependent field.

During an implementation of SAP CRM we focus a lot on tuning the system to user requirements. By configuring the UI based on user roles we have the opportunity to hide or show fields as the role requires. This is not always the case for filter values and search fields.

The standard product search in CRM will show the user all materials in the system. For this blog we want to help users to quickly find the right products depending on the role they use in the UI. Not all of these requirements can be solved with authorization so in this blog we describe the steps needed to enhance the standard product search with the field Item Category group and limit the values of this field per Business Role.

Adding the new field to the Product Search


Extending search structure

Using the Genil model browser you can find the corresponding attribute structure for a query. For the product search this is the CRMT_PRIL_QUERY_ADVSEARCH_PROD structure. Via SE11 you can extend this structure using below append.


Adding Search Customizing

We now have the field available in the search structure but we need to specify where the system needs to search for this attribute. This can be done in the IMG:

Customer Relationship Management -> Master Data -> Products -> Basic Settings -> Add Attributes to Search Structure.


Configuration of view

You can now add the field to the view configuration of component PRD01QR. There are two views, Search for the generic product search and SearchHelp for the product search pop-up.

Please note that if you do not deactivate the hiding of fields in customizing the additional field will not be visible in the configuration.

Customer Relationship Management -> UI Framework -> UI Framework Definition -> Design Layer -> Deactivate Hiding of Fields.


Limit the values based on Business Role

Now we see the Item Category Group field on the product search, since this will show all available item category Groups including all SAP standards this is not very user friendly. To limit the results we will enhance this standard component and implement a custom customizing table to restrict values based on the business role. Since the list will be much smaller we will also make it a pick list.

Create Customizing table



Since we want to limit the values based on the business role we create a custom table with the following fields. We have also created a field for SEARCH_FIELD, this makes it possible to use the same table for filtering other fields in the same structure.

As an example for this blog we have filled the table with the following values.

 

Enhance Component, Views and redefine method

We need to enhance the component PRD01QR and also the Views SearchHelp and Search.

To make the field a pick list we have generated a GET_P method and implemented below code:

CASE iv_property.
WHEN if_bsp_wd_model_setter_getter=>fp_fieldtype.
     rv_value = cl_bsp_dlc_view_descriptor=>field_type_picklist.
ENDCASE.


In below class we need to redefine method CHANGE_DQUERY_DEF_EXTENSION.



In method we then filter the values with the following sample implementation:

DATA:
lv_role TYPE string,
lt_prod_src_flt TYPE STANDARD TABLE OF zzip_prd_src_flt,

BEGIN OF ls_src_range,
     search_field TYPE zzip_itm_cat_flt-search_field,
     search_value TYPE RANGE OF zzip_itm_cat_flt-search_value,
END OF ls_src_range,

ls_range_value LIKE LINE OF ls_src_range-search_value,
lt_src_range LIKE STANDARD TABLE OF ls_src_range.

FIELD-SYMBOLS:
<lfs_result> TYPE crms_thtmlb_search_field_info,
<lfs_prod_src_flt> TYPE zzip_itm_cat_flt,
<lfs_src_range> LIKE ls_src_range.

* Call SUPER
CALL METHOD super->change_dquery_def_extension
     CHANGING
     ct_result = ct_result.* Determine Business Role
     lv_role = cl_crm_ui_profile=>get_instance( )->get_profile( ).

* Get Product Search Filter conditions - Based on Business Role
SELECT * FROM zzip_prd_src_flt
    INTO CORRESPONDING FIELDS OF TABLE lt_prod_src_flt
    WHERE business_role = lv_role.

* Continue only if Filter conditions are found!
CHECK sy-subrc = 0.

* Create a range table for each field to be filtered
LOOP AT lt_prod_src_flt ASSIGNING <lfs_prod_src_flt>.
     CLEAR ls_range_value.

     "Read filter range for field     READ TABLE lt_src_range
         ASSIGNING <lfs_src_range>
         WITH KEY search_field = <lfs_prod_src_flt>-search_field.

     "Not found? Then create it! (First filter condition for current field)
     IF sy-subrc NE 0.
         APPEND INITIAL LINE TO lt_src_range
         ASSIGNING <lfs_src_range>.
     ENDIF.

    <lfs_src_range>-search_field = <lfs_prod_src_flt>-search_field.

    "Add filter condition
    ls_range_value-sign = 'I'.
    ls_range_value-option = 'EQ'.
    ls_range_value-low = <lfs_prod_src_flt>-search_value.
    ls_range_value-high = ''.
    APPEND ls_range_value TO <lfs_src_range>-search_value.
ENDLOOP.

* Process Product Search Filter conditions
LOOP AT lt_src_range ASSIGNING <lfs_src_range>.
     "Read field to be filtered
     READ TABLE ct_result
        ASSIGNING <lfs_result>
        WITH KEY field = <lfs_src_range>-search_field.

     "Apply filter
     IF sy-subrc = 0.
         DELETE <lfs_result>-ddlb_options
               WHERE key
               NOT IN <lfs_src_range>-search_value.
     ENDIF.
ENDLOOP.

If you have multiple implementations for filtering, you could move this code to a generic class and calling that class in this method.

Result

The field is shown in the product search and the dropdown list only shows the customized values.


5 comments:

  1. Greetings Mark Peeters,

    First i thank you for the great valuable share of your work :)

    while am trying to implement, everything fine upto "Create Customizing table"

    but after some doublts here, where to implement the GET_P method , in Search view or in SearchHelp view , and in which attribute?

    then in coding part, zzip_itm_cat_flt is a structure or table?

    Kindly clarify on above..thank you :)

    cheers,

    Das

    ReplyDelete
    Replies
    1. Hi Das,

      Sorry for the late reply. You have probably answered your questions already, but just for the blog purpose here the answers.
      We have implmented the filtering in the Searchhelp view (pop-up window, since this is were we need it. The Search view is the standard product search.
      The Get_P needs to be implemented for the attribute you wish to filter. In our case item_cat_group.
      Since this attribute is not a standard one, you some z entities in the coding. ZZIP_ITM_CAT_FLT is a table.

      Hope this clarifies your open points,

      Regards,
      Mark Peeters

      Delete
  2. Hello Mark!

    First of all, thanks for your post. You're building a really great blog altogether.

    I'm facing a similar issue, but in my case it's in the Activity History (BT126S_APPT), which includes the field Status.

    This field shows all the options in the system, and I'd like to restrict it to the options for the User Status Profile assigned by Transaction Type. Is that possible using configuration?

    Or may I enhance the component?

    Thanks!
    Francesc.

    ReplyDelete
  3. Francesc,

    You can enhance the search screen to limit the number of available options, but this would probably not be a logical change.

    The search screen allows you to search for different types of transactions, and should thus contain all userstatusses of all available transactions.

    Also note that there are 2 fields available. As far as I know, the field status contains system statusses and status_common contains user statusses.

    If this is not the case in your system, maybe you can find a note on the topic in the service marketplace.

    Regards,
    Pieter

    ReplyDelete
    Replies
    1. Thanks Pieter.

      I've reviewed the configuration, and displayed both fields. The status field lists only 4 options, while status_common lists many more.

      I think there are some User Status listed in the Status_common field. I'll try to investigate how to limit it.

      Thanks again.
      Regards,
      Francesc.

      Delete