You need to sign in to do that
Don't have an account?
ENTITY IS LOCKED Error when updating child record when parent is approved
We have built a Purchase Order system into Salesforce. The Purchase Order object is a parent of the Purchase Item object, and when the PO is approved, a trigger fires which updates all the PIs with the value of the PO Stage field.
However, that trigger prevents the Purchase Order from being approved, as it generates the following error:
There were custom validation error(s) encountered while saving the affected record(s). The first validation error encountered was "Apex trigger PurchaseOrderTrigger caused an unexpected exception, contact your administrator: PurchaseOrderTrigger: execution of AfterUpdate caused by: System.DmlException: Update failed. First exception on row 0 with id a0W200000091BnTEAU; first error: ENTITY_IS_LOCKED, the entity is locked for editing: []: Class.PurchaseItemTriggerMethods.copyStageToStatusFromOrder: line 131, column 1".
Here is the firing trigger:
trigger PurchaseOrderTrigger on Purchase_Orders__c (after update) { PurchaseItemTriggerMethods.copyStageToStatusFromOrder(Trigger.newMap); }
And here are the relevant lines of the class:
public static void copyStageToStatusFromOrder(Map<Id, Purchase_Orders__c> purchOrderMap) { Map<Id,Purchase_Item__c> purchItemMap = new Map<Id,Purchase_Item__c>([Select Status_Copy__c, Stage__c From Purchase_Item__c Where Purchase_Order__c IN :purchOrderMap.KeySet()]); Map<Id,Purchase_Item__c> purchItemMapEmpty = new Map<Id,Purchase_Item__c>(); copyStageToStatusFromItem(purchItemMap.Values(), purchItemMapempty, True); Update purchItemMap.Values(); }
From my research I have found that it might be something to do with using an after update and the Trigger.newMap value. However, I have not found the right changes that will fix the issue.
Can anyone help?
I managed to solve this by changing the approval process to allow the current approver to edit the record during the approval process.
So the child records can be updated by the parent when they approve.
All Answers
Something on the child is trying to update the parent when you update the child (roll-up summary, trigger, etc)
Try simply changing the trigger to a before update..
Hi Starz26
I tried that but there is a test class system.assert which checks the status update has happened, and it now fails.
Any other ideas?
Thanks.
Then you will have to debug your code to find out why the status is changed.
When you are doing the system assert, did you query for the record again before doing the assert?
You cannot just use the inserted record to do the assert. For example this WILL NOT work:
Account a = New Account(Name = 'Test');
Insert a;
//Trigger updated a Custome__c field
system.assertEquals(True,a.Custom__c != Null);
This will fail as the a variable is not updated with new values except for the ID.
You have to query before the systemassert:
a = [Select Custom__c From Account where ID = :a.id];
system.assertEquals(True,a.Custom__c != Null);
This will work.
So either your trigger is not doing what it is supposed to or your test method is not testing properly. The simple act of doing a before vs after insert should not make your test methodsfail as everything is done after the record is committed regardless of the trigger context.
Thanks for your reply again, Starz26.
I have tried debugging the code, but I can't find any clues.
Here is the test class which, as you described, re-queries before the system.assert (the last few lines are the most relevant):
Any help?
When you do this via the UI (Not test methods) does it work??
If so then you are going to have to go through your code line by line, review what the values should be, compare them to what they are, and find out where it is going wrong.
If it works in the UI it should work in the test method....
Another way to go about it:
- Following exactly what your test method is doing, complete those steps in sequence LIVE (via the UI). See what the results are.
It is difficult to follow your code so you are going to have to do a bit of the work using debug logs, developer console, etc.
The key part is that changing it from after update to before update should not afftect your test methods....either the trigger is not correct or the test methods are not correct.....IMHO
Thanks for your feedback, again, Starz26.
So it seems, at least partly, that I was being an idiot - the test class was working and correct. It seems the trigger is not working in the 'before update' position.
I have a theory that this may be something to do with the fact that the field that is being used to update another field is formula. I think the value of the field is not recalculated until after the update, and therefore the trigger updates with the wrong value.
Here are the workings of the trigger:
Let me know if this makes sense, and if I'm right about the problem.
Thanks again.
I managed to solve this by changing the approval process to allow the current approver to edit the record during the approval process.
So the child records can be updated by the parent when they approve.
Thank you.