Skip to content

Analytical List Page whit ABAP CDS views and annotations

Notifications You must be signed in to change notification settings

GonzaloMB/z_demo_flight_cds

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

6 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Analytical List Page | ABAP CDS | UI5 πŸ–₯️

Create an Analytical List Page using ABAP CDS views and annotations.

Starting πŸš€

Analytical List Page is a powerful Fiori Element available since SAPUI5 innovation version 1.48, this template provides the ability to create an analytical dashboard with KPIs, charts, tables and also a drill-down navigation to a detail page.

You can find all the relevant information about Analytical List Pages in the SAP Fiori Design Guideline.

Pre-requirements πŸ“‹

Tools you need to be able to develop this application

  • SAP Logon
  • SAP Cloud Connector (SCC)
  • SAP Cloud Platform (SCP) or SAP Business Technology Platform (BTP)
  • Eclipse
  • SAP Web IDE or SAP BAS

Practical case βš™οΈ

In this application we are going to develop both the back-end and the front-end part

Back-end πŸ”©

1. ABAP CDS

  • DIMENSION: Airline
@AbapCatalog.sqlViewName: 'ZDIMEAIRLINE'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Airline'

@Analytics.dataCategory: #DIMENSION

define view Z_Dimension_Airline
  as select from scarr
{
      @ObjectModel.text.element: [ 'AirlineName' ]
  key carrid   as Airline,
  
      @Semantics.text: true
      carrname as AirlineName,
      
      @Semantics.currencyCode: true
      currcode as Currency
} 
  • DIMENSION: Connection
@AbapCatalog.sqlViewName: 'ZDIMECONNECT'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Flight Connection'

@Analytics.dataCategory: #DIMENSION

@ObjectModel.representativeKey: 'FlightConnection'

define view Z_Dimension_Connection
  as select from spfli
  association [0..1] to Z_Dimension_Airline as _Airline on $projection.Airline = _Airline.Airline
{
      @ObjectModel.foreignKey.association: '_Airline'
  key carrid                    as Airline,

      @ObjectModel.text.element: [ 'Destination' ]
  key connid                    as FlightConnection,

      @Semantics.text: true
      concat(cityfrom,
        concat(' -> ', cityto)) as Destination,

      _Airline
} 
  • DIMENSION: Customer
@AbapCatalog.sqlViewName: 'ZDIMECUSTOMER'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Flight Customer'

@Analytics.dataCategory: #DIMENSION

define view Z_Dimension_Customer
  as select from scustom
  association [0..1] to I_Country as _Country on $projection.Country = _Country.Country
{
      @ObjectModel.text.element: [ 'CustomerName' ]
  key id      as Customer,

      @Semantics.text: true
      name    as CustomerName,

      @ObjectModel.foreignKey.association: '_Country'
      @Semantics.address.country: true
      country as Country,

      @Semantics.address.city: true
      city    as City,
      
      _Country
} 
  • DIMENSION: Travel Agency
@AbapCatalog.sqlViewName: 'ZDIMETRVAGENCY'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Travel Agency'

@Analytics.dataCategory: #DIMENSION

define view Z_Dimension_TravelAgency
  as select from stravelag
  association [0..1] to I_Country as _Country on $projection.Country = _Country.Country
{
      @ObjectModel.text.element: [ 'TravelAgencyName' ]
  key agencynum as TravelAgency,

      @Semantics.text: true
      name      as TravelAgencyName,

      @ObjectModel.foreignKey.association: '_Country'
      @Semantics.address.country: true
      country   as Country,

      @Semantics.address.city: true
      city      as City,
      
      _Country
} 
  • CUBE: Flight Bookings
@AbapCatalog.sqlViewName: 'ZCUBEFLIGHTBOOK'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Flight Bookings'

@Analytics.dataCategory: #CUBE

define view Z_Cube_FlightBookings
  as select from sbook
  association [0..1] to I_CalendarDate           as _CalendarDate on  $projection.FlightDate = _CalendarDate.CalendarDate
  association [0..1] to Z_Dimension_Airline      as _Airline      on  $projection.Airline = _Airline.Airline
  association [0..1] to Z_Dimension_Connection   as _Connection   on  $projection.Airline          = _Connection.Airline
                                                                  and $projection.FlightConnection = _Connection.FlightConnection
  association [0..1] to Z_Dimension_Customer     as _Customer     on  $projection.Customer = _Customer.Customer
  association [0..1] to Z_Dimension_TravelAgency as _TravelAgency on  $projection.TravelAgency = _TravelAgency.TravelAgency
{
  /** DIMENSIONS **/

  @EndUserText.label: 'Airline'
  @ObjectModel.foreignKey.association: '_Airline'
  carrid                 as Airline,

  @EndUserText.label: 'Connection'
  @ObjectModel.foreignKey.association: '_Connection'
  connid                 as FlightConnection,

  @EndUserText.label: 'Flight Date'
  @ObjectModel.foreignKey.association: '_CalendarDate'
  fldate                 as FlightDate,

  @EndUserText.label: 'Book No.'
  bookid                 as BookNumber,

  @EndUserText.label: 'Customer'
  @ObjectModel.foreignKey.association: '_Customer'
  customid               as Customer,

  @EndUserText.label: 'Travel Agency'
  @ObjectModel.foreignKey.association: '_TravelAgency'
  agencynum              as TravelAgency,

  @EndUserText.label: 'Flight Year'
  _CalendarDate.CalendarYear,

  @EndUserText.label: 'Flight Month'
  _CalendarDate.CalendarMonth,

  @EndUserText.label: 'Customer Country'
  @ObjectModel.foreignKey.association: '_CustomerCountry'
  _Customer.Country      as CustomerCountry,

  @EndUserText.label: 'Customer City'
  _Customer.City         as CustomerCity,

  @EndUserText.label: 'Travel Agency Country'
  @ObjectModel.foreignKey.association: '_TravelAgencyCountry'
  _TravelAgency.Country  as TravelAgencyCountry,

  @EndUserText.label: 'Travel Agency Customer City'
  _TravelAgency.City     as TravelAgencyCity,

  /** MEASURES **/

  @EndUserText.label: 'Total of Bookings'
  @DefaultAggregation: #SUM
  1                      as TotalOfBookings,

  @EndUserText.label: 'Weight of Luggage'
  @DefaultAggregation: #SUM
  @Semantics.quantity.unitOfMeasure: 'WeightUOM'
  luggweight             as WeightOfLuggage,

  @EndUserText.label: 'Weight Unit'
  @Semantics.unitOfMeasure: true
  wunit                  as WeightUOM,

  @EndUserText.label: 'Booking Price'
  @DefaultAggregation: #SUM
  @Semantics.amount.currencyCode: 'Currency'
  forcuram               as BookingPrice,

  @EndUserText.label: 'Currency'
  @Semantics.currencyCode: true
  forcurkey              as Currency,

  // Associations
  _Airline,
  _CalendarDate,
  _CalendarDate._CalendarMonth,
  _CalendarDate._CalendarYear,
  _Connection,
  _Customer,
  _Customer._Country     as _CustomerCountry,
  _TravelAgency,
  _TravelAgency._Country as _TravelAgencyCountry
} 
  • QUERY: Flight Bookings
@AbapCatalog.sqlViewName: 'ZQUERYFLIGHTBOOK'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Flight Bookings'

@Analytics.query: true
@VDM.viewType: #CONSUMPTION

define view Z_Query_FlightBookings
  as select from Z_Cube_FlightBookings
{
    /** DIMENSIONS **/
    
    @AnalyticsDetails.query.display: #KEY_TEXT
    @AnalyticsDetails.query.axis: #FREE
    Airline, 
    @AnalyticsDetails.query.display: #KEY_TEXT
    @AnalyticsDetails.query.axis: #FREE
    FlightConnection, 
    @AnalyticsDetails.query.display: #KEY
    @AnalyticsDetails.query.axis: #FREE
    FlightDate, 
    @AnalyticsDetails.query.display: #KEY_TEXT
    @AnalyticsDetails.query.axis: #FREE
    Customer, 
    @AnalyticsDetails.query.display: #KEY_TEXT
    @AnalyticsDetails.query.axis: #FREE
    TravelAgency, 
    @AnalyticsDetails.query.display: #KEY
    @AnalyticsDetails.query.axis: #FREE
    CalendarYear,
    @AnalyticsDetails.query.display: #TEXT
    @AnalyticsDetails.query.axis: #FREE
    CalendarMonth,
    @AnalyticsDetails.query.display: #TEXT
    @AnalyticsDetails.query.axis: #FREE
    CustomerCountry,
    @AnalyticsDetails.query.display: #KEY
    @AnalyticsDetails.query.axis: #FREE
    CustomerCity,
    @AnalyticsDetails.query.display: #TEXT
    @AnalyticsDetails.query.axis: #FREE
    TravelAgencyCountry,
    @AnalyticsDetails.query.display: #KEY
    @AnalyticsDetails.query.axis: #FREE
    TravelAgencyCity,
    @AnalyticsDetails.query.display: #KEY
    @AnalyticsDetails.query.axis: #FREE
    Currency,
    @AnalyticsDetails.query.display: #KEY
    @AnalyticsDetails.query.axis: #FREE
    WeightUOM,
    
    /** MEASURES **/
    
    TotalOfBookings, 
    WeightOfLuggage,
    BookingPrice,
    
    @EndUserText.label: 'Average Weight Per Flight'
    @AnalyticsDetails.exceptionAggregationSteps.exceptionAggregationBehavior: #AVG
    @AnalyticsDetails.exceptionAggregationSteps.exceptionAggregationElements: [ 'Airline', 'FlightConnection', 'FlightDate' ]
    @AnalyticsDetails.query.formula: '$projection.WeightOfLuggage'
    @AnalyticsDetails.query.decimals: 0
    0 as AverageWeightPerFlight
} 

Front-End ⌨️

2. UI5 Fiori elements applications (Web IDE)

  • Select Analytical List Page as the template.

image

  • Fill the project name, title, namespace and description.

image

  • Select the OData service Z_QUERY_FLIGHT_ALP_CDS.

image

  • Select the remote annotation file to expose the annotations generated through the ABAP CDS view, this file contains the XML output demonstrated in the previous section.

image

  • Define the template configuration:

    ** OData Collection: Z_QUERY_FLIGHT_ALP ** Qualifier: Default ** Table Type: Responsive ** Auto Hide: TRUE

image

  • Press Finish to conclude the Web IDE wizard. This is the structure of your project after you conclude all the steps.

image

Inside the manifest.json we can find the code generated automatically based on our previous configuration through the Web IDE wizard.

KPI (manifest.json) Place this snippet of code inside the keyPerformanceIndicators attribute:

"keyPerformanceIndicators": { "WeightByCountry": { "model": "kpi", "entitySet": "Z_QUERY_FLIGHT_ALP", "qualifier": "KPIWeightByCountry" } } Don’t forget to create a new model called kpi pointing to your data souce, in my example the model references the mainService data source but you could use a different source if you want.

  • KPI (manifest.json)
 "keyPerformanceIndicators": {
      "WeightByCountry": {
          "model": "kpi",
          "entitySet": "ZQUERYFLIGHTALP",
          "qualifier": "KPIWeightByCountry"
      }
  }

*Create a new model called kpi pointing to your data souce

image

  • Visual Filter (annotation.xml)

image image

This is the code generated :

<Annotations Target="Z_QUERY_FLIGHT_ALP_CDS.Z_QUERY_FLIGHT_ALPType/CalendarYear">
    <Annotation Term="Common.ValueList">
        <Record Type="Common.ValueListType">
            <PropertyValue Property="CollectionPath" String="Z_QUERY_FLIGHT_ALP"/>
            <PropertyValue Property="Parameters"/>
            <PropertyValue Property="PresentationVariantQualifier" String="FilterBookingsByYear"/>
        </Record>
    </Annotation>
</Annotations>
  • Object Page (annotation.xml)

image

This is the code generated :

<Annotation Term="UI.Facets">
    <Collection>
        <Record Type="UI.CollectionFacet">
            <PropertyValue Property="ID" String="MainSection"/>
            <PropertyValue Property="Label" String="{@i18n&gt;DETAILS}"/>
            <PropertyValue Property="Facets">
                <Collection>
                    <Record Type="UI.ReferenceFacet">
                        <PropertyValue Property="Target" AnnotationPath="@UI.LineItem"/>
                    </Record>
                </Collection>
            </PropertyValue>
        </Record>
    </Collection>
</Annotation>

Testing the Analytical List Page πŸ‘¨β€πŸ’»

Analytical.Lis.Page.mp4

Acknowledgement πŸ“š

  • ABAP CDS
  • Fiori Elements
  • Annotations
  • UI5

Built with πŸ› οΈ

Back-end:

  • ABAP CDS

Gateway:

  • oData

Front-End:

  • UI5
  • Fiori Elements
  • Annotations

⌨️ with ❀️ love GonzaloMB 😊

About

Analytical List Page whit ABAP CDS views and annotations

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published