Technology Blog Posts by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
Srivatsa
Explorer
0 Kudos
349

Data Model

The data model defines the structure of our application's data. In our Customer Management scenario, we have a central Customer entity and several related child entities. This parent-child relationship allows us to organize and manage customer information effectively.

  • Entities:
    • Customer (Parent): Stores core customer information.
    • Child Entities:
      • Account Reference
      • Agreement Reference
      • Contact Medium
      • Payment Method
      • Customer Attachment
      • Characteristic
      • Credit Profile
      • Event Input
      • Event Subscription
      • Related Party
      • Time Period

We use database tables to persist the data for these entities.

  • Database Table Examples:

    • Customer Table (zztmfcustomer):

      • id: Primary key, uniquely identifies each customer. The not null constraint ensures that every customer record has an ID.
      • name: Customer's name.
      • status: Current status of the customer.
      • href: A general link or reference field.
      • last_changed_at: A timestamp to track when the record was last modified, useful for concurrency control.
@EndUserText.label : 'Table to Store Customer details'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zztmfcustomer {

  key id          : char10 not null;
  href            : char100;
  name            : char20 not null;
  status          : char20;
  statusreason    : char30;
  validfor        : datab;
  last_changed_at : timestampl;

}​

 

 

 

  • Account Reference Table (zztmfaccountref):

    • id, name: Combined primary key, ensuring each account reference has a unique ID and name combination.
    • description: Additional details about the account reference.
@EndUserText.label : 'Account Reference'
@AbapCatalog.enhancement.category : #EXTENSIBLE_ANY
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zztmfaccountref {

  key id          : char10 not null;
  key name        : char40 not null;
  href            : char100;
  description     : char255;
  last_changed_at : timestampl;

}​

 

 

  • Primary Keys:

    • Primary keys are essential for uniquely identifying each record in a database table. They ensure data integrity and are used to establish relationships between tables.
    • In zztmfcustomer, id is the primary key.
    • In zztmfaccountref, the combination of id and name forms the primary key.

CDS Views

CDS (Core Data Services) views are virtual data models defined on top of database tables. They simplify data access and provide features like data aggregation, calculations, and annotations. In RAP, CDS views are crucial for exposing data to the service layer.

  • CDS View Examples:

    • Basic Customer View (ZC_TMF_Customer):

      • This view selects fields from the zztmfcustomer table and exposes them as the ZC_TMF_Customer entity.
      • The key annotation marks the id field as the key, which is essential for identifying customer records.
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Customer'
@Metadata.ignorePropagatedAnnotations: true
@Metadata.allowExtensions: true

define root view entity ZC_TMF_Customer 

  as select from zztmfcustomer as Customer 
composition [0..*] of  ZC_TMF_AccountRef as _AccountRef // on _AccountRef.customer_id = Customer.id
 composition [0..*] of ZC_TMF_AgreementRe as _AgreementRe // on _AgreementRe.customer_id = Customer.id
 composition [0..*] of ZC_TMF_ContactMedium as _ContactMedium // on _ContactMedium.customer_id = Customer.id
composition [0..*] of ZC_TMF_CreditProfile as _CreditProfile //on _CreditProfile.customer_id = Customer.id
composition [0..*] of ZC_TMF_EventInput as _EventInput //on _EventInput.customer_id = Customer.id
composition [0..*] of ZC_TMF_Characteristic as _Characteristic //on _EventInput.customer_id = Customer.id
composition [0..*] of ZC_TMF_EventSubscription as _EventSubscription // on _EventSubscription.customer_id = Customer.id
 composition [0..*] of ZC_TMF_PaymentMethod as _PaymentMethod // on _PaymentMethod.customer_id = Customer.id
composition [0..*] of ZC_TMF_RelatedParty as _RelatedParty // on _RelatedParty.customer_id = Customer.id
composition [0..*] of ZC_TMF_TimePeriod as _TimePeriod //on _TimePeriod.customer_id = Customer.id
 composition [0..*] of ZC_TMF_CustomerAttachment as _Attachments
   
{
  key 
Customer.id as customer_id,

  Customer.name as Name,
  Customer.href as Link,
  Customer.status as Status,
last_changed_at,
_AccountRef,
      _AgreementRe,
      _ContactMedium,
     _CreditProfile,
      _EventInput,
      _EventSubscription,
      _Characteristic,
      _PaymentMethod,
      _RelatedParty,
      _TimePeriod,
      _Attachments
}
​

 

 

  • Customer View with Associations (ZC_TMF_Customer):

    • This view includes associations (_AccountRef, _AgreementRe, etc.) to child entities. These associations define the relationships between the Customer entity and its related data.
  • Associations:

    • Associations in CDS views define relationships between entities. They allow you to navigate from one entity to another, retrieving related data.
    • In our example, the associations in the ZC_TMF_Customer view enable you to access a customer's account references, agreements, and other related information.
    • Associations are crucial for creating a hierarchical data structure and simplifying data retrieval.
    • Why use associations to the parent? Associations from child entities back to the parent (_Customer) are used to establish the context of the child data. This is essential for:
      • Data integrity: Ensuring child records are linked to a valid parent.
      • Navigation: Allowing the UI and service to easily navigate from a child record to its corresponding customer.
      • Data retrieval: Simplifying queries to fetch child data in the context of a specific customer.
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'CDS view for Account Ref'
@Metadata.ignorePropagatedAnnotations: true
@Metadata.allowExtensions: true
//@AbapCatalog.sqlViewName: 'ZCTMFV_ACCR'
define view entity ZC_TMF_AccountRef as select from zztmfaccountref as accou
association to parent ZC_TMF_Customer  as _Customer on $projection.Id = _Customer.customer_id {

    key id as Id,
      key  name as name,
    accou.href as Href,
    description as Description,
 last_changed_at,
    _Customer
   
}
​

 

 

  • Composition:

    • Composition is a stronger form of association that implies ownership. When you compose child entities within a parent, the lifecycle of the child is dependent on the parent. If you delete the parent, the children are typically deleted as well.
    • While the provided CDS views use associations, composition would be suitable if the child entities exclusively belong to the parent Customer and should not exist independently.
    • Why composition is used: Composition is used to model strong ownership relationships. It ensures data consistency and simplifies data management by automatically handling the lifecycle of child entities.

Metadata Annotations

Metadata annotations are used to enrich CDS views with semantic information that controls how the data is presented and processed by the UI and service layer.

  • Annotation Examples:

    • @ui.lineItem:

      • This annotation specifies how the customer_Id field should be displayed in a list (e.g., in a table).
      • position: Determines the order of the column.
      • label: Provides a user-friendly column header.
      • importance: Controls the column's visibility based on screen size.
    • @ui.facet:

      • This annotation defines sections or groups of fields in the UI (e.g., in an object page).
      • type: #IDENTIFICATION_REFERENCE: Creates an identification facet (header section).
      • type: #FIELDGROUP_REFERENCE: References a field group to display fields together.
      • position: Determines the order of the facet.
      • label: Provides a user-friendly header for the facet.
@Metadata.layer: #CUSTOMER
@UI: {
  headerInfo: {
    typeName: 'Customer',
    typeNamePlural: 'Customers',
    title: { type: #STANDARD, label: 'Customer ID', value: 'customer_id' },
    description: { label: 'Name', value: 'name' }
  }
}

annotate view ZC_TMF_Customer with
{
  @UI.facet: [
    { 
      id: 'General', 
      type: #IDENTIFICATION_REFERENCE,
      position: 10, 
      label: 'Customer Data'
    },
    { 
      type: #FIELDGROUP_REFERENCE, 
      position: 10, 
      targetQualifier: 'BasicInfo',
      parentId: 'General', 
      isSummary: true, 
      isPartOfPreview: true
    },
    { 
      id: 'AccountRefsFacet',
      purpose: #STANDARD, 
      type: #LINEITEM_REFERENCE,
      label: 'Account References', 
      position: 20, 
      targetElement: '_AccountRef'
    },
    { 
      id: 'AgreementReFacet',
      purpose: #STANDARD, 
      type: #LINEITEM_REFERENCE,
      label: 'Agreements', 
      position: 30, 
      targetElement: '_AgreementRe'
    },
   
    { 
      id: 'ContactMediumFacet',
      purpose: #STANDARD, 
      type: #LINEITEM_REFERENCE,
      label: 'Contact Mediums', 
      position: 40, 
      targetElement: '_ContactMedium'
    },
    { 
      id: 'CreditProfileFacet',
      purpose: #STANDARD, 
      type: #LINEITEM_REFERENCE,
      label: 'Credit Profiles', 
      position: 50, 
      targetElement: '_CreditProfile'
    },
    { 
      id: 'EventInputFacet',
      purpose: #STANDARD, 
      type: #LINEITEM_REFERENCE,
      label: 'Event Inputs', 
      position: 60, 
      targetElement: '_EventInput'
    },
    { 
      id: 'EventSubscriptionFacet',
      purpose: #STANDARD, 
      type: #LINEITEM_REFERENCE,
      label: 'Event Subscriptions', 
      position: 70, 
      targetElement: '_EventSubscription'
    },
    { 
      id: 'CharacteristicFacet',
      purpose: #STANDARD, 
      type: #LINEITEM_REFERENCE,
      label: 'Characteristics', 
      position: 80, 
      targetElement: '_Characteristic'
    },
    { 
      id: 'PaymentMethodFacet',
      purpose: #STANDARD, 
      type: #LINEITEM_REFERENCE,
      label: 'Payment Methods', 
      position: 90, 
      targetElement: '_PaymentMethod'
    },
    { 
      id: 'RelatedPartyFacet',
      purpose: #STANDARD, 
      type: #LINEITEM_REFERENCE,
      label: 'Related Parties', 
      position: 100, 
      targetElement: '_RelatedParty'
    },
        { 
      id: 'CustAttFacet',
      purpose: #STANDARD, 
      type: #LINEITEM_REFERENCE,
      label: 'Attachment', 
      position: 110, 
      targetElement: '_Attachments'
    },
    { 
      id: 'TimePeriodFacet',
      purpose: #STANDARD, 
      type: #LINEITEM_REFERENCE,
      label: 'Time Periods', 
      position: 120, 
      targetElement: '_TimePeriod'
    }
  ]

  // List and Identification fields
  @UI.lineItem: [{ position: 10, label: 'Customer ID', importance: #HIGH }]
  @UI.identification: [{ position: 10, label: 'Customer ID' }]
  @UI.selectionField: [{ position: 10 }]
  @EndUserText.label: 'Customer ID'
  customer_id;
  
  @UI.lineItem: [{ position: 20, label: 'Name', importance: #HIGH }]
  @UI.identification: [{ position: 20, label: 'Name' }]
  @UI.fieldGroup: [{ qualifier: 'BasicInfo', position: 10, importance: #HIGH }]
  Name;
  
  @UI.lineItem: [{ position: 30, label: 'Link', importance: #HIGH }]
  @UI.identification: [{ position: 30, label: 'Link' }]
  @UI.fieldGroup: [{ qualifier: 'BasicInfo', position: 20, importance: #HIGH }]
  Link;
  
  
  @UI.lineItem: [
  { position: 40, label: 'Status', importance: #HIGH },
  { type: #FOR_ACTION, dataAction: 'copy', label: 'Copy', position: 100 }
]
@UI.identification: [{ position: 40, label: 'Status' }]
@UI.fieldGroup: [{ qualifier: 'BasicInfo', position: 30, importance: #HIGH }]
Status;
//  @UI.lineItem: [{ position: 40, label: 'Status', importance: #HIGH }]
//  @UI.identification: [{ position: 40, label: 'Status' }]
//  @UI.fieldGroup: [{ qualifier: 'BasicInfo', position: 30, importance: #HIGH }]
//  
//  Status;

}​

 

 

  • Associated Child Entities : 
@Metadata.layer: #CUSTOMER
annotate entity ZC_TMF_AgreementRe
    with 
{
  @UI.facet: [
    { 
      type: #IDENTIFICATION_REFERENCE, 
      position: 10, 
      id: 'AgrHdr', 
      label: 'Agreement'
    },
    { 
      type: #FIELDGROUP_REFERENCE, 
      position: 10, 
      targetQualifier: 'AgrBasic', 
      parentId: 'AgrHdr',
      isSummary: true, 
      isPartOfPreview: true 
    }
  ]

  @UI.lineItem: [{ position: 10, label: 'ID', importance: #HIGH }]
  @UI.identification: [{ position: 10, label: 'ID' }]
  Id;
  
  @UI.lineItem: [{ position: 20, label: 'Href', importance: #HIGH }]
  @UI.identification: [{ position: 20, label: 'Href' }]
  @UI.fieldGroup: [{ qualifier: 'AgrBasic', position: 10, importance: #HIGH }]
  Href;
  
  @UI.lineItem: [{ position: 30, label: 'Name', importance: #HIGH }]
  @UI.identification: [{ position: 30, label: 'Name' }]
  @UI.fieldGroup: [{ qualifier: 'AgrBasic', position: 20, importance: #HIGH }]
  Name;
}​

 

 

Behavior Definition

The behavior definition defines the behavior and properties of a RAP business object. It specifies the standard operations (CRUD - Create, Read, Update, Delete) and other actions that can be performed on the entity.

  • Behavior Definition Example (ZC_TMF_Customer):

    • unmanaged implementation in class zbp_c_tmf_customer unique;: Specifies that we are responsible for implementing the behavior (CRUD operations) in the zbp_c_tmf_customer class.
    • with draft;: Enables draft functionality for the entity.
    • define behavior for ZC_TMF_Customer alias Customer: Defines the behavior for the ZC_TMF_Customer entity.
    • authorization master ( instance 😞 Specifies authorization control.
    • draft table ZZTMFCUSTOMER_d: Links the entity to its draft table.
    • create; update; delete;: Enables the standard CRUD operations.
    • action copy;: Defines a custom action.
    • draft action ...: Enables draft-specific actions.
    • field ( readonly ) customer_Id;: Makes the customer_Id field read-only.
    • association ... { create; }: Defines associations to child entities and allows creating them.
    • // validation ...: A commented-out example of validation logic.
  • Unmanaged Scenario:

    • In an unmanaged scenario, the developer is responsible for writing the ABAP code to implement the standard CRUD operations and any custom business logic.
    • Why use an unmanaged scenario?
      • Flexibility: Provides maximum control over the implementation.
      • Complex logic: Suitable for scenarios with intricate business rules or performance-critical operations.
      • Legacy integration: Can be necessary when integrating with existing, non-RAP code.
  • ETag:

    • etag master last_changed_at: ETags (Entity Tags) are used for optimistic locking. They help prevent data loss when multiple users edit the same data concurrently.
    • The last_changed_at field is used as the ETag. When a user updates a Customer, the last_changed_at value is checked against the value that the user originally read. If they don't match, it means someone else has changed the data in the meantime, and the update is prevented.
  • Entities:

    • In the context of the behavior definition, "entities" refers to the instances of the business object (e.g., Customer records) that are being processed by the defined operations (Create, Update, Delete). For example, in a CREATE operation, "entities" would contain the data for the new Customer records being created.
unmanaged implementation in class zbp_c_tmf_customer unique;
with draft;

define behavior for ZC_TMF_Customer alias Customer
authorization master ( instance )
draft table ZZTMFCUSTOMER_d
etag master last_changed_at
lock master total etag last_changed_at
early numbering
{
  // Root entity
  create;
  update;
  delete;
  action copy;

  // Draft handling
  draft action Edit;
  draft action Activate;
  draft action Discard;
  draft action Resume;
  draft determine action Prepare;


  field ( readonly ) customer_Id;
  association _AccountRef { create; }
  association _AgreementRe { create; }
  association _ContactMedium { create; }
  association _CreditProfile { create; }
  association _EventInput { create; }
  association _EventSubscription { create; }
  association _Characteristic { create; }
  association _PaymentMethod { create; }
  association _RelatedParty { create; }
  association _TimePeriod { create; }
  association _Attachments{ create; }

  // Draft validation
 // validation validateName on save { create; update; }
}

define behavior for ZC_TMF_CUSTOMERATTACHMENT alias Attachment
implementation in class zbp_c_tmf_customer unique
draft table zztmcustatt_d
lock dependent
{
  field ( readonly ) AttachId, CustomerId; // Parent key
  field (mandatory ) Attachment;

  //create;
  update;

delete;
  association _Customer;
}
define behavior for ZC_TMF_AccountRef alias AccountRef
implementation in class zbp_c_tmf_customer unique
draft table zztmfaccount_d
lock dependent
{
  field ( readonly ) Id; // Parent key
  field (mandatory ) name;

  //create;
  update;

delete;
  association _Customer;
}

define behavior for ZC_TMF_AgreementRe alias AgreementRe
implementation in class zbp_c_tmf_customer unique
draft table zztmfagreem_d
lock dependent
{
  field ( readonly ) Id; // Parent key
  field ( mandatory) Name;
  //create;
  delete;
  update;
  association _Customer;
}

define behavior for ZC_TMF_ContactMedium alias ContactMedium
implementation in class zbp_c_tmf_customer unique
draft table zztmfcontactme_d
lock dependent
{
  field ( readonly ) customer_id; // Parent key
  field ( mandatory ) Mediumtype;
  update;
  //create;
  delete;
  association _Customer;
}

define behavior for ZC_TMF_CreditProfile alias CreditProfile
implementation in class zbp_c_tmf_customer unique
draft table zztmfcreditpro_d
lock dependent
{
  field ( readonly ) customer_id; // Parent key
  field ( mandatory ) Creditprofiledate;
  update;
  //create;
  delete;
  association _Customer;
}

define behavior for ZC_TMF_Characteristic alias Characteristic
implementation in class zbp_c_tmf_customer unique
draft table zztmfcharacte_d
lock dependent
{
  field ( readonly ) id, customer_id; // Parent key
  field ( mandatory ) Name, Value;
  update;
  //create;
  delete;
  association _Customer;
}

define behavior for ZC_TMF_EventInput alias EventInput
implementation in class zbp_c_tmf_customer unique
draft table zztmfeventinp_d
lock dependent
{
  field ( readonly ) customer_id; // Parent key
  field ( mandatory ) Callback;
  update;
  //create;
  delete;
  association _Customer;
}

define behavior for ZC_TMF_EventSubscription alias EventSubscription
implementation in class zbp_c_tmf_customer unique
draft table zztmfeventsubs_d
lock dependent
{
  field ( readonly ) customer_Id; // Parent key
  field ( mandatory ) Callback;
  update;
  //create;
  delete;
  association _Customer;
}

define behavior for ZC_TMF_PaymentMethod alias PaymentMethod
implementation in class zbp_c_tmf_customer unique
draft table zztmfpaymentme_d
lock dependent
{
  field ( readonly ) customer_Id; // Parent key
  field ( mandatory ) Name;
  update;
  //create;
  delete;
  association _Customer;
}

define behavior for ZC_TMF_RelatedParty alias RelatedParty
implementation in class zbp_c_tmf_customer unique
draft table zztmfrelatedpa_d
lock dependent
{
  field ( readonly ) customer_Id; // Parent key
  field ( mandatory ) Name, Role;
  update;
  //create;
  delete;
  association _Customer;
}

define behavior for ZC_TMF_TimePeriod alias TimePeriod
 implementation in class zbp_c_tmf_customer unique
 draft table zztmftimeperi_d
 lock dependent
{
  field ( readonly ) customer_id; // Parent key
  field ( mandatory ) Startdatetime;
  update;
  delete;
  //create;
  association _Customer;
}​

 

 

Conclusion

In Part 1, we defined the foundation of our Customer Management application by creating the data model, CDS views, and behavior definition. We explored key concepts like primary keys, associations, metadata annotations, and the unmanaged RAP scenario.

 

Part 2: Local Handler Class, Draft Functionality, ... - SAP Community