Introduction
A CDS custom entity is to implement own data retrieval using ABAP.
A CDS custom entity is linked with an ABAP class, and the data retrieval is executed on the application server.
Custom entities are used for data models whose runtime is implemented manually.
At the CDS level, only an interface is defined.
Runtime of a CDS Custom Entity
It shows that the data retrieval is implemented by an ABAP class and the data source does not have to be a database table.
CDS custom entities transient entities, which means they aren’t created as a database object and can’t be accessed using ABAP SQL.
In ABAP RESTful Application Programming Model (RAP), custom entities are used as a data model basis for RAP unmanaged queries, the ABAP query is executed by the RAP query engine.
A CDS custom entity cannot be used as a data source in other CDS entities or in ABAP SQL.
Syntax
// optional header annotations
@ObjectModel.query.implementedBy : ‘ClassName’
define [root] custom entity EntityName
[with parameters …]
{
[field]
[association]
[annotation]
}
Creating a CDS Custom Entity
Defining the Data Model in a CDS Custom Entity
A custom entity defines an element list that can consist of elements or associations to other CDS entities.
It binds an ABAP class with annotation @ObjectModel.query.implementedBy.
Annotations and input parameters are optional.
The element list of a custom entity can contain single fields or CDS associations:
Individual fields have a name and a data type. The data type can be specified using a CDS built-in type, a CDS simple type, a CDS enumerated type, or a DDIC data element.Associations can be regular associations or specialized associations, i.e. to-parent associations or to-child associations. They can be used to define a relationship to another table entity, thereby adding the association target as an additional data source.Annotations at the element level can be used to add semantic information, such as text labels.@EndUserText.label: ‘PO Header’
define custom entity ZI_PO_HEAD
with parameters parameter_name : parameter_type
{
key key_element_name : key_element_type;
element_name : element_types;
}
Header Entity
@EndUserText.label: ‘PO Header’
define custom entity ZI_PO_HEAD
//with parameters parameter_name: parameter_type
{
key po_num : ebeln;
doc_cat : bstyp;
type : abap.char(2);
org : ekorg;
comp_code : bukrs;
status : abap.char(1);
vendor : Lifnrs
plant : werks_d;
}
Item Entity
@EndUserText.label: ‘PO Items’
define custom entity ZI_PO_ITS
// with parameters parameter_name : parameter_type
{
key po num : ebeln;
key po_item : ebelp;
item_text : abap.char (40);
material : abap.char(40);
plant : werks_d;
stor_loc : Lgort_d;
@Semantics.quantity.unitOfMeasure: ‘uom
qty : abap.quan(13,3);
uom : abap.unit (3);
@Semantics.amount.currencyCode: ‘price_unit’
product_price : abap.curr(10,2);
price_unit : abap.cuky;
}
Header Entity as Root Entity
@EndUserText.label: ‘PO Header’
define root custom entity ZI_PO_HEAD
//with parameters parameter_name: parameter_type
{
key po_num : ebeln;
doc_cat : bstyp;
type : abap.char(2);
org : ekorg;
comp_code : bukrs;
status : abap.char(1);
vendor : Lifnrs
plant : werks_d;
}
Relationships in CDS Custom Entity
@EndUserText.label: ‘PO Header’
define root custom entity ZI_PO_HEAD
//with parameters parameter_name: parameter_type
{
key po_num : ebeln;
doc_cat : bstyp;
type : abap.char(2);
org : ekorg;
comp_code : bukrs;
status : abap.char(1);
vendor : Lifnrs
plant : werks_d;
_itms : composition [1..*] of ZI_PO_ITS;
}@EndUserText.label: ‘PO Items’
define custom entity ZI_PO_ITS
// with parameters parameter_name : parameter_type
{
key po num : ebeln;
key po_item : ebelp;
item_text : abap.char (40);
material : abap.char(40);
plant : werks_d;
stor_loc : Lgort_d;
@Semantics.quantity.unitOfMeasure: ‘uom
qty : abap.quan(13,3);
uom : abap.unit (3);
@Semantics.amount.currencyCode: ‘price_unit’
product_price : abap.curr(10,2);
price_unit : abap.cuky;
_HD : association to parent ZI_PO_HEAD
on $projection.po_num = _hd.po_num;
}
Creating the Query Implementation Class
The runtime of a CDS custom entity must be implemented manually.
It requires an ABAP class that implements the select method of the interface IF_RAP_QUERY_PROVIDER to handle query requests by the client.
This class is referenced by the custom entity and is dedicated to implementing the OData client data requests.
CLASS zcl_po_hd DEFINITION
PUBLIC
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if rap_query_provider.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_po_hd IMPLEMENTATION.
METHOD if_rap_query_provider~select.
ENDMETHOD.
ENDCLASS.
Adding Query Implementation Class to the CDS Custom Entities- Header and Items
@EndUserText.label: ‘PO Header’
@ObjectModel.query.implementedBy: ‘ABAP:ZCL_PO_HD’
define root custom entity ZI_PO_HEAD
//with parameters parameter_name: parameter_type
{
key po_num : ebeln;
doc_cat : bstyp;
type : abap.char(2);
org : ekorg;
comp_code : bukrs;
status : abap.char(1);
vendor : Lifnrs
plant : werks_d;
_itms : composition [1..*] of ZI_PO_ITS;
}@EndUserText.label: ‘PO Items’
@ObjectModel.query.implementedBy: ‘ABAP:ZCL_PO_HD
define custom entity ZI_PO_ITS
// with parameters parameter_name : parameter_type
{
key po num : ebeln;
key po_item : ebelp;
item_text : abap.char (40);
material : abap.char(40);
plant : werks_d;
stor_loc : Lgort_d;
@Semantics.quantity.unitOfMeasure: ‘uom
qty : abap.quan(13,3);
uom : abap.unit (3);
@Semantics.amount.currencyCode: ‘price_unit’
product_price : abap.curr(10,2);
price_unit : abap.cuky;
_HD : association to parent ZI_PO_HEAD
on $projection.po_num = _hd.po_num;
}
Implementation
CLASS zcl_po_hd DEFINITION
PUBLIC
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if rap_query_provider.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_po_hd IMPLEMENTATION.
METHOD if_rap_query_provider~select.
DATA: it_hd TYPE TABLE OF zi_po_head,
it_itms TYPE TABLE OF zi_po_its.
CASE io_request-get_entity_id( ).
WHEN ‘ZI_PO_HEAD’
DATA(lv_hd_fs) = io_request-get_filter( )->get_as_sql_string( ).
DATA(lo_paging) = io_request->get_paging( ).
DATA(lv_skip) = io_request->get_paging( )->get_offset( ).
DATA(lv_top) = io_request->get_paging( )->get_page_size( ).
If lv_top < 0.
lv_top = 1.
ENDIF
DATA(it_sort) = io_request->get_sort_elements( ).
READ TABLE it_sort INTO DATA(ls_sort) INDEX 1.
IF ls_sort-descending = abap_true.
DATA(lv_order) = |'{ ls_sort-element_name } DESCENDING’|.
ELSE.
lv_order = |'{ ls_sort-element_name } ASCENDING’|.
ENDIF.
IF lv_order IS INITIAL.
lv_order = ‘po_num’.
ENDIF.
SELECT * FROM ztb_po_header
WHERE (lv_hd_fs)
ORDER BY (lv_order)
INTO CORRESPONDING FIELDS OF TABLE _hd.
io_response->set_total_number_of_records( lines( it_hd ) ).
IF lv_hd_fs IS INITIAL.
IF lv_skip EQ 0.
DELETE it_hd FROM lv_top + 1.
ELSE.
DELETE it_hd FROM lv_top + lv_skip + 1 TO lines( it_hd ).
DELETE it_hd FROM 1 TO lv_skip.
ENDIF.
ENDIF.
io_response->set_data( it_hd ).
WHEN ‘ZI_PO_ITS’
DATA(lv_item_fs) = io_request-get_filter( )->get_as_sql_string( ).
DATA(lv_skips) = io_request->get_paging( )->get_offset( ).
DATA(lv_tops) = io_request->get_paging( )->get_page_size( ).
If lv_top < 0.
lv_top = 1.
ENDIF
SELECT * FROM ztb_po_item
WHERE (lv_item_fs)
ORDER BY po_num
INTO CORRESPONDING FIELDS OF TABLE _itms.
io_response->set_total_number_of_records( lines( it_itms ) ).
io_response->set_data( it_itms ).
ENDCASE.
ENDMETHOD.
ENDCLASS.
Metadata Extension
Header
@Metadata.layer: #CORE
@UI:{ headerInfo: {
typeName: ‘Purchase Order’,
typeNamePlural: ‘Purchase Orders’,
title: {
type: #STANDARD,
value: ‘po_num’
}
} }
annotate entity ZI_PO_HEAD with
{
@UI.facet: [[
id: ‘po_num’,
purpose: #STANDARD,
position: 10,
type:#IDENTIFICATION REFERENCE,
// type:#COLLECTION,
label: ‘Purchase Order Header’
},
{
id: ‘POItems’,
purpose: #STANDARD,
type:#LINEITEM_REFERENCE,
position: 20,
targetElement: ‘_itms’,
label: ‘Purchase Order Items’
}
]
@UI.lineItem: [{position: 10, label: ‘Purchase Order’}]
@UI.selectionField: [{ position: 10 }]
@UI.identification: [{ position: 10, label: ‘Purchase Order’ }]
po_num;
@UI.lineItem: [{position: 30,label: ‘Order Type’, importance: #HIGH }]
@UI.identification: [{position: 30,label: ‘Order Type’ }]
type;
@UI.lineItem: [{position: 40, label: ‘Company Code’, importance: HIGH }]
@UI.identification: [{ position: 40,label: ‘Company Code’ }]
comp_code;
@UI.lineItem: [{position: 50, label: ‘Organization’, importance: #HIGH }]
@UI.identification: [{position: 50, label: ‘Organization’ }]
org;
@UI.lineItem: [{ position: 60, label: ‘Vendor’ }]
@UI.identification: [{ position: 60, label: ‘Vendor’ }]
vendor;
@UI.lineItem: [{ position: 70, label: ‘Plant’ }]
@UI.selectionfield: [{ position: 70 }]
@UI.identification: [{ position: 70, label: ‘Plant’ }]
plant;
@UI.lineItem: [{ position: 80, label: ‘Status’ }]
@UI.identification: [{ position: 80, label: ‘Purchase Status’ }]
status;
@UI.lineItem: [{ position: 90, label: ‘Purchase Cat’ }]
@UI.identification: [{ position: 90, label: ‘Purchase Cat’ }]
doc_cat;
}
Items
@Metadata.layer: #CORE
@UI:headerInfo: {
title: {
label: ‘PurchaseItemInfo’
type: #STANDARD,
value: ‘_hd’
}
} }
annotate entity ZI_PO_ITS with
{
@UI.facet: [[
id: ‘ItemID’,
purpose: #STANDARD,
position: 10,
type:#IDENTIFICATION REFERENCE,
label: ‘Item Information’
} ]
@UI.lineItem: [{position: 10, label: ‘Purchase Order’}]
@UI.identification: [{ position: 10, label: ‘Purchase Order’ }]
po_num;
@UI.lineItem: [{position: 20,label: ‘Item Number’}]
@UI.identification: [{position: 20,label: ‘Item Number’ }]
po_item;
@UI.lineItem: [{position: 30,label: ‘Short text’ }]
@UI.identification: [{position: 30,label: ‘Short text’ }]
item_text;
@UI.lineItem: [{position: 40, label: ‘Material’}]
@UI.identification: [{ position: 40,label: ‘Material’ }]
material;
@UI.lineItem: [{position: 50, label: ‘Plant’ }]
@UI.identification: [{position: 50, label: ‘Plant’ }]
plant;
@UI.lineItem: [{ position: 60, label: ‘Storage Location’ }]
@UI.identification: [{ position: 60, label: ‘Storage Location’ }]
stor_loc;
@UI.lineItem: [{ position: 70, label: ‘Order Quantity’ }]
@UI.identification: [{ position: 70, label: ‘Order Quantity’ }]
qty;
@UI.lineItem: [{ position: 80, label: ‘Product Price’ }]
@UI.identification: [{ position: 80, label: ‘Product Price’ }]
product_price;
}
Service Definition
Expose the Custom Entities
@EndUserText.label: ‘PO’
define service ZUI_PO_HO {
expose ZI_PO_HEAD as PO;
expose ZI_PO_ITS as Item;
}
Service Binding
Preview the Application
Choose Preview
Choose Go, then Implementation class is executed.
Navigate to items details.
References
Custom Entities | SAP Help PortalCDS DDL – DEFINE CUSTOM ENTITY | ABAP Keyword DocumentationCDS DDL – DEFINE CUSTOM ENTITY, ABAP Class | ABAP Keyword DocumentationUsing a CDS Custom Entity for Data Modeling | SAP Help Portal
Conclusion
A CDS custom entity is used to write the custom logic with an ABAP class, and the data retrieval logic is executed on the application server .
Service definition and Binding can be created for a custom entity with a Binding type Web API and UI.
IntroductionA CDS custom entity is to implement own data retrieval using ABAP.A CDS custom entity is linked with an ABAP class, and the data retrieval is executed on the application server.Custom entities are used for data models whose runtime is implemented manually.At the CDS level, only an interface is defined.Runtime of a CDS Custom EntityIt shows that the data retrieval is implemented by an ABAP class and the data source does not have to be a database table.CDS custom entities transient entities, which means they aren’t created as a database object and can’t be accessed using ABAP SQL.In ABAP RESTful Application Programming Model (RAP), custom entities are used as a data model basis for RAP unmanaged queries, the ABAP query is executed by the RAP query engine.A CDS custom entity cannot be used as a data source in other CDS entities or in ABAP SQL.Syntax// optional header annotations
@ObjectModel.query.implementedBy : ‘ClassName’
define [root] custom entity EntityName
[with parameters …]
{
[field]
[association]
[annotation]
}Creating a CDS Custom EntityDefining the Data Model in a CDS Custom EntityA custom entity defines an element list that can consist of elements or associations to other CDS entities.It binds an ABAP class with annotation @ObjectModel.query.implementedBy.Annotations and input parameters are optional.The element list of a custom entity can contain single fields or CDS associations:Individual fields have a name and a data type. The data type can be specified using a CDS built-in type, a CDS simple type, a CDS enumerated type, or a DDIC data element.Associations can be regular associations or specialized associations, i.e. to-parent associations or to-child associations. They can be used to define a relationship to another table entity, thereby adding the association target as an additional data source.Annotations at the element level can be used to add semantic information, such as text labels.@EndUserText.label: ‘PO Header’
define custom entity ZI_PO_HEAD
with parameters parameter_name : parameter_type
{
key key_element_name : key_element_type;
element_name : element_types;
}Header Entity@EndUserText.label: ‘PO Header’
define custom entity ZI_PO_HEAD
//with parameters parameter_name: parameter_type
{
key po_num : ebeln;
doc_cat : bstyp;
type : abap.char(2);
org : ekorg;
comp_code : bukrs;
status : abap.char(1);
vendor : Lifnrs
plant : werks_d;
}Item Entity@EndUserText.label: ‘PO Items’
define custom entity ZI_PO_ITS
// with parameters parameter_name : parameter_type
{
key po num : ebeln;
key po_item : ebelp;
item_text : abap.char (40);
material : abap.char(40);
plant : werks_d;
stor_loc : Lgort_d;
@Semantics.quantity.unitOfMeasure: ‘uom
qty : abap.quan(13,3);
uom : abap.unit (3);
@Semantics.amount.currencyCode: ‘price_unit’
product_price : abap.curr(10,2);
price_unit : abap.cuky;
}Header Entity as Root Entity@EndUserText.label: ‘PO Header’
define root custom entity ZI_PO_HEAD
//with parameters parameter_name: parameter_type
{
key po_num : ebeln;
doc_cat : bstyp;
type : abap.char(2);
org : ekorg;
comp_code : bukrs;
status : abap.char(1);
vendor : Lifnrs
plant : werks_d;
}Relationships in CDS Custom Entity@EndUserText.label: ‘PO Header’
define root custom entity ZI_PO_HEAD
//with parameters parameter_name: parameter_type
{
key po_num : ebeln;
doc_cat : bstyp;
type : abap.char(2);
org : ekorg;
comp_code : bukrs;
status : abap.char(1);
vendor : Lifnrs
plant : werks_d;
_itms : composition [1..*] of ZI_PO_ITS;
}@EndUserText.label: ‘PO Items’
define custom entity ZI_PO_ITS
// with parameters parameter_name : parameter_type
{
key po num : ebeln;
key po_item : ebelp;
item_text : abap.char (40);
material : abap.char(40);
plant : werks_d;
stor_loc : Lgort_d;
@Semantics.quantity.unitOfMeasure: ‘uom
qty : abap.quan(13,3);
uom : abap.unit (3);
@Semantics.amount.currencyCode: ‘price_unit’
product_price : abap.curr(10,2);
price_unit : abap.cuky;
_HD : association to parent ZI_PO_HEAD
on $projection.po_num = _hd.po_num;
}Creating the Query Implementation ClassThe runtime of a CDS custom entity must be implemented manually.It requires an ABAP class that implements the select method of the interface IF_RAP_QUERY_PROVIDER to handle query requests by the client.This class is referenced by the custom entity and is dedicated to implementing the OData client data requests.CLASS zcl_po_hd DEFINITION
PUBLIC
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if rap_query_provider.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_po_hd IMPLEMENTATION.
METHOD if_rap_query_provider~select.
ENDMETHOD.
ENDCLASS.Adding Query Implementation Class to the CDS Custom Entities- Header and Items@EndUserText.label: ‘PO Header’
@ObjectModel.query.implementedBy: ‘ABAP:ZCL_PO_HD’
define root custom entity ZI_PO_HEAD
//with parameters parameter_name: parameter_type
{
key po_num : ebeln;
doc_cat : bstyp;
type : abap.char(2);
org : ekorg;
comp_code : bukrs;
status : abap.char(1);
vendor : Lifnrs
plant : werks_d;
_itms : composition [1..*] of ZI_PO_ITS;
}@EndUserText.label: ‘PO Items’
@ObjectModel.query.implementedBy: ‘ABAP:ZCL_PO_HD
define custom entity ZI_PO_ITS
// with parameters parameter_name : parameter_type
{
key po num : ebeln;
key po_item : ebelp;
item_text : abap.char (40);
material : abap.char(40);
plant : werks_d;
stor_loc : Lgort_d;
@Semantics.quantity.unitOfMeasure: ‘uom
qty : abap.quan(13,3);
uom : abap.unit (3);
@Semantics.amount.currencyCode: ‘price_unit’
product_price : abap.curr(10,2);
price_unit : abap.cuky;
_HD : association to parent ZI_PO_HEAD
on $projection.po_num = _hd.po_num;
}ImplementationCLASS zcl_po_hd DEFINITION
PUBLIC
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if rap_query_provider.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_po_hd IMPLEMENTATION.
METHOD if_rap_query_provider~select.
DATA: it_hd TYPE TABLE OF zi_po_head,
it_itms TYPE TABLE OF zi_po_its.
CASE io_request-get_entity_id( ).
WHEN ‘ZI_PO_HEAD’
DATA(lv_hd_fs) = io_request-get_filter( )->get_as_sql_string( ).
DATA(lo_paging) = io_request->get_paging( ).
DATA(lv_skip) = io_request->get_paging( )->get_offset( ).
DATA(lv_top) = io_request->get_paging( )->get_page_size( ).
If lv_top < 0.
lv_top = 1.
ENDIF
DATA(it_sort) = io_request->get_sort_elements( ).
READ TABLE it_sort INTO DATA(ls_sort) INDEX 1.
IF ls_sort-descending = abap_true.
DATA(lv_order) = |'{ ls_sort-element_name } DESCENDING’|.
ELSE.
lv_order = |'{ ls_sort-element_name } ASCENDING’|.
ENDIF.
IF lv_order IS INITIAL.
lv_order = ‘po_num’.
ENDIF.
SELECT * FROM ztb_po_header
WHERE (lv_hd_fs)
ORDER BY (lv_order)
INTO CORRESPONDING FIELDS OF TABLE _hd.
io_response->set_total_number_of_records( lines( it_hd ) ).
IF lv_hd_fs IS INITIAL.
IF lv_skip EQ 0.
DELETE it_hd FROM lv_top + 1.
ELSE.
DELETE it_hd FROM lv_top + lv_skip + 1 TO lines( it_hd ).
DELETE it_hd FROM 1 TO lv_skip.
ENDIF.
ENDIF.
io_response->set_data( it_hd ).
WHEN ‘ZI_PO_ITS’
DATA(lv_item_fs) = io_request-get_filter( )->get_as_sql_string( ).
DATA(lv_skips) = io_request->get_paging( )->get_offset( ).
DATA(lv_tops) = io_request->get_paging( )->get_page_size( ).
If lv_top < 0.
lv_top = 1.
ENDIF
SELECT * FROM ztb_po_item
WHERE (lv_item_fs)
ORDER BY po_num
INTO CORRESPONDING FIELDS OF TABLE _itms.
io_response->set_total_number_of_records( lines( it_itms ) ).
io_response->set_data( it_itms ).
ENDCASE.
ENDMETHOD.
ENDCLASS.Metadata ExtensionHeader@Metadata.layer: #CORE
@UI:{ headerInfo: {
typeName: ‘Purchase Order’,
typeNamePlural: ‘Purchase Orders’,
title: {
type: #STANDARD,
value: ‘po_num’
}
} }
annotate entity ZI_PO_HEAD with
{
@UI.facet: [[
id: ‘po_num’,
purpose: #STANDARD,
position: 10,
type:#IDENTIFICATION REFERENCE,
// type:#COLLECTION,
label: ‘Purchase Order Header’
},
{
id: ‘POItems’,
purpose: #STANDARD,
type:#LINEITEM_REFERENCE,
position: 20,
targetElement: ‘_itms’,
label: ‘Purchase Order Items’
}
]
@UI.lineItem: [{position: 10, label: ‘Purchase Order’}]
@UI.selectionField: [{ position: 10 }]
@UI.identification: [{ position: 10, label: ‘Purchase Order’ }]
po_num;
@UI.lineItem: [{position: 30,label: ‘Order Type’, importance: #HIGH }]
@UI.identification: [{position: 30,label: ‘Order Type’ }]
type;
@UI.lineItem: [{position: 40, label: ‘Company Code’, importance: HIGH }]
@UI.identification: [{ position: 40,label: ‘Company Code’ }]
comp_code;
@UI.lineItem: [{position: 50, label: ‘Organization’, importance: #HIGH }]
@UI.identification: [{position: 50, label: ‘Organization’ }]
org;
@UI.lineItem: [{ position: 60, label: ‘Vendor’ }]
@UI.identification: [{ position: 60, label: ‘Vendor’ }]
vendor;
@UI.lineItem: [{ position: 70, label: ‘Plant’ }]
@UI.selectionfield: [{ position: 70 }]
@UI.identification: [{ position: 70, label: ‘Plant’ }]
plant;
@UI.lineItem: [{ position: 80, label: ‘Status’ }]
@UI.identification: [{ position: 80, label: ‘Purchase Status’ }]
status;
@UI.lineItem: [{ position: 90, label: ‘Purchase Cat’ }]
@UI.identification: [{ position: 90, label: ‘Purchase Cat’ }]
doc_cat;
}Items@Metadata.layer: #CORE
@UI:headerInfo: {
title: {
label: ‘PurchaseItemInfo’
type: #STANDARD,
value: ‘_hd’
}
} }
annotate entity ZI_PO_ITS with
{
@UI.facet: [[
id: ‘ItemID’,
purpose: #STANDARD,
position: 10,
type:#IDENTIFICATION REFERENCE,
label: ‘Item Information’
} ]
@UI.lineItem: [{position: 10, label: ‘Purchase Order’}]
@UI.identification: [{ position: 10, label: ‘Purchase Order’ }]
po_num;
@UI.lineItem: [{position: 20,label: ‘Item Number’}]
@UI.identification: [{position: 20,label: ‘Item Number’ }]
po_item;
@UI.lineItem: [{position: 30,label: ‘Short text’ }]
@UI.identification: [{position: 30,label: ‘Short text’ }]
item_text;
@UI.lineItem: [{position: 40, label: ‘Material’}]
@UI.identification: [{ position: 40,label: ‘Material’ }]
material;
@UI.lineItem: [{position: 50, label: ‘Plant’ }]
@UI.identification: [{position: 50, label: ‘Plant’ }]
plant;
@UI.lineItem: [{ position: 60, label: ‘Storage Location’ }]
@UI.identification: [{ position: 60, label: ‘Storage Location’ }]
stor_loc;
@UI.lineItem: [{ position: 70, label: ‘Order Quantity’ }]
@UI.identification: [{ position: 70, label: ‘Order Quantity’ }]
qty;
@UI.lineItem: [{ position: 80, label: ‘Product Price’ }]
@UI.identification: [{ position: 80, label: ‘Product Price’ }]
product_price;
}Service DefinitionExpose the Custom Entities@EndUserText.label: ‘PO’
define service ZUI_PO_HO {
expose ZI_PO_HEAD as PO;
expose ZI_PO_ITS as Item;
}Service BindingPreview the ApplicationChoose PreviewChoose Go, then Implementation class is executed.Navigate to items details.ReferencesCustom Entities | SAP Help PortalCDS DDL – DEFINE CUSTOM ENTITY | ABAP Keyword DocumentationCDS DDL – DEFINE CUSTOM ENTITY, ABAP Class | ABAP Keyword DocumentationUsing a CDS Custom Entity for Data Modeling | SAP Help PortalConclusionA CDS custom entity is used to write the custom logic with an ABAP class, and the data retrieval logic is executed on the application server .Service definition and Binding can be created for a custom entity with a Binding type Web API and UI. Read More Technology Blog Posts by Members articles
#SAP
#SAPTechnologyblog