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
Hugo_BHugo_B 

Help with a trigger. Accessing a related parent record values to populate child record fields

I have a trigger on a custom object called "Time_Entry__c" that; when a record is created and *IF* there is a related contract associated with the Time Entry, it looks up the rates set-out on that contract record and uses the rates listed in the parent (Contract) record.

 

  Rate_1__c  (currency field)

  Rate_2__c  (currency field)

 

The look-up field on the Time_Entry__C object is called Contract__c

 

The related object is the Contract object in SF:  Contract__r

 

Contract__r has the two currency fields.

 

    CustomRate1__c

    CustomRate2__c

 

 

What I need is to have my trigger, look up the parent contract (if there is a value in Contract__c). and pull the two rates CustomRate1__c and CustomRate2__c and populate them into the Time Entry records Rate_1__c and Rate_2__c respectively.

 

Can anyone help with code for this trigger???

 

 

Best Answer chosen by Admin (Salesforce Developers) 
OzymandiasOzymandias

Let me give it a go:

 

trigger MyTrigger on Time_Entry__c (before update, before insert) {
    
    Set<Id> contractIds = new Set<Id>();    

    for (Time_Entry__c te : Trigger.new) {
        if (te.Contract__c != null) {
            contractIds.add(te.Contract__c);
        }
    }

    Map<Id, Contract> contractEntries = new Map<Id, Contract>(
        [select CustomRate1__c, CustomRate2__c from Contract where id in :contractIds]
    );

    for (Time_Entry__c te : Trigger.new) {
        Contract con = contractEntries.get(te.Contract__c);
        
        if (con != null) {
            te.Rate_1__c = con.CustomRate1__c;
            te.Rate_2__c = con.CustomRate2__c;
        }
    }
}

 Haven't really checked for syntax errors though, so let me know if it works.

All Answers

OzymandiasOzymandias

Let me give it a go:

 

trigger MyTrigger on Time_Entry__c (before update, before insert) {
    
    Set<Id> contractIds = new Set<Id>();    

    for (Time_Entry__c te : Trigger.new) {
        if (te.Contract__c != null) {
            contractIds.add(te.Contract__c);
        }
    }

    Map<Id, Contract> contractEntries = new Map<Id, Contract>(
        [select CustomRate1__c, CustomRate2__c from Contract where id in :contractIds]
    );

    for (Time_Entry__c te : Trigger.new) {
        Contract con = contractEntries.get(te.Contract__c);
        
        if (con != null) {
            te.Rate_1__c = con.CustomRate1__c;
            te.Rate_2__c = con.CustomRate2__c;
        }
    }
}

 Haven't really checked for syntax errors though, so let me know if it works.

This was selected as the best answer
Hugo_BHugo_B

Thanks for this!

 

Here is my full code using your solution:  However, I get the following error when I try to save the Time Entry Record:  In this case line 33 in my test record is running the correct line of code, but it is telling me that the TE.Rate__c is read only??  Any ideas?

 

Error: Invalid Data. Review all error messages below to correct your data. Apex trigger trg_AfterTimeEntryInsertUpdate caused an unexpected exception, contact your administrator: trg_AfterTimeEntryInsertUpdate: execution of AfterUpdate caused by: System.FinalException: Record is read-only: Trigger.trg_AfterTimeEntryInsertUpdate: line 33, column 13
 
 
 
trigger trg_AfterTimeEntryInsertUpdate on Time_Entry__c (after insert, after update) {

    Set<Id> contractIds = new Set<Id>();    

    for (Time_Entry__c te : Trigger.new) {
        if (te.Contract__c != null) {
            contractIds.add(te.Contract__c);
        }
    }

    Map<Id, Contract> contractEntries = new Map<Id, Contract>(
        [select CMRate__c, ConsultingRate__c, Data_ManagementRate__c, PMRate__c, SupportRate__c, GrpTrainRateFL__c, 
        GrpTrainRateHd__c, GrTrainRateHR__c, OneTrainRate__c from Contract where id in :contractIds]
    );

    for (Time_Entry__c te : Trigger.new) {
        Contract con = contractEntries.get(te.Contract__c);
        
        if (con != null) {
//            te.Rate__c = con.CMRate__c;
//            te.Rate_2__c = con.CustomRate2__c;
   if  (TE.Functional_Area__c == 'Case Management') {
            te.Rate__c = con.CMRate__c;
    } else if   (TE.Functional_Area__c == 'Consultation') {
            te.Rate__c = con.ConsultingRate__c;
    } else if   (TE.Functional_Area__c == 'Data Management') {
            te.Rate__c = con.Data_ManagementRate__c;
    } else if   (TE.Functional_Area__c == 'Project Management') {
            te.Rate__c = con.PMRate__c;
    } else if   (TE.Functional_Area__c == 'Technical Support') {
            te.Rate__c = con.SupportRate__c;
    } else if   (TE.Functional_Area__c == 'Training - Group Full Day') {
            te.Rate__c = con.GrpTrainRateFl__c;
    } else if   (TE.Functional_Area__c == 'Training - Group Half Day') {
            te.Rate__c = con.GrpTrainRateHd__c;
    } else if   (TE.Functional_Area__c == 'Training - Group Hourly') {
            te.Rate__c = con.GrTrainRateHR__c;
    } else if   (TE.Functional_Area__c == 'Training - Individual Hourly') {
            te.Rate__c = con.OneTrainRate__c;
    } else {
            te.Rate__c = 2.00;
    }

} else {
    if  (TE.Functional_Area__c == 'Case Management') {
            te.Rate__c = 275.00;
    } else if   (TE.Functional_ARea__c == 'Consultation') {
            te.Rate__c = 275.00;
    } else if   (TE.Functional_ARea__c == 'Data Management') {
            te.Rate__c = 125.00;
    } else if   (TE.Functional_ARea__c == 'Project Management') {
            te.Rate__c = 250.00;
    } else if   (TE.Functional_ARea__c == 'Technical Support') {
            te.Rate__c = 200.00;
    } else if   (TE.Functional_ARea__c == 'Training - Group Full Day') {
            te.Rate__c = 1600.00;
    } else if   (TE.Functional_ARea__c == 'Training - Group Half Day') {
            te.Rate__c = 800.00;
    } else if   (TE.Functional_ARea__c == 'Training - Group Hourly') {
            te.Rate__c = 300.00;
    } else if   (TE.Functional_ARea__c == 'Training - Individual Hourly') {
            te.Rate__c = 250.00;
    } else {
            te.Rate__c = 0.00;
    }  
 

        }
    }
}

 

OzymandiasOzymandias

It looks like it's related to you changing it from "before insert/update" to "after insert/update". In an after insert/update trigger, you're not allowed to change field values in Trigger.new context objects (the Apex Code Developer's Guide has a table showing what you can and can't do to context variables with different types of triggers).

 

Is there any reason why you prefer this code to be triggered after the insert or update?

Hugo_BHugo_B

Nope - I realized the mistake.  This worked - You're the best ;)

 

Hugo

TomTom GermanyTomTom Germany

Is this trigger only useful with lookups or can it be used with master detail related lookup as well? how would the code coverage be done?