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