Skip to Content
Author's profile photo Jerry Wang

Step by step to expose Sales Office and Sales group to My Opportunity – part2

In previous blog, the two fields Sales Office and Sales Group have already been exposed via OData service read operation. In this part I will make the two fields visible in Fiori UI. The final UI would look like below:

/wp-content/uploads/2015/07/clipboard1_746432.png

Step1: find the available extension point in UI to hold the two fields

There is existing extension point in opportunity detail view:

/wp-content/uploads/2015/07/clipboard2_746434.png

As the first step, our aim is just to display the two fields in Fiori UI without considering format requirement. So we just directly bind the two fields to SalesOfficeCode and SalesGroupCode exposed by blog part1.

/wp-content/uploads/2015/07/clipboard3_746435.png

This step is quite easy to do. The UI after this step looks like below. We can notice that for the other three standard fields, always the format <description> + ( + <code> + ) is displayed in UI.

/wp-content/uploads/2015/07/clipboard4_746437.png

The format is defined in xml view as below:

<Text id="salesorganization_Text"
            text="{parts: [{path :'json&gt;/SalesOrganizationDescription'},{path : 'json&gt;/SalesOrganization'}],
                     formatter : 'cus.crm.opportunity.util.Formatter.formatSalesOrganization'}"></Text>

and the simple format function:

formatSalesOrganization : function(SalesOrganizationDescription, SalesOrganizationId){
        var SalesOrganization = "";
        if(SalesOrganizationId != undefined && SalesOrganizationId != "")
        {
         SalesOrganization = SalesOrganizationDescription + " (" + SalesOrganizationId + ")";
        }
        return SalesOrganization;
       },

In next step, we will enable the same format function for the two new fields.

Step2: create another two new fields SalesGroupText and SalesOfficeText to hold the description

The steps are also exactly the same as how we create the two fields SalesGroupCode and SalesOfficeCode in blog1: add the fields in DDIC structure and related Odata Model node:

/wp-content/uploads/2015/07/clipboard5_746441.png

/wp-content/uploads/2015/07/clipboard6_746442.png

After we have these two fields to store description, we can write the logic to get description by code.

All READ-related methods need to be enhanced with this logic.

a. redefine method OPPORTUNITIES_GET_ENTITYSET and paste the following source code:

METHOD opportunities_get_entityset.
    DATA: lv_otype     TYPE otype.
    FIELD-SYMBOLS: <opportunity> LIKE LINE OF et_entityset.
    CALL METHOD super->opportunities_get_entityset
      EXPORTING
        iv_entity_name           = iv_entity_name
        iv_entity_set_name       = iv_entity_set_name
        iv_source_name           = iv_source_name
        it_filter_select_options = it_filter_select_options
        is_paging                = is_paging
        it_key_tab               = it_key_tab
        it_navigation_path       = it_navigation_path
        it_order                 = it_order
        iv_filter_string         = iv_filter_string
        iv_search_string         = iv_search_string
      IMPORTING
        et_entityset             = et_entityset.
* Note: the single read below is not efficient from performance point of view.
* In production code you can use cl_crm_orgman_interface=>READ_TEXT_MULTI to improve performance
    LOOP AT et_entityset ASSIGNING <opportunity>.
      IF <opportunity>-sales_group IS NOT INITIAL.
        lv_otype = <opportunity>-sales_group+0(1).
        CALL METHOD cl_crm_orgman_interface=>read_text_single
          EXPORTING
            otype        = lv_otype
            objid        = <opportunity>-sales_group+2(8)
          IMPORTING
            display_text = <opportunity>-sales_group_txt.
      ENDIF.
      IF <opportunity>-sales_office IS NOT INITIAL.
        lv_otype = <opportunity>-sales_office+0(1).
        CALL METHOD cl_crm_orgman_interface=>read_text_single
          EXPORTING
            otype        = lv_otype
            objid        = <opportunity>-sales_office+2(8)
          IMPORTING
            display_text = <opportunity>-sales_office_txt.
      ENDIF.
    ENDLOOP.
  ENDMETHOD.

b. create a new private method FILL_SALES_TEXT with the following signature:

/wp-content/uploads/2015/07/clipboard7_746443.png

source code:

METHOD fill_sales_text.
    FIELD-SYMBOLS: <opp_header>      TYPE cl_crm_opportunity_mpc=>ts_opportunity,
                   <opp_expand>      TYPE crmt_odata_oppt_hdr_expanded,
                   <opp>             TYPE any,
                   <salegroup_text>  TYPE crmt_odata_oppt_header-sales_group_txt,
                   <saleoffice_text> TYPE crmt_odata_oppt_header-sales_office_txt,
                   <salegroup_code>  TYPE crmt_odata_oppt_header-sales_group,
                   <saleoffice_code> TYPE crmt_odata_oppt_header-sales_office.
    DATA: lv_otype     TYPE otype.
    IF iv_called_by_expand = abap_false.
      ASSIGN cr_entity->* TO <opp_header>.
      ASSIGN <opp_header> TO <opp>.
    ELSE.
      ASSIGN cr_entity->* TO <opp_expand>.
      ASSIGN <opp_expand> TO <opp>.
    ENDIF.
    ASSIGN COMPONENT 'SALES_GROUP' OF STRUCTURE <opp> TO <salegroup_code>.
    ASSIGN COMPONENT 'SALES_GROUP_TXT' OF STRUCTURE <opp> TO <salegroup_text>.
    ASSIGN COMPONENT 'SALES_OFFICE' OF STRUCTURE <opp> TO <saleoffice_code>.
    ASSIGN COMPONENT 'SALES_OFFICE_TXT' OF STRUCTURE <opp> TO <saleoffice_text>.
    IF <salegroup_code> IS NOT INITIAL.
      lv_otype = <salegroup_code>+0(1).
      CALL METHOD cl_crm_orgman_interface=>read_text_single
        EXPORTING
          otype        = lv_otype
          objid        = <salegroup_code>+2(8)
        IMPORTING
          display_text = <salegroup_text>.
    ENDIF.
    IF <saleoffice_code> IS NOT INITIAL.
      lv_otype = <saleoffice_code>+0(1).
      CALL METHOD cl_crm_orgman_interface=>read_text_single
        EXPORTING
          otype        = lv_otype
          objid        = <saleoffice_code>+2(8)
        IMPORTING
          display_text = <saleoffice_text>.
    ENDIF.
  ENDMETHOD.

c. in DPC_EXT’s method /IWBEP/IF_MGW_APPL_SRV_RUNTIME~GET_ENTITY, call the FILL_SALES_TEXT:

METHOD /iwbep/if_mgw_appl_srv_runtime~get_entity.
    CALL METHOD super->/iwbep/if_mgw_appl_srv_runtime~get_entity
      EXPORTING
        iv_entity_name          = iv_entity_name
        iv_entity_set_name      = iv_entity_set_name
        iv_source_name          = iv_source_name
        it_key_tab              = it_key_tab
        it_navigation_path      = it_navigation_path
        io_tech_request_context = io_tech_request_context
      IMPORTING
        er_entity               = er_entity
        es_response_context     = es_response_context.
    CASE iv_entity_name.
      WHEN 'Opportunity'.
        CALL METHOD fill_sales_text
          EXPORTING
            iv_called_by_expand = abap_false
          CHANGING
            cr_entity           = er_entity.
      WHEN OTHERS.
    ENDCASE.
  ENDMETHOD.

in DPC_EXT’s method /IWBEP/IF_MGW_APPL_SRV_RUNTIME~GET_EXPANDED_ENTITY, call the method as well:

METHOD /iwbep/if_mgw_appl_srv_runtime~get_expanded_entity.
    CALL METHOD super->/iwbep/if_mgw_appl_srv_runtime~get_expanded_entity
      EXPORTING
        iv_entity_name           = iv_entity_name
        iv_entity_set_name       = iv_entity_set_name
        iv_source_name           = iv_source_name
        it_key_tab               = it_key_tab
        it_navigation_path       = it_navigation_path
        io_expand                = io_expand
        io_tech_request_context  = io_tech_request_context
      IMPORTING
        er_entity                = er_entity
        es_response_context      = es_response_context
        et_expanded_clauses      = et_expanded_clauses
        et_expanded_tech_clauses = et_expanded_tech_clauses.
    CASE iv_entity_name.
      WHEN 'Opportunity'.
        CALL METHOD fill_sales_text
          EXPORTING
            iv_called_by_expand = abap_true
          CHANGING
            cr_entity           = er_entity.
    ENDCASE.
  ENDMETHOD.

Once this step is done, you could test your enhanced Odata service read operation and ensure you could see both code and description of SalesGroup and SalesOffice in response.

/wp-content/uploads/2015/07/clipboard8_746447.png

Step3: change the binding of extension fields

Just change the binding path from code to the converted value formatted by the formatter.

<core:FragmentDefinition xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:ui="sap.ui.layout">
   <ui:form.SimpleForm id="salesAreaInfoTabContentBottomExtension">
        <ui:content>
         <Label id="SalesOfficeLabel" text="Sales Office">
         </Label>
         <Text id="SalesOffice" text="{parts: [{path :'json>/SalesOfficeText'},{path : 'json>/SalesOfficeCode'}],
                 formatter : 'cus.crm.opportunity.CRM_OPPRTNTYExtension.UtilExtension.Util.formatSalesOffice'}"></Text>
       
         <Label id="SalesGroupLabel" text="Sales Group">
         </Label>
         <Text id="SalesGroup" text="{parts: [{path :'json>/SalesGroupText'},{path : 'json>/SalesGroupCode'}],
                 formatter : 'cus.crm.opportunity.CRM_OPPRTNTYExtension.UtilExtension.Util.formatSalesOffice'}"></Text>
        </ui:content>
        </ui:form.SimpleForm>
</core:FragmentDefinition>

The complete UI code could be found in github: https://github.com/i042416/testOpportunityExtension/ with commit id: 7489bd487cc40fff1a9dd3b9d3683036961a1061

The complete backend source code could be found from attachment.

Assigned Tags

      Be the first to leave a comment
      You must be Logged on to comment or reply to a post.