You need to sign in to do that
Don't have an account?
Stuart HARRISON
Create renewal opportunity based on a future date
Ive been looking at Apex Triggers to clone an opportunity as a "renewal opportunity" - to be created 3 months prior to the policy end date.
can this be done with an Apex Trigger ?
We have a custom object (Policy) which is created by a custom button available once the opportunity is Closed - Won. The Policy holds the name of the original opportunity. 3 months prior to policy completion im after a new opportunity cloned from the original with the year section of the name changed (first 4 digits).
Possible ?
can this be done with an Apex Trigger ?
We have a custom object (Policy) which is created by a custom button available once the opportunity is Closed - Won. The Policy holds the name of the original opportunity. 3 months prior to policy completion im after a new opportunity cloned from the original with the year section of the name changed (first 4 digits).
Possible ?
As per my understanding, you need to create a new opportunity as soon as the policy is created on the source opportunity. The new opportunity will be the clone of the source opportunity with just some modification in the name. If this is what your requiremnet is, then,yes it is possible with the help of the apex trigger.
Let me know if you need any help with the apex trigger.
Thanks,
Abhishek Bansal.
What I'd really like is for the opportunity not to be created straight away, but instead be created 3 months prior to the insured_to date. Im not sure i can trigger an apex trigger on a future date ?
Additionally I'd like for the clone to not add the "_copy" to the name - I'd prefer to change the first 4 digits to the insure from year but I cant seem to get any code for this to work:
trigger Renewal on Opportunity (before update) {
if(Trigger.isUpdate){
List<Opportunity> listOppor = new List<Opportunity>();
for (Opportunity o: Trigger.new){
if (o.StageName == 'Closed - Won' && o.Renewal_Created__c == null){
Opportunity oppNew = o.clone();
// oppNew.Name = oppNew.Name + '_Renewal';
oppNew.StageName = 'New';
oppNew.Renewal_Indicator__c = true;
OppNew.CloseDate = OppNew.CloseDate.addyears(1);
OppNew.Insured_period_from__c = OppNew.Insured_period_from__c.addyears(1);
OppNew.Insured_period_to__c = OppNew.Insured_period_to__c.addyears(1);
OppNew.OwnerID = o.CreatedByID;
o.Renewal_Created__c = 'Yes';
Oppnew.Renewed_Opportunity__c = oppNew.Name;
OppNew.Description = OppNew.Description + ' Original S6130 Line Size was : ' + OppNew.S6130_Line_Size__c;
listOppor.add(oppNew);
}// end if
}//end for
if(listOppor.size() > 0){
insert listOppor;
}//end if
}//end if
}
Yes, you are right, we can not schedule a trigger to execute on a future date but however we can craete a schedulable class that will run on a particular basis. In this case, we can write a scheduler class that will run daily and will clone the opportunity whose insured_to date will be after 3 months. In that scheduler class you can also adjust the name of the new opportunity as per your requirement. Let me know if you need any help with the scheduler class.
Thanks,
Abhishek Bansal.
You can learn how to write the batch class and how to schedule it from the trailhead link given below:
https://trailhead.salesforce.com/en/modules/asynchronous_apex/units/async_apex_batch
If you want to me to write a scheduler class for this requirement then you can contact me on
Gmail: abhibansal2790@gmail.com
Skype: abhishek.bansal2790
Thanks,
Abhishek Bansal.
1) I cant get the "add" function to save/compile (in bold)
2) I cant see this class in the list available for scheduling ?
Code is below - Im not sure its fully complete.
global class ScheduleRenewal implements Database.Batchable<SObject>
{
global Database.queryLocator start(Database.BatchableContext ctx)
{
return Database.getQueryLocator([Select Opportunity.Name, Opportunity.StageName, opportunity.Renewal_Created__c, opportunity.Insured_period_from__c, opportunity.Insured_period_to__c From Opportunity where Opportunity.Insured_Period_to__c >= LAST_N_DAYS:60 AND Opportunity.Renewal_Created__c != 'YES']);
}
global void execute(Database.BatchableContext BC, List<opportunity> opportunityList)
{
//for creating new opportunity.
List<Opportunity> newOpps=new List<Opportunity>();
for(Opportunity c: opportunityList)
{
if (c.StageName == 'Closed - Won'){
Opportunity opp = c.clone();
// oppNew.Name = OppNew.Insured_period_from__c.year & oppNew.Name.substringadter('_');
opp.Name = c.Name + '_Renewal';
opp.StageName = 'New';
opp.Renewal_Indicator__c = true;
Opp.Insured_period_from__c = c.Insured_period_to__c;
Opp.Insured_period_to__c = Opp.Insured_period_from__c.adddays(c.Insured_period_to__c.daysbetween(c.Insured_period_from__c));
Opp.CloseDate = Opp.Insured_period_from__c.addmonths(-1);
Opp.OwnerID = c.CreatedByID;
c.Renewal_Created__c = 'Yes';
Opp.Previously_won_or_lost__c = 'Won';
Opp.Renewed_Opportunity__c = opp.Name;
Opp.Renewal_Information__c = 'Original S6130 Line Size was : ' + Opp.S6130_Line_Size__c;
}
if (c.StageName == 'Closed - Lost'){
Opportunity opp = c.clone();
// oppNew.Name = OppNew.Insured_period_from__c.year & oppNew.Name.substringadter('_');
opp.Name = c.Name + '_Renewal';
opp.StageName = 'New';
opp.Renewal_Indicator__c = true;
Opp.Insured_period_from__c = c.Insured_period_to__c;
Opp.Insured_period_to__c = Opp.Insured_period_from__c.adddays(c.Insured_period_to__c.daysbetween(c.Insured_period_from__c));
Opp.CloseDate = Opp.Insured_period_from__c.addmonths(-1);
Opp.OwnerID = c.CreatedByID;
c.Renewal_Created__c = 'Yes';
Opp.Previously_won_or_lost__c = 'Lost';
Opp.Renewed_Opportunity__c = opp.Name;
Opp.Renewal_Information__c = 'Lost Reason : ' + c.Lost_Cancel_Reason__c + ' - comment : ' + c.Lost_Cancelled_Reason_Comment__c + ' - Pricing : ' + c.Lost_Due_to_Pricing_Currency__c + ' ' + c.Lost_Due_to_Pricing_amount__c;
Opp.Lost_Cancel_Reason__c = null;
Opp.Lost_Cancelled_Reason_Comment__c = null;
Opp.Lost_Due_to_Pricing_Currency__c = null;
Opp.Lost_Due_to_Pricing_amount__c = null;
}
// newOpps.add(Opp);
}
insert newOpps;
}
global void finish(Database.BatchableContext BC)
{
}
}
What is the error you are facing while saving the code highlighted in Bold and you need to create a scheduler class for this batch class in order to get it scheduled.
Please find help from link given below:
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_scheduler.htm
Thanks,
Abhishek Bansal.
Error: Compile Error: Variable does not exist: Opp at line 57 column 20
Since the variable is declared inside the if block so it would not be available outside the block. Please move this line inside the if block as mentioned below:
Let me know if you need any further help on this.
Thanks,
Abhishek Bansal.
I have managed to create an apex class that saves, and have managed to add it into a schedule which has run - but it did nothing. Have i closed off the job before it actually gets to do anything ? Or am I not writing the opportunities at the end ? Its a hybrid from examples I have found and a trigeer that was working successfully. im not sure if i need to change the global database line ?
global class ScheduleRenewal implements Schedulable {
global void execute(SchedulableContext ctx) {
}
global Database.queryLocator start(Database.BatchableContext ctx)
{
return Database.getQueryLocator([Select Opportunity.Name, Opportunity.StageName, opportunity.Renewal_Created__c, opportunity.Insured_period_from__c, opportunity.Insured_period_to__c From Opportunity where Opportunity.Insured_Period_to__c >= LAST_N_DAYS:60 AND Opportunity.Renewal_Created__c != 'YES']);
}
global void execute(Database.BatchableContext BC, List<opportunity> opportunityList)
{
//for creating new opportunity.
List<Opportunity> newOpps=new List<Opportunity>();
for(Opportunity c: opportunityList)
{
if (c.StageName == 'Closed - Won'){
Opportunity opp = c.clone();
// oppNew.Name = OppNew.Insured_period_from__c.year & oppNew.Name.substringadter('_');
opp.Name = c.Name + '_Renewal';
opp.StageName = 'New';
opp.Renewal_Indicator__c = true;
Opp.Insured_period_from__c = c.Insured_period_to__c;
Opp.Insured_period_to__c = Opp.Insured_period_from__c.adddays(c.Insured_period_to__c.daysbetween(c.Insured_period_from__c));
Opp.CloseDate = Opp.Insured_period_from__c.addmonths(-1);
Opp.OwnerID = c.CreatedByID;
c.Renewal_Created__c = 'Yes';
Opp.Previously_won_or_lost__c = 'Won';
Opp.Renewed_Opportunity__c = opp.Name;
Opp.Renewal_Information__c = 'Original S6130 Line Size was : ' + Opp.S6130_Line_Size__c;
newOpps.add(Opp);
}
if (c.StageName == 'Closed - Lost'){
Opportunity opp = c.clone();
// oppNew.Name = OppNew.Insured_period_from__c.year & oppNew.Name.substringadter('_');
opp.Name = c.Name + '_Renewal';
opp.StageName = 'New';
opp.Renewal_Indicator__c = true;
Opp.Insured_period_from__c = c.Insured_period_to__c;
Opp.Insured_period_to__c = Opp.Insured_period_from__c.adddays(c.Insured_period_to__c.daysbetween(c.Insured_period_from__c));
Opp.CloseDate = Opp.Insured_period_from__c.addmonths(-1);
Opp.OwnerID = c.CreatedByID;
c.Renewal_Created__c = 'Yes';
Opp.Previously_won_or_lost__c = 'Lost';
Opp.Renewed_Opportunity__c = opp.Name;
Opp.Renewal_Information__c = 'Lost Reason : ' + c.Lost_Cancel_Reason__c + ' - comment : ' + c.Lost_Cancelled_Reason_Comment__c + ' - Pricing : ' + c.Lost_Due_to_Pricing_Currency__c + ' ' + c.Lost_Due_to_Pricing_amount__c;
Opp.Lost_Cancel_Reason__c = null;
Opp.Lost_Cancelled_Reason_Comment__c = null;
Opp.Lost_Due_to_Pricing_Currency__c = null;
Opp.Lost_Due_to_Pricing_amount__c = null;
newOpps.add(Opp);
}
// newOpps.add(Opp);
}
insert newOpps;
}
global void finish(Database.BatchableContext BC)
{
}
}
global class ScheduleRenewal implements Schedulable {
global void execute(SchedulableContext ctx) {
}
global Database.queryLocator start(Database.BatchableContext ctx)
{
return Database.getQueryLocator([Select Opportunity.Name, Opportunity.StageName, opportunity.Renewal_Created__c,
opportunity.Insured_period_from__c, opportunity.Insured_period_to__c From Opportunity
]);
}
global void execute(Database.BatchableContext BC, List<opportunity> opportunityList)
{
//for creating new opportunity.
List<Opportunity> newOpps=new List<Opportunity>();
for(Opportunity c: opportunityList)
{
System.Debug('message 1');
System.Debug(c.StageName );
if (c.StageName == 'Closed - Won'){
Opportunity opp = c.clone();
// oppNew.Name = OppNew.Insured_period_from__c.year & oppNew.Name.substringadter('_');
opp.Name = c.Name + '_Renewal';
opp.StageName = 'New';
opp.Renewal_Indicator__c = true;
Opp.Insured_period_from__c = c.Insured_period_to__c;
Opp.Insured_period_to__c = Opp.Insured_period_from__c.adddays(c.Insured_period_to__c.daysbetween(c.Insured_period_from__c));
Opp.CloseDate = Opp.Insured_period_from__c.addmonths(-1);
Opp.OwnerID = c.CreatedByID;
c.Renewal_Created__c = 'Yes';
Opp.Previously_won_or_lost__c = 'Won';
Opp.Renewed_Opportunity__c = opp.Name;
Opp.Renewal_Information__c = 'Original S6130 Line Size was : ' + Opp.S6130_Line_Size__c;
newOpps.add(Opp);
System.Debug('message 2');
}
if (c.StageName == 'Closed - Lost'){
Opportunity opp = c.clone();
// oppNew.Name = OppNew.Insured_period_from__c.year & oppNew.Name.substringadter('_');
opp.Name = c.Name + '_Renewal';
opp.StageName = 'New';
opp.Renewal_Indicator__c = true;
Opp.Insured_period_from__c = c.Insured_period_to__c;
Opp.Insured_period_to__c = Opp.Insured_period_from__c.adddays(c.Insured_period_to__c.daysbetween(c.Insured_period_from__c));
Opp.CloseDate = Opp.Insured_period_from__c.addmonths(-1);
Opp.OwnerID = c.CreatedByID;
c.Renewal_Created__c = 'Yes';
Opp.Previously_won_or_lost__c = 'Lost';
Opp.Renewed_Opportunity__c = opp.Name;
Opp.Renewal_Information__c = 'Lost Reason : ' + c.Lost_Cancel_Reason__c + ' - comment : ' + c.Lost_Cancelled_Reason_Comment__c + ' - Pricing : ' + c.Lost_Due_to_Pricing_Currency__c + ' ' + c.Lost_Due_to_Pricing_amount__c;
Opp.Lost_Cancel_Reason__c = null;
Opp.Lost_Cancelled_Reason_Comment__c = null;
Opp.Lost_Due_to_Pricing_Currency__c = null;
Opp.Lost_Due_to_Pricing_amount__c = null;
newOpps.add(Opp);
System.Debug('message 3');
}
}
insert newOpps;
}
global void finish(Database.BatchableContext BC)
{
System.Debug('message 4');
}
}
Your batch class seems absolutely fine. Just need to take care of the Schedule class and how to schedule the batch. Please follow the steps below:
Save you batch class with all the query filters as per your requirement. Find the class below: Now create a new class i.e. Scheduler class with below code:
Now run the following command in the Developer Console: CronStr represents that how you want to schedule your batch. In this case, your batch will run daily at 1:00 PM. You can modify the crone expression by using the following link. Means if you want to change the running time of your batch then you can generate the crone string from link givenn below:
http://www.cronmaker.com/
Once you run the above statements in the developer console then your batch is successfully scheduled. You can check the scheduled jobs to see that your batch is scheduked to run daily at 1:00 PM with 'Create Renewal Opportunity' name.
Once the batch is run you can check the history of the batch in the Apex Jobs. This will show you how many batches have been processed by the class and how many are successfull.
Please let me know if you need any further information on this.
Thanks,
Abhishek Bansal.