[SalesForce] Need to fire trigger on child objects when parent object is updated

I have a 1-to-many relationship using a lookup. I have a trigger that does a rollup on the parent object. So, anytime a child record is inserted, updated or deleted, the trigger fires and updates the master with the new rollup total. It works perfectly. However, there is a field on the parent object that if changed, needs to re-run the rollup of the child objects. What is the best approach to do this?

Also, I have another issue with a master-detail relationship, that the master record being deleted does not fire the child records delete via a cascade delete? How can I get the trigger to fire on the child object when the master is deleted?

Thanks for any help.

Best Answer

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);
}

and sharing most of the code:

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();
    }
}