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
Mounika VarmaMounika Varma 

Hi Everyone, I have Created a field called Total Amount on Account and I need to Populate the Total Amount on Account with the sum of the opportunity amounts for all the opportunities for that account Using Batch class

I have tried this  below  code its not working 
someone please help me writing the batch class and test class for this scenerio

global class batchclass implements Database.Batchable<sObject>,Database.Stateful{
    global Decimal sum;
     /* Batch class constructor */
    global batchclass(){}
    //Start method
    global Database.QueryLocator start(Database.BatchableContext BC)
    {
        String query='SELECT id, Amount from Opportunity';
         return Database.getQueryLocator(query);
        }

    //Excute method
    
global void execute(Database.BatchableContext BC, List<Opportunity> scope)
{
    //Excution logic
    //List<Opportunity> opp= new List<Opportunities>();
    AggregateResult[] gr= [SELECT SUM(Amount) optyamt FROM Opportunity];
    
    for(AggregateResult ag:gr){
        sum = (Decimal)ag.get('optyamt');
    }
    
}
      global void finish(Database.BatchableContext BC){
            // Finish logic
          system.debug(''+sum); 
       }
}
Lukesh KarmoreLukesh Karmore
hii  Mounika Varma
i write trigger on above scneario Try it works and mark the best answer so it helps other.

handler:

public with sharing class CountOpportunityAmountt {
public void AfterinsertOpp(list<opportunity> newopp,list<opportunity> oldopp, map<Id,opportunity> NewMapOpp,map<Id,opportunity> OldMapopp){
    set<Id> accountIds=new set<Id>();
    for(opportunity o:newopp){
        accountIds.add(o.accountId);
    }
    updateAmt(accountIds);
}
public void AfterUndeletetOpp(list<opportunity> newopp,list<opportunity> oldopp, map<Id,opportunity> NewMapOpp,map<Id,opportunity> OldMapopp){
    set<Id> accountIds=new set<Id>();
    for(opportunity o:newopp){
        accountIds.add(o.accountId);
    }
    updateAmt(accountIds);
}
public void AfterUpdateOpp(list<opportunity> newopp,list<opportunity> oldopp, map<Id,opportunity> NewMapOpp,map<Id,opportunity> OldMapopp){
    set<Id> accountIds=new set<Id>();
    for(opportunity o:newopp){
        if(o.amount !=OldMapopp.get(o.Id).amount){
        accountIds.add(o.accountId);
        
    }
    accountIds.add(OldMapopp.get(o.Id).accountId);
}
    updateAmt(accountIds);
}
public void AfterDeleteOpp(list<opportunity> newopp,list<opportunity> oldopp, map<Id,opportunity> NewMapOpp,map<Id,opportunity> OldMapopp){
    set<Id> accountIds=new set<Id>();
    for(opportunity o:Oldopp){
        accountIds.add(o.accountId);
    }
    updateAmt(accountIds);
}
public static void updateAmt(set<Id> accountIds){
    if(accountIds.size()>0){
    decimal sum=0;
        list<account> acclist=[select id,total_opportunity_amount__c,(select amount from Opportunities) from account where id IN:accountIds];
    if(acclist.size()>0){
        for(Account a:acclist){
            for(opportunity o:a.Opportunities){
            sum=sum+o.amount;
        }
        a.total_opportunity_amount__c=sum;
    }
        Update acclist;
    }
   
}
}
}
trigger:

trigger Question16 on opportunity (after insert,after update,after delete,after Undelete ) {
    CountOpportunityAmountt  handler=new CountOpportunityAmountt();
    if(Trigger.isInsert){
    handler.AfterinsertOpp(Trigger.new,Trigger.old,Trigger.NewMap,Trigger.OldMap);
}
 else if(Trigger.isUndelete){
    handler.AfterUpdateOpp(Trigger.new,Trigger.old,Trigger.NewMap,Trigger.OldMap);
}
else if(Trigger.isUpdate){
    handler.AfterdeleteOpp(Trigger.new,Trigger.old,Trigger.NewMap,Trigger.OldMap);
}
else if(Trigger.isdelete){
    handler.AfterundeleteOpp(Trigger.new,Trigger.old,Trigger.NewMap,Trigger.OldMap);
}
}
Thanks
ShekarMSShekarMS
Couple of changes
1. Change the scope query to query the account Ids 
2. Change the Aggregate query in execute method  like this
AggregateResult[] gr= [SELECT AccountId,SUM(Amount) optyamt FROM Opportunity where accountId in : scopeIdList group by accountId ];
then loop through the aggregate results and update account.
Mounika VarmaMounika Varma
Hi ShekarMS
thank you so much 
can i get test class for it 
CharuDuttCharuDutt
HII Mounika
Try Below Test Class
@istest
Public class batchclassTest{
@istest
Public static void UnitTest() {
List<opportunity> lstOpp = new list<opportunity>() ;
Account acc =new Account() ;
Acc.Name='test Account' ;
/*fill all necessary fields*/
Insert acc;

For(integer i=0;i<5;i++){
Opportunity opp=new opportunity () ;
Opp.Name ='test opp' +i;
Opp.Stage='closed won' ;
​​​Opp.AccountId= acc.Id;
Opp.ClosedDate=system.today();
Opp.Amount=1000+i;
​​​​​​lsrOpp. Add(opp) ;
​​​​​​} 
Insert lstopp;
Test.startTest();
 /* batchclassname ob = new batchclassname() ;
Database.executeBatch(ob);*/
batchclass obj = new batchclass() ; 
DataBase.executeBatch(obj); 
Test.stopTest(); 
} }
Please Mark It As Best Answer If It Helps 
Thank you  
 
Mounika VarmaMounika Varma
Hi CharuDutt
My batch class is having errors can u please help me with this

global class batchclass implements Database.Batchable<sObject>,Database.Stateful{
    global Decimal sum;
     /* Batch class constructor */
    global batchclass(){}
    //Start method
    global Database.QueryLocator start(Database.BatchableContext BC)
    {
        String query='SELECT id, Amount from Opportunity';
         return Database.getQueryLocator(query);
        }

    //Excute method
    
global void execute(Database.BatchableContext BC, List<Opportunity> scope)
{
    //Excution logic
    //List<Opportunity> opp= new List<Opportunities>();
    AggregateResult[] gr= [SELECT AccountId,SUM(Amount) optyamt FROM Opportunity where accountId in: scopeIdList group by accountId];
    system.debug(gr);
    for(AggregateResult ag:gr){
        sum = (Decimal)ag.get('optyamt');
        system.debug(''+sum);
    }
    
}
      global void finish(Database.BatchableContext BC){
            // Finish logic
          system.debug(''+sum); 
       }
}
Suraj Tripathi 47Suraj Tripathi 47
Hi Mounika,
You have take reference from this below code:-
global class batchclass implements Database.Batchable<sObject>,Database.Stateful{
    
    global Database.QueryLocator start(Database.BatchableContext BC)
    {
        String query='select id,TotalAmount__c from account ';
        return Database.getQueryLocator(query);
    }
    
    global void execute(Database.BatchableContext BC, List<Account> scope)
    {
        
        List<opportunity> oppList=[select id, amount,accountid from Opportunity where accountid IN:scope and amount!=null];
        map<id,decimal> accidVsCountAmount = new map<id,decimal>();
        for(opportunity opp:oppList){
            if(!accidVsCountAmount.containskey(opp.accountid)){
                accidVsCountAmount.put(opp.accountid,opp.amount);
            }
            else{
                decimal count=accidVsCountAmount.get(opp.accountid);
                count=count+opp.amount;
                accidVsCountAmount.put(opp.accountid,count);
            }
        }
        for(account acc: scope){
            if(accidVsCountAmount.containskey(acc.id)){
                acc.TotalAmount__c = accidVsCountAmount.get(acc.id);
            }
        }
        update scope;
    }
    global void finish(Database.BatchableContext BC){
        system.debug('finish'); 
    }
}

In case you find any other issue please mention. 
If you find your Solution then mark this as the best answer. 

 
CharuDuttCharuDutt
Hii Mounika
Try Below Code With Test Class
global class batchclass implements Database.Batchable<sObject>,Database.Stateful{
    
    global Database.QueryLocator start(Database.BatchableContext BC)
    {
        String query='select id,Total_Amount__c from Account ';
        return Database.getQueryLocator(query);
    }
    
    global void execute(Database.BatchableContext BC, List<Account> scope)
    {
        integer i = 0;
        List<Opportunity> lstOpp=[select id,Amount,AccountId from Opportunity where AccountId IN:scope];
       
        for(Opportunity Opp:lstOpp){
            i=i+integer.valueof(Opp.salary__c);
    
        }
        for(Account acc: scope){
           
                acc.Total_Amount__c = integer.valueof(i;
            
        }
        update scope;
    }
    global void finish(Database.BatchableContext BC){
        Id job = bc.getJobId();
    }
}

-------------------------------------------------------------------

Test Class
@isTest
public class BatchClassTest {
  @isTest
  static void setup() {
      account acc = new account() ;
      acc.Name = 'test' ;
      
      insert acc;
        List<Opportunity > lstOpp= new List<Opportunity >();
    for(Integer i=0; i <100; i++) {
        Opportunity Opp = new Opportunity ();
           Opp.Name = 'Test Opp'+i;
            Opp.AccountId = acc.id;
            Opp.Amount= 100+i;
            Opp.StageName = 'Closed Won';
            Opp.CloseDate = System.Today();
            lstOpp.add(Opp );
    }
        insert lstOpp;
    

    

    batchclass lp =new batchclass();
    Id batchId = Database.executeBatch(lp);
    }
}
Please Mark It As Best Answer If It Helps
Thank You!
 
Andrew GAndrew G
Obviously just a test for creating a batch class et al.  

Because out of the box you can just create a Roll Up Summary field on the Account object that summarises values on the Opportunity.

Funny though as a test of skill that we go to the forums and ask others to write our code.

cheers

Andrew