Introduction
As part of SAP Multichannel Foundation for Utilities and Public Sector, we ship template UI applications that show the functionality behind the OData service models for SAP IS-U and SAP CRM for Utilities. These template applications consume both SAP ERP (IS-U) and SAP CRM OData models. SAP CRM is used primarily for account information, contract management, products, marketing permissions and other features.
Some customers want to run SAP Multichannel Foundation for Utilities and Public Sector connected to an SAP IS-U system only, i.e. without integrating it to an SAP CRM system. For this “IS-U only” scenario, necessary OData services are available to achieve that. Delivered template responsive and desktop UIs need to be adapted. In this blog I will take an example of a responsive UI template and demonstrate how it can be adapted for IS-U only scenario.
Main master and transactional data objects from SAP IS-U are listed here:
- Account (Business Partner)
- Address Dependent & Independent Phone, E-mail, Fax
- Contract Account
- Contract
- Bank Account
- Account Address
- Account Contact
- Division
- Country
- Region
- PaymentCard
- PaymentCardType
- Service Notification
- Service Order
- Budget Billing Plan
- Payment Plan
- Payment Document
- Invoice
- Device
- Meter Reading and etc.
Sometimes, we get questions about where to find information on OData entities in both service models :twisted: . You can always refer to our
help documentation to get a full list of entities both on SAP CRM and SAP IS-U. Alternatively, you can see our delivered OData models in transaction SEGW (Gateway Service Builder) – both in the IS-U and the CRM systems. It displays all properties of the OData services including entity properties, navigation links, key attributes, settings on entities like filterable, creatable, updateable and others.
Prerequisites
Tools: Eclipse Kepler with SAP UI5 plugins with Apache Tomcat™ web server, SAP Gateway (GW) with UMCUI501 add-on SP04, SAP IS-U (ERP) with UMCERP01 add-on SP04.
Before you start modifying the responsive UI, you need to make sure that the OData services necessary to run the application are available and configured. Please read chapter 4 in the
Admin Guide which describes IS-U only installation scenario.
The services that we need are:
- ERP_UTILITIES_UMC – main OData services with Utilities content
- ERP_UTILITIES_UMC_PUBLIC_SRV - OData services exposing anonymous/public services (anonymous meter reading, anonymous payments)
- ERP_UTILITIES_UMC_URM – User Request management services needed for user creation
- USERMANAGEMENT – OData service for logged user offering features like password change or display user profile
- VBI_APPL_DEF_SRV – Visual Business OData service offering retrieval of application customizing used for outages map display
- VBI_GEOCODER_SRV – Visual Business OData service exposing address to geo-coordinates transformation for outage map display
Note: if you don’t have outage map display, simply remove the tiles related to outages from main application as well as public application. VBI_APPL_DEF_SRV and VBI_GEOCODER_SRV would not be needed in this case.
Before making any UI changes, perform a smoke test with advanced REST Client or Gateway Client on SAP GW system (for example, try requests like: HTTP GET on ERP_UTILITIES_UMC/$metadata and HTTP GET on ERP_UTILITIES_UMC/Accounts) to see if you get response.
Hint: Prepare your test user in SU01 by having a user with the same names on GW and ERP, and assign a business partner with good test data to this user on ERP.
Result of the test of the service (you get “200 OK” as response and the data for business partner attached to your user):
Final prerequisite: download the source code of the UI application from UMCUI501 add-on. You need to download UMCUI5_MOBILE application using Eclipse team provider tool. Download as well public application part and foundation library using the following
blog.
I must warn that I’m not going into details about SAP UI5 architecture or programming; as well, I don’t describe how to set up Apache Tomcat™ web server. Please check the resources available to learn more about these technologies, for example, the following . There is a Getting Started on SAP UI5 blog which you should read.
Please use the report BSP_UPDATE_MIMEREPOS to download from MIME repository public application which is not loaded to SAP Gateway as a BSP application. Foundation is just a foundation library of the application and, usually, you don’t need to modify it.
Setting up IS-U only scenario
As discussed, the UI responsive application consists of three parts: logon (public part), foundation library, and the actual application (UMCUI5_MOBILE).
The UI application is based on MVC pattern – model view controller design pattern. However, separate tiles with the views, model, and controllers are grouped into components. We also decided to group data retrieval and manipulation logic in so called “data providers” instead of a controller. DataProvider is an object that works with data received from OData calls. Controllers in UI call specific data providers.
Let’s take a look at the structure of a typical component in mobile responsive app:
The foundation has all the functionalities required by both public and private application and has the main base controller and classes which are abstract and are extended by components. Service Wrapper is a connectivity utility that offers generic functions for HTTP read, update, delete, batch requests, and others.
In this blog I will
only demonstrate how to adapt the code of the private application UMCUI5_MOBILE, and won’t get into details of how to adapt logon application; but as you will see the same approach can be used.
OK, now let's start doing JavaScript coding :lol: .
Remark: if you renamed the application to let's say zumcui5_mobile, you will have to adapt how the application is loaded in WebContent/index.js by replacing umcui5_mobile with zumcui5_mobile:
fnRegisterModules('sap.umc.mobile', "umcui5_mobile", "/sap/bc/ui5_ui5/sap");
As a quick way to set IS-U only, in main UMCUI5_MOBILE, go to WebContent/app_private/DataProvider.js and change the following line of code in method _prepareData:
this.CRM = this._initService(sap.umc.mobile.CONSTANTS.ODATA_SERVICE_CRM, true);
to:
this.CRM = this._initService(sap.umc.mobile.CONSTANTS.ODATA_SERVICE_ERP, true)
Now all requests that were meant for CRM OData model will be routed via ERP OData model. If you don’t like seeing ‘this.CRM’ variable on app_private DataProvider, you can use “Search->File->Replace” feature of Eclipse to replace ‘CRM’ with ‘ERP’.
Let’s test locally the application on Apache Tomcat™ Server to see the effect.
I suggest opening Web debugger in Google Chrome or any other browser and going through all pages of the application. Check the network communication in the Web debugger to see which requests didn’t work.
By doing a quick test, the following requests were issued by the UI application and received “404 Not Found” error:
ERP_UTILITIES_UMC/Accounts(‘XX’)/BusinessAgreements?$format=json&$expand=ContractAccountBalance,BillToAccountAddress
ERP_UTILITIES_UMC/Accounts('XX')/ContractItems?$format=json&$expand=Premise,Division,Product,BusinessAgreement
ERP_UTILITIES_UMC/Accounts('XX')/CommunicationPermissions?$format=json&$expand=CommunicationChannel,CommunicationPermissionStatus
Obviously, the BusinessAgreements entity needs to be replaced by ContractAccounts, ContractItems by Contracts. CommunicationPermissions representing market permissions on CRM has no corresponding entity on ERP. So, references to not available OData entities and their structures or attributes need to be replaced.
List of affected tiles in UI:
- User Profile
- Message Center
- Services
- Change Services (has to be taken out since it can’t be replaced, UI coding is required to replace this implementation with fast move-in/out EC70 process and corresponding OData entities of ParkedDocument)
Let’s work on the first tile to bring it back to life by performing the following JavaScript code modifications. General guideline: I’m writing the file and a method name, the commented code is the old code that you should be able to find.
1) WebContent/user_profile/model/OnlineDataProvider.js, method _readBusinessAgreements
//new code:
this.CRM.read(this.getAccountPath() + "ContractAccounts", ["$format=json", "$expand=Contracts/Division"], true, {
//this.CRM.read(this.getAccountPath() + "BusinessAgreements", ["$format=json", "$expand=ContractItems/Division"], true, {
2) WebContent/user_profile/model/OnlineDataProvider.js, method _readBusinessAgreement
:
//new code:
this.CRM.read(this.getAccountPath() + "ContractAccounts(ContractAccountID=\'" + sBusinessAgreementID + "\')", ["$format=json"], true, {
//this.CRM.read(this.getAccountPath() + "BusinessAgreements(BusinessAgreementID=\'" + sBusinessAgreementID + "\')", ["$format=json"], true, {
After these JavaScript code modifications in OnlineDataProvider.js, please test the application on Apache Tomcat™ local Server :wink: :
The information about contract accounts started appearing. However, auto-pay and billing address view needs tweaking as well:
1) WebContent/user_profile/view/BillingAddress.controller.js, method _finishEditingBusinessAgreements
if (oBusinessAgreement.ContractAccountID === this.getView().getModel("billingAddress").getProperty("/AgreementNumber")) {
//if (oBusinessAgreement.BusinessAgreementID === this.getView().getModel("billingAddress").getProperty("/AgreementNumber")) {
2) Add the following lines of code to WebContent/user_profile/view/BillingAddress.controller.js
//added
delete oBusinessAgreementCopy.Contracts;
delete oBusinessAgreementCopy.Invoices;
//up to here
this.getDataProvider().addBatchOperation(oBusinessAgreementCopy, batch);
3) AutoPay.view.xml, adjust UI to display ContractAccountID instead of BusinessAgreementID
<Label text="{businessAgreements>ContractAccountID}" class="sapUmcHorizontalBeforeSpacingX1_5" />
<!-- <Label text="{businessAgreements>BusinessAgreementID}" class="sapUmcHorizontalBeforeSpacingX1_5" /> -->
4) AutoPay.controller.js, method _getSelectedPaymentMethod
//new code:
if (sBusinessAgreementID === this.getView().getModel("businessAgreements").getData().results[i].ContractAccountID) {
//if (sBusinessAgreementID === this.getView().getModel("businessAgreements").getData().results[i].BusinessAgreementID) {
5) AutoPay.controller.js, method _saveBusinessAgreement
//new code:
delete oBusinessAgreementCopy.Contracts;
delete oBusinessAgreementCopy.Invoices;
//up to here
this.getDataProvider().addBatchOperation(oBusinessAgreementCopy, batch);
Now, billing address and auto-pay UIs started working :smile: :
User Profile tile and views inside this tile work well now. Let’s go through other tiles.
To fix message center by disconnecting reading CRM related data, in WebContent/message_center/model/OnlineDataProvider.js, method _readMessages, comment this line of code:
//this._performCRMBatch(oDeferredCRM);
Finally, the Services tile displays information about premises that the customer has, related contracts, products. This tile is a mashup of CRM and ERP services. We need to change how the data is read.
1) WebContent/services/model/OnlineDataProvider.js, method _readServices:
this.CRM.read(this.getAccountPath() + "ContractAccounts", ["$format=json", "$expand=Contracts/Premise,Contracts/Division"], true, {
//this.CRM.read(this.getAccountPath() + "Contracts", ["$format=json", "$expand=Premise,Division,Product,ContractAccounts"], true, {
2) WebContent/services/model/DataProvider.js, method loadServices. Since the way how data is retrieved has changed, the method needs to be rewritten, please replace the whole method with this code :oops: :
loadServices: function(oDelegate) {
this.oPremises = new sap.ui.model.json.JSONModel();
var fnCallBack = jQuery.proxy(function(oData) {
if (oData && oData.results) {
var i, j, l, iPremiseIndex, bPremiseFound, aContracts, oContractForPremise, oPremiseWithContracts, aContractAccounts;
aContractAccounts = oData.results;
var aPremises = [];
iPremiseIndex = 0;
for (i=0; i < aContractAccounts.length; i++){
aContracts = aContractAccounts[i].Contracts.results;
for (l = 0; l < aContracts.length; l++) {
bPremiseFound = false;
for (j = 0; j < aPremises.length; j++) {
if (aPremises[j].PremiseID === aContracts[l].Premise.PremiseID) {
oContractForPremise = sap.umc.mobile.private.app.js.utils.copyObjectProperties(sap.umc.mobile.private.app.js.utils
.deleteLocalProperties(aContracts[l]));
delete oContractForPremise.Premise;
aPremises[l]._contracts.push(oContractForPremise);
bPremiseFound = true;
break;
}
}
if (bPremiseFound === false) {
oPremiseWithContracts = aContracts[l].Premise;
oContractForPremise = sap.umc.mobile.private.app.js.utils.copyObjectProperties(sap.umc.mobile.private.app.js.utils
.deleteLocalProperties(aContracts[l]));
delete oContractForPremise.Premise;
oPremiseWithContracts._contracts = [oContractForPremise];
oPremiseWithContracts._ID = iPremiseIndex;
iPremiseIndex++;
aPremises.push(oPremiseWithContracts);
}
}
}
for(var k = 0; k < aPremises.length; k++){
aPremises[k]._contracts.reverse();
}
// fix default premise with home tiles
aPremises.reverse();
this.oPremises.setData(aPremises);
oDelegate.onPremisesLoaded(this.oPremises);
}
}, this);
this._readServices(fnCallBack);
},
Two other small modifications and we are done:
1) WebContent/services/view/ServiceDetail.controller.js, method _initializeContractModel:
//modified
//this.getDataProvider().loadBudgetBillingProcedure(oContract.contract.BusinessAgreementID, jQuery.proxy(this._intializeVisibleTabs, this));
this.getDataProvider().loadBudgetBillingProcedure(oContract.contract.ContractAccountID, jQuery.proxy(this._intializeVisibleTabs, this));
2) WebContent/services/view/ServiceDetail.view.xml, UI display modifications to use model correctly, old xml commented out, new in.
<ObjectAttribute
text="{parts:[ 'contract>/division' , 'contract>/division/Description'], formatter:'sap.umc.mobile.services.js.utils.productFormatter
<!-- text="{parts:[ 'contract>/division' , 'contract>/contract/Product/Description'], formatter:'sap.umc.mobile.services.js.utils.productFormatter'}" class="sapUmcWhiteTextColor"/> -->
Finally, the services display now works :wink: :
One tile that needs complete rewriting is the "Manage Services" tile. It needs to be rewritten to adapt to ISU way of how to create move-in/out. We deliver OData entities needed to execute fast move-in/out process as per transaction EC70.
I decided to remove “Manage Services” tile from the application by commenting out the following code in WebContent/home/model/Tiles.js:
//this.addManageService = (function(){
//var oTile = {
// "number": "",
// "numberUnit": "",
// "numberClass": "sapUmcTileNumber sapUmcGreyTextColor",
// "numberUnitClass": "sapUmcTileNumberUnit sapUmcGreyTextColor",
// "info": sap.ui.getCore().getModel("i18n").getProperty("HOME.CHANGE_SERVICE_INFO"),
// "icon": "sap-icon://settings",
// "title": sap.ui.getCore().getModel("i18n").getProperty("HOME.MANAGE_SERVICE")
// };
// this.TileCollection.push(oTile);
//}).call(this);
Result :smile: :
That’s it for now. I hope you got the idea on how to create IS-U only UI applications using our templates. Please leave your comments and feedback on this blog.
:lol: :twisted: