function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
SalesforceCrm AccountCRMSalesforceCrm AccountCRM 

Send email notification to the owner of the record 30 days before the contract end date

Hello All,
I have a requirement where i need to send an email notification to the contract owner 30 days before the contract end date , when the contract role is 'SA/EB?TA' etc.Any suggestion  with an example very much appreciated.
Best Answer chosen by SalesforceCrm AccountCRM
Mahesh DMahesh D
Hi

Please find the below code:

Here I considered:

(1) Included Contract's Email.
(2) Added the code in finish method.
(3) Implement with Schedulable so that you can write the schedulable code here it self.

 
global class NotificationEmailtoAccountExecutive implements Database.Batchable < sObject >, Schedulable, Database.Stateful {
	global List<String> errorMessages = new List<String>();
    global Database.QueryLocator start(Database.BatchableContext bc) {
        /* Date d = Date.today();*/
        Date ed = Date.today().addDays(110);
        System.debug(Date.today().addDays(110));
        
        set<Id> setContractIds = new set<Id>();

        for(Contract_role__c objContract: [SELECT  Contract__c FROM Contract_role__c WHERE Role__c = 'Subscription Administrator' AND Contract__r.EndDate =: ed]) {
			setContractIds.add(objContract.Contract__c);
        }
        
        return Database.getQueryLocator('Select  id, Contract_Name__c , EndDate ,Contact_Email__c, Contract_End_Date_2__c, Owner.Email FROM Contract  WHERE Id IN: setContractIds');
    }

    global void execute(Database.BatchableContext bc, List < Contract > recs) {
        List < Messaging.SingleEmailMessage > mailList = new List < Messaging.SingleEmailMessage > ();
        for (Contract c: recs) {
            if (c.Contact_Email__c != null) {
                List < String > toAddresses = new List < String > ();
                Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
                toAddresses.add(c.Contact_Email__c);
				toAddresses.add(c.Owner.Email);
                mail.setToAddresses(toAddresses);
                mail.setSubject('Notification Before 110 Days of Contract End Date');
                String messageBody = '<html><body>Hi ' + c.Contract_Name__c  + ',<br>Your  Contract Expires within 110 Days . <br>Kindly take approriate action.<br><br><b>Regards,</b><br>EDB</body></html>';
                mail.setHtmlBody(messageBody);
                mailList.add(mail);
            }
        }
        Messaging.sendEmail(mailList);
    }

    global void finish(Database.BatchableContext bc) {
		AsyncApexJob aaj = [Select Id, Status, NumberOfErrors, JobItemsProcessed, MethodName, TotalJobItems, CreatedBy.Email from AsyncApexJob where Id =:BC.getJobId()];
        
        // Send an email to the Apex job's submitter notifying of job completion.
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        String[] toAddresses = new String[] {aaj.CreatedBy.Email};
        mail.setToAddresses(toAddresses);
        mail.setSubject('JOB Salesforce NotificationEmailtoAccountExecutive Finished: ' + aaj.Status);
        String bodyText='Total Job Items ' + aaj.TotalJobItems + ' Number of records processed ' + aaj.JobItemsProcessed + ' with '+ aaj.NumberOfErrors + ' failures.\n';
        bodyText += 'Number of Error Messages ' + errorMessages.size() + '\n';
        bodyText += 'Error Message' + String.join(errorMessages, '\n');
        mail.setPlainTextBody(bodyText);
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
	}
	
	global void execute(SchedulableContext SC) {
        NotificationEmailtoAccountExecutive batchable = new NotificationEmailtoAccountExecutive();
		database.executebatch(batchable);
    }
}

Please do let me know if it helps you.

Regards,
Mahesh

All Answers

SalesforceCrm AccountCRMSalesforceCrm AccountCRM
@Mahesh D:Thanks for your response .The notification can be sent to owner with the workflow but we have a few specific contract role where the notification to be sent .We have a custom object as Contract Role and it has ROLE as a picklist field which has values as "SA" ,"EB","OR" ETC.It has a master detail relationship with Contract.Now i would like to send an email notification to Contract role before 30 days from the contract end date whos role is " SA/EB/OR ".This notification should be sent to the "SA/EB/OR Role".
Amit Chaudhary 8Amit Chaudhary 8
Hi ,
Try to use salesforce Batch job for same and schedule the batch job in late night which will fatch all record where we need to send email (30 days one ). Please check below post for help
1) http://amitsalesforce.blogspot.in/2016/02/batch-apex-in-salesforce-test-class-for.html

Batch Apex
A Batch class allows you to define a single job that can be broken up into manageable chunks that will be processed separately.

Sample Batch Apex
1) Start method is automatically called at the beginning of the apex job. This method will collect record or objects on which the operation should be performed. These record are divided into subtasks & passes those to execute method.

2) Execute Method performs operation which we want to perform on the records fetched from start method.

3) Finish method executes after all batches are processed. Use this method to send confirmation email notifications.

Please start coding we will help you
Mahesh DMahesh D
Hi,

I assume that 'Contract' is the Master and 'Contract Role' is the Detail object.

User-added image

Created a formula field to get the Master's means Contract End Date on the Contract Role object.

Regards,
Mahesh

 
SalesforceCrm AccountCRMSalesforceCrm AccountCRM
@Amit Chaudhary 8 ,@Mahesh D :Thanks for your response.I have tried using batch class and schedule ,but it was for the contact email.Now how could i send it to the Contract Owner /user of the record .Any suggestion please .
global class NotificationEmailtoAccountExecutive implements Database.Batchable < sObject > 
{
    global Database.QueryLocator start(Database.BatchableContext bc) 
    {
        /* Date d = Date.today();*/
        Date ed = Date.today().addDays(110);
        System.debug(Date.today().addDays(110));
        
        set<Id> setContractIds = new set<Id>();

        for(Contract_role__c objContract: [SELECT  Contract__c FROM Contract_role__c WHERE Role__c = 'Subscription Administrator' AND Contract__r.EndDate =: ed])
        {
          setContractIds.add(objContract.Contract__c);
        }
        
        //String soql = 'Select  id, Contract_Name__c , EndDate ,Contact_Email__c, Contract_End_Date_2__c , ( SELECT  Name, Role__c FROM Contract_roles__r WHERE Role__c = \'Subscription Administrator\') FROM Contract  WHERE EndDate =: ed';
        return Database.getQueryLocator('Select  id, Contract_Name__c , EndDate ,Contact_Email__c, Contract_End_Date_2__c FROM Contract  WHERE Id IN: setContractIds');
    }

    global void execute(Database.BatchableContext bc, List < Contract > recs) 
    {
        List < Messaging.SingleEmailMessage > mailList = new List < Messaging.SingleEmailMessage > ();
        for (Contract c: recs) 
        {
            if (c.Contact_Email__c != null) 
            {
                List < String > toAddresses = new List < String > ();
                Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
                toAddresses.add(c.Contact_Email__c);
                mail.setToAddresses(toAddresses);
                mail.setSubject('Notification Before 110 Days of Contract End Date');
                String messageBody = '<html><body>Hi ' + c.Contract_Name__c  + ',<br>Your  Contract Expires within 110 Days . <br>Kindly take approriate action.<br><br><b>Regards,</b><br>EDB</body></html>';
                mail.setHtmlBody(messageBody);
                mailList.add(mail);
            }
        }
        Messaging.sendEmail(mailList);
    }

    global void finish(Database.BatchableContext bc) {}
}

 
Mahesh DMahesh D
Hi

Please find the below code:

Here I considered:

(1) Included Contract's Email.
(2) Added the code in finish method.
(3) Implement with Schedulable so that you can write the schedulable code here it self.

 
global class NotificationEmailtoAccountExecutive implements Database.Batchable < sObject >, Schedulable, Database.Stateful {
	global List<String> errorMessages = new List<String>();
    global Database.QueryLocator start(Database.BatchableContext bc) {
        /* Date d = Date.today();*/
        Date ed = Date.today().addDays(110);
        System.debug(Date.today().addDays(110));
        
        set<Id> setContractIds = new set<Id>();

        for(Contract_role__c objContract: [SELECT  Contract__c FROM Contract_role__c WHERE Role__c = 'Subscription Administrator' AND Contract__r.EndDate =: ed]) {
			setContractIds.add(objContract.Contract__c);
        }
        
        return Database.getQueryLocator('Select  id, Contract_Name__c , EndDate ,Contact_Email__c, Contract_End_Date_2__c, Owner.Email FROM Contract  WHERE Id IN: setContractIds');
    }

    global void execute(Database.BatchableContext bc, List < Contract > recs) {
        List < Messaging.SingleEmailMessage > mailList = new List < Messaging.SingleEmailMessage > ();
        for (Contract c: recs) {
            if (c.Contact_Email__c != null) {
                List < String > toAddresses = new List < String > ();
                Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
                toAddresses.add(c.Contact_Email__c);
				toAddresses.add(c.Owner.Email);
                mail.setToAddresses(toAddresses);
                mail.setSubject('Notification Before 110 Days of Contract End Date');
                String messageBody = '<html><body>Hi ' + c.Contract_Name__c  + ',<br>Your  Contract Expires within 110 Days . <br>Kindly take approriate action.<br><br><b>Regards,</b><br>EDB</body></html>';
                mail.setHtmlBody(messageBody);
                mailList.add(mail);
            }
        }
        Messaging.sendEmail(mailList);
    }

    global void finish(Database.BatchableContext bc) {
		AsyncApexJob aaj = [Select Id, Status, NumberOfErrors, JobItemsProcessed, MethodName, TotalJobItems, CreatedBy.Email from AsyncApexJob where Id =:BC.getJobId()];
        
        // Send an email to the Apex job's submitter notifying of job completion.
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        String[] toAddresses = new String[] {aaj.CreatedBy.Email};
        mail.setToAddresses(toAddresses);
        mail.setSubject('JOB Salesforce NotificationEmailtoAccountExecutive Finished: ' + aaj.Status);
        String bodyText='Total Job Items ' + aaj.TotalJobItems + ' Number of records processed ' + aaj.JobItemsProcessed + ' with '+ aaj.NumberOfErrors + ' failures.\n';
        bodyText += 'Number of Error Messages ' + errorMessages.size() + '\n';
        bodyText += 'Error Message' + String.join(errorMessages, '\n');
        mail.setPlainTextBody(bodyText);
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
	}
	
	global void execute(SchedulableContext SC) {
        NotificationEmailtoAccountExecutive batchable = new NotificationEmailtoAccountExecutive();
		database.executebatch(batchable);
    }
}

Please do let me know if it helps you.

Regards,
Mahesh
This was selected as the best answer
SalesforceCrm AccountCRMSalesforceCrm AccountCRM
@Mahesh D :Thanks for your response.It worked for the Owner of the record .Now Similarly , we need to send an notification email for the Owner of the record and manager , before 100 days of the contract end date .But how do i get the manager in the code.Any help very much appreciated.
Mahesh DMahesh D
Hi,

In your query you can add 

Owner.Manager.Email
 
return Database.getQueryLocator('Select  id, Contract_Name__c , EndDate ,Contact_Email__c, Contract_End_Date_2__c, Owner.Email, Owner.Manager.Email FROM Contract  WHERE Id IN: setContractIds');
Please find the below modified code:
 
global class NotificationEmailtoAccountExecutive implements Database.Batchable < sObject >, Schedulable, Database.Stateful {
	global List<String> errorMessages = new List<String>();
    global Database.QueryLocator start(Database.BatchableContext bc) {
        /* Date d = Date.today();*/
        Date ed = Date.today().addDays(110);
        System.debug(Date.today().addDays(110));
        
        set<Id> setContractIds = new set<Id>();

        for(Contract_role__c objContract: [SELECT  Contract__c FROM Contract_role__c WHERE Role__c = 'Subscription Administrator' AND Contract__r.EndDate =: ed]) {
			setContractIds.add(objContract.Contract__c);
        }
        
        return Database.getQueryLocator('Select  id, Contract_Name__c , EndDate ,Contact_Email__c, Contract_End_Date_2__c, Owner.Email, Owner.Manager.Email FROM Contract  WHERE Id IN: setContractIds');
    }

    global void execute(Database.BatchableContext bc, List < Contract > recs) {
        List < Messaging.SingleEmailMessage > mailList = new List < Messaging.SingleEmailMessage > ();
        for (Contract c: recs) {
            if (c.Contact_Email__c != null) {
                List < String > toAddresses = new List < String > ();
                Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
                toAddresses.add(c.Contact_Email__c);
				toAddresses.add(c.Owner.Email);
                mail.setToAddresses(toAddresses);
                mail.setSubject('Notification Before 110 Days of Contract End Date');
                String messageBody = '<html><body>Hi ' + c.Contract_Name__c  + ',<br>Your  Contract Expires within 110 Days . <br>Kindly take approriate action.<br><br><b>Regards,</b><br>EDB</body></html>';
                mail.setHtmlBody(messageBody);
                mailList.add(mail);
            }
        }
        Messaging.sendEmail(mailList);
    }

    global void finish(Database.BatchableContext bc) {
		AsyncApexJob aaj = [Select Id, Status, NumberOfErrors, JobItemsProcessed, MethodName, TotalJobItems, CreatedBy.Email from AsyncApexJob where Id =:BC.getJobId()];
        
        // Send an email to the Apex job's submitter notifying of job completion.
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        String[] toAddresses = new String[] {aaj.CreatedBy.Email};
        mail.setToAddresses(toAddresses);
        mail.setSubject('JOB Salesforce NotificationEmailtoAccountExecutive Finished: ' + aaj.Status);
        String bodyText='Total Job Items ' + aaj.TotalJobItems + ' Number of records processed ' + aaj.JobItemsProcessed + ' with '+ aaj.NumberOfErrors + ' failures.\n';
        bodyText += 'Number of Error Messages ' + errorMessages.size() + '\n';
        bodyText += 'Error Message' + String.join(errorMessages, '\n');
        mail.setPlainTextBody(bodyText);
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
	}
	
	global void execute(SchedulableContext SC) {
        NotificationEmailtoAccountExecutive batchable = new NotificationEmailtoAccountExecutive();
		database.executebatch(batchable);
    }
}

Please do let me know if it helps you.

Regards,
Mahesh
SalesforceCrm AccountCRMSalesforceCrm AccountCRM
@Mahesh D :Thanks for the reply.Apart from send an email notification to the contract owner manager ,it needs to be sent to Account / Opportunity owner and manager .How do we fetch them in the code.Any help very much appreciated.
Mahesh DMahesh D
Hi,

In your query you can add:

Account.Owner.Manager.Email

 
return Database.getQueryLocator('Select  id, Contract_Name__c, EndDate ,Contact_Email__c, Contract_End_Date_2__c, Owner.Email, Owner.Manager.Email, Account.Owner.Manager.Email FROM Contract  WHERE Id IN: setContractIds');

Regards,
Mahesh
SalesforceCrm AccountCRMSalesforceCrm AccountCRM
@Mahesh D :Thanks .Now we have a field  as SRR  (picklist field) when the Account owner / Manager  --- fills the field as Yes , then a notification email should trigger to the customer (contract name )for 30 , 15 , 5 days regarding their contract expiry.
Similary  when the Account owner / Manager  --- fills the field as NO , then we need to stop sending the email notification.
So can we have 'n' of if conditions in batch class.Any help very much appreciated.
 
Mahesh DMahesh D
Hi

Please open a new discussion for this as we mixed up many thing into this, which is not good. 
Please mark it as solved and open a new discussion so that it will be helpful to others in the future.

Regards,
Mahesh
SalesforceCrm AccountCRMSalesforceCrm AccountCRM
@Mahesh D :Thanks.Okay, i have selected the best answer and opened a new discussion.PF the link.
https://developer.salesforce.com/forums/ForumsMain?id=906F0000000DEhEIAW
Any suggestion.