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.
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.
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
3. Start transaction SE11. In ABAP in Eclipse you can do so by pressing ALT+F8.
4. Enter the following values:
Database Table: ZTAB_SO_#
where # has to be replaced by your group number and press Create
5. 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.
6. 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.
7. 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.
8. Finally do not forget to maintain the technical settings.
9. 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 link
http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/sap/ZDEMO_C_SALESORDER_TX_35_CDS/?sap-ds-debug=true
and 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 values
Project 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.
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.
nice .Very useful .Thank you for sharing sap fiori online access
ReplyDeletenice blog
ReplyDeletesap hana online access
Thanks for Nice and Informative Post on.sap-pp training
ReplyDelete