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
Jerry ClifftJerry Clifft 

Hmm, can a trigger not copy from a child?

I have this trigger, it seems simple enough. On the case object is a lookup to Opportunity. Opportunity has a rich text field I want to copy to the case. However, this does not copy the value from the Opp field to the case field. Any suggestion / help?

trigger CaseHiddenProductCopyToCase_Testingsomething on Case (Before Insert, Before Update)
   {
         Case ca = trigger.new[0];
             { ca.Product_Change_Request_s__c = ca.Opportunity__r.Hidden_Products__c;}
    }
Best Answer chosen by Jerry Clifft
karnadesaikarnadesai
Gotcha! Now I understand your question.

The reason this happens is because in before / after insert triggers, relationship fields are not reference-able directly, as there is no way for Salesforce to know which fields of the related object it should load and make available.

Also, try to bulkify your code as best practices



trigger CaseHiddenProductCopyToCase_Testingsomething on Case (Before Insert, Before Update)
   {
        Set<Id> caseIds=new Set<Id>();
        for(Case c:Trigger.New)
         {
             caseIds.add(c.Opportunity__c);
         }
         Map<Id,Opportunity> opptyMap=new  Map<Id,Opportunity> ([select Id,Hidden_Products__c from Opportunity where Id in :caseIds]);
         for(Case c:Trigger.New)
         {
              c.Product_Change_Request_s__c = opptyMap.get(c.Opportunity__c).Hidden_Products__c;
                      }
    }

All Answers

karnadesaikarnadesai
You would have to write trigger on Opportunity which changes value of associated Case.

Tip: If this is a read only field then you can use Cross Object Formula field which does not require custom code
Jerry ClifftJerry Clifft
How can I update the case if the case is not yet created?
karnadesaikarnadesai
Gotcha! Now I understand your question.

The reason this happens is because in before / after insert triggers, relationship fields are not reference-able directly, as there is no way for Salesforce to know which fields of the related object it should load and make available.

Also, try to bulkify your code as best practices



trigger CaseHiddenProductCopyToCase_Testingsomething on Case (Before Insert, Before Update)
   {
        Set<Id> caseIds=new Set<Id>();
        for(Case c:Trigger.New)
         {
             caseIds.add(c.Opportunity__c);
         }
         Map<Id,Opportunity> opptyMap=new  Map<Id,Opportunity> ([select Id,Hidden_Products__c from Opportunity where Id in :caseIds]);
         for(Case c:Trigger.New)
         {
              c.Product_Change_Request_s__c = opptyMap.get(c.Opportunity__c).Hidden_Products__c;
                      }
    }
This was selected as the best answer
Jerry ClifftJerry Clifft
Your solution works great, thanks!

A quick question if you have time, I tried something similar to this, but it only worked if the Opp field was not blank, do you know why this would happen, here is what I tired.

Error: Invalid Data.
Review all error messages below to correct your data.
Apex trigger CaseHiddenProductCopyToCase caused an unexpected exception, contact your administrator: CaseHiddenProductCopyToCase: execution of AfterInsert caused by: System.DmlException: Update failed. First exception on row 0 with id 500m0000000pWuuAAE; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, CaseHiddenProductCopyToCase: maximum trigger depth exceeded Case trigger event AfterInsert for [500m0000000pWuu] Case trigger event AfterUpdate for [500m0000000pWuu] Case trigger event AfterUpdate for [500m0000000pWuu] Case trigger event AfterUpdate for [500m0000000pWuu] Case trigger event AfterUpdate for [500m0000000pWuu] Case trigger event AfterUpdate for [500m0000000pWuu] Case trigger event AfterUpdate for [500m0000000pWuu] Case trigger event AfterUpdate for [500m0000000pWuu] Case trigger event AfterUpdate for [500m0000000pWuu] Case trigger event AfterUpdate for [500m0000000pWuu] Case trigger event AfterUpdate for [500m0000000pWuu] Case trigger event AfterUpdate for [500m0000000pWuu] Case trigger event AfterUpdate for [500m0000000pWuu] Case trigger event AfterUpdate for [500m0000000pWuu] Case trigger event AfterUpdate for [500m0000000pWuu] Case trigger event AfterUpdate for [500m0000000pWuu]: []: Trigger.CaseHiddenProductCopyToCase: line 25, column 1


Again, thanks for your solution above!

trigger CaseHiddenProductCopyToCase on Case (After Insert, After Update) {

Case ca = trigger.new[0];
    if (ca.Product_Change_Request_s__c == NULL && ca.Hidden_Case_History__c == False && ca.Opportunity__c != null && ca.Status == 'Form Submitted' && (ca.RequestedAction__c == 'Activation' || ca.RequestedAction__c == 'Change' ||  ca.RequestedAction__c == 'Installation/Activation' ||  ca.RequestedAction__c == 'Pre-Activation' ||   ca.RequestedAction__c == 'Restart' ||   ca.RequestedAction__c == 'Two (2) Hour Activation' ||   ca.RequestedAction__c == 'Pre-Build' || ca.RequestedAction__c == 'Disconnect' ))
        {
   
        Set<Id> caseIds = new Set<Id>();
        Set<Id> opIds = new Set<Id>();
            for (Case c: Trigger.New)
                    {
                        opIds.add(c.Opportunity__c);
                        caseIds.add(c.Id);
                    }

                    list<opportunity> opp = [select id, Hidden_Case_History__c, Hidden_Products__c from opportunity where Id in :opIds AND Hidden_Case_History__c = True Limit 1];
                     list<case> cz = [select id, Status, Hidden_Case_History__c, Product_Change_Request_s__c from case where Id in :caseIds AND Hidden_Case_History__c = False AND Status = 'Form Submitted' Limit 1];

                    if(cz.size() > 0 && opp.size() > 0)
                        for (case ca2: cz)
                            {
                               cz[0].Product_Change_Request_s__c = opp[0].Hidden_Products__c;
                               cz[0].Hidden_Case_History__c = True;
                            }
    Database.update(cz);
        }
}
karnadesaikarnadesai
Using After trigger on the trigger object and updating the trigger object would create an infinite loop.

For eg
  1.  For a Case A update trigger is invoked
  2. Inside trigger you update Case A
  3. For Case A update trigger is invoked again.

So Step 1-3 would run infinitely ,
possible solutions are
  • Use before trigger (Would also not use any DML operation)
  • Use static variable to check if the trigger is already invoked and make sure that the trigger code is not invoked again.

http://stackoverflow.com/questions/11586739/salesforce-trigger-infinite-loop