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
skiptomylou48skiptomylou48 

APEX trigger to pass information to related object (Master-Detail)

Hi all,

 

On the opportunity I have to fields:

First Delivery (Date field)

Last Delivery (Date field)

 

On a custom object (Fleet__c) linked via Master-Detail relationship I have two fields:

Year of First Delivery (Number (4,0))

Year of Last Delivery (Number (4,0))

Both fields are set to read-only.

 

What I want to the code to do is on saving an Opportunity, take only the year from the 'First Delviery' and 'Last Delivery' field on the opportunity and put it into the two fields on all related Fleet__c entries.

 

Any help is very much appreciated! 

 

Many thanks,

Patrick

Best Answer chosen by Admin (Salesforce Developers) 
Sean TanSean Tan

Great sorry I was on the wrong impression about the objects.

 

Right I overlooked that part in your post. Are there any flat fields on the SubFleet object that's just a plain text field? If so you can use the Date's.year() property to get the year.

 

Something like this should work:

 

trigger SyncFleetDeliveryDates on Fleet__c (after update)
{
    Map<Id, Fleet__c> oppMap = new Map<Id, Fleet__c>{};
    
    for (Fleet__c item : Trigger.new)
    {
        Fleet__c oldItem = Trigger.oldMap.get(item.Id);
        //Check if the dates are changing...
        if (oldItem.First_Delivery__c != item.First_Delivery__c || oldItem.Last_Delivery__c != item.Last_Delivery__c )
        {
            oppMap.put(item.Id, item);
        }
    }
    
    if (!oppMap.isEmpty())
    {
        SubFleet__c[] childFleets = [ SELECT Id, Fleet__c FROM SubFleet__c WHERE Fleet__c IN :oppMap.keySet() ];
        
        for (SubFleet__c item : childFleets)
        {
            Fleet__c opp = oppMap.get(item.Fleet__c);
            item.First_Delivery__c = opp.First_Delivery__c ;            
            item.Last_Delivery__c = opp.Last_Delivery__c ;
            //Year values
            //Change the fields as you need to
            item.First_Delivery_Year__c = opp.First_Delivery__c.year();
            item.Last_Delivery_Year__c = opp.Last_Delivery__c.year();
        }
        
        if (!childFleets.isEmpty())
        {
            update childFleets;
        }
    }    
}

 

All Answers

Sean TanSean Tan

If it's a master detail (even a lookup would do). Wouldn't a formula field suffice for what you're trying to do?

 

Something like this should work for a formula (Use a string formula instead of number formula):

 

TEXT(YEAR(Opportunity__r.First_Deliver__c))

 

Repeat for last delivery.

skiptomylou48skiptomylou48

Thanks Sean,

 

I should have included that we want to use the Year of First / Last Delivery in a Roll-up Summary field to show the oldest Year (MIN) of all the related fleet entries on the opportunity.

Therefore, I fear a formula field won't work as this can't be used in a roll-up summary as I understand.

 

Best regards,

Patrick

Sean TanSean Tan

Alright that makes sense from a business standpoint then. So instead you want a trigger to write these dates to any of the related Fleets under the opportunity.

 

If so, something like this should get you along the way. This was written on the fly (so may not compile) and I don't know the exact API names so you'll need to correct them as needed:

 

//Wont bother with insert operations since the child records cant exist yet
trigger SyncFleetDeliveryDates on Opportunity (after update)
{
    Map<Id, Opportunity> oppMap = new Map<Id, Opportunity>{};
    
    for (Opportunity item : Trigger.new)
    {
        Opportunity oldItem = Trigger.oldMap.get(item.Id);
        //Check if the dates are changing...
        if (oldItem.First_Delivery__c != item.First_Delivery__c || oldItem.Last_Delivery__c != item.Last_Delivery__c)
        {
            oppMap.put(item.Id, item);
        }
    }
    
    if (!oppMap.isEmpty())
    {
        Fleet__c[] childFleets = [ SELECT Id, Opportunity__c FROM Fleet__c WHERE Opportunity__c IN :oppMap.keySet() ];
        
        for (Fleet__c item : childFleets)
        {
            Opportunity opp = oppMap.get(item.Opportunity__c);
            item.First_Delivery__c = opp.First_Delivery__c;
            item.Last_Delivery__c = opp.Last_Delivery__c;
        }
        
        if (!childFleets.isEmpty())
        {
            update childFleets;
        }
    }    
}

 

 

skiptomylou48skiptomylou48

Thanks Sean,

 

I have adjusted your code slightly and it works!

Actually the master object is not Opportunity but Fleet__c and the sub object is called SubFleet__c.

 

At the moment however it transfers the date one to one from Fleet__c to SubFleet__c.

What we would like to have that it takes the date (e.g. 9/10/2013) from Fleet__c and saves only the year (2013) into a number field on SubFleet__c.

Would you have any suggestion for this as well?

 

Again, many thanks and best regards,

Patrick

 

trigger SyncFleetDeliveryDates on Fleet__c (after update)
{
    Map<Id, Fleet__c> oppMap = new Map<Id, Fleet__c>{};
    
    for (Fleet__c item : Trigger.new)
    {
        Fleet__c oldItem = Trigger.oldMap.get(item.Id);
        //Check if the dates are changing...
        if (oldItem.First_Delivery__c != item.First_Delivery__c || oldItem.Last_Delivery__c != item.Last_Delivery__c )
        {
            oppMap.put(item.Id, item);
        }
    }
    
    if (!oppMap.isEmpty())
    {
        SubFleet__c[] childFleets = [ SELECT Id, Fleet__c FROM SubFleet__c WHERE Fleet__c IN :oppMap.keySet() ];
        
        for (SubFleet__c item : childFleets)
        {
            Fleet__c opp = oppMap.get(item.Fleet__c);
            item.First_Delivery__c = opp.First_Delivery__c ;
            item.Last_Delivery__c = opp.Last_Delivery__c ;
        }
        
        if (!childFleets.isEmpty())
        {
            update childFleets;
        }
    }    
}

 

Sean TanSean Tan

Great sorry I was on the wrong impression about the objects.

 

Right I overlooked that part in your post. Are there any flat fields on the SubFleet object that's just a plain text field? If so you can use the Date's.year() property to get the year.

 

Something like this should work:

 

trigger SyncFleetDeliveryDates on Fleet__c (after update)
{
    Map<Id, Fleet__c> oppMap = new Map<Id, Fleet__c>{};
    
    for (Fleet__c item : Trigger.new)
    {
        Fleet__c oldItem = Trigger.oldMap.get(item.Id);
        //Check if the dates are changing...
        if (oldItem.First_Delivery__c != item.First_Delivery__c || oldItem.Last_Delivery__c != item.Last_Delivery__c )
        {
            oppMap.put(item.Id, item);
        }
    }
    
    if (!oppMap.isEmpty())
    {
        SubFleet__c[] childFleets = [ SELECT Id, Fleet__c FROM SubFleet__c WHERE Fleet__c IN :oppMap.keySet() ];
        
        for (SubFleet__c item : childFleets)
        {
            Fleet__c opp = oppMap.get(item.Fleet__c);
            item.First_Delivery__c = opp.First_Delivery__c ;            
            item.Last_Delivery__c = opp.Last_Delivery__c ;
            //Year values
            //Change the fields as you need to
            item.First_Delivery_Year__c = opp.First_Delivery__c.year();
            item.Last_Delivery_Year__c = opp.Last_Delivery__c.year();
        }
        
        if (!childFleets.isEmpty())
        {
            update childFleets;
        }
    }    
}

 

This was selected as the best answer
skiptomylou48skiptomylou48
Thanks Sean!!!