Skip to Content

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.
To report this post you need to login first.

1 Comment

You must be Logged on to comment or reply to a post.

Leave a Reply