+ Start a Discussion
dlCamelotdlCamelot 

Trigger Help - Cross-Object Update

Hi all,

I'm so close to getting this trigger to work, but could use some help with the last bit.  For context, this is a cross-object (child to parent) relationship - Event Attendence (child) adds/edits will update a date field on the Contact (parent).   What do I need to adjust? 

trigger Contact_Update on EventAttendance__c (before insert, before update) {
  //Holds Ids of Event Attendence Records
  Set<ID> eventattendIDs = new Set<ID>();
  //Maps Contact IDs to Event Attendence Date
  Map<ID,DATE> c2ea = new Map<ID,DATE>();
    
      for(EventAttendance__c ea: Trigger.new){
        eventattendIDs.add(ea.id);
        system.debug('This the event attendence record being added:'+ ea.id);
    }
    
   List<EventAttendance__c> lastDate = [SELECT Event_Date__c FROM EventAttendance__c WHERE Contact__c = :eventattendIDs ORDER BY Event_Date__c DESC LIMIT 1];
   system.debug('This is the date pulled by SoQL' + lastDate);
       
   for (Contact c: lastDate) {
        lastDate.Last_Event_Date__c =
        trigger.newMap.get(c2ea.date);  
    }
    
    update eventattendIDs;
}

Newbie here so please explain the logic for your changes.
James LoghryJames Loghry
Think we might need a bit more context on the use case, but here's what I think you're going for.  See my comments for an idea of how the trigger (should) work.  Keep in mind, this is late on a Friday and I'm at least one scotch into the night, so it might not compile on the first shot :-D

 
trigger Contact_Update on EventAttendance__c (before insert, before update) {
  
    
    //Map for holding the contacts we need to query (as the key of the map)
    //along with a list of event dates associated with those contacts, found in this trigger context.
    Map<Id,List<Date>> contactToDatesMap = new Map<Id,List<Date>>();
   
    //Loop through the event attendance records that make up this trigger.
    for(EventAttendance__c ea: Trigger.new){

        //Look for any event attendance records that are either new, or have an updated
        //Event Date.
        if(Trigger.oldMap == null || Trigger.oldMap.get(ea.Id).Event_Date__c != ea.Event_Date__c){
            List<Date> contactEventDates = contactToDatesMap.get(ea.Contact__c);

            //Manages the list of events for each unique contact record we've found
            if(contactEventDates == null){
                contactEventDates = new List<Date>();
                contactToDatesMap.put(ea.Contact__c,contactEventDates);
            }
            contactEventDates.add(ea.Event_Date__c);
        }
    }

    //Query for all the contacts that are related to event attendances where the last event date is either now or has changed.
    //Inside the for loop for the query, check to see if there are any event dates that come after the contact's last event date.
    //If such a date exists, then update the contacts with the last event date.
    Map<Id,Contact> contactsToUpdate = new Map<Id,Contact>();
    for(Contact c : [Select Last_Event_Date__c From Contact Where Id in :contactToDatesMap.keySet()]){
        for(Date d : contactToDatesMap.get(c.Id)){
            //If the given date is greater than the contact's current last event date,
            //Set the Last Event Date on the contact.
            if(d > c.Last_Event_Date__c){
                c.Last_Event_Date__c = d;
                contactsToUpdate.put(c.Id,c);
            }
        }
    }

    //Bulk DML to update any necessary contacts
    update contactsToUpdate.values();
}

 
James LoghryJames Loghry
Here's another approach, using a sub query on contacts, that will work better for situations like when the Event Date is updated to be less than / prior to what it was beforehand.

trigger Contact_Update on EventAttendance__c (before insert, before update) {

    Set<Id> contactIds = new Set<Id>();
    for(EventAttendance__c ea: Trigger.new){
        if(Trigger.oldMap == null || Trigger.oldMap.get(ea.Id).Event_Date__c != ea.Event_Date__c){
            contactIds.add(ea.Contact__c);
        }
    }

    //Use a sub query (assuming Event_Attendances__r is the child relationship API name) to get the greatest event attendance date for each contact associated with this trigger.
    List<Contact> contactsToUpdate = [Select Last_Event_Date__c,(Select Event_Date__c From Event_Attendances___r Order By Event_Date__c Desc) From Contact Where Id in :contactIds];
    for(Contact c : contactsToUpdate){
        c.Last_Event_Date__c = Event_Attendances__r.isEmpty() ? c.Last_Event_Date__c : Event_Attendances__r.get(0);
    }
    update contactsToUpdate;
}