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.
cancel
Showing results for 
Search instead for 
Did you mean: 
uday_kamte2
Discoverer

Introduction


Blockchain is one of the intelligent technologies that constitute Intelligent Enterprise and SAP offers blockchain-as-a-service (BaaS) as part of SAP Cloud Platform to cater to it. Hyperledger Fabric, Multichain and Quorum technologies are made available to the customers with the help of this offering.

This blog explains how BaaS, specifically Multichain, offered by SAP Cloud Platform could be integrated with standard business processes in SAP Business ByDesign using the Cloud Application Studio.

Business Case and Example


The business case selected for this example is material provenance in manufacturing, in which the information about the origin of the product with regard to the input products and their characteristics is captured in the blockchain.

Since this use case is from the manufacturing sector, the product characteristic selected here is the serial number – as a serial number is unique for a product. However, depending on the industry to which a business process belongs, other characteristics could also be selected; for instance, the characteristic could be batch of a product in the pharmaceutical industry.

Let’s say there are three parties involved in the process; the manufacturer, who produces/assembles the finished product, the distributor who sells and repairs the product and the end customer who buys the product.


The finished product in our example is a laptop, which has a serial number associated with it. However, there are other input products such as RAM, processor and motherboard with their own serial numbers that will have been used in assembling this laptop.

Without the blockchain, the distributors and the customers only have access to the serial number of the laptop - they don't have any information about the input products and their serial numbers. However, with the blockchain material provenance this information would also be available to them.



 

Value Addition and Business Relevance


Let's say, the customer has given a laptop to the distributor for repair, and to fix the issue the distributor had to replace one or more components in it. With material provenance, this information would be captured in the blockchain - and with it, the customer would now have clear information about what was the existing configuration/serial numbers and what has been changed. The customer can use the information derived from the blockchain to physically validate the replaced components. Not only that, the customer can now use this information to check if the replaced component is of the right configuration, and if it is something that has been recommended by the manufacturer.

The approach described here can also possibly be applied to different business use cases in other areas like purchasing, sales, financials, projects, etc.

Technical Details


Please note, the code snippets provided here are only examples (there will be no maintenance support) and they should help you to save time when setting up your own scenarios. However, if you do find bugs, do let me know and I will adjust the blog accordingly.

This blog would not cover the service prerequisites for blockchain in SAP Could Platform, you can refer to this SAP Help portal link for the details.

I would also not be covering how the Multichain service can be configured in SAP Cloud Platform, you can refer to this SAP Help portal link for more details.

Block Diagram


The following block diagram explains the composition of the solution.



 

Setting up Integration with SAP Cloud Platform in Cloud Application Studio


Create a PDI solution, and in it create a REST based communication scenario and specify the service name and the placeholder for API keys – these would be used later in the code while triggering the REST call.







 

Create a communication system and a communication arrangement for the scenario created in the earlier step.



 

Specify the URL and the API key from the service instance created in SAP Cloud Platform.







 

Create an extension BO for Goods and Activity Confirmation (GAC) and in its ‘Event-BeforeSave’ event, obtain all the input serial numbers associated with the serial number of the finished material being shipped out in the outbound delivery.

Concatenate input product and input serial number information, separated by space, and capture it in a string. Convert the content of this string to hexadecimal (HEX) format.. This information in HEX form is then written to the blockchain by invoking a REST call, under which ‘publish’ method is called. While triggering the ‘publish’ method, we specify the finished serial number along with its product ID and name of the blockchain stream to which this data would written.



 



 
/*
Add your SAP Business ByDesign scripting language implementation for:
Business Object: GoodsAndActivityConfirmation
Node: Root
Event: BeforeSave

Note:
- To access the elements of the business object node,
use path expressions, for example, this.<element name>.
- To use code completion, press CTRL+J.
- The solution uses this script when:
- the instance of the business object is being saved.
- the instance of the business object is created from other sources like web services, preview screen, and so on.
*/

import ABSL;
import AP.Common.GDT;
import AP.FO.ProductDataMaintenance.Global;
import AP.LogisticsExecution.Global;

var stringInput : DataType::LANGUAGEINDEPENDENT_EXTENDED_Text;
var stringLoopVal : DataType::LANGUAGEINDEPENDENT_EXTENDED_Text;
var stringHexVal : DataType::LANGUAGEINDEPENDENT_EXTENDED_Text;
var Body : DataType::LANGUAGEINDEPENDENT_EXTENDED_Text;
var productId : DataType::LANGUAGEINDEPENDENT_EXTENDED_Text;
var serialId : DataType::LANGUAGEINDEPENDENT_EXTENDED_Text;
var root : elementsof GoodsAndActivityConfirmation;
var invChgItem = this.InventoryChangeItem;

if (this.BaseBusinessTransactionDocumentReference.TypeCode == "73" && this.CancellationDocumentIndicator == false)
{
foreach (var invCItem in invChgItem)
{
if (invCItem.InventoryMovementDirectionCode == "1")
{
var prodID = invCItem.InventoryItemChange.MainInventorySeparatingValues.MaterialKey.ProductID.content;
var invItemChgSNo = invCItem.InventoryItemChangeSerialNumber;
var indProd : IndividualProduct.ServiceProcessInformation.SerialNumberIdentification.SerialNumberIdentificationOverview;
var qrySerialID = indProd.QueryByElements;
var selParm = qrySerialID.CreateSelectionParams();
selParm.Add(qrySerialID.ParentRefProductKey.ProductID.content, "I", "EQ", prodID);
foreach (var invSlNo in invItemChgSNo)
{
selParm.Add(qrySerialID.ParentSerialID, "I", "EQ", invSlNo.SerialID);
var result = qrySerialID.Execute(selParm);
stringInput.Clear();

foreach (var resultLine in result)
{
stringLoopVal.Clear();
productId = resultLine.ReferencedProductKey.ProductID.content.RemoveLeadingZeros();

serialId = resultLine.IndividualProductSerialNumberKey.SerialID.RemoveLeadingZeros();

stringLoopVal = productId + " " + serialId + ",";
stringInput = stringInput + stringLoopVal;

}

if (!stringInput.IsInitial())
{

stringHexVal.Clear();
stringHexVal = GAC_StringToHexLibrary.StringToHex(stringInput);

var ScenarioName = "BAAS";
var ServiceName = "SCPIntegration";
var HttpMethod = "POST";
var ContentType = "application/json";
var HeaderParameter : collectionof NameAndValue;
var URLParameter : collectionof NameAndValue;
var HttpResource = "";
var URLParameterEntry : NameAndValue;
var HeaderParameterEntry : NameAndValue;

HeaderParameterEntry.Name = "apikey";
HeaderParameterEntry.Value = "&BAAS_apikey&";
HeaderParameter.Add(HeaderParameterEntry);

var initialBody = "{ \"method\": \"publish\", \"params\":[\"NewSerialNumbers\", ";

var endBody = "\"] }";

Body = initialBody + "\"" + prodID + " " + invSlNo.SerialID + "\"" + "," + "\"" + stringHexVal + endBody;

var ws_result = WebServiceUtilities.ExecuteRESTService(ScenarioName, ServiceName, HttpMethod, HttpResource, URLParameter, HeaderParameter, ContentType, Body);

}
}
}
}
}


 

You should also ensure that the certificate for SAP Cloud Platform is added to the 'Certificate Trust List' in 'Application and User Management' Work Center; without this, the system firewall may block the outgoing REST call.

 


Example of Data written to the blockchain


Let’s say we have a laptop with serial ID LAPTOP_SN16, which constitutes following input products and input serial IDs:

When an outbound Delivery corresponding to this laptop is released, this input product information would be written to the blockchain.



Similarly, when the laptop's components are replaced by the distributor as a part of the repair process, the new component information could be written to the blockchain.

Reading the blockchain data


The data written to the blockchain can be checked using the Multichain Dashboard.





 

However, we could also develop a PDI solution that reads the data from the blockchain. This could be achieved using a custom BO, which would trigger a REST call and read the blockchain data for the entered product and serial number.





 





 
/*
Add your SAP Business ByDesign scripting language implementation for:
Business Object: ReadBlockChainData
Node: Root
Action: readData

Note:
- To access the elements of the business object node,
use path expressions, for example, this.<element name>.
- To use code completion, press CTRL+J.
- This script file is mass-enabled, i.e. the keyword "this"
refers to a collection of node instances.

*/

import ABSL;
import AP.Common.GDT;
import AP.FO.ProductDataMaintenance.Global;
import AP.LogisticsExecution.Global;
import AP.PlatinumEngineering;

var Body : DataType::LANGUAGEINDEPENDENT_EXTENDED_Text;
var prodDetails : DataType::LANGUAGEINDEPENDENT_EXTENDED_Text;
var hexString : DataType::XPEXStringType;
var manufactKey = "1XypvHi6BjzrQpgih9SEPbagRjdYj67NJ5duEr";
var resultNode : elementsof ReadBlockChainData.Result;

foreach (var rootNode in this)
{
if (rootNode.Result.Count() > 0){
rootNode.Result.Delete();
}

var ScenarioName = "BAAS";
var ServiceName = "SCPIntegration";
var HttpMethod = "POST";
var ContentType = "application/json";
var HeaderParameter : collectionof NameAndValue;
var URLParameter : collectionof NameAndValue;
var HttpResource = "";
var URLParameterEntry : NameAndValue;
var HeaderParameterEntry : NameAndValue;

HeaderParameterEntry.Name = "apikey";
HeaderParameterEntry.Value = "&BAAS_apikey&";
HeaderParameter.Add(HeaderParameterEntry);

var initialBody = "{ \"method\": \"liststreamkeyitems\", \"params\":[\"NewSerialNumbers\", ";

var endBody = "\"] }";

prodDetails = rootNode.productid.RemoveLeadingZeros() + " " + rootNode.serialnum.RemoveLeadingZeros();

Body = initialBody + "\"" + prodDetails + endBody;

var ws_result = WebServiceUtilities.ExecuteRESTService(ScenarioName, ServiceName, HttpMethod, HttpResource, URLParameter, HeaderParameter, ContentType, Body);

var json = ws_result.Content;
var i = 0;
var subString;
var publisherPattern = "(\"publishers\")";
var publisherEndPattern = "(\"],\")";
var blocktimePattern = "(\"blocktime\")";
var dataPattern = "(\"data\":\")";
var comaPattern = "(\",\")";
var startPosition = 0;
var comaPosition = 0;
var substringLength = 0;
var patternPosition = 0;
var exitLoop = 0;

while (exitLoop < 1)
{
resultNode.Clear();
// Read the Publisher
patternPosition = json.FindRegex(publisherPattern, startPosition);
if (patternPosition < 0)
{
exitLoop = 1;
}
else
{
comaPosition = json.FindRegex(publisherEndPattern, patternPosition);
if (comaPosition < 0)
{
exitLoop = 1;
}
else
{
substringLength = comaPosition - patternPosition;
subString = json.Substring(patternPosition, substringLength);
subString = subString.Replace("\"publishers\":[\"", " ");
subString = subString.Trim();

if (subString == manufactKey)
{
resultNode.publisher = "Manufacturer";
}
else
{
resultNode.publisher = "Distributor";
}
startPosition = comaPosition;
}
}


// Read the Data
patternPosition = json.FindRegex(dataPattern, startPosition);
if (patternPosition < 0)
{
exitLoop = 1;
}
else
{
comaPosition = json.FindRegex(comaPattern, patternPosition);
if (comaPosition < 0)
{
exitLoop = 1;
}
else
{
substringLength = comaPosition - patternPosition;
subString = json.Substring(patternPosition, substringLength);
subString = subString.Replace("\"data\":\"", " ");
subString = subString.Trim();
subString = subString.ToUpperCase();

var stringResult = GAC_StringToHexLibrary.HexToString(subString);
resultNode.result = stringResult;
startPosition = comaPosition;
}
}

// Read Block Time
patternPosition = json.FindRegex(blocktimePattern, startPosition);
if (patternPosition < 0)
{
exitLoop = 1;
}
else
{

substringLength = 22;
subString = json.Substring(patternPosition, substringLength);
subString = subString.Replace("\"blocktime\":", " ");
subString = subString.Trim();
resultNode.dateTime = GAC_UnixTimeLibrary.UnixTimeStampConversion(subString);
startPosition = patternPosition + 22;
}

if (exitLoop != 1)
{
rootNode.Result.Create(resultNode);
}
}
}


Here we read the data using ‘liststreamkeyitems’ method by specifying the key, which in our case is the product ID and the serial ID separated by space.

This REST call returns the data in JSON format, which is parsed to separate the information about the publisher (in our case, either a manufacturer or a distributor), the block time (when the block was created) and the actual data stored in the block (which will be returned in HEX format).

Once the actual data content is identified in JSON, it is converted from HEX to string - to make it intelligible to the end user - and displayed on the UI.





 

Disclaimer


Please note, the idea behind publishing this blog is to showcase how blockchain integration could be achieved in SAP Business ByDesign. It is not to stipulate the information provided here as a standard template for all the blockchain scenarios.

Useful Links


SAP Cloud Platform
SAP’s Blockchain offerings
SAP Cloud Platform’s Multichain home page
SAP Help for Multichain
1 Comment