0

I have written a trigger for following scenario.

Positon is a object. There are two fields Parent_position and Head_count

Position object. Parent_position is self lookup field to position object.

Head_count is the number of positions those selected this position as parent.

Whenever Parent_position is updated, Head_count on new parent should be incremented by 1 and old parent should be decremented by 1.

The following is code. Head_count is decrementing on old parent but its not incrementing on new parent(In debug logs its showing correct value but not in front end).

Can anyone please tell me where its going wrong.

if(Trigger.isUpdate ){
   Set<Id> parentIdSet2 = new Set<Id>();
    for(Position__c record : trigger.new)
    {
        parentIdSet2.add(record.Parent_Position__c);
    }
    Map<Id,Position__c> allParentRecords2 = new Map<Id,Position__c>([Select Head_Count__c from Position__c where id in :parentIdSet2]);
   Set<Id> parentIdSet3 = new Set<Id>();
    for(Position__c oldrecord : trigger.old)
    {
        parentIdSet3.add(oldrecord.Parent_Position__c);
    }
    Map<Id,Position__c> allParentRecords3 = new Map<Id,Position__c>([Select Head_Count__c from Position__c where id in :parentIdSet3]);

       for(Position__c record : trigger.new)
    {
        Position__c oldrecord = Trigger.oldMap.get(record.Id);
        if(record.Parent_Position__c!=oldrecord.Parent_Position__c)
        system.debug('old parent=='+oldrecord.Parent_Position__c );

        {
        if(allParentRecords2.size() > 0 && allParentRecords2.containsKey(record.Parent_Position__c))
        {
        system.debug('New parent=='+allParentRecords2.get(record.Parent_Position__c ));
        allParentRecords2.get(record.Parent_Position__c).Head_Count__c = allParentRecords2.get(record.Parent_Position__c).Head_Count__c + 1;
        system.debug('New parent=='+allParentRecords2.get(record.Parent_Position__c ));
        }
        if(allParentRecords3.size() > 0 && allParentRecords3.containsKey(oldrecord.Parent_Position__c))
        {
        system.debug('old parent=='+allParentRecords3.get(oldrecord.Parent_Position__c ));
        allParentRecords3.get(oldrecord.Parent_Position__c).Head_Count__c = allParentRecords3.get(oldrecord.Parent_Position__c).Head_Count__c - 1;
        system.debug('old parent=='+allParentRecords3.get(oldrecord.Parent_Position__c ));
        }
        }
    }
   update allParentRecords2.values();
   update allParentRecords3.values();   
 }
4
  • whenever you write or share a code, it would be a good practice to write comments. It will help not only others to understand, but also you will bring more confidence on your coding. Commented Apr 22, 2017 at 16:11
  • The conventional wisdom these days (and one in which I agree with) is to have code that is self-documenting. You can read more about it here: blog.codinghorror.com/coding-without-comments
    – willard
    Commented Apr 22, 2017 at 16:26
  • I think it may have something to do with in which phase (before/after) your trigger is being called. Updating other records should really be called within the after phase. Posting all of your trigger code will probably be helpful in this instance.
    – willard
    Commented Apr 22, 2017 at 16:33
  • @Willard, Thank you for your answer. I understood the logic you used but its not compiling. i am getting error in line Map<Id, Position__c> enhancedPositions = new Map<Id, Position__c>([select Id, (select Id from Positions__r ) from Position__c where Id in :Trigger.new]); Can you please help me here.
    – Ramya
    Commented Apr 23, 2017 at 5:45

1 Answer 1

1

Here's some code (not sure if it compiles, just wrote it in notepad) that i think will fix your problem. As you can see, there are two different actions in this trigger. One during the before phase and once during the after.

The after phase is what you should look at first, which is gathering all the positions that need their Head_Count field updated. This will then kick off an update call to the parent positions to properly update their Head_Count field.

The before phase is called on those parent positions, and using some child queries, the Head_Count size is update appropriately. No math involved, and this also handles bulk transactions in case multiple child positions are moved.

In addition, this solution requires only one SOQL query and only issues one additional DML statement vs. the two that you have in your code above.

If you have some insert logic in this trigger, then you can just update this code to use if (Trigger.isUpdate) to compartmentalize it.

trigger PositionTrigger on Position__c(before update, after update) {
    if (Trigger.isBefore) {
        Map<Id, Position__c> enhancedPositions = 
            new Map<Id, Position__c>([select Id, (select Id from Positions__r /* or whatever you child relationship is called */) 
                from Position__c where Id in :Trigger.new]);
        for (Position__c position : Trigger.new) {
            position.Head_Count__c = enhancedPositions.get(position.Id).Positions__r.size();
        }
    }
    if (Trigger.isAfter) {
        Position__c[] positionsToUpdate = new List<Position__c>();
        for (Position__c position : Trigger.new) {
            Position__c oldPosition = Trigger.oldMap.get(position.Id);
            if (oldPosition.Parent_Position__c != position.Parent_Position__c) {
                positionsToUpdate.add(new Position__c(Id = position.Parent_Position__c));
                positionsToUpdate.add(new Position__c(Id = oldPosition.Parent_Position__c));
            }
        }
        update positionsToUpdate;
    }
}
3
  • can you please explain order of execution of code? I have little knowledge on triggers. here map enhancedPositions is not updating and is not linked to isafter part then how come i can see correct head_count values after update. Please help me in understanding.
    – Ramya
    Commented Apr 23, 2017 at 15:38
  • When a trigger is invoked, it actually runs twice if you have both before and after actions specified: once in the before phase, and then in the after phase. You must take care to conditionally execute your code depending on which phase you are in. You should also look into a trigger framework to help organize your code.
    – willard
    Commented Apr 23, 2017 at 22:39
  • The before phase executes before the record is saved to the database. So whatever fields you change in this phase will be saved to the db. The after phase executes after the record has been saved to the db and so any updates to fields you make will not be saved. The after phase is usually used to update related records, which in your case would be the parent positions.
    – willard
    Commented Apr 23, 2017 at 22:42

You must log in to answer this question.

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