Re: Selecting a particular Custom object to display in Velocity Token for emails

LCENTENO
Level 3

Hi everyone, 
Quick question. I have a custom object called "Accounts", which has several different data fed fields including one called "Product". I created the custom tokens in my velocity script (snapshots below) to show the balance, and next date due of a specific product.


Payment Velocity Script:

LCENTENO_1-1682610442284.png

Next Due Date Velocity Script:

LCENTENO_2-1682611018262.png

Product Code Velocity Script:

LCENTENO_3-1682612187074.png

 

However, the data shown when the tokens are placed in the email is incorrect, as it is pulling the payment amount and due date info for the wrong product. The issue here is that under the "Accounts" custom object, another entry is added for every new product that is purchased by a customer. My question is, is there a string of code that should be applied to the "payment" and or "due date" custom tokens to ensure that the data pulled is for the correct Product? Thanks in advance. 🙂

Best,

Lucas

42 REPLIES 42
Darshil_Shah1
Level 10 - Community Advisor + Adobe Champion

You'd need to first sort the custom object records based on the field of interest (e.g., by last updated datetime). By default, the custom object records are sorted by created datetime in descending order. You should check out Sandy's blog on Sorting objects and lists in Velocity. Additionally, if you're looking to grab the custom object based on a field's value, then you can loop through the custom object records, and use conditionals to determine whether the data in the CO record matches the data you're looking for (sample code below).

 

#foreach($data in $cCUAccount_cList)
#if($data.productCode.equals("123"))
${data.currentPayment}
#end
#end

 

You can use the $TriggerObject (e.g., $TriggerObject.productCode) in case you want to reference the CO that triggered the campaign.

 

LCENTENO
Level 3

Hi Darshil,
So, two things. First to confirm, I would need to apply the following below to both my Payment and Due Date Tokens correct?
Next Due Date Example:

${cCUAccount_cList.get(0).nextDueDate}
#foreach($data in $cCUAccount_cList)
#if($data.productCode.equals("123"))
${data.nextDueDate}
#end



Second, since we have 15 different product codes, how would that be applied to the code so that the custom token picks up and applies the correct Next Due Date and or Payment? Thanks again for your insight and patience. 🙂

Best,
Lucas

Darshil_Shah1
Level 10 - Community Advisor + Adobe Champion

Why are you creating separate email script tokens for displaying each custom object attribute? You can just create a single email script token, add a conditional statement based on the product code you want to grab the CO record for and print all the corresponding CO record fields. Sample script below: 

 

#foreach($data in $cCUAccount_cList)
#if($data.productCode.equals("123"))
${data.nextDueDate}
${data.payment}
${data.productCode}
#end
#end

 

Also, I don't understand why are you referencing the first element of the CO for printing the "nextDueDate" data (i.e., in the first line of your code). Do you really need it? As I said in my previous comment, by default the CO records are stored by created date, in descending order. So the first record at the 0th index would be the one that was created at last. Let us know if you have questions.

 

LCENTENO
Level 3

Hi Darshil,
The email copy we are applying the tokens to is below:
{{lead.First Name:default=edit me}}, this is a reminder that your first loan payment of {{my.CurrentPayment:default=edit me}} is due on {{my.NextDueDate:default=edit me}}
So we want to pull the value for each token based on the Product Code. So, in the snapshot, we have a member who has the NEW AUTO CE12 Product Code, so his payment of 54 is due on December 15th. 

LCENTENO_1-1682623903908.png

How would this be implemented into the email copy above for payment and next due date tokens?
Best,

Lucas

 

SanfordWhiteman
Level 10 - Community Moderator

There’s not enough information for a complete answer yet.

 

Are you sending this at the moment they have the CO record added? If so, trigger on Added to <Custom Object Name> and use $TriggerObject in your code. (Don’t iterate over the list of CO records, it’s unnecessary because you already know which record you’re focused on.)

 

With output this brief, you can output it all from 1 {{my.token}}, which is what Darshil mentioned above. Just include the whole paragraph in the token. Or you could have the 2 {{my.token}}s as in your example. But don’t repeat the same code across tokens, that leads to hard-to-find bugs and wastes resources.

Darshil_Shah1
Level 10 - Community Advisor + Adobe Champion

Agreed with Sandy here! There's just not enough information here to provide you with a set-in-stone code / decide whether you should be iterating over the list of CO records or just could get away with the TriggerObject to pull fields of the record that triggered the campaign. I've tried including both the options in my first comment, but the one that you should actually implement depends on your use-case.

 

LCENTENO
Level 3

Hi Darshil and Sandford,

We are basically targeting this towards customers who opened a new loan. We wait until 7 days before their first payment is due before sending the message indicated above. 

Also, for the product code, since there are more than one product code, could you install all the product categories in the same code as listed by Darshil, using the dummy example product codes AUTO222, AUTO225, AUTO2277:

#foreach($data in $cCUAccount_cList)
#if($data.productCode.equals("123"))
${data.nextDueDate}
${data.payment}
${data.productCode}
#end
#end

Would you be using the && and || code to separate each product code in the #if statement? 

Thanks in advance and let me know if this helped to clarify or if more info is needed.

Best,

Lucas

SanfordWhiteman
Level 10 - Community Moderator

Please edit your post to use the Syntax Highlighter, then we’ll continue. Thanks.

LCENTENO
Level 3

Hi Sandford, 

I'm a little unclear about what you're asking.

Best,
Lucas

SanfordWhiteman
Level 10 - Community Moderator

Please insert code by clicking this button in the toolbar:

 

SanfordWhiteman_0-1682711226574.png

Choose Java as the language.

LCENTENO
Level 3
#foreach($data in $cCUAccount_cList)
#if($data.productCode.equals("123"))
${data.nextDueDate}
${data.payment}
${data.productCode}
#end
#end


Like this?

Darshil_Shah1
Level 10 - Community Advisor + Adobe Champion

You should set this up as a daily batch campaign with the "Has <friendly name of custom object> = True" filter, and in the flow, use Send Email flow step.

 

For the email script, you can use the velocity's date tool to find the difference between the current date and the $nextDueDate of all the CO records to check whether it's equal to 7. For the CO records that have the date difference = 7, you can print the CO record details. Additionally, if you wish to add further conditions on the product code along with the date difference equal to 7, you can first add the conditions for the product code. Note that individual product codes should be added in OR condition as you'd need to allow records with any of those product codes. So your code could be something like the below:

 

#set( $defaultTimeZone = $date.getTimeZone().getTimeZone("America/New_York") )
#set( $defaultLocale = $date.getLocale() )
#set( $calNow = $date.getCalendar() )
#set( $ret = $calNow.setTimeZone($defaultTimeZone) )
#set( $calConst = $field.in($calNow) )
#set( $ISO8601DateOnly = "yyyy-MM-dd" )
#set( $ISO8601DateTime = "yyyy-MM-dd'T'HH:mm:ss" )
#set( $ISO8601DateTimeWithSpace = "yyyy-MM-dd HH:mm:ss" )
#set( $ISO8601DateTimeWithMillisUTC = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" )
#set( $ISO8601DateTimeWithMillisTZ = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" )

#foreach($data in $cCUAccount_cList)
#if($data.productCode.equals("AUTO222") || $data.productCode.equals("AUTO225") || $data.productCode.equals("AUTO2277"))
#if (!$data.nextDueDate.isEmpty() && $data.nextDueDate)
#set( $convertednNextDueDate=$convert.toCalendar(
$convert.parseDate(
$data.nextDueDate, 
$ISO8601DateOnly,
$defaultLocale, 
$defaultTimeZone 
)
))
#set($diffDates=$date.difference($calNow,$convertednNextDueDate))
#set( $differenceInDays= $convert.toInteger($diffDates.getDays()))
#if($differenceInDays == 7)
${data.nextDueDate}
${data.payment}
${data.productCode}
#end 
#end
#end
#end

 

I hope this is helpful. Let us know if you have questions.

 

LCENTENO
Level 3

Hi Darshil and Sandford,

Okay, the code Darshil provided is a good to know, but it's not really something we are looking to implement into the email itself. I am not sure to which custom token I should be implementing these codes. I really only need the tokens to pull the payment balance and next due date based on their product categories. 

So, for the Payment Custom Token, I have this inserted:

#foreach($data in $cCUAccount_cList)
#if(($data.productCode.equals("PRODUCT 1") || $data.productCode.equals("PRODUCT 2") || $data.productCode.equals("PRODUCT 3") || $data.productCode.equals("PRODUCT 4") || $data.productCode.equals("PRODUCT 5") || $data.productCode.equals("PRODUCT 6") || $data.productCode.equals("PRODUCT 7") || $data.productCode.equals("PRODUCT 8") || $data.productCode.equals("PRODUCT 9") || $data.productCode.equals("PRODUCT 10") || $data.productCode.equals("PRODUCT 11") || $data.productCode.equals("PRODUCT 12") || $data.productCode.equals("PRODUCT 13") || $data.productCode.equals("PRODUCT 14"))
${data.payment}
${data.productCode}
#end
#end

 

Is this the correct code that is being applied? I would assume it is not since upon previewing my email with the custom token applied, an error message was displayed.

Also, since the field for payment is in string format, I am pretty sure it will not be displayed with currency symbols. Can I add coding within here to ensure that it displays the payment amount in currency?

Also, just to confirm, I can use the same coding above with the only change being I would change "data.payment" to "data.next due date" correct?

Lastly, I want to thank you both for your patience. Javascript and Velocity are two areas that I am quite new to and I am trying to learn it as I progress. Thanks again in advance for your continued assistance.

Best,

Lucas

SanfordWhiteman
Level 10 - Community Moderator

Oof. Follow the DRY principle. It’s more organized, more readable, less prone to typos.

#set( $interestingProductCodes = ["PRODUCT 1","PRODUCT 2","PRODUCT 3"] )
#foreach( $account in $cCUAccount_cList )
#if( $interestingProductCodes.contains($account.productCode) )
product code is interesting, do or output something
#end
#end

 

LCENTENO
Level 3

Hi Sandford,

So based on your feedback. I inserted the code with the 14 different product codes accordingly in line as you described below and included an action line under the #if statement.

#set( $interestingProductCodes = ["PRODUCT 1","PRODUCT 2","PRODUCT 3"] )
#foreach( $account in $cCUAccount_cList )
#if( $interestingProductCodes.contains($account.productCode) )
${cCUAccount_cList.get(0).currentPayment}
#end
#end


When I test the custom token in the email it does not appear to be pulling anything. Is there something here that I might have missed?

Best,

Lucas 

SanfordWhiteman
Level 10 - Community Moderator

Can’t make out why you’re doing this.

 

Why would you be always displaying the currentPayment property of the first item in the list, rather than the the current item as you’re iterating?

LCENTENO
Level 3

Basically, I want to display the current payment property of any items that fit the criteria based on their product code. The email is basically informing a customer that opened a new loan that their first payment in the amount of is due on whatever specific date their loan is due:

You're first payment of $0.00 is due on ________.

I am wanting to pull the payment amount based on the product codes that fit that criteria. I hope this makes sense.

 

Best,

Lucas

SanfordWhiteman
Level 10 - Community Moderator

So you should be outputting the properties of $account. That’s your loop variable.

 

$account is set to each item in the list, in list order.

 

You should not be referring to the (0)th item in the list. That’s the first item.

LCENTENO
Level 3

Ok, I am having a little trouble grasping what you're saying (again first time in velocity and Java). So for the code below:

#set( $interestingProductCodes = ["PRODUCT 1","PRODUCT 2","PRODUCT 3"] )
#foreach( $account in $cCUAccount_cList )
#if( $interestingProductCodes.contains($account.productCode) )
${cCUAccount_cList.get(0).currentPayment}
#end
#end

 


Are you saying that line 4 in the code (${cCUAccount_cList.get(0).currentPayment}) should be moved up to line 1? As far as the properties of $account, can you clarify? I assumed that I was doing that in line 2 of the code. Thanks. 

Best,

Lucas

SanfordWhiteman
Level 10 - Community Moderator

Are you saying that line 4 in the code (${cCUAccount_cList.get(0).currentPayment}) should be moved up to line 1?

No, I’m saying that line shouldn’t exist anywhere! There’s no reason, inside a #foreach loop, to ever be directly referencing the 0th (first) item in the list.

 

Velocity sets the loop variable to the value of each item of the list, in turn.

 

This code:

#set( $mylist = [1,2,3,4] )
#foreach( $myloopvariablename in $mylist )
loop var value is ${myloopvariablename}
#end

 

Will output:

loop var value is 1
loop var value is 2
loop var value is 3
loop var value is 4

 

It’s the same idea in any language that has a for/foreach concept.

 

Did you read my post on loops in Velocity?