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 Gateway” which 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. CALL FUNCTION 'CRM_DOC_FLOW_READ_DB' EXPORTING iv_header_guid = iv_guid IMPORTING et_doc_links = lt_docs EXCEPTIONS error_occurred = 1 OTHERS = 2. IF sy-subrc <> 0. ENDIF. 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'. ENDIF. * 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. ENDIF. APPEND ls_entityset TO et_entityset. ELSE. 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'. ENDIF. * 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. ENDIF. APPEND ls_entityset TO et_entityset. ENDIF. ENDLOOP. ENDIF. ENDIF. ENDMETHOD.
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.
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.