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
suji srinivasansuji srinivasan 

Batch Apex update issue

Hi, 
I need to update
1.account rating as client customer if opportunity = last 2 years & closed opportunity
2.account rating as prospect if  opportunity  = last 3 to 5 years & open opportunity.
3.  for last 2 years if  account have two opportunity and both are open it should get update as prospect.

4.some accounts have two opportunities one as open and another as closed and  its updating it as  prospect   if it has open opportunity for recent year it should get update as client customer 
can anyone guide me .

global class AccountOptyBatchclass implements  Database.Batchable<sObject>  {

global  Database.QueryLocator start(Database.BatchableContext bc) {
   list<Id> accopty = new list<Id>();
      string query='select ID,Name,Rating,(select Id,AccountId,stageName,CloseDate From Opportunities) from Account';
      return Database.getQueryLocator(query);
   }
global Void execute(Database.BatchableContext bc, List<Account> Scope){
       list<Account> accopty = new list<account>();
   
        system.debug('query'+scope);
        for(Account a :Scope){
            for(Opportunity o: a.Opportunities){
                date dt = system.today().adddays(-1825);
                date ty = system.today().adddays(-730);
               
                system.debug ('dt'+dt);
                system.debug ('ty'+ty);
                  if((o.CloseDate >=ty) && (o.StageName =='Won-Work In Progress' || o.StageName =='Closed Won' || o.StageName =='Delivered')) {
                   
                     a.rating='Client - Customer';
                      accopty.add(a) ;
                    system.debug(' Last2yearsCloseDate'+a.rating) ;
                
                }

               else if( (o.CloseDate >=ty) && (o.StageName =='Shaping' || o.StageName =='Proposal Submitted' || o.StageName =='Decision' || o.StageName =='Engagement' )){
                   //if ((o.StageName !='Won-Work In Progress' || o.StageName !='Closed Won' || o.StageName !='Delivered' )&&(o.CloseDate < ty)){
                     a.rating='prospect';
                     accopty.add(a) ;
                       system.debug(' Last3to5yearsCloseDate'+a.rating) ; //}
                
                
                    } 
                
        }}
  
    update accopty ;
   
}
        global void finish(Database.BatchableContext bc){
   }
}
 

Thanks in Advance
Best Answer chosen by suji srinivasan
Bryan Leaman 6Bryan Leaman 6
Ahh, I see -- it's not just the closed opportunity that has to be within 2 years, then? That's part of what wasn't clear to me from your description & code. A small adjustment should handle this:
global class AccountOptyBatchclass implements  Database.Batchable<sObject>  {

global  Database.QueryLocator start(Database.BatchableContext bc) {
    string query='select ID,Name,Rating,(select Id,AccountId,stageName,CloseDate From Opportunities) from Account';
    return Database.getQueryLocator(query);
}

global Void execute(Database.BatchableContext bc, List<Account> Scope){
    list<Account> accopty = new list<account>();
    system.debug('query'+scope);
    Date twoYearsAgo = Date.today().addDays(-730);
    Date fiveYearsAgo = Date.today().addDays(-1825);
    Set<String> closedStage = new Set<String>{
         'Won-Work In Progress', 'Closed Won', 'Delivered'
    };
    Set<String> openStage = new Set<String>{
        'Shaping', 'Proposal Submitted', 'Decision', 'Engagement'
    };
    for(Account a :Scope){
        Integer numberClosed = 0;                // new line
        Integer closedLast2Years = 0;
        Integer openLast2Years = 0;
        Integer open3To5Years = 0;
        for(Opportunity o: a.Opportunities) {
            if (closedStage.contains(o.StageName) {
                ++numberClosed;                 // new line
                if (o.CloseDate>=twoYearsAgo) closedLast2Years++;
            }
            if (openStage.contains(o.StageName) {
                if (o.CloseDate>=twoYearsAgo) openLast2Years++;
                if (o.CloseDate>=fiveYearsAgo && o.CloseDate<twoYearsAgo) open3To5Years++;
            } 
        }

        // new condition - if any open w/in last 2 years and any closed, they are a client
        if (openLast2Years>0 && numberClosed>0) accopt = new Account(Id=a.Id, Rating='Client');
        
        // account rating as client customer if opportunity = last 2 years & closed opportunity
        else if (closedLast2Years>0) accopty = new Account(Id=a.Id, Rating='Client');
        // for last 2 years if  account have two opportunity and both are open it should get update as prospect
        else if (openLast2Years==2) accopty = new Account(Id=a.Id, Rating='Prospect');
        // account rating as prospect if  opportunity  = last 3 to 5 years & open opportunity
        else if (open3To5Years>0) accopty = new Account(Id=a.Id, Rating='Prospect');
    }

    update accopty;
 
}

global void finish(Database.BatchableContext bc){
}

}

 

All Answers

Bryan Leaman 6Bryan Leaman 6
How about something like this? At least written this way might be a little clearer to see if I understood the requirements properly:
global class AccountOptyBatchclass implements  Database.Batchable<sObject>  {

global  Database.QueryLocator start(Database.BatchableContext bc) {
    string query='select ID,Name,Rating,(select Id,AccountId,stageName,CloseDate From Opportunities) from Account';
    return Database.getQueryLocator(query);
}

global Void execute(Database.BatchableContext bc, List<Account> Scope){
    list<Account> accopty = new list<account>();
    system.debug('query'+scope);
    Date twoYearsAgo = Date.today().addDays(-730);
    Date fiveYearsAgo = Date.today().addDays(-1825);
    Set<String> closedStage = new Set<String>{
         'Won-Work In Progress', 'Closed Won', 'Delivered'
    };
    Set<String> openStage = new Set<String>{
        'Shaping', 'Proposal Submitted', 'Decision', 'Engagement'
    };
    for(Account a :Scope){

        Integer closedLast2Years = 0;
        Integer openLast2Years = 0;
        Integer open3To5Years = 0;
        for(Opportunity o: a.Opportunities) {
            if (closedStage.contains(o.StageName) {
                if (o.CloseDate>=twoYearsAgo) closedLast2Years++;
            }
            if (openStage.contains(o.StageName) {
                if (o.CloseDate>=twoYearsAgo) openLast2Years++;
                if (o.CloseDate>=fiveYearsAgo && o.CloseDate<twoYearsAgo) open3To5Years++;
            } 
        }

        // account rating as client customer if opportunity = last 2 years & closed opportunity
        if (closedLast2Years>0) accopty = new Account(Id=a.Id, Rating='Client');
        // for last 2 years if  account have two opportunity and both are open it should get update as prospect
        else if (openLast2Years==2) accopty = new Account(Id=a.Id, Rating='Prospect');
        // account rating as prospect if  opportunity  = last 3 to 5 years & open opportunity
        else if (open3To5Years>0) accopty = new Account(Id=a.Id, Rating='Prospect');
    }

    update accopty;
 
}

global void finish(Database.BatchableContext bc){
}

}

 
suji srinivasansuji srinivasan
Thank you for your response Bryan Leaman . I was able to achieve the scenarios as you suggested. but unable to meet the following criteria. accounts which have two opportunities one as open and another as closed and its updating it as prospect . *if it has one open opportunity for last 2 years and another opportunity as closed it should get update as client customer .* *how to achieve this?* *Thanks in Advance*
Bryan Leaman 6Bryan Leaman 6
Ahh, I see -- it's not just the closed opportunity that has to be within 2 years, then? That's part of what wasn't clear to me from your description & code. A small adjustment should handle this:
global class AccountOptyBatchclass implements  Database.Batchable<sObject>  {

global  Database.QueryLocator start(Database.BatchableContext bc) {
    string query='select ID,Name,Rating,(select Id,AccountId,stageName,CloseDate From Opportunities) from Account';
    return Database.getQueryLocator(query);
}

global Void execute(Database.BatchableContext bc, List<Account> Scope){
    list<Account> accopty = new list<account>();
    system.debug('query'+scope);
    Date twoYearsAgo = Date.today().addDays(-730);
    Date fiveYearsAgo = Date.today().addDays(-1825);
    Set<String> closedStage = new Set<String>{
         'Won-Work In Progress', 'Closed Won', 'Delivered'
    };
    Set<String> openStage = new Set<String>{
        'Shaping', 'Proposal Submitted', 'Decision', 'Engagement'
    };
    for(Account a :Scope){
        Integer numberClosed = 0;                // new line
        Integer closedLast2Years = 0;
        Integer openLast2Years = 0;
        Integer open3To5Years = 0;
        for(Opportunity o: a.Opportunities) {
            if (closedStage.contains(o.StageName) {
                ++numberClosed;                 // new line
                if (o.CloseDate>=twoYearsAgo) closedLast2Years++;
            }
            if (openStage.contains(o.StageName) {
                if (o.CloseDate>=twoYearsAgo) openLast2Years++;
                if (o.CloseDate>=fiveYearsAgo && o.CloseDate<twoYearsAgo) open3To5Years++;
            } 
        }

        // new condition - if any open w/in last 2 years and any closed, they are a client
        if (openLast2Years>0 && numberClosed>0) accopt = new Account(Id=a.Id, Rating='Client');
        
        // account rating as client customer if opportunity = last 2 years & closed opportunity
        else if (closedLast2Years>0) accopty = new Account(Id=a.Id, Rating='Client');
        // for last 2 years if  account have two opportunity and both are open it should get update as prospect
        else if (openLast2Years==2) accopty = new Account(Id=a.Id, Rating='Prospect');
        // account rating as prospect if  opportunity  = last 3 to 5 years & open opportunity
        else if (open3To5Years>0) accopty = new Account(Id=a.Id, Rating='Prospect');
    }

    update accopty;
 
}

global void finish(Database.BatchableContext bc){
}

}

 
This was selected as the best answer