This blog is created to throw some lights on SAP CPI concepts, which experienced in my journey. Trying to explore more about HCI/Cloud platform integration/SCPI and sharing the contents to help you. Thanks for all Users your support. Please give your comments below ...
Friday, 29 November 2024
Set dispute flag for multiple invoice lines
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
def Message processData(Message message) {
def body = message.getBody(java.lang.String);
def newbody = body.replace('-','_');
def list = new XmlSlurper().parseText(newbody);
def map = message.getProperties();
def InvoiceId = map.get("InvoiceId");
def disputeInvoice = "No";
def returnInvoiceError = "No";
int counter = 0;
def approval_id = list.invoice_header.approvals.approval.id.text();
def InvoiceType = list.invoice_header.invoice_lines.invoice_line[0].custom_fields.item_category.text();
def DocumentType = list.invoice_header.document_type.text();
def InvoiceNumber = list.invoice_header.invoice_number.text();
def AccountType = list.invoice_header.account_type.name.text();
int lengthofInvoiceNumber = InvoiceNumber.length();
message.setProperty("approval_id",approval_id);
list.invoice_header.invoice_lines.invoice_line.each
{
counter = counter + 1;
}
if((DocumentType == "Invoice") && (InvoiceType == "Services") && (AccountType.contains("GBL")))
{
if(counter > 1)
{
disputeInvoice = "Yes";
returnInvoiceError = "Invoice Id: " + InvoiceId + " " + "is a Service Invoice with multiple Invoice lines. Please submit new invoice with single line only and do not issue a credit memo."
}
}
message.setProperty("disputeInvoice",disputeInvoice);
message.setProperty("returnInvoiceError",returnInvoiceError);
return message;
}
Replace xml declaration using XSLT
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl=http://www.w3.org/1999/XSL/Transform>
<xsl:output indent="yes" method="xml" encoding="utf-8" omit-xml-declaration="yes"/>
<!-- template to copy elements -->
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
<!-- template to copy attributes -->
<xsl:template match="@*">
<xsl:attribute name="{local-name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<!-- template to copy the rest of the nodes -->
<xsl:template match="comment() | text() | processing-instruction()">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>
SortBy invoice approvalID for XSLT mapping
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl=http://www.w3.org/1999/XSL/Transform>
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="root/invoice-header">
<xsl:copy>
<xsl:apply-templates select="node() except (approvals)"/>
<approvals>
<xsl:apply-templates select="approvals/approval">
<xsl:sort select="id" order= "descending"/>
</xsl:apply-templates>
</approvals>
</xsl:copy>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Get the dynamic value from property and compare the values and select the interface at Router
import com.sap.gateway.ip.core.customdev.util.Message;
import groovy.xml.*;
import groovy.util.*;
import groovy.xml.MarkupBuilder;
def Message processData(Message message) {
def body = message.getBody(java.lang.String) as String
def payload = new XmlParser().parseText(body);
def mProp = message.getProperties();
String input = mProp.get("Cust_MessageDirect_FO_TORType");
String TOR_50 = mProp.get("Cust_FreightOrder_TORTypes");
String Typdecode_50 = mProp.get("Cust_Typecode_50");
String Typdecode_208 = mProp.get("Cust_Typecode_208");
String Typdecode_67 = mProp.get("Cust_Typecode_67");
def result = TOR_50.contains(input)
message.setProperty("TOR_IsMatch_50",result);
def Type_IsMatch_50="false";
def Type_IsMatch_208="false";
def Type_IsMatch_67="false";
def typdeCode = payload.TransportationDocument.TextCollection.Text.'*'.findAll{node->node.name()=="TypeCode"}*.text()
for(int i=0;i<typdeCode.size();i++)
{
if(Typdecode_50.contains(typdeCode[i]))
{
Type_IsMatch_50 = "true";
}
if(Typdecode_208.contains(typdeCode[i]))
{
Type_IsMatch_208 = "true";
}
if(Typdecode_67.contains(typdeCode[i]))
{
Type_IsMatch_67 = "true";
}
}
message.setProperty("Type_IsMatch_50",Type_IsMatch_50)
message.setProperty("Type_IsMatch_208",Type_IsMatch_208)
message.setProperty("Type_IsMatch_67",Type_IsMatch_67)
return message;
}
Input:
Cust_MessageDirect_FO_TORType = ZF02
Cust_FreightOrder_TORTypes = 'ZF01','ZF02','ZF03'
Cust_Typecode_50 = 'ZBYRC','ZBYPA'
Cust_Typecode_208 = ZTORT
Cust_Typecode_67 = ZFCPI
Output:
Returns true or false for all property values.
Tuesday, 26 November 2024
XML to JSON convertor using XSLT mapping
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">{
<xsl:apply-templates select="*"/>}
</xsl:template>
<!-- Object or Element Property-->
<xsl:template match="*">
"<xsl:value-of select="name()"/>" : <xsl:call-template name="Properties"/>
</xsl:template>
<!-- Array Element -->
<xsl:template match="*" mode="ArrayElement">
<xsl:call-template name="Properties"/>
</xsl:template>
<!-- Object Properties -->
<xsl:template name="Properties">
<xsl:variable name="childName" select="name(*[1])"/>
<xsl:choose>
<xsl:when test="not(*|@*)">"<xsl:value-of select="."/>"</xsl:when>
<xsl:when test="count(*[name()=$childName]) > 1">{ "<xsl:value-of select="$childName"/>" :[<xsl:apply-templates select="*" mode="ArrayElement"/>] }</xsl:when>
<xsl:otherwise>{
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="*"/>
}</xsl:otherwise>
</xsl:choose>
<xsl:if test="following-sibling::*">,</xsl:if>
</xsl:template>
<!-- Attribute Property -->
<xsl:template match="@*">"<xsl:value-of select="name()"/>" : "<xsl:value-of select="."/>",
</xsl:template>
</xsl:stylesheet>
Thursday, 21 November 2024
Groovy Script to form the dynamic http query for top and skip
For ODATA - Using looping process can achieve it
For HTTP - there is no easy way so you can use this script and use iterating splitter and gather, in between use the request reply to pull 100, 100 records to get all records.
Groovy script
import com.sap.gateway.ip.core.customdev.util.Message;
import groovy.xml.*;
import java.text.SimpleDateFormat;
import groovy.json.*;
import groovy.util.*;
import groovy.xml.MarkupBuilder;
def Message processData(Message message) {
def body = message.getBody(java.lang.String) as String
def headers = message.getHeaders();
def count = headers.get("count");
count = count.toInteger();
// def count = 640;
int chunksize = 100
int iteration = Math.ceil(count / chunksize).toInteger()
StringWriter writer = new StringWriter()
MarkupBuilder xml = new MarkupBuilder(writer)
xml.Nodes {
for(int i=0;i < iteration;i++){
int skip = i * chunksize
println skip
int top = (i == iteration - 1)?(count % chunksize == 0 ? chunksize : count % chunksize): chunksize
//println top
Node {
if (skip == 0) {
query "\$top=${top}"
}
else{
query "\$top=${top}&\$skip=${skip}"
}
}
}
}
def resultXML =writer.toString()
message.setBody(resultXML)
return message;
}
Input => Header => Count =640
Output:
<Nodes>
<Node>
<query>$top=100</query>
</Node>
<Node>
<query>$top=100&$skip=100</query>
</Node>
<Node>
<query>$top=100&$skip=200</query>
</Node>
<Node>
<query>$top=100&$skip=300</query>
</Node>
<Node>
<query>$top=100&$skip=400</query>
</Node>
<Node>
<query>$top=100&$skip=500</query>
</Node>
<Node>
<query>$top=40&$skip=600</query>
</Node>
</Nodes>
Groovy Script to use the mod and divide on the count in sap cpi
import com.sap.gateway.ip.core.customdev.util.Message;
import groovy.xml.*;
import java.text.SimpleDateFormat;
import groovy.json.*;
import groovy.util.*;
import groovy.xml.MarkupBuilder;
def Message processData(Message message) {
def body = message.getBody(java.lang.String) as String
def headers = message.getHeaders();
def count = headers.get("count");
count = count.toInteger()
// def count = 340;
int ct = count / 100
int remain = count % 100
StringWriter writer = new StringWriter()
MarkupBuilder xml = new MarkupBuilder(writer)
xml.Nodes {
(1..ct).each { index ->
Node {
Value(100)
}
}
if(remain > 0 ){
Node{
Value(remain)
}
}
}
def resultXML = writer.toString()
message.setBody(resultXML)
return message;
}
Input:
Output:
<Nodes>
<Node>
<Value>100</Value>
</Node>
<Node>
<Value>100</Value>
</Node>
<Node>
<Value>100</Value>
</Node>
<Node>
<Value>40</Value>
</Node>
</Nodes>
Tuesday, 30 July 2024
Pick integer from alphanumeric String in Mapping
Pick only integer value from alphanumeric string in message mapping
import com.sap.it.api.mapping.*;
def String extractNumeric(String arg1){
def str = arg1.replaceAll("\\D+","");
return str
}
To remove the duplicate lines in CSV file
To remove the duplicate lines in CSV file:
Groovy script:
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import groovy.xml.XmlUtil;
import groovy.util.*;
//import java.io.file.*
def Message processData(Message message) {
def body = message.getBody(java.lang.String) as String;
def myList = body.tokenize("\n")*.trim()
myList = myList.unique()
body = myList
// message.setBody(body)
message.setProperty("BusinessPartner", myList);
return message;
}
Remove dummy fields from Json
Remove dummy fields from Json:
Groovy script:
import com.sap.gateway.ip.core.customdev.util.Message;
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
def Message processData(Message message){
def body =message.getBody(java.lang.String) as String
def jsonParser =new JsonSlurper()
def jsonObject = jsonParser.parseText(body)
def rem = []
for(i=0;i<=20;i++){
def toseries = "dummy${i}"
rem << toseries
}
println rem.size()
def toRemove = rem
//def toRemove =["dummy0","dummy1"]
println toRemove
toRemove.each { field ->
jsonObject.remove(field.toString())
message.setBody(JsonOutput.toJson(jsonObject))}
return message;
}
ODATA xml message unformatted xml and shift to new line
Find all the messages from the unformatted xml and place in newline:
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import groovy.xml.XmlUtil;
import groovy.util.*;
def Message processData(Message message) {
def body = message.getBody(java.lang.String) as String;
def xml = new XmlSlurper().parseText(body)
def error = xml.'**'.findAll { it.name() == 'message' }*.text().join('\n')
message.setBody(error);
return message;
}
Multiple header and multiple item xml.to csv conversion
CSV file to be prepared with multiple header with multiple line item on it
import com.sap.gateway.ip.core.customdev.util.Message;
import groovy.xml.*;
def Message processData(Message message) {
def body = message.getBody(java.lang.String) as String;
def ag = new xml2csv()
message.setBody(ag.execute(body))
return message
}
class xml2csv {
def execute(ins) {
//define writer
def writer = new StringWriter()
//parse input
def parsedXml = new XmlParser().parseText(ins)
def content = new XmlSlurper().parseText(ins)
def header = content.Header.children().collect().join(',')
def csv = content.Item.inject(header){ result, row ->
[result, row.children().collect().join(',')].join("\n")
}
println csv.toString()
return csv.toString()
}
}
Set flag on particular dates in month in sap cpi groovy
Requirementis to send the report on particular date's on the month in groovy script.
Groovy script:
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import groovy.json.JsonSlurper
import groovy.json.JsonException
import groovy.json.JsonOutput
import javax.xml.*;
import groovy.xml.*
def Message processData(Message message) {
def body = message.getBody(java.lang.String) as String;
def date = new Date()
def day = date.getDate()
def Flag = ""
if(day == 20 || day == 21 || day == 22 || day == 23){
Flag = "true"
}
else {
Flag = "false"
}
message.setProperty("Flag",Flag)
return message;
}
Day comparison groovy script and set flag
Get all the day from the input 3 fields and check if it matching with today day then return true or false.
Day comparison script
Groovy script:
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import groovy.json.JsonSlurper
import groovy.json.JsonException
import groovy.json.JsonOutput
import javax.xml.*;
import groovy.xml.*
def Message processData(Message message)
{def propertyMap = message.getProperties()
String date2 = propertyMap.get("ExectutionDate");
String date3 = propertyMap.get("ExectutionDate1");
String date4 = propertyMap.get("ExectutionDate2");
def date1 = new Date()
String day = date1.getDate()
if (day == date2 || day == date3 || day == date4 )
{ Flag = "true"; }
else {Flag = "false" }
message.setProperty("Flag1", Flag)
message.setProperty("day1", day)
return message;}
Special character issue \u00a0 in SAP CPI
URL Encode the query:
Data: "ADDRESS": "+GleuelerStr.70\u00a0Building5,floor2A,room015+Cologne\u00a0NorthRhine-Westphalia+50931",
This char "\u00a0" is causing the issue, so can't pull location info from GoogleAPI.
Google script line:
inputurl = URLEncoder.encode(inputurl, "UTF-8")
We can get the response.
Set timezone in Content modifier
Set timezone in Content modifier directly without script:
${date-with-timezone:now:America/Los_Angeles:yyyy-MM-dd'T'HH:mm:
Remove new line csv file on conversion
Remove the new line for the XML to CSV conversion:
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
def Message processData(Message message)
{
def content= message.getBody(java.lang.String); // Read Body
newcontent=content.replaceAll("[\n\r]", "")
message.setBody(newcontent); // Set message body
return message;
}
Check first char is string or number
To check if the first character is number or string:
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
def Message processData(Message message) {
//Body
def body = message.getBody(java.lang.String);
def firstChar = body.substring(0..1)
if (firstChar.matches("[0-9]+")){
number= "true"
}else
{
number = "false"
}
message.setProperty("number",number)
return message;
}
Allow only numeric value on string
Groovy script:
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
def Message processData(Message message) {
//Body
def body = message.getBody(java.lang.String);
//message.setBody(body);
def num = body.replaceAll("[^0-9]", "")
message.setProperty("num",num)
return message;
}
Input: 43645fdggtshf
Output: num: 43645
Remove the lines inbetween the header and item after csv conversion
Groovy script:
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
def Message processData(Message message)
{
def content= message.getBody(java.lang.String); // Read Body
def newcontent=content.replaceAll('\n\n', '\n');
message.setBody(newcontent); // Set message body
return message;
}
Remove multimap XSLT mapping
XSLT Mapping:
<xsl:template match="//ns1:SupplierInformation">
<xsl:copy-of select="."/>
</xsl:template>
Manual xml to csv convertion
Convert XML to CSV conversion different option:
import com.sap.gateway.ip.core.customdev.util.Message;
import groovy.util.*
import groovy.xml.XmlUtil;
import groovy.util.XmlSlurper;
import groovy.xml.MarkupBuilder;
def Message processData(Message message) {
//Body
def body = message.getBody(java.lang.String) as String;
def det
def body1
def lines = body.split("\n")
def CAMPAIGN = lines[1].trim()
def POLY = lines[3].trim()
def BATCH = lines[5].trim()
def UOM = lines[7].trim()
def PRODUCT = lines[9].trim()
def LINE = lines[11].trim()
def VERSION = lines[13].trim()
def TIMESTAMP = lines[15].trim()
def ABORTED = lines[17].trim()
for(i=19;i<=lines.size();i++)
{
if(lines[i-1].trim() != "EVENTS:"){
det = i;
}
else{ break;}
}
for(j=19;j<det;j++)
{
def data = lines[j].trim()
data = data.split(/\s+/)
body1 += "\n<CONS>\n";
body1 += "<Name>${data[0]}</Name>\n";
body1 += "<value>${data[1]}</value>\n";
body1 += "<Test>${data[2]}</Test>\n";
body1 += "</CONS>";
}
println body1
//def xmlBuilder = new StringBuilder()
//xmlBuilder.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
def xmlString = """
<data>
<CAMPAIGN>${CAMPAIGN}</CAMPAIGN>
<POLY>${POLY}</POLY>
<BATCH>${BATCH}</BATCH>
<UOM>${POLY}</UOM>
<PRODUCT>${BATCH}</PRODUCT>
<LINE>${LINE}</LINE>
<VERSION>${VERSION}</VERSION>
<TIMESTAMP>${TIMESTAMP}</TIMESTAMP>
<ABORTED>${ABORTED}</ABORTED>
<CONSUMPTIONS>${body1}</CONSUMPTIONS>
</data>
"""
xmlString = xmlString.replaceAll("null","")
message.setProperty("data",xmlString)
return message
}