Quite often we have requirements to develop a component and reuse it across multiple applications. I came across a requirement to show Document Flow on few of the CRM Fiori Transactional Apps.

In CRM, there is a capability to create follow up documents for a transaction record. An Opportunity can have a follow up Appointment and an Appointment could have a follow up task. In the below screen, there are two follow up document created for a particular opportunity. It consists of an Appointment and a Task.


Neither the standard OData services nor Fiori UI have this information. I will go through the steps involved to bring this additional information in such a manner that it could be reused. Please note that I will not be going into the details of how to redefine a standard OData service or extend a standard Fiori UI5 project. You can find more info in SAP Fiori UX – Extensibility.

Reuse OData services

The logic to retrieve Document flow records would remain in a separate OData service, but it would consumed in the existing Opportunity/Task/Appointment OData services. This way we do not need to create an entity and have a repetitive code in all the dependent OData services.

In Gateway, there is an option to include an OData service into another OData service. This sort of composition relies on that fact that there should be an association using the key of the Parent entity to a field of the Dependent entity.

There is also a similar blog put by Rashmi How to Compose Multiple OData Services using SAP NetWeaver Gatewaywhich covers this concept.

Begin by creating a fresh project for Document Flow in SEGW.  Create an Entity/Entity set with properties as shown below


After generating the project, the runtime artifacts would looks like below


Redefine the Get Entity Set method in the Provider class.


I have put the code snippet below in case anyone wants to refer. It may not be optimal.

  METHOD docflowsset_get_entityset.

 DATA: iv_guid      TYPE crmt_object_guid,
 lt_docs      TYPE crmt_doc_flow_db_wrkt,
 ls_docs      LIKE LINE OF lt_docs,
 ls_entityset TYPE /cba/sls_str_doc_flow,
 lv_date      TYPE comt_created_at_usr,
 lv_desc      TYPE crmt_process_description.

 DATA: ls_filter_select_options TYPE /iwbep/s_mgw_select_option,
 lt_filter_options        TYPE /iwbep/t_mgw_select_option,
 ls_select_options        TYPE /iwbep/s_cod_select_option,
 lt_select_options        TYPE /iwbep/t_cod_select_options,
 ls_property              LIKE LINE OF cl_crm_opportunity_impl=>gt_properties.

 *   Read the Parent GUID
 READ TABLE it_filter_select_options INTO ls_filter_select_options  WITH KEY property = 'GUID_PARENT'.
 IF sy-subrc = 0.
 READ TABLE ls_filter_select_options-select_options INTO ls_select_options INDEX 1.
 IF sy-subrc = 0.
 iv_guid = ls_select_options-low.

 iv_header_guid = iv_guid
 et_doc_links   = lt_docs
 error_occurred = 1
 OTHERS         = 2.
 IF sy-subrc <> 0.


 LOOP AT lt_docs INTO ls_docs.

 IF ( ls_docs-objkey_a = iv_guid AND ls_docs-roletype_a = 'VORGAENGER' ). "There are successor documents
 ls_entityset-guid_parent = iv_guid.
 ls_entityset-guid_dependant = ls_docs-objkey_b.
 ls_entityset-roletype = 'Next Document'.
 IF ls_docs-objtype_b = 'BUS2000126'.
 ls_entityset-doctype = 'Appointment'.
 ELSEIF ls_docs-objtype_b = 'BUS2000125'.
 ls_entityset-doctype = 'Task'.
 ELSEIF ls_docs-objtype_b = 'BUS2000111'.
 ls_entityset-doctype = 'Opportunity'.

 *           Retrieve the description of the transaction
 SELECT SINGLE description created_at INTO (lv_desc,lv_date) FROM crmd_orderadm_h WHERE guid = ls_docs-objkey_b.

 IF sy-subrc = 0.
 ls_entityset-created_at = lv_date.
 ls_entityset-description = lv_desc.

 APPEND ls_entityset TO et_entityset.

 ls_entityset-guid_parent = iv_guid.
 ls_entityset-guid_dependant = ls_docs-objkey_a.
 ls_entityset-roletype = 'Previous Document'.
 IF ls_docs-objtype_a = 'BUS2000126'.
 ls_entityset-doctype = 'Appointment'.
 ELSEIF ls_docs-objtype_a = 'BUS2000125'.
 ls_entityset-doctype = 'Task'.
 ELSEIF ls_docs-objtype_a = 'BUS2000111'.
 ls_entityset-doctype = 'Opportunity'.

 *           Retrieve the description of the transaction
 SELECT SINGLE description created_at INTO (lv_desc,lv_date) FROM crmd_orderadm_h WHERE guid = ls_docs-objkey_a.

 IF sy-subrc = 0.
 ls_entityset-created_at = lv_date.
 ls_entityset-description = lv_desc.

 APPEND ls_entityset TO et_entityset.

With this the Document Flow service is complete. We have to link the document flow service with all dependant services. Below I have chosen Opportunity service.

Assuming you have not redefined the Opportunity service, begin by creating a custom opportunity service say, ZMS_OPPORTUNITY. Redefine this service based on the standard Opportunity service.


Include the Document Flow OData Service as shown below.


Provide the Document Flow Technical Service name


You will now be able to see it under Model references


Within the Opportunity OData Service, we need to create an Association, Association Set and a Navigation target. Create an Association. Provide the name and click on the button next to the name.


Select Association type as External and refer the Document Flow service model


The association would look like below


Add a referential constraint as shown below. The Guid in the Opportunity service is linked to the Guid_Parent  in the Document flow.


Add a Navigation Property as shown below under the Opportunity entity


Add an Association set as shown below


Finally generate the project and test the service. Notice that the Guid from the Opportunity service is passed to the Document flow service which in turn provides the list of document flow records.  The below screen shot displays two follow up records for the particular Opportunity./wp-content/uploads/2014/08/15_524936.jpg

In a similar fashion we could include the Document Flow service into other services like Tasks and Appointments to enable the display of document flow records.

In the next article, I will write about enabling the Fiori extension projects to consume these OData services.

To report this post you need to login first.


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

Leave a Reply