Skip to Content
Technical Articles
Author's profile photo Andre Fischer

How to develop a transactional app using the ABAP Programming Model for SAP Fiori

🔥 Check out the blog post Evolution of the ABAP Programming Model and the SAP Community page Modern ABAP Development with RAP to find out more about the ABAP RESTful Application Programming Model which you should use when you are on SAP S/4HANA 2020 or later.

Introduction

The purpose of this how to guide is not to simply duplicate the content of the SAP Online Help, but to provide guidance for the participants of a SAP CodeJam event. Participants of a SAP CodeJam event shall be guided to create their own repository objects and services in one system without messing up the implementation of the other participants. Therefore, all repository objects contain the participant / group number indicated by a hash # as a suffix.

The steps described in this how to guide are based on the SAP Online Help

https://help.sap.com/viewer/cc0c305d2fab47bd808adcad3ca7ee9d/7.51.2/en-US/971e03cd952a47458e57f87fc566a8f3.html

Data model

From bottom to top, you see the so-called interface view ZDEMO_I_SalesOrder_TX_# which is a CDS view that selects data from the respective database table ZTAB_SO_#. The interface views can contain model information like CRUD (Create, Read, Update and Delete) and Draft enablement, text associations, value helps and many more non-UI-specific metadata.


On top of the interface view there is a so-called consumption view ZDEMO_C_SalesOrder_TX_#. The consumption views, as you can assume from its name, represents the data model layer where to define scenario-specific data model and consumption-specific information. This is for example the appropriate layer for exposing a given data model as OData service. Each scenario can have its own consumption views if needed, whereas the interface views are common to different scenarios.
As of SAP NetWeaver 7.51 the metadata extensions can be used to enrich a given consumption data model with UI-specific metadata (using CDS annotations), thus separating them from the data model (i.e. separation of concerns).
If your system runs on top of SAP NetWeaver 750, UI-specific metadata is maintained in the consumption view as well.
Since we are creating a new data model that is based on new database tables we can leverage BOPF objects.

If your data is stored in existing database tables and is updated via existing API’s such as BAPI’s or classes, you can also leverage CDS views as a data model and the SADL runtime for a generic read access without having to write a single line of ABAP code. In this case updates will be best implemented using the referenced data source approach where the existing API’s can be called via code based implementation. This approach is described in the following two blogs:

OData service development with SAP Gateway using CDS via Referenced Data Sources

OData service development with SAP Gateway using CDS via Referenced Data Sources – How to implement updates

 

How to section

In the following you will perform the following steps to create a transactional app using the new SAP Fiori programming model

  • Create a database table to store the sales order header data
  • Create an interface view to read the data from the database table
  • Create a consumption view to expose the CDS-based data model as OData service using the annotation @OData.publish: true
  • Activate the generated OData service in the transaction /IWFND/MAINT_SERVICE
  • Test your OData service in the browser
  • Generate a SAP Fiori Elements Application to consume the OData service

Create a database table

  1. Start transaction SE11. In ABAP in Eclipse you can do so by pressing ALT+F8.
  2. Enter the following values:
    Database Table: ZTAB_SO_#
    where # has to be replaced by your group number and press Create
  3. On the screen Dictionary : Change Table enter the following values in the tab Delivery and Maintenance

    Description : sales order header data group #
    Delivery Class: L
    Data Browser / Table View Editing: Display/Maintenance AllowedWe choose the option to allow table maintenance here for demo purposes and convenience only. This way you are able to create and maintain the demo data easily also without a UI.
  4. In the Tab Fields You can use cut and paste from the following table to enter the field names and data elements.
    Field

    Data Element

    CLIENT

    MANDT

    SALESORDER

    SNWD_SO_ID

    BUSINESSPARTNER

    SNWD_PARTNER_ID

    CURRENCYCODE

    SNWD_CURR_CODE

    GROSSAMOUNT

    SNWD_TTL_GROSS_AMOUNT

    NETAMOUNT

    SNWD_TTL_NET_AMOUNT

    BILLINGSTATUS

    SNWD_SO_CF_STATUS_CODE

    OVERALLSTATUS

    SNWD_SO_OA_STATUS_CODE

    .INCLUDE

    /BOBF/S_LIB_ADMIN_DATA

    Then chosse the check boxes  key and initial value for both fields Client and Salesorder.

  5. Tab Currency/Quantity FieldsOn the Currency/Quantity Fields tab, define the Reference field CURRENCYCODE and Reference table ZTAB_SO_# for the both fields GROSSAMOUNT and NETAMOUNT.
  6. Finally do not forget to maintain the technical settings.
  7. Actvate the table

Create the interface view

  1. Right click on the package $TMP within your favorite packages
  2. Select New –> Other ABAP Repository Object
  3. Choose Core Data Services -> Data Definition and press Next
  4. Here enter the following valuesName: ZDEMO_I_SalesOrder_TX_#
    Description: Sales Order for transactional app – group #and press Finish.

  5. Copy the DDL source code from the following box and use Ctrl+F to replace the string ### with your group number (here 35) and choose Replace All.The code contains a specific set of @ObjectModel CDS annotations which add business object semantics to the data model.A detailed explanation can be found here:SAP Online Help
    @AbapCatalog.sqlViewName: 'ZDEMO_I_SO_###'
    @AbapCatalog.compiler.compareFilter: true
    @AccessControl.authorizationCheck: #NOT_REQUIRED
    @EndUserText.label: 'Sales Order for transactional app - group ###'
            
    @ObjectModel.semanticKey: 'SalesOrder'
            
    @ObjectModel.modelCategory: #BUSINESS_OBJECT 
    @ObjectModel.compositionRoot: true  
    @ObjectModel.transactionalProcessingEnabled: true  
    @ObjectModel.writeActivePersistence: 'ZTAB_SO_###'
            
    @ObjectModel.createEnabled: true
    @ObjectModel.deleteEnabled: true 
    @ObjectModel.updateEnabled: true
            
            
    define view ZDEMO_I_SalesOrder_TX_### 
            
      as select from ztab_so_### as SalesOrder  -- the sales order table is the data source for this view
            
      association [0..1] to SEPM_I_BusinessPartner            as _BusinessPartner on $projection.BusinessPartner = _BusinessPartner.BusinessPartner
            
      association [0..1] to SEPM_I_Currency                   as _Currency        on $projection.CurrencyCode     = _Currency.Currency
            
      association [0..1] to SEPM_I_SalesOrderBillingStatus    as _BillingStatus   on $projection.BillingStatus    = _BillingStatus.SalesOrderBillingStatus
            
      association [0..1] to Sepm_I_SalesOrdOverallStatus      as _OverallStatus   on $projection.OverallStatus    = _OverallStatus.SalesOrderOverallStatus    
            
    {        
      key SalesOrder.salesorder           as SalesOrder, 
            
      @ObjectModel.foreignKey.association: '_BusinessPartner'
      SalesOrder.businesspartner          as BusinessPartner,       
            
      @ObjectModel.foreignKey.association: '_Currency'  
      @Semantics.currencyCode: true
      SalesOrder.currencycode             as CurrencyCode, 
            
      @Semantics.amount.currencyCode: 'CurrencyCode'
            
      SalesOrder.grossamount              as GrossAmount, 
            
      @Semantics.amount.currencyCode: 'CurrencyCode'
      SalesOrder.netamount                as NetAmount, 
            
      @ObjectModel.foreignKey.association: '_BillingStatus'
      SalesOrder.billingstatus            as BillingStatus, 
            
      @ObjectModel.foreignKey.association: '_OverallStatus'
      SalesOrder.overallstatus            as OverallStatus,
            
            
      /* Associations */ 
      _BusinessPartner,
      _Currency,
      _BillingStatus, 
      _OverallStatus     
    }
       
     ​

    Do not forget to activate your changes

  6. After you have activated the interface view you will notice that a BOPF object has been generated as well

 

Create a consumption view

  1. In the folder of the package $TMP expand the folder Core Data Services right click on the folder Data Definition and choose New Data Defintion.
  2. In the following screen enterDescription: Sales Order for transactional app – group #Name: ZDEMO_C_SalesOrder_TX_#and press Finsih.
  3. In the editor cut and paste the following DDL source code.The code contains several @ObjectModel annotations and also @UI annotations that are used by the SAP Fiori elements apps.A detailed description what these annotations do can be found here: SAP Online Help
    @AbapCatalog.sqlViewName: 'ZDEMO_C_SO_###'
      @AccessControl.authorizationCheck: #NOT_REQUIRED
      @EndUserText.label: 'Sales Order for transactional app - group ###'
            
      @ObjectModel.semanticKey: 'SalesOrder'
            
      @ObjectModel.transactionalProcessingDelegated: true
            
      @ObjectModel.createEnabled: true
      @ObjectModel.deleteEnabled: true
      @ObjectModel.updateEnabled: true
            
      @UI.headerInfo: { typeName: 'Sales Order', typeNamePlural: 'Sales Orders' }
            
      @OData.publish: true
            
      define view ZDEMO_C_SalesOrder_TX_###
            
        as select from ZDEMO_I_SalesOrder_TX_### as Document
      {
            
        @UI.lineItem.position: 10
        @UI.identification.position: 10
        key Document.SalesOrder,
            
        @UI.lineItem.position: 20
            
        @UI.identification.position: 20
        Document.BusinessPartner,
            
        Document.CurrencyCode,
            
        @UI.lineItem.position: 50
            
        @UI.identification.position: 50
        Document.GrossAmount,
            
        @UI.lineItem.position: 60
            
        @UI.identification.position: 60
        Document.NetAmount,
            
        @UI.lineItem.position: 30
        @UI.selectionField.position: 30
        @UI.identification.position: 30
        Document.BillingStatus,
            
        @UI.lineItem.position: 40
        @UI.selectionField.position: 40
        @UI.identification.position: 40
        Document.OverallStatus,
            
        /* Exposing value via associations */ 
        @UI.lineItem:  { value: '.CompanyName', position: 15 }
        Document._BusinessPartner,
            
        Document._Currency,   
        Document._BillingStatus, 
        Document._OverallStatus   
            
      }
    ​
  4. As described above for the interface view you have to replace the string ### with your group number (here 35)
  5. Activate the coding
  6. When checking the annotation @OData.publish: true you are notified that the OData service has not been activated yet. So far only the appropriate repository objects in the SAP backend have been generated.

Activate the OData service

  1. In your ABAP in Eclipse project press ALT+F8 and search for the transaction /IWFND/MAINT_SERVICE
  2. In the first screen click on Add Service
  3. Then you have to
    • Enter the following valuesSystem Alias: LOCAL
      Technical Service Name: *##* (where ## denotes your group number, here 35)
    • Click on Get Services
    • Double-Click on the line that contains the name of your service ZDEMO_C_SALESORDER_TX_#_CDS where # has to be replaced by your group number
    • Click on Add Selected Service
  4. In the next screen simply click on Local Object and press Next.
  5. You will receive a success message that the metadata of your service has been loaded successfully.
  6. If you now navigate back to the tab in ABAP in Eclipse where you have edited the source code of the consumption view you will notice that the warning has vanished and that there is now a grey button beside the annoation OData.publish : true.
  7. if you hoover across the grey button a popup window shows up
  8. When you click on the link a new tab opens in the browser that tries to open the following linkhttp://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/sap/ZDEMO_C_SALESORDER_TX_35_CDS/?sap-ds-debug=trueand you are asked to provide the credentials of your SAP user
  9. As a result the service document of your OData service will be rendered in your browser

Generate a SAP Fiori Elements Application

  1. Start your SAP Web IDE
  2. From the menu select File –> New –> Project from Template
  3. Select the New  List Report Application template
  4. Enter the following valuesProject Name: SmartTXApp_35
    Title: SAP Fiori Elements CUD App – Group 35
  5. Now you have to
    • Select the backend system (here NPL)
    • Enter your group number # in the search field for the service
    • Select your service from the list
    • Press Next
  6. The wizard will retrieve annotations from the $metadata document and the annoation file that has been generated based on the annoations in the consumption view.
  7. In a last step you have to select the entity set ZDEMO_C_SalesOrder_TX_# which is the same as the name of the consumption view.
  8. Press Finish

Test the application

 

  1. The generated app can be tested immediately by pressing the run button.
  2. In the following dialogue be sure to choose flpSandbox.html
  3. Click on the tile in the Sanbox FLP
  4. Finally your app starts. Based on the provided annoations you are able to create sales order header data by pressing the “+” sign.
  5. In the following screen you can enter data and use the search helps to retrieve data for the business partner and the status
  6. Having saved the data you can now retrieve a list (that contains just one entry) of sales order header data

Checking content of the table ZTAB_SO_#

In ABAP in Eclipse select the table definition and press F8.

 

Alternatively you can also run transaction SE16, the classical data browser in the SAPGUI to verify that the data really has been saved to the database ;-).

 

Add an action to your application

As described in the SAP Online Help it is possible to add so called quick actions to your application that can for example be used to change the status of a sales order to paid.

Extending Apps with Quick Actions

If you want to do this you can follow the steps described in the Online Help and use the following coding for the implementation that contains the string ### as a placeholder for your group number.

class ZCL_DEMO_A_SET_TO_PAID_### definition
  public
  inheriting from /BOBF/CL_LIB_A_SUPERCL_SIMPLE
  final
  create public .

public section.

  methods /BOBF/IF_FRW_ACTION~EXECUTE
    redefinition .
protected section.
private section.
ENDCLASS.



CLASS ZCL_DEMO_A_SET_TO_PAID_### IMPLEMENTATION.


  method /BOBF/IF_FRW_ACTION~EXECUTE.

  " Typed with node's combined table type
  DATA(lt_sales_order) = VALUE ztdemo_i_salesorder_tx_###( ).

  " READING BO data ----------------------------------------------

  " Retrieve the data of the requested node instance
  io_read->retrieve(
    EXPORTING
    iv_node         = is_ctx-node_key
    it_key          = it_key
    IMPORTING
    et_data         = lt_sales_order
  ).

  " WRITING BO data ---------------------------------------------

  LOOP AT lt_sales_order ASSIGNING FIELD-SYMBOL(<s_sales_order>).

  " Set the attribue billing_status to new value
  <s_sales_order>-billingstatus = 'P'.  " PAID

  " Set the attribue overall_status to new value
  IF
    <s_sales_order>-overallstatus = 'N' OR <s_sales_order>-overallstatus = ' '.
    <s_sales_order>-overallstatus  = 'P'.  " PAID
  ENDIF.

  " Update the changed data (billig_status) of the node instance
  io_modify->update(
    EXPORTING
    iv_node               = is_ctx-node_key
    iv_key                = <s_sales_order>-key
    iv_root_key           = <s_sales_order>-root_key
    is_data               = REF #( <s_sales_order>-node_data )
    it_changed_fields     = VALUE #(
      ( zif_demo_i_salesorder_tx_###_c=>sc_node_attribute-zdemo_i_salesorder_tx_###-billingstatus )
      ( zif_demo_i_salesorder_tx_###_c=>sc_node_attribute-zdemo_i_salesorder_tx_###-overallstatus )
    )
    ).
  ENDLOOP.

  endmethod.
ENDCLASS.

Assigned Tags

      18 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Enric Castella Gonzalez
      Enric Castella Gonzalez

      Hi,

       

      Congratulatios for this great post.

       

      One question, in screenshort 6, How do I add default status filters?

       

      Thanks,

      Best regards

      Author's profile photo Sitakant Tripathy
      Sitakant Tripathy

      Hi Andre,

      thanks for the informative blog. Everywhere we see examples with a header and item table and a BOPF action thrown in but the real requirements are much more complicated than this.

      Consider the PO creation app which is supposed to be equivalent of ME21N/BAPI_PO_CREATE1 from ECC world. These are massive functionalities with a lot of business rules built in and DB modelling with multiple tables.

      BOPF, on a high level, would work on the node level and the framework would save the data directly in the specified persistence tables once all the built in validations and determinations have kicked in.

      Could you please throw some light on what approach has been taken when converting applications into Fiori Transactional Apps. Has everything been re-written into the BOPF framework or the update BAPIs have been coded into data provider classes. What would be closest to SAP design guidelines for modelling considerably sized custom objects

      I don't have access to a S4 HANA system yet and these basics around application building have been puzzling for quiet some time now 🙂

      Regards,

      Sitakant.

      Author's profile photo Andre Fischer
      Andre Fischer
      Blog Post Author

      Hi Sitakant,

      you are right. Examples like this always show how to guides that are easy to follow.

      One approach how to create transactional SAP Fiori apps is to use the Referenced Data Source approach. Here the data model is modelled via CDS and code for read access is generated as well.

      When it comes to updates however you have the option to call classic API's like the BAPI you mentioned above using ABAP code based implementation.

      I have described this approach here.

      https://blogs.sap.com/2016/06/02/odata-service-development-with-sap-gateway-using-cds-via-referenced-data-sources-how-to-implement-updates/

      The described scenario for using BOPF objects is better suited for a green field approach where everything including the tables to store the data is built from scratch.

      Best Regards,

      Andre

       

       

      Author's profile photo Sitakant Tripathy
      Sitakant Tripathy

      Thanks a lot for the help Andre 🙂

      Regards,

      Sitakant.

      Author's profile photo Harikrishna Chelluri
      Harikrishna Chelluri

      Hi Andre,

      Thank you for this beautiful blog. Very informative.

      Using this article, I could do the update on a single line ( Radio button) with BOPF quick action from a Fiori list report (developed using CDS view).

      However, I have a requirement to do same action on multiple lines.

      I added below code in manifest.json file.

      "settings": {

      "gridTable": false,

      "multiSelect": true

      That gave me check boxes on the front end.

      And in the business object (ZDEMO_PBOM_I_DM), I pretty much kept the same code in the implementation class I used for single update but made the below changes: 

      I put external BP in the code but it was not getting hit. And the update is not working.

      Any ideas on what I am missing? And what else needs to be done for BOPF Quick actions to work on MULTIPLE LINES?

      Thank you so much for your time,

      Hari.

      Author's profile photo Andre Fischer
      Andre Fischer
      Blog Post Author

      In a SAP NetWeaver 752 System or in a SAP S/4HANA 1809 you can find a new app based on SAP Fiori Elements that Supports selecting mulitple values and copying them via an Action.

      EPM Fiori Ref Apps: Manage Sales Orders (Draft 2.0)

      Technical Service Name: SEPMRA_SO_MAN2

      CDS View: SEPMRA_C_SalesOrderTP

      BOPF Object: SEPMRA_I_SALESORDERTP

      The instance multiplicity is set to “Single Node Instance”.

      Multiple calls are put within one Change set.

      POST SEPMRA_C_SalesOrderTPCopy?SalesOrder=’500000004’&DraftUUID=guid’00000000-0000-0000-0000-000000000000’&IsActiveEntity=true HTTP/1.1
      POST SEPMRA_C_SalesOrderTPCopy?SalesOrder=’500000005’&DraftUUID=guid’00000000-0000-0000-0000-000000000000’&IsActiveEntity=true HTTP/1.1

      Please post any further quesitons in the Q&A area rather than as a comment to my blog.

       

      Regards,

      Andre

       

      Author's profile photo Hiroyuki Goto
      Hiroyuki Goto

      Hi

      I am doing a similar development.

      I am working on S/4 HANA 1610 system.

      Is there an option to display a field as a checkbox?

      or currently there is a radiobuttion, can this be changed to a check box and handle multiselection?

      my requirement is all rows when displayed should not be allowed to be checked based on a particular fieldvalue.

      please suggest.

      Author's profile photo Andre Fischer
      Andre Fischer
      Blog Post Author

      Hi Hiroyuki,

      it would only be possible to have checkboxes for all entries that are all enabled.

      For more details on how to develop apps with SAP Fiori Elements see the following link:

      https://help.sap.com/viewer/468a97775123488ab3345a0c48cadd8f/7.51.4/en-US/03265b0408e2432c9571d6b3feb6b1fd.html

      Regards,

      Andre

       

      Author's profile photo Hiroyuki Goto
      Hiroyuki Goto

       

      Thanks Andre for your response.

       

      I have done some workaround for that.

      but is it possible to change the table on click of a button like action buttion in CDS BOPF scenario?

      my requiremnt is the user should get to flip the records on a click(initially where a filed value = 'X' and on click all the records)

      Author's profile photo Andre Fischer
      Andre Fischer
      Blog Post Author

       

      Please ask more detailed questions here: https://answers.sap.com/questions/ask.html

      Author's profile photo Hiroyuki Goto
      Hiroyuki Goto

       

      already posted but no response.

      Author's profile photo Mani Kothapalli
      Mani Kothapalli

      Nice Blog for BOPF execute method insight.  Thanks.

      Author's profile photo N. Uppila
      N. Uppila

      Hi Andre,

      Thanks for sharing this great post. I am able to create the transactional app based on your blog. Now I have a requirement of an app inserting data into two tables. The problem I am facing is, in the parent table the data is inserting properly, but in child table the key from master table is not getting inserted. Could you please help me in solve this issue, kindly share if you have any examples if any. I did some research on the community for the same and found blogs related with this, but even after following those methods I am not able to solve the issue.

      Regards,
      Nithin U

      Author's profile photo Andre Fischer
      Andre Fischer
      Blog Post Author

      Check out the following two Blogs from Mahesh Kumar Palavalli

      https://blogs.sap.com/2018/06/24/abap-programming-model-for-fiori-transactional-apps-with-draft-capabilities-using-standard-tables/

      and Diego Borja

      https://blogs.sap.com/2018/06/24/abap-programming-model-for-fiori-transactional-apps-with-draft-capabilities-using-standard-tables/

      Regards,

      Andre

       

      Author's profile photo Pavan Golesar
      Pavan Golesar

      Hi Andre,

       

      Thanks but I think you mistakenly posted duplicate links to blog here in comment. 🙂 Pls update so that we can try!

      https://blogs.sap.com/2018/06/24/abap-programming-model-for-fiori-transactional-apps-with-draft-capabilities-using-standard-tables/

       

      Regards,

      Pavan Golesar

      Author's profile photo Vijay Chintarlapalli
      Vijay Chintarlapalli

      Hallo @ Andre Fischer ,

      Very nice blog

      How to make the line item fields editable using a annotations in List report.

      Thanks,
      Vijay

      Author's profile photo Mounika Reddy Digavasadum
      Mounika Reddy Digavasadum

      Hi Andre,

      Do we have a gateway project in this process.? Do we have DPC/MPC_EXT classes ?

      Regards,

      Mounika

      Author's profile photo Pavan Golesar
      Pavan Golesar

      Hi Mounika Digavasadum,

       

      Answer to 1st question is NO–  In this case as we have exposed the CDS-based data model as OData service using the annotation @OData.publish: true.

      In other words in SEGW transaction you won’t be able to find any such gateway project.

       

      To answer your second question, SADL (Service Adaptation Description Language) framework generates several Gateway artifacts that are stored in the back end.

      There are three things that SADL framework would generate:
      #1- The actual service artifact with the technical name <CDS_VIEW>_CDS. You can find it as SAP Gateway Business Suite Enablement - Service object (object type: R3TR IWSV)
      #2- An SAP Gateway model (object type: R3TR IWMO) with the name <CDS_VIEW>_CDS
      #3- An ABAP class CL_<CDS_VIEW> that is used to provide model metadata to the SAP Gateway service.

       

      Regards,

      Pavan Golesar