+ Start a Discussion
Bertrand DBBertrand DB 

Multiplication for Roll-Up Summary Field

Hello,
I have a custom object called "Line Item", that has a master-detail relationship on Opportunity.
On an opportunity, I can have multiple "Line items". Each line item has a value.

I would like to multiply these values, and get the result in a field on opportunity.

Example:
"My opportunity":
  • Line item 1: 2
  • Line item 2: 10
  • Line item 3: 2

Field "my multiplication" on "My opportunity": 2*10*2=40

What I'm trying to achieve is actually a custom field with a field type "Roll up summary", but Salesforce only allows to calcualte Min, Max, Count, Sum...

Any ideas how I can achieve this?

Best Answer chosen by Bertrand DB
RamakantRamakant
Hi Bertrand,

This functionality is not possible with RollUpSummary fields. We need to do this using triggers:
Trigger updateChildsOnParentDelete on OpportunityLineItem(After Insert, After Update, After Delete, After UnDelete){
    
    List<ID> opportunityIds = New List<ID>();
	List<ID> OpportunityLineItemIds = New List<ID>();
    
    If(Trigger.IsInsert || Trigger.IsUpdate || Trigger.IsUnDelete){
        For(OpportunityLineItem oli: Trigger.New){
            if(oli.OpportunityId  != null){
                opportunityIds.add(oli.OpportunityId);
				OpportunityLineItemIds.add(oli.Id);
            }  
        }
    }
    If(Trigger.IsDelete){
        For(OpportunityLineItem con: Trigger.Old){
            opportunityIds.add(con.OpportunityId);
			OpportunityLineItemIds.add(con.Id);
        }
    }
     
    List<opportunity> opportunityListToUPdate = New List<opportunity>();
    Decimal RollupAmount = 1;
    For(Opportunity opt: [Select Id, RollUpAmount__c, (Select ID, TotalPrice FROM OpportunityLineItems) FROM Opportunity WHERE ID = :opportunityIds]){
		for(OpportunityLineItem con:opt.OpportunityLineItems){
			//act.Con_names__c  = con.FirstName +' '+ con.LastName +',';
			RollupAmount = RollupAmount * con.TotalPrice;
		}
		opt.RollUpAmount__c = RollupAmount;
		opportunityListToUPdate.add(opt);
    }
     
     
    try{
        Update opportunityListToUPdate;
    }
     Catch(Exception E){
        System.Debug('Error Message: ' + e.getMessage());
    }
}

Please mark as best answe.

Regards,
Ramakant​
 

All Answers

Aamir KhanAamir Khan
Aloha,

Please follow the below code:
trigger RollUpSummaryTrigger on Contact (after insert, after update, after delete, after undelete) {
    
    Set<Id> accSet = new Set<Id>();
    for(Contact c : Trigger.new){
        accSet.add(c.AccountId);
    }
        
    Map<Id,Account> accMap = new Map<Id,Account> ();
    
    for(Account acc : [SELECT id, Total_Salary__c FROM Account WHERE id IN :accSet]){
        accMap.put(acc.ID,acc);
    }

    for(Contact con : Trigger.new){
		if(accMap.get(con.AccountId).Total_Amount__c >0 )
        accMap.get(con.AccountId).Total_Amount__c = accMap.get(con.AccountId).Total_Amount__c * con.Amount__c;    
	}
    upsert accmap.values();
}

Hope this helps.

Please mark Solved if it works.

Mahalo,
Aamir AH Khan
Lead Salesforce Lightning Developer 
RamakantRamakant
Hi Bertrand,

This functionality is not possible with RollUpSummary fields. We need to do this using triggers:
Trigger updateChildsOnParentDelete on OpportunityLineItem(After Insert, After Update, After Delete, After UnDelete){
    
    List<ID> opportunityIds = New List<ID>();
	List<ID> OpportunityLineItemIds = New List<ID>();
    
    If(Trigger.IsInsert || Trigger.IsUpdate || Trigger.IsUnDelete){
        For(OpportunityLineItem oli: Trigger.New){
            if(oli.OpportunityId  != null){
                opportunityIds.add(oli.OpportunityId);
				OpportunityLineItemIds.add(oli.Id);
            }  
        }
    }
    If(Trigger.IsDelete){
        For(OpportunityLineItem con: Trigger.Old){
            opportunityIds.add(con.OpportunityId);
			OpportunityLineItemIds.add(con.Id);
        }
    }
     
    List<opportunity> opportunityListToUPdate = New List<opportunity>();
    Decimal RollupAmount = 1;
    For(Opportunity opt: [Select Id, RollUpAmount__c, (Select ID, TotalPrice FROM OpportunityLineItems) FROM Opportunity WHERE ID = :opportunityIds]){
		for(OpportunityLineItem con:opt.OpportunityLineItems){
			//act.Con_names__c  = con.FirstName +' '+ con.LastName +',';
			RollupAmount = RollupAmount * con.TotalPrice;
		}
		opt.RollUpAmount__c = RollupAmount;
		opportunityListToUPdate.add(opt);
    }
     
     
    try{
        Update opportunityListToUPdate;
    }
     Catch(Exception E){
        System.Debug('Error Message: ' + e.getMessage());
    }
}

Please mark as best answe.

Regards,
Ramakant​
 
This was selected as the best answer
Sarath AddankiSarath Addanki
@Bertrand Deglaire 4: Implement triggers like @Aamir suggested. But @Aamir solution doesn't take care of syncing values when line's get deleted. So, take care of that too.

Thanks,
Sarath
Bertrand DBBertrand DB
Hello all,
Thank you for your apex suggestions.

I took the one of @Ramakant, as it takes into account deleted lines.

I customized it as it's a little bit different with a custom object, in my case "Line_items__c". In this example, I update Number_of_beneficiaries__c on Opportunity:
Trigger updateField on Line_items__c(After Insert, After Update, After Delete, After UnDelete){
    
    List<ID> opportunityIds = New List<ID>();
    List<ID> mylistIds = New List<ID>();
    
    If(Trigger.IsInsert || Trigger.IsUpdate || Trigger.IsUnDelete){
        For(Line_items__c oli: Trigger.New){
            if(oli.Opportunity__c  != null){
                opportunityIds.add(oli.Opportunity__c);
                mylistIds.add(oli.Id);
            }  
        }
    }
    If(Trigger.IsDelete){
        For(Line_items__c con: Trigger.Old){
            opportunityIds.add(con.Opportunity__c);
            mylistIds.add(con.Id);
        }
    }
     
    List<opportunity> opportunityListToUPdate = New List<opportunity>();
    Decimal RollupAmount = 1;
    For(Opportunity opt: [Select Id, Number_of_beneficiaries__c, (Select ID, Quantity__c FROM Line_items__r WHERE Unit__c='€' AND Calculation__c=true) FROM Opportunity WHERE ID = :opportunityIds]){
        for(Line_items__c con:opt.Line_items__r){
            //act.Con_names__c  = con.FirstName +' '+ con.LastName +',';
            RollupAmount = RollupAmount * con.Quantity__c;
        }
        opt.Number_of_beneficiaries__c = RollupAmount;
        opportunityListToUPdate.add(opt);
    }
     
     
    try{
        Update opportunityListToUPdate;
    }
     Catch(Exception E){
        System.Debug('Error Message: ' + e.getMessage());
    }
}

 
Sarath AddankiSarath Addanki
Hi Bertrand, 

Move the below line from Line 22 to Line 24. RollupAmount variable needs to be re-initialized in outer for loop.
Decimal RollupAmount = 1;

 
Bertrand DBBertrand DB
Hello Sarath,
You mean before the for loop?

I'm not sure this makes a difference, it still works the same in both case.