I have One schedulable class that calls a method that have multiple if conditions to be executed
FOR(Contact cont : contacts){
if(cont.Account.Due_date_of_last_open_invoice__c == system.today() + 14) {
template = DueInvoice;
}
if(cont.Account.Due_date_of_last_open_invoice__c == system.today()) {
template = DueInvoice;
}
if(cont.Account.Due_date_of_last_open_invoice__c == system.today() + 7){
template = DueInvoice;
}
if(cont.Account.Due_date_of_last_open_invoice__c == system.today() - 7){
template = BlockingOutstanding;
}
if(cont.Account.Due_date_of_last_open_invoice__c == system.today() - 14) {
template = BlockingAccount;
}
if(cont.Account.Due_date_of_last_open_invoice__c == system.today() - 28) {
template = DeactivatingAccount;
}
and sometimes the method hits the governor limits. I'm sure the root cause is when its rendering the VF page for which another action from the extension (init) is also called.
What is the best practice to prevent my code from hitting SOQL limit, is it better for me to have different methods that cover all conditions or make a queueable kind of thing that is scheduled in apex job that has a purpose to stop the code from running if governor limit is reached and will be continued in the next schedule?
public List<OrgWideEmailAddress> orgWideMail = [SELECT Id FROM OrgWideEmailAddress];
public EmailTemplate ExpiringContract = [SELECT Id, Name, Description, Subject FROM EmailTemplate WHERE Name =: 'New Renewal Notice' LIMIT 1];
public EmailTemplate DueInvoice = [SELECT Id, Name, Description, Subject FROM EmailTemplate WHERE Name =: 'Invoice Due in 2 Weeks' LIMIT 1];
public EmailTemplate BlockingOutstanding = [SELECT Id, Name, Description, Subject FROM EmailTemplate WHERE Name =: 'Blocking Outstanding' LIMIT 1];
public EmailTemplate BlockingAccount = [SELECT Id, Name, Description, Subject FROM EmailTemplate WHERE Name =: 'Blocking Account' LIMIT 1];
public EmailTemplate DeactivatingAccount = [SELECT Id, Name, Description, Subject FROM EmailTemplate WHERE Name =: 'Deactivated Contract' LIMIT 1];
public EmailTemplate PerformanceReport = [SELECT Id, Name, Description, Subject FROM EmailTemplate WHERE Name =: 'New Performance Report PH' LIMIT 1];
public Id emailtemplate;
public String templateDescription; // The template description will be assigned to the Task Subject of the task
public String templateSubject;
public Id invPDFattachmemt{get;set;}
public Attachment attach{get;set;}
public EmailTemplate template;
public List<Invoice__c> linv;
public String day = String.valueOf(date.today().day());
public Decimal dday = [SELECT Id, GLRemainingQuota__c from Account WHERE Name =: 'Trash Account DO NOT DELETE'].GLRemainingQuota__c; // used to simply being able to change the supposed sendout date of performance mail without changing and re-deploying the class
public void autoEmailSendout(){
/**** Put here the sendouts that are active ****/
this.sendInvoiceReminder();
}
public void sendInvoiceReminder(){
String ReplyToEmail;
/**** Set Sender Name (as appears in client's mailbox) ****/
String senderName = 'some name';
String defaultReplyEmail = 'some email'; // used only if both Account Owner and Aftersales Managers are inactive in SF
/**** Set Template ****/
List<Messaging.SingleEmailMessage> mails = new List<Messaging.SingleEmailMessage>();
Set<Id> ids = new Set<Id>();
/**** Set filters and conditions (recipients and criteria -> To:, When?, who?, why?) ****/
List<Contact> licontact = [SELECT Id FROM Contact
WHERE ContactForContracts__c = TRUE // only contacts that are marked to receive contract info
AND Email <> ''
AND Account.ExcludeFromAutomatedSendouts__c = FALSE // Checkbox on account to exclude Account from sendouts
AND Account.Outstanding_Amount__c >:0
AND
(Account.Due_date_of_last_open_invoice__c =: system.today() + 14
OR Account.Due_date_of_last_open_invoice__c =: system.today() + 7
OR Account.Due_date_of_last_open_invoice__c =: system.today() - 7
OR Account.Due_date_of_last_open_invoice__c =: system.today()
OR Account.Due_date_of_last_open_invoice__c =: system.today() - 14
OR Account.Due_date_of_last_open_invoice__c =: system.today() - 28)
AND Account.AccountCountry__c = 'PH' AND Account.TypeOfCompany__c = 'Agent / Broker'
AND (Account.LastInvoiceNoticeDate__c <: system.today() OR Account.LastInvoiceNoticeDate__c =: null)]; // avoids multiple sendouts in case the method is called several times on the same day
system.debug('aaa' + licontact.size());
/**** Start process ****/
IF(licontact.size() >0){
/**** Set parameters ****/
List<Contact> contacts = [SELECT Id, AccountId, Account.AccountManager__r.Email, Account.AccountManager__r.isActive, Account.Owner.Email, Account.Owner.isActive, Account.Due_date_of_last_open_invoice__c
FROM Contact WHERE Id in: licontact];
FOR(Contact cont : contacts){
ids.add(cont.Account.Id);
}
List<Account> accounts = [SELECT LastInvoiceNoticeDate__c FROM Account WHERE Id in: ids];//this is for updating the last_invoice_date in account
List<Invoice__c> linv = [SELECT Id, NetAmount__c, Tax__c, TotalAmount__c, ServicePeriodStartDate__c, ServicePeriodEndDate__c, Account__c, Account__r.Due_date_of_last_open_invoice__c
, InvoiceAutoNumber__c, Contract__c, Account__r.Name, Account__r.AccountCountry__c, Account__r.AccountLegalName__c, Account__r.TaxID__c
, Account__r.BillingStreet, Account__r.BillingCity, Account__r.BillingState, Account__r.BillingPostalCode
, Account__r.BillingCountry, Date_sent__c, Date_1st_reminder_sent__c, Date_2nd_reminder_sent__c
FROM Invoice__c
WHERE Account__c in: ids];
Account parent = [SELECT Id FROM Account where Name =:'Trash Account DO NOT DELETE'];
/**** Create emails ****/
FOR(Contact cont : contacts){
if(cont.Account.Due_date_of_last_open_invoice__c == system.today() + 14) {
template = DueInvoice;
}
if(cont.Account.Due_date_of_last_open_invoice__c == system.today()) {
template = DueInvoice;
}
if(cont.Account.Due_date_of_last_open_invoice__c == system.today() + 7){
template = DueInvoice;
}
if(cont.Account.Due_date_of_last_open_invoice__c == system.today() - 7){
template = BlockingOutstanding;
}
if(cont.Account.Due_date_of_last_open_invoice__c == system.today() - 14) {
template = BlockingAccount;
}
if(cont.Account.Due_date_of_last_open_invoice__c == system.today() - 28) {
template = DeactivatingAccount;
}
emailtemplate = template.Id;
templateDescription = template.Description; // The template description will be assigned to the Task Subject of the task
templateSubject = template.Subject;
system.debug('**linv**' + linv.size());
FOR(Invoice__c inv : linv){
/// Create the pdf for attachment ///
if(inv.Account__c == cont.AccountId && inv.ServicePeriodStartDate__c == inv.Account__r.Due_date_of_last_open_invoice__c){
PageReference BillPDF = new PageReference('/apex/InvoicePDF' + inv.Account__r.AccountCountry__c);
String pdfname = 'temp';
BillPDF.getParameters().put('id', inv.Id);
attach = new Attachment();
Blob attachbody;
try{
attachbody = BillPDF.getContentAsPDF();
} catch (VisualForceException e) {
attachbody = Blob.valueof(pdfname);
}
attach.Body = attachbody;
attach.Name = 'Invoice' + inv.InvoiceAutoNumber__c + '.pdf';
attach.IsPrivate = true;
attach.ParentId = parent.Id;
insert attach;
invPDFattachmemt = attach.Id;
/// Attach pdf to mail ///
Messaging.Emailfileattachment efa = new Messaging.Emailfileattachment();
efa.setFileName(attach.Name);
efa.setBody(attach.Body);
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setTemplateId(emailtemplate);
mail.setOrgWideEmailAddressId(orgWideMail[0].Id);
// mail.setSenderDisplayName(senderName);
mail.setTargetObjectId(cont.Id);
mail.setWhatId(inv.Id);
mail.setFileAttachments(new Messaging.EmailFileAttachment[] {efa});
/**** Set the email address to which the clients replies
** Aftersales manager by default
** Account Owner if AS is inactive
** default email address otherwise ****/
IF(cont.Account.AccountManager__r.Email <> null && cont.Account.AccountManager__r.isActive == TRUE)
ReplyToEmail = cont.Account.AccountManager__r.Email;
ELSE IF(cont.Account.Owner.Email <> null && cont.Account.Owner.isActive == TRUE)
ReplyToEmail = cont.Account.Owner.Email;
ELSE
ReplyToEmail = defaultReplyEmail;
mail.setReplyTo(ReplyToEmail);
mails.add(mail);
}
}
}
system.debug(mails.size());
system.debug(mails);
/**** Send emails ****/
IF(mails.size() >0){
Messaging.sendEmail(mails, false);
/***** updates Account date of last sendout to avoid multiple sendouts ****/
FOR(Account acc : accounts){
acc.LastInvoiceNoticeDate__c = system.today();
}
update accounts;
}
}
}
}
my Extension class for the VF page
public with sharing class InvoiceControllerExtension{
public Invoice__c inv{get;set;}
public string contractId{get;set;}
public string account_name{get;set;}
public string account_country{get;set;}
public string tax_id{get;set;}
public string billing_street {get;set;}
public string billing_city {get;set;}
public string billing_state {get;set;}
public string billing_zip {get;set;}
public string billing_country {get;set;}
public List<InvoiceLineItem__c> liili{get;set;}
public Decimal rowsCliTable {get;set;}
public decimal price {get;set;}
public decimal vat {get;set;}
public decimal total {get;set;}
public string pagebreak{get;set;}
public List<SelectOption> templateoptions = new List<selectOption>();
public Id invPDFattachmemt{get;set;}
public Attachment attach{get;set;}
public Id template{get;set;}
public Id MessageLink{get;set;}
public Boolean confirm{get;set;}
public string ReplyToEmail ;
public InvoiceControllerExtension(ApexPages.StandardController ctr) {
inv = (Invoice__c) ctr.getRecord();
inv = [SELECT Name, NetAmount__c, Tax__c, TotalAmount__c, ServicePeriodStartDate__c, ServicePeriodEndDate__c, Account__c
, InvoiceAutoNumber__c, Contract__c, Account__r.Name, Account__r.AccountCountry__c, Account__r.AccountLegalName__c, Account__r.TaxID__c
, Account__r.BillingStreet, Account__r.BillingCity, Account__r.BillingState, Account__r.BillingPostalCode
, Account__r.BillingCountry, Date_sent__c, Date_1st_reminder_sent__c, Date_2nd_reminder_sent__c
FROM Invoice__c WHERE Id =: inv.Id];
contractId = inv.Contract__c;
}
public PageReference init()
{
try{
IF(inv.Account__r.AccountLegalName__c != null)
account_name = inv.Account__r.AccountLegalName__c;
ELSE account_name = inv.Account__r.Name;
account_country = inv.Account__r.AccountCountry__c;
tax_id = inv.Account__r.TaxID__c;
billing_street = inv.Account__r.BillingStreet;
billing_city = inv.Account__r.BillingCity;
billing_state = inv.Account__r.BillingState;
billing_zip = inv.Account__r.BillingPostalCode;
billing_country = inv.Account__r.BillingCountry;
liili= [SELECT Id, Name, ContractLineItem__r.Quantity__c, NetAmount__c, ContractLineItem__r.TaxRate__c, TaxRate__c
, TotalAmount__c, ContractLineItem__r.Name from InvoiceLineItem__c
WHERE Invoice__c =: inv.Id];
price = 0;
vat = 0;
rowsCliTable = 0;
FOR(InvoiceLineItem__c ili : liili){
rowsCliTable = rowsCliTable + (ili.ContractLineItem__r.Name.length()/40.0).round(System.RoundingMode.UP); // affects 1 line per 40 characters for CLI name (over 40 char, text is wrapped on VF)
}
IF(rowsCliTable > 12){ pagebreak = 'always';} ELSE{ pagebreak = 'avoid';}
IF(liili != null){
for (InvoiceLineItem__c ili : liili){
if(ili.NetAmount__c > 0 || ili.TaxRate__c > 0){
price = price + ili.NetAmount__c;
vat = vat + ili.NetAmount__c*(ili.TaxRate__c/100);
}
}
total = price + vat;
}
}
catch (System.CalloutException e){
ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.FATAL,contractId);
ApexPages.addMessage(myMsg);
}
return null;
}
}