Вы находитесь на странице: 1из 37

An example of End to End extension on CRM Fiori application

part1
June 18, 2015 | 1,512 Views |

Jerry Wang

more by this author


SAP Fiori
SAP Fiori for SAP CRM cachecrm fioricrudendtoend extensionextensibilityextensionfiori

share 0
share 0
tweet
share 0

Follow

Step1 Create extension project using transaction code SEGW


Step2 Register your extension service in gateway ( frontend ) system
Step3 Enhance OData model
Step4 finish data provider class enhancement

These series of blogs give a step-by-step instructions about how to extend


SAP standard CRM Fiori application in an End-to-End way.
The CRM application My Opportunity is used as example. End-to-End
means:
Enhance the standard OData model to fulfill customer specific business requirement which could not
be covered by standard.

Technically, it means new extension fields are enhanced upon related standard DDIC structures.
The Create, Read, Update and Delete operations are supported upon those extension fields.

Enhance the runtime OData service implementation to manipulate on the OData extensions done by
step1.
Consume the extension fields exposed enhanced OData service done by step1 & step2 in UI.

This article will cover step1 & step2. The involved scenario is:
1. enhance a new field in OData model to store the user name who creates
the current Opportunity currently being read.
2. enhance the OData services read operation, so that this extension field is
filled with correct value in the backend.

Step1 Create extension project using transaction


code SEGW
This extension project is used to store all kinds of extensions on standard
gateway project CRM_OPPORTUNITY

choose Redefine->OData Service(SAP GW):

Select standard project: CRM_OPPORTUNITY


Just select all entities and click Finish button.

Generate all Runtime artifacts, ensure successful generation:


Use default proposed name or change according to your own naming
convention. Write down your technical service Name, here is
ZJERRY_DEMO_SRV:
Step2 Register your extension service in
gateway ( frontend ) system
Till now we havent done any extension yet, which means all the CRUD
operations on Opportunity should work.
Log on to your gateway system, use transaction code
/IWFND/MAINT_SERVICE, click Add Service button:
Search by the technical service name which you got in step 1:

Add the found technical service, then registration is done. Now you could test
your service via gateway client.

Launch gateway client via this button:


Test whether metadata retrieve works.

Test whether read operation on given Opportunity instance specified by guid


also works or not. Just replace the standard service name
CRM_OPPORTUNITY with your own one: ZJERRY_DEMO_SRV:
Step3 Enhance OData model
Suppose we need to extend Opportunity header structure with new field which
stores the information who has created the opportunity.
The first step is to figure out which DDIC structure you need to extend. In this
example, since I need to extend Opportunity header, so I just look into data
type TS_OPPORTUNITY defined in Opportunity MPC ( metadata provider
class ),

types: TS_OPPORTUNITY type CRMT_ODATA_OPPT_HEADER.


If you need to do extension on any part of Opportunity, for example on product
level, then use the structure defined in TS_OPPORTUNITYPRODUCT
instead.
Create a new extension field EXT_CREATED_BY via append structure.
go to tcode SEGW, extend the OData model as well. Double click on the
folder icon Properties of Opportunity node, create a new field:

Specify the field name, field type and the most important is the ABAP field
name EXT_CREATED_BY must be bound to this field in model.
Once done, regenerate the runtime artifacts by clicking the icon Generate
Runtime Objects in toolbar.
Till now your model enhancement is done.
<Note> every time you have make modifications on your OData model in
backend system, to make it take effect, you have to clear the cache in
both gateway and backend system separately, or else when your model
is accessed in the runtime, still the old structure stored in cache table is
used. You could not see the new field you just created.
Tcode to clear cache in frontend system: /IWFND/CACHE_CLEANUP
Tcode to clear cache in backend system: /IWBEP/CACHE_CLEANUP

Step4 finish data provider class enhancement


In this step, we must enhance the original OData service implementation:
fetch the created by information of a given Opportunity being read and fill it to
extension field EXT_CREATED_BY.
open your DPC_EXT class, and redefine method GET_ENTITY, as which will
be called when an opportunity is read via its guid.
<Note> Please always make changes on the DPC_EXT class. All your
changes on DPC class will get lost every time you click Generate Runtime
Objects button in tcode SEGW.
paste the source code below to method implementation:
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.
* Customer extension could be put here
CASE iv_entity_name.
WHEN 'Opportunity'.
* Extension logic on Opportunity header
CALL METHOD fill_created_by
EXPORTING
it_key_tab = it_key_tab
CHANGING
cr_entity = er_entity.
WHEN OTHERS.
ENDCASE.
ENDMETHOD.
And source code for private method fill_created_by:
method FILL_CREATED_BY.

FIELD-SYMBOLS: <s_guid> LIKE LINE OF it_key_tab,


<opp_header> TYPE cl_crm_opportunity_mpc=>ts_opportunity,

<created_by> TYPE sy-uname.

DATA: lv_created_by TYPE crmd_orderadm_h-created_by.

ASSIGN cr_entity->* TO <opp_header>.

ASSIGN COMPONENT 'EXT_CREATED_BY' of STRUCTURE <opp_header> TO <created_by>.

CHECK sy-subrc = 0.

READ TABLE it_key_tab ASSIGNING <s_guid> WITH KEY name = 'Guid'.

CHECK sy-subrc = 0.

SELECT SINGLE created_by INTO lv_created_by FROM crmd_orderadm_h WHERE guid =


<s_guid>-value.

IF sy-subrc = 0.

<created_by> = lv_created_by.

ENDIF.

endmethod.
The signature of method:
methods FILL_CREATED_BY
importing
!IT_KEY_TAB type /IWBEP/T_MGW_NAME_VALUE_PAIR
changing
!CR_ENTITY type ref to DATA .
Then test in gateway client: the extension field is filled with correct data in the
runtime.

In the next blog, it will introduce how to consume this extension field in Fiori
UI.
An example of End to End extension on CRM Fiori application
part2
June 19, 2015 | 706 Views |

Jerry Wang

more by this author


SAP Fiori
extensionpointexthookfiorifiori extensibilityfiori uihooksimpleform

share 0
share 0
tweet
share 0

Follow

Aim of this blog


Solution
Next step

In previous blog An example of End to End extension on CRM Fiori application part1:
we have already enhanced the standard CRM OData Model, Opportunity, by adding a new field to
store creator of a given opportunity and expose it via enhanced OData service implementation.
Aim of this blog
In this part we will consume this extension field extCreatedBy in Fiori UI.
It is only possible for you to put your extension fields to UI area where an ExtensionPoint exists,
which is delivered by SAP.

Since I need to put the new field under the last field Log of Changes, below screenshot is original
UI before we extend:
The screenshot below is what we expect to achieve after this blog:? the enhanced UI with extension
field:
Solution
Find out its ExtensionPoint in xml view:

The idea here is you need to create a new view fragment, and put your extension field into this
fragment, which is embedded into the standard opportunity view via ExtensionPoint.
The complete source code of extCreatedBy.fragment.xml:
<core:FragmentDefinition xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:ui="sap.ui.layout">
<ui:form.SimpleForm id="opportunityExtension">
<ui:content>
<Label id="opportunityCreatedByLbael" text="Created By">
</Label>
<Text id="opportunityCreatedByValue" text="{json>/extCreatedBy}"></Text>
</ui:content>
</ui:form.SimpleForm>
</core:FragmentDefinition>
Finally, specify the OData service url to your own OData service implemented via the step
mentioned in previous blog:

The complete source code of frontend part could be found in


github: https://github.com/i042416/testOpportunityExtension
commit id:

Last but not least, since now we have consumed the extension field in Fiori UI, not simply via
gateway client in previous blog, so we need to ensure that the extension field could successfully be
read out in all scenarios.
It means the following two methods should be redefined now ( for the first method
/IWBEP/IF_MGW_APPL_SRV_RUNTIME~GET_ENTITY, it is already redefined in previous blog ).
source code are listed below:
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.
* Customer extension could be put here
CASE iv_entity_name.
WHEN 'Opportunity'.
* Extension logic on Opportunity header
CALL METHOD fill_created_by
EXPORTING
it_key_tab = it_key_tab
iv_called_by_expand = abap_false
CHANGING
cr_entity = er_entity.
WHEN OTHERS.
ENDCASE.
ENDMETHOD.
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'.
* Extension logic on Opportunity header
CALL METHOD fill_created_by
EXPORTING
it_key_tab = it_key_tab
iv_called_by_expand = abap_true
CHANGING
cr_entity = er_entity.
WHEN OTHERS.
ENDCASE.
ENDMETHOD.
method FILL_CREATED_BY.
FIELD-SYMBOLS: <s_guid> LIKE LINE OF it_key_tab,
<opp_header> TYPE cl_crm_opportunity_mpc=>ts_opportunity,
<opp_expand> TYPE CRMT_ODATA_OPPT_HDR_EXPANDED,
<created_by> TYPE sy-uname.
DATA: lv_created_by TYPE crmd_orderadm_h-created_by.
IF iv_called_by_expand = abap_false.
ASSIGN cr_entity->* TO <opp_header>.
ASSIGN COMPONENT 'EXT_CREATED_BY' of STRUCTURE <opp_header> TO <created_by>.
ELSE.
ASSIGN cr_entity->* TO <opp_expand>.
ASSIGN COMPONENT 'EXT_CREATED_BY' of STRUCTURE <opp_expand> TO <created_by>.
ENDIF.
READ TABLE it_key_tab ASSIGNING <s_guid> WITH KEY name = 'Guid'.
CHECK sy-subrc = 0.
SELECT SINGLE created_by INTO lv_created_by FROM crmd_orderadm_h WHERE guid =
<s_guid>-value.
IF sy-subrc = 0.
<created_by> = lv_created_by.
ENDIF.
endmethod.
Signature of private method FILL_CREATED_BY:
methods FILL_CREATED_BY
importing
!IT_KEY_TAB type /IWBEP/T_MGW_NAME_VALUE_PAIR
!IV_CALLED_BY_EXPAND type ABAP_BOOL
changing
!CR_ENTITY type ref to DATA .
In order to make FILL_CREATED_BY used by both read redefined method, I add a new importing
parameter iv_called_by_expand to differentiate its used scenario, since for read and read_expand
scenario, the exporting parameters structure are different. The fill_created_by should react
accordingly.

Next step
In next blog I will introduce how to persist the extension field value maintained by end user in Fiori UI
to backend database table, that is, to support the update operation on extension field.
An example of End to End extension on CRM Fiori application
part3
June 20, 2015 | 605 Views |

Jerry Wang

more by this author


SAP Fiori
aetcrudcustom fielddatabase tableeewextensionfiori

share 0
share 0
tweet
share 0

Follow

Aim of this blog


Step1 create new field in Opportunity edit view
Step2 Enhance controller javascript code to also send the value of extension field to backend
Step3 enhance OData service implementation so that extension field could be persisted in database
table
Step4 adapt the read operation implementation to load the extension field value from DB table
Last Part

In previous blogs:

An example of End to End extension on CRM Fiori application part1


An example of End to End extension on CRM Fiori application part2

I introduced how to create a new extension field on Opportunity OData model, expose it via OData service and
consume it in Fiori UI.

Aim of this blog


In this blog we will go a step further: we will allow end user to manually type some value in this extension
field and persist the value to the database table in CRM backend server, when save button is clicked.

Requirement: The value must be saved into a new corresponding field in database table CRMD_OPPORT_H.
Here below is the UI so far we get:

There is an extension field done on Opportunity detail view.


When the detail is rendered, the value of the extension field is fetched from database table
CRMD_ORDERADM_H, field CREATED_BY.
Step1 create new field in Opportunity edit view
We notice that once edit button in toolbar is clicked, we will reach opportunity edit view. Now the extension
field is only available in detail view ( read only there ), so we need also to add the extension field into edit
view.
Use the similar approach in part2 blog to bring the extension field to edit view. Currently we didnt do any
binding to this field in edit value, just use a hard code value Jerry
<core:FragmentDefinition xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:ui="sap.ui.layout">
<ui:form.SimpleForm id="OpportunityEditExtension" minWidth="1024"
maxContainerCols="2" editable="true" layout="ResponsiveGridLayout"
labelSpanL="3" labelSpanM="3" emptySpanL="4" emptySpanM="4" columnsL="1"
columnsM="1" class="editableForm" >
<ui:content>
<Label id="opportunityCreatedByLbael" text="Created By">
</Label>
<Input id="createdByInput" value="Jerry"></Input>
</ui:content>
</ui:form.SimpleForm>
</core:FragmentDefinition>
After this step the edit UI looks like below:
Step2 Enhance controller JavaScript code to
also send the value of extension field to backend
Check the extension-point we could use to put the extension field value to the request sent to backend via
searching keyword extHook:

Implement the extension-point by creating a new controller extension and paste the following source code:
sap.ui.controller("cus.crm.opportunity.CRM_OPPRTNTYExtension.view.extS4", {
onInit : function () {
//Execute onInit for the base class BaseMasterController
sap.ca.scfld.md.controller.BaseDetailController.prototype.onInit.call(this);
},
extHookAddCustomHeaderFields : function(oEntry) {
// "createdByInput" is the id for extension UI element defined in extS4CreatedBy.fragment.xml
var oExtensionControl = this.byId("createdByInput");
// get the current value that end user has entered in extension field in detail view
var extensionValue = oExtensionControl.getValue();
oEntry.extCreatedBy = extensionValue;
}
});
Now we could test in Edit UI. Once you type something in Created By field and click save button, you should
see your input is successfully passed to backend via http post operation. Of course so far it will not take effect
since the backend support for this extension field is not done yet. We will finish it in next step.
Step3 enhance OData service implementation so
that extension field could be persisted in
database table
First we have to identify which method in the backend needs to be enhanced. Set a breakpoint on OData
service provider class: method PATCH_ENTITY and click save button, breakpoint is triggered:

The user input in Fiori UI is already successfully passed to backend by gateway framework. Now it is our turn
to pass it to one order related function module to persist it into database table.
as a result, redefine method /IWBEP/IF_MGW_APPL_SRV_RUNTIME~PATCH_ENTITY in your own
DPC_EXT class.
In this method, the idea is, to store the extension value passed from Fiori UI via gateway framework ( the field
CRMT_ODATA_OPPT_HEADER-EXT_CREATED_BY ) to Opportunity service implementations internal
buffer maintained in CL_CRM_OPPORTUNITY_IMPL=>GT_OPPORT_H ( which is an internal table with
line structure CRMT_OPPORT_H_COM. And we need also to create a new field in database table
CRMD_OPPORT_H to persist the value. To summarize, we need two new extension fields besides the one
created in the first blog.

You can manually create them separately, or use some extension tool like EEW or AET ( application extension
tool ).
You may look at these two wikis regarding extension field creation approach in CRM:

Step by step to create new fields on UI via Application Extension Tool


How to create new fields: AET Vs Custom Development

In this blog, I use AET so the field name is automatically determined by the tool: FLD00008B.
The final source code of patch_entity:
METHOD /iwbep/if_mgw_appl_srv_runtime~patch_entity.
CALL METHOD super->/iwbep/if_mgw_appl_srv_runtime~patch_entity
EXPORTING
iv_entity_name = iv_entity_name
iv_entity_set_name = iv_entity_set_name
iv_source_name = iv_source_name
io_data_provider = io_data_provider
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.
FIELD-SYMBOLS: <header_from_ui> TYPE crmt_odata_oppt_header ,
<header_buffer> TYPE crmt_opport_h_com,
<value_ui> TYPE crmt_odata_oppt_header-ext_created_by,
<value_db> TYPE crmt_opport_h_com-fld00008b,
<input_fields> LIKE LINE OF
cl_crm_opportunity_impl=>gt_input_fields.
DATA: ls_input TYPE crmt_input_field_names .
CHECK iv_entity_name = 'Opportunity'.
ASSIGN er_entity->* TO <header_from_ui>.
CHECK sy-subrc = 0.
READ TABLE cl_crm_opportunity_impl=>gt_opport_h ASSIGNING <header_buffer> INDEX 1.
CHECK sy-subrc = 0.
ASSIGN COMPONENT 'EXT_CREATED_BY' OF STRUCTURE <header_from_ui> TO <value_ui>.
CHECK sy-subrc = 0.
ASSIGN COMPONENT 'FLD00008B' OF STRUCTURE <header_buffer> TO <value_db>.
CHECK sy-subrc = 0.
<value_db> = <value_ui>.
READ TABLE cl_crm_opportunity_impl=>gt_input_fields ASSIGNING <input_fields>
WITH KEY objectname = 'OPPORT_H'.
CHECK sy-subrc = 0.
* Notify One order function module that we want to persist the value of this field
ls_input-fieldname = 'FLD00008B'.
INSERT ls_input INTO TABLE <input_fields>-field_names.
ENDMETHOD.
Now we could test the save operation on this extension field:

Once we click save button, the value is persisted to database table as expected.
Step4 adapt the read operation implementation
to load the extension field value from DB table
This step is quite simple, just make small adaptions in private method FILL_CREATED_BY

Before: ( in blog 2 )
DATA: lv_created_by TYPE crmd_orderadm_h-created_by.
SELECT SINGLE created_by INTO lv_created_by FROM crmd_orderadm_h WHERE guid = <s_guid>-
value.
IF sy-subrc = 0.
<created_by> = lv_created_by.
ENDIF.
After:
DATA: lv_created_by TYPE crmd_opport_h-fld00008b.
SELECT SINGLE fld00008b INTO lv_created_by FROM crmd_opport_h WHERE guid = <s_guid>-
value.
IF sy-subrc = 0.
<created_by> = lv_created_by.
ENDIF.
finally replace the hard code value in step1 with model binding, and thats all.

Now the extension field could support both read and update function.

Complete frontend source code could be found in


github: https://github.com/i042416/testOpportunityExtension/commits/master
commit id:

Last Part
In next blog, the steps how to enable the creation on extension field will be introduced.

An example of End to End extension on CRM Fiori application


part4
June 24, 2015 | 322 Views |

Jerry Wang

more by this author


SAP Fiori
Mobile crudcrud operationscustom developmentextensionfiorifiori appsfiori extensibility
share 0
share 0
tweet
share 0

Follow

Step1 add new extension field in creation UI view


Step2 Create sub class based on CL_CRM_OPPORTUNITY_IMPL
Step3 Redefine /IWBEP/IF_MGW_APPL_SRV_RUNTIME~CREATE_DEEP_ENTITY

This blog is the last part of the extension series. In the previous three blogs, we have already
created extension field on the UI of CRM Fiori application My Opportunities:

An example of End to End extension on CRM Fiori application part1


An example of End to End extension on CRM Fiori application part2
An example of End to End extension on CRM Fiori application part3
That means, the read and update operation on extension fields are already supported. In this blog,
we will finish the left part: support creation operation as well. The UI after enhancement would look
like below:

Step1 add new extension field in creation


UI view
The logic is exactly the same as how we have added the extension in detail view and edit view. To
avoid duplication the source code is not listed here:

See complete UI source code from github: https://github.com/i042416/testOpportunityExtension

Step2 Create sub class based on


CL_CRM_OPPORTUNITY_IMPL
In my blog, the sub class is ZCL_CRM_OPPORTUNITY_IMPL_SUB. Only one method below needs
redefinition.
The purpose of this redefined method are to populate necessary information regarding extension
field passed from UI and store them in internal table et_customer_h and et_input_fields, which will
be used in function module CRM_ORDER_MAINTAIN for opportunity creation.
METHOD create_oppt_header_input.
CALL METHOD super->create_oppt_header_input
EXPORTING
is_oppt_exp_hdr = is_oppt_exp_hdr
iv_handle = iv_handle
IMPORTING
ev_relationid = ev_relationid
et_opport_h = et_opport_h
et_input_fields = et_input_fields
ev_object_guid = ev_object_guid
et_orderadm_h = et_orderadm_h
et_pricing = et_pricing
et_partner = et_partner
et_orgman = et_orgman
et_customer_h = et_customer_h.
DATA: ls_input TYPE crmt_input_field,
ls_input_name TYPE crmt_input_field_names,
ls_customer_h LIKE LINE OF et_customer_h.
* The code below is responsible for populate it_customer_h internal table
* which is to be used in FM CRM_ORDER_MAINTAIN later
ls_customer_h-fld00008c = is_oppt_exp_hdr-ext_created_by.
ls_customer_h-ref_guid = ev_object_guid.
APPEND ls_customer_h TO et_customer_h.
* The code below is responsible for populate CT_INPUT_FIELDS internal table
* which is to be used in FM CRM_ORDER_MAINTAIN later
ls_input-objectname = 'CUSTOMER_H'.
ls_input-ref_guid = ev_object_guid.
ls_input-ref_kind = 'A'.
* Notify One order function module that we want to persist the value of this field
ls_input_name-fieldname = 'FLD00008C'.
APPEND ls_input_name TO ls_input-field_names.
INSERT ls_input INTO TABLE et_input_fields.
ENDMETHOD.

Step3 Redefine
/IWBEP/IF_MGW_APPL_SRV_RUNTIME~
CREATE_DEEP_ENTITY
Redefine method /IWBEP/IF_MGW_APPL_SRV_RUNTIME~CREATE_DEEP_ENTITY of your own
OData service implementation class. The idea is simple, just replace the usage of standard
CL_CRM_OPPORTUNITY_IMPL to your own sub class created in step2.
method /IWBEP/IF_MGW_APPL_SRV_RUNTIME~CREATE_DEEP_ENTITY.
DATA: lr_opportunity TYPE crmt_odata_oppt_hdr_expanded,
lo_oppt_impl TYPE REF TO zcl_crm_opportunity_impl_sub.
CREATE OBJECT lo_oppt_impl.
lo_oppt_impl->/iwbep/if_mgw_core_srv_runtime~set_context( mo_context ).
lo_oppt_impl->create_deep_oppt_entity (
EXPORTING
iv_entity_name = iv_entity_name
iv_entity_set_name = iv_entity_set_name
iv_source_name = iv_source_name
io_data_provider = io_data_provider
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_deep_entity = lr_opportunity ). " Table of Strings
copy_data_to_ref( EXPORTING is_data = lr_opportunity
CHANGING cr_data = er_deep_entity ).
endmethod.
Till now all steps are done. Please see the final achievement regarding extension field CRUD
operation from this video:

https://github.com/i042416/jerryslide/blob/master/video/extensionFieldCRUD.wmv
Alert Moderator

Be the first to leave a comment


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

Step by Step to create HANA live report in Webclient UI


August 26, 2015 | 566 Views |

Jerry Wang

more by this author


SAP Customer Relationship Management
analyticsprocrmhana xshanalivereporthanaodatahanaqueryhanareport

share 0
share 0
tweet
share 0

Follow

1. Log on WebUI with role ANALYTICSPRO.

create a new HANA live report:


report type choose SHL:

in popup window, you have to specify the following three attributes:

For field SAP HANA Live Query, You can choose from F4 value help:
In this example I just use standard HANA query delivered by SAP:
OpportunityQuery.
2. Do not be confused by the id OpportunityService in previous screenshot.
It is just an identifier defined in SPRO, but not the technical ID for a given
HANA query view.
The 5 entries of the value help come from the below customizing:

So the query ID I choose, OpportunityService, actually points to the HANA


query OpportunityQuery.xsodata:

3. Now you are asked to specify value for mandatory parameters of the HANA
query you select from step2.
The three mandatory parameters are defined in HANA studio:

You can find the example OpportunityQuery via the path in System
perspective in HANA studio: sap->hba->crm->Calculation Views.
define an attribute for report ( Attributes are the individual non-measurable
analytical elements). Here I choose Analysis Phase.

Add measure ( Measures are measurable analytical elements ):


4. Now the report can be rendered all the data comes from HANA database
retrieved by HANA query efficiently:

In Chrome development tool, you can observe how analytic data is retrieved
by HANA query:

response:
And the response data is also displayed in the bottom part of report:

You can switch to different stype of graph via the Select Chart Type drop
down list.
Note: The prerequisite of using this solution in CRM Webui is the following
configuration must be done for SAP Web Dispatcher.
URLs with the path /sap/hba/apps/crmhlq are routed to the OData port for the SAP HANA Extended
Application Services in the SAP HANA database, which contains the SAP HANA Live Content with
the query views used.
URLs with the path /sap/opu/odata/sap/ are routed to the message server for the CRM system.