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 '16 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. – loggedinuser May 5 '16 at 17:43
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 '16 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 '16 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. – Vigneshwaran G May 5 '16 at 17:49
  • 1
    Gotcha makes sense. – Adrian Larson May 5 '16 at 17:49

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.