Skip to Content

Most of the time, Customers create its own date-types to assign different dates to business transactions like opportunities. These date-types are assigned to date-profile which in-turn assigned to transaction type.

Lets take an example, Customer has enhanced its opportunity transaction to have ‘Contract Signature Date’ with date-type ZCONTDATE and maintain this date in milestone assignment block in opportunity. Standard SAP CRM doesn’t support business transaction search, based on these custom date-types.

Customer wants to enhance its opportunity search with one of the custom date-type. To achieve the desired functionality, refer the following steps by step procedure:

1. Enhance the Opportunity Search Structure: Create an append structure, for example ZZCRMST_QUERY_OPP_BTIL to opportunity search structure CRMST_QUERY_OPP_BTIL.

Opp_search_struct_enh.png

2.  Enable field in design layer: Being a custom field it wouldn’t be available in search view configuration by default, hence, we need to enable design layer configuration for this field.

     Refer the following location and image to do this change         

     SPRO->Customer Relationship Management->UI Framework->Design Layer->Copy SAP Design Objects

Design_Obj.png

3. Change Opportunity Search View Configuration: As soon as, we enable the design layer configuration for the field, field would start appearing in available field list for search context node in opportunity search view configuration. Move the field from available list to displayed field list in correct view configuration according to your business role etc.

4 Implement the BADI CRM_BADI_RF_Q1O_SEARCH:

After completing step 3, you would be able to see Contract Signature Date in Opportunity search screen and also there would be date popup value help associated with this field as you have used DATUM as type of this field.

If you perform search based on this date field, it wouldn’t work as we still need to write the search logic based on this date field. We could achieve this by implementing the CRM_BADI_RF_Q1O_SEARCH BADI. There could be multiple implementations for this BADI, It executes the correct implementation based on filter value. In our case, we need to enhance opportunity search so will give the BTQOPP as filter value to filter attribute OBJ_IL.

Implement the searchmethod of this BADI.

Important Point:

  1. If there is an implementation exists for this BADI for a particular filter value like BTQOPP (For Opportunity) this would always execute the BADI implementation (not the standard Opportunity search ) for Opportunity search irrespective of the search parameters used in search. Hence, we need to take care for standard search along with our custom field search in BADI implementation.
  2. Dates are stored as timestamp in table scapptseg.

     Refer the sample code below:

   METHOD if_crm_rf_q1o_search~search.

  DATA: ls_return                 TYPE bapiret2.
  DATA: ls_multi_val              TYPE crmt_bsp_search_multi_val.
  DATA: ls_multi_val_temp         TYPE crmt_bsp_search_multi_val.
  DATA: lt_multi_val              TYPE crmt_bsp_search_multi_val_tab.
  DATA: lv_zzcondate_search       TYPE boolean.
  DATA: lv_std_search_req         TYPE boolean.
  DATA: lt_bsp_range              TYPE crmt_bsp_range_tab.
  DATA: lt_guids_temp             TYPE crmt_object_guid_tab.
  DATA: lv_guid                   TYPE crmt_object_guid.
  DATA: lt_guids                  TYPE crmt_object_guid_tab.
  DATA: lt_guidlist               TYPE crmt_bsp_objectkey_tab.
  DATA: ls_guidlist               TYPE crmt_bsp_objectkey.
  DATA: lv_dt_string              TYPE string.
  DATA: lv_time                   TYPE sy-timlo.
  DATA: lv_recs                   TYPE int4.
  DATA: lv_recs_temp              TYPE int4.
  DATA: lv_max_hit                TYPE int4.
  DATA: lv_number                 TYPE int4.


  CONSTANTS:
        c_abap_true               TYPE boolean VALUE 'X',
        c_abap_false              TYPE boolean VALUE '',
        lc_timelow                TYPE sy-timlo VALUE '000000',
        lc_timehigh               TYPE sy-timlo VALUE '235959'.

  FIELD-SYMBOLS:
        <fs_bsp_range>            TYPE crmt_bsp_range.

  lv_zzcondate_search = c_abap_false.   " Flag to check whether search is based on Contract Signature Date or not
  lv_std_search_req = c_abap_true.      " Flag to check whether standard search is required or not
  lv_max_hit = 0.
  lt_multi_val[] = it_multivalues[].
  READ TABLE it_multivalues INTO ls_multi_val
              WITH KEY fieldname = 'ZZCONTDATE'. " IF Contract Sig. Date is there in search parameter then set lv_zzcondate_search to true
  IF sy-subrc = 0.
    lv_zzcondate_search = c_abap_true.
    DELETE lt_multi_val WHERE fieldname = 'ZZCONTDATE'.   " In Standard search Contact Sig. Parameter shouldn't be passed
    DESCRIBE TABLE lt_multi_val LINES lv_recs.

* If only OBJECT_ID is there in search parameter list with no values in its value internal table that means no search parameter is passed.
    IF lv_recs = 1.
      READ TABLE lt_multi_val INTO ls_multi_val_temp WITH KEY fieldname = 'OBJECT_ID'.
      IF sy-subrc = 0.
        DESCRIBE TABLE ls_multi_val_temp-searchvalues LINES lv_recs." ls_multi_val_temp-searchvalues is search parameter value table for that field
        IF lv_recs = 0.
          lv_std_search_req = c_abap_false.
        ENDIF.
      ENDIF.
    ENDIF.
  ENDIF.

  CLEAR lv_recs.
  IF lv_std_search_req = c_abap_true. " Call standard search only if lv_std_search_req is true
    IF lv_zzcondate_search = c_abap_true." Search is based on Contract Sig. date as well some other fields so set the max limit to 1000
      lv_number = 1000.
    ELSE. "Search is only based on standard fields or other than Contact Sig. date
      lv_number = iv_number.
    ENDIF.
    CALL FUNCTION 'CRM_BSP_OIC_1O_SEARCH_FROM_RF'
      EXPORTING
        it_search_tab             = it_search_tab
        it_multivalues            = lt_multi_val
        iv_number                 = lv_number
        iv_extern_call            = 'X'
        iv_select_for_headerlevel = 'X'
      IMPORTING
        et_guidlist               = lt_guidlist
        et_return                 = et_return
      EXCEPTIONS
        date_not_correct          = 1
        no_card_type              = 2
        no_card_no                = 3
        no_program_id             = 4.
    CASE sy-subrc.
      WHEN 1.
        CALL FUNCTION 'BALW_BAPIRETURN_GET2'
          EXPORTING
            type   = 'E'
            cl     = 'CRMN_REPORT'
            number = 141
          IMPORTING
            return = ls_return.
        APPEND ls_return TO et_return.
      WHEN 2.
        CALL FUNCTION 'BALW_BAPIRETURN_GET2'
          EXPORTING
            type   = 'E'
            cl     = 'CRMN_REPORT'
            number = 128
          IMPORTING
            return = ls_return.
        APPEND ls_return TO et_return.
      WHEN 3.
        CALL FUNCTION 'BALW_BAPIRETURN_GET2'
          EXPORTING
            type   = 'E'
            cl     = 'CRMN_REPORT'
            number = 129
          IMPORTING
            return = ls_return.
        APPEND ls_return TO et_return.
      WHEN 4.
        CALL FUNCTION 'BALW_BAPIRETURN_GET2'
          EXPORTING
            type   = 'E'
            cl     = 'CRMN_REPORT'
            number = 142
          IMPORTING
            return = ls_return.
        APPEND ls_return TO et_return.
    ENDCASE.
  ENDIF.

  IF lv_zzcondate_search = c_abap_true. " means search is also based on Contract Sig. date

    REFRESH: lt_guids_temp, lt_guids.
    lt_bsp_range = ls_multi_val-searchvalues.

    LOOP AT lt_bsp_range ASSIGNING <fs_bsp_range>.

* Contract Sign. date is stored as a timestamp in the table so convert date to time table
* For exaple Contact Sig. date  EQ 07/06/2009 would be replaced by 20090706000000 to 20090706235959 range, with BT Option, to cover
* full time of that date.

      IF <fs_bsp_range>-option = 'EQ'.
        lv_dt_string = <fs_bsp_range>-low.
        CONCATENATE lv_dt_string '000000' INTO lv_dt_string.
        <fs_bsp_range>-low = lv_dt_string.
        <fs_bsp_range>-option = 'BT'.

        CLEAR lv_dt_string.
        lv_dt_string = <fs_bsp_range>-low.
        REPLACE '000000' WITH '235959' INTO lv_dt_string.
        <fs_bsp_range>-high = lv_dt_string.
      ELSE.

        IF <fs_bsp_range>-option = 'LT'.
          lv_time = lc_timehigh.
        ELSEIF <fs_bsp_range>-option = 'GT'.
          lv_time = lc_timelow.
        ELSEIF <fs_bsp_range>-option = 'BT'.
          lv_time = lc_timelow.
        ENDIF.

        CLEAR lv_dt_string.
        lv_dt_string = <fs_bsp_range>-low.
        CONCATENATE lv_dt_string '000000' INTO lv_dt_string.
        <fs_bsp_range>-low = lv_dt_string.

        IF NOT <fs_bsp_range>-high IS INITIAL.
          CLEAR lv_dt_string.
          lv_dt_string = <fs_bsp_range>-high.
          CONCATENATE lv_dt_string '235959' INTO lv_dt_string.
          <fs_bsp_range>-high = lv_dt_string.
        ENDIF.

      ENDIF.

    ENDLOOP.

    IF lv_std_search_req = c_abap_false.
* Means no standard parameter is passed and search is only based on Contract Sig. date so get the result UP to MAX_HIT and return

* Fetch Opportunity based on Contract Signature Date
      SELECT a~guid_hi FROM crmd_link AS a INNER JOIN scapptseg AS b ON a~guid_set = b~appl_guid
                       INTO TABLE lt_guids_temp UP TO iv_number ROWS WHERE b~tst_from IN lt_bsp_range AND
                                                        b~appt_type = 'ZCONTDATE' AND
                                                        a~objtype_hi = '05' AND
                                                        a~objtype_set = '30' .
      LOOP AT lt_guids_temp INTO lv_guid.
        APPEND lv_guid TO et_guidlist.
      ENDLOOP.

      RETURN.
    ENDIF.

* Search is based on some standard field as well as Contract Sig. date

* Fetch Opportunity based on Contract Signature Date
    SELECT a~guid_hi FROM crmd_link AS a INNER JOIN scapptseg AS b ON a~guid_set = b~appl_guid
                     INTO TABLE lt_guids_temp WHERE b~tst_from IN lt_bsp_range AND
                                                      b~appt_type = 'ZCONTDATE' AND
                                                      a~objtype_hi = '05' AND
                                                      a~objtype_set = '30'.

    IF sy-subrc = 0.
      SORT lt_guidlist.
      DESCRIBE TABLE lt_guidlist LINES lv_recs.
      DESCRIBE TABLE lt_guids_temp LINES lv_recs_temp.

* Check which table has less number of records, will loop on that table.
      IF lv_recs < lv_recs_temp.
        LOOP AT lt_guidlist INTO ls_guidlist.
          READ TABLE lt_guids_temp TRANSPORTING NO FIELDS WITH KEY table_line = ls_guidlist BINARY SEARCH.
          IF sy-subrc = 0.
            lv_max_hit = lv_max_hit + 1.
            APPEND ls_guidlist TO et_guidlist.
            IF lv_max_hit = iv_number.
              EXIT.
            ENDIF.
          ENDIF.
        ENDLOOP.
      ELSE.
        LOOP AT lt_guids_temp INTO lv_guid.
          READ TABLE lt_guidlist TRANSPORTING NO FIELDS WITH KEY table_line = lv_guid BINARY SEARCH.
          IF sy-subrc = 0.
            lv_max_hit = lv_max_hit + 1.
            APPEND lv_guid TO et_guidlist.
            IF lv_max_hit = iv_number.
              EXIT.
            ENDIF.
          ENDIF.
        ENDLOOP.
      ENDIF.
    ENDIF.

  ELSE."    Search is only based on standard fields or other than Contact Sig. date
    LOOP AT lt_guidlist INTO ls_guidlist.
      APPEND ls_guidlist TO et_guidlist.
    ENDLOOP.

  ENDIF.

ENDMETHOD.

Share your views 🙂

– Ajay

To report this post you need to login first.

5 Comments

You must be Logged on to comment or reply to a post.

  1. Ajaya Kumar Post author

    There is one small limitation with this implementation. Let say, Opportunity Search is performed based on some standard opportunity field(i.e. Description) and along with custom date ( i.e. Contract Signature Date) with max hits 100. With this implementation first it would perform search based on Description and then based on Contract Signature date and then it would prepare the result with common Opportunity records.

    max hits, we have given, is 100, here, we are not sure that 100 records that are coming from standard field search would satisfy the Contract Signature Date condition as well and vice versa. So, while performing the search based on standard search we’re changing the max hits value to 1000 (Assuming these 1000 records would satisfy Contract Signature Date condition) and then out of these 1000 records we find the required records those satisfy the Contract Signature Date condition. This assumption is the limitation here. 

    Performance wise it takes little more time when searching based on standard field as well custom field as two separate searches get executed. In other cases it works perfectly fine.

    (0) 
    1. Harshit Kumar

      There is another way to deal with this issue, instead of doing it on UI which will have the above mentioned limitation and hence should not be used.

      You can extend the one order query class which will take care of everything. Doing everything on UI is not always the best solution.

      Regards,

      Harshit Kumar

      (0) 
      1. Anil Sahoo

        Harshit,

        I referred this document for one of my requirement, related to opportunity search, and it is working fine. Could yo please share, how we can extend one order qery class for this kind of reqirements. Also, if reqirement is addressed by implementation of a badi, does it mean we are doing it on web ui? as you said.

        -Anil

        (0) 
  2. Lukasz Lagodzinski

    Hello, I am afraid this code will not work for the date criteria set in different time zone than UTC. System saves data in UTC, so you cannot simply compare date criteria with UTC timestamp from the table. It should be adjusted to work properly.

    (0) 

Leave a Reply