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
SUMIT BANERJEESUMIT BANERJEE 

Hi I have written batch class to update stage field of opportunity as per close date

Hi I have written batch class to update stage field of opportunity as per close date but when I run my batch class it will be updating close date also.
How to prevent that can you guide where I did mistake in my code :

global class batchOpportunityUpdate implements Database.Batchable <sObject>{
    
    date dt1 = system.today().addDays(+30);
    date dt2 = system.today().addDays(+120);
    date dt3 = system.today().addDays(+182);
    Id oppRecordTypeId = Schema.SObjectType.Opportunity.getRecordTypeInfosByName().get('New Rec3 Type').getRecordTypeId(); 
    
    
    global Database.QueryLocator start(Database.BatchableContext BC){
        
        string query = 'SELECT Id,CloseDate,StageName,RecordTypeId FROM Opportunity Where RecordTypeId =:oppRecordTypeId ';
        return Database.getQueryLocator(query);
    }
    global void execute(Database.BatchableContext BC, List<Opportunity> scope){
            for(Opportunity opp : scope){
                if(opp.CloseDate <= dt1 && oppRecordTypeId == opp.RecordTypeId){
                System.debug('Record'+oppRecordTypeId +'dt1'+dt1);
                opp.StageName ='Qualification';
                }else if(opp.CloseDate <= dt2 && oppRecordTypeId == opp.RecordTypeId){
                    opp.StageName ='Needs Analysis';
                }else if(opp.CloseDate <= dt3 && oppRecordTypeId == opp.RecordTypeId){
                opp.StageName ='Closed Won';
                }
            }
            update scope;
            
    }
    global void finish(Database.BatchableContext BC){
            
    }
}


Thanks,
sumit
Best Answer chosen by SUMIT BANERJEE
UC InnovationUC Innovation
Hi Sumit,

I believe this is standard salesforce functionality. If an opportunity is future and the status is changed to closed then close date gets updated to the date which it closed (e.g. today). This seems to be what you are seeing. If you wish to prevent this you might want to store the original close date in a date variable and adjust after the initial update to the record(s). Simply changing your execute function like this might do the trick:
 
global void execute(Database.BatchableContext BC, List<Opportunity> scope){
    Map<Opportunity, Date> opportunityToOldClosedDateMap = new Map<Opportunity, Date>();

    for (Opportunity opp : scope) {
        if(opp.CloseDate <= dt1 && oppRecordTypeId == opp.RecordTypeId) {
            System.debug('Record'+oppRecordTypeId +'dt1'+dt1);
            opp.StageName ='Qualification';
        } else if(opp.CloseDate <= dt2 && oppRecordTypeId == opp.RecordTypeId) {
            opp.StageName ='Needs Analysis';
        } else if(opp.CloseDate <= dt3 && oppRecordTypeId == opp.RecordTypeId) {   
            opp.StageName ='Closed Won';
            opportunityToOldClosedDateMap.put(opp, opp.CloseDate);
        }
    }
    
    update scope;

    for (Opportunity closedOpp : opportunityToOldClosedDateMap.keySet() ) {
        closedOpp.closeDate = opportunityToOldClosedDateMap.get(closedOpp);
    }

    update new List<Opportunity>(opportunityToOldClosedDateMap.keySet());
 }

Hope this helps!

If you have any further questions please feel free to as them. Also, if you feel like my answer helped resolve your issue(s) please remember to mark it as best answer so others can benefit from it as well.

AM

All Answers

UC InnovationUC Innovation
Hi Sumit,

I believe this is standard salesforce functionality. If an opportunity is future and the status is changed to closed then close date gets updated to the date which it closed (e.g. today). This seems to be what you are seeing. If you wish to prevent this you might want to store the original close date in a date variable and adjust after the initial update to the record(s). Simply changing your execute function like this might do the trick:
 
global void execute(Database.BatchableContext BC, List<Opportunity> scope){
    Map<Opportunity, Date> opportunityToOldClosedDateMap = new Map<Opportunity, Date>();

    for (Opportunity opp : scope) {
        if(opp.CloseDate <= dt1 && oppRecordTypeId == opp.RecordTypeId) {
            System.debug('Record'+oppRecordTypeId +'dt1'+dt1);
            opp.StageName ='Qualification';
        } else if(opp.CloseDate <= dt2 && oppRecordTypeId == opp.RecordTypeId) {
            opp.StageName ='Needs Analysis';
        } else if(opp.CloseDate <= dt3 && oppRecordTypeId == opp.RecordTypeId) {   
            opp.StageName ='Closed Won';
            opportunityToOldClosedDateMap.put(opp, opp.CloseDate);
        }
    }
    
    update scope;

    for (Opportunity closedOpp : opportunityToOldClosedDateMap.keySet() ) {
        closedOpp.closeDate = opportunityToOldClosedDateMap.get(closedOpp);
    }

    update new List<Opportunity>(opportunityToOldClosedDateMap.keySet());
 }

Hope this helps!

If you have any further questions please feel free to as them. Also, if you feel like my answer helped resolve your issue(s) please remember to mark it as best answer so others can benefit from it as well.

AM
This was selected as the best answer
SUMIT BANERJEESUMIT BANERJEE
Thanks, @UC Innovation your code is really helpful for me. I thanks for the great support.
UC InnovationUC Innovation
If you feel like my answer helped resolve your issue(s) please remember to mark it as best answer so others can benefit from it as well.
SUMIT BANERJEESUMIT BANERJEE
Sure @UC Innovation