I need to send an email to Contact(s) listed in my Opportunity Contact Roles, 24 hours after an Opportunity has been Closed/Lost, if the Opportunity hasn't been reopened in the meantime. So essentially I need to replicate a Time Dependent Workflow Action or Process Builder's Scheduled Action.
I'm guessing that I can use a Queueable
class for this but I can't find any documentation explaining how to schedule the job so that it's run after a certain time period?
public class WE_WinLossSurvey {
Map<Id,Opportunity> oldOpps;
Map<Id,Opportunity> newOpps;
Set<Id> oldOppsIds;
Set<Id> newOppsIds;
Opportunity oldOpp;
Set<Id> lostOppIds = new Set<Id>();
List<Opportunity> oppsWithNoDmContact = new List<Opportunity>();
Set<Id> oppIdsToProcess = new Set<Id>();
public WE_WinLossSurvey(
Map<Id, Opportunity> oldTriggerOpps,
Map<Id, Opportunity> newTriggerOpps) {
oldOpps = oldTriggerOpps;
newOpps = newTriggerOpps;
WE_ApexUtility apxUtil = new WE_ApexUtility();
apxUtil.checkApexControllerStatus();
if (!WE_ApexUtility.setting.contains(true)){
apxUtil.retrieveValidRecordTypes(
'EU Opps');
for(Opportunity o : newOpps.values()) {
oldOpp = oldOpps.get(o.Id);
if (WE_ApexUtility.validEuRecordTypeIds.contains(o.RecordTypeId) &&
oldOpp.Probability != o.Probability &&
o.Probability == 0)
{
lostOppIds.add(o.Id);
}
}
if (lostOppIds.size() > 0) {
for(Opportunity o : [SELECT Id, Owner.Email, Owner.SenderName,
(SELECT Contact.Email
FROM OpportunityContactRoles
WHERE Role = 'Decision Maker')
FROM Opportunity
WHERE Id IN :lostOppIds])
{
if (o.OpportunityContactRoles.size() == 0) {
oppsWithNoDmContact.add(newOpps.get(o.Id));
} else {
oppIdsToProcess.add(o.Id);
}
}
if (oppsWithNoDmContact.size() > 0) {
for(Opportunity o : oppsWithNoDmContact) {
o.addError(' Please select a Contact with the Role \'Decision Maker\'. This Contact will receive the Lost Deal Survey');
}
}
if (oppIdsToProcess.size() > 0) {
SendWinLossSurveyEmails surveySender = new SendWinLossSurveyEmails(lostOppIds);
Id jobId = System.enqueueJob(surveySender);
}
}
}
}
public class SendWinLossSurveyEmails implements Queueable {
Set<Id> lostOppIds = new Set<Id>();
public SendWinLossSurveyEmails(
Set<Id> classIds) {
lostOppIds = classIds;
}
public void execute(QueueableContext context) {
List<Messaging.SingleEmailMessage> emailsToSend = new List<Messaging.SingleEmailMessage>();
List<String> sendTos = new List<String>();
List<String> ccTos = new List<String>();
List<String> bccTos = new List<String>();
if (lostOppIds.size() > 0) {
for(Opportunity o : [SELECT Id, Owner.Email, Owner.SenderName, Probability,
(SELECT Contact.Email
FROM OpportunityContactRoles
WHERE Role = 'Decision Maker')
FROM Opportunity
WHERE Id IN :lostOppIds])
{
if (o.Probability == 0) {
WE_ApexUtility.PrepareEmails pe = new WE_ApexUtility.PrepareEmails();
Messaging.reserveSingleEmailCapacity(o.OpportunityContactRoles.size());
for(OpportunityContactRole ocr : o.OpportunityContactRoles) {
sendTos.add(ocr.Contact.Email);
// ccTo & bccTo deliberately left empty
emailsToSend.add(pe.createEmail(
sendTos, // sendTo
o.Owner.Email, // replyTo
o.Owner.SenderName,// displayName
ccTos, // ccTo
bccTos, // bccTo
'Survey', // subject
'Testing' // body
));
sendTos.Clear();
ccTos.Clear();
bccTos.Clear();
}
}
if (emailsToSend.size() > 0) {
for(Messaging.SingleEmailMessage e : emailsToSend) {
Messaging.SendEmail(new Messaging.SingleEmailMessage[] { e });
}
}
}
}
}
}
}