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>