Monday 24 May 2021

SAP oDATA V4 API – Using ABAP Restful Programming

Challenge:

Create a ABAP V4 – API with Parent and Child Relationship using existing Standard CDS Views Provided by SAP without Writing an ABAP Code

Note: Some of the code are not pasted so that readers try it with hands on.

Business Scenario: Get All Business Partner Details – Supplier – Customer – Expanding from Parent Child

Steps Followed :

Step 1:

We need to 2 Views , one acts as a parent ( Header ) and another as a child ( Item level)

In this case Business Partner is a header Info and Supplier is a Item detail ( Child ) . We will also see in the next steps that by using standard CDS Views the associations of the child view ( Supplier ) and associations of parent view ( Business Partner Header ) ,  parent child relationship will automatically pop up in the V4 API without any ABAP code involved.

Create two simple Custom CDS Views ZI_BP_PARENT and ZI_BP_SUPPLIER in your Package as shown below :

ZI_BP_PARENT

@AccessControl.authorizationCheck: #CHECK

@EndUserText.label: 'View for Consuming View as a oDATA V4'

define root view entity ZI_BP_PARENT as select from I_BusinessPartner as BPartner

composition [1..1] of ZI_BP_SUPPLIER as _Supplier 

association [0..1] to bp001 as _BusinessPartner on $projection.BusinessPartner = _BusinessPartner.partner

association [0..1] to I_CustomerToBusinessPartner as _CustomerToBusinessPartner on BPartner.BusinessPartnerUUID = _CustomerToBusinessPartner.BusinessPartnerUUID

association [0..1] to I_SupplierToBusinessPartner as _SupplierToBusinessPartner on BPartner.BusinessPartnerUUID = _SupplierToBusinessPartner.BusinessPartnerUUID

association [0..1] to A_Customer as _Customer on $projection.customer = _Customer.Customer

//association [0..1] to A_Supplier as _Supplier on $projection.supplier = _Supplier.Supplier

association [0..*] to A_BusinessPartnerAddress as _BusinessPartnerAddress on $projection.BusinessPartner = _BusinessPartnerAddress.BusinessPartner

association [0..*] to A_BusinessPartnerRole as _BusinessPartnerRole on $projection.BusinessPartner =  _BusinessPartnerRole.BusinessPartner

association [0..*] to A_BusinessPartnerTaxNumber as _BusinessPartnerTax on $projection.BusinessPartner =  _BusinessPartnerTax.BusinessPartner

association [0..*] to A_BusinessPartnerBank as _BusinessPartnerBank on $projection.BusinessPartner =  _BusinessPartnerBank.BusinessPartner

association [0..*] to A_BuPaIdentification as _BuPaIdentification on $projection.BusinessPartner =  _BuPaIdentification.BusinessPartner

association [0..*] to A_BusinessPartnerContact as _BusinessPartnerContact on $projection.BusinessPartner = _BusinessPartnerContact.BusinessPartnerCompany

association [0..*] to A_BuPaIndustry as _BuPaIndustry on $projection.BusinessPartner = _BuPaIndustry.BusinessPartner

{

key BusinessPartner,

  @ObjectModel.readOnly: true

  _CustomerToBusinessPartner.Customer,

  @ObjectModel.readOnly: true

  _SupplierToBusinessPartner.Supplier,

  AcademicTitle,

  AuthorizationGroup,

  BusinessPartnerCategory,

  @ObjectModel.readOnly: true

  BusinessPartnerFullName,

  BusinessPartnerGrouping,

  @ObjectModel.readOnly: true

  BusinessPartnerName,

  @ObjectModel.readOnly: true

  BusinessPartnerUUID,

  CorrespondenceLanguage,

  @ObjectModel.readOnly: true

  CreatedByUser,

  @ObjectModel.readOnly: true

  CreationDate,

  @ObjectModel.readOnly: true

  CreationTime,

  FirstName,

  FormOfAddress,

  Industry,

  InternationalLocationNumber1,

  InternationalLocationNumber2,

//  @API.element.releaseState:#DEPRECATED

  IsFemale,

//  @API.element.releaseState:#DEPRECATED

  IsMale,

  IsNaturalPerson,

//  @API.element.releaseState:#DEPRECATED

  IsSexUnknown,

//  @API.element.successor

  GenderCodeName,

  Language,

  @ObjectModel.readOnly: true

  LastChangeDate,

  @ObjectModel.readOnly: true

  LastChangeTime,

  @ObjectModel.readOnly: true

  LastChangedByUser,

  LastName,

  LegalForm,

  OrganizationBPName1,

  OrganizationBPName2,

  OrganizationBPName3,

  OrganizationBPName4,

  OrganizationFoundationDate,

  OrganizationLiquidationDate,

  SearchTerm1,

  SearchTerm2,

  AdditionalLastName,

  BirthDate,

  BusinessPartnerBirthDateStatus,

  BusinessPartnerBirthplaceName,

  BusinessPartnerIsBlocked,

  BusinessPartnerType,

  @ObjectModel.readOnly: true

  ETag,

  GroupBusinessPartnerName1,

  GroupBusinessPartnerName2,

  @ObjectModel.readOnly: true

  IndependentAddressID,

  InternationalLocationNumber3,

  MiddleName,

  NameCountry,

  NameFormat,

  PersonFullName,

  @ObjectModel.readOnly: true

  PersonNumber,

  IsMarkedForArchiving,

  @Consumption.hidden: true

  IsBusinessPurposeCompleted,

  BusinessPartnerIDByExtSystem,

  _BusinessPartner.vbund as TradingPartner,

  _Customer,

  _Supplier,

  _BusinessPartnerAddress,

  _BusinessPartnerRole,

  _BusinessPartnerTax,

  _BusinessPartnerBank,

  _BuPaIdentification,

  _BusinessPartnerContact,

  _BuPaIndustry

}

ZI_BP_SUPPLIER

@AccessControl.authorizationCheck: #CHECK

@EndUserText.label: 'CDS View for Supplier View'

define view entity ZI_BP_SUPPLIER as select from I_Supplier as BpSupplier

association to parent ZI_BP_PARENT as _BpParent on $projection.Supplier = _BpParent.BusinessPartner

association [0..*] to A_SupplierCompany as _SupplierCompany on $projection.Supplier =  _SupplierCompany.Supplier

association [0..*] to A_SupplierPurchasingOrg as _SupplierPurchasingOrg on $projection.Supplier =  _SupplierPurchasingOrg.Supplier

association [0..*] to A_SupplierText as _SupplierText on $projection.Supplier = _SupplierText.Supplier {

    key Supplier,

AlternativePayeeAccountNumber, 

AuthorizationGroup, 

@ObjectModel.readOnly: true

CreatedByUser,

@ObjectModel.readOnly: true 

CreationDate, 

Customer, 

PaymentIsBlockedForSupplier, 

PostingIsBlocked, 

PurchasingIsBlocked,  

SupplierAccountGroup, 

@ObjectModel.readOnly: true 

SupplierFullName,  

@ObjectModel.readOnly: true

SupplierName, 

VATRegistration,

BirthDate,  

@ObjectModel.readOnly: true

ConcatenatedInternationalLocNo, 

DeletionIndicator, 

FiscalAddress, 

@ObjectModel.readOnly: true

Industry, 

InternationalLocationNumber1, 

InternationalLocationNumber2, 

InternationalLocationNumber3, 

IsNaturalPerson,  

ResponsibleType, 

SuplrQltyInProcmtCertfnValidTo, 

SuplrQualityManagementSystem, 

SupplierCorporateGroup, 

SupplierProcurementBlock, 

@ObjectModel.readOnly: true

TaxNumber1, 

@ObjectModel.readOnly: true

TaxNumber2, 

@ObjectModel.readOnly: true

TaxNumber3, 

@ObjectModel.readOnly: true

TaxNumber4, 

@ObjectModel.readOnly: true

TaxNumber5, 

TaxNumberResponsible, 

TaxNumberType, 

SuplrProofOfDelivRlvtCode,

 @Consumption.hidden: true

IsBusinessPurposeCompleted,

BR_TaxIsSplit,


/*associations*/

_SupplierCompany,

_SupplierPurchasingOrg,

_SupplierText,

_BpParent

}

Step 2 : Activate both the views together – Obligatory Step

Step 3 : Create two corresponding Projection Views for the CDS Views for previously created Views

Projection View : ZC_BP_SUPPLIER on ZI_BP_PARENT

and ZC_BP_SUPPLIER on ZI_BP_SUPPLIER

@EndUserText.label: 'Projection View for ZI_BP_PARENT'

@AccessControl.authorizationCheck: #NOT_REQUIRED

@Search.searchable: true

@Metadata.allowExtensions: true

define root view entity ZC_BP_PARENT 

as projection on ZI_BP_PARENT as BPartner {

    key BusinessPartner,

    @Search.defaultSearchElement: true

    Customer,

    @Search.defaultSearchElement: true

    Supplier,

    @Search.defaultSearchElement: true

    AcademicTitle,

    AuthorizationGroup,

    BusinessPartnerCategory,

    BusinessPartnerFullName,

    BusinessPartnerGrouping,

    BusinessPartnerName,

    BusinessPartnerUUID,

    CorrespondenceLanguage,

    CreatedByUser,

    CreationDate,

    CreationTime,

    FirstName,

    FormOfAddress,

    Industry,

    InternationalLocationNumber1,

    InternationalLocationNumber2,

    IsFemale,

    IsMale,

    IsNaturalPerson,

    IsSexUnknown,

    GenderCodeName,

    Language,

    LastChangeDate,

    LastChangeTime,

    LastChangedByUser,

    LastName,

    LegalForm,

    OrganizationBPName1,

    OrganizationBPName2,

    OrganizationBPName3,

    OrganizationBPName4,

    OrganizationFoundationDate,

    OrganizationLiquidationDate,

    SearchTerm1,

    SearchTerm2,

    AdditionalLastName,

    BirthDate,

    BusinessPartnerBirthDateStatus,

    BusinessPartnerBirthplaceName,

    BusinessPartnerIsBlocked,

    BusinessPartnerType,

    ETag,

    GroupBusinessPartnerName1,

    GroupBusinessPartnerName2,

    IndependentAddressID,

    InternationalLocationNumber3,

    MiddleName,

    NameCountry,

    NameFormat,

    PersonFullName,

    PersonNumber,

    IsMarkedForArchiving,

    IsBusinessPurposeCompleted,

    BusinessPartnerIDByExtSystem,

    TradingPartner,

    /* Associations */

    _BuPaIdentification,

    _BuPaIndustry,

    _BusinessPartnerAddress,

    _BusinessPartnerBank,

    _BusinessPartnerContact,

    _BusinessPartnerRole,

    _BusinessPartnerTax,

    _Customer,

    _Supplier : redirected to composition child ZC_BP_SUPPLIER

}

@EndUserText.label: 'Projection View for ZI_BP_SUPPLIER'

@AccessControl.authorizationCheck: #NOT_REQUIRED

@Search.searchable: true

@Metadata.allowExtensions: true

define view entity ZC_BP_SUPPLIER 

as projection on ZI_BP_SUPPLIER {

    key Supplier,

    @Search.defaultSearchElement: true

    AlternativePayeeAccountNumber,

    @Search.defaultSearchElement: true

    AuthorizationGroup,

    CreatedByUser,

    CreationDate,

    Customer,

    PaymentIsBlockedForSupplier,

    PostingIsBlocked,

    PurchasingIsBlocked,

        @Search.defaultSearchElement: true

    SupplierAccountGroup,

        @Search.defaultSearchElement: true

    SupplierFullName,

    SupplierName,

    VATRegistration,

    BirthDate,

    ConcatenatedInternationalLocNo,

    DeletionIndicator,

    FiscalAddress,

    Industry,

    InternationalLocationNumber1,

    InternationalLocationNumber2,

    InternationalLocationNumber3,

    IsNaturalPerson,

    ResponsibleType,

    SuplrQltyInProcmtCertfnValidTo,

    SuplrQualityManagementSystem,

    SupplierCorporateGroup,

    SupplierProcurementBlock,

    TaxNumber1,

    TaxNumber2,

    TaxNumber3,

    TaxNumber4,

    TaxNumber5,

    TaxNumberResponsible,

    TaxNumberType,

    SuplrProofOfDelivRlvtCode,

    IsBusinessPurposeCompleted,

    BR_TaxIsSplit,

    /* Associations */

    _BpParent : redirected to parent ZC_BP_PARENT,

    _SupplierCompany,

    _SupplierPurchasingOrg,

    _SupplierText

}

Step 4 : Create a Business Services

SAP oDATA, SAP ABAP Career, SAP ABAP Tutorial and Material, SAP ABAP Certification, SAP ABAP Prep, SAP ABAP Preparation, SAP ABAP Guides

Create Business Service Definition

@EndUserText.label: 'Business Partner Service Definitions'
define service ZAPI_BUSINESS_PARTNER {
  expose ZC_BP_PARENT as BPartner;
  expose ZC_BP_SUPPLIER as Supplier;
  expose A_Customer;
  expose A_SupplierCompany;
  expose A_SupplierDunning;
  expose A_BuPaIdentification;
  expose A_BusinessPartnerBank;
  expose A_BusinessPartnerContact;
  expose A_BPContactToFuncAndDept;
  expose A_BusinessPartnerAddress;
  expose A_AddressEmailAddress;
  expose A_AddressFaxNumber;
  expose A_AddressPhoneNumber;
  expose I_CustomerToBusinessPartner;
  expose I_SupplierToBusinessPartner;
  expose A_SupplierPurchasingOrg;
  expose A_SupplierPurchasingOrgText;
}

Step 5 : Create a Business Service Binding

SAP oDATA, SAP ABAP Career, SAP ABAP Tutorial and Material, SAP ABAP Certification, SAP ABAP Prep, SAP ABAP Preparation, SAP ABAP Guides
Create a Business Service Binding

Choose V4 as Binding Type

SAP oDATA, SAP ABAP Career, SAP ABAP Tutorial and Material, SAP ABAP Certification, SAP ABAP Prep, SAP ABAP Preparation, SAP ABAP Guides
Add the Service Definition to the Binding

Now let us publish the service : Click on Publish Button

SAP oDATA, SAP ABAP Career, SAP ABAP Tutorial and Material, SAP ABAP Certification, SAP ABAP Prep, SAP ABAP Preparation, SAP ABAP Guides
Publish oDATA V4

After Publishing check the child nodes :

SAP oDATA, SAP ABAP Career, SAP ABAP Tutorial and Material, SAP ABAP Certification, SAP ABAP Prep, SAP ABAP Preparation, SAP ABAP Guides

CDS Associations are automatically visible in the service

As you can see there are Parent and Child relationship visible. The associations of the CDS View can be used for multiple $expand and $filter works perfectly with Parent and Child and further child relationship

Test Results:


Test URL in your GATEWAY CLIENT will be something like this :

Case 1: 
 
The  service is going to search the Business Partner details who has an email noidea@gmail.com

/sap/opu/odata4/sap/zapi_business_partner_srv/srvd_a2x/sap/zapi_business_partner/0001/BPartner?$top=10&$filter=_BusinessPartnerAddress/any(a: a/_EmailAddress/any(e: e/EmailAddress eq ‘noidea@gmail.com’))&$expand=_BusinessPartnerAddress

{
    "@odata.context": "$metadata#BPartner(_BusinessPartnerAddress())",
    "@odata.metadataEtag": "W/\"20210408204812\"",
    "value": [
        {
            "BusinessPartner": "12345",
            "Customer": "12345",
            "Supplier": "12345",
            "AcademicTitle": "",
            "AuthorizationGroup": "",
            "BusinessPartnerCategory": "2",
            "BusinessPartnerFullName": "NO IDEA Unlimited",
            "BusinessPartnerGrouping": "ZIDEA",
            "BusinessPartnerName": "NO IDEA",
            "BusinessPartnerUUID": "rewtret435435435435345",
            "CorrespondenceLanguage": "",
            "CreatedByUser": "ABCD",
            "CreationDate": "2019-04-18",
            "CreationTime": "12:53:28",
            "FirstName": "",
            "FormOfAddress": "",
            "Industry": "",
            "InternationalLocationNumber1": "0",
            "InternationalLocationNumber2": "0",
            "IsFemale": false,
            "IsMale": false,
            "IsNaturalPerson": "",
            "IsSexUnknown": false,
            "GenderCodeName": "",
            "Language": "",
            "LastChangeDate": "2021-02-22",
            "LastChangeTime": "18:53:53",
            "LastChangedByUser": "ABCDE",
            "LastName": "",
            "LegalForm": "",
            "OrganizationBPName1": "NO IDEA Unlimited",
            "OrganizationBPName2": "NO IDEA Unlimited",
            "OrganizationBPName3": "",
            "OrganizationBPName4": "",
            "OrganizationFoundationDate": null,
            "OrganizationLiquidationDate": null,
            "SearchTerm1": "NO",
            "SearchTerm2": "NO IDEA",
            "AdditionalLastName": "",
            "BirthDate": null,
            "BusinessPartnerBirthDateStatus": "",
            "BusinessPartnerBirthplaceName": "",
            "BusinessPartnerIsBlocked": false,
            "BusinessPartnerType": "",
            "ETag": "12345678",
            "GroupBusinessPartnerName1": "",
            "GroupBusinessPartnerName2": "",
            "IndependentAddressID": "12345",
            "InternationalLocationNumber3": "0",
            "MiddleName": "",
            "NameCountry": "",
            "NameFormat": "",
            "PersonFullName": "",
            "PersonNumber": "",
            "IsMarkedForArchiving": false,
            "BusinessPartnerIDByExtSystem": "",
            "TradingPartner": "",
            "_BusinessPartnerAddress": [
                {
                    "BusinessPartner": "12345",
                    "AddressID": "12345",
                    "ValidityStartDate": "9999-12-31T23:59:59Z",
                    "ValidityEndDate": "9999-12-31T23:59:59Z",
                    "AuthorizationGroup": "",
                    "AddressUUID": "3232-ferewrew-erwerew",
                    "AdditionalStreetPrefixName": "",
                    "AdditionalStreetSuffixName": "",
                    "AddressTimeZone": "CST",
                    "CareOfName": "",
                    "CityCode": "",
                    "CityName": "NOT SURE",
                    "CompanyPostalCode": "",
                    "Country": "US",
                    "County": "",
                    "DeliveryServiceNumber": "",
                    "DeliveryServiceTypeCode": "",
                    "District": "",
                    "FormOfAddress": "",
                    "FullName": "NO IDEA FULL NAME",
                    "HomeCityName": "",
                    "HouseNumber": "",
                    "HouseNumberSupplementText": "",
                    "Language": "EN",
                    "POBox": "",
                    "POBoxDeviatingCityName": "",
                    "POBoxDeviatingCountry": "",
                    "POBoxDeviatingRegion": "",
                    "POBoxIsWithoutNumber": false,
                    "POBoxLobbyName": "",
                    "POBoxPostalCode": "",
                    "Person": "",
                    "PostalCode": "12345",
                    "PrfrdCommMediumType": "",
                    "Region": "",
                    "StreetName": "XYZ",
                    "StreetPrefixName": "",
                    "StreetSuffixName": "",
                    "TaxJurisdiction": "12345678",
                    "TransportZone": "",
                    "AddressIDByExternalSystem": "",
                    "CountyCode": "",
                    "TownshipCode": "",
                    "TownshipName": "",
                    "SAP__Messages": [],
                    "_EmailAddress": [
                        {
                            "AddressID": "12345",
                            "Person": "",
                            "OrdinalNumber": "1",
                            "IsDefaultEmailAddress": true,
                            "EmailAddress": "NOIDEA@GMAIL.COM",
                            "SearchEmailAddress": "NOIDEA@GMAIL.COM",
                            "AddressCommunicationRemarkText": "",
                            "SAP__Messages": []
                        }
                    ]
                }
            ]
        }
    ]
}

Case 2 :

We can $expand from BusinesssPartner(BPartner) Header to Child _Supplier and its following child _SupplierCompany

Service is going to expand all the child nodes of the parent

/sap/opu/odata4/sap/zapi_business_partner_srv/srvd_a2x/sap/zapi_business_partner/0001/BPartner?$expand=_Supplier($expand=_SupplierCompany),_BusinessPartnerAddress($expand=_EmailAddress)

Source: sap.com

No comments:

Post a Comment