{table-plus:width=750}
h3. Component
|| {color:#003366}NAME{color} | DynamicSender \\ ||
|| {color:#003366}CLASS_NAME{color} | com.CDRator.billing.workflow2.components.DynamicSender \\ ||
|| {color:#003366}DESCRIPTION{color} | A component used for sending dynamic mail or SMS. ||
|| PROJECT | svn.cdrator.com/svn/dev/core/trunk/Rator ||
h3. Methods
|| METHOD | execute ||
|| OBJECTS \\ | SUBSCRIPTION context ||
|| DESCRIPTION | Sends SMS or mail. ||
|| {color:#003366}PARAMETERS{color} || {color:#003366}OUTCOME{color} || {color:#003366}NOTES AND CONSIDERATIONS{color} ||
| The Parameter *TEMPLATE_KEY* is used to find the template from MailTemplate. The TEMPLATE_KEY is mandatory for the Dynamic Sender to Work. \\
From CORE Release 8.5 it is possible to set the TEMPLATE_KEY as a Context Object instead of a Parameter. In case there is both a TEMPLATE_KEY Parameter and a TEMPLATE_KEY Context Object, the value of the TEMPLATE_KEY Parameter is used. \\
From CORE Release 8.6, which will support letter generation, the TEMPLATE_KEY which is used to find template from MailTemplate, will also be used to fetch letter(LETTER_KEY). \\
\\
The Parameter *TEMPLATE_TYPE* is used to find out whether to send the template as SMS or Email or LETTER(LETTER option will be available from CORE RELEASE 8.6). \\
If the TEMPLATE_TYPE is not defined the message is sent as Email \\
From CORE Release 8.5 it is possible to set the TEMPLATE_TYPE as a Context Object instead of a Parameter. In case there is both a TEMPLATE_TYPE Parameter and a TEMPLATE_TYPE Context Object, the value of the TEMPLATE_TYPE Parameter is used. \\
From CORE Release 8.6 Dynamic Sender can be used for generating letters, by setting the TEMPLATE_TYPE to LETTER. \\
\\
The Parameter *TEMPLATE_TO* is used to find out to whom the template should be sent. If this parameter is not defined, then default value sub.getService().getPhoneNumber() for SMS and sub.getOwner().getEmail() for Mail will be used. \\
\\
It the parameter value is put in "" (double quotes), it will be used direct, e.g. TEMPLATE_TO="support@cdrator.com" means that this will be the destination of the email. \\
\\
Parameters prefix: \\
*WORK\_*<SOMETHING> is seen as temporary objects (any kind of object) which can be used for holding info until needed in another parameter. \\
\\
*LABEL\_*<SOMETHING> will become an available label in the template \\
\\
*CASE\_*<SOMETHING> will become an available condition in the template \\
\\
*ATTACHMENT*\_<SOMETHING> will be attached to the email. This can be used like: \\
1. ATTACHMENT_INVOICE=INVOICE.getDocArchive(WORK_INV_CODE).getDocArchiveFile \\
2. ATTACHMENT_SOME_FILE="C:/rator/files/somefile.txt" \\
3. Attachments in context CONTEXT.get("ATTACHMENT_<SOMETHING>"). \\
\\
*BLOCK\_*<SOMETHING> is explained in the section *Using BLOCK Replacement* below. \\
\\
These Objects will by default be available: \\
DATE_UTIL (DateUtil.java) \\
NUMBER_UTIL (NumberUtil.java) \\
COMMON_UTIL (CommonUtils.java) \\
You use them like: \\
WORK_NOW=*DATE_UTIL*.now; \\
WORK_BGM=SUBSCRIPTION.getBillingGroup(WORK_NOW); \\
\\ {color:#008000}{*}The order of parameters does not matter{*}{color} \\ | DONE \\ | It is possible to define who should receive the mail/sms at an earlier activity in the workflow. This can be done by adding a key "TEMPLATE_TO" to the context which defines the receiver. It is also possible to define the "TEMPLATE_TO" parameter on the activity itself. This will override the existing "TEMPLATE_TO" value in the context, if one already exists. Also TEMPLATE_KEY=<template name> and TEMPLATE_TYPE=EMAIL/SMS can be defined. \\
\\
Data can be retrieved using the same navigation logic as for labels and conditions by TYPE_LABEL. \\
\\
Advanced labels can be configured by defining retrieval path. An example could be where Context contains a SUBSCRIPTION and is a mobile subscription meaning serice will know the simcard. You can then navigate to simcard using: \\
LABEL_PIN1=SUBSCRIPTION.getService.getSimCard.getPin1 \\
LABEL_PIN2=SUBSCRIPTION.getService.getSimCard.getPin1 \\
\\
You can use work-labels for advanced navigation i.e. \\
WORK_SIMCARD=SUBSCRIPTION.getService.getSimCard \\
LABEL_PIN1=WORK_SIMCARD.getPin1 \\
\\
Future logic can be accomplished using TYPE_CASE and TYPE_BLOCK, which must be defined in template body as following: \\
{code}***IF@SOME_LABEL_NAME****
show this true value
***ELSE@SOME_LABEL_NAME***
Show this false value
***END@SOME_LABEL_NAME***{code}
Block is used for reports. \\ |
*Sample config:*
!20110214_dynamic_sender_sample.PNG|border=1,height=539,width=514!
*Sample parameters:*
|| KEY || VALUE || COMMENT ||
| TEMPLATE_TYPE | EMAIL | Setting which type of communication should be sent |
| TEMPLATE_KEY | MOBILE_SIGNUP_ORDER_CONFIRM | The reference (KEY) to the template |
| WORK_VOICE_KEY | TALE_PAKKE% | A work variable to hold a string value |
| CASE_HAS_VOICE_OPTION | SUBSCRIPTION.getService.hasOptionLike(WORK_VOICE_KEY) | Use Subscription from context to find out if the service has this option. \\
This will be an available condition in the template:{code}***IF@HAS_VOICE_OPTION***{code} \\
\\
Note the use of a previous found work variable (WORK_VOICE_KEY). |
| WORK_VOICE_OPTION | SUBSCRIPTION.getService.getOptionLike(WORK_VOICE_KEY) | A temporary work object to hold the option. \\ |
| LABEL_VOICE_OPTION_NAME | WORK_VOICE_OPTION.getProductOption.getName | Prepare a option *name* LABEL for the template by using a previous work object. The result of invoking the parameter value, will be the end result. |
| LABEL_VOICE_OPTION_DESCRIPTION | WORK_VOICE_OPTION.getProductOption.getDescription | Prepare a option *description* LABEL for the template by using a previous work object. The result of invoking the parameter value, will be the end result. |
*Sample Template:*
{code}
<html>
<body>
<p>
***IF@HAS_VOICE_OPTION***
You subscribed for this voice option: ***LABEL@VOICE_OPTION_NAME*** with description ***LABEL@VOICE_OPTION_DESCRIPTION***
***ELSE@HAS_VOICE_OPTION***
You did not subscribe for any voice option
***END@HAS_VOICE_OPTION***
</p>
</body>
</html>
{code}
h3. Using BLOCK Replacement
In order to use the Block Replacement functionality in the Dynamic Sender the *BLOCK_<SOME_BLOCK_NAME>* parameter has to be present, and the value has to be either a List of Hashtables or a String.
In case the value of the parameter is a String, the Block is simply replaced by the value of the parameter.
In case the value of the parameter is a List of Hashtables, the below section explains how to code and configure the Dynamic Sender Activity. Also, in the case that the List of Hashtables is created as a Context Object, the workflow has to be an In-Process workflow or, as a work-around, the List of Hashtables needs to be created as a Context Object in a Java Script activity in the activity just before the Dynamic Sender Activity which then needs to be an In-Process Activity. This is because the Hashtables inside the List cannot be persisted in the database.
{note}
The BLOCK Replacement functionality is available from CORE Release 8.5.
{note}
h4. Replacing a BLOCK List
Lets assume that we want to send a list of users and their phone number in a email.
For this we could have a template which looks like the following.
*Sample Template:*
{code}<html>
<body>
Here is a list of users and their Phone Number:
<p>
<!***BLOCK@USERS***>
***LABEL@FIRST_NAME*** ***LABEL@LAST_NAME***
***LABEL@PHONE_NUMBER***
<!***BLOCK@USERS***>
</p>
</body></html>{code}
So inside the Block *USERS* we have three labels we want to replace, namely, *FIRST_NAME*, *LAST_NAME* and *PHONE_NUMBER*.
In order for the Dynamic Sender to know which values should be replaced in the labels, a Hashtable needs to be created with the values for each User which should be included in the list. These Hashtables then need to be added to a List object which is assigned as the value of the *BLOCK_<SOME_BLOCK_NAME>* parameter (in this case BLOCK_USERS) in the Workflow Activity.
The List object would then typically be part of the Context for the workflow, but it is also possible to call a method on another Context Object which returns the needed List Object.
h5. List Object is part of Context
If the List Object is part of the workflow context, the Dynamic Sender Activity Parameter for the above template sample could look like this:
|| KEY || VALUE \\ ||
| BLOCK_USERS \\ | USER_BLOCK \\ |
This of course means that a List Object has to exist as a Context Object with the Key "USER_BLOCK".
The List Object can either be added to Context when the Hookpoint is invoked, or it can be created and added to the context in a JavaScript Activity inside the workflow.
It is very important that the Hashtable only contains Strings, because assigning any other object as the value will cause the Dynamic Sender activity to fail.
The following shows a simple example of building a List Object to be added to the Context when invoking the Hookpoint:
*Sample Java Code:*
{code}// Create List to hold all blocks
ArrayList<Hashtable> blockList = new ArrayList<Hashtable>();
// Get all Users objects to create a Block for
ArrayList<Users> users = getUsers();
// Run throuh all Users, create Hashtable with label names and values to be replaced, and add Hashtable to the List of Blocks
for (Users user : users) {
Hashtable block = new Hashtable();
block.put("FIRST_NAME", user.getFirstName());
block.put("LAST_NAME", user.getLastName());
block.put("PHONE_NUMBER", user.getSubscription().getService().get(0).getPhoneNumber());
blockList.add(block);
}
// Add the List of Blocks to the Context as a Context Object
Hashtable<String, Object> contextObjects = new Hashtable<String, Object> ();
contextObjects.put("USER_BLOCK", blockList);{code}
The following shows a simple example of building a List Object to be added to the Context inside the workflow in a JavaScript Activity:
*Sample JavaScript Activity Code:*
{code}// Create List to hold all blocks
blockList = new java.util.ArrayList();
// Get all Users objects to create a Block for from the context
users = WFCONTEXT.get("USERS");
// Run throuh all Users, create Hashtable with label names and values to be replaced, and add Hashtable to the List of Blocks
for (int i = 0; i < users.size(); i++) {
user = users.get(i);
block = new java.util.Hashtable();
block.put("FIRST_NAME", user.getFirstName());
block.put("LAST_NAME", user.getLastName());
block.put("PHONE_NUMBER", user.getSubscription().getService().get(0).getPhoneNumber());
blockList.add(block);
}
// Add the List of Blocks to the Context
WFCONTEXT.put("USER_BLOCK", blockList);{code}
{table-plus:width=750}
{table-plus} |