4

I'm learning triggers and need some help with the logic. Election_Position__c looks up to Election__c and Contact objects. A contact can be assigned only one position in an election. In other words, a contact cannot have more than one position in an election. Here's where I got so far:

trigger TestTrigger on Election_Position__c (before insert, before update) {
    Map<Id, Set<Id>> electionToWorkersMap = new Map<Id, Set<Id>>();
    for(Election_Position__c ep: [SELECT Election__c, Assigned_Worker__c FROM Election_Position__c]){
        if(!electionToWorkersMap.containsKey(ep.Election__c)){
            electionToWorkersMap.put(ep.Election__c, new Set<Id>());
        }
        electionToWorkersMap.get(ep.Election__c).add(ep.Assigned_Worker__c);
    }
    for(Election_Position__c ep : Trigger.new){
        if(electionToWorkersMap.containsKey(ep.Assigned_Worker__c)){
            ep.addError('The worker already is assigned to this election, please select another election');
        }
    }
}
2
  • Wait, one position in any election or one per?
    – Adrian Larson
    May 5, 2016 at 17:33
  • 2
    One per. A contact can be assigned in multiple elections but can only be assigned one position in each election. Hope this makes sense. May 5, 2016 at 17:43

3 Answers 3

4

You are comparing ids of different type. Your map key has an Election__c id, but you are looking for a Contact key. You want:

electionToWorkersMap.containsKey(ep.Election__c) &&
    electionToWorkersMap.get(ep.Election__c).containsKey(ep.Assigned_Worker_c);

My initial understanding was they can only be added to one Election, which would look like:

Set<Id> existingWorkerIds = new Set<Id>();
for (AggregateResult aggregate : [
    SELECT Assigned_Worker__c workerId FROM Election_Position__c
    GROUP BY Assigned_Worker__c
])
    existingWorkerIds.add((Id)aggregate.get('workerId'));
for (Election_Position__c record : trigger.new)
    if (existingWorkerIds.contains(ep.Assigned_Worker__c))
        record.addError('message');
1
  • But that means they can't be in more than one election...
    – sfdcfox
    May 5, 2016 at 17:33
3
trigger TestTrigger on Election_Position__c (after insert, after update) {
    Map<Election_Position__c, Id> positions = new Map<Election_Position__c, Id>();
    Set<Id> assignedWorkers = new Set<Id>();
    for(Election_Position__c record: Trigger.new) {
        positions.put(new Election_Position__c(Election__c=record.Election__c, Assigned_Worker__c=record.Assigned_Worker__c), record.Id);
        assignedWorkers.add(record.Assigned_Worker__c);
    }

    for(Election_Position__c record: [SELECT Election__c, Assigned_Worker__c FROM Election_Position__c WHERE Assigned_Worker__c IN :assignedWorkers]){
        Election_Position__c key = new Election_Position__c(Election__c=record.Election__c, Assigned_Worker__c=record.Assigned_Worker__c);
        if(positions.containsKey(key)) {
            Trigger.newMap.get(positions.get(key)).addError('The worker already is assigned to this election, please select another election');
        }
    }
}

This version uses Election_Position__c records as keys into a map, making it efficient to find duplicates without managing nested collections, and using a minimal amount of memory.

1

Your map key contains Id of Election but you are trying to check whether it contains Assigned_Worker__c(Contact) which will always be false.

So change your if condition to

if(electionToWorkersMap.get(ep.Election__c).contains(ep.Assigned_Worker__c))

Hope it helps.

3
  • 1
    This solution will break if there are no positions assigned to the election yet.
    – Adrian Larson
    May 5, 2016 at 17:47
  • 1
    I got that after you did edit to your answer but kept it so that OP will have the option to look worst case aswell. May 5, 2016 at 17:49
  • 1
    Gotcha makes sense.
    – Adrian Larson
    May 5, 2016 at 17:49

You must log in to answer this question.

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