3

I have a trigger on a custom object called CustomActivity__c that calls a class on before insert and before update. I have a custom object similar to Opportunity Teams (StudyTeam__c) where there is a record for every User who has access to a record for a custom object called Study__c. StudyTeam__c and CustomActivity__c are child objects of master Study__c. StudyTeam__c and CustomActivity__c both have lookups to the standard User object, the fields being User__c.

A Validation Rule will not work because of the object relationships. I need code to evaluate that the User lookup ID indicated on CustomActivity__c record matches a User lookup ID indicated on any of the StudyTeam__c records for the Study__c. If the User lookup on CustomActivity__c does not match the User lookup on a StudyTeam__c record for the Study__c, then the system should throw an error saying "Only team members can be assigned to the activity."

Can you help me with the class? I don't have much written because I don't know how to write code well.

I assume it'll be:

  1. Get a list of StudyTeam__c records for the Study__c
  2. Compare if User__c for CustomActivity__c matches User__c for StudyTeam__c in the list of StudyTeam__c records
  3. If FALSE, display an error message

Trigger

    trigger CustomActivityTrigger on CustomActivity__c (after insert, after update, after undelete, after delete, before insert, before update, before delete) {

        if(trigger.isBefore && (trigger.isInsert || trigger.isUpdate)){
            CustomActivityUserValidation.validation(trigger.new);
        }

    }

Class

    public class CustomActivityUserValidation {

        public static void validation(List<CustomActivity__c> val) {

            Set<Id> studyIds = new Set<Id>();
            for(CustomActivity__c ca : val){
                studyIds.add(ca.Study__c);
            }

        }// End public static void

    }// End class
2
  • 1
    You say you have a trigger for this. Can you please post what you have? Apr 1, 2015 at 19:52
  • Bri meant class, what is CustomActivityUserValidation
    – EricSSH
    Apr 1, 2015 at 20:22

2 Answers 2

3

Both CustomActivity__c and StudyTeam__c are children of Study__c, so you first need to get all the Study__c Records that are related to your list of CustomActivity__c records. You could do this with a set or map, I generally prefer maps, but it's not totally necessary here as your not really doing anything with the Study__c object, but I use a map anyway

map<Id,Study__c> studyMap = new map<Id,Study__c>();
for(CustomActivity__c cAct : val){
    studyMap.put(cAct.Study__c, null);
}
studyMap.remove(null);
studyMap.putAll([Select Id, Name From Study Where Id In : studyMap.keyset()]);

So now you have a map of the Study__c objects that are parents to your CustomActivity records. The next thing you need to do is query the StudyTeam__c records that have any of your Study__c records as a parent.

list<StudyTeam__c> sTeamList = [Select Id, Name, Study__c, User__c From StudyTeam__c Where Study__c in : studyMap.keyset()];

So now you have a list of all the StudyTeam__c objects you need to check the User__c field against your new CustomActivity records.

In order to compare them, you need an elegant way to access a Study__c record, and all the associated StudyTeam__c User__c values, so I would use a map for this

map<Id,set<Id>> study2IdsMap = new map<Id,set<Id>>();
for(StudyTeam__c sTeam : sTeamList){
     if(!study2IdsMap.containsKey(sTeam.Study__c)){
          study2IdsMap.put(sTeam.Study__c, new set<Id>();
     }
     study2IdsMap.get(sTeam.Study__c).add(sTeam.User__c); 
}

Now you have a map that takes a Study__c object and returns a full set of all user IDs that are associated with a StudyTeam__c object. So now you just need to make sure the User__c field on your CustomActivity__c field is in that set, or else throw an error.

for(CustomActivity__c cAct : val){
     if(!study2IdsMap.get(cAct.Study__c).contains(cAct.User__c)){
          cAct.addError('YOU CANNOT DO THAT!!');
     }
}

So then you just tie all the pieces together

public class CustomActivityUserValidation {

    public static void validation(List<CustomActivity__c> val) {

         map<Id,Study__c> studyMap = new map<Id,Study__c>();
         for(CustomActivity__c cAct : val){
            studyMap.put(cAct.Study__c, null);
         }
         studyMap.remove(null);
         studyMap.putAll([Select Id, Name From Study Where Id In : studyMap.keyset()]);

         list<StudyTeam__c> sTeamList = [Select Id, Name, Study__c, User__c From StudyTeam__c Where Study__c in : studyMap.keyset()];

         map<Id,set<Id>> study2IdsMap = new map<Id,set<Id>>();
         for(StudyTeam__c sTeam : sTeamList){
            if(!study2IdsMap.containsKey(sTeam.Study__c)){
               study2IdsMap.put(sTeam.Study__c, new set<Id>();
            }
            study2IdsMap.get(sTeam.Study__c).add(sTeam.User__c); 
         }

         for(CustomActivity__c cAct : val){
            if(!study2IdsMap.get(cAct.Study__c).contains(cAct.User__c)){
                cAct.addError('YOU CANNOT DO THAT!!');
            }
         }

    }// End public static void

}// End class
1
1

This is appropriate logic.

  1. Get a list of StudyTeam__c records for the Study__c
  2. Compare if User__c for CustomActivity__c matches User__c for StudyTeam__c in the list of StudyTeam__c records
  3. If FALSE, display an error message

Your class might be written as below.

There is room for optimization in this code, but it demonstrates the idea and has comments which should help you get going.

public class CustomActivityUserValidation {

    public static void validation(List<CustomActivity__c> customActivities) {

        // variable which we're going to use for query later
        Set<Id> studyIds = new Set<Id>();

        // iterate these activities from the trigger and get the parts which are important
        for (CustomActivity__c customActivity : customActivities) {

            // capture the studyid for the query
            studyIds.add(customActivity.Study__c);
        }

        // no records for the query that follows, may as well exit early
        if (studyIds.isEmpty()) {
            return;
        }

        // query for StudyTeam__c records for these study records
        List<StudyTeam__c> studyTeams = [SELECT User__c FROM StudyTeam__c WHERE Id IN :studyIds];

        // a variable to store the userids for comparison
        Set<Id> studyTeamUserIds = new Set<Id>();

        // loop the study teams to collect the User ids for comparison
        for (StudyTeam__c studyTeam : studyTeams) {
            studyTeamUserIds.add(studyTeam.User__c);
        }

        // iterate the CustomActivity__c records and see if
        // the user on the record is in the collection of users of the study team
        for (CustomActivity__c customActivity : customActivities) {

            // check to see if the user on this activity is in the collection
            if (studyTeamUserIds.contains(customActivity.User__c)) {
                // all good - keep going
            } else {
                // the user on this activity isn't part of the study team
                // add an error to the record from the trigger which will surface a failure on this record
                customActivity.addError('Only team members can be assigned to the activity.');
            }
        }


    }// End public static void

}// End class

You must log in to answer this question.

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