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
Aron Schor 24Aron Schor 24 

Help with Trigger that updates multiple records

Hi, I have a trigger that updates a field on a custom object, Pitch.  I got it to partially work with help from ChatGPT and my own tweaks.

1. What it does is update a field that shows the total of all Opportunity Amounts related to a specific Opportunity Property Group.
2. Next it should find all other Pitch records that have the same Opportunity Property Group do the same update so all related records should be in sync.

ie Select SUM(Opportunity__r.Amount) From Pitch__c where Property_Group__c = :record.Property_Group__c

It does not do step 2 but I can't figure out why.  Any idea?

trigger calculatePropertyGroupAmountBeforeFull on Pitch__c (before insert, before update) {
  // Get the records that are being triggered on.
  List<Pitch__c> records = Trigger.new;

  // Get the property group amount for each record.
  for (Pitch__c record : records) {
    List<AggregateResult> propertyGroupAmounts = [

      SELECT SUM(Opportunity__r.Amount)
      FROM Pitch__c
      WHERE Id = :record.Id OR     
     Property_Group__c = :record.Property_Group__c
      GROUP BY propertyhighspot__r.Property_Group_Text__c

    ];

    // Set the property group amount for each record.
    if (propertyGroupAmounts != null && propertyGroupAmounts.size() > 0) {
      record.Property_Group_Amount__c = (Decimal)propertyGroupAmounts[0].get('expr0');
    } else {
      // Set the property group amount to 0 if there is no amount.
      record.Property_Group_Amount__c = 0;
    }
  }

  // Check if the trigger is currently running.
  if (RecursiveTriggerHandler.isFirstTime) {
    return;
  }


  // Get the property group amount for each record.
  for (Pitch__c record : records) {
    List<AggregateResult> propertyGroupAmounts = [
      SELECT SUM(Opportunity__r.Amount)
      FROM Pitch__c
      WHERE Id = :record.Id OR Property_Group__c = :record.Property_Group__c
      GROUP BY propertyhighspot__r.Property_Group_Text__c
    ];

    // Set the property group amount for each record.
    if (propertyGroupAmounts != null && propertyGroupAmounts.size() > 0) {
      record.Property_Group_Amount__c = (Decimal)propertyGroupAmounts[0].get('expr0');
    } else {
      // Set the property group amount to 0 if there is no amount.
      record.Property_Group_Amount__c = 0;
    }
  }

  // Update all records with the same value for Property_Group__c.
  List<Pitch__c> matchingRecordsToUpdate = new List<Pitch__c>();
  for (Pitch__c record : records) {
    if (record.Property_Group__c != null) {
      // Get all records with the same value for Property_Group__c.
      List<Pitch__c> matchingRecords = [
        SELECT Id, Property_Group_Amount__c
        FROM Pitch__c
        WHERE Property_Group__c = :record.Property_Group__c
        AND Id != :record.Id
      ];

      // Update the property group amount for all matching records.
      for (Pitch__c matchingRecord : matchingRecords) {
        if (!matchingRecord.IsUpdated__c) {
          matchingRecord.Property_Group_Amount__c = record.Property_Group_Amount__c;
          matchingRecord.IsUpdated__c = true;
          matchingRecordsToUpdate.add(matchingRecord);
        }
      }
    }
  }

  // Update all matching records outside of the trigger context.
  if (!matchingRecordsToUpdate.isEmpty()) {
    update matchingRecordsToUpdate;
  }
}

Apex Class
public class RecursiveTriggerHandler{
public static Boolean isFirstTime = true;
}
Best Answer chosen by Aron Schor 24
Prateek Prasoon 25Prateek Prasoon 25
Based on the code you provided, it seems like you are trying to update the Property_Group_Amount__c field on the Pitch__c object for all related records that have the same Property_Group__c value. However, there are a few issues in the trigger code that may be causing the update to not work as expected.
In the first query, you are grouping by propertyhighspot__r.Property_Group_Text__c, but propertyhighspot__r is not referenced anywhere in the code or in the object structure provided. Please make sure that you are referencing the correct relationship name in your query.
In the second query, you are also grouping by propertyhighspot__r.Property_Group_Text__c, but you are using record.Property_Group__c as the filter condition. Make sure that record.Property_Group__c is the correct field to filter the query based on your object structure.
You are using a custom Boolean variable RecursiveTriggerHandler.isFirstTime to check if the trigger is currently running. However, in your trigger code, you are not setting this variable to false at any point, which means that the trigger will always return early and not execute the intended updates. Make sure to update this variable appropriately in your trigger code.
You are using a custom field IsUpdated__c to prevent updates on the same record within the trigger context. However, this field is not being set to true anywhere in your code, which means that the condition !matchingRecord.IsUpdated__c will always evaluate to false and prevent updates on matching records. Make sure to set this field to true appropriately in your code.
Here's an updated version of your trigger code with the above issues addressed:
trigger calculatePropertyGroupAmountBeforeFull on Pitch__c (before insert, before update) {
  // Get the records that are being triggered on.
  List<Pitch__c> records = Trigger.new;
  // Get the property group amount for each record.
  for (Pitch__c record : records) {
    List<AggregateResult> propertyGroupAmounts = [
      SELECT SUM(Opportunity__r.Amount)
      FROM Pitch__c
      WHERE Property_Group__c = :record.Property_Group__c
      GROUP BY Property_Group__c
    ];
    // Set the property group amount for each record.
    if (propertyGroupAmounts != null && propertyGroupAmounts.size() > 0) {
      record.Property_Group_Amount__c = (Decimal)propertyGroupAmounts[0].get('expr0');
    } else {
      // Set the property group amount to 0 if there is no amount.
      record.Property_Group_Amount__c = 0;
    }
  }
  // Check if the trigger is currently running.
  if (RecursiveTriggerHandler.isFirstTime) {
    // Set isFirstTime to false to prevent recursion.
    RecursiveTriggerHandler.isFirstTime = false;
    // Update all records with the same value for Property_Group__c.
    List<Pitch__c> matchingRecordsToUpdate = new List<Pitch__c>();
    for (Pitch__c record : records) {
      if (record.Property_Group__c != null) {
        // Get all records with the same value for Property_Group__c.
        List<Pitch__c> matchingRecords = [
          SELECT Id, Property_Group_Amount__c
          FROM Pitch__c
          WHERE Property_Group__c = :record.Property_Group__c
          AND Id != :record.Id
        ];
        // Update the property group amount for all matching records.
        for (Pitch__c matchingRecord : matchingRecords) {
          if (!matchingRecord.IsUpdated__c) {
            matchingRecord.Property_Group_Amount__c = record.Property_Group_Amount__c;
            matchingRecord.IsUpdated__c = true;
            matchingRecordsToUpdate.add(matchingRecord);
          }
        }
      }
    }
    // Update all matching records outside of the trigger context.
    if (!matchingRecordsToUpdate.isEmpty()) {
      update matchingRecordsToUpdate;
    }
  }
}

If you find this answer helpful,Please mark it as the best answer.

All Answers

Prateek Prasoon 25Prateek Prasoon 25
Based on the code you provided, it seems like you are trying to update the Property_Group_Amount__c field on the Pitch__c object for all related records that have the same Property_Group__c value. However, there are a few issues in the trigger code that may be causing the update to not work as expected.
In the first query, you are grouping by propertyhighspot__r.Property_Group_Text__c, but propertyhighspot__r is not referenced anywhere in the code or in the object structure provided. Please make sure that you are referencing the correct relationship name in your query.
In the second query, you are also grouping by propertyhighspot__r.Property_Group_Text__c, but you are using record.Property_Group__c as the filter condition. Make sure that record.Property_Group__c is the correct field to filter the query based on your object structure.
You are using a custom Boolean variable RecursiveTriggerHandler.isFirstTime to check if the trigger is currently running. However, in your trigger code, you are not setting this variable to false at any point, which means that the trigger will always return early and not execute the intended updates. Make sure to update this variable appropriately in your trigger code.
You are using a custom field IsUpdated__c to prevent updates on the same record within the trigger context. However, this field is not being set to true anywhere in your code, which means that the condition !matchingRecord.IsUpdated__c will always evaluate to false and prevent updates on matching records. Make sure to set this field to true appropriately in your code.
Here's an updated version of your trigger code with the above issues addressed:
trigger calculatePropertyGroupAmountBeforeFull on Pitch__c (before insert, before update) {
  // Get the records that are being triggered on.
  List<Pitch__c> records = Trigger.new;
  // Get the property group amount for each record.
  for (Pitch__c record : records) {
    List<AggregateResult> propertyGroupAmounts = [
      SELECT SUM(Opportunity__r.Amount)
      FROM Pitch__c
      WHERE Property_Group__c = :record.Property_Group__c
      GROUP BY Property_Group__c
    ];
    // Set the property group amount for each record.
    if (propertyGroupAmounts != null && propertyGroupAmounts.size() > 0) {
      record.Property_Group_Amount__c = (Decimal)propertyGroupAmounts[0].get('expr0');
    } else {
      // Set the property group amount to 0 if there is no amount.
      record.Property_Group_Amount__c = 0;
    }
  }
  // Check if the trigger is currently running.
  if (RecursiveTriggerHandler.isFirstTime) {
    // Set isFirstTime to false to prevent recursion.
    RecursiveTriggerHandler.isFirstTime = false;
    // Update all records with the same value for Property_Group__c.
    List<Pitch__c> matchingRecordsToUpdate = new List<Pitch__c>();
    for (Pitch__c record : records) {
      if (record.Property_Group__c != null) {
        // Get all records with the same value for Property_Group__c.
        List<Pitch__c> matchingRecords = [
          SELECT Id, Property_Group_Amount__c
          FROM Pitch__c
          WHERE Property_Group__c = :record.Property_Group__c
          AND Id != :record.Id
        ];
        // Update the property group amount for all matching records.
        for (Pitch__c matchingRecord : matchingRecords) {
          if (!matchingRecord.IsUpdated__c) {
            matchingRecord.Property_Group_Amount__c = record.Property_Group_Amount__c;
            matchingRecord.IsUpdated__c = true;
            matchingRecordsToUpdate.add(matchingRecord);
          }
        }
      }
    }
    // Update all matching records outside of the trigger context.
    if (!matchingRecordsToUpdate.isEmpty()) {
      update matchingRecordsToUpdate;
    }
  }
}

If you find this answer helpful,Please mark it as the best answer.
This was selected as the best answer
Aron Schor 24Aron Schor 24
Thanks Prateek, I did some tweaks and got me to the next step.  I am still having one final issue that I can see that I posted about below.  It looks like the related records get updated to the correct amount, but not the triggering record.

See link or comments below.
https://developer.salesforce.com/forums/ForumsMain?id=9062I000000DPLNQA4#!/feedtype=SINGLE_QUESTION_DETAIL&dc=Apex_Code_Development&criteria=OPENQUESTIONS&id=9062I000000DPNnQAO

I am using two Triggers and it seems the record that is initially being updated does not stay in sync with the other records.
Example, for Pitch (custom) record 123, let's say I add a $2 Opportunity and then Property tied to Property Group A.
What happens is Total Amount is $102 for all related records EXCEPT 123 which shows $100.
It seems the amount is set for that record prior to it being tied to the Property Group.
After, if I update record 123 by making any change, then it becomes $102.  I want it to become $102 with these triggers.

trigger PropertyCalc1 on Pitch__c (before insert, before update) {

  // Get the records that are being triggered on.
  List<Pitch__c> records = Trigger.new;

  // Get the property group amount for each record.
  for (Pitch__c record : records) {
    List<AggregateResult> propertyGroupAmounts = [
      SELECT SUM(Opportunity__r.Amount)
      FROM Pitch__c
      WHERE Property_Group__c = :record.Property_Group__c
      GROUP BY propertyhighspot__r.Property_Group_Text__c
    ];

    // Set the property group amount for each record.
    if (propertyGroupAmounts != null && propertyGroupAmounts.size() > 0) {
      record.Property_Group_Amount__c = (Decimal)propertyGroupAmounts[0].get('expr0');
    } else {
      // Set the property group amount to 0 if there is no amount.
      record.Property_Group_Amount__c = 0;
    }
  }
}

trigger PropertyCalc2 on Pitch__c (after update) {

  // Get the records that are being triggered on.
  List<Pitch__c> records = Trigger.new;

  // Check if the trigger is currently running.
  if (RecursiveTriggerHandler.isFirstTime) {
    // Set isFirstTime to false to prevent recursion.
    RecursiveTriggerHandler.isFirstTime = false;

    // Update all records with the same value for Property_Group__c.
    List<Pitch__c> matchingRecordsToUpdate = new List<Pitch__c>();
    for (Pitch__c record : records) {
      if (record.Property_Group__c != null) {
        // Get all records with the same value for Property_Group__c.
        List<Pitch__c> matchingRecords = [
          SELECT Id, Property_Group_Amount__c
          FROM Pitch__c
          WHERE Property_Group__c = :record.Property_Group__c
          AND Id != :record.Id
        ];

        // Update the property group amount for all matching records.
        for (Pitch__c matchingRecord : matchingRecords) {
          matchingRecord.Property_Group_Amount__c = record.Property_Group_Amount__c;
          matchingRecordsToUpdate.add(matchingRecord);
        }
      }
    }

    // Update all matching records outside of the trigger context.
    if (!matchingRecordsToUpdate.isEmpty()) {
      update matchingRecordsToUpdate;
    }
  }
}