使用擴充套件技術對SAP Fiori應用進行端到端的增強,一個實際案例介紹
第一章
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:
(1) 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. (2) Enhance the runtime OData service implementation to manipulate on the OData extensions done by step1.
(3) 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 service’s 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 haven’t 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.
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. 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 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/test OpportunityExtension 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 parameter’s structure are different. The fill_created_by should react accordingly.
第三章
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:
(1) There is an extension field done on Opportunity detail view. (2) 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 didn’t 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>
要獲取更多Jerry的原創文章,請關注公眾號"汪子熙":
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24475491/viewspace-2718406/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 使用View modification擴充套件SAP Fiori應用的一個案例View套件
- 使用擴充套件方式隱藏SAP Fiori應用某個表格標籤頁的實際案例套件
- 使用擴充套件技術將SAP Fiori應用隱藏動態建立的UI欄位套件UI
- SAP Fiori應用索引大全工具和 SAP Fiori Tools 的使用介紹索引
- SAP Spartacus checkout 流程的擴充套件(extend)實現介紹套件
- 介紹一個能夠對日誌檔案進行自定義高亮的 VS Code 擴充套件套件
- plain framework的實際應用和擴充套件AIFramework套件
- SAP S/4HANA extensibility擴充套件原理介紹套件
- 如何使用 SEGW 的 redefine 功能對 SAP 標準 OData 服務進行擴充套件套件
- SAP S/4HANA Material Fiori應用根據擴充套件欄位搜尋的實現原理套件
- 如何使用Key User Tool擴充套件SAP S/4HANA Fiori UI套件UI
- 介紹一個功能強大的 Visual Studio Code 擴充套件 - Rest Client,能部分替代 Postman套件RESTclientPostman
- 使用Kotlin擴充套件函式擴充套件Spring Data案例Kotlin套件函式Spring
- 把Flutter擴充套件到微信小程式端的探索Flutter套件微信小程式
- 如何使用前端技術開發一個桌面跨端應用前端跨端
- RabbitMQ實戰:擴充套件介紹與系列總結MQ套件
- Laravel-admin 新增擴充套件介紹Laravel套件
- VSCode擴充套件應用VSCode套件
- SAP Fiori Launchpad 應用的兩個實用技巧分享
- 介紹一個好用的能讓網頁變成黑色背景的護眼 Chrome 擴充套件應用 - Night Eye網頁Chrome套件
- 介紹一個能將任意關鍵字高亮實現的 Visual Studio Code 擴充套件套件
- windbg除錯系列教程:sos擴充套件的介紹和使用除錯套件
- SAP SD 實際應用增強(含程式碼)總結
- 介紹兩個好玩的和Github相關的Chrome擴充套件GithubChrome套件
- 使用Java後端對Angular應用進行Docker化 -BhargavJava後端AngularDocker
- Flutter 應用程式建立一個擴充套件皮膚列表Flutter套件
- 乾貨 | 把Flutter擴充套件到微信小程式端的探索Flutter套件微信小程式
- SAPS/4HANAextensibility擴充套件原理介紹套件
- 擴充套件:使用 Vue.js 和 node 共建一個簡單的 CRUD 應用套件Vue.js
- 介紹一個能避免 CORS 錯誤的 Chrome 擴充套件 - Moesif Origin & CORS ChangerCORSChrome套件
- 最佳VSCode的增強型Git擴充套件外掛VSCodeGit套件
- Fortinet將SecurityFabric架構安全能力擴充套件到雲端架構套件
- PHP擴充套件開發就是一個自己的PHP擴充套件PHP套件
- 一個典型的使用 SAP Cloud Application Programming 模型開發的 Fiori 應用CloudAPP模型
- 使用SAP CDS view快速建立一個Fiori應用,管理Service OrderView
- 如何透過連線資料庫的方式對線下應用進行線上擴充套件資料庫套件
- SAP Fiori應用裡對國際化RTL需求(right-to-left)的支援
- dart系列之:你的地盤你做主,使用Extension對類進行擴充套件Dart套件