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
Nathan Prats 22Nathan Prats 22 

Apex Rollup summary

Hi, 

I'm trying to update a field named Primary Partner Gross Margin on the opportunity object based on opportunity line items. 
The code compiles, but it doesn't update the field on update. Any idea why ? 
trigger OpportunityTriggers on Opportunity (before update) {
    
    // Quand 1 Opp a un Primary Partner Account Reseller, remplir le champs "Primary Partner Gross Margin" = Sum OpportunityLineItems Software  * Primary_Partner_Margin__c
    // C'est forcément before car on a besoin d'update des records, et quand on est en after, les records sont lock
    
    // Prendre la liste des opportunités pour lesquelles on va peupler Primary_Partner_Gross_Margin__c
    For (Opportunity opp : [SELECT Id,Primary_Partner_Gross_Margin__c,Primary_Partner_Margin__c 
                            FROM Opportunity
                            WHERE Primary_Partner_Role__c ='Reseller'
                            AND Deal_with_a_partner__c = 'Yes'
                            AND Id IN :Trigger.old
                           ]) {
                               
                               // Updater le champs Primary_Partner_Gross_Margin__c
                               Double GrossMargin = [SELECT TotalPrice 
                                                      FROM OpportunityLineItem
                                                      WHERE PricebookEntry.product2.Family='Software'
                                                      AND  OpportunityId =: opp.Id ][0].TotalPrice;
                               
                               
                               opp.Primary_Partner_Gross_Margin__c=GrossMargin*opp.Primary_Partner_Margin__c;
                               opp.Name = 'Worked';
                               
                           }
}

 
Best Answer chosen by Nathan Prats 22
balaji Jayararmanbalaji Jayararman
Hi Nathan,

Please write a trigger on opportunity line items. Here's the code you are looking for
trigger OpportunityTriggers on OpportunityLineItem (after insert, after update) {

	// Quand 1 Opp a un Primary Partner Account Reseller, remplir le champs "Primary Partner Gross Margin" = Sum OpportunityLineItems Software  * Primary_Partner_Margin__c
	// C'est forcément before car on a besoin d'update des records, et quand on est en after, les records sont lock

	// Prendre la liste des opportunités pour lesquelles on va peupler Primary_Partner_Gross_Margin__c
	Set<Id> oppIdSet = new Set<Id>();
	for (OpportunityLineItem oppLineItem : Trigger.new) {
		if (opp.OpportunityId != null) {
			oppIdSet.add(opp.OpportunityId);
		}
	}
	if (oppIdSet.isEmpty()) {
		return;
	}
	Map<Id, Opportunity> oppUpdateMap = new Map<Id, Opportunity>();
	for (Opportunity opp : [
		SELECT
			Primary_Partner_Margin__c,
			(SELECT
				TotalPrice 
			FROM
				OpportunityLineItems
			WHERE
				PricebookEntry.product2.Family = 'Software')
		FROM
			Opportunity
		WHERE
			Id IN :oppIdSet AND
			Primary_Partner_Role__c = 'Reseller' AND
			Deal_with_a_partner__c = 'Yes'
	]) {
		Double grossMargin = 0;
		for (OpportunityLineItems oppLineItems : opp.OpportunityLineItems) {
			grossMargin += oppLineItems.TotalPrice;
		}
		opp.Primary_Partner_Gross_Margin__c = grossMargin * opp.Primary_Partner_Margin__c;
		opp.Name = 'Worked';
		oppUpdateMap.put(opp.Id, opp);
	}
	if (!oppUpdateMap.isEmpty()) {
		update oppUpdateMap.values();
	}
}

Hope it solves your problem.

Please mark this as best answer if it solves.

Thanks,
Balaji J 

All Answers

balaji Jayararmanbalaji Jayararman
Hi Nathan,

Please write a trigger on opportunity line items. Here's the code you are looking for
trigger OpportunityTriggers on OpportunityLineItem (after insert, after update) {

	// Quand 1 Opp a un Primary Partner Account Reseller, remplir le champs "Primary Partner Gross Margin" = Sum OpportunityLineItems Software  * Primary_Partner_Margin__c
	// C'est forcément before car on a besoin d'update des records, et quand on est en after, les records sont lock

	// Prendre la liste des opportunités pour lesquelles on va peupler Primary_Partner_Gross_Margin__c
	Set<Id> oppIdSet = new Set<Id>();
	for (OpportunityLineItem oppLineItem : Trigger.new) {
		if (opp.OpportunityId != null) {
			oppIdSet.add(opp.OpportunityId);
		}
	}
	if (oppIdSet.isEmpty()) {
		return;
	}
	Map<Id, Opportunity> oppUpdateMap = new Map<Id, Opportunity>();
	for (Opportunity opp : [
		SELECT
			Primary_Partner_Margin__c,
			(SELECT
				TotalPrice 
			FROM
				OpportunityLineItems
			WHERE
				PricebookEntry.product2.Family = 'Software')
		FROM
			Opportunity
		WHERE
			Id IN :oppIdSet AND
			Primary_Partner_Role__c = 'Reseller' AND
			Deal_with_a_partner__c = 'Yes'
	]) {
		Double grossMargin = 0;
		for (OpportunityLineItems oppLineItems : opp.OpportunityLineItems) {
			grossMargin += oppLineItems.TotalPrice;
		}
		opp.Primary_Partner_Gross_Margin__c = grossMargin * opp.Primary_Partner_Margin__c;
		opp.Name = 'Worked';
		oppUpdateMap.put(opp.Id, opp);
	}
	if (!oppUpdateMap.isEmpty()) {
		update oppUpdateMap.values();
	}
}

Hope it solves your problem.

Please mark this as best answer if it solves.

Thanks,
Balaji J 
This was selected as the best answer
Nathan Prats 22Nathan Prats 22
Hi Balaji, Thanks for your help. 

I changed my code like this. It seems to work I did a few tests.
Why is it better to do a trigger on line items over the opportunity object ? I don't understand. 
 
trigger OpportunityTriggers on Opportunity (before delete, before insert, before update,after delete, after insert, after update) {
    
    if(Trigger.isBefore && (Trigger.isInsert || Trigger.isUpdate)){
        
        /// Primary_Partner_Gross_Margin__c
        
        // Build a list that contains all opportunities for which we need to update the Primary_Partner_Gross_Margin__c field
        List<Opportunity> Opps = new List<Opportunity>();
        
        For (Opportunity opp :trigger.new){
            if(opp.Primary_Partner_Role__c =='Reseller' && opp.Primary_Partner_Account__c != NULL && opp.Primary_Partner_Margin__c != NULL){
                Opps.add(opp);
            }
            
            // Loop through the list and Update the Primary_Partner_Gross_Margin__c field
            For (Opportunity opp2 :Opps){
                
                Decimal GrossMargin = [SELECT TotalPrice
                                       FROM OpportunityLineItem
                                       WHERE PricebookEntry.product2.Family='Software'
                                       AND  OpportunityId =: opp2.Id][0].TotalPrice;
                
                opp2.Primary_Partner_Gross_Margin__c=GrossMargin*opp2.Primary_Partner_Margin__c/100;
            }
        }
    }
}

 
balaji Jayararmanbalaji Jayararman
Nathan, Here's my answer for your question.

First thing is you are calculating Opportunity.Primary_Partner_Gross_Margin__c field value based on the TotalPrice value in the OpportunityLineItems.

If you write a trigger on opportunity object,  the trigger won't fire when you insert/update an opportunityLineItem and the Primary_Partner_Gross_Margin__c field on Opportunity does not contain the correct value. To get the right value, you have to do manual update on oppotunity record.

So,Please write a trigger on opportunity object to get the right value without doing any manual things.