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.');

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 '16 at 22:47
  • Let me know how you go. – Cloud Ninja Dec 16 '16 at 0:04
  • 1
    Got it to work. Dude, you rock. – Rock Tober Dec 20 '16 at 23:03
  • Glad you made it. You save a bit of coding and test class to write – Cloud Ninja Dec 20 '16 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 '16 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>();` – nhelterbrand Dec 16 '16 at 3:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.