Repeating Salesforce Workflow actions every x days - salesforce

I am a salesforce administrator and I am told to create a new task every 90 days based on a date.
I have created a workflow rule which creates a new task 90 days after the data filed (Initial bill date 2 in my case).
The data field I am based on is a formula field. I tried to update the filed with a field Update action by adding 90 (Initial Bill Date 2 + 90) but I read Workflow rules considerations:
Field updates occur before email alerts, tasks, and outbound messages.
-Read-only fields like formula or auto-number fields are not available for field update action.
Until now I have created a workflow rule that triggers a Time dependent new task 90 days after initial bill date 2. I am not finding a way how to repeat this action every 90 days.
Can someone help with an answer?
Thank you

Time Dependent actions in Workflow Rules and Process Builder do not repeat. They're enqueued exactly once by the platform for each qualifying invocation of the Workflow or Process. That is, the record is modified; it matches the entry criteria of the Workflow; and only then is a single time-dependent action enqueued.
You can sometimes contrive chains of declarative automations to update records in such a way as to cause reevaluation of Workflow criteria and get those actions re-scheduled. However, this is tricky, hard to reason about, and error-prone. Plus, the limit for processing time-dependent actions is only 1,000 per hour, which is really easy to blow past if you're using the feature heavily.
Instead, consider using an app like Doug Ayers' open source Mass Action Scheduler to process specific actions on a schedule.

Related

How to know a Salesforce table field is auto-calculated?

Salesforce provides CaseMilestone table. Each time I call the API to get a same object, I noticed that TimeRemainingInMins field has a different value. So I guessed this field is auto-calculated each time I call the API.
Is there a way to know what fields in a table are auto-calculated ?
Note : I am using python simple-salesforce library.
Case milestone is special because it's used as countdown to service level agreement (SLA) violation, drives some escalation rules. Depending on how admin configured the clock you may notice it stops for weekends, bank holidays or maybe count only Mon-Fri 9-17...
Out of the box other place that may have similar functionality is OpportunityHistory table. Don't remember exactly but it's used by SF for for duration reporting, how long oppty spent in each stage.
That's standard. For custom fields that change every time you read them despite nothing actually changing the record (lastmodifiedate staying same) - your admin could have created formula fields based on "NOW()" or "TODAY()", these would also recalculate every time you read them. You'd need some "describe" calls to get the field types and the formula itself.

Create a task when the Training is end

Im new to salesforce, I have an Object Training__c and field End_Date, and when the End_Date came I need to create a task, but I dont know how to track this End_Date, because it is not a trigger...
Thanks
Look into time-based workflows (bit old school, we're encouraged to use flows now so check scheduled flows out.
It could be a whole scheduled flow (kind of like a nightly batch job) or a scheduled path in your "normal" flow (if you already have one on this object). There are some trailhead modules to get you started:
https://trailhead.salesforce.com/content/learn/modules/record-triggered-flows/get-started-with-triggered-flows
https://trailhead.salesforce.com/content/learn/modules/record-triggered-flows/add-a-scheduled-task-to-your-flow
Roughly speaking you'd set the action to fire "0 days after end date" and it becomes Salesforce's problem to modify the job if the end date changes. It's elegant, code free, fairly easy.
There are some problems with it such as scale, will there be tens of thousands of records? Another thing is this will work only for records created / modified since you activated this flow. What about all old data? What if I need to modify the flow's definition, will it de-queue all actions? (that one was a legit concern with time-based workflows. to edit the workflow you had to deactivate it - but doing so nuked all submitted actions).
So... you may decide to write some code for this after all. Have an apex batch job running nightly, selecting records with End Date <= TODAY that don't have (open)? tasks yet - and adding these. (maybe if a task is completed you'd want to give another one). Different solution, requiring you to write an unit test for it too (which isn't neccessarily a bad thing), bit more resilient than flows.
This looks like fairly similar problem solved with a batch: https://salesforce.stackexchange.com/q/118214/799

Saleforce Admin Sharing Rule

[Note: There is a Teacher Object with the fields such as Teacher Name, DateofJoining, and also a formula field called Experience]
My Task was to create a Public Group consisting of another user
and this user should only see teachers who have experience greater than 2 years
But when i create a sharing rule based on criteria the field name called Experience doesn't show up as it is a formula field.
So i got an idea of creating a new field(maybe a text or number data type) which would have the value of Experience in it. (But i have no idea on how to implement this)
Is there a way to implement this?
Any other solution is also well appreciated!
Hard to say.
Normal trick would be to create a helper field (text, number, whatever) and have piece of functionality that populates it. An "early flow" or "before insert, before update" trigger ideally. Worst case a normal flow, process builder or "after insert, after update" trigger. Something like "if Experience__c != 'your formula here' then Experience__c = 'your formula here'". Consult normal SF help and trailhead if you never used early flows
You'd make an one-off data fix to populate existing records and job done, normal field should be selectable as sharing rule criteria.
=====
But I smell trouble with your formula. What exactly you have there, something like Experience__c = (TODAY() - DateofJoining__c) / 365? That's bit evil. Formulas with TODAY(), NOW() or anything with $ (roughly speaking who's looking at the data, user's name, profile role... not what's actually on the record itself) are "nondeterministic". Unpredictable.
A "today()" changes just like that, without updating the record. Sure, when you watch the record a fresh value will be calculated but other than that LastModifiedDate doesn't change, there's no magical trigger running at midnight that rechecks sharing. (especially that there's no single midnight, you could have users in multiple timezones). SF just doesn't allow nondeterministic fields in many places, see https://salesforce.stackexchange.com/q/32122/799
So if you do rely on TODAY() in your formula you might have to make a "scheduled flow" or read about schedulable, batchable apex. Create nightly job that would run and recalculate your helper field with right experience. You'd probably even need both solutions, a "before save" flow for new data created today and nightly job to advance the clock on existing old data...

Ways to design a digest email implementation?

I'm looking for some thoughts about how to design a digest email feature. I'm not concerned about the actual business code; instead I'd like to focus on the gist of it.
Let's tackle this with a known example: articles. Here's a general overview of some important features:
The user is able to choose the digest frequency (e.g. daily or weekly);
The digest only contains new articles;
"New articles" are to be considered relative to the previous digest that was sent to a specific user;
I've been thinking about the following:
Introduce per-user tracking of articles previously included in a digest and filter those out?
Requires a new database table;
Could become expensive when the table contains millions of rows;
What to do in case of including multiple types of models in the digest? Multiple tracking tables? Polymorphic table? ...?
Use article creation dates to include articles between current date and the chosen digest frequency?
Uses current date and information already present in the database, so no new tables required;
What happens when a user changes from daily to weekly emails? He could receive the same article again in the weekly digest. Should this edge case be considered? If so, how to mitigate?
For some reason the creation date of an article is being updated to today, positively triggering the date comparison again. Should this edge case be considered? If so, how to mitigate?
Or can you think of other ways to implement this feature?
I'm eager to learn your insights.
You can make an additional table that will contain information about digest subscription by each user. This way gives the ability to make a database design cleaner and more universal because mailing is a separate logical module. Aside from that, the additional table gives the ability to expand stored data about digest subscription easy in future. For example:
With help usage of this table, you would manage data easy. For example, you can select all recipient of daily digest:
SELECT *
FROM digest_subscription
WHERE interval_type = 'daily'
AND last_date_distribution <= NOW()
or select all recipient of the weekly digest
SELECT *
FROM digest_subscription
WHERE interval_type = 'weekly'
AND last_date_distribution <= NOW() - INTERVAL 7 DAY
Condition by interval type and compare the last date distribution by rule "equal or less" give the ability to avoid problems of untimely sending of emails (for example technical failures on a server, etc.)
Also, you can make correct articles list with help information of the last data distribution. Usage of the last data distribution gives the ability to avoid problems of interval change. For example:
SELECT *
FROM articles
WHERE created_at >= <the last date distribution of the user>
Of course, you don't avoid the problems of updated creation date. But you should minimize the reasons for that happening. For example, your code can update the modification date but your code shouldn't modify the creation date.

Laying out a database schema for a calendar application

I want to write a calendar application. It is really recurring items that throw a wrench in the works for the DB schema. I would love some input on how to organize this.
What if a user creates an event, and inputs that it repeats everyone Monday, forever? How could I store all that in the database? I can't create infinite events. Do I simply put a table in there that holds the relevant info so I can calculate where all the events go? If so, I would have to calculate them every time the user views a new part of the calendar. What if they page through the months, but they have a ton of recurring items?
Also, the schema needs to handle when a user clicks an item and says "Edit this one in the sequence" not all items in the sequence. Do I then split the one item off of the sequence?
Update 1
I have not looked at iCal at all. To be clear, I think saving the info that allows you to calculate the recurring items, and splitting off any that differ from the sequence is a great way to store it to be able to transfer it. But I think that in an application, this would be too slow, to do the date math all over the place.
I have been struggling with the same problem, and I was actually toying with the "cache table" idea suggested above, but then I came across an alternative (suggested here) that doesn't seem to have been represented yet.
Build a table containing all events
EventID (primary key)
Description
StartDate
PeriodType - days, weeks, months, years
PeriodFreq - # of days, weeks, etc between events
EndDate
... other attributes that can be modified
Then add a table for exceptions to these events. This table uses a composite key, made up of the EventID that maps to the event table, and an instance ID to pick the particular event in the series.
EventID (key)
InstanceID (key)
InstanceDate - the modified date of the exception
IsCancelled - a flag to skip this date when traversing the series
... other attributes that can be modified
It seems to keep the event table normalised, and avoids splitting up series to handle exceptions.
I recently created a calendar application and this was one of the many challenges that I faced.
I eventually came up with a semi hack-ish solution. I created an event_type column. In that column, I had either: daily, weekly, monthly, or yearly. I also had a start_date and an end_date columns. Everything else was handled in the actual backend code.
I never tried to split an event if a user edited only one event. It wasn't necessary in the situation. However, you could split an event by changing the end_date of the first, creating a new event with a new start_date and the end_date of the original, and finally, a new event for the one you just chose to edit. This process would end up creating 3 events.
Hack-ish, I know. I couldn't think of a clever way to handle this problem at the time.
Hold the recurring item in the events table as normal, but flagged as recurring with the appropriate start/ end dates.
If the user modifies a single instance of the appointment, just create a new event, perhaps with a 'parentId' equal to the recurring event's id.
Build logic that causes the calendar to override any recurring events on a particular day with events with matching parent IDs.
Your question about performance is basically the old speed vs. storage issue. I really don't think the calculation required would exceed the space requirement for storing so many appointments. Just read up on database optimization- indexing etc.
Could you bridge the two worlds with a "cache" table, in which you pre-compute the next X days worth of events?
So three tables:
recurring_event_specs
one_time_events
cached_recurring_events
For any part of the calendar within X days of today, your query will UNION one_time_events and cached_recurring_events.
Then you would only have to do on-the-fly date calculations if the user tried to look at a part of the calendar more than X days in the future. I imagine you could find a sane X that would cover the majority of normal use.
The cached_recurring_events table would need to be updated whenever a user adds a new recurring event -- and possibly once a day offline, by a cron-job/scheduled-task. But only on days when no new recurring event has been created.
Why not use Google Calendar as a database for this calendar application by relying on Google Calendar's API for storing and retrieving calendar events?
The Calendar API is a REST API that can be accessed through explicit HTTP calls; the API exposes most of the features available in the Google Calendar Web interface, so your calendar application can as much functionality as Google Calendar does (a lot of functionality!!!).
Your application need only implement OAuth 2.0 for Google APIs, which can be made easy using a single sign-on service like Auth0 to provide the appropriate access tokens. Then, your calendar application can use these tokens in conjunction with the Calendar API to provide seamless storage and retrieval of calendar events in a JSON format.
Users create events within their own "New Calendar." This calendar is shared with you in the form of a gmail account dedicated to this application - the application's gmail account.
Basically, Google Calendar becomes your database, whereby you can have the application's gmail account not only store all of your application's events, but also allow you to view and edit these events with an intuitive interface.
The best way to do this is to store a standards based recurrence pattern string (iCal).. and leave blank if it's a single event. There are a few APIs that can parse the recurrence pattern and create event objects that you can bind to UI elements.... none of the occurrences need ever be stored in the database, only the initial event (occurrence)..
Couldn't you store the events per day with start and end time? It will generate a lot of data for events that happen everyday (maybe go non-relational for this) but it will make querying easier and it will be possible to make exceptions (f.e. the event place burned down, or employees are striking). To generate the days for the event I would suggest to implement that in the front-end derived on some ICal-ish pattern.

Resources