Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
mark_wright
Product and Topic Expert
Product and Topic Expert
Solution Overview:

SAP Cloud Platform Mobile Services now includes a mobile card kit.  It is an easy to use tool for micro app generation on iOS and Android. The tool provides companies a solution to create “no code” and “low code” micro apps in hours, not months. Mobile Card kit can mobilize data from any system that is accessible via REST so there are low barriers to getting started. A single SAP Mobile Cards app can have cards coming from many different SAP & non-SAP based systems.

Sample use cases for SAP Mobile Cards:

  • Companion micro apps that reference a report or a KPI that may be in a larger purpose built app

  • Quick reference apps

  • Lightweight simple apps. If you are thinking of an app that may fit 1-2 screens, it’s likely SAP Mobile Card kit is a great fit.

  • Company message cards (e.g. – building / campus information cards, HR deadlines, company events, etc)

  • Micro apps for lean process workflows. BTW – we also have a pre-built card to support the UWL/SAP Inbox


No iOS or Android development experience necessary. End users download the SAP Mobile Cards app from the public app stores and then deploy these lightweight micro-apps directly into the app. End users can enjoy this live & interactive, digital wallet experience for business. Users are notified when important stuff happens and the content is available all of the time.

How to Enable Purchase Order Approval for mobile card kit:

With mobile card kit you can enable multiple scenarios, here I'm going to show you how you can enable Purchase Order Approvals.  This will take you through how to do this in the SAP Fiori Trial environment where one of the Fiori Apps that exist there is Approve Purchase Orders.  If you are doing this in your environment it will be a similar setup, however you may need to make some changes depending on the data that you are returning and what customization you have done.  You should be able to take a similar approach to enabling scenario's like Shopping Cart Approval, or Leave Request Approval, Purchase Contract Approval etc.  Check out Michael Van Cutsem's Blog about doing similar for Leave Request. https://blogs.sap.com/2018/04/16/sap-mobile-cards-building-cards-from-fiori-applications/

Additionally many of these above mentioned scenario's may be enabled via the unified inbox in Fiori.  If this is the case you can follow this tutorial to enable Mobile Cards for Unified Inbox.  https://www.sap.com/developer/tutorial-navigator/mobile-interactive-tutorials/content2go/intermediat...



Get the JSON for Purchase Order Approval in Fiori Trial:

First register for an account with the SAP Fiori Cloud Demo at https://www.sapfioritrial.com/   Once you have gone there, select "See it in action" and then you'll want a defined launchpad so select the "Customize and Extend" option, and then select "Get Started".  You'll want to login with the same user and password that you will be using in the SAP Cloud Platform environment.  If you are using an SAP Cloud Platform account make sure you have "Development & Operations" under Mobile Services enabled.  You can use std or preview.



If you do not have an SAP Cloud Platform account you can sign up for a trial here, https://account.hanatrial.ondemand.com/ which will enable you with the Development & Operations service.

Now you should have an SAP Fiori Launchpad and under Logistics (MM) group you will see Approve Purchase Orders.  If it shows 0 orders, it will refresh with orders over time.



Once you have that setup, lets grab one thing that we need that is based on your launchpad.  With Mobile Cards we use the JSON that is returned based on the REST query to determine how the data is formatted.  To get your JSON document run the following query in the browser window but change the first part of the URL to match your Fiori Launchpad URL, if using the Fiori Trial you should only need to replace the x's with your identifier.  If you are doing something other than Fiori Trial and PO Approval you can use the Developers Tools in Chrome and in the Network XHR trace you will find the URL that is used to return your list, Michael goes into more details on this in his blog mentioned above.

https://fiorilaunchpad-xxxxxxxxx.dispatcher.us1.hana.ondemand.com/sap/fiori/uis2pmmpurchorderapprove...

This will create a JSON result in your browser with the data of one purchase order by using the top=1 filter.  You'll want to save this output as a JSON document.  Once saved you will want to modify the JSON document so that it does not have the results array in it.  Open the JSON document in your editor and remove the text
"results":[
{

at the top of the document and the corresponding close brackets at the end of the document.
}
]

We do the above because we want to return a single card for each purchase order.  If the JSON document has an array of these the cards will not get created correctly.  There is a results array in this returned JSON in order for us to loop through the items that are returned for each PO, we leave that array in tact.

You should end up with a JSON document that is very similar to the following.  You can use the following JSON as well, however if you have made any changes or are using an environment that is not Fiori Trial the JSON may be different.  The above method gives you the JSON for your account.
{
"d": {
"__metadata": {
"id": "https://fiorilaunchpad-xxxxxxxx.dispatcher.us1.hana.ondemand.com/sap/fiori/uis2pmmpurchorderapprove/sap/opu/odata/SAP/GBAPP_POAPPROVAL;mo/WorkflowTaskCollection(SAP__Origin='EC3_800',WorkitemID='000002629726')",
"uri": "https://fiorilaunchpad-xxxxxxx.dispatcher.us1.hana.ondemand.com/sap/fiori/uis2pmmpurchorderapprove/sap/opu/odata/SAP/GBAPP_POAPPROVAL;mo/WorkflowTaskCollection(SAP__Origin='EC3_800',WorkitemID='000002629726')",
"type": "GBAPP_POAPPROVAL.WorkflowTask"
},
"SAP__Origin": "EC3_800",
"WorkitemID": "000002629726",
"TaskType": "TS20000166",
"PoNumber": "4500049352",
"PoNumberFormatted": "4500049352",
"WiCreatedAt": "\/Date(1524244623000)\/",
"ForwardedByID": "",
"ForwardedByName": "",
"SubstitutingForID": "",
"SubstitutingForName": "",
"CreatedByID": "PURCHASER",
"CreatedByName": "Paula Purchaser",
"Value": "1500.00",
"Currency": "EUR",
"SupplierID": "3701",
"SupplierName": "eSupplier, Inc",
"ItemDescriptions": "Portable DVD RW",
"SearchForText": "",
"HeaderDetails": {
"__metadata": {
"id": "https://fiorilaunchpad-xxxxxxxx.dispatcher.us1.hana.ondemand.com/sap/fiori/uis2pmmpurchorderapprove/sap/opu/odata/SAP/GBAPP_POAPPROVAL;mo/HeaderDetailCollection(SAP__Origin='EC3_800',PoNumber='4500049352')",
"uri": "https://fiorilaunchpad-xxxxxxxx.dispatcher.us1.hana.ondemand.com/sap/fiori/uis2pmmpurchorderapprove/sap/opu/odata/SAP/GBAPP_POAPPROVAL;mo/HeaderDetailCollection(SAP__Origin='EC3_800',PoNumber='4500049352')",
"type": "GBAPP_POAPPROVAL.HeaderDetail"
},
"HeaderInfo": {
"__metadata": {
"type": "GBAPP_POAPPROVAL.HeaderInfo"
},
"AccountCategoryDescription": "",
"AccountNumber": "",
"AccountDescription": "",
"GlAccountNumber": "",
"GlAccountDescription": "",
"CumulatedAccountingTypeCode": "0",
"CumulatedAccountingTypeCodeName": "No Assignment",
"CostCentre": "",
"CostCentreIndicator": "",
"CostCentreDescription": "",
"WBSElement": "",
"WBSElementIndicator": "",
"WBSElementDescription": "",
"Network": "",
"NetworkIndicator": "",
"NetworkDescription": "",
"Order": "",
"OrderIndicator": "",
"OrderDescription": "",
"SalesOrder": "",
"SalesOrderItem": "0",
"SalesOrderScheduleLine": "0",
"SalesOrderIndicator": "",
"SalesOrderDescription": "",
"Asset": "",
"AssetSubNumber": "",
"AssetIndicator": "",
"AssetDescription": ""
},
"SAP__Origin": "EC3_800",
"WorkitemID": "000002629726",
"PoNumber": "4500049352",
"PoNumberFormatted": "4500049352",
"WiCreatedAt": "\/Date(1524244623000)\/",
"ForwardedByID": "",
"ForwardedByName": "",
"SubstitutingForID": "",
"SubstitutingForName": "",
"PaymentTerm": "0002",
"PaymentTermDescription": "",
"Incoterm": "CPT",
"IncotermDescription": "Freight-free",
"IncotermLocation": "FOB",
"CompanyCode": "1000",
"CompanyCodeDescription": "BestRun Germany",
"CreatedByID": "PURCHASER",
"CreatedByName": "Paula Purchaser",
"NumberOfNotes": 1,
"NumberOfAttachments": 0,
"Value": "1500.00",
"Currency": "EUR",
"SupplierID": "3701",
"SupplierName": "eSupplier, Inc",
"NumberOfItems": 1,
"Plant": "1000",
"PlantName": "Werk Hamburg",
"DeliveryDate": "\/Date(1524441600000)\/",
"DeliveryDateAlsoLater": "",
"ItemDetails": {
"results": [
{
"__metadata": {
"id": "https://fiorilaunchpad-xxxxxxxx.dispatcher.us1.hana.ondemand.com/sap/fiori/uis2pmmpurchorderapprove/sap/opu/odata/SAP/GBAPP_POAPPROVAL;mo/ItemDetailCollection(SAP__Origin='EC3_800',ItemNumber='00010',PoNumber='4500049352')",
"uri": "https://fiorilaunchpad-xxxxxxxx.dispatcher.us1.hana.ondemand.com/sap/fiori/uis2pmmpurchorderapprove/sap/opu/odata/SAP/GBAPP_POAPPROVAL;mo/ItemDetailCollection(SAP__Origin='EC3_800',ItemNumber='00010',PoNumber='4500049352')",
"type": "GBAPP_POAPPROVAL.ItemDetail"
},
"LimitDetails": {
"__metadata": {
"type": "GBAPP_POAPPROVAL.LimitDetails"
},
"LimitDescription": "",
"IsValueUnLimited": "",
"ValueLimit": "0.0",
"ExpectedValue": "0.0",
"Currency": ""
},
"ProductDetails": {
"__metadata": {
"type": "GBAPP_POAPPROVAL.ProductDetails"
},
"ItemType": "M",
"MaterialID": "DPC2013",
"MaterialGroupDescription": "Drives",
"MaterialGroup": "00209"
},
"DeliveryAddress": {
"__metadata": {
"type": "GBAPP_POAPPROVAL.DeliveryAddress"
},
"Plant": "1000",
"PlantName": "Werk Hamburg",
"CustomerId": "",
"CustomerName": "",
"AddressString": "Alsterdorfer Strasse 13, 22299 Hamburg-Alsterdorf, Germany"
},
"SAP__Origin": "EC3_800",
"ItemNumber": "00010",
"PoNumber": "4500049352",
"ItemNumberFormatted": "10",
"PoNumberFormatted": "4500049352",
"ItemCategory": "0",
"ItemCategoryDescription": "Standard",
"Description": "Portable DVD RW",
"Blocked": "",
"Unit": "PCE",
"UnitDescription": "Piece",
"Quantity": "10",
"Value": "1500.00",
"Currency": "EUR",
"PricePerUnit": "150.00",
"CurrencyForPPU": "EUR",
"QuantityForPPU": "1",
"UnitForPPU": "PCE",
"UnitForPPUDescription": "Piece",
"DeliveryDate": "\/Date(1524441600000)\/",
"DeliveryDateAlsoLater": "",
"Incoterm": "",
"IncotermDescription": "",
"IncotermLocation": "",
"NumberOfNotes": 1,
"NumberOfAttachments": 0,
"NumberServiceLines": 0,
"ServiceLines": {
"__deferred": {
"uri": "https://fiorilaunchpad-xxxxxxxx.dispatcher.us1.hana.ondemand.com/sap/fiori/uis2pmmpurchorderapprove/sap/opu/odata/SAP/GBAPP_POAPPROVAL;mo/ItemDetailCollection(SAP__Origin='EC3_800',ItemNumber='00010',PoNumber='4500049352')/ServiceLines"
}
},
"Limits": {
"__deferred": {
"uri": "https://fiorilaunchpad-xxxxxxxx.dispatcher.us1.hana.ondemand.com/sap/fiori/uis2pmmpurchorderapprove/sap/opu/odata/SAP/GBAPP_POAPPROVAL;mo/ItemDetailCollection(SAP__Origin='EC3_800',ItemNumber='00010',PoNumber='4500049352')/Limits"
}
},
"PricingConditions": {
"__deferred": {
"uri": "https://fiorilaunchpad-xxxxxxxxx.dispatcher.us1.hana.ondemand.com/sap/fiori/uis2pmmpurchorderapprove/sap/opu/odata/SAP/GBAPP_POAPPROVAL;mo/ItemDetailCollection(SAP__Origin='EC3_800',ItemNumber='00010',PoNumber='4500049352')/PricingConditions"
}
},
"Attachments": {
"__deferred": {
"uri": "https://fiorilaunchpad-xxxxxxxx.dispatcher.us1.hana.ondemand.com/sap/fiori/uis2pmmpurchorderapprove/sap/opu/odata/SAP/GBAPP_POAPPROVAL;mo/ItemDetailCollection(SAP__Origin='EC3_800',ItemNumber='00010',PoNumber='4500049352')/Attachments"
}
},
"Notes": {
"__deferred": {
"uri": "https://fiorilaunchpad-xxxxxxxxx.dispatcher.us1.hana.ondemand.com/sap/fiori/uis2pmmpurchorderapprove/sap/opu/odata/SAP/GBAPP_POAPPROVAL;mo/ItemDetailCollection(SAP__Origin='EC3_800',ItemNumber='00010',PoNumber='4500049352')/Notes"
}
},
"Accountings": {
"__deferred": {
"uri": "https://fiorilaunchpad-xxxxxxxxx.dispatcher.us1.hana.ondemand.com/sap/fiori/uis2pmmpurchorderapprove/sap/opu/odata/SAP/GBAPP_POAPPROVAL;mo/ItemDetailCollection(SAP__Origin='EC3_800',ItemNumber='00010',PoNumber='4500049352')/Accountings"
}
},
"Components": {
"__deferred": {
"uri": "https://fiorilaunchpad-xxxxxxxxx.dispatcher.us1.hana.ondemand.com/sap/fiori/uis2pmmpurchorderapprove/sap/opu/odata/SAP/GBAPP_POAPPROVAL;mo/ItemDetailCollection(SAP__Origin='EC3_800',ItemNumber='00010',PoNumber='4500049352')/Components"
}
}
}
]
},
"Attachments": {
"__deferred": {
"uri": "https://fiorilaunchpad-xxxxxxxxx.dispatcher.us1.hana.ondemand.com/sap/fiori/uis2pmmpurchorderapprove/sap/opu/odata/SAP/GBAPP_POAPPROVAL;mo/HeaderDetailCollection(SAP__Origin='EC3_800',PoNumber='4500049352')/Attachments"
}
},
"Notes": {
"__deferred": {
"uri": "https://fiorilaunchpad-xxxxxxxxx.dispatcher.us1.hana.ondemand.com/sap/fiori/uis2pmmpurchorderapprove/sap/opu/odata/SAP/GBAPP_POAPPROVAL;mo/HeaderDetailCollection(SAP__Origin='EC3_800',PoNumber='4500049352')/Notes"
}
}
}
}
}

Configure the Card:

In Mobile Services the first thing you need to do is add the destination to your Fiori Trial Launchpad.  From Mobile Services, select SAP Mobile Cards from the Mobile Applications menu and then select Connectivity from the Assigned Features list.



Form the Connectivity screen use the create icon in the top right hand corner above the list of destinations to create a new destination.



When entering the URL make sure it is your URL, do not use the xxx's per the example.  You should only need to set the following three entries and leave everything else as a default.

Type: Mobile Destination

Destination Name: FioriTrial

URL: https://fiorilaunchpad-xxxxxxx.dispatcher.us1.hana.ondemand.com

Now that you have the destination, select SAP Mobile Cards from the menu and then select the create icon to Create a New Card



We will use the Template Manager to import a card template that is similar to our needs.  From the Template Manager, scroll down and find the "Sample Unified Inbox Card"  and select the Create New Card Icon



We need to change a few things in order to match our Purchase Order app as this template was defined to be used for the Unified Inbox.  Make the following changes.

Name: PO Approval

Destination: FioriTrial

Card Type: Automatic Instance Generation

Query: /sap/fiori/uis2pmmpurchorderapprove/sap/opu/odata/SAP/GBAPP_POAPPROVAL;mo/WorkflowTaskCollection?$skip=0&$top=10&$orderby=WiCreatedAt%20desc&$inlinecount=allpages&sap-client=001&$expand=HeaderDetails/ItemDetails&$format=json

 

Collection Handling: Use Collection

Query URL Collection Root: $.d.results

Query Entity Key Paths: $.d.__metadata.uri

Query Refresh Mode: Keep up-to-date

Description: PO Approval - Query Based Collection Only

Parameter Name - SupplierName

$.d.SupplierName

Parameter Name -  PoNumber

$.d.PoNumber



Select the Sample Data option and then either copy and paste your JSON from above into the Data section, or use the browse button to find your JSON File, you should then have the following



Select Editor.  In the HTML section copy and paste the following HTML.  You can modify the HTML for your design as needed at any time.
<div id="mySimpleTemplate" class="myTemplate" data-type="text/x-handlebars-template">
<div class="header" style="height: 30px">
<div style="text-align: left;">
<span style="font-weight: bold; font-size: 24px; float: left; color: #ffffff; display: inline; padding-top: 8px">
Purchase Order Approval
</span>
</div>
<div style="text-align: right;">
<span style="float: right; display: inline; font-size: 17px; color:#CEDDEC; padding-top: 5px">
{{Value}}
</span>
</div>
<div style="text-align: right;">
<span style="float: right; clear: right; display: inline; font-size: 11px; color: #fafafa; padding-top: 4px">
{{Currency}}
</span>
</div>
</div>
<div class="card-content">
<div class="listitem">
<div class="listitem-label">
<span>
Supplier Name
</span>
</div>
<br>
<div class="listitem-value">
<span>
{{SupplierName}}
</span>
</div>
</div>
<div class="listitem">
<div class="listitem-label">
<span>
Created By
</span>
</div>
<br>
<div class="listitem-value">
<span>
{{CreatedByName}}
</span>
</div>
</div>
<div class="listitem">
<div class="listitem-label">
<span>
Plant Name
</span>
</div>
<br>
<div class="listitem-value">
<span>
{{PlantName}}
</span>
</div>
</div>
<div class="listitem">
<div class="listitem-label">
<span>
Company Code Description
</span>
</div>
<br>
<div class="listitem-value">
<span>
{{CompanyCodeDescription}}
</span>
</div>
</div>
<div class="listitem">
<div class="listitem-label">
<span>
DeliveryDate
</span>
</div>
<br>
<div class="listitem-value">
<span>
{{DeliveryDate}}
</span>
</div>
</div>
<br>
<br>
<div class="listitem">
<div class="listitem-label">
<span>
Items in Purchase Order
</span>
</div>
<br>
</div>
{{#each ItemDetails.results}}
<div style="clear:left; text-overflow: ellipsis; overflow: hidden; white-space: nowrap;">
<span style="float:left; width:40%; text-align:left; font-weight:bold; white-space:nowrap">
Description: {{Description}}
</span>
<br>
Category: {{ItemCategoryDescription}}
<br>
Quantity: {{Quantity}}
<br>
Price Per Unit: {{Value}}&nbsp;{{CurrencyForPPU}}
<br>
</div>
{{/each}}
</div>
</div>

 

Once you have done that if you select any of the menu buttons, like Assets and then go back to Editor you should see the changes reflected and should find something similar to this



Make sure the Data Mapping is correct.  Select the Data Mapping menu option and make sure the settings match, most likely the only change you'll have to make is to change the format of the DeliveryDate.  You will see that there is a section for ItemResults, this is an array of items that we will loop through that are part of the Purchase Order, that way we can put on the card each item in the purchase order.  Another approach to the design may be to put the items on the back of the card, in this tutorial everything is on the front of the card.

Value: d.Value

Currency: d.Currency

SupplierName: d.SupplierName

CreatedByName: d.CreatedByName

PlantName: d.HeaderDetails.PlantName

CompanyCodeDescription: d.HeaderDetails.CompanyCodeDescription

DeliveryDate: d.HeaderDetails.DeliveryDate MM/dd/yyyy

ItemDetails.results: d.HeaderDetails.ItemDetails.results

Description: Description

ItemCategoryDescription: ItemCategoryDescription

Quantity: Quantity

Value: Value

CurrencyForPPU: CurrencyForPPU



 

In order to Approve or Reject the PO we need to create the actions.  Select Actions and you will see two actions defined, ACCEPT and REJECT.

Change the XCSRF Token URL to the Query URL found in the Info section.  You don't need the entire URL with the filter, etc, it should be similar to:

/sap/fiori/uis2pmmpurchorderapprove/sap/opu/odata/SAP/GBAPP_POAPPROVAL;mo/

Similar to how you found the JSON for the PO Approval list, using the Debug Console in your browser get a network trace of when you approve a PO.  You will see a POST command in the XHR.  The Request URL is what will be used to send the Approve scenario.  Keep in mind, this may be implemented differently in your environment.  There will likely be a POST URL, but in some cases you may see a Body that is sent with the POST, you will need to take the JSON of the Request Body and put it in the Action Body in SAP Mobile Cards when defining the action.  You may also need to include the Request Header content-type with a value application/json.

 



Change the URL for the ACCEPT action which you just got from the network trace.  You will need to make it so the URL accepts parameters.  In this case we need to change the WorkitemID and the Comment to take inputs.  The WorkitemID is given to you by the Query URL, so we will pass in ${ID2}, ID1 is the Origin which we hard code in this case.  We then want to send in the input from the comment section.  Here we have defined a Parameter called comments.  If you are copying and pasting the URL below pay attention to the single quotes as you will get an invalid URL if you don't change them after pasting.

/sap/fiori/uis2pmmpurchorderapprove/sap/opu/odata/SAP/GBAPP_POAPPROVAL;mo/ApplyDecision?SAP__Origin='EC3_800'&WorkitemID='${ID2}'&DecisionKey='0001'&Comment='${comments}'


For the REJECT action we use the same URL but change the DecisionKey to 0002

/sap/fiori/uis2pmmpurchorderapprove/sap/opu/odata/SAP/GBAPP_POAPPROVAL;mo/ApplyDecision?SAP__Origin='EC3_800'&WorkitemID='${ID2}'&DecisionKey='000'&Comment='${comments}'

 



 

Last change we make is going into the Notifications and change the New Card Notification to match up with the changes we made in the Info section.  We will pass in the SupplierName and the PoNumber in this case so that a notification is shown with that information.

A new item is ready for your approval in your Inbox: ${SupplierName} - ${PoNumber}



Press Save and now you should have a Card Type of PO Approval in your list.  We now want to make sure the card will show up successfully.

You should have SAP Mobile Cards installed on your device.  If you have not already connected and registered to your environment select the API's menu and then using the camera on your iPhone or Android scan the QR code, which will open up the SAP Mobile Cards app and start the registration process

Once you are registered you will need to subscribe to the card.  In the top right hand corner select the + sign in a circle.  Select the All option and then you will see the PO Approval. Select that and then select Subscribe.  Once you are subscribed you can go back to the home screen and the PO Approval cards should be available, in this case we should see 10 cards of 10 approvals are available as that is what we set our query to retrieve using top=10.  You should be able to perform an action on the select Purchase Order and when new Purchase Orders are added you will receive a notification.



 

 
40 Comments