[SalesForce] Records retaining lock when recall of approval process is complete

I have a custom object called Journal and they have line items. There is an approval process on the journal and the journal in question was in the approval process. The process was recalled and the recall action is set to unlock the record. This has been done and the journal shows no unlock record button. This tells me it is no longer locked as the approval process action is setup to do. The issue is, we are getting an error out of the AfterUpdate trigger on Journal, stating the journal line item entity is locked and can't be edited.

The error is:

There were custom validation error(s) encountered while saving the
affected record(s). The first validation error encountered was "Apex
trigger ffgl.Journal caused an unexpected exception, contact your
administrator: ffgl.Journal: execution of AfterUpdate caused by:
Systmem.DmlException: Update failed. First exception on row 0 with id
a0xa000000EDlDCAAT; first error: ENTITY_IS_LOCKED, the entity is
locked for editing:[]: (ffgl)."

Any help on this would be great. I don't understand how SF determines if a record is locked. I thought at first it would be a standard field like isLocked but I don't see this on the objects. Does anyone know how SF tracks this? I am wondering if they locked the journal entity and its children the journal line items and when the recall was done only unlocked the journal and not the line items.

Best Answer

Why don´t you approve this process by quering the ProcessInstanceWorkitem, you can access the ProcessInstance Object to check for pending, rejected or approved requests and do specific actions on each case. Here is an example on how to approve one Item:

public static void approveApproval(Id aeId) {
        List<ProcessInstanceWorkitem> listaAprobacionPendiente = [SELECT Id, ProcessInstance.TargetObjectId
                                                                    FROM ProcessInstanceWorkitem
                                                                   WHERE ProcessInstance.TargetObjectId =:aeId];


        Approval.ProcessWorkitemRequest req = new Approval.ProcessWorkitemRequest();
        req.setComments('Aprobado desde proceso automático de aprobación.');
        req.setAction('Approve');
        req.setWorkitemId(listaAprobacionPendiente[0].Id);
        Approval.ProcessResult result = Approval.process(req);
}