OData Example: Create and Update Product Data in S...
Enterprise Resource Planning Blogs by SAP
Get insights and updates about cloud ERP and RISE with SAP, SAP S/4HANA and SAP S/4HANA Cloud, and more enterprise management capabilities with SAP blog posts.
SAP Business ByDesign (ByD) provides you with REST/OData access to product (material and service) business objects. This blog post provides you with an sample round trip example (create – read – update - delete) using ByD OData services for product business objects.
To get some hands-on experience using the OData API for Business Objects you find some examples in the GitHubrepository SAP Business ByDesign – API Usage Samples.
The GitHub repository has sample OData API packages. Product Data package contains Postman collections, a Postman environment and all ByD Custom OData Services required to run the OData requests of the Postman collection.
Note: for the detailed steps of Product Data Postman collection please refer to README file in the GitHub repository
Example Scenario
In the example we are creating reading updating Materials and Service products using SAP Business ByDesign Custom OData Services. For details refer to demo video.
In the material maintenance scenario we are creating and updating the following information of material.
Create material with General information like ID, Description, Product Category, Identified stock type, Base UoM and quantity conversion data
Updates material with Purchasing data like purchasing unit of measure and sets the purchasing status to active
Updates material with Logistics data like logistics unit of measure, sites info and sets the logistics status to active
Updates material with Planning data like Planning Area ID, Default Procurement Method, Supply Planning Procedure, Lot Size Procedure Code and sets the planning areas status to active
Updates material with Availability Confirmation data like Planning Area ID, Availability Check Scope and sets the planning areas status to active
Updates material with Sales data like Item Group, Cash Discount Allowed indicator and sets the Distribution Chains status to active
Updates material with Sales data like Valuation Level Type, Company, Business Residence and sets the valuation status to active
Updates material with product tax classification data and deletes product tax classification data
In the service product maintenance scenario we are creating and updating the following information of service.
Create service with General information like ID, Description, Product Category, Identified stock type, Base UoM and quantity conversion data
Updates service with Purchasing data like purchasing unit of measure and sets the purchasing status to active
Updates service with Sales data like Item Group, Cash Discount Allowed indicator and sets the Distribution Chains status to active
Updates service with Sales data like Valuation Level Type, Company and sets the valuation status to active
Products Custom OData Services can be created in two ways:
Option 1: upload the Custom OData Services as explained in the configuration section of README file in the GitHub repository.
Option 2: create the Custom OData Services in as explained in below steps Expose ByD Materials as OData Service and Expose ByD Service Product as OData Service.
Expose ByD Materials as OData Service
Open work center view Application and User Management – OData Services and create a Custom OData Service for business object Material.
Make sure you expose material properties that enable you to create, filter, read and update all relevant material data incl. nodes Root, MaterialCrossProcessCategory, ProcurementProcessInformation, QuantityConversion, MaterialInventoryProcessInformation, MaterialAvailabilityConfirmationProcessInformation, MaterialSupplyPlanningProcessInformation, MaterialSalesProcessInformation, MaterialFinancialProcessInformation and MaterialDeviantTaxClassification. In my example I included the following elements to my Custom OData Service “vmumaterial“:
InternalID
UUID
Description (incl. content and languageCode)
BaseMeasureUnitCode
IdentifiedStockTypeCode
ProductValuationLevelTypeCode
ProcurementProcessInformation (embedded in collection Material)
ProcurementMeasureUnitCode
ProcurementLifeCycleStatusCode
MaterialCrossProcessCategory
ProductCategoryInternalID
Description
DescriptionLanguageCode
QuantityConversion (created as separate collection MaterialQuantityConversion with all elements)
CorrespondingQuantity
CorrespondingQuantityUnitCode
BatchDependentIndicator
Quantity
QuantityUnitCode
ProcurementProcessInformation (embedded in collection Material)
Note: replace the {{TenantHostname}} with ByD tenant host name, example: my123456.sapbydesign.com
Create and Update Material General Information using the Custom OData Service
In the custom OData service select the general information relevant fields in co-relation with UI fields in general section of material.
Step 1: Create material
Using the http-method POST and entity set MaterialCollection you can create ByD materials and include header information like InternalID, BaseMeasureUnitCode, ProductCategoryID along with Description and Purchasing information:
x-csrf-token=fetch to get the CSRF-token to create the material via POST service call ( note: the x-csrf-token is fetched in the GET service call , for details refer to postman example collection ).
Note: ProductCategoryInternalID should be the valid and existing id in system.
As result ByD returns the following OData response body:
As you can see the material is created with relevant information.
Details about x-csrf-token:
SAP Business ByDesign System generates a CSRF token and sends it back in the HTTP response header field X-CSRF-Token.
This happens in a non-modifying request (such as GET) if the header field X-CSRF-Token with the value Fetch is sent along with the non-modifying request.
Note: CSRF (Cross Site Request Forgery) token is a random, hard-to-guess string. the server would generate a random string and is stored in the session or by setting a cookie containing the value
For example Steps to Follow:
Step 1: call the Get service by setting the Header key field “x-csrf-token” with value “fetch”
Step 2: in the HTTP response header of above GET service call you read the field value “x-csrf-token”
Step 3: in the subsequent POST calls use the x-csrf-token .
Read and Update Material Procurement Data using the Custom OData Service
In the custom OData service select the procurement relevant fields in co-relation with UI fields in purchasing section of material.
Step 1: Get material data
Using the http-method GET and entity set MaterialCollection you can filter and read ByD materials and include quantity conversions:
$filter=InternalID eq ‘{{MaterialID}}’ to filter the materials by the internal ID,
$expand=MaterialQuantityConversion to include the product quantity conversions in the OData response, and
$format=json to use JSON as body format of the response (default is xml),
and the http-header parameter
x-csrf-token=fetch to get the CSRF-token to update the material in the next step.
As result ByD returns the following OData response body:
As you can see the material “{{MaterialID}}” has the base unit of measure and procurement unit of measure “Each” and no quantity conversion so far.
Step 2: Create quantity conversion
Before we can change the procurement UoM to a unit that differs from the base UoM, we need to create the quantity conversion between the base UoM and the new procurement UoM. In our example the ratio should be 1 Box corresponds to 42 Each.
Using http-method POST and the parent object ID (material object ID) provided by GET-response in step 1 you can create a new quantity conversion:
As result ByD returns the following OData response body:
As you can see the material “{{MaterialID}}” now has the procurement unit of measure “Box” with procurement status "active" and a material quantity conversion node instance for the conversion between Each and Box.
Read and Update Material Logistics Data using the Custom OData Service
In the custom OData service select the Inventory information relevant fields in co-relation with UI fields in Logistics section of material.
Step 1: Get material data
Using the http-method GET and entity set MaterialCollection you can filter and read ByD materials and include material logistics information:
$filter=InternalID eq ‘{{MaterialID}}’ to filter the materials by the internal ID,
$expand=MaterialInventoryProcessInformation to include the logistics information in the OData response, and
$format=json to use JSON as body format of the response (default is xml),
and the http-header parameter
x-csrf-token=fetch to get the CSRF-token to update the material in the next step.
As result ByD returns the following OData response body:
As you can see the material “{{MaterialID}}” has the no material logistics / inventory process information so far.
Step 2: Create site
We can create and associate site information to material.
Using http-method POST and the parent object ID (material object ID) provided by GET-response in step 1 you can create and associate site information to material:
$filter=InternalID eq ‘{{MaterialID}}’ to filter the materials by the internal ID,
$expand=MaterialSupplyPlanningProcessInformationto include the planning information in the OData response, and
$format=json to use JSON as body format of the response (default is xml),
and the http-header parameter
x-csrf-token=fetch to get the CSRF-token to update the material in the next step.
As result ByD returns the following OData response body:
As you can see the material “{{MaterialID}}” has the no material planning process information so far.
Step 2: Create planning areas
We can create and associate planning area information to material.
Using http-method POST and the parent object ID (material object ID) provided by GET-response in step 1 you can create and associate MaterialSupplyPlanningProcessInformation to material:
Note: SupplyPlanningAreaID is the valid planning area ID and should be existing in the system.
Step 3: Get planning areas
Using the http-method GET and entity set MaterialSupplyPlanningProcessInformationCollection you can get the instance details of planning area information created in previous step and read material planning area information:
Read and Update Material Availability Confirmation Data using the Custom OData Service
In the custom OData service select the availability confirmation information relevant fields in co-relation with UI fields in Availability Confirmation section of material.
Step 1: Get material data and expand
Using the http-method GET and entity set MaterialCollection you can filter and read ByD materials and include material planning information:
$filter=InternalID eq ‘{{MaterialID}}’ to filter the materials by the internal ID,
$expand=MaterialAvailabilityConfirmationProcessInformation include the availability confirmation information in the OData response, and
$format=json to use JSON as body format of the response (default is xml),
and the http-header parameter
x-csrf-token=fetch to get the CSRF-token to update the material in the next step.
As result ByD returns the following OData response body:
As you can see the material “{{MaterialID}}” has the no material availability process information so far.
Step 2: Create planning areas
We can create and associate planning area information to material.
Using http-method POST and the parent object ID (material object ID) provided by GET-response in step 1 you can create and associate MaterialAvailabilityConfirmationProcessInformationCollection to material:
Note: SupplyPlanningAreaID is the valid planning area ID and should be existing in the system.
Step 3: Get planning areas
Using the http-method GET and entity set MaterialAvailabilityConfirmationProcessInformationCollection you can get the instance details of planning area information created in previous step and read material planning area information:
$filter=InternalID eq ‘{{MaterialID}}’ to filter the materials by the internal ID,
$expand=MaterialSalesProcessInformation include the sales information in the OData response, and
$format=json to use JSON as body format of the response (default is xml),
and the http-header parameter
x-csrf-token=fetch to get the CSRF-token to update the material in the next step.
As result ByD returns the following OData response body:
As you can see the material “{{MaterialID}}” has the no material sales process information so far.
Step 2: Create distribution chains
We can create and associate sales information with distribution chains to material.
Using http-method POST and the parent object ID (material object ID) provided by GET-response in step 1 you can create and associate MaterialSalesProcessInformation to material:
Note: SalesOrganisationID and DistributionChannelCode is the valid ID and should be existing in the system.
Step 3: Get distribution chains / sales info
Using the http-method GET and entity set MaterialSalesProcessInformation you can get the instance details of sales process information created in previous step and read material sales process info:
$format=json to use JSON as body format of the response (default is xml),
and the http-header parameter
x-csrf-token=fetch to get the CSRF-token to update the material in the next step.
As result ByD returns the following OData response body:
As you can see the material “{{MaterialID}}” has the sales process information which was created in previous step.
Step 4: Update distribution chains / sales info
Now we can update the planning information details of material like CustomerTransactionDocumentItemProcessingTypeDeterminationProductGroupCode and CashDiscountDeductibleIndicator.
We are again using http-method PATCH with the material object ID provided by the GET-response in step 3:
$filter=InternalID eq ‘{{MaterialID}}’ to filter the materials by the internal ID,
$expand=MaterialFinancialProcessInformation include the valuation information in the OData response, and
$format=json to use JSON as body format of the response (default is xml),
and the http-header parameter
x-csrf-token=fetch to get the CSRF-token to update the material in the next step.
As result ByD returns the following OData response body:
As you can see the material “{{MaterialID}}” has the no material valuation information so far.
Step 2: Create companies and business residence
We can create and associate valuation information with company and business residence to material.
Using http-method POST and the parent object ID (material object ID) provided by GET-response in step 1 you can create and associate CompanyID and PermanentEstablishmentID to material:
Note: CompanyID and PermanentEstablishmentID is the valid ID and should be existing in the system.
Step 3: Get companies and business residence
Using the http-method GET and entity set MaterialFinancialProcessInformationCollection you can get the instance details of valuation information created in previous step and read material financial process info:
$format=json to use JSON as body format of the response (default is xml),
and the http-header parameter
x-csrf-token=fetch to get the CSRF-token to update the material in the next step.
As result ByD returns the following OData response body:
As you can see the material “{{MaterialID}}” has the valuation / financial process information which was created in previous step.
Step 4: Query material valuation data
In the material Valuation section to update the Account Determination field value, user has to create a custom OData service on business object MaterialValuationData.
Using the http-method GET and query MaterialValuationDataQueryByMaterialID you can filter and read the material valuation data information like AccountDeterminationMaterialValuationDataGroupCode:
$filter=ObjectID eq ‘{{MVDObjectID}}’ to filter the material valuation data by the MVDObjectID,
$expand=MaterialValuationDataAccountDeterminationSpecification include the Account Determination GroupCode information in the OData response, and
$format=json to use JSON as body format of the response (default is xml),
and the http-header parameter
x-csrf-token=fetch to get the CSRF-token to update the material in the next step.
As result ByD returns the following OData response body:
Read and Update Material Product Tax Classification using the Custom OData Service
In the custom OData service select the DeviantTaxClassification relevant fields in co-relation with UI fields in Product Tax Classification section in Taxes tab of material.
Step 1: Get material data and expand
Using the http-method GET and entity set MaterialCollection you can filter and read ByD materials and include material product tax classification:
$filter=InternalID eq ‘{{MaterialID}}’ to filter the materials by the internal ID,
$expand=MaterialDeviantTaxClassification include the sales information in the OData response, and
$format=json to use JSON as body format of the response (default is xml),
and the http-header parameter
x-csrf-token=fetch to get the CSRF-token to update the material in the next step.
As result ByD returns the following OData response body:
As you can see the material “{{MaterialID}}” has the no material tax classification information so far.
Step 2: Create product tax classification
We can create product tax classification information.
Using http-method POST and the parent object ID (material object ID) provided by GET-response in step 1 you can create MaterialDeviantTaxClassificationCollection to material:
Note: RegionCode, TaxTypeCode and TaxExemptionReasonCode is the valid data and should be existing in the system.
Step 3: Get product tax classification
Using the http-method GET and entity set MaterialDeviantTaxClassificationCollection you can get the instance details of tax information created in previous step and read material tax info:
x-csrf-token = <as provided by the response header in step 3>
x-http-method = DELETE
Expose ByD Service Product as OData Service
Open work center view Application and User Management – OData Services and create a Custom OData Service for business object ServiceProduct.
Make sure you expose service product properties that enable you to create, filter, read and update all relevant service data incl. nodes Root, ServiceProductCrossProcessCategory, ProcurementProcessInformation, QuantityConversion,ServiceProductSalesProcessInformation,ServiceProductFinancialProcessInformation. In my example I included the following elements to my Custom OData Service “vmuservice“:
InternalID
UUID
Description (incl. content and languageCode)
BaseMeasureUnitCode
ProductValuationLevelTypeCode
ProcurementProcessInformation (embedded in collection Service)
ProcurementMeasureUnitCode
ProcurementLifeCycleStatusCode
ServiceProductCrossProcessCategory
ProductCategoryInternalID
Description
DescriptionLanguageCode
ServiceProductQuantityConversion (created as separate collection QuantityConversion with all elements)
CorrespondingQuantity
CorrespondingQuantityUnitCode
BatchDependentIndicator
Quantity
QuantityUnitCode
ProcurementProcessInformation (embedded in collection Service)
ProcurementMeasureUnitCode
ProcurementLifeCycleStatusCode
ServiceProductSalesProcessInformation
SalesOrganisationID
DistributionChannelCode
LifeCycleStatusCode
SalesMeasureUnitCode
ItemProcessingTypeDeterminationProductGroupCode
ServiceProductFinancialProcessInformation
CompanyID
PermanentEstablishmentID
LifeCycleStatusCode
Please note: In my example I changed some property names to align with UI element names for better usability.
Activate your custom OData service and note down the Service URL from the OData Editor. In my example the service URL is
Note: replace the {{TenantHostname}} with ByD tenant host name, example : my123456.sapbydesign.com
Create and Update Service Product General Information using the Custom OData Service
In the custom OData service select the general data relevant fields in co-relation with UI fields in General section of service product.
Step 1: Create service
Using the http-method POST and entity set ServiceProductCollection you can create ByD service product and include general / header information like InternalID, BaseMeasureUnitCode, ProductCategoryID along with Description and Purchasing information:
x-csrf-token=fetch to get the CSRF-token to create the service via POST service call ( note: the x-csrf-token is fetched in the GET service call , for details refer to postman example collection ).
Note: ProductCategoryInternalID should be the valid and existing id in system.
As result ByD returns the following OData response body:
As you can see the service product is created with relevant information.
Read and Update Service Product Procurement Data using the Custom OData Service
In the custom OData service select the procurement information data relevant fields in co-relation with UI fields in Purchasing section of service product.
Step 1: Get service data
Using the http-method GET and entity set ServiceProductCollection you can filter and read ByD service and include quantity conversions:
$filter=InternalID eq ‘{{ServiceID}}’ to filter the service by the internal ID,
$expand=ServiceProductQuantityConversion to include the service quantity conversions in the OData response, and
$format=json to use JSON as body format of the response (default is xml),
and the http-header parameter
x-csrf-token=fetch to get the CSRF-token to update the service in the next step.
As result ByD returns the following OData response body:
As you can see the service “{{ServiceID}}” has the base unit of measure and procurement unit of measure “Each” and no quantity conversion so far.
Step 2: Create quantity conversion
Before we can change the procurement UoM to a unit that differs from the base UoM, we need to create the quantity conversion between the base UoM and the new procurement UoM. In our example the ratio should be 1 EA corresponds to 8 HUR.
Using http-method POST and the parent object ID (service object ID) provided by GET-response in step 1 you can create a new quantity conversion:
As result ByD returns the following OData response body:
As you can see the service “{{ServiceID}}” now has the procurement unit of measure “Hour” with procurement status "active" and a service quantity conversion node instance for the conversion between Hour and Each.
Read and Update Service Product Sales Data using the Custom OData Service
In the custom OData service select the sales information relevant fields in co-relation with UI fields in Sales section of service product.
Step 1: Get service data and expand
Using the http-method GET and entity set ServiceProductCollection you can filter and read ByD service and include service sales information:
$filter=InternalID eq ‘{{ServiceID}}’ to filter the service by the internal ID,
$expand=ServiceProductSalesProcessInformation include the sales information in the OData response, and
$format=json to use JSON as body format of the response (default is xml),
and the http-header parameter
x-csrf-token=fetch to get the CSRF-token to update the service in the next step.
As result ByD returns the following OData response body:
As you can see the service “{{ServiceID}}” has the no service sales process information so far.
Step 2: Create distribution chains
We can create and associate sales information with distribution chains to service.
Using http-method POST and the parent object ID (service object ID) provided by GET-response in step 1 you can create and associate ServiceProductSalesProcessInformationCollectionto service:
Note: SalesOrganisationID and DistributionChannelCode is the valid ID and should be existing in the system.
Step 3: Get distribution chains / sales info
Using the http-method GET and entity set ServiceProductSalesProcessInformationCollection you can get the instance details of sales process information created in previous step and read service sales process info:
$format=json to use JSON as body format of the response (default is xml),
and the http-header parameter
x-csrf-token=fetch to get the CSRF-token to update the service in the next step.
As result ByD returns the following OData response body:
As you can see the service “{{ServiceID}}” has the sales process information which was created in previous step.
Step 4: Update distribution chains / sales info
Now we can update the planning information details of service like CustomerTransactionDocumentItemProcessingTypeDeterminationProductGroupCode and CashDiscountDeductibleIndicator.
We are again using http-method PATCH with the service object ID provided by the GET-response in step 3:
$filter=InternalID eq ‘{{ServiceID}}’ to filter the service by the internal ID,
$expand=ServiceProductFinancialProcessInformation include the valuation information in the OData response, and
$format=json to use JSON as body format of the response (default is xml),
and the http-header parameter
x-csrf-token=fetch to get the CSRF-token to update the service in the next step.
As result ByD returns the following OData response body:
As you can see the service “{{ServiceID}}” has the no service valuation information so far.
Step 2: Create companies
We can create and associate valuation information with company to service product.
Using http-method POST and the parent object ID (service object ID) provided by GET-response in step 1 you can create and associate CompanyID to service:
Note: CompanyID is the valid ID and should be existing in the system.
Step 3: Get companies
Using the http-method GET and entity set ServiceProductFinancialProcessInformationCollection you can get the instance details of valuation information created in previous step and read service financial process info:
$format=json to use JSON as body format of the response (default is xml),
and the http-header parameter
x-csrf-token=fetch to get the CSRF-token to update the service in the next step.
As result ByD returns the following OData response body:
As you can see the service “{{ServiceID}}” has the valuation / financial process information which was created in previous step.
Step 4: Query service valuation data (SVD)
Using the http-method GET and query ServiceProductValuationDataQueryByServiceProductID you can filter and read the service valuation data information like AccountDeterminationServiceProductValuationDataGroupCode:
$filter=ObjectID eq ‘{{SVDObjectID}}’ to filter the service valuation data by the SVDObjectID,
$expand=ServiceProductValuationDataAccountDeterminationSpecification include the Account Determination GroupCode information in the OData response, and
$format=json to use JSON as body format of the response (default is xml),
and the http-header parameter
x-csrf-token=fetch to get the CSRF-token to update the service in the next step.
As result ByD returns the following OData response body:
Step 6: Update account determination group (SVD)
In the service Valuation section to update the Account Determination field value, user has to create a custom OData service on business object ServiceValuationData.
We can update valuation information with account determination group of service product in business object Service Valuation Data (SVD).
Using http-method PATCH and the parent object ID (SVD Account Determination Object ID) provided by GET-response in step 5 you can update the account determination group of service product :
How to run an Product Data OData API Sample Scenario?
The following example creates material and service product by running the scenario “Product Data“:
Install the API sample package “Product Data” and configure your ByD system following the instructions in chapters “Download and Installation” and “Configuration” of the GitHub repositoryreadme file.
Open the Postman Runner and select the collection “Product Data”, the collection folder “Materials” , "Services" and the environment “ByD Product Data – <your ByD tenant>“:
Enter the postman environment variable UserName and Password
Run the postman collection using collection runner