0

I'm trying to compare dates of old contracts and new contracts (trigger.new) from the same account, the new contracts are imported and are from a lot of different accounts. But the performance of it has to be better. So I was thinking to do a map of old contracts that compare by the AccountId and not iterate all contracts every time. Below is my code so far. Is it possible to do it using a map, maybe like Map <Id, List<Contract>> ? And how I iterate over a map like this one?

public class NewContracts {

public static void comparingContracts(List<Contract> newContracts){

    Set<String> setAccounts = new set<String>();
    list<Contract> oldContracts = new list<Contract>();


    for (Contract c: newContracts){
        setAccounts.add(c.AccountId);
    } 

    oldContracts = [SELECT AccountId, EndDate, RecordTypeId FROM Contract WHERE AccountId in :setAccounts];

    for(Contract oCon: oldContracts){

        for(Contract nCon: newContracts){                            
            if (oCon.AccountId == nCon.AccountId ){
                nCon.checkTest__c= compareDate(oCon.EndDate, nCon.StartDate);   
            }               
        }  
    }  
}

}

1 Answer 1

1

Yes, you can do that. It requires a three step process that I call the Aggregate Query Update pattern.

public static void comparingContracts(List<Contract> newContracts) {
    Map<Id, Contract[]> oldContracts = new Map<Id, Contract[]>();
    // Aggregate
    for(Contract record: newContracts) {
        oldContracts.put(record.AccountId, new Contract[0]);
    }
    // Query 
    for(Contract record: [SELECT AccountId, EndDate, RecordTypeId FROM Contract WHERE AccountId in :oldContracts.keySet()]) {
        oldContracts.get(record.AccountId).add(record);
    }
    // Update
    for(Contract record: newContracts) {
        for(Contract oldRecord: oldContracts.get(record.AccountId)) {
            record.CheckTest__c = compareDate(oldRecord.EndDate, record.StartDate);
        }
    }
}
5
  • Thank you so much, it helps me a lot.
    – user82245
    Apr 26, 2020 at 0:43
  • But in case I have to compare among the new contracts of the same account too. Let's suppose the list of new contracts have 3 contracts of the same account and between two of them return true from compareDate function. In that case I can accomplish it just adding a third For loop after the second For from Update? That will make my code very slow right? Thanks again for the help dude.
    – user82245
    Apr 26, 2020 at 0:59
  • @AliasX I don't think you should have a problem with it. The main problem you want to avoid are exponential loops, where looping over, for example, 200 x 200 records results in 40,000 iterations.
    – sfdcfox
    Apr 26, 2020 at 1:17
  • That's exactly what I'm worried about. Maybe I'll have 2.000 records at once. I know that trigger will process 200 at time but will happen what you just said, 200 x 200 (not counting the iteration with old contracts).
    – user82245
    Apr 26, 2020 at 1:36
  • @AliasX If you want, I can review the final product, but as long as you're not looping over one large list within another large list, you'll be fine.
    – sfdcfox
    Apr 26, 2020 at 1:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy