Tuesday, 15 December 2020

Extending SAP Fiori App: My Inbox – Approve Purchase Requisitions (F0401A)

Overview

The intent of this blog post is to provide some initial insight in extending the standard SAP Fiori – My Inbox application. Specifically, this will deal with the SAP Fiori app: My Inbox – Approve Purchase Requisition (F0401A). Take note that this will not go into the details of setting up the SAP Business Workflow that will be using this, but only extending the SAP Fiori app itself. Fortunately, once set-up properly, we only need look at the ABAP Core Data Services (CDS) views to modify the front-end output.

In particular, the UI.Facet annotations within the CDS view will now drive the changes to the output, without the need to update the annotation MDL xml file in server. As we will see in the below example, there is no need to change the delivered CDS views. Creating an extend view will suffice.

Reference Configuration

Just to provide some reference, the following are the entries maintained in back-end system (SAP S/4HANA) for the SAP Business Workflow configuration:

Transaction Code: SPRO

Path: SAP Reference IMG -> SAP Customizing Implementation Guide -> SAP Netweaver -> SAP Gateway Service Enablement -> Content -> Workflow Settings -> Maintain Task Names and Decision Options

SAP ABAP Exam Prep, SAP ABAP Tutorial and Material, SAP ABAP Prep

Transaction Code: SWFVISU

SAP ABAP Exam Prep, SAP ABAP Tutorial and Material, SAP ABAP Prep

Front-End Visualization


The following images show the areas in which the enhancements will be reflected when opening the SAP Fiori App

SAP ABAP Exam Prep, SAP ABAP Tutorial and Material, SAP ABAP Prep

SAP ABAP Exam Prep, SAP ABAP Tutorial and Material, SAP ABAP Prep

Extending CDS views


For Header level changes, we will be extending C_PurRequisitionFs. This CDS view will have data at the PR header level. The following will be the definition of the CDS extend view ZC_PurRequistionFSExt

@AbapCatalog.sqlViewAppendName: 'ZCPURREQFSEXT'
@EndUserText.label: 'Extension view for C_PurRequistionFS'
extend view C_PurRequisitionFs with ZC_PurRequistionFSExt {
. . .
}

◉ To change the Header Area (“Administrative Data” section), the following annotations are used:

     ◉ Annotation “@UI.identification”

@UI.identification:{importance: #HIGH, position: 1000}
_Facts.CreatedByUser as CreatedByUserExt,  

@Semantics.amount.currencyCode: 'DisplayCurrency'
@UI.identification:{label:'Total Net Value', importance: #HIGH, valueFormat.numberOfFractionalDigits: 2, position: 1020} 
cast(cast(_Facts.PurReqnTotalAmountInDspCrcy as abap.curr( 15, 2 )) as mm_pur_requisition_tnetvalue)  as PurReqnTotalAmountInDspCrcyExt

◉ ’importance’ needs to be set to #HIGH for the field to appear
◉ ‘position’ will define where the field will be shown
◉ ’valueFormat.numberOfFractionalDigits’ can be used to change the number of decimal places shown for the value
◉ ’label’ can be used to define the field description, else it will take this from the CDS view definition
◉ Annotations “@Semantics.amount.currencyCode” and “@Semantics.quantity.unitOfMeasure” can be used to relate the field to the appropriate unit field

For Item level changes, we will be extending C_PurRequisitionItemFs. This CDS view will have data at the PR Item level. The following will be the definition of the CDS extend view ZC_PurRequistionItemFSExt

@AbapCatalog.sqlViewAppendName: 'ZCPURREQITMFSEXT'
@EndUserText.label: 'Extension view for C_PurRequistionItemFS'
extend view C_PurRequisitionItemFs with ZC_PurRequistionItemFSExt {
. . .
}

◉ To change the Item Summary table (Section below “Administrative Data”), the following annotations are used:

     ◉ Annotation “@UI.lineItem”

@UI.lineItem:{position: 900, importance: #HIGH, label: ‘Test Label’}
I_Purchaserequisitionitem.FieldName as NewFieldName,

@Semantics.amount.currencyCode: 'NewCurrency'
@UI.lineItem:{position: 1000, importance: #HIGH, label: 'Amount Value'}
I_Purchaserequisitionitem.AmountField as NewAmountField,
@Semantics.currencyCode: true
I_Purchaserequisitionitem.PurReqnItemCurrency as NewCurrency,

@Semantics.quantity.unitOfMeasure: 'NewUoM'
@UI.lineItem:{position: 1100, importance: #HIGH, label: 'Test7'}
I_Purchaserequisitionitem.QuantityField as NewQuantityField,
@Semantics.unitOfMeasure: true
I_Purchaserequisitionitem.BaseUnit as NewUoM

◉ ‘position’ will define where the field will be shown in the table.
◉ ’importance’ needs to be set to #HIGH for the field to appear
◉ ’label’ can be used to define the field description, else it will take this from the CDS view definition
◉ Annotations “@Semantics.amount.currencyCode” and “@Semantics.quantity.unitOfMeasure” can be used to relate the field to the appropriate unit field
◉ Annotation “@Semantics.unitOfMeasure: true” can be used when defining a new unit field, if one is not already available

◉ To change the Item Detail section, when navigating/double clicking on the individual items, the following annotations are used:

 ◉ Annotation “@UI.facet”

     ◉ This will identify the different sections (or facets) that will be available/shown
     ◉ An initial entry is needed to define the collection of facets, even if only a single facet is needed:

@UI.facet: [{ 
          id: 'xxx',
          isSummary: true,
          type: #COLLECTION
      },
...
      ]

     ◉ The parameter ‘id’ can be defined as you want, however, ‘isSummary’ and ‘type’ need to be defined as shown
 
     ◉ Next, the different sections need to be defined:

{
    parentId: 'xxx',
    id: 'yyy',
    type: #FIELDGROUP_REFERENCE,
    targetQualifier: 'nnn',
    label: 'Description Here'
}

     ◉ ’parameterID’ needs to refer to the collection define in the previous step
     ◉ ’id’, ‘targetQualifier’ and ‘label’ can be defined as you want
     ◉ ’type’ needs to be defined as shown
     ◉ Multiple sections can be defined; ensure that these are separated using a comma

◉ Annotation “@UI. fieldGroup”

     ◉ This will now define what is shown in the output
     ◉ Each field will have its own entry, and will use the qualifier (targetQualifier) defined in the previous step to determine where the field will be output

@UI.fieldGroup: [{ qualifier: 'nnn',
                   position: 10,
                   label: ‘Label Here’  }]
I_Purchaserequisitionitem.FieldName as NewFieldName,

     ◉ Parameter ‘qualifier’ should refer to the appropriate ‘targetQualifier’ of the section maintained in the annotation @UI.facet
     ◉ ’position’ will define the order that the field will be displayed within the section
     ◉ If ‘label’ is not defined, it will take the description of the CDS View field
     ◉ The following can also be added after the UI.fieldGroup annotation, as needed, to add the unit to the display:

1. @Semantics.quantity.unitOfMeasure: ‘UnitOfMeasure’
2. @Semantics.amount.currencyCode: ‘CurrencyField’

And now here is the full code to the 2 CDS extend views that correspond to the images shown above:

CDS View ZC_PurRequistionFSExt

@AbapCatalog.sqlViewAppendName: 'ZCPURREQFSEXT'
@EndUserText.label: 'Extension view for C_PurRequistionFS'
extend view C_PurRequisitionFs with ZC_PurRequistionFSExt {
  @UI.identification:{importance: #HIGH, position: 1000}
  _Facts.CreatedByUser as CreatedByUserExt,  

   @Semantics.amount.currencyCode: 'DisplayCurrency'
   @UI.identification:{label:'Total Net Value', importance: #HIGH,  valueFormat.numberOfFractionalDigits: 2, position: 1020} 
   cast(cast(_Facts.PurReqnTotalAmountInDspCrcy as abap.curr( 15, 2 )) as mm_pur_requisition_tnetvalue)  as PurReqnTotalAmountInDspCrcyExt,
   
   @UI.identification:{ importance: #HIGH, position: 1030}  
   _Facts.PurchaseRequisitionType as PurchaseRequisitionTypeExt,

   @UI.identification:{ importance: #HIGH, position: 1040, label: 'Test8'}
   @ObjectModel.text.association: '_PurchasingDocumentTypeText'  
   _Facts.PurchaseRequisitionType as PurchaseRequisitionTypeExt2,

   @Semantics.amount.currencyCode: 'DisplayCurrency'
   @UI.identification:{label:'Test9', importance: #HIGH, valueFormat.numberOfFractionalDigits: 3, position: 1050} 
   cast(cast(_Facts.PurReqnTotalAmountInDspCrcy as abap.curr( 15, 2 )) as mm_pur_requisition_tnetvalue)  as PurReqnTotalAmountExt2
}

CDS View ZC_PurRequistionItemFSExt

@AbapCatalog.sqlViewAppendName: 'ZCPURREQITMFSEXT'
@EndUserText.label: 'Extension view for C_PurRequistionItemFS'
extend view C_PurRequisitionItemFs with ZC_PurRequistionItemFSExt {
      @UI.facet: [{ 
                id: 'ItemDetails',
                isSummary: true,
                type: #COLLECTION
            },
            {
                parentId: 'ItemDetails',
                id: 'ItemDetailsInfo',
                type: #FIELDGROUP_REFERENCE,
                targetQualifier: 'one',
                label: 'PR Line Item Details'
            }] 
                 
      @UI.fieldGroup: [{ qualifier: 'one', position: 10  }]
      I_Purchaserequisitionitem.RequisitionerName as RequisitionerNameExt2,

      @UI.fieldGroup: [{ qualifier: 'one', position: 20  }]
      I_Purchaserequisitionitem.RequirementTracking as RequirementTrackingExt2,

      @UI.fieldGroup: [{ qualifier: 'one', position: 30, label: 'Test Label'  }]
      I_Purchaserequisitionitem.RequirementTracking as RequirementTrackingExt3,

      @UI.fieldGroup: [{ qualifier: 'one', position: 40, label: 'Test Value'  }]
      @Semantics.quantity.unitOfMeasure: 'BaseUnitExt3'
      @UI.identification: {position: 40, valueFormat.numberOfFractionalDigits: 4, importance: #HIGH}
      I_Purchaserequisitionitem.RequestedQuantity as RequestedQuantityExt3,
      @Semantics.unitOfMeasure: true
      I_Purchaserequisitionitem.BaseUnit as BaseUnitExt3,

//Start of Summary Table enhancement
      @UI.lineItem:{position: 1000, importance: #HIGH, label: 'Test5'}
      I_Purchaserequisitionitem.PurchaseRequisitionType as PurchaseRequisitionTypExt3,
      
      @Consumption.semanticObject: 'PurchaseRequisitionItem'
      @Semantics.amount.currencyCode: 'PurReqnItemCurrencyExt'
      @UI.lineItem:{position: 1100, importance: #HIGH, label: 'Test6'}
      I_Purchaserequisitionitem.PurchaseRequisitionPrice as PurchaseRequisitionPriceExt,
      @Semantics.currencyCode: true
      I_Purchaserequisitionitem.PurReqnItemCurrency as PurReqnItemCurrencyExt,

      @Consumption.semanticObject: 'PurchaseRequisitionItem'
      @Semantics.quantity.unitOfMeasure: 'BaseUnitExt'
      @UI.lineItem:{position: 1200, importance: #HIGH, label: 'Test7'}
      @UI.identification: {position: 1200, importance: #HIGH}
      I_Purchaserequisitionitem.RequestedQuantity as RequestedQuantityExt,
      @Semantics.unitOfMeasure: true
      I_Purchaserequisitionitem.BaseUnit as BaseUnitExt,

      @Consumption.semanticObject: 'PurchaseRequisitionItem'
      @UI.lineItem:{position: 1300, importance: #HIGH, label: 'Test8'}
      @UI.identification: {position: 1300, importance: #HIGH}
      I_Purchaserequisitionitem.RequestedQuantity as RequestedQuantityExt2

}

No comments:

Post a Comment