Trigger Design Patterns Without Framework :
=================================
Frameworks improve reliability and maintainability,and make probelms easier to debug.
ex :
1.Follow up on lead account(Process Builder)
a. Insert lead with 'Open not Contacted' with good email
b. Create a follow up task.
2.taskTriggerSetStatus
a.Task created for lead
b.if the lead has a task, set its status to 'Working-Contacted'
or 'Working - harder '.
3.leadTriggerSetFollowup
a.if a lead has a working status
b.Create a follow-up task (reminder).
4.taskTriggerTrackCount
a.Task is created,updated or deleted
b.Update # of tasks on the lead
5.First Owner Worked (Process Builder)
a.Lead status starts with Working and Owner is a user.
b.Set first owner worked field.
Note :
=========
1.controling the trigger order
2.Combining DML operations
3.controlling reentrancy
Dynamic Trigger Handler :
===========================
public interface ITriggerExtension
{
void HandlerTrigger(TriggerOperation operationType,
List<SObject> newList,List<SObject> oldList,
Map<ID,SObject> newMap,Map<ID,SObject> oldMap);
}
public with sharing class dynamicTaskTriggerHandler implements ITriggerExtension{
public void HandleTrigger(TriggerOperation operationType,List<SObject> newList,List<SObject> oldList,
Map<ID,SObject> newMap,Map<ID,SObject> oldMap)
{
system.debug('Trigger execution was called');
}
}
trigger taskTrigger on Task (before insert,after insert,before update,after update,before delete,after delete){
simpleLeadUpdater leadUpdater = new simpleLeadUpdater();
// What happens when you change the order of these two triggers handlers?
if(trigger.operationType == TriggerOperation.AFTER_INSERT)
{
taskSetStatus.handleTrigger(trigger.new,leadUpdater);
}
if(trigger.operationType == TriggerOperation.AFTER_INSERT ||
trigger.operationType == TriggerOperation.AFTER_UPDATE ||
trigger.operationType == TriggerOperation.AFTER_DELETE )
{
taskTrackCount.handleTrigger (trigger.operationType,trigger.new,trigger.old,leadUpdater);
}
List<ITriggerExtension> dynamicTriggers = TriggerExtensionSupport.getTriggerClasses('Task');
for(ITriggerExtension trig : dynamic Triggers)
{
trig.HandleTrigger(trigger.operationType,trigger.new,trigger.old,trigger.newMap,trigger.oldMap);
}
leadUpdater.updateLeads();
}
public with sharing class TriggerExtensionSupport{
public static List<ITriggerExtension> getTriggerClasses(String objectType)
{
List<Dynamic_Trigger_mdt> triggerSettings = [ Select Class_Name__c from Dynamic_Trigger__mdt where
Object_Type__c = : objectType OrderBy Priority__c ASC];
List<ITriggerExtension> results = new List<ITriggerExtension>();
for(Dynamic_Trigger__mdt setting : triggerSettings)
{
System.Type thetype = Type.forName(setting.Class_Name__c);
if(thetype == null)
thetype = Type.forName('',setting.Class_Name__c); // Try resolving local class
if(thetype!=null){
Object theobject = thetype.newInstance();
if(theobject instanceof ITriggerExtension) results.add ((ITriggerExtension) theobject);
}
}
return results ;
}
}
public with sharing class taskTrackCount {
public static void handleTrigger (TriggerOperation operationType, List<Task> newList,List<Task> oldList,simpleLeadUpdater leadUpdater)
{
Set<ID> leadIds = new Set<ID>();
if(operationType == TriggerOperation.AFTER_UPDATE || operationType == TriggerOperation.AFTER_INSERT)
{
for(Task t : newList)
{
if(t.WhoId!=null && t.WhoId.getSObjectType()==Schema.Lead.SObjectType)
leadIds.add(t.WhoId);
}
}
if(operationType == TriggerOperation.AFTER_UPDATE || operationType == TriggerOperation.AFTER_DELETE)
{
for(Task t : oldList)
if(t.whoId !=null && t.whoID.getSObjectType() == Schema.Lead.SObjectType)
leadIds.add(t.whoId);
}
List<Lead> leads = [Select ID,Task_Count__c from Lead where ID in : leadIds];
List<AggregateResult> tasks = [Select Count(ID) items,WhoId from Task where WhoId in : leadIds group by WhoID];
Map<ID,Interger> taskCounts = new Map<ID,Interger>();
for(AggregateResult ar : tasks)
{
taskCounts.put((ID)ar.get('WhoId'),(Interger) ar.get('items));
}
for(Lead ld : leads)
{
if(ld.Task_Count__c != taskCounts.get(ld.Id))
{
Lead toUpdate = leadUpdater.getLead(ld.id);
toUpdate.Task_Count__c = taskCounts.get(ld.id);
}
}
}
}
public with sharing class taskSetStatus {
private static Set<ID> statusUpdated = new Set<ID>();
public static void handleTrigger (List<Task> newTasks,simpleLeadUpdater leadUpdater){
Set<ID> leadIds = new Set<ID>();
for(Task t : newTasks)
{
if(t.whoId!=null && t.whoId.getSObjectType() == Schema.Lead.SObjectType && !t.Declarative_Created__c)
leadIds.add(t.whoId);
}
List<Lead> leads = [Slect ID,Status from Lead where ID in : leadids];
for(Lead ld : leads)
{
if(statusUpdated.contains(ld.id)) continue; // Skip those already updated
switch on ld.status
{
when 'Open - Not Contacted'
{
Lead toUpdate = leadUpdater.getLead(ld.id);
toUpdate.status = 'Working - Contacted ';
statusUpdated.add(ld.id);
}
when 'Working - Contacted'
{
Lead toUpdate = leadUpdater.getLead(ld.id);
toUpdate.status = 'Working Harder ';
statusUpdated.add(ld.id);
}
}
}
}
}
public with sharing class simpleLeadUpdater {
Map<ID,Lead> leadsToUpdate = new Map<ID, Lead>();
public Lead getLead(ID leadID)
{
Lead targetLead = leadsToUpdate.get(leadID);
if(targetLead == null)
{
targetLead = new Lead (ID = leadID);
leadsToUpdate.put(leadID,targetLead);
}
return tragetLead;
}
public void updateLeads()
{
if(leadsToUpdate.size()>0)
update leadsToUpdate.values();
}
}
Test Class :
===============
@istest
public with sharing class TestLeadActions{
@istest
public static void TestInsertSingleLead(){
Test.startTest();
InsertLeads(1,'Open-Not Contacted');
Test.stopTest();
}
@isTest
public static void TestInsertBulkLead()
{
Long startTime = DateTime.now().getTime();
Long startCPU = Limits.getCpuTime();
Test.startTest();
InsertLeads(200,'Open - Not Contacted');
Test.stopTest();
system.debug ('Elapsed : ' + (Datetime.Now().getTime() - startTime));
system.debug ('Elapsed CPU : ' + (Limits.getCpuTime() - startCPU));
}
public static void InsertLeads(Interger count,String leadstatus)
{
List<Lead> leadsToInsert = new List<Lead>();
for(Interger x=0;x<count;x++)
{
String xs = string.valueOf(x);
leadsToInsert.add(new Lead(FirstName = 'f' +xs,LastName = 'l'+xs,
status=leadstatus,
Company = 'c' + xs,
email = 'e' + 'xs' + '@pluralsight.com',
Bypass_Declarative__c = 0 ));
}
insert leadsToInsert;
}
Public static void UpdateLeadStatus()
{
List<Lead> leads = [ select Id, status from Lead ];
for(Lead ld : leads)
ld.status = 'Working - Contacted ';
Test.startTest();
update leads ;
Test.stopTest();
}
}
No comments:
Post a Comment