0

I am trying to update a field 'PricePerUnit__c' in trigger using before update event on object 'Insurances__c' but the value isn't getting updated on the record. However, when i check the debug logs it shows that the field is being updated with new value, but on record it doesn't get updated.

trigger InsurancesTrigger on Insurances__c (before update) {
        InsurTriggerHandler.beforeUpdate(Trigger.New); 
    }

// TriggerHandlerClass

    public static void beforeUpdate(list<Insurances__c> lstIns) {
         updateRec(lstIns);
    }

    
    Public static void updateRec(list<Insurances__c> lstIns){ 
        for(Insurances__c cp : [Select id,Reported_Complaint__r.Name, UnitCode__c,PricePerUnit__c from Insurances__c where ID IN: lstIns]){
            if(cp.Reported_Complaint__r.Name == 'PHI' && (cp.UnitCode__c == '12CM' || cp.UnitCode__c  == '12S')){
                    cp.PricePerUnit__c =  20.00;
                    system.debug('++++cp.PricePerUnit_c++++'+cp.PricePerUnit__c);
            }       
        }    
    }

2 Answers 2

3

you can set field values and they will be commited in before update only for records, which are from Trigger.new context variable. In your code, you are not referencing Trigger.new, but brand new queried records. Your code should be:

public static void updateRec(List<Insurances__c> lstIns){ 
    for(Insurances__c cp : [Select id,Reported_Complaint__r.Name, UnitCode__c,PricePerUnit__c from Insurances__c where ID IN: lstIns]){
        if(cp.Reported_Complaint__r.Name == 'PHI' && (cp.UnitCode__c == '12CM' || cp.UnitCode__c  == '12S')){
            ((Insurances__c)Trigger.newMap.get(cp.Id)).PricePerUnit__c =  20.00;
        }       
    }    
}
4
  • 1
    +1 but important side note: doing the query "before update" will return the old values in the database, so this code might not work correctly when Reported_Complaint__r is changing.
    – sfdcfox
    Oct 20, 2021 at 13:14
  • 1
    +1 but I'd really be hesitant to introduce a direct reference to Trigger.newMap (or any trigger context variable) into a handler class. Using TCVs negates one of the main benefits to separating logic from the trigger (tests being able to execute the code directly, not requiring DML to execute it).
    – Derek F
    Oct 20, 2021 at 13:18
  • @DerekF yes, it would be easier, if to pass not Trigger.new, but Trigger.newMap, as a parameter of the handler method. Oct 20, 2021 at 13:21
  • Thanks all for your inputs and help. @OleksandrBerehovskyi I am accepting yours as an answer for this. Thanks.
    – SFDCKASH
    Oct 20, 2021 at 17:19
1

To take advantage of the DML-less record updating action in before insert and before update trigger contexts, you need to make the changes to an instance of the triggered object contained in trigger.new or trigger.newMap.

In this case, that means that you need to update your field on a record in your lstIns variable.

You're currently updating the field on a separate in-memory instance of the record that you obtain from a separate query.

Probably the easiest approach to address this would be to turn your if(cp.Reported_Complaint__r.Name == 'PHI' && (cp.UnitCode__c == '12CM' || cp.UnitCode__c == '12S')) into a formula field. That would make it so that you no longer need to explicitly query for related data, and you would be able to simply iterate over lstIns.

If that's not an option, then you'd want to use a Map to store the related data (by Id), and then loop over lstIns and fetch the related data by Id.

Something like

Map<Id, MyObject__c> relatedDataMap = new Map<Id, MyObject__c>([SELECT Parent__r.Name FROM MyObject__c WHERE Id IN :recordsPassedIn]);

for(MyObject__c fromTriggerContext :recordsPassedIn){
    MyObject__c relatedData = relatedDataMap.get(objectInstance.Id);

    if(relatedData.Parent__r.Name == 'value'){
        fromTriggerContext.Field__c = 'new value';
    }
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .