Technical Articles
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
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
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
- Start transaction SE11. In ABAP in Eclipse you can do so by pressing ALT+F8.
- Enter the following values:
Database Table: ZTAB_SO_#
where # has to be replaced by your group number and press Create - 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. - 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.
- 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.
- Finally do not forget to maintain the technical settings.
- Actvate the table
Create the interface view
- Right click on the package $TMP within your favorite packages
- Select New –> Other ABAP Repository Object
- Choose Core Data Services -> Data Definition and press Next
- Here enter the following valuesName: ZDEMO_I_SalesOrder_TX_#
Description: Sales Order for transactional app – group #and press Finish.
- 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
- After you have activated the interface view you will notice that a BOPF object has been generated as well
Create a consumption view
- 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.
- In the following screen enterDescription: Sales Order for transactional app – group #Name: ZDEMO_C_SalesOrder_TX_#and press Finsih.
- 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 } ​
- As described above for the interface view you have to replace the string ### with your group number (here 35)
- Activate the coding
- 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
- In your ABAP in Eclipse project press ALT+F8 and search for the transaction /IWFND/MAINT_SERVICE
- In the first screen click on Add Service
- 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
- Enter the following valuesSystem Alias: LOCAL
- In the next screen simply click on Local Object and press Next.
- You will receive a success message that the metadata of your service has been loaded successfully.
- 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.
- if you hoover across the grey button a popup window shows up
- 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
- As a result the service document of your OData service will be rendered in your browser
Generate a SAP Fiori Elements Application
- Start your SAP Web IDE
- From the menu select File –> New –> Project from Template
- Select the New List Report Application template
- Enter the following valuesProject Name: SmartTXApp_35
Title: SAP Fiori Elements CUD App – Group 35 - 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
- 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.
- 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.
- Press Finish
Test the application
- The generated app can be tested immediately by pressing the run button.
- In the following dialogue be sure to choose flpSandbox.html
- Click on the tile in the Sanbox FLP
- Finally your app starts. Based on the provided annoations you are able to create sales order header data by pressing the “+” sign.
- In the following screen you can enter data and use the search helps to retrieve data for the business partner and the status
- 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.
Hi,
Congratulatios for this great post.
One question, in screenshort 6, How do I add default status filters?
Thanks,
Best regards
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.
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
Thanks a lot for the help Andre 🙂
Regards,
Sitakant.
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.
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
Â
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.
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
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)
Please ask more detailed questions here: https://answers.sap.com/questions/ask.html
already posted but no response.
Nice Blog for BOPF execute method insight. Thanks.
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
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
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
Hallo @Â Andre Fischer ,
Very nice blog
How to make the line item fields editable using a annotations in List report.
Thanks,
Vijay
Hi Andre,
Do we have a gateway project in this process.? Do we have DPC/MPC_EXT classes ?
Regards,
Mounika
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