Monday, 11 May 2020

Display Standard text using CDS annotation @ObjectModel.virtualElement in Gateway Service (Odata) or Fiori

Overview


Often we come across scenario where we need to display document/item text, which are stored in SAP as standard text. This blogs explains how standard text can be displayed in Gateway Service (Odata) or Fiori using CDS annotation @ObjectModel.virtualElement.

What Are Virtual Elements, and Why Do I Need Them?


For some business use cases, it may be necessary to add new fields to the data model (CDS/table) of an application and to calculate their values using ABAP programming (like FM, methods). Virtual elements come into play if these fields are not provided as part of the original persistence data model or cannot be easily integrated (derived) in CDS so that their values can be calculated directly on SAP HANA.

Virtual elements represent transient fields in business applications. They are defined at the level of CDS consumption views as additional elements within the SELECT list using specific @DataModel annotations. However, the calculation or further processing of their values is carried out by means of ABAP classes that implement the specific code exit interfaces provided for this purpose.

It can be conceptualize as CDS field exit.

Example tested on system: SAP S/4 HANA 1909( AS ABAP 754)


In below example, I will derive Purchase Order Item text which is stored as Standard text.

◉ Create CDS & publish it as Odata service using Auto-exposure

SAP ABAP CDS, SAP ABAP Tutorial and Material, SAP ABAP Learning, SAP ABAP Certification, SAP ABAP Cert Exam

CDS Source Code

@AbapCatalog.sqlViewName: 'ZVPOITEXT'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@VDM.viewType: #CONSUMPTION
@EndUserText.label: 'Purchase Order Item Standard Text in CDS'
@OData: { publish: true }            --Publish CDS as OData Service

define view ZPurchaseOrderItemText
  as select from I_PurchaseOrderItem --Data Source: Standard CDS(Purchase Document Line items)
{
  key PurchaseOrder,                              --Purchase Document number
  key PurchaseOrderItem,                          --Purchase Document Item number
      @ObjectModel.virtualElement: true
      @ObjectModel.virtualElementCalculatedBy: 'ZCL_PO_ITEM_TEXT'
      cast( ''  as abap.char(255)) as item_text1, ---field limited to maximum 255 characters for text
      @ObjectModel.virtualElement: true
      @ObjectModel.virtualElementCalculatedBy: 'ZCL_PO_ITEM_TEXT'
      cast( ''  as abap.char(255)) as item_text2  ---field limited to maximum 255 characters for text
};

◉ Register & activate the OData service in T-code: /N/IWFND/MAINT_SERVICE

SAP ABAP CDS, SAP ABAP Tutorial and Material, SAP ABAP Learning, SAP ABAP Certification, SAP ABAP Cert Exam

Auto-generated CDS based OData service-naming convention: CDS entity name + ‘_CDS’

SAP ABAP CDS, SAP ABAP Tutorial and Material, SAP ABAP Learning, SAP ABAP Certification, SAP ABAP Cert Exam

Service registered & activated.

SAP ABAP CDS, SAP ABAP Tutorial and Material, SAP ABAP Learning, SAP ABAP Certification, SAP ABAP Cert Exam

Check CDS source code, new icon will be displayed after successful service registration as below:

SAP ABAP CDS, SAP ABAP Tutorial and Material, SAP ABAP Learning, SAP ABAP Certification, SAP ABAP Cert Exam

◉ Create class & implement interface IF_SADL_EXIT_CALC_ELEMENT_READ. This interface has 2 methods as below:

SAP ABAP CDS, SAP ABAP Tutorial and Material, SAP ABAP Learning, SAP ABAP Certification, SAP ABAP Cert Exam

Implement the method calculate & add below logic to fetch PO Item text

SAP ABAP CDS, SAP ABAP Tutorial and Material, SAP ABAP Learning, SAP ABAP Certification, SAP ABAP Cert Exam

METHOD if_sadl_exit_calc_element_read~calculate.
    TRY.
        DATA : lt_poitem    TYPE STANDARD TABLE OF zvpoitext WITH DEFAULT KEY,
               lt_lines     TYPE STANDARD TABLE OF tline,
               lv_long_text TYPE string.

        lt_poitem = CORRESPONDING #( it_original_data ).

        LOOP AT lt_poitem ASSIGNING FIELD-SYMBOL(<ls_poitem>).
*--preapre PO item text name
          DATA(lv_name) = CONV tdobname( <ls_poitem>-purchaseorder && <ls_poitem>-purchaseorderitem ).
          CALL FUNCTION 'READ_TEXT'
            EXPORTING
              client                  = sy-mandt
              id                      = 'F01'
              language                = sy-langu
              name                    = lv_name
              object                  = 'EKPO'
            TABLES
              lines                   = lt_lines
            EXCEPTIONS
              id                      = 1
              language                = 2
              name                    = 3
              not_found               = 4
              object                  = 5
              reference_check         = 6
              wrong_access_to_archive = 7
              OTHERS                  = 8.
          IF sy-subrc IS INITIAL.
            LOOP AT lt_lines ASSIGNING FIELD-SYMBOL(<ls_lines>).
              lv_long_text =  lv_long_text && <ls_lines>-tdline .
            ENDLOOP.
*--split text into below field with maximum 255 characters
            <ls_poitem>-item_text1 = lv_long_text+0(255).
            <ls_poitem>-item_text2 = lv_long_text+255(255).
            CLEAR lv_long_text.
          ENDIF.
*--return derived text
          ct_calculated_data = CORRESPONDING #( lt_poitem ).
        ENDLOOP.
*--catch exception to avoid short dump
      CATCH cx_root INTO DATA(lo_err).
        DATA(lv_msg) = lo_err->get_text(  ).
    ENDTRY.
  ENDMETHOD.

PO item standard text details:

ID: F01

Name: Purchase Document + Item Number

Object: EKPO

SAP ABAP CDS, SAP ABAP Tutorial and Material, SAP ABAP Learning, SAP ABAP Certification, SAP ABAP Cert Exam

◉ Test gateway service

Standard text fetched & displayed in filed item_text1 & item_text2 as below:

SAP ABAP CDS, SAP ABAP Tutorial and Material, SAP ABAP Learning, SAP ABAP Certification, SAP ABAP Cert Exam

The service can further be consumed in Fiori.

No comments:

Post a Comment