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 | |
2 | Interface CDS Views | ZSO_HDR_I | ZSO_ITM_I | ZSO_STAT_I | ZSO_ITM_STAT_I |
3 | Consumption CDS Views | ZSO_ITM_C | ZSO_STAT_C | ZSO_ITM_STAT_C | |
4 | Behavior Definitions | ZSO_ITM_I & ZSO_ITM_C |
ZSO_STAT_I & ZSO_STAT_C |
ZSO_ITM_STAT_I & ZSO_ITM_STAT_C |
|
5 | Service Definition | ZSRV_SO_ITM_STAT | |||
6 | 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.