Most of you should be familiar with Core Data Services by now.You DO NOT need to be using SAP on HANA or S/4HANA to use CDS because it is database independent.One innovation that the S/4HANA programming approach is depending on is CDS. We can generate OData, develop SAPUI5 apps, construct graphs, and show charts using CDS. The beauty of CDS is in that.
Now that we are familiar with the fundamentals of CDS, it is imperative that we study the following advanced topic. It’s called the Virtual Data Model, or VDM. Virtual refers to nonexistent.Put differently, VDM functions as an intermediary for the CDS, strategically structured and adjusted to produce a more accurate depiction of the data.
The architecture for creating a Virtual Data Model (VDM) in S/4HANA will be covered in this article. VDM is constructed from CDS. Any discussion of VDM implies that CDS Views, or Core Data Services, are the foundation.
The architecture and programming model of SAP S/4HANA heavily rely on CDS Views. For all SAP Fiori Applications, VDMs and CDS are the primary data sources and data modes. On VDM, all recent advancements in S/4HANA are built.
Why is VDM required?
- Understandability: Business, non-technical, and functional people can all grasp VDM with ease.
- Reusability: After they are launched, customers and partners can reuse parts of the VDM perspective, which are expected to be reused by other teams.
- Leading S/4HANA Programming Model: For all S/4HANA initiatives, VDM is the recommended programming model. CDS/VDM is the basis for other data models, such as Analytic and OData Models. Also, VDM is used in the development of all new SAP standard Fiori Apps.
- Performance: Because VDM views are run directly at the database level, they take advantage of all of its features and performance.
- Transport Management: As the foundation of VDM, CDS makes use of the reliable, dependable ABAP Application Infrastructure and Change
- How Can a Transient Provider Be Created?
- How Can SAP Analysis for Office (AO) See VDM?
- How Can UI Annotations and CDS Views Be Used to Build Fiori Apps?
Embedded denotes integrated. With S/4HANA System, embedded analytics refers to built-in analytics. It creates virtual data models, or representations of operational data, using the technology of SAP ABAP Core Data Services, also known as CDS.
SAP HANA Pre-delivered CDS views, which are pre-packaged analytical tools included with Embedded Analytics, allow users to execute real-time data analytics on transactional data without having to know much about the underlying data tables or structures. The views can be used directly or combined with new views (or modified/enhanced views) to generate new data models, depending on the analytical needs of a business.
Building a semantic overlay on top of the current database architecture is the fundamental idea behind a virtual data model.
VDM can be divided into two primary categories:
- Interface Views
- Basic View
- Composite View
Consumption Views
- Interface Views
Because they are built directly on top of DDIC tables or views, Basic Views (Core Entity Views, Text Views, and Hierarchy Views) interface with database tables to retrieve data. To put it briefly, Basic Views are created when you are directly picking data from a database table. - One or more Basic Views serve as the foundation for Composite Views. To create a composite view, several basic views can be put together and calculations made using functions and expressions. Composite views have the option of being reusable or consumption-specific.
2. Consumption View
- Because Consumption Views are constructed on top of Composite Views, they are incompatible with DDIC tables and Basic Views.
- The views that are exposed to front-end tools such as SAP Analytics Cloud, BEX Queries, Analysis for Office, Fiori Apps, etc. are called consumption views.
- @VDM.viewType: # BASIC , COMPOSITE,CONSUMPTION
- @Analytics.DataCategory: #DIMENSION , FACT,CUBE
- @Analytics.Query: # TRUE,FALSE
- @Analytics.dataExtraction.enabled: #TRUE, FALSE
- @ObjectModel.dataCategory: #TEXT, HIERARCHY
- @Odata.Publish: TRUE
Today’s task will involve creating CDS Views for Sales Flow. For VBAK (Sales Header), Basic CDS View ZVDM_I_VBAK is made. Basic CDS View ZVDM_I_LIPS is built for Delivery Header and Item, and Basic View ZVDM_I_VBAP is created for VBAP (Sales Item).
On top of the Basic CDS Views mentioned above is the Composite CDS view ZVDM_CO_SALES.
The Composite View above serves as the foundation for the Consumption View ZVDM_C_SALES.
In our practice today, we also used Partner CDS View and Standard Material CDS View.
We are going to construct CDS Views for Sales Flow as part of today’s activity. ZVDM_I_VBAK, the Basic CDS View, is made for VBAK (Sales Header). For VBAP (Sales Item), Basic View ZVDM_I_VBAP is constructed, and for Delivery Header and Item, Basic CDS View ZVDM_I_LIPS is created.
- The Basic CDS Views above provide the foundation for the Composite CDS view ZVDM_CO_SALES.
- Built upon the Composite View mentioned above is the Consumption View ZVDM_C_SALES.
- In today’s activity, we also employed Partner CDS View and Standard Material CDS View.
Take the CDS Basics Quiz 1.
Exercise 1: Make a Simple CDS See: ZVDM_I_VBAK (FACT, BASIC)
@Analytics.dataCategory: #FACT — Since this is a basic view, we are fetching the transactional table here without using any semantic annotations.
Used the annotations below to specify the CDS view’s size and data class in accordance with the specifications
- @ObjectModel.dataClass.usageType: #TRADESIONAL
- UsageType.serviceQuality @ObjectModel: #B
- UsageType.sizeCategory @ObjectModel.usage: #XL
@AbapCatalog.sqlViewName: 'ZVDM_VIEW_VBAK'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Sales header data( Basic View , Fact table)'
@VDM.viewType: #BASIC
@Analytics.dataCategory: #FACT
@Analytics.dataExtraction.enabled: true
@ObjectModel.representativeKey: [ 'SalesDocument' ]
@ObjectModel.usageType.dataClass: #TRANSACTIONAL
@ObjectModel.usageType.serviceQuality: #B
@ObjectModel.usageType.sizeCategory: #XL
define view ZVDM_I_VBAK
as select from vbak
{
//Key
key vbeln as SalesDocument,
//Category
vbak.vbtyp as SDDocumentCategory,
vbak.auart as SalesDocumentType,
// Created By , Date and Time
vbak.ernam as CreatedByUser,
vbak.erdat as CreationDate,
cast( vbak.erzet as creation_time preserving type ) as CreationTime,
//Organization
vbak.vkorg as SalesOrganization,
vbak.vtweg as DistributionChannel,
vbak.spart as OrganizationDivision,
vbak.vkgrp as SalesGroup,
vbak.vkbur as SalesOffice,
//Sales Customer
vbak.kunnr as SoldToParty,
//Amount
vbak.netwr as TotalNetAmount,
vbak.waerk as TransactionCurrency,
vbak.vdatu as RequestedDeliveryDate,
vbak.vsbed as ShippingCondition,
vbak.autlf as CompleteDeliveryIsDefined,
vbak.lifsk as DeliveryBlockReason,
//Reference
vbak.vgbel as ReferenceSDDocument,
vbak.vgtyp as ReferenceSDDocumentCategory,
//Status
vbak.gbstk as OverallSDProcessStatus,
vbak.abstk as OverallSDDocumentRejectionSts
}
Exercise 2: Make a Simple CDS View: ZVDM I VBAP (FACT, BASIC)
Using Association I created a CDS view (Basic, FACT) from VBAP and attached it to the above CDS view (ZVDM_I_VBAK).
@AbapCatalog.sqlViewName: 'ZVDM_VIEW_VBAP'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Sales Item data( Basic View , Fact table)'
@VDM.viewType: #BASIC
@Analytics.dataCategory: #FACT
@Analytics.dataExtraction.enabled: true
@ObjectModel.representativeKey: [ 'SalesDocument']
@ObjectModel.usageType.dataClass: #TRANSACTIONAL
@ObjectModel.usageType.serviceQuality: #B
@ObjectModel.usageType.sizeCategory: #XL
define view ZVDM_I_VBAP
as select from vbap
association[1..1] to ZVDM_I_VBAK as _vbak on $projection.SalesDocument = _vbak.SalesDocument
{
key vbap.vbeln as SalesDocument,
key vbap.posnr as SalesDocumentItem,
vbap.matnr as Material,
vbap.arktx as SalesDocumentItemText,
vbap.posex as UnderlyingPurchaseOrderItem,
vbap.kwmeng as OrderQuantity,
vbap.vrkme as OrderQuantityUnit,
vbap.zmeng as TargetQuantity,
vbap.zieme as TargetQuantityUnit,
//Pricing
vbap.netwr as NetAmount,
vbap.waerk as TransactionCurrency,
vbap.netpr as NetPriceAmount,
//Shipping
vbap.vstel as ShippingPoint,
vbap.werks as Plant,
vbap.lgort as StorageLocation,
vbap.route as Route,
//Reference Dosument
vbap.vbelv as OriginSDDocument,
vbap.posnv as OriginSDDocumentItem,
vbap.vgbel as ReferenceSDDocument,
vbap.vgpos as ReferenceSDDocumentItem,
vbap.vgtyp as ReferenceSDDocumentCategory,
vbap.uepos as HigherLevelItem,
//Status
vbap.gbsta as SDProcessStatus,
vbap.absta as SDDocumentRejectionStatus,
//Make Association
_vbak
}
Exercise 3: Make a Simple CDS ZVDM_I_LIPS (BASIC, FACT) is displayed.
utilizing Association a CDS View (Basic, FACT) was created from the LIPS and LIKP data.
@AbapCatalog.sqlViewName: 'ZVDM_VIEW_LIPS'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Delivery Item data( Basic View , Fact table)'
@VDM.viewType: #BASIC
@Analytics.dataCategory: #FACT
@Analytics.dataExtraction.enabled: true
@ObjectModel.representativeKey: [ 'ReferenceSDDocument' ]
@ObjectModel.usageType.dataClass: #TRANSACTIONAL
@ObjectModel.usageType.serviceQuality: #B
@ObjectModel.usageType.sizeCategory: #XL
define view ZVDM_I_LIPS
as select from lips
//Associations
association[1..1] to likp as _likp on $projection.DeliveryDocument = _likp.vbeln
{
//Keys
key vbeln as DeliveryDocument,
key posnr as DeliveryDocumentItem,
key vgbel as ReferenceSDDocument,
matnr as Material,
pstyv as DeliveryDocumentItemCategory,
lgort as StorageLocation,
lgpla as StorageBin,
lgtyp as StorageType,
//delivery
arktx as DeliveryDocumentItemText,
@Semantics.unitOfMeasure: true
vrkme as DeliveryQuantityUnit,
@DefaultAggregation: #SUM
@Semantics.quantity.unitOfMeasure: 'DeliveryQuantityUnit'
lfimg as ActualDeliveryQuantity,
@DefaultAggregation: #SUM
@Semantics.quantity.unitOfMeasure: 'DeliveryQuantityUnit'
ormng as OriginalDeliveryQuantity,
@Semantics.unitOfMeasure: true
meins as BaseUnit,
//reference
vgpos as ReferenceSDDocumentItem,
vgtyp as ReferenceSDDocumentCategory,
//Status
gbsta as SDProcessStatus,
fksta as DeliveryRelatedBillingStatus,
// Pricing
vbelv as OriginSDDocument,
posnv as SDDocumentItem,
vbtyv as SalesSDDocumentCategory,
ematn as BaseUnit1,
werks as DelPlant,
// _likp.kunag as ShipToParty,
// Make Associations
_likp
}
Worksheet 4: Construct Composite CDS View: ZVDM CO SALES (CUBE, COMPOSITE)
Using the custom CDS views ZVDM_I_VBAP, ZVDM_I_LIPS, and Standard Material CDS views as a basis, a Composite View was created. Partners in SalesDocumentItemPartner, I_Material, and I_MaterialText.
Here, we represented the currency and quantities using semantic annotations in the composite view, and we created the Transient Provider using the specialized annotation @Analytics.datacategory; #CUBE.
Add the RSRTS_ODP_DIS transaction to your favorites. This is for the Temporary Provider Preview.
Use of @Anlytics.dataCategory:#CUBE in the CDS View will result in the creation of a transient provider in the S/4HANA system.It is applicable to several reporting tools.
@AbapCatalog.sqlViewName: 'ZVDM_VIEW_SALES'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Sales Composite View(Composite View ,CUBE)'
@VDM.viewType: #COMPOSITE
@Analytics.dataCategory: #CUBE
@ObjectModel.usageType.dataClass: #TRANSACTIONAL
@ObjectModel.usageType.serviceQuality: #B
@ObjectModel.usageType.sizeCategory: #XL
@Search.searchable: true
define view ZVDM_CO_SALES
as select from ZVDM_I_VBAP as VBAP
association[0..*] to ZVDM_I_LIPS as _LIPS on $projection.SalesDocument = _LIPS.ReferenceSDDocument and
$projection.SalesDocumentItem = _LIPS.ReferenceSDDocumentItem
association[1..1] to I_Material as _Material on $projection.materialNumber = _Material.Material
association[0..*] to I_MaterialText as _MaterialText on $projection.materialNumber = _MaterialText.Material
association[0..*] to I_SalesDocumentItemPartner as _Partneritem on $projection.SalesDocument = _Partneritem.SalesDocument and
$projection.SalesDocumentItem = _Partneritem .SalesDocumentItem
{
//VBAP
//@ObjectModel.foreignKey.association: '_vbak'
@Search.defaultSearchElement: true
key VBAP.SalesDocument,
key VBAP.SalesDocumentItem,
_vbak.SalesOrganization as SalesOrganization,
Material as materialNumber,
@EndUserText.label: 'Material Descrption'
@EndUserText.quickInfo: 'Material Desc'
@Semantics.text: true
_MaterialText[ 1:Language = $session.system_language ].MaterialName as MaterialDescrption,
SalesDocumentItemText,
UnderlyingPurchaseOrderItem,
case
when (_LIPS.DeliveryDocument is null ) then 'No Follow ON Document Created'
else _LIPS.DeliveryDocument
end as Status,
_LIPS.DeliveryDocument,
_LIPS.DeliveryDocumentItem,
@Semantics.unitOfMeasure: true
OrderQuantityUnit,
@Semantics.unitOfMeasure: true
TargetQuantityUnit,
@Semantics.currencyCode: true
TransactionCurrency,
ShippingPoint,
Plant,
StorageLocation,
Route,
OriginSDDocument,
OriginSDDocumentItem,
// ReferenceSDDocument as SalesDocument NU,
// ReferenceSDDocumentItem as SalesDocumentItem,
ReferenceSDDocumentCategory,
HigherLevelItem,
SDProcessStatus,
SDDocumentRejectionStatus,
// _LIPS.Material,
_LIPS.DeliveryDocumentItemCategory,
// _LIPS.StorageLocation,
_LIPS.StorageBin,
_LIPS.StorageType,
_LIPS.DeliveryDocumentItemText,
@Semantics.unitOfMeasure: true
_LIPS.DeliveryQuantityUnit as DELIVERYQUNATITYUNIT,
@Semantics.quantity.unitOfMeasure: 'DELIVERYQUNATITYUNIT'
_LIPS.OriginalDeliveryQuantity,
_LIPS.BaseUnit,
// _LIPS.ReferenceSDDocument,
// _LIPS.ReferenceSDDocumentItem,
// _LIPS.ReferenceSDDocumentCategory,
_LIPS.SDProcessStatus as DeliveryStatus,
_LIPS.DeliveryRelatedBillingStatus,
// _LIPS.OriginSDDocument,
// _LIPS.SDDocumentItem,
_LIPS.SalesSDDocumentCategory,
//Aggregations
@DefaultAggregation:#SUM
@Semantics.quantity.unitOfMeasure: 'OrderQuantityUnit'
OrderQuantity,
@Semantics.quantity.unitOfMeasure: 'TargetQuantityUnit'
@DefaultAggregation:#SUM
TargetQuantity,
@Semantics.amount.currencyCode: 'TransactionCurrency'
@DefaultAggregation:#SUM
NetAmount,
@Semantics.amount.currencyCode: 'TransactionCurrency'
@DefaultAggregation:#SUM
NetPriceAmount,
@Semantics.quantity.unitOfMeasure: 'DELIVERYQUNATITYUNIT'
@DefaultAggregation:#SUM
_LIPS.ActualDeliveryQuantity,
/* Associations */
_vbak,
_LIPS,
_Material,
_MaterialText,
_Partneritem
}
With ADT (Eclipse/HANA Studio), you may preview the data of each VDM created individually by simply pressing F8 or right-clicking and selecting Preview.
To learn how to Create Transient Provider was one of the article’s objectives. And we already have knowledge. Transient Provider is automatically created when you construct the Composite View with annotation @Analytics.datacategory; #CUBE.
How Can a Transient Provider Be Used?
Transaction Code: RSRTS_ODP_DIS; execute. Select ODP Name: ZVDM_VIEW_SALES (SQL View Name of Composite and CUBE Name), ODP Context: ABAP Core Data Services.
Note that the SQL View Name was selected, not the CDS Entity View name. You can access SQL View Name at the Data Dictionary Level.
Select the Standard Query option.
From the FREE Characteristics, choose the fields you wish to study (we choose sales order, sales order item, and material).
That is all. Congratulations! Using the Transient Provider was a successful use. The Composite View’s output is visible to you in the Transient Provider. ABAP developers typically don’t use it.It’s for reporting people (you could feel more at ease if your friend is a BI, BO, or BW).
How Can SAP Analysis for Office (AO) See VDM?
- The only thing Analysis Office is is a SAP Business Objects Add-on for Microsoft Excel and PowerPoint.
- The two images below illustrate steps 1 through 5 for using CDS view in Analysis for Office.
Please install Analysis Office for Microsoft Excel if you are unable to see the Analysis Menu.
- As an alternative, you could take the actions listed below.
- Launch Excel and select the Analysis Menu Tab.
Go to Insert Data Source and hit Select Data Source
Step 6: Select the S/4HANA System and give your credentials.
Step 7: Search with Composite View SQL Name and Select your CDS view
chosen CDS view.
If for any reason you are unable to locate your CDS SQL Name. Try searching after entering 2C in front of your CDS SQL.In other words.
Step 8: Since we haven’t used any filter annotations or @AnalyticsDetails, the Analysis Office’s first screen will only display measurements automatically.Axis annotations for Query.
While filters are available in Consumption View, we haven’t utilized them here because we’re using Composite Cube View instead of Consumption View. You may give parameters a try.
@consumption.filter annotation:{ MultipleSelections: True, SelectionType: # Range, Mandatory: False}
Step 9: Drag and Drop Required Fields in to Rows.
We can use below annotation to display the fields automatically rows and columns.
Annotation : @AnalyticsDetails.Query.Axis: #Rows /#Columns
That means, if you use @AnalyticsDetails.Query.Axis: #Rows, the Analysis Office would automatically show the data from the VDM. You do not need to drag and drop the fields.
If you do not want to show some fields in the Analysis Office, you may use below annotation with value #FREE. It will not display.
@AnalyticsDetails.Query.Axis: #FREE
This excel sheet can be saved and provided as a template for the end user. End user can change the input parameter via prompts and view data accordingly.
Exercise 5 – Create Consumption View: ZVDM_C_SALES
Finally, let’s created a Consumption View based on the Composite View to create an App in Fiori
We have used semantics annotations in the Consumption View to represent the currency and quantities and also used other UI annotations.
Below 2 Annotations are used for displaying the text in the Fiori Apps
@EndUserText.label: ‘Sales Order Number’
@EndUserText.quickInfo: ‘Sales Order NO’
Below 2 Annotations are used for positioning fields and selection fields in the Fiori Apps.
@UI.lineItem: [{position:10 ,importance: #HIGH}]
@UI.selectionField: [{position: 10}]
It is necessary to publish the CDS view as an OData Service to consume it in Fiori Apps. Below annotation helps.
@ODATA.Publish: true
@AbapCatalog.sqlViewName: 'ZVDM_V_SALES'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Consumption(Sales Information)'
@VDM.viewType: #CONSUMPTION
@OData.publish: true
@Search.searchable: true
define view ZVDM_C_SALES
//with parameters
//@EndUserText.label: 'Sales Orgnization'
//@Consumption.defaultValue: 'US01'
//p_salesorg: vkorg
as select from ZVDM_CO_SALES
{
//ZVDM_CO_SALES
@EndUserText.label: 'Sales Order Number'
@EndUserText.quickInfo: 'Sales Order NO'
@UI.lineItem: [{position:10 ,importance: #HIGH}]
@UI.selectionField: [{position: 10}]
@ObjectModel.foreignKey.association: '_VBAK'
@Search.defaultSearchElement: true
key SalesDocument,
@EndUserText.label: 'Sales Order Item Number'
@EndUserText.quickInfo: 'Sales Order Item NO'
@UI.lineItem: [{position:20 }]
key SalesDocumentItem,
@EndUserText.label: 'Follow On Document'
@EndUserText.quickInfo: 'Delivery Document'
@UI.lineItem: [{position:30, importance: #HIGH}]
Status,
@EndUserText.label: 'Material Number'
@EndUserText.quickInfo: 'Material NO'
@UI.lineItem: [{position: 30}]
materialNumber,
@EndUserText.label: 'Material Dec'
@EndUserText.quickInfo: 'Material Descrption'
@UI.lineItem: [{position: 40}]
MaterialDescrption,
@EndUserText.label: 'Sales Orgnization'
@EndUserText.quickInfo: 'Sales Org'
@UI.lineItem: [{position: 50}]
SalesOrganization as SalesOrganization,
@EndUserText.label: 'Sales Doc Type'
@UI.lineItem: [{position: 60}]
_vbak.SalesDocumentType as SalesDocType,
@UI.lineItem: [{position: 70}]
_vbak.DistributionChannel as DChannel,
@UI.hidden: true
SalesDocumentItemText,
@UI.hidden: true
UnderlyingPurchaseOrderItem,
@UI.lineItem: [{position: 80}]
DeliveryDocument,
@UI.lineItem: [{position: 90}]
DeliveryDocumentItem,
@UI.lineItem: [{position: 110}]
@Semantics.unitOfMeasure: true
OrderQuantityUnit,
@UI.lineItem: [{position: 130}]
@Semantics.unitOfMeasure: true
TargetQuantityUnit,
@UI.lineItem: [{position: 150}]
@Semantics.currencyCode: true
TransactionCurrency,
NetPriceAmount,
ShippingPoint,
Plant,
StorageLocation,
Route,
OriginSDDocument,
OriginSDDocumentItem,
ReferenceSDDocumentCategory,
HigherLevelItem,
SDProcessStatus,
SDDocumentRejectionStatus,
DeliveryDocumentItemCategory,
StorageBin,
StorageType,
DeliveryDocumentItemText,
DELIVERYQUNATITYUNIT,
ActualDeliveryQuantity,
OriginalDeliveryQuantity,
BaseUnit,
DeliveryStatus,
DeliveryRelatedBillingStatus,
SalesSDDocumentCategory,
//Aggregations
@Semantics.quantity.unitOfMeasure: 'ORDERQUANTITYUNIT'
@DefaultAggregation:#SUM
@UI.lineItem: [{position: 100}]
OrderQuantity,
@Semantics.quantity.unitOfMeasure: 'TARGETQUANTITYUNIT'
@DefaultAggregation:#SUM
@UI.lineItem: [{position: 120}]
TargetQuantity,
@Semantics.amount.currencyCode: 'TRANSACTIONCURRENCY'
@DefaultAggregation:#SUM
@UI.lineItem: [{position: 140}]
NetAmount,
/* Associations */
//ZVDM_CO_SALES
_vbak,
_LIPS,
_Material,
_MaterialText,
_Partneritem
}
OData Service Activation
When we create OData from CDS using annotation, we need to go to the backend SAP System and perform this step manually one time. After we activate the OData Service and create the related DPC and MPC and add the OData Service to the Service Catalog, we do not need to perform this step again, even if we make changes in the original CDS Views.
Let’s see, how we activate the OData Service.
Open the t-code /n/iwfnd/maint_service and press the Add Service button.
In the Add Selected Services screen provide a System Alias, and then press the Get Services button. The Technical Service Name field, ZVDM_C_SALES, can be provided to filter the results if necessary.
Selecting the service should result in the Add Service dialog appearing. Here you can assign it a package and choose the enter button to complete the process.
The above steps would activate the OData Service and Add it to the Service Catalog. Once it is in the Service Catalog, it is ready to be consumed in the WebIDE while developing Fiori Apps.
If you go back to /N/IWFND/MAINT_SERVICE t-code, you should see your OData Service in the Service Catalog.
Choose your OData and click on SAP Gateway Client (or go to t-code /N/IWFND/GW_CLIENT) to test your OData Service. If it returns status code 200, you are all set. Your OData is working correctly.
Did you notice, the OData Service name is your CDS View name with a suffix _CDS?
Create Fiori Apps Using CDS Views & UI Annotations
Exercise 6 – Fiori Apps using List Report Template
Create Fiori App from Standard Template using SAP WebIDE Full-Stack. This SAP WebIDE Full-Stack will open from SAP Cloud Platform Cockpit.
We connected Cloud Connector and SAP Cloud Platform Cockpit.
Once you are in the WebIDE, select Project from Template in the SAP WebIDE Full-Stack and select the List Report Application.
Select the SAP Backend System and OData Service and click on finish button.
Once, finished, you may Deploy the App to your ABAP repository. You need to do this step, only if you are planning to move your App to your next SAP environment say Quality and then to Production using Transport. For testing, you may skip this step.
Select SAP System and give application name and description. Select the transport request and confirm it so your application is deployed to the backend SAP System.
Now, let’s test our App.
Did you realize? We did not write an single line of code in the App in WebIDE and we are ready to test out of the box. That is the beauty of creating App using CDS/VDM Views.
Click on Run-> Run as Web Application
Select the flpSandbox.html file
Our Fiori App is ready. Click on our app (ZSALES_REPORT).
It will show a blank output.
You need to click on Go button to see the report.
Fiori App display will change based on the Semantics annotations, UI Annotations, Text Annotations.
We can use different annotations for Charts, Header Info, Images, Navigation etc.
Exercise 7 – Fiori Overview Page Report(OVP) Template
We will not go in to the details of this template but we will just explain few annotations.
Annotation @UI.headerInfo: Use this annotation to define the typeName which will be shown as the card header, as well as a title and header.
@UI.headerInfo: {
typeNamePlural: ‘Sales Orders’,
// imageUrl: ‘VenkatImg’,
typeName: ‘Sales Order’,
title: {
label: ‘Order ID’,
value: ‘SalesDocument’
},
description: {
label: ‘Customer’,
value: ‘Customer’
}
}
Annotation @UI.identification: Used for navigating from one view to other view using Semantic Navigation.
@UI.identification: {type: #FOR_INTENT_BASED_NAVIGATION, semanticObjectAction: ”, label: ”, position: ”}
Annotation @UI.chart : Used for displaying the Charts in the Fiori app.
@UI.chart:[{
qualifier: ‘chartLineItem’,
title:’Order Net Amount’,
chartType: #COLUMN,
dimensions: [‘SalesDocument’],
measures: [‘NetAmount’, ‘NetPriceAmount’],
dimensionAttributes: {dimension: ‘SalesDocument’, role:#SERIES},
measureAttributes: [{measure: ‘NetAmount’, role: #AXIS_1}, {measure:
NetPriceAmount’, role: #AXIS_1}]
}]
Annotation @UI.dataPoint : Used for displaying the KPI values.
@UI.dataPoint: {title: ‘Net Amt’,
criticalityCalculation: {
improvementDirection: #TARGET,
deviationRangeLowValue: 000,
toleranceRangeLowValue: 600,
toleranceRangeHighValue: 1000,
deviationRangeHighValue: 1400
}}
@AbapCatalog.sqlViewName: 'ZVDM_V_SALES1'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Sales OVP Report'
@VDM.viewType: #CONSUMPTION
@OData.publish: true
@Search.searchable: true
@UI.headerInfo: {
typeNamePlural: 'Sales Orders',
// imageUrl: 'mytestImg',
typeName: 'Sales Order',
title: {
label: 'Order ID',
value: 'SalesDocument'
},
description: {
label: 'Customer',
value: 'Customer'
}
}
@UI.chart:[{
qualifier: 'chartLineItem',
title:'Order Net Amount',
chartType: #COLUMN,
dimensions: ['SalesDocument'],
measures: ['NetAmount', 'NetPriceAmount'],
dimensionAttributes: {dimension: 'SalesDocument', role:#SERIES},
measureAttributes: [{measure: 'NetAmount', role: #AXIS_1}, {measure: 'NetPriceAmount', role: #AXIS_1}]
}]
@UI.presentationVariant: [{qualifier: 'top5Changed', maxItems: '5', sortOrder.by: 'SalesDocument', sortOrder.direction: #DESC }]
define view ZVDM_C_SALES1
//with parameters
//@EndUserText.label: 'Sales Orgnization'
//@Consumption.defaultValue: 'US01'
//p_salesorg: vkorg
as select from ZVDM_CO_SALES
{
//ZVDM_CO_SALES
// @EndUserText.label: 'Sales Order Number'
// @EndUserText.quickInfo: 'Sales Order NO'
@UI.lineItem: [{position:10 ,qualifier: 'ordOverView',importance: #HIGH,label: 'Sales Order'}] --,{qualifier: 'chartLineItem'}]
@UI.selectionField: [{position: 10}]
//@ObjectModel.foreignKey.association: '_VBAK'
@Search.defaultSearchElement: true
key SalesDocument,
// @EndUserText.label: 'Sales Order Item Number'
// @EndUserText.quickInfo: 'Sales Order Item NO'
// @UI.lineItem: [{position:20 }]
key SalesDocumentItem,
@UI.selectionField: [ { position: 20 } ]
@UI.lineItem: { position: 20, qualifier:'ordOverView', label: 'Customer' }
_Partneritem.Customer as Customer,
// @EndUserText.label: 'Follow On Document'
// @EndUserText.quickInfo: 'Delivery Document'
// // @UI.lineItem: [{position:30, importance: #HIGH}]
// @UI.identification: [{position: 10}]
// @UI.fieldGroup: [{qualifier: 'Account Group' }]
Status,
// @EndUserText.label: 'Material Number'
// @EndUserText.quickInfo: 'Material NO'
// @UI.lineItem: [{position: 30}]
@UI.identification: [{position: 10}]
materialNumber,
_vbak.CreatedByUser as CreatedBy,
// @EndUserText.label: 'Material Dec'
// @EndUserText.quickInfo: 'Material Descrption'
// @UI.lineItem: [{position: 40}]
@UI.identification: [{position: 20}]
MaterialDescrption,
// @EndUserText.label: 'Sales Orgnization'
// @EndUserText.quickInfo: 'Sales Org'
// @UI.lineItem: [{position: 50}]
SalesOrganization as SalesOrganization,
// @EndUserText.label: 'Sales Doc Type'
// @UI.lineItem: [{position: 60}]
_vbak.SalesDocumentType as SalesDocType,
// @UI.lineItem: [{position: 70}]
_vbak.DistributionChannel as DChannel,
@UI.hidden: true
SalesDocumentItemText,
@UI.hidden: true
UnderlyingPurchaseOrderItem,
// @UI.lineItem: [{position: 80}]
DeliveryDocument,
// @UI.lineItem: [{position: 90}]
DeliveryDocumentItem,
// @UI.lineItem: [{position: 110}]
@Semantics.unitOfMeasure: true
OrderQuantityUnit,
// @UI.lineItem: [{position: 130}]
@Semantics.unitOfMeasure: true
TargetQuantityUnit,
// @UI.lineItem: [{position: 150}]
@Semantics.currencyCode: true
TransactionCurrency,
// @UI.identification: [{position: 20}]
// @UI.fieldGroup: [{qualifier: 'Account Group' }]
@UI.dataPoint: {title: 'Price Amount', valueFormat:{ numberOfFractionalDigits: 2 }}
@UI.lineItem: [{ position: 40, qualifier:'ordOverView', label: 'Tax Amount', type: #AS_DATAPOINT},{qualifier: 'chartLineItem'}]
@Semantics.amount.currencyCode: 'TransactionCurrency'
NetPriceAmount,
ShippingPoint,
Plant,
StorageLocation,
Route,
OriginSDDocument,
OriginSDDocumentItem,
ReferenceSDDocumentCategory,
HigherLevelItem,
SDProcessStatus,
SDDocumentRejectionStatus,
DeliveryDocumentItemCategory,
StorageBin,
StorageType,
DeliveryDocumentItemText,
DELIVERYQUNATITYUNIT,
ActualDeliveryQuantity,
OriginalDeliveryQuantity,
BaseUnit,
DeliveryStatus,
DeliveryRelatedBillingStatus,
SalesSDDocumentCategory,
//Aggregations
@Semantics.quantity.unitOfMeasure: 'ORDERQUANTITYUNIT'
@DefaultAggregation:#SUM
// @UI.lineItem: [{position: 100}]
OrderQuantity,
@Semantics.quantity.unitOfMeasure: 'TARGETQUANTITYUNIT'
@DefaultAggregation:#SUM
// @UI.lineItem: [{position: 120}]
TargetQuantity,
@Semantics.amount.currencyCode: 'TRANSACTIONCURRENCY'
@DefaultAggregation:#SUM
// @UI.lineItem: [{position: 140}]
@UI.dataPoint: {title: 'Net Amt',
criticalityCalculation: {
improvementDirection: #TARGET,
deviationRangeLowValue: 000,
toleranceRangeLowValue: 600,
toleranceRangeHighValue: 1000,
deviationRangeHighValue: 1400
}}
@UI.lineItem: [{ position: 30, qualifier:'ordOverView', label: 'Net Amount', type: #AS_DATAPOINT},{ qualifier: 'chartLineItem'}]
NetAmount,
/* Associations */
//ZVDM_CO_SALES
_vbak,
_LIPS,
_Material,
_MaterialText,
_Partneritem
}
To get the above OVP results we have to change some code in the Manifest.jason file in the WebIDE tool.
As promised in the beginning of this article, we completed Transient Provider, Analysis For Office and Smart Template Application based on CDS VDM Views.
You can explore more about the annotations in CDS views and surprise yourself.
This is my first article at Technicalgyanguru. Your suggestions are welcomed. Do let me know what topics you want me to cover in Core Data Services and Virtual Data Models.