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
cbrocbro 

Defaulting in values to a parent object from a newly created child object

I need help updating a field in the Parent Object after the Child Object is created.

 

In this case, the field: Contract.Contract_Header__c needs to be updated with Contract_Header__c.Id after creation of this child object from THIS trigger below.

 

I have no idea how to go about this...  a couple of questions:

  • Is this possible within this trigger or do I have to write a new trigger on the Contract_Header__c Object?
  • Any help in getting started would be greatly appreciated!

 

Thanks,

Chris

 

Here is the code that I wrote that creates the child object (Contract_Header__c) from the parent object (Contract):

 

 

 

trigger Contract on Contract (after update) 
{
    List <Contract_Header__c> contractHeaders = new List <Contract_Header__c> ();
    Map <Id, Contract> oldmap = new Map <Id, Contract>();
    Map <Id, Contract> newmap = new Map <Id, Contract>();

 //System.debug('Chris in trigger');//

    for(Contract c: Trigger.new) 
    {
    //System.debug('Chris in contract loop');//
     if ((Trigger.oldMap.get(c.Id).Status != Trigger.newMap.get(c.Id).Status) && Trigger.newMap.get(c.Id).Status == 'Activated')
        { 
        //System.debug('Chris in status changed');//
        Contract_Header__c contractHeader = new Contract_Header__c ();
        contractHeader.Contract__c = c.Id;

        //System.debug('Chris creating new contract header and adding to list');//
        contractHeaders.add(contractHeader);
        }
    }

    if(contractHeaders.size()>0)
    {
    //System.debug('Chris has values to insert = '+ ContractHeaderInsert.size());//
     try{
        insert contractHeaders;
        }catch (System.Dmlexception e)  
             {
             system.debug (e); 
             }
    }

}

Best Answer chosen by Admin (Salesforce Developers) 
jbroquistjbroquist

 

Your global class with the future method should look something like this:

global class MyFutureClass
{
    @future
    global static void updateContracts(Map<Id, Id> contractIdMap)
    {
        Contract[] contracts = [SELCT Id, Contract_Header__c FROM Contract WHERE Id IN :contractIdMap.keySet()];
        for(Contract c : contracts)
        {
            c.Contract_Header__c = contractIdMap.get(c.Id);
        }

        update contracts;
    }
}

 

And your Contract_Header__c trigger something like this:

trigger ContractHeaderAfterInsert on Contract_Header__c (after insert)
{
    //instantiate map to map contract ids to contrac_header__c ids
    Map<Id, Id> contractIdMap = new Map<Id,Id>();
    
    for(Contract_Header__c ch : Trigger.new)
    {
        //verify the contract header is related to a contract
        if(ch.Contract__c != null)
            contractIdMap.put(ch.Contract__c, ch.Id);
    }

    if(contractIdMap.size() > 0) MyFutureClass.updateContracts(contractIdMap);
}

 Now I haven't tested this code, but it should definitely help ya out.

 

All Answers

cbrocbro

This is what I've come up with to update the field on the Contract (master) from the Contract_Header__c custom object (detail)

 

 

HERE IS THE CODE:

 

trigger ContractHeader on Contract_Header__c (after insert) {
Contract_Header__c contractHeader = [SELECT Id FROM Contract_Header__c WHERE Id IN :Trigger.new];
update contractHeader;
Contract contract = [SELECT Id, contractHeader.Contract_Header__c.Id FROM Contract_Header__c WHERE Id IN :Trigger.new];
}

 

 

 

I GET THIS ERRORr:

 

Error: Compile Error: Didn't understand relationship 'contractHeader' in field path. If you are attempting to use a custom relationship, be sure to append the '__r' after the custom relationship name. Please reference your WSDL or the describe call for the appropriate names. at line 4 column 21
jbroquistjbroquist

If I'm understanding you're code and requirements right you're trying to automatically create a Contract_Header__c record from the Contract record, when the Contract Status is updated to "Activated". After the Contract_Header__c record is created you want the Contract record to be updated with a direct relationship to the Contract_Header__c record.

 

With that being said, you're first trigger to automatically create the Contract_Header__c record looks fine. What you need to do though is create a trigger with an @future call on the Contract_Header__c object to update its parent record. Check out this article to see how you can build the @future method. http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_classes_annotation_future.htm

cbrocbro

Yes, this is exactly what the code is doing...

 

and exactly what I need to do...

 

I will look at this @future method documentation and see if I can figure it out...

 

oh, and thanks!

jbroquistjbroquist

 

Your global class with the future method should look something like this:

global class MyFutureClass
{
    @future
    global static void updateContracts(Map<Id, Id> contractIdMap)
    {
        Contract[] contracts = [SELCT Id, Contract_Header__c FROM Contract WHERE Id IN :contractIdMap.keySet()];
        for(Contract c : contracts)
        {
            c.Contract_Header__c = contractIdMap.get(c.Id);
        }

        update contracts;
    }
}

 

And your Contract_Header__c trigger something like this:

trigger ContractHeaderAfterInsert on Contract_Header__c (after insert)
{
    //instantiate map to map contract ids to contrac_header__c ids
    Map<Id, Id> contractIdMap = new Map<Id,Id>();
    
    for(Contract_Header__c ch : Trigger.new)
    {
        //verify the contract header is related to a contract
        if(ch.Contract__c != null)
            contractIdMap.put(ch.Contract__c, ch.Id);
    }

    if(contractIdMap.size() > 0) MyFutureClass.updateContracts(contractIdMap);
}

 Now I haven't tested this code, but it should definitely help ya out.

 

This was selected as the best answer
cbrocbro


I am getting this Error: Error: Compile Error: Incompatible value type Id for MAP<Id,Contract_Header__c> at line 10 column 13

 

and here is what I have for the Trigger:

 

trigger ContractHeaderUpdateonContract on Contract_Header__c (after insert)
{
     //instantiate map to map contract ids to contrac_header__c ids
     Map<Id, Contract_Header__c> contractIdMap = new Map<Id, Contract_Header__c>();

     for(Contract_Header__c co : Trigger.new)
     {
          //verify the contract header is related to a contract
          if(co.Contract__c != null)
          contractIdMap.put(co.Contract__c, co.Id);
     }

if(contractIdMap.size()>0)

FutureClass.updateContracts(contractIdMap);
}

 

 

 

jbroquistjbroquist
trigger ContractHeaderUpdateonContract on Contract_Header__c (after insert)
{
     //instantiate map to map contract ids to contrac_header__c ids
     Map<Id, Contract_Header__c> contractIdMap = new Map<Id, Contract_Header__c>();

     for(Contract_Header__c co : Trigger.new)
     {
          //verify the contract header is related to a contract
          if(co.Contract__c != null)
          contractIdMap.put(co.Contract__c, co.Id);
     }
if(contractIdMap.size()>0)

FutureClass.updateContracts(contractIdMap);
}

 That line should be the following if you're going off my example above:

     Map<Id, Id> contractIdMap = new Map<Id, Id>();

 

cbrocbro

hmmm.  I changed it, but now I am getting the following error:  

Error: Compile Error: Method is not visible: FutureClass.updateContracts(MAP<Id,Id>) at line 15 column 5

 

Saying that the Method is not visible?

 

Here is the global class that you showed me as it is here:

 

global class FutureClass
{
    @future
    static void updateContracts(Map<Id, Id> contractIdMap)
    {
        Contract[] contracts = [SELECT Id, Contract_Header__c FROM Contract WHERE Id IN :contractIdMap.keySet()];
        for(Contract c : contracts)
        {
            c.Contract_Header__c = contractIdMap.get(c.Id);
        }

        update contracts;
    }
}

 

 

jbroquistjbroquist

Change the method signature to have a global context:

global static void updateContracts(Map<Id, Id> contractIdMap)
{
//etc..
}

 

cbrocbro

it worked!  thanks a million for all of your help!

 

i can't tell you how much I appreciate it!

 

Chris