This topic demonstrates how you can implement a Business Object view to provide a normalized data model for a simple Sales Order application.
Each business object view must contain a specific set of @ObjectModel CDS annotations, indicating - for example - the root of the given entity. The business object view of the root entity needs additional CDS annotations in order to trigger the automatic generation of the respective BOPF business object, which is named after the respective business object view.
The annotations (required) for each root entity are:
Annotation and Values |
Effect |
---|---|
@ObjectModel.modelCategory: #BUSINESS_OBJECT |
Serves for semantic categorization only (the CDS view represents a business object) in the context of the Virtual Data Model (VDM). The model category is an optional annotation and has no runtime effect. We recommend adding this annotation to views representing the root node of a business object. |
@ObjectModel.compositionRoot: true |
Defines the root of the compositional hierarchy for the business object to be created |
@ObjectModel.transactionalProcessingEnabled: true |
Enables transactional runtime support |
In addition, the following annotations are required for all editable entities (including the root entity):
Annotation and Values |
Effect |
---|---|
@ObjectModel.writeActivePersistence: '<database_table> |
Specifies the database table for storing BO data changes that result from transactional behavior |
@ObjectModel.createEnabled: true |
Allows you to create new business object instances |
@ObjectModel.deleteEnabled: true |
Allows you to delete business object instances |
@ObjectModel.updateEnabled: true |
Allows you to update existing business object instances |
More on this: OData Annotations
The following listing provides you with the implementation of a rather elementary Sales Order data model, where the database table ZTAB_SO is defined as the data source for the corresponding CDS view ZDEMO_I_SalesOrder_TX (camel case notation!). In addition, the table ZTAB_SO also serves as a storage place for business object data changes that result from transactional behavior. Therefore, this table is specified in the @ObjectModel.writeActivePersistence annotation. To be able to access business data from other entities, a set of associations is defined as part of the data model. These associations refer to CDS views that are already provided as part of the EPM data model.
@AbapCatalog.sqlViewName: 'ZDEMO_I_SO' @AbapCatalog.compiler.compareFilter: true @AccessControl.authorizationCheck: #NOT_REQUIRED @EndUserText.label: 'Sales Order for transactional app' @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 }
After ensuring that the syntax of the CDS view is complete and correct, activate the data definition (as the corresponding development object).
As a result of successful activation, the BOPF runtime creates a business object ZDEMO_I_SALESORDER_TX (upper case notation!) that is named after, and is stored in, the same package as the underlying CDS view, in our case: ZDEMO_I_SalesOrder_TX (camel case notation!). The decorator within the editor ruler indicates that the generation process has been successful. If you move the cursor over the decorator, an info screen informs you that the business object is generated for the CDS view. In addition, the info screen provides you with a link to the business object editor.
On the entry page of the BO editor, you can identify the Constants Interface that has been generated together with the business object.
If you now choose Go to the ROOT node, you can view some more details at the entity level of the business object. You must know these when you proceed to use the BOPF API - for example, when implementing an action. Here you can find the names of the ABAP Dictionary objects that have been generated together with the business object.
If you click on the Properties tab, you can view the status of each element (attribute) related to the business object created. This information is important for you when you proceed to define the static field control in the business object view later on.