function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
James Sherrard0742540083538499James Sherrard0742540083538499 

Apex rollup code across 2 objects with formula fields

Hi,

I'm trying to implement a rollup summary with apex code but it's only working 95% of the way and takes a human click to finish the process, obviously I would like it to all happen at once. 

I have a custom object called "Participant Accounts" and then the standard object "Contacts". Each participant account under a contact is in fact a single mututal fund. We would like certain aspects of every participant account(mutual fund) to SUM up to the contact. The market value of each participant account SUMs and rollsup to the contact just fine as their total account balance. 

This is where it gets hairy(I think). Based on the summed total balance now on the contact, I made a formula field back under participant account that divides its own market value by the contacts total account balance so that I know what percent that participant account is of the total balance for the contact. I then multiple the new number by 3 fields I have previously set up under participant accounts which are Equity, Fixed Income, or Cash. If a mutual fund(participant account) is 100% equity then 100 goes in equity, 0 in fixed income, and 0 in cash. I think you can see how that goes on. 

At this point I know how much each partipant account(mutual fund) is of the total balance is as well as how much it is of total equity, fixed income, and cash holdings. The equity, fixed income, and cash rollup to the contact as they are supposed to but don't add up correctly initially. It takes me opening any participant account(not changing anything) and just saving for the rollup to then work. 

Is there something simple I'm missing to put into coding to have it update both participant accounts(or contacts?) to have it add correctly the first time around?

I'm extremely new to all of this but it appears that the back and forth formulas are the hang up.. maybe.

Thank you in advance. I have code if needed.

James
Anil KamisettyAnil Kamisetty
James

Any reason why you are using Apex for achieving this?

If I understood correctly, you are playing with the currency fields between two objects which has some relationships. i.e. Contacts is parent and Participant Account is Child object.

1. Salesforce allows you to create Roll up summary fields on the Parent object (thus summarizing the total value from the child objects. If multiple fileds on the child object, add all of them into a single formula field in child and use that for rollup)
2. Once the parent has the roll up summary value, you can use that Parent summary field on the Child object. Create a formula on the Child object and then use the Parent Summary field from the Parent object and do the maths.

I believe what's happening here is Salesforce don't know which one to execute in what order and hence you are facing this error. As mentioned above, you can achieve what you want.

If this doesnot support your need, feel free to elaborate and post back.

Note : If this answers your question, please mark this as Answered, thus helping others.
James Sherrard0742540083538499James Sherrard0742540083538499
Anil

Honestly with semi limited knowledge, Apex seemed like the next progession in solving this. 

I see where you are going with this although I have a question in regards to your first statement.

How would you make the formula to be elastic? As in the participant accounts for any given contact could number anywhere between 1 to 20.

Thanks for your quick reply. 

James
Anil KamisettyAnil Kamisetty
James

I am expecting that Percentage of contibution (Equity / fixed income / cash etc) are stored on the Participant Account.

a. Try creating a separate formula for each type. And in that, calculate the value (Percentage contibution * Account Value / Total Contact Value*100)

As #1 is a formula field, it can't be rolled up automatically onto the Contact Object. Formula is not a supported field to rollup. For that, you have to do little differently.

1. Try to have separate fields on the Contact Obejct to summarize the Individual contibutions (Sum (% contibution * Participant account value). (3 separate fields)
2. As you hvae the Roll up of Total Participant Account Value on Contact already, try to get the % calculated at the Contact Obejct (i.e. #1 / #2 * 100)

Hope this helps.

Note : If this answers your question, please mark this as Answered, thus helping others.
Sagar Nagvekar 20Sagar Nagvekar 20
/*
    Implementing rollup summary field type addition operation between two custom objects which do not have
    master-detail relationship between them. They have lookup relationship between them.
    Parent object = DataStorage (DataStorage__c)
    Child object = Work Life Data (Work_Life_Data__c)
    Field on parent object = work life total (work_life_total__c) [Data type = Number(18, 0)]
    Field on child object = Hours working per month (Hours_working_per_month__c) [Data type = Number(3, 0)]
    Whenever any child record is created/inserted or edited/updated, then the total will get updated on the
    work_life_total__c field of the parent record.
    Below trigger on the child object will add the new value of Hours_working_per_month__c field on the child
    record and subtract the old value of this field (in case of update) and thus the total will reflect
    properly on the work_life_total__c field of the parent record.
    Thus it will be similar to "sum" operation of rollup summary field in case of master-detail
    relationship between two objects.
*/
trigger SendToDataStorage on Work_Life_Data__c (after insert, after update)
{
    // Key = id of DataStorage__c record, value = list of Work_Life_Data__c records
    Map<Id, List<Work_Life_Data__c>> dataStorageMap = new Map<Id, List<Work_Life_Data__c>>();
    
    // Key = id of Work_Life_Data__c record, value = old value in field Hours_working_per_month__c of Work_Life_Data__c record
    Map<Id, Decimal> mapOfOldValues = new Map<Id, Decimal>();
    
    for(Work_Life_Data__c workLifeDataObj : trigger.new)
    {
        if(Trigger.isUpdate)
        {
            Work_Life_Data__c workLifeDataOldObj = Trigger.oldMap.get(workLifeDataObj.Id);
            if(workLifeDataObj.Hours_working_per_month__c != workLifeDataOldObj.Hours_working_per_month__c)
            {
                mapOfOldValues.put(workLifeDataObj.id, workLifeDataOldObj.Hours_working_per_month__c);
            }
        }
        
        if(workLifeDataObj.DataStorage__c != null)
        {
            List<Work_Life_Data__c> workLifeDataLst = dataStorageMap.get(workLifeDataObj.DataStorage__c);
            if(workLifeDataLst == null)
            {
                workLifeDataLst = new List<Work_Life_Data__c>();
                workLifeDataLst.add(workLifeDataObj);
            }
            dataStorageMap.put(workLifeDataObj.DataStorage__c, workLifeDataLst);        
        }
    }
    
    if(dataStorageMap.size() > 0)
    {
        List<DataStorage__c> dataStorageLst =
            [select id, name, work_life_total__c from DataStorage__c where id in :dataStorageMap.keySet()];
            
        // List of DataStorage records to be updated    
        List<DataStorage__c> updateDataStorageLst = new List<DataStorage__c>();
            
        for(DataStorage__c dataStorageObj : dataStorageLst)
        {
            Boolean updateThisDataStorageObj = false;
            List<Work_Life_Data__c> workLifeDataLst = dataStorageMap.get(dataStorageObj.id);
            
            Decimal workLifeTotal = 0;
            for(Work_Life_Data__c workLifeDataObj : workLifeDataLst)
            {
                if(Trigger.isInsert)
                {
                    workLifeTotal = workLifeTotal + workLifeDataObj.Hours_working_per_month__c;
                    updateThisDataStorageObj = true;
                }
                else if (Trigger.isUpdate)
                {
                    Work_Life_Data__c workLifeDataOldObj = Trigger.oldMap.get(workLifeDataObj.Id);
                    if(workLifeDataObj.Hours_working_per_month__c != workLifeDataOldObj.Hours_working_per_month__c)
                    {
                        workLifeTotal = workLifeTotal + workLifeDataObj.Hours_working_per_month__c;
                        
                        if(mapOfOldValues.containsKey(workLifeDataObj.id))
                        {
                            Decimal oldValue = mapOfOldValues.get(workLifeDataObj.id);
                            workLifeTotal = workLifeTotal - oldValue;
                        }
                        updateThisDataStorageObj = true;
                    }
                }
            }
            
            if(updateThisDataStorageObj)
            {
                if(dataStorageObj.work_life_total__c == null)
                {
                    dataStorageObj.work_life_total__c = workLifeTotal;
                }
                else
                {
                    dataStorageObj.work_life_total__c = dataStorageObj.work_life_total__c + workLifeTotal;
                }
                updateDataStorageLst.add(dataStorageObj);    
            }
        }
        
        if(updateDataStorageLst.size() > 0)
        {
            update updateDataStorageLst;
        }
    }
}