Programming

Transactional Object Models in CDS for ABAP

This blog post introduces the transactional object models in Core Data Services (CDS).

 

You’ll learn how to define and implement a business object and its business logic. First, you’ll define the data model and introduce an object structure. In the transactional world, we consequently make use of the newer CDS entity types (aka CDS V2 models). You’ll then enhance the business object defined in this way to support transactional changes.

 

Object Models

Business objects are defined as tree or compositional structures of entities. To describe business objects in the network of CDS entities and associations, the root of the composition tree is defined as such, and the relevant associations are defined as compositions.

 

Transactional View Layer: We recommend that you define dedicated CDS views for your transactional application that are based on your basic interface views. This makes the model and its use clearer while leaving the model open for further developments and new features. We further recommend that you add the suffix »TP« to the underlying CDS view names as a naming convention for this kind of CDS view.

 

In spoken language, no distinction is usually made between the business object (in our example, the sales order) and its root entity (in our example, the sales order header), and the name of the business object is used synonymously for both of them. In the following example, we retain the correct definitions and terms to avoid conceptual confusion, making it clear when the business object or the root entity of the business object is being referred to.

 

Let’s define the model of the business object for the sales order. Because you base the transactional CDS views on the basic interface views already defined, known and available annotations of the underlying fields, such as their semantics, are automatically available using the annotation propagation logic. In addition, the field names already have a semantic and readable alias.

 

Inheriting Annotations: In part of our example, we still add some annotations to the CDS model that may also be inherited to increase the readability and understandability of the examples.

 

Define the sales order header as shown below.

 

@AccessControl.authorizationCheck: #MANDATORY

@EndUserText.label: 'Sales Order'

define root view entity ZR_SalesOrderTP

   as select from ZI_SalesOrder

   composition [0..*] of ZR_SalesOrderItemTP as _Item

   association [0..1] to ZI_Customer as _SoldToParty

       on $projection.SoldToParty = _SoldToParty.Customer

   association [1] to I_User as _CreatedByUser

       on $projection.CreatedByUser = _CreatedByUser.UserID

   association [1] to I_User as _LastChangedByUser

       on $projection.LastChangedByUser = _LastChangedByUser.UserID

{

   key ZI_SalesOrder.SalesOrder,

           ZI_SalesOrder.SalesOrderType,

           ZI_SalesOrder.SalesOrganization,

           ZI_SalesOrder.SoldToParty,

           ZI_SalesOrder.DistributionChannel,

           ZI_SalesOrder.OrganizationDivision,

           @Semantics.amount.currencyCode: 'TransactionCurrency'

           ZI_SalesOrder.NetAmount,

           ZI_SalesOrder.TransactionCurrency,

           ZI_SalesOrder.DeliveryStatus,

           @Semantics.booleanIndicator: true

           ZI_SalesOrder.DeletionIndicator,

           @Semantics.user.createdBy: true

           ZI_SalesOrder.CreatedByUser,

           @Semantics.systemDateTime.createdAt: true

           ZI_SalesOrder.CreationDateTime,

           @Semantics.user.lastChangedBy: true

           ZI_SalesOrder.LastChangedByUser,

           @Semantics.systemDateTime.lastChangedAt: true

           ZI_SalesOrder.LastChangeDateTime,

           _Item,

           _SoldToParty,

           _CreatedByUser,

           _LastChangedByUser

}

 

It already contains a child association to the sales order item, which is defined in the next listing.

 

@AccessControl.authorizationCheck: #MANDATORY

@EndUserText.label: 'Sales Order Item'

define view entity ZR_SalesOrderItemTP

   as select from ZI_SalesOrderItem

   association to parent ZR_SalesOrderTP as _SalesOrder

       on $projection.SalesOrder = _SalesOrder.SalesOrder

   composition [0..*] of ZR_SalesOrderScheduleLineTP

       as _ScheduleLine

   association [0..1] to ZI_Product as _Product

       on $projection.Product = _Product.Product

   association [1] to I_User as _CreatedByUser

       on $projection.CreatedByUser = _CreatedByUser.UserID

   association [1] to I_User as _LastChangedByUser

       on $projection.LastChangedByUser = _LastChangedByUser.UserID

{

           @ObjectModel.foreignKey.association: '_SalesOrder'

key ZI_SalesOrderItem.SalesOrder,

key ZI_SalesOrderItem.SalesOrderItem,

           ZI_SalesOrderItem.Product,

           @Semantics.quantity.unitOfMeasure: 'OrderQuantityUnit'

           ZI_SalesOrderItem.OrderQuantity,

           ZI_SalesOrderItem.OrderQuantityUnit,

           @Semantics.amount.currencyCode: 'TransactionCurrency'

           ZI_SalesOrderItem.NetAmount,

           ZI_SalesOrderItem.TransactionCurrency,

           @Semantics.user.createdBy: true

           ZI_SalesOrderItem.CreatedByUser,

           @Semantics.systemDateTime.createdAt: true

           ZI_SalesOrderItem.CreationDateTime,

           @Semantics.user.lastChangedBy: true

           ZI_SalesOrderItem.LastChangedByUser,

           @Semantics.systemDateTime.lastChangedAt: true

           ZI_SalesOrderItem.LastChangeDateTime,

           _SalesOrder,

           _ScheduleLine,

           _Product,

           _CreatedByUser,

           _LastChangedByUser

}

 

This listing shows the sales order item that has associations to both the sales order header and the schedule lines defined in the listing below. That listing shows the sales order schedule line that has associations to the sales order header as root entity and to the sales order items as parent entity.

 

@AccessControl.authorizationCheck: #MANDATORY

@EndUserText.label: 'Sales Order Schedule Line'

define view entity ZR_SalesOrderScheduleLineTP

   as select from ZI_SalesOrderScheduleLine

   association [1..1] to ZR_SalesOrderTP as _SalesOrder

       on $projection.SalesOrder = _SalesOrder.SalesOrder

   association               to parent ZR_SalesOrderItemTP

   as _SalesOrderItem

on $projection.SalesOrder        = _SalesOrderItem.SalesOrder and

       $projection.SalesOrderItem = _SalesOrderItem.SalesOrderItem

   association [1] to I_User as _CreatedByUser

       on $projection.CreatedByUser = _CreatedByUser.UserID

   association [1] to I_User as _LastChangedByUser

       on $projection.LastChangedByUser = _LastChangedByUser.UserID

{

   key ZI_SalesOrderScheduleLine.SalesOrder,

   key ZI_SalesOrderScheduleLine.SalesOrderItem,

   key ZI_SalesOrderScheduleLine.SalesOrderScheduleLine,

           ZI_SalesOrderScheduleLine.DeliveryDate,

        @Semantics.quantity.unitOfMeasure: 'OrderQuantityUnit'

        ZI_SalesOrderScheduleLine.OrderQuantity,

        ZI_SalesOrderScheduleLine.OrderQuantityUnit,

        ZI_SalesOrderScheduleLine.SalesOrderScheduleLineType,

        @Semantics.user.createdBy: true

        ZI_SalesOrderScheduleLine.CreatedByUser,

        @Semantics.systemDateTime.createdAt: true

        ZI_SalesOrderScheduleLine.CreationDateTime,

        @Semantics.user.lastChangedBy: true

        ZI_SalesOrderScheduleLine.LastChangedByUser,

        @Semantics.systemDateTime.lastChangedAt: true

        ZI_SalesOrderScheduleLine.LastChangeDateTime,

        _SalesOrder,

        _SalesOrderItem,

        _CreatedByUser,

        _LastChangedByUser

}

 

CDS View Activation: To avoid issues with CDS view activation, we recommend that you first define and activate the CDS views without associations and add the associations in the second step. The definition of the associations to parent entities needs to be done up front to the definition of the related compositions.

 

Access Controls

Read access is controlled via the well-known access control. As we define the transactional layer on top of our basic layer, we can simply inherit the access control from the underlying CDS entities. The listing below shows the inherited access control of the sales order header.

11

@EndUserText.label: 'Sales Order'

@MappingRole: true

define role ZR_SalesOrderTP {

   grant

       select

           on

               ZR_SalesOrderTP

                   where

                       inheriting conditions from entity

                           ZI_SalesOrder;

}

 

The access control for the sales order item is shown here.

 

@EndUserText.label: 'Sales Order Item'

@MappingRole: true

define role ZR_SalesOrderItemTP {

   grant

      select

         on

            ZR_SalesOrderItemTP

                  where

                        inheriting conditions from entity

                           ZI_SalesOrderItem;

}

 

The access control of the sales order schedule line is shown in the next listing.

 

@EndUserText.label: 'Sales Order Schedule Line'

@MappingRole: true

define role ZR_SalesOrderScheduleLineTP {

   grant

      select

         on

            ZR_SalesOrderScheduleLineTP

               where

                  inheriting conditions from entity

                     ZI_SalesOrderScheduleLine;

}

 

Editor’s note: This post has been adapted from a section of the book Core Data Services for ABAP by Renzo Colle, Ralf Dentzer, and Jan Hrastnik.

Recommendation

Core Data Services for ABAP
Core Data Services for ABAP

If you’re developing ABAP applications, you need CDS expertise. This book is your all-in-one guide, updated for SAP S/4HANA 2023! Start by learning to create and edit CDS views. Walk through CDS syntax and see how to define associations and annotations. Further refine your model by implementing access controls, service bindings, and table functions. Understand the CDS-based virtual data model, and then follow step-by-step instructions to model analytical and transactional applications. From modeling to testing to troubleshooting, this is the only book you need!

Learn More
SAP PRESS
by SAP PRESS

SAP PRESS is the world's leading SAP publisher, with books on ABAP, SAP S/4HANA, SAP IBP, intelligent technologies, SAP Business Technology Platform, and more!

Comments