This post continues the blog series A Programming Model for Business Applications. If you havn´t read the first parts in the series, I recommend that you read the first part A Programming Model for Business Applications (1): Assumptions, Building Blocks, and Example App and the second part A Programming Model for Business Applications (2): Implementing the Entity Model with CDS first.

In this part, I want to discuss the implementation of the business object read service and the properties on the server side.

Business Object Read Service

Let us start with the BO-specific views for calculated elements. Obviously, I would like to define calculated elements that belong to the BO in the entity definitions itself. For example the following amount calculation:

NetAmount = {

  Currency = ListPriceAmount.Currency,

  Value   = ( ListPriceAmount.Value * Quantity.Value ) * (100 DiscountPercentValue) / 100 


Unfortunately, in SPS8, CDS does not support the definition of calculated elements in an entity, so I have implemented calculated elements as separate views postfixed by $C.

The first listing shows the view for the Item entity with two examples for amount calculations:

  view Item$C as select from bo.SalesOrder.Item {



    ListPriceAmount.Currency.Code     as “NetAmount.Currency.Code”,

       (ListPriceAmount.Value * Quantity.Value) * (100 DiscountPercentValue) / 100 as “NetAmount.Value”,

    ListPriceAmount.Currency.Code     as “GrossAmount.Currency.Code”,

    NetAmount.Value + TaxAmount.Value as “GrossAmount.Value”


The next listing shows the view for the Sales Order entity with a summation over the items. Here, unfortunately a second limitation of CDS hits us: It is not yet possible defining (unmanaged) associations between views. As I want to use calculated elements of the Item$C view in the SalesOrder$C view, I cannot refer to them via association, but I have to define a join between SalesOrder and Item$C, which makes the select statement more complex, and which is not supported by CDS in SPS8. As a consequence, I implemented the SalesOrder$C view as hdbview artifact using the following select clause::



      sum(I.“NetAmount.Value”)   as “NetAmount.Value”,

   SO.“Currency.Code”         as “NetAmount.Currency.Code”

  from <schema>.<path>::bo.SalesOrder.SalesOrder” as SO

  join <schema>.<path>::bo.SalesOrder.Item$C” as I on SO.ID_ = I.“Parent_ID_”

group by SO.ID_ , SO.“Currency.Code”  

The last listing shows the (simplified) calculation of the formatted name for a business partner (simplified) as part of the BusinessPartner$C view.

case when (CategoryCode = ‘1’) then

      case when (not(Person.AcademicTitle.Code = )) then

            concat(Person.AcademicTitle.TitleText , concat(‘ ‘, concat(concat(Person.GivenName, ‘ ‘), Person.FamilyName)))

            else concat(concat(Person.GivenName, ‘ ‘), Person.FamilyName) end


   case when (not(Organization.SecondLineName = )) then

      concat(Organization.FirstLineName, concat(‘ ‘, Organization.SecondLineName))


     Organization.FirstLineName end

end as FormattedName

As a result the following formatted names may be returned: “SuccessFactors A SAP Company” (organization with two name lines), “Thomas Schneider” (no academic title), “Dr. Thomas Schneider” (academic title before the name), or “Thomas Schneider, PhD” (academic title after the name, not implemented).

This little example already shows us that a simple calculation like a formatted name can be quite complex (the complete code that considers all possible combinations is even longer). But it gives us a good reason for the argument that these type of calculation should be done in centrally as business object logic and should not be repeated in the service implementation or the UI.


Property logic provides information whether data can be updated, are mandatory, etc. depending on the lifecycle of an object. Examples for properties are:

  • Disabled: an element or entity is disabled
  • Read-only: an element or entity is read-only. If the entity is read-only, all elements are read-only.
  • Mandatory: the element must have an input value

Properties can be static, dependent on some business configuration or master data, or dependent on the status of the business object.


  • Static: the Last Changed DateTime element is read-only, it is always set by the system.
  • Dependent on the master data: in a sales order, the properties depend strongly on the product you are selling: In case you are selling physical materials, or services, or projects, various elements (for example the Incoterms elements) may be disabled (= not relevant for the product), read-only (= prefilled by the system), or mandatory.
  • Dependent on the status: Sales orders in status “Completed” cannot be changed, they are read-only.

The UI may optionally request the properties as part of the read request and set the properties of the respective UI control accordingly. Properties checks also run as part of the CUD request to check if the input is valid at a certain point in time (I will discuss this in a later blog).

For the implementation of properties, I am using an additional view with name postfix $P, for example SalesOrder$P, etc.


  • Properties are view fields of type Boolean (workaround: Integer), named, for example “Incoterms.Classification.IsMandatory”
  • Properties are optional, in other words, not all properties are modelled in the properties view 
  • A Null value is equivalent to False.

Properties are a very powerful concept, but you can introduce them step by step. In the following blogs I will come back to the properties view and discuss how it is consumed in case of the read and the write scenario.

The next blog in this series shows the implementation of the service adaptation read service the OData service and the corresponding UI implementation: A Programming Model for Business Applications (4) Service Adaptation and UI (Read Service).

To report this post you need to login first.

Be the first to leave a comment

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

Leave a Reply