Nowadays, most part of the organizations make use of Key Performance Indicators (a.k.a KPIs) to evaluate their success in different activities relevant with their business. A KPI is a measurable value that demonstrates how effectively a company is achieving its objectives.
When we relate KPIs with the SAP Fiori experience the first thing that comes to our minds is the use of SAP Smart Business Applications and the KPI Modeller (more information available here), but what most part of the developers don’t know is that this is not the only path available to publish KPIs in an SAP Fiori application.
We know already that Fiori Elements can generate UIs at runtime based on metadata annotations and predefined templates, but one of the most interesting functionalities (and not so widespread) is the ability to publish KPIs using the @UI.dataPoint annotation.
With a measurable field (number, price, quantity or percentage) you can define a threshold and evaluate how the indicator has been performing and display the result in a range of different colors and symbols. This concept is defined as Trend-Criticality Calculation and you can check the official documentation here.
The focus of this post is to explain only the Criticality calculation inside an Overview Page application, but since there are different Fiori Elements providing support to the annotation @UI.dataPoint is possible to adapt the same concepts for different kind of developments (e.g. KPI in the header of an Object Page).
This post covers not only Fiori and UI5 concepts but also ABAP CDS, if you are not familiar with these concepts I advise you to check my previous posts or to have a look in SAP official documentation.
What do I need to know about Criticality?
In a criticality calculation we need to provide the following data:
- Improvement direction
- Threshold (low and high values)
Depending on the selected direction we must define multiple low and high values, let’s check in details the available directions and the expected threshold values:
- #TARGET: Your key figure must stay inside a specific target in the center of your threshold, deviations in any directions will reflect a bad performance of the indicator.
- Example of an use case: Headcount.
- #MINIMIZE: Your key figure must stay in the lowest part of the threshold to indicate a good performance, deviation in the opposite direction will reflect as bad performance.
- Example of an use case: Work Incidents.
- #MAXIMIZE: Your key figure must stay in the highest part of the threshold to indicate a good performance, deviation in the opposite direction will reflect as bad performance.
- Example of an use case: Sales.
Now that you are able to identify the available scenarios we can start the development of our demo. To construct our application we will use data from SFLIGHTS standard view and create a KPI to check the seating occupancy for each one of the scheduled flights in the system. Comparing the number of occupied seats against the maximum seats available in the plane is possible to generate a percentage value and evaluate the position with a criticality calculation.
The improvement direction in this case must be #MAXIMIZE because the airline wants to sell all the seats available in the plane, if the indicator is showing entries with red color it basically means they need to focus sales in those particular flights with a low occupancy.
The UI5 application will be based on an Overview Page template with a List card with progress bar. When we combine a data point annotation with this card template the framework populates automatically the colors and completion of the bar.
As usual, I’m splitting this post in 3 sections:
- ABAP CDS
- OData Project
- UI5 Project (Web IDE)
ABAP CDS
Create the view ZDEMO_CRITICALITY_OVP and select data from the view SFLIGHTS. The following fields are expected as the result:
- FlightCode: The union of the airline code (CARRID) and the connection number (CONNID). This field should be available inside the list card and in the global filter of the Overview Page.
- FlightDate: Date of the flight, configured as a secondary data point in the list card.
- Destination: The arrival city, expected in the result of the card as well.
- Occupancy: A percentage result based on the calculation of the maximum seats (SEATSMAX) against the occupied seats (SEATSOCC). This field should be configured as a data point to become a KPI about seating occupancy. Extra configurations determine only 2 fractional digits, expected values between 0 and 100, and a criticality calculation with a maximize direction with the following range of colors:
- RED from 0 to 25.
- YELLOW from 26 to 60.
- GREEN from 61 to 100.
- Percentage: Just a unit of measure to associate directly with the occupancy field.
@AbapCatalog.sqlViewName: 'ZDEMOCRITOVP' @AbapCatalog.compiler.compareFilter: true @AccessControl.authorizationCheck: #CHECK @EndUserText.label: 'Criticality OVP' @OData.publish: true define view ZDEMO_CRITICALITY_OVP as select from sflights as Flight { @EndUserText.label: 'Flight Code' @UI: { selectionField.position: 10, lineItem.position: 10 } key concat(carrid, connid) as FlightCode, @UI: { lineItem: { type: #AS_DATAPOINT, importance: #HIGH, position: 20 }, dataPoint: { title: 'Flight Date' } } key fldate as FlightDate, @UI.lineItem.position: 20 cityto as Destination, @UI: { lineItem: { type: #AS_DATAPOINT, importance: #HIGH, position: 10 }, dataPoint: { title: 'Flight Date', valueFormat.numberOfFractionalDigits: 2, minimumValue: 0, maximumValue: 100, criticalityCalculation: { improvementDirection: #MAXIMIZE, deviationRangeLowValue: 25, toleranceRangeLowValue: 60 } } } @Semantics.quantity.unitOfMeasure: 'Percentage' division(seatsocc * 100, seatsmax, 2) as Occupancy, @Semantics.unitOfMeasure: true cast(' % ' as abap.unit(3)) as Percentage }
Important points about the annotations used in this CDS view:
- @OData.publish: Used to publish the OData service automatically without the need to create an OData project through transaction SEGW.
- @EndUserText.label: This annotation provides a label to the field.
- @UI.selectionField: This annotation determines the position of the field in the global filter of the Overview Page.
- @UI.lineItem: This annotation determines the position of the fied inside the cell of our list card.
- @UI.dataPoint: This annotation holds the criticality calculation of our KPI. Notice that we use #MAXIMIZE as the improvement direction, so we just need to fill deviationRangeLowValue and toleranceRangeLowValue to determine the threshold (as described by SAP documentation). Also, there is a configuration for decimal places and the minimum and maximum values expected for the field.
- @Semantics.quantity and @Semantics.unitOfMeasure: These annotations define a relation between a quantity field and its respective unit.
This is the expected outcome:_CRITICALITY_OVP as select from sflights as Flight { ... }
Remember always to activate the OData service in the Front-end server (SAP Gateway server) through the transaction /IWFND/MAINT_SERVICE.
UI5 Project (Web IDE)
The process to create an UI5 application through Web IDE is pretty simple and straightforward, just follow the steps below to create an Overview Page with a list card with progress bar.
Right click in your Workspace folder and click New -> Project from Template.
Template Selection: Create a new project based on a Overview Page.
Basic Information: Define the project name as zdemo_criticality_ovp.
Data Connection: Select your system and OData project.
Annotation Selection: Select the remote annotation provided by the ABAP CDS exposure.
.
Template Customization: Define a namespace, data source, entity type, app title and description. The rest of the configuration doesn’t affect this demo.
Finish the wizard and conclude the creation of your Overview Page.
Now we need to configure a List card inside of our application, right click in the main folder of your project, click New -> Card.
Configure Datasource: Select the existing data source and continue.
Select a Card: Select a List card template, no need to mark the extra configuration in the bottom.
Template Customization: Select the entity set, provide a title and fill the card properties with the following data:
- List Type: Extended
- List Flavor: Bar
- Sort By: Flight Date
- Sort Order: Descending
Finish the wizard and conclude the creation of your new card.
Note #2: The list flavor must be set as Bar to allow the use of progress bar and provide support to data points with criticality calculation.
Note #3: The list type must be set as Extended to provide extra space for all of our fields.
Note #4: The sort order was just configured like this to increase our chances to find flights with low occupancy during the tests.
Now the application is concluded and we can start the tests, just filter by Flight Code to navigate across different KPI results. Since we configured a sort by Flight Date the chances to find flights with low occupancy are higher. Check some examples below:
SQ0015 (Singapore)
AZ0555 (Frankfurt)
LH0402 (New York)
LH2402 (Berlin)
The blog was very subjective and it clears the idea about SAP.
Great work Felipe! I’ve added your blog to our SAP Fiori elements wiki
I’d love to see more blogs from you on Fiori elements topics … as you are interested in analytics you might like to do something on the Analytical List Page perhaps?
Hi Jocelyn,
Thanks for the feedback!
I’m actually with this idea in mind since the release of version 1.48. I’ve been planning to deliver two new posts for the next months, first one focused only in ABAP CDS development for analytical purposes (dimensions, texts, cubes and queries) and the second post about Analytical List Page (probably consuming the data model created in the first article).
I think it would be good to explain how to generate a proper data model for an Analytical application before we discuss how to configure the front-end application.
Best Regards,
Felipe
Hi Jocelyn Dart,
Hope you’re well.
As we discussed previously, I’ve been working with those two articles about ABAP CDS analytical views and the Analytical List Page during the last months.
I just released the last article about ALP a few minutes ago, so I would like to share with you and see if they are aligned with your expectations. These are the links:
Hope you like it.
Cheers,
Felipe
Fantastic work Felipe!!! I’m adding them to the Fiori Elements Wiki
They will be much appreciated by many of our readers I know!
Hi Felipe,
I don’t find the annotation..
Can you tell me how to build this?
kind regards,
Cesar
Hi Cesar,
There is an OData Service which controls the annotations catalogues, I advise you to check if this service is active in your front-end server, access the transaction SICF and check the following node:
If the service is already active, I recommend to use transaction /IWFND/GW_CLIENT to read all the catalogues and confirm if your ABAP CDS view is available in the list.
Let me know how it goes.
Cheers,
Felipe
Hello Felipe,
Many thanks for the wonderful blog with end to end developemet. Not only the developement part,
but explaination of annotations, use case makes this blog my favorite one to learn Cds views and
Fiori Elements.
Also thanks Jocelyn Dart for posting it on wiki else I would have missed this precious info. You and your team are organising and updating the contents so well.
Best Regards,
Smriti
Hi Smriti,
Thank you for the feedback.
Cheers,
Felipe
Hi Felipe,
I am currently trying to get deeper into the ALP and Overview Page, so first of all thanks a lot for your Blog (series). They content is arranged very nice and well explained. Great work.
As I always try to understand also the idea behind an implementation (and not just the implementation itself), I would like to ask you a few things about your example. It would be nice, if you find the time to answer.
Just to make sure: My questions should rather be understood as criticism or something into this direction, but they should provide some constructive feedback.
Best regards and thanks one more time for the blog series, look forward to read the other blogs,
Sebastian
Hi Sebastian,
Thank you for the feedback, I’m glad when people start to explore these subjects in a deeper level. Regarding your questions here it goes the explanation:
Hope this information helps.
Cheers,
Felipe
Hi Felipe,
thanks a lot for your time – especially the thing with the positions is very interessting (and shame on me that I missed your blog about the dates – I think it is the only one).
Looking forward to hopefully see new content provided by you in the future.
Bye,
Sebastian
Great block, thanks a lot!
Error
I am facing a weird error.. somehow my bars are all empty, even though the “Percentage” part works fine. The bars are just grayed out, as if the value is 0 for all entries.