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
kamala swarnalathakamala swarnalatha 

Apex class not working on the child object attaching the parent object.

Hi,

Hope someone helps here!

I have written the code to get a count of opportunities on the contract. It works fine when I have add the opportunity under the contract. But it doesn't work on adding the contract through the contract lookup field on an opportunity.

This is the Trigger and Apex class I have written.

Apex Trigger:

trigger OpportunityTrigger on Opportunity (After Insert,After Update,After Delete,After undelete)
{
OppTriggerHandler handler=new OppTriggerHandler();
if(Trigger.isAfter && Trigger.isInsert)
{
handler.afterInsert(Trigger.newMap);
}
if(Trigger.isAfter && Trigger.isDelete)
{
handler.afterdelete(Trigger.oldMap);
}
if(Trigger.isAfter && Trigger.isUndelete)
{
handler.afterUndelete(Trigger.newMap);
}
if(Trigger.isAfter && Trigger.isUpdate)
{
handler.afterUpdate(Trigger.oldMap);
}
}


Apex class:

public class OppTriggerHandler
{
//After insert
public void afterInsert(Map<Id,Opportunity> newMap)
{
//contracts to update
Set<Id> contrIds=new Set<Id>();
//Iterate to get contract Ids
for(Opportunity opp:newMap.Values())
{
//check opportunity have contract Id
if(opp.ContractId!=null)
{
//Adding contract Id to the Set<Id>
contrIds.add(opp.ContractId);
}
}
//call update contract actions
if(contrIds.size()>0)
{
THIS.updateContracts(contrIds);
THIS.updateContracts2(contrIds);
}
}
//After update
public void afterUpdate(Map<Id,Opportunity> oldMap)
{
//contracts to update
Set<Id> contrIds=new Set<Id>();
//Iterate to get contract Ids
for(Opportunity opp:oldMap.Values())
{
//check opportunity have contract Id
if(opp.ContractId!=null)
{
//Adding contract Id to the Set<Id>
contrIds.add(opp.ContractId);
}
}
//call update contract actions
if(contrIds.size()>0)
{
THIS.updateContracts(contrIds);
THIS.updateContracts2(contrIds);
}
}
//After delete
public void afterdelete(Map<Id,Opportunity> oldMap)
{
//contracts to update
Set<Id> contrIds=new Set<Id>();
//Iterate to get contract Ids
for(Opportunity opp:oldMap.Values())
{
//check opportunity have contract Id
if(opp.ContractId!=null)
{
//Adding contract Id to the Set<Id>
contrIds.add(opp.ContractId);
}
}
//call update contract actions
if(contrIds.size()>0)
{
THIS.updateContracts(contrIds);
THIS.updateContracts2(contrIds);
}
}
//After Undelete
public void afterUndelete(Map<Id,Opportunity> newMap)
{
//contracts to update
Set<Id> contrIds=new Set<Id>();
//Iterate to get contract Ids
for(Opportunity opp:newMap.Values())
{
//check opportunity have contract Id
if(opp.ContractId!=null)
{
//Adding contract Id to the Set<Id>
contrIds.add(opp.ContractId);
}
}
//call update contract actions
if(contrIds.size()>0)
{
THIS.updateContracts(contrIds);
THIS.updateContracts2(contrIds);
}
}
//contracts to be updated
private void updateContracts(Set<Id> contrIds)
{
Decimal totalValue = 0;
//getting contract records based on Contract Ids
List<Contract> contrlist=[SELECT Id,Opp_Count__c,Opp_Amount__c,(select Id FROM Opportunities) FROM Contract WHERE Id IN:contrIds];
//Iterating Contracts to update Total opportunities from child on parent query
for(Contract con : contrlist)
{
con.Opp_count__c=con.opportunities.size();
}
if(contrlist.size()>0)
{
update contrlist;
}
}
private void updateContracts2(Set<Id> contrIds)
{
List<Opportunity> oppforContracts = [SELECT Id ,ContractId, Amount FROM Opportunity WHERE ContractId IN :contrIds];

List<Contract> contrsToUpdate = [SELECT Id, Opp_Amount__c FROM Contract WHERE Id IN :contrIds];

for (Contract contr : contrsToUpdate) {
Set<Id> oppIds = new Set<Id>();
Decimal totalValue = 0;
for (Opportunity opp1 : oppforContracts) {
    if (opp1.ContractId == contr.Id && opp1.Amount != NULL) {
        totalValue += opp1.Amount; 
    }
}
contr.Opp_Amount__c = totalValue;
}
if(contrsToUpdate.size() > 0) {
    update contrsToUpdate;
}
}
}

Thanks in Advance!
Kamala Swarnalatha
ANUTEJANUTEJ (Salesforce Developers) 
Hi Kamala,

You can modify the below snippet that counts number of contacts under an account as this is similar to your requirement:
 
trigger ContactTrigger on Contact (after insert, after update, after delete, after undelete) {
    //---> above handling all states which could see a contact added to or removed from an account
   
    //---> on delete we use Trigger.Old, all else, Trigger.new
    List<Contact> contacts = Trigger.isDelete ? Trigger.old : Trigger.new;

    //---> the Set class rocks for finding the unique values in a list
    Set<Id> acctIds = new Set<Id>();
   
    for (Contact c : contacts) {
     //yes, you can have a contact without an account
        if (c.AccountId != null) {
            acctIds.add(c.AccountId);
        }
    }
   
    List<Account> acctsToRollup = new List<Account>();
    
    //****** Here is the Aggregate query...don't count in loops, let the DB do it for you*****
    for (AggregateResult ar : [SELECT AccountId AcctId, Count(id) ContactCount 
                               FROM Contact 
                               WHERE AccountId in: acctIds 
                               GROUP BY AccountId]){
        Account a = new Account();
        a.Id = (Id) ar.get('AcctId'); //---> handy trick for updates, set the id and update
        a.Contact_Count__c = (Integer) ar.get('ContactCount');
        acctsToRollup.add(a);
    }
    
    //----> probably you'll want to do a little more error handling than this...but this should work. 
    update acctsToRollup;

}

reference: https://developer.salesforce.com/forums/?id=906F0000000AcdaIAC

Let me know if it helps you and close your query by marking it as solved so that it can help others in the future.  

Thanks.