I have 2 custom objects: Project__c (parent) and Project_Contact__c (child). The parent has a picklist field called project_status__c with values Open or Closed. On the child object, there's a checkbox that must be checked before the parent can close. The checkbox is called survey_sent__c. When a user tries to close the parent and the survey_sent_c box isn't checked on the child object, this trigger is supposet to check for that condition, prevent the project from closing, and throw an error message to inform the user to send a survey before closing. Here's the code I have so far. Can anyone help me correct my wrong? Salesforce doesn't throw any errors.


trigger SurveyNotSentError on Project__c (before update){

    // List of PCs without surveys sent.
    List<Project_Contact__c> myList = [SELECT id FROM Project_Contact__c WHERE Survey_Sent__c = false];

    // Create an empty set to use later
    set<String> mySet = new set<String>();

    // Add PC Ids w/no survey sent to mySet
    for(Project_Contact__c PC : myList){ 

    //Look thru Ps. Check if set of PCs contains a P id. If true, throw error message.
    for(Project__c P : trigger.new){
        if(mySet.contains(P.id) && P.Project_Status__c == 'Closed'){
            P.addError('This is a bad survey, dude.');

2 Answers 2


I know you went through the coding path but here is an alternative solution... If you Project__c and Project_Contact__c are linked through a master-detail relationship, you could create 2 rollup summary :

  • Count total of project contact
  • Count Total of survey sent (filter by survey_sent__c)

Then create a custom validation rule if Total_Project_Contact__c != Total_Survey_Sent__c AND Project_Status__c == Closed then throw an error.

  • 1
    The relationship between these objects is indeed master-detail. I'll give this solution a try.
    – Rock Tober
    Dec 15, 2016 at 22:47
  • Let me know how you go.
    – brovasi
    Dec 16, 2016 at 0:04
  • 1
    Got it to work. Dude, you rock.
    – Rock Tober
    Dec 20, 2016 at 23:03
  • Glad you made it. You save a bit of coding and test class to write
    – brovasi
    Dec 20, 2016 at 23:04

You're going to have to gather the Project record id's of the record's that are attempting to be closed first. Then you can query for the Project Contact's that are related to those Project records and check to see if the checkbox has been checked. This way you aren't querying for more child records than you need to check.

Something like this:

trigger SurveyNotSentError on Project__c (before update) { Map<Id, Boolean> projectsAttemptingToBeClosed = new Map<Id, Project__c>(); for (Project__c p : Trigger.new) { if (p.Project_Status__c == 'Closed') { projectsAttemptingToBeClosed.put(p.Id, false); } } for (Project_Contact__c pc : [SELECT Id, Survey_Sent__c FROM Project__c WHERE Project__c IN :projectsAttemptingToBeClosed.keySet()]) { if (pc.Survey_Sent__c == true) { projectsAttemptingToBeClosed.get(pc.Project__c) = true; } } for (Project__c p : Trigger.new) { if (projectsAttemptingToBeClosed.containsKey(p.Id) && projectsAttemptingToBeClosed.get(p.Id) == false) { p.addError('This is a bad survey, dude.'); } } }

It's kind of funky and I know looping through the trigger list twice doesn't feel right, but you need to make sure you're adding the error to the records in the trigger context instead of a list that's only a copy of those records.

Hope this helps!

  • I understand MAPs logically, but I'm no good at using them. I say that because your code yields errors that I'm not sure how to correct. Thank you for your help however.
    – Rock Tober
    Dec 15, 2016 at 22:45
  • Ahh whoops, so I messed up the declaration of the map in the first line of the trigger method. Instead of = new Map<Id, Project__c>(); it should be ` = new Map<Id, Boolean>();` Dec 16, 2016 at 3:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .