Friday, 29 November 2024

Set dispute flag for multiple invoice lines

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;

}




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>





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.




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>





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&amp;$skip=100</query>

</Node>

<Node>

<query>$top=100&amp;$skip=200</query>

</Node>

<Node>

<query>$top=100&amp;$skip=300</query>

</Node>

<Node>

<query>$top=100&amp;$skip=400</query>

</Node>

<Node>

<query>$top=100&amp;$skip=500</query>

</Node>

<Node>

<query>$top=40&amp;$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:

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>





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

}