Notifications_Setting__mdt
What are 'Notifications Setting'
While building the Restocker App we wanted to avoid the confusing mess of conditional paths and multiple trigger methods that has made maintaining other parts of our Salesforce platform difficult.
To address this we have created a metadata based Notification System controlled by the 'Notifications_Setting__mdt' (note: Do not get confused with the similarly named Notification_Setting__mdt, this is a legacy solution that will be removed in time)
The new system allows us to create both 'Scheduled' and 'Instant' Notifications for any object and can deliver Notifications via DocGen or Email with room to expand to other Notification types in the future.
The Notifications System works with three main components:
- the Notifications_Setting__mdt Metadata record
- a Batch Apex class that runs every morning
- the inclusion of the NotificationInstantBuilder.processInstantNotifications Apex Class and Method.
In addition to being able to create dynamic Notifications, the system is designed to work with the 'Region__c' field on our objects in order to enable or disable a Notification on a region by region basis.
Notification Types
There are two kinds of Notification available: Instant and Scheduled.
Each type of Notification has their own configuration and considerations.
There are some configuration fields that are shared between types:
Delivery: The delivery method for the Notification - Email or Drawloop
Template: The Classic Email Template ID when using the 'Email' delivery method or the Drawloop Package ID when using the 'Drawloop' delivery method
DDP Delivery Option: The Drawloop Package Delivery Option ID when using the 'Drawloop' delivery method
Object: The API Name of the Object that this Notification is used with
Recipient Field: The field which looks up to or contains the Contact record Id that the Notification will be sent to
State: A comma separated list of the State shortcodes for which region's will receive the Notification (e.g. 'ACT,SA,NAT')
Instant
Instant notifications leverage the recently added FormulaBuilder Apex feature.
Effectively we give a Instant Notification a formula criteria for the 'Old' record and a formula criteria for the 'New' record.
This allows us to ensure that we don't send a Notification every time a record is updated as we can use the prior value to check that the required fields have changed.
Enabling Instant Notifications for an Object
In order to use Instant Notifications with an Object, we must add a call to the NotificationInstantBuilder.processInstantNotifications Method in the Apex Trigger for that object.
Edit or Create an Apex Trigger for your object and add the following:
// Call NotificationInstantBuilder to process instant notifications
if (Trigger.isAfter) {
List<SObject> newRecords = Trigger.new;
Map<Id, SObject> oldRecords = Trigger.isUpdate ? Trigger.oldMap : null;
NotificationInstantBuilder.processInstantNotifications(newRecords, oldRecords);
}
It's important to note that any Object which will use the Notifications Setting framework must have a 'Region__c' field that resolves to a state shortcode (e.g. 'ACT').
Creating an Instant Setting
To create an Instant Notification, make a new Metadata record and set the common fields:
Delivery, Template, DDP Delivery Option (if required), Object, Recipient Field, State.
To set the criteria for when to deliver the Notification we must use the 'Current Conditions' and 'Prior Conditions' fields.
The Current Conditions field uses a Salesforce Formula to evaluate the state of the updated record. If the Formula resolves to True, then the record meets the Current Condition.
Set the Current Conditions field with your desired Formula for the current state of the record.
We cannot use some Formula features such as 'IsChanged' as we do not have access to those properties during the Apex execution.
In order to avoid retriggering Notifications we use the 'Prior Conditions' field.
The Prior Conditions field uses a Salesforce Formula to evaluate the previous value of the record. If the record is a new record (no previous value) or the previous value resolves to True, then the record meets the Prior Condition.
Setting the Prior Conditions field can be tricky as you must ensure that you are capturing the 'Anti' of whatever condition is in the 'Current Conditions' field as well as any additional requirements.
For example if you want to send a Notification when a Service has its status updated to 'Completed' you must be sure to add 'NOT(ISPICKVAL(Status, 'Completed'))' to your formula in order to ensure that future updates don't accidentally resend the Notification.
Once you have set the common fields and created your formulas you can save your Metadata record, enabling the Notification.
The following is an example of an Instant Notification:
State: "ACT,NAT"
Object: "Service__c"
Recipient Field: "Primary_Contact__c"
Type: "Instant"
Current Conditions: "AND(ISPICKVAL(Status__c, 'Scheduled'),NOT(ISBLANK(Primary_Contact__c)))"
Prior Conditions: "OR(NOT(ISPICKVAL(Status__c, 'Scheduled')),AND(ISPICKVAL(Status__c, 'Scheduled'),ISBLANK(Primary_Contact__c)))"
Delivery: "Email"
Template: "00X9n0000025x4mEAA"
Batch Criteria: null
DDP Delivery Option Id: null
Scheduled
Scheduled Notifications are executed by the NotificationScheduler batch class and uses a SOQL formula to identify records that should receive the Notification
Creating a Scheduled Setting
To create a Scheduled Notification, make a new Metadata record and set the common fields:
Delivery, Template, DDP Delivery Option (if required), Object, Recipient Field, State.
Set the criteria for the Scheduled Notification using the Batch Criteria Field to enter an SOQL WHERE condition without a Region__c field.
The criteria should include an evaluation that resolves to a single date e.g. 'Service_Start__c = NEXT_N_DAYS:3 AND (NOT Service_Start__c = NEXT_N_DAYS:2)' as well as any other conditions for the Notification.
Once you have set the common fields and added the Batch Criteria you can save your Metadata record, enabling the Notification.
The following is an example of a Scheduled Notification:
State: "SA"
Object: "Service__c"
Recipient Field: "Primary_Contact__c"
Type: "Scheduled"
Current Conditions: null
Prior Conditions: null
Delivery: "Drawloop"
Template: "exampleDDPId"
Batch Criteria: "Service_Start__c = NEXT_N_DAYS:3 AND (NOT Service_Start__c = NEXT_N_DAYS:2) AND Status__c = 'Scheduled' AND Primary_Contact__c != null"
DDP Delivery Option Id: "exampleDelId"