The business requirement is to have a lookup relation ship between a Contract and Opportunity. A field on the opportunity must get the SUM of a custom field on the Contracts which belong to the opportunity. I use the @future annotation to increase the CPU time, however, I get an error "Attempt to de-reference a null object".
public class contractRollUpCLASS {
@future
public static void calculate() {
//limit the size of list by using Sets which do not contain duplicate elements.
Set<ID> oppIds = new Set<ID>();
//when adding new or updating existing contracts.
if(trigger.isInsert || trigger.isUpdate) {
for(Contract con : (List<Contract>)trigger.new) {
if(con.Is_Obsolete__c == false)
oppIds.add(con.Renewal_Opportunity__c);
}
}
//when deleting contracts.
if(trigger.isDelete){
for(Contract con : (List<Contract>)trigger.old ) {
if(con.Is_Obsolete__c == false)
oppIds.add(con.Renewal_Opportunity__c);
}
}
System.debug('***************NUMBER OF IDS ************** : '+ String.ValueOf(oppIds.size()));
//Map will contain one Opportunity Id to one sum value.
map<Id, Double> OpportunityMap = new Map<Id,Double>();
List<Opportunity> oppsToUpdate = new List<Opportunity>();
//aggregate result.
for(AggregateResult q : [SELECT Renewal_Opportunity__c, SUM(Latest_PD_Renewal_Amount__c) sumLatest FROM Contract WHERE Renewal_Opportunity__c IN : oppIds AND Latest_PD_Renewal_Amount__c != null GROUP BY Renewal_Opportunity__c]) {
OpportunityMap.put((Id)q.get('Renewal_Opportunity__c'),(Double)q.get('sumLatest'));
}
for(Opportunity opp : [SELECT Id, Annual_Maintenance_Value__c FROM Opportunity WHERE Id IN : oppIds]) {
Double sumLatestPD = OpportunityMap.get(opp.Id);
opp.Annual_Maintenance_Value__c = sumLatestPD;
oppsToUpdate.add(opp);
}
update oppsToUpdate;
}
}
Here's the trigger:
trigger invokeClasses on Contract (after insert, after update, after delete, after undelete) {
contractRollUpCLASS.calculate();
}