Building a RAP-Based Application Using Two Custom Tables in SAP BTP ABAP Environment

May 5, 2025
cgutjahr

This article guides you through creating a Sales Order business object using the ABAP RESTful Application Programming Model (RAP). You’ll define database tables, build CDS views, implement behavior definitions, and expose the service—all using best practices in naming and structure for maintainability and clarity.

Data Modeling with Transparent Tables

Overview: This section defines the database foundation of our RAP business object using two transparent tables: one for Sales Order Headers and one for Sales Order Items. These tables form the persistent layer for our RAP model.

Sales Order Header Table: ztest_sales_hdr

define table ztest_sales_hdr {
  key client: abap.clnt not null;
  key sales_order_id: vbeln not null;
  order_created_date: erdat;
  order_created_user: syuname;
  category: abap.char(2);
  description: abap.char(100);
  customer_id: abap.char(20);
  created_by: abp_creation_user;
  created_at: abp_creation_tstmpl;
  last_changed_by: abp_lastchange_user;
  last_changed_at: abp_lastchange_tstmpl;
  local_last_changed_at: abp_locinst_lastchange_tstmpl;
}

Sales Order Header Table Draft: ztest_sales_hdr_d

define table ztest_sales_hdr_d {
  key client: abap.clnt not null;
  key sales_order_id: vbeln not null;
  order_created_date: erdat;
  order_created_user: syuname;
  category: abap.char(2);
  description: abap.char(100);
  customer_id: abap.char(20);
  created_by: abp_creation_user;
  created_at: abp_creation_tstmpl;
  last_changed_by: abp_lastchange_user;
  last_changed_at: abp_lastchange_tstmpl;
  local_last_changed_at: abp_locinst_lastchange_tstmpl;
  "%admin" : include sych_bdl_raft_admin_inc;
}

Sales Order Item Table: ztest_sales_item

define table ztest_sales_item {
  key client: abap.clnt not null;
  key sales_order_id: vbeln not null;
  key item_number: posnr not null;
  material_id: abap.char(6);
  material_description: abap.char(20);
  quantity: abap.quan(2,0);
  uom: meins;
  price: abap.curr(5,2);
  currency: abap.cuky;
  created_by: abp_creation_user;
  created_at: abp_creation_tstmpl;
  last_changed_by: abp_lastchange_user;
  last_changed_at: abp_lastchange_tstmpl;
  local_last_changed_at: abp_locinst_lastchange_tstmpl;
}

Sales Order Item Table Draft: ztest_sales_item_d

define table ztest_sales_item_d {
  key client: abap.clnt not null;
  key sales_order_id: vbeln not null;
  key item_number: posnr not null;
  material_id: abap.char(6);
  material_description: abap.char(20);
  quantity: abap.quan(2,0);
  uom: meins;
  price: abap.curr(5,2);
  currency: abap.cuky;
  created_by: abp_creation_user;
  created_at: abp_creation_tstmpl;
  last_changed_by: abp_lastchange_user;
  last_changed_at: abp_lastchange_tstmpl;
  local_last_changed_at: abp_locinst_lastchange_tstmpl;
  "%admin" : include sych_bdl_raft_admin_inc;
}

CDS View Entities

Overview: This section defines the abstraction layer that exposes database content through CDS view entities. The header view forms the root, while the item view is its child in a composition hierarchy.

Root View: ZI_SALES_HEADER

define root view entity ZI_SALES_HEADER as select from ztest_sales_hdr
  composition [1..*] of ZI_SALES_ITEM as _Salesitem {
    key sales_order_id,
    order_created_date,
    order_created_user,
    category,
    description,
    customer_id,
    created_by,
    created_at,
    last_changed_by,
    last_changed_at,
    local_last_changed_at,
    _Salesitem
}

Child View: ZI_SALES_ITEM

define view entity ZI_SALES_ITEM as select from ztest_sales_item
  association to parent ZI_SALES_HEADER as _Header on $projection.sales_order_id = _Header.sales_order_id {
    key sales_order_id,
    key item_number,
    material_id,
    material_description,
    quantity,
    uom,
    price,
    currency,
    created_by,
    created_at,
    last_changed_by,
    last_changed_at,
    local_last_changed_at,
    _Header
}

Behavior Definitions

Overview: This section introduces the behavior layer, which encapsulates the business logic and lifecycle operations like create, update, and delete. Draft handling is enabled to support Fiori Elements features like Edit and Activate.

Header Behavior

define behavior for ZI_SALES_HEADER
  persistent table ztest_sales_hdr
  draft table ztest_sales_hdr_d
  lock master total etag last_changed_at
  authorization master ( instance )
  etag master last_changed_at {
    create;
    update;
    delete;
    field ( mandatory: create ) sales_order_id;
    field ( readonly: update ) sales_order_id;
    association _Salesitem { create; with draft; }
    draft action Activate optimized;
    draft action Resume;
    draft action Edit;
    draft action Discard;
    draft determine action Prepare;
}

Item Behavior

define behavior for ZI_SALES_ITEM
  persistent table ztest_sales_item
  draft table ztest_sales_item_d
  lock dependent by _Header
  authorization dependent by _Header
  etag master last_changed_at {
    update;
    delete;
    field ( mandatory: create ) item_number;
    field ( readonly: update ) item_number;
    field ( readonly ) sales_order_id;
    association _Header { with draft; }
}

Service Definition

Overview: Here we define the OData service that exposes the business object to the frontend. This step allows Fiori Elements to consume the data model and behavior definitions seamlessly.

define service ZSD_SALES_HEADER {
  expose ZI_SALES_HEADER;
  expose ZI_SALES_ITEM;
}

Conclusion

This RAP implementation demonstrates how to model and expose a transactional Sales Order business object using semantically aligned field names. It supports modularity, maintainability, and alignment with Fiori Elements standards.