Groovy script:
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;
}
SAP HCI/CPI - Cloud Platform Integration
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
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
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>
<?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
Groovy script:
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.
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
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>
<?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
When cant use the ODATA adapter if there is limitation on pulling the records from API
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>
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
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 = 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:
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:
CM - header
count = 340;
Output:
<Nodes>
<Node>
<Value>100</Value>
</Node>
<Node>
<Value>100</Value>
</Node>
<Node>
<Value>100</Value>
</Node>
<Node>
<Value>40</Value>
</Node>
</Nodes>
Output:
<Nodes>
<Node>
<Value>100</Value>
</Node>
<Node>
<Value>100</Value>
</Node>
<Node>
<Value>100</Value>
</Node>
<Node>
<Value>40</Value>
</Node>
</Nodes>
Subscribe to:
Posts (Atom)