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
You need to query for the parent records in order to get this information.
Set<Id> parentIds = new Set<Id>();
for (Child__c newRecord : trigger.new)
parentIds.add(newRecord.Parent__c);
Map<Id, Parent__c> parents = new Map<Id, Parent__c>([
SELECT Name FROM Parent__c WHERE Id IN :parentids
]);
Now you can loop through newList
and figure out the corresponding parent record.
for(zqu__QuoteCharge__c quoteCharge: newList)
{
zqu__ProductRatePlanCharge__c parent =
parents.get(quoteCharge.zqu__ProductRatePlanCharge__c);
}
You actually have an issue with your logic that the above will not fix. If you insert sibling records with the same parent, their sum might be greater than the allowed maximum. You also need to factor in siblings already in the database. It should be something more like:
public static void validateMaximum(List<Child__c> newRecords)
{
Map<Id, Decimal> parentToQuantity = new Map<Id, Decimal>();
for (Child__c newRecord : newRecords)
{
if (!parentToQuantity.containsKey(newRecord.Parent__c))
parentToQuantity.put(newRecord.Parent__c, 0);
parentToQuantity.get(newRecord.Parent__c) += newRecord.Quantity__c;
}
// now you have the totals from the trigger context
Map<Id, Parent__c> parents = new Map<Id, Parent__c>([
SELECT Maximum__c, (SELECT Quantity__c FROM Children__r)
WHERE Id IN :parentToQuantity.keySet()
];
for (Parent__c parent : parents.values())
for (Child__c child : parent.Children__r)
parentToQuantity.get(parent.Id) += child.Quantity__c;
// now you have a comprehensive total including existing values
for (Child__c newRecord : newRecords)
{
Parent__c parent = parents.get(newRecord.Parent__c);
if (parentToQuantity.get(parent.Id) > parent.Maximum__c)
newRecord.addError('message');
}
}
Best Answer
First of all, the duplicate checking can be done in a couple of ways:
As @ajay noted,
addError()
needs to be used againstTrigger.new
(or any variable that is a reference toTrigger.new
)Duplicate checking involves checking intrabatch (are there any duplicates within
Trigger.new
) as well as extraBatch (are there any duplicates when considering records already saved by previous transactions)You also need to check for duplicates on before insert and before update unless the key fields become read-only after insertion