cancel
Showing results for 
Search instead for 
Did you mean: 

Need groovy script for SAP CPI to loop through the nodes and add new node based on logic

8885676259
Explorer
0 Kudos

Hi Experts,

I am new to groovy and learning basics. But got little complex requirement which I tried but couldn't get the desired requirement. So asking your help to achieve my requirement. Please help me to achieve below requirment.

I need to read xml message and from that take value of /User/User/CustomField_BookingHours which is currently -2 and sort all /User/User/TimeAccount/timeAccountDetails/TimeAccountDetail/bookingDate, oldest date should the top one then take value of first /User/User/TimeAccount/timeAccountDetails/TimeAccountDetail/bookingAmount and add both like 0.5 + (-2) then the balance is -1.5 and then take 2nd /User/User/TimeAccount/timeAccountDetails/TimeAccountDetail/bookingAmount which is 0.5 and add reslted balance which is -1.5, so the result is 0.5 + (-1.5) now new balance is -1.0 and then take 2nd /User/User/TimeAccount/timeAccountDetails/TimeAccountDetail/bookingAmount whoch is 3.0 and add reslted balance which is -1.0, so the result is 3.0 + (-1.0) now new balance is 2.0 which is greater than or eauql to 0, add the new node after 3rd TimeAccountDetail node, after which balanc value becomes >= 0, with field /User/User/TimeAccount/timeAccountDetails/TimeAccountDetail/bookingAmount value of /User/User/CustomField_BookingHours.

Excepting adding this new node, remaining payload should be as-is. Only add new node with /User/User/CustomField_BookingHours where ever it becomes >= 0 after adding to each /User/User/TimeAccount/timeAccountDetails/TimeAccountDetail/bookingAmount.

Sample payload 

<User>
<User>
<CustomField_BookingHours>-2</CustomField_BookingHours>
<bookingDate>2023-11-11T00:00:00.000</bookingDate>
<TimeAccount>
<timeAccountDetails>
<TimeAccountDetail>
<bookingAmount>0.5</bookingAmount>
<bookingDate>2022-01-14T00:00:00.000</bookingDate>
</TimeAccountDetail>
<TimeAccountDetail>
<bookingAmount>0.5</bookingAmount>
<bookingDate>2022-04-02T00:00:00.000</bookingDate>
</TimeAccountDetail>
<TimeAccountDetail>
<bookingAmount>3.0</bookingAmount>
<bookingDate>2023-02-27T00:00:00.000</bookingDate>
</TimeAccountDetail>
<TimeAccountDetail>
<bookingAmount>1.0</bookingAmount>
<bookingDate>2024-04-03T00:00:00.000</bookingDate>
</TimeAccountDetail>
</timeAccountDetails>
</TimeAccount>
</User>
</User>

The output should be

<User>
<User>
<CustomField_BookingHours>-2</CustomField_BookingHours>
<bookingDate>2023-11-11T00:00:00.000</bookingDate>
<TimeAccount>
<timeAccountDetails>
<TimeAccountDetail>
<bookingAmount>0.5</bookingAmount>
<bookingDate>2022-01-14T00:00:00.000</bookingDate>
</TimeAccountDetail>
<TimeAccountDetail>
<bookingAmount>0.5</bookingAmount>
<bookingDate>2022-04-02T00:00:00.000</bookingDate>
</TimeAccountDetail>
<TimeAccountDetail>
<bookingAmount>3.0</bookingAmount>
<bookingDate>2023-02-27T00:00:00.000</bookingDate>
</TimeAccountDetail>
<TimeAccountDetail>
<bookingAmount>-2</bookingAmount>
<bookingDate>2023-11-11T00:00:00.000</bookingDate>
</TimeAccountDetail>
<TimeAccountDetail>
<bookingAmount>1.0</bookingAmount>
<bookingDate>2024-04-03T00:00:00.000</bookingDate>
</TimeAccountDetail>
</timeAccountDetails>
</TimeAccount>
</User>
</User>

Accepted Solutions (1)

Accepted Solutions (1)

naveen4796
Participant

Hi,

Got it, script was slightly modified to handle the dataType as in "Double" integer and here is the updated script. Give it a try now.

 

import com.sap.gateway.ip.core.customdev.util.Message;
    import java.util.HashMap;
    
    def Message processData(Message message) {
        //getting the input body
        def body = message.getBody(java.lang.String) as String;
        //prasing the input XML body
        def xml = new XmlParser().parseText(body)
        //running each User node
        xml.User.each{ 
            recs ->
            timeAccount = recs.TimeAccount.timeAccountDetails.TimeAccountDetail
            //sort the timeaccount records based on the order of old to new date
            timeAccount.sort { 
                a, b ->
                Date.parse("yyyy-MM-dd'T'HH:mm:ss.SSS", a.bookingDate.text()) <=> Date.parse("yyyy-MM-dd'T'HH:mm:ss.SSS", b.bookingDate.text())
            }
            boolean customAddHour_Flag = false
            //get CustomField_BookingHours
            def rootHour = recs.CustomField_BookingHours.text().toDouble()
            //replace the Timeaccountdetail segment with the updated logic
            recs.TimeAccount.timeAccountDetails.replaceNode{
                timeAccountDetails{
                    timeAccount.each{
                        timeRecs ->
                        //copy the /User/User/TimeAccount/timeAccountDetails/TimeAccountDetail
                        TimeAccountDetail{
                                bookingAmount(timeRecs.bookingAmount.text())
                                bookingDate(timeRecs.bookingDate.text())
                        }
                        
                        //get timeAccount - BookingAmount
                        def bAmount = timeRecs.bookingAmount.text().toDouble()
                        //add the hours
                        rootHour = rootHour + bAmount
                        //when hour is greater than or eauql to 0, add the new node after the TimeAccountDetail node
                        if(rootHour >= 0 && !customAddHour_Flag){
                            customAddHour_Flag = true
                            TimeAccountDetail{
                                bookingAmount(recs.CustomField_BookingHours.text())
                                bookingDate(recs.bookingDate.text())
                            }
                        }
                    }
                }
            }
        }
        //setting the output body
        message.setBody(groovy.xml.XmlUtil.serialize(xml))
        return message;
    }
    

 

 

GroovyIDE link for reference:

GroovyIDE Online Simulator 

Answers (2)

Answers (2)

8885676259
Explorer
0 Kudos

Hi @naveen4796 ,

Thank for the quick groovy. Current groovy logic considering adding node where ever the CustomField_BookingHours becomes zero with single TimeAccountDetail/bookingAmount. My requirement is to minus(actually plus we need to use as we are getting - sign in the for the value)) the CustomField_BookingHours from each TimeAccountDetail/bookingAmount and with the balance hours, I need to minus from next TimeAccountDetail/bookingAmount and with the balance, I need to minus next TimeAccountDetail/bookingAmount. LIke this loop, where ever the value becomes >= 0, after that we need to add the node. 

<User>
<User>
<CustomField_BookingHours>-0.75</CustomField_BookingHours>
<bookingDate>2023-11-11T00:00:00.000</bookingDate>
<TimeAccount>
<timeAccountDetails>
<TimeAccountDetail>
<bookingAmount>0.5</bookingAmount>
<bookingDate>2022-01-14T00:00:00.000</bookingDate>
</TimeAccountDetail>
<TimeAccountDetail>
<bookingAmount>0.5</bookingAmount>
<bookingDate>2022-04-02T00:00:00.000</bookingDate>
</TimeAccountDetail>
<TimeAccountDetail>
<bookingAmount>3.0</bookingAmount>
<bookingDate>2023-02-27T00:00:00.000</bookingDate>
</TimeAccountDetail>
<TimeAccountDetail>
<bookingAmount>1.0</bookingAmount>
<bookingDate>2024-04-03T00:00:00.000</bookingDate>
</TimeAccountDetail>
</timeAccountDetails>
</TimeAccount>
</User>
</User>

in SAP CPI, I need to read xml message and from that take value of /User/User/CustomField_BookingHours which is currently -0.75 and then take value of first /User/User/TimeAccount/timeAccountDetails/TimeAccountDetail/bookingAmount and add both like 0.5 + (-0.75) then the balance is -0.25 and then take 2nd /User/User/TimeAccount/timeAccountDetails/TimeAccountDetail/bookingAmount whoch is 0.5 and add reslted balance which is -0.25, so the result is 0.5 + (-0.25) now new balance is 0.25 which is greater than or eauql to 0, add the new node after 2rd TimeAccountDetail node, after which balanc value becomes >= 0, with field /User/User/TimeAccount/timeAccountDetails/TimeAccountDetail/bookingAmount value of /User/User/CustomField_BookingHours. So the output should be like below

<User>
<User>
<CustomField_BookingHours>-0.75</CustomField_BookingHours>
<bookingDate>2023-11-11T00:00:00.000</bookingDate>
<TimeAccount>
<timeAccountDetails>
<TimeAccountDetail>
<bookingAmount>0.5</bookingAmount>
<bookingDate>2022-01-14T00:00:00.000</bookingDate>
</TimeAccountDetail>
<TimeAccountDetail>
<bookingAmount>0.5</bookingAmount>
<bookingDate>2022-04-02T00:00:00.000</bookingDate>
</TimeAccountDetail>
<TimeAccountDetail>
<bookingAmount>-0.75</bookingAmount>
<bookingDate>2023-11-11T00:00:00.000</bookingDate>
</TimeAccountDetail>
<TimeAccountDetail>
<bookingAmount>3.0</bookingAmount>
<bookingDate>2023-02-27T00:00:00.000</bookingDate>
</TimeAccountDetail>
<TimeAccountDetail>
<bookingAmount>1.0</bookingAmount>
<bookingDate>2024-04-03T00:00:00.000</bookingDate>
</TimeAccountDetail>
</timeAccountDetails>
</TimeAccount>
</User>
</User>

naveen4796
Participant
0 Kudos

Hi,

The following groovy should fulfill your requirement, kindly give it a try.

import com.sap.gateway.ip.core.customdev.util.Message;
    import java.util.HashMap;
    
    def Message processData(Message message) {
        //getting the input body
        def body = message.getBody(java.lang.String) as String;
        //prasing the input XML body
        def xml = new XmlParser().parseText(body)
        //running each User node
        xml.User.each{ 
            recs ->
            timeAccount = recs.TimeAccount.timeAccountDetails.TimeAccountDetail
            //sort the timeaccount records based on the order of old to new date
            timeAccount.sort { 
                a, b ->
                Date.parse("yyyy-MM-dd'T'HH:mm:ss.SSS", a.bookingDate.text()) <=> Date.parse("yyyy-MM-dd'T'HH:mm:ss.SSS", b.bookingDate.text())
            }
            //replace the Timeaccountdetail segment with the updated logic
            recs.TimeAccount.timeAccountDetails.replaceNode{
                timeAccountDetails{
                    timeAccount.each{
                        timeRecs ->
                        //copy the /User/User/TimeAccount/timeAccountDetails/TimeAccountDetail
                        TimeAccountDetail{
                                bookingAmount(timeRecs.bookingAmount.text())
                                bookingDate(timeRecs.bookingDate.text())
                        }
                        //get CustomField_BookingHours
                        def rootHour = recs.CustomField_BookingHours.text().toFloat()
                        //get timeAccount - BookingAmount
                        def bAmount = timeRecs.bookingAmount.text().toFloat()
                        //add the hours
                        def hourAdd = rootHour + bAmount
                        //when hour is greater than or eauql to 0, add the new node after the TimeAccountDetail node
                        if(hourAdd >= 0){
                            TimeAccountDetail{
                                bookingAmount(recs.CustomField_BookingHours.text())
                                bookingDate(recs.bookingDate.text())
                            }
                        }
                    }
                }
            }
        }
        //setting the output body
        message.setBody(groovy.xml.XmlUtil.serialize(xml))
        return message;
    }
    

Adding GroovyIDE Online simulator link for your reference:
GroovyIDE Link - execute code 

Regards,

Naveen

8885676259
Explorer
0 Kudos
Hi @naveen4796, Thank for the quick groovy. Current groovy logic considering adding node where ever the CustomField_BookingHours becomes zero with single TimeAccountDetail/bookingAmount. My requirement is to minus(actually plus we need to use as we are getting - sign in the for the value)) the CustomField_BookingHours from each TimeAccountDetail/bookingAmount and with the balance hours, I need to minus from next TimeAccountDetail/bookingAmount and with the balance, I need to minus next TimeAccountDetail/bookingAmount. LIke this loop, where ever the value becomes >= 0, after that we need to add the node. <?xml version='1.0' encoding='UTF-8'?> <User> <User> <CustomField_BookingHours>-0.75</CustomField_BookingHours> <bookingDate>2023-11-11T00:00:00.000</bookingDate> <TimeAccount> <timeAccountDetails> <TimeAccountDetail> <bookingAmount>0.5</bookingAmount> <bookingDate>2022-01-14T00:00:00.000</bookingDate> </TimeAccountDetail> <TimeAccountDetail> <bookingAmount>0.5</bookingAmount> <bookingDate>2022-04-02T00:00:00.000</bookingDate> </TimeAccountDetail> <TimeAccountDetail> <bookingAmount>3.0</bookingAmount> <bookingDate>2023-02-27T00:00:00.000</bookingDate> </TimeAccountDetail> <TimeAccountDetail> <bookingAmount>1.0</bookingAmount> <bookingDate>2024-04-03T00:00:00.000</bookingDate> </TimeAccountDetail> </timeAccountDetails> </TimeAccount> </User> </User> in SAP CPI, I need to read xml message and from that take value of /User/User/CustomField_BookingHours which is currently -0.75 and then take value of first /User/User/TimeAccount/timeAccountDetails/TimeAccountDetail/bookingAmount and add both like 0.5 + (-0.75) then the balance is -0.25 and then take 2nd /User/User/TimeAccount/timeAccountDetails/TimeAccountDetail/bookingAmount whoch is 0.5 and add reslted balance which is -0.25, so the result is 0.5 + (-0.25) now new balance is 0.25 which is greater than or eauql to 0, add the new node after 2rd TimeAccountDetail node, after which balanc value becomes >= 0, with field /User/User/TimeAccount/timeAccountDetails/TimeAccountDetail/bookingAmount value of /User/User/CustomField_BookingHours. So the output should be like below <User> <User> <CustomField_BookingHours>-0.75</CustomField_BookingHours> <bookingDate>2023-11-11T00:00:00.000</bookingDate> <TimeAccount> <timeAccountDetails> <TimeAccountDetail> <bookingAmount>0.5</bookingAmount> <bookingDate>2022-01-14T00:00:00.000</bookingDate> </TimeAccountDetail> <TimeAccountDetail> <bookingAmount>0.5</bookingAmount> <bookingDate>2022-04-02T00:00:00.000</bookingDate> </TimeAccountDetail> <TimeAccountDetail> <bookingAmount>-0.75</bookingAmount> <bookingDate>2023-11-11T00:00:00.000</bookingDate> </TimeAccountDetail> <TimeAccountDetail> <bookingAmount>3.0</bookingAmount> <bookingDate>2023-02-27T00:00:00.000</bookingDate> </TimeAccountDetail> <TimeAccountDetail> <bookingAmount>1.0</bookingAmount> <bookingDate>2024-04-03T00:00:00.000</bookingDate> </TimeAccountDetail> </timeAccountDetails> </TimeAccount> </User> </User>