You are viewing limited content. For full access, please sign in.

Question

Question

Email notifications every 30 days

asked on June 15, 2016

Hi -

I am working on a workflow that sends out reminder emails that contracts are expiring soon.  So, if a contract expires on 10/1/2016 and NotficationDays is set to 90, the initial email reminder will go out on 7/1/2016.  This date is calculated using Expiration Date minus NotficationDays = 10/1/2016 - 90 days.  A 2nd email reminder is sent on 8/1/2016 (30 days after the initial reminder).  This is calculated using the following formula = Expiration Date minus NotficationDays + 30 days (10/1/2016 - 90 days + 30 days).  I have all of this working.

 

Where I need assistance is on how to generalize the formula. Depending on how much work is involved in renewing the contract NotficationDays for a particular contract could be set to 360, 180, 120, 90, 60, or 30 days.  I want an initial email to be sent on NotficationDays prior to the contract expiring and then every 30 days following that date, until the contract has expired or the expiration date has been update and this condition for sending email reminders is no longer valid.

Any assistance is greatly appreciated.  Please let me know if something is not clear.

Thank you.

 

0 0

Replies

replied on June 15, 2016

We use the Date Token Calculator to check the Expiry Date before notifications.

 

Then we use some conditional decisions for it to decide what to do with any of those it finds that meet the criteria.

1 0
replied on June 16, 2016

Connie,

Thanks for sharing.  I like the way you handle non renewed contracts.  I hadn't focused on that area yet.    I have used the Date/Time tokens in the past.  The question I have is, do I have to set up an additional date/time token if I want to send email notifications at 60 days and then again at 30 days?  If the initial email notification goes at 90 days, then I want subsequent email notifications at 60 and 30.

Barb

0 0
replied on June 16, 2016

It's probably best to keep them separate. You could set up the processing part as its own workflow and invoke it within the For Each Entry loop to both speed up your workflow and make it easier to edit that part and reuse it in multiple workflows.

0 0
replied on June 16, 2016

Miruna - I've just posted a new work flow (see below).  I would value your thoughts on how I approached the matter.  

0 0
replied on June 15, 2016 Show version history

Greetings Barb,

 

Are you storing the notification days as a number in multi-value field? 

 

You could add in a For Each Value loop which takes the value in the Notification Day, runs it through a Date Token Calculator based on the Expiration Date, and then perform a conditional activity.

 

It would look like this:

 

Let me know if you would like further detail.

 

Cheers,

Carl

0 0
replied on June 16, 2016

Hi Carl,

I'm storing the notification days as a number.  Why would it need to be a multi-value field?  

 

Your workflow has given me some ideas.  Let me go back to the drawing board on my workflow.  I'll be in touch.  

 

Thank you for your suggestions.

0 0
replied on June 16, 2016

Carl, this workflow will end up processing the same documents over and over even when no notifications need to be sent out. Depending on the size of the document set and how many expire each day, this can get really slow and inefficient. Searching for the documents that need to send emails each day like Connie suggested is more efficient.

1 0
replied on June 16, 2016

I have reworked my workflow.

My subsequent email reminders at 30, 60, etc days after the initial reminder will be directed through here:

 

0 0
replied on June 17, 2016

Does the email message change depending on whether it's the first notification or not?

What are the search criteria?

0 0
replied on June 17, 2016

The email message is the same.

The Initial notification day search criteria is:

 

The Yes, subsequent reminder day criteria is:

 

Are you going to suggest that I combine the two criterias and lead to a single email?

0 0
replied on June 17, 2016

Then I think we can do it in one workflow without needing conditions.

I'll use the example with 30-, 60-, 90-day so it's easier to read but the workflow would be the same for everything up to 360.

For example, today, 6/17/2016, we'd need to get contracts with NotificationDays set to 90 and Expiration Date of 9/15/2016 (today+ 90 days).

For expiration dates 60 days out from today, we'd have 2 cases:

  • NotificationDays = 90 and Expiration Date = 8/16/2016 (second pass for contracts we started sending notifications last month)
  • NotificationDays = 60 and Expiration Date = 8/16/2016 (first pass for contracts expiring 60 days from today

For expiration dates 30 days out from today, we'd have 3 cases:

  • NotificationDays = 90 and Expiration Date = 7/17/2016 (third pass at contracts we started notifying 2 months ago)
  • NotificationDays = 60 and Expiration Date = 7/17/2016 (second pass for contracts we started sending notifications last month)
  • NotificationDays = 30 and Expiration Date = 7/17/2016 (first pass for contracts expiring 60 days from today

So today, we'd need to run 3 searches:

  • NotificationDays = 90 AND Expiration Date = 9/15/2016
  • (NotificationDays = 90 OR NotificationDate = 60) AND Expiration Date = 8/16/2016
  • (NotificationDays = 90 OR NotificationDate = 60 OR NotificationDate = 30) AND Expiration Date = 7/17/2016

So I'm going iterate over all possible values for how far ahead you want to send notifications: 30, 60, 90. Then for each one of them I'm going to calculate the date I need to run the search.

Where it gets slightly complicated, it's the search for the NotificationDays field. For 90, it would be easy, it's {[]:[NotificationDays] = "90"} . For 60, I'd have two criteria: {[]:[NotificationDays] = "90"} | {[]:[NotificationDays] = "60"}. And for 30, we'd have 3. So I'm going to iterate through the values in reverse order so I can append to the search criteria as we go.

To do that I'm going to use a multi-value token and append the entire search criterion at each pass using {[]:[NotificationDays]="%(ForEachValue_Current Value)"}

That will give me just one value for 90, 2 for 60 and 3 for 30. Then we can flatten them out into an "or" search by indexing the token in Search Repository with "|", which happens to be the "or" operator in the Laserfiche advanced search syntax.

 

You can set Search Repository to retrieve any fields you might need in the email along with the documents.

Let me know if anything else needs more explanation.

0 0
replied on June 20, 2016

The section labeled "Assign Token Values 2" is confusing.

 

If I use "90" as the value for the 1st iteration of the For Loop.  The date token calculator assigns 90 days to today (6/20/2016).  So current expiration date equals 9/20/2016.  

In my example of using "90" as NotificationDays search,  what happens in the "Assign Token Values 2" area?

 

Thank you for the assistance.

 

0 0
replied on June 20, 2016

That one is building the search. So for the first iteration, with "90", it will end up as {[]:[NotificationDays]="90"}, which we need in the search.

0 0
replied on June 20, 2016

What is being appended?   Doesn't NotificationDaysSearch already the values of 90, 60, 30 assigned from the Assign Token Values at the beginning of the work flow?  I feel like I'm missing something here.

0 0
replied on June 20, 2016

No, the token starts out blank. You can't start out with the token fully populated with all 3 values because your search results would be wrong.  A search for NotificationDays in (90,60,30) and Expiration Date 9/15/2016 might bring up a document with NotificationDays = 60. In that case, you'd be emailing a month too early.

So the search has to be built as we go. For 90, we need just NotificationDays = 90, fo 60, we need both 90 and 60, for 30, we need 90, 60, and 30. That's why I'm going through the values in reverse order: each iteration adds another search criterion.

(Side note: 90 days from 6/20/2016 is 9/18/2016. If the day is supposed to stay the same, we'd need to add 3 months instead of 90 days.)

0 0
replied on June 22, 2016

As you can tell, I'm pretty new to the laserfiche workflow process.  I appreciate the assistance.  Do I have the following correct?
 


 

0 0
replied on June 22, 2016

No worries. You want to append the whole search criterion for the field search for the NotificationDays field:

 

0 0
replied on June 22, 2016

Here is my search:

Could you explain how this logic works?  I had to insert spaces into #[ | ]# or Laserfiche returned an error.   

Thank you.

0 0
replied on June 22, 2016

What is the best way to limit which folders are searched? I don't need the whole laserfiche database searched.  I have typically started my workflows with a "Find Entries" pointed to the folder I wish to search.

0 0
replied on June 22, 2016

Sure.

So on the first iteration ("90"), NotificationDaysSearch token has one value:  {[]:[NotificationDays]="90"}. Current expiration date is today + 90 days, so 9/20/2016. At this point we're searching for {[]:[NotificationDays]="90"} & {[]:[Date] = "9/20/2016"}. Which gives us the documents that will expire in 90 days and need the first email sent.

On the second iteration ("60"), NotificationDaysSearch token still has the first value {[]:[NotificationDays]="90"} and gets a second value appended to it: {[]:[NotificationDays]="60"}. Current expiration date is today + 60 days, so 8/21/2016. Formatting the NotificationDaysSearch token with " | " gives us {[]:[NotificationDays]="90"} | {[]:[NotificationDays]="60"}, so our search becomes ({[]:[NotificationDays]="90"} | {[]:[NotificationDays]="60"}) & {[]:[Date] = "8/21/2016"}. This gives us documents that expire in 60 days and are either on their first email (for 60) or on their second notification (for 90).

Same way, for 30, we get a third criterion for the search, so we end up with documents that expire in 30 days and are on their first notification (NotificationDays = 30), on their second (60) or their third (90).

You can add a {LF:Lookin="path"} to narrow down to a specific part of the repository.

 

0 0
replied on June 22, 2016

Ok.  The search keeps returning 0, when I use this structure:

{%(NotificationDaysSearch#[ | ]#)} & {[]:[Date]="%(DateTokenCalculator_CurrentExpirationDate)"}

 

So, I attempted to recreate the search directly in Laserfiche to see if I was missing something.  If I use the following search, I get the appropriate records returned, however I can't find a way to say Notification Days = 90 OR 60.   If I insert | then it tells back and tells me undefined character.

{[Contracts]:[Department]="Town Clerk", [Notification Days]="90"} & {[Contracts]:[ExpirationDate]>="08/13/2016", <="10/01/2016"} & {LF:LOOKIN="TownOfBrighton\Town Clerk\Contracts"}

 

I figured if I could get the search to work with hard coded values, then I could go back to re inserting the variables.

 

0 0
replied on June 22, 2016

"|" is used to represent "OR" in between search criteria, not in between values. So it would have to be ({[]:[NotificationDays]="90"} | {[]:[NotificationDays]="60"}). Or, since you seem to be using the "Contracts" template, ({[Contracts]:[NotificationDays]="90"} | {[Contracts]:[NotificationDays]="60"}). The parentheses are there so the other criteria are considered together with the results of this OR search.

0 0
replied on June 23, 2016 Show version history

This is working:

({[Contracts]:[Department]="Town Clerk", [Notification Days]="90"} | {[Contracts]:[Department]="Town Clerk", [Notification Days]="60"} )
& {LF:LOOKIN="TownOfBrighton\Town Clerk\Contracts"}

How do I replace the 90 and 60 with NotificationDaysSearch ?

 

When I change the search to the following, it returns 0 results.  I have a contract that expires 60 days from today (6/23/2016) on 8/22/2016 and one that expires 9/20/2016 (90 days from today).

({[Contracts]:[Department]="Town Clerk", [Notification Days]="90"} | {[Contracts]:[Department]="Town Clerk", [Notification Days]="60"} ) & {[]:[Date]="%(DateTokenCalculator_CurrentExpirationDate)"}
& {LF:LOOKIN="TownOfBrighton\Town Clerk\Contracts"}

 

0 0
replied on June 23, 2016 Show version history

In an effort to troubleshoot the process, I disabled the lower portion of the work flow and sent myself an email just after the Assign Token Values 2 step.   In that email I sent myself the following values:

 

GLobal Date: 6/23/2016

NotificationDaysSearch = {[]:[Notification Days]="90"}

For each current value = 90

CurrentExpirationDate 9/21/2016

 

As you can see the NotificationDaysSearch value is not as I would expect.  Is this correct or do I need to modify something?

Thank you.

 

Update:  I found I needed to change the syntax in my email to get all the values to display.  Are these values correct?  Each value starts and ends with { }.

NotificationDaysSearch = {[]:[NotificationDays]="90"}
{[]:[NotificationDays]="60"}
{[]:[NotificationDays]="30"}

 

Further Update: I modified NotificationDaysSearch to Append Values; Token Value of  %(ForEachValue_Current Value)

I now have the values of 90, 60, 30 being stored correctly.

0 0
replied on June 23, 2016 Show version history

Ok, I'm feeling like I am close to figuring this out.  I think my biggest hurdle lies in the way NotificationDaysSearch is storing the values.   

I can run a "test search query"  with the following search and have it return the correct results to me 

{[Contracts]:[Department]="Town Clerk"} & {LF:LOOKIN="TownOfBrighton\Town Clerk\Contracts\_Dummy Contracts for testing"}


When I try and run this search query it pulls back no results.  

(%(NotificationDaysSearch#[|]#) ) &
{[Contracts]:[Department]="Town Clerk"} & {LF:LOOKIN="TownOfBrighton\Town Clerk\Contracts\_Dummy Contracts for testing"}

0 0
replied on June 23, 2016

Do the contracts in the "_Dummy Contracts for testing" folder match any of the NotificationDays values? Or are the contracts in subfolders of that folder?

0 0
replied on June 24, 2016

Yes, there are contracts that match the NotificationDays values in the " _Dummy Contracts for testing folder".   There are no subfolders in that folder.

0 0
replied on June 24, 2016

Immediately before entering the "Search Repository" step, I sent myself an email that prints out   NotificationDaysSearch =  %(NotificationDaysSearch#[]#)

I can see that 90, 60, 30 is stored within NotificationDaysSearch.

 

Immediately after the "Search Repository" step, I sent myself another email that shows:

%(NotificationDaysSearch#[]#)

Current value  %(ForEachValue_Current Value)

Current expiration Date:  %(DateTokenCalculator_CurrentExpirationDate)

%(SearchRepository_FirstResult_Name)  %(SearchRepository_FirstResult_Path)

Result count - %(SearchRepository_Result Count)

 

Which translates to the following:

 

90

Current value 90

Current expiration Date: 9/22/2016
 

 

Result count - 0

*************************************************
 

90
60

Current value 60

Current expiration Date: 8/23/2016

 

Result count - 0

***********************************************

90
60
30

Current value 30

Current expiration Date: 7/24/2016



Result count - 0

*************************************************************

In none of the 3 emails do I see %(SearchRepository_FirstResult_Name)  %(SearchRepository_FirstResult_Path) printed out.

 

I have verified that I have 2 contracts in the appropriate folder that match the current values of 90 & 60 with the approrpiate expiriation dates.

 

0 0
replied on June 24, 2016

Closer yet:

{[Contracts]:[Department]="Town Clerk", [Notification Days]="%(ForEachValue_Current Value)"} &{LF:LOOKIN="TownOfBrighton\Town Clerk\Contracts\_Dummy Contracts for testing"}

Now, I just need to add the expiration date piece in.  The key piece I learned here is that there is a comma between "Town Clerk" and [Notification Days] and not a &.   If someone can explain the difference to me, I would appreciate it greatly.

0 0
replied on June 24, 2016

AND ("&") and OR ("|") operators are used between search blocks (aka, the stuff in curly brackets). Within a search block, like your field search for example, the field names you're searching for are delimited with commas: {[Contracts]:[Department]="Town Clerk", [Notification Days]="%(ForEachValue_Current Value)"}

0 0
replied on June 17, 2016

Okay, so, our reminders are handled on a separate WF.  The first workflow sends the initial notification and also moves the contract into a holding folder.  The second workflow monitors the contracts in the holding folder(s) and sends reminders once a month on a never ending loop, until someone changes the contract status to something that will make it stop (like "renewed" or "renewal denied").

0 0
replied on July 20, 2016

Hi Everyone,

I wanted to post back and let everyone know how my workflow turned out.  The attached file shows the flow for expiration dates 30 and 60 days out.   The full work flow also covers 90, 120, 180 and 360 days.  I hope others find this useful.  Thanks for all the input.

workflow.jpg
workflow.jpg (58.07 KB)
0 0
replied on November 29, 2018

Good Morning,  I know it has been a long time since you posted this solution; however, this is almost identical to what I am attempting to accomplish.  I am confused about how to configure the Date Token Calculator for 30, 60, and 90 days.  Can post an image of how you accomplished this?

 

Thank you.

0 0
replied on December 4, 2018

0 0
replied on December 11, 2018

0 0
You are not allowed to follow up in this post.

Sign in to reply to this post.