ABAP Development, ABAP RESTful Programming Model, SAP S/4HANA Cloud

Transactional Fiori App using ABAP Restful Programming Model

UI Apps development is getting simplified with the evolution of ABAP. In my experience when UI5 was released i had to learn JavaScript ,jQuery concepts and use them to create even a simple UI App ,and then with the advent of ABAP Programming model for Fiori it changed the approach, since using BOPF with annotations we can easily create simple Transactional UI app’s with minimal frontend code. Now with ABAP RAP programming which is an evolution of latter, it further simplified and made flexible for UI App development.

In this blog, i had taken a very simple use case without any custom business logic which is managed by the framework itself and developed a simple Fiori application, of course we can further extend this app with complex use cases.

I had used ABAP Cloud environment which is hosted in SAP Cloud Platform.

Overview

Below are various sequence of objects i had created as in below table.

Steps          
1 Tables Created   ZSO_HDR  ZSO_ITM  ZSO_STAT   
Interface CDS Views ZSO_HDR_I   ZSO_ITM_I  ZSO_STAT_I ZSO_ITM_STAT_I 
Consumption CDS Views     ZSO_ITM_C  ZSO_STAT_C  ZSO_ITM_STAT_C 
Behavior Definitions     ZSO_ITM_I &
ZSO_ITM_C
ZSO_STAT_I &
ZSO_STAT_C 
ZSO_ITM_STAT_I &
ZSO_ITM_STAT_C 
Service Definition         ZSRV_SO_ITM_STAT 
Service Binding         ZBIN_SO_ITM_STAT 

1. Tables Created:

ZSO_HDR

@EndUserText.label : 'Custom Sales Order Header'
@AbapCatalog.enhancementCategory : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #ALLOWED
define table zso_hdr {
  key client : abap.clnt not null;
  key so     : zso not null;
  @Semantics.amount.currencyCode : 'zso_hdr.curr'
  net_val    : abap.curr(10,2);
  curr       : abap.cuky;
  @Semantics.quantity.unitOfMeasure : 'zso_hdr.uom'
  net_qty    : abap.quan(10,2);
  uom        : abap.unit(2);

}

ZSO_ITM

@EndUserText.label : 'Custom Sales Order Item'
@AbapCatalog.enhancementCategory : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #ALLOWED
define table zso_itm {
  key client : abap.clnt not null;
  @AbapCatalog.foreignKey.keyType : #KEY
  @AbapCatalog.foreignKey.screenCheck : true
  key so     : zso not null
    with foreign key [0..*,1] zso_hdr
      where so = zso_itm.so;
  key posnr  : zitem not null;
  matnr      : abap.char(30);
  @Semantics.quantity.unitOfMeasure : 'zso_itm.uom'
  qty        : abap.quan(10,2);
  uom        : abap.unit(2);

}

ZSO_STAT

@EndUserText.label : 'Custom Sales Order Item Status'
@AbapCatalog.enhancementCategory : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #ALLOWED
define table zso_stat {
  key client : abap.clnt not null;
  @AbapCatalog.foreignKey.screenCheck : true
  key so     : zso not null
    with foreign key [0..*,1] zso_itm
      where so = zso_stat.so;
  key posnr  : zitem not null;
  status     : zstat;

}

2. Interface CDS Views:

ZSO_HDR_I

@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Interface view for ZSO_HDR'
define root view entity ZSO_HDR_I as select from zso_hdr
{
    //ZSO_HDR
    key so,
    net_val,
    curr,
    net_qty,
    uom
     // Make association public
}

ZSO_ITM_I

@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Interface view for ZSO_ITM'
define root view entity zso_itm_i
  as select from zso_itm
  
{
      //ZSO_ITM
  key so,
  key posnr,
      matnr,
      qty,
      uom

}

ZSO_STAT_I

@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Interface view for ZSO_STAT'
define root view entity zso_stat_i as select from zso_stat
 {
    //ZSO_STAT
    key so,
    key posnr,
    status  
}

ZSO_ITM_STAT_I

@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'INterface view for Zso_hdr_i & Zso_stat_i & Zso_itm_i'
define root view entity zso_itm_stat_i as select from ZSO_HDR_I
association [0..*] to zso_itm_i   as item on  item.so   = $projection.so
association [0..*] to zso_stat_i  as stat on  stat.so   = $projection.so
 {
    //ZSO_HDR
    key so,
    net_val,
    curr,
    net_qty,
    uom,
    item, // Make association public
    stat
}

3. Consumption CDS Views:

ZSO_ITM_C

@EndUserText.label: 'Consumption view for Zso_itm_i'
@AccessControl.authorizationCheck: #CHECK

@UI: { headerInfo: { title.label: 'SO Item Info',title.type: #STANDARD,
                     typeName: 'SO Item',typeNamePlural: 'SO Items'}}
define root view entity zso_itm_c
  as projection on zso_itm_i
{
      @UI.facet: [{ id: 'POSNR',position: 10,label: 'SO Item Details',type: #IDENTIFICATION_REFERENCE }]
      @UI.lineItem: [{position: 10,type: #STANDARD }]
      @UI.identification: [{position: 10,type: #STANDARD }]
  key so,
      @UI.lineItem: [{position: 20,type: #STANDARD }]
      @UI.identification: [{position: 20,type: #STANDARD }]
  key posnr,
      @UI.lineItem: [{position: 30,type: #STANDARD,label: 'Material' }]
      @UI.identification: [{position: 30,type: #STANDARD,label: 'Material' }]
      matnr,
      @UI.lineItem: [{position: 40,type: #STANDARD,label: 'Qty' }]
      @UI.identification: [{position: 50,type: #STANDARD,label: 'Qty' }]
      qty,
      @UI.lineItem: [{position: 50,type: #STANDARD,label: 'UOM' }]
      @UI.identification: [{position: 50,type: #STANDARD,label: 'UOM' }]
      @Consumption.valueHelpDefinition: [{entity:{ element: 'UnitOfMeasure',name: 'I_UnitOfMeasureStdVH'} }] 
      uom
}

ZSO_STAT_C

@EndUserText.label: 'Consumption view for Zso_stat_i'
@AccessControl.authorizationCheck: #CHECK

@UI: { headerInfo: { title.label: 'SO Item Status',title.type: #STANDARD,
                     typeName: 'SO Item Status',typeNamePlural: 'SO Items Status'}}
                     
define root view entity zso_stat_c as projection on zso_stat_i {
    //ZSO_STAT_I
      @UI.facet: [{ id: 'STAT',position: 10,label: 'SO Item STatus',type: #IDENTIFICATION_REFERENCE }]
      @UI.lineItem: [{position: 10,type: #STANDARD }]
      @UI.identification: [{position: 10,type: #STANDARD }]    
    key so,
      @UI.lineItem: [{position: 20,type: #STANDARD }]
      @UI.identification: [{position: 20,type: #STANDARD }]    
    key posnr,
      @UI.lineItem: [{position: 30,type: #STANDARD }]
      @UI.identification: [{position: 30,type: #STANDARD }]    
    status
}

ZSO_ITM_STAT_C

@EndUserText.label: 'Consumption view for Zso_hdr_i & Zso_stat_i & Zso_itm_i'
@AccessControl.authorizationCheck: #CHECK


@UI: { headerInfo: { title.label: 'SO Info',title.type: #STANDARD,
                     typeName: 'SO Info',typeNamePlural: 'SO'}}
                     
define root view entity zso_itm_stat_c as projection on zso_itm_stat_i {

@UI.facet: [{ id: 'SO',position: 10,label: 'SO Details',type: #COLLECTION },
            { position: 20,label: 'SO Item Details',type:#LINEITEM_REFERENCE,targetElement: 'item'}, 
            { position: 30,label: 'SO Item Status',type:#LINEITEM_REFERENCE,targetElement: 'stat'},            
            { id: 'FLD',parentId: 'SO',position: 10,type: #FIELDGROUP_REFERENCE,targetQualifier: 'GP'}]   
            
@UI.lineItem: [{position: 10}]
@UI.fieldGroup: [{qualifier: 'GP',position: 10 }] 
@UI.selectionField: [{position: 10}]
    key so,
@UI.lineItem: [{position: 20,label:'Net Value'}]
@UI.fieldGroup: [{qualifier: 'GP',position: 30,label:'Net Value' }]    
    net_val,
@UI.lineItem: [{position: 30,label:'Currency'}]
@UI.fieldGroup: [{qualifier: 'GP',position: 50,label:'Currency' }]  
@Consumption.valueHelpDefinition: [{entity:{ element: 'Currency',name: 'I_CurrencyStdVH'} }]  
    curr,
@UI.lineItem: [{position: 40,label:'Net Qty'}]
@UI.fieldGroup: [{qualifier: 'GP',position: 20,label:'Net Qty' }]    
    net_qty,
@UI.lineItem: [{position: 50,label:'UOM'}]
@UI.fieldGroup: [{qualifier: 'GP',position: 40 ,label:'UOM'}]    
@Consumption.valueHelpDefinition: [{entity:{ element: 'UnitOfMeasure',name: 'I_UnitOfMeasureStdVH'} }] 
    uom,
    /* Associations */
    //zso_itm_stat_i
    item : redirected to zso_itm_c,
    stat : redirected to zso_stat_c    
}

4. Behavior Definitions:

ZSO_STAT_I & ZSO_STAT_C

ZSO_STAT_I

managed; // implementation in class zbp_so_stat_i unique;

define behavior for zso_stat_i alias STATI
persistent table zso_stat
lock master
//authorization master ( instance )
//etag master <field_name>
{
  create;
  update;
  delete;
}

ZSO_STAT_C

projection;

define behavior for zso_stat_c alias STATC
{
  use create;
  use update;
  use delete;
}

ZSO_ITM_I & ZSO_ITM_C

ZSO_ITM_I

managed; // implementation in class zbp_so_itm_i unique;

define behavior for zso_itm_i alias ITEMI
persistent table zso_itm
lock master
//authorization master ( instance )
//etag master <field_name>
{
  create;
  update;
  delete;
}

ZSO_ITM_C
projection;

define behavior for zso_itm_c alias ITEMC
{
  use create;
  use update;
  use delete;
}

ZSO_ITM_STAT_I & ZSO_ITM_STAT_C

ZSO_ITM_STAT_I

managed; // implementation in class zbp_so_itm_stat_i unique;

define behavior for zso_itm_stat_i alias SOINFOI
persistent table zso_hdr
lock master
//authorization master ( instance )
//etag master <field_name>
{
  create;
  update;
  delete;

}

ZSO_ITM_STAT_C

projection;

define behavior for zso_itm_stat_c alias SOINFOC
{
  use create;
  use update;
  use delete;
}

5. Service Definition:

ZSRV_SO_ITM_STAT

@EndUserText.label: 'Service for Transaction App of SO'
define service ZSRV_SO_ITM_STAT {
  expose zso_itm_stat_c;
  expose zso_itm_c;
  expose zso_stat_c;
}

6. Service Binding:

7. Fiori Application :

Double click on zso_itm_stat_c in service binding or click Preview .

Click Create add details

Create Line Item Entries & Status Entries for Sales Order using ZSO_ITM_C & ZSO_STAT_C

ZSO_ITM_C–> Item level App

Click Create and add details

Similarly add Status for items for ZSO_STAT_C

And after adding data in the final app on ZSO_ITM_STAT_C we can see the data flow.

Using this App on Click on Header EDIT button we edit all details ,just to note in this App Create button functionality of SO Item Details & Status Details may not work since we need to do Behavior Implementations for those, but individual Apps of SO Item Details & Status will work without any issues for Create as in above screenshots of ZSO_ITM_C & ZSO_STAT_C.

Restful ABAP Programming has simplified the Fiori App development as we can use CDS views with annotations and behavior implementations to create complex or simple UI Apps.

Leave a Reply

Your email address will not be published. Required fields are marked *