1

I currently have an object called Opportunities__c with a child object related to it, Opportunities_Forecast__c via a Master-Detail relationship. The Forecast__c object contains two number fields that ultimately get summed up using a Roll-Up Summary field on the Opportunities__c object.

The nature of the object needs to change now in that Opportunities_Forecast__c is just a general forecasting object and could be related to the Account object or Opportunities__c object, thus it may not always have a relationship to an Opportunity__c record. I know Master-Detail fields are required on child objects, so I have to change the data type to a Lookup.

I can't do this (yet) because of the Roll-Up summary fields. So, I was wondering what the best way to handle the functionality of Roll-Up summary fields, without them being Roll-Up summary fields.

One idea I had was to use a Trigger that would check for Create, Update and Delete events and recalculate the fields accordingly, but I was wondering if there was a better way to do this.

  • Write Apex Trigger to calculate the summed up value. The trigger context will be on insert, update and delete. – RCS Jan 11 '17 at 11:00
  • @RCS This is an idea I already had, although I'm curious to know if there's a better way of doing it rather than just throwing Apex at it I suppose. – Dan Jones Jan 11 '17 at 11:01
  • Unfortunately the only way to do this would be using a trigger as you've anticipated. I would strongly recommend using a lib like this: github.com/abhinavguptas/Salesforce-Lookup-Rollup-Summaries so you don't have to build it all by yourself. – 0ff Jan 11 '17 at 11:03
4

The standard go-to answer is to use Andrew Fawcett's excellent Declarative Rollup Summary package. There's a managed package install link, and it comes complete with a UI for configuring your desired rollups. It works on any object that supports custom fields and triggers, so give it a go! Also, it's open source, so you can borrow bits and pieces if you decide to give it a go yourself. Finally, this has definitely been answered here on SFSE before, including an answer of my own. The actual implementation is pretty trivial when you get down to it, but you do need to pay attention to the details.

  • Thanks for this, looks like I'm writing a Trigger! I'd prefer that to installing a package. @RobCowell I wanted to avoid using Apex Triggers, although I'd prefer to write Apex than install a managed package by preference. I think Mr. Fox is alluding to questions around writing an Apex Trigger for this functionality, whereas this is asking if there's declarative workarounds, which there is, but not quite what I was hoping for. :) – Dan Jones Jan 11 '17 at 11:08
  • 1
    @DanJones Yes, unfortunately triggers is the only option. The newer features like Process Builder don't work on deletes, so they can't keep your data in sync. If you absolutely need correct data, you absolutely need a trigger. – sfdcfox Jan 11 '17 at 11:10
  • @sfdcfox That's perfectly fine and I'm comfortable with writing that. My mentality here is 90% Clicks before Code, 10% laziness. ;D – Dan Jones Jan 11 '17 at 11:13
0

You are right, a trigger is the best Solution.

You will need to have a trigger that maps and groups all children by parent. So you can iterate across the parents children. Not tested Psuedo Code:

trigger(After Insert/Update){
    map<id, list<child>> parentChild_Map = new map<id, list<child>>();
    map<id,parent> parent_Map = new map<id,parent>();
    set<id> parent_Set = new set<id>();
    set<id> parent_Set2 = new set<id>();

    for(children c : trigger.new){
        parent_Set.add(c.parentId);
    }
    parent_Map = [SELECT id, sum__c FROM Parent WHERE Id IN parent_Set];
    children_List = [SELECT id, parentid, value__c FROM child WHERE parentId IN parent_Set];

    for(child c : children_List){
        if(parent_Set2.contains(c.parentId)) {
           parent_map.get(p.ParentId).sum__c = parent_map.get(p.ParentId).sum__c + c.value__c;
        else{
           parent_Set2.add(c.ParentId);
           parent_map.get(c.ParentId).sum__c = c.value__c;
        }
    }

    update parent_map.values();
}

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.