Skip to main content
added 34 characters in body
Source Link
Keith C
  • 137.3k
  • 29
  • 218
  • 458

On the rollup question only...

This is a case where it is probably worth factoring out the code that does the rollup into a separate class. That then allows the triggers to be fairly simple:

trigger ParentTrigger on Parent__c (before ...) {
    if (change detected) {
        // Trigger objects will be persisted so just copy result
        for (Parent p : ChildRollup.executecalculateParents(Trigger.newMap)) {
            Trigger.newMap.get(p.Id).Sum__c = p.Sum__c;
        }
    }
}

trigger ParentTrigger on Parent__c (after ...) {
    if (change detected) {
        update ChildRollup.executecalculateParents(Trigger.newMap);
    }
}

trigger ChildTrigger on Child__c (...) {
    update ChildRollup.executecalculateParents(Trigger.newMap);
}
public class ChildRollup {
    public static Parent__c[] executecalculateParents(Map<Id, Parent__c> parents) {
        return executecalculateParents(parents.keySet());
    }
    public static Parent__c[] executecalculateParents(Map<Id, Child__c> children) {
        Set<Id> parentIds = new Set<Id>();
        for (Child__c c : children.values()) {
            parentIds.add(c.Parent__c);
        }
        return executecalculateParents(parentIds);
    }
    private static Parent__c[] executecalculateParents(Set<Id> parentIds) {
        Map<Id, Parent__c> parents = new Map<Id, Parent__c>();
        for (Id parentId : parentIds) {
            parents.put(parentId, new Parent__c(Id = parentId, Sum__c = 0.00));
        }
        for (AggregateResult ar : [
                select Parent__c p, sum(Value__c) s
                from Child__c
                where Parent_c in :parentIds
                group by Parent__c
                ]) {
            parents.get((Id) ar.get('p')).Sum__c += (Decimal) ar.get('s');
        }
        return parents.values();
    }
}

This is a case where it is probably worth factoring out the code that does the rollup into a separate class. That then allows the triggers to be fairly simple:

trigger ParentTrigger on Parent__c (before ...) {
    if (change detected) {
        // Trigger objects will be persisted so just copy result
        for (Parent p : ChildRollup.execute(Trigger.newMap)) {
            Trigger.newMap.get(p.Id).Sum__c = p.Sum__c;
        }
    }
}

trigger ParentTrigger on Parent__c (after ...) {
    if (change detected) {
        update ChildRollup.execute(Trigger.newMap);
    }
}

trigger ChildTrigger on Child__c (...) {
    update ChildRollup.execute(Trigger.newMap);
}
public class ChildRollup {
    public static Parent__c[] execute(Map<Id, Parent__c> parents) {
        return execute(parents.keySet());
    }
    public static Parent__c[] execute(Map<Id, Child__c> children) {
        Set<Id> parentIds = new Set<Id>();
        for (Child__c c : children.values()) {
            parentIds.add(c.Parent__c);
        }
        return execute(parentIds);
    }
    private static Parent__c[] execute(Set<Id> parentIds) {
        Map<Id, Parent__c> parents = new Map<Id, Parent__c>();
        for (Id parentId : parentIds) {
            parents.put(parentId, new Parent__c(Id = parentId, Sum__c = 0.00));
        }
        for (AggregateResult ar : [
                select Parent__c p, sum(Value__c) s
                from Child__c
                where Parent_c in :parentIds
                group by Parent__c
                ]) {
            parents.get((Id) ar.get('p')).Sum__c += (Decimal) ar.get('s');
        }
        return parents.values();
    }
}

On the rollup question only...

This is a case where it is probably worth factoring out the code that does the rollup into a separate class. That then allows the triggers to be fairly simple:

trigger ParentTrigger on Parent__c (before ...) {
    if (change detected) {
        // Trigger objects will be persisted so just copy result
        for (Parent p : ChildRollup.calculateParents(Trigger.newMap)) {
            Trigger.newMap.get(p.Id).Sum__c = p.Sum__c;
        }
    }
}

trigger ParentTrigger on Parent__c (after ...) {
    if (change detected) {
        update ChildRollup.calculateParents(Trigger.newMap);
    }
}

trigger ChildTrigger on Child__c (...) {
    update ChildRollup.calculateParents(Trigger.newMap);
}
public class ChildRollup {
    public static Parent__c[] calculateParents(Map<Id, Parent__c> parents) {
        return calculateParents(parents.keySet());
    }
    public static Parent__c[] calculateParents(Map<Id, Child__c> children) {
        Set<Id> parentIds = new Set<Id>();
        for (Child__c c : children.values()) {
            parentIds.add(c.Parent__c);
        }
        return calculateParents(parentIds);
    }
    private static Parent__c[] calculateParents(Set<Id> parentIds) {
        Map<Id, Parent__c> parents = new Map<Id, Parent__c>();
        for (Id parentId : parentIds) {
            parents.put(parentId, new Parent__c(Id = parentId, Sum__c = 0.00));
        }
        for (AggregateResult ar : [
                select Parent__c p, sum(Value__c) s
                from Child__c
                where Parent_c in :parentIds
                group by Parent__c
                ]) {
            parents.get((Id) ar.get('p')).Sum__c += (Decimal) ar.get('s');
        }
        return parents.values();
    }
}
Source Link
Keith C
  • 137.3k
  • 29
  • 218
  • 458

This is a case where it is probably worth factoring out the code that does the rollup into a separate class. That then allows the triggers to be fairly simple:

trigger ParentTrigger on Parent__c (before ...) {
    if (change detected) {
        // Trigger objects will be persisted so just copy result
        for (Parent p : ChildRollup.execute(Trigger.newMap)) {
            Trigger.newMap.get(p.Id).Sum__c = p.Sum__c;
        }
    }
}

trigger ParentTrigger on Parent__c (after ...) {
    if (change detected) {
        update ChildRollup.execute(Trigger.newMap);
    }
}

trigger ChildTrigger on Child__c (...) {
    update ChildRollup.execute(Trigger.newMap);
}

and sharing most of the code:

public class ChildRollup {
    public static Parent__c[] execute(Map<Id, Parent__c> parents) {
        return execute(parents.keySet());
    }
    public static Parent__c[] execute(Map<Id, Child__c> children) {
        Set<Id> parentIds = new Set<Id>();
        for (Child__c c : children.values()) {
            parentIds.add(c.Parent__c);
        }
        return execute(parentIds);
    }
    private static Parent__c[] execute(Set<Id> parentIds) {
        Map<Id, Parent__c> parents = new Map<Id, Parent__c>();
        for (Id parentId : parentIds) {
            parents.put(parentId, new Parent__c(Id = parentId, Sum__c = 0.00));
        }
        for (AggregateResult ar : [
                select Parent__c p, sum(Value__c) s
                from Child__c
                where Parent_c in :parentIds
                group by Parent__c
                ]) {
            parents.get((Id) ar.get('p')).Sum__c += (Decimal) ar.get('s');
        }
        return parents.values();
    }
}