[SalesForce] error when trying to approve request

hello i created a trigger who auto submit the approval request into the approval process. when i create opportunity with the entry criteria of the trigger and the procces i get to approval requeset if i try to approve or reject one of them i get this error:

Validation Errors While Saving Record(s)

There were custom validation error(s) encountered while saving the
affected record(s). The first validation error encountered was "Apex
trigger OpportunitySubmitForOrderListApproval caused an unexpected
exception, contact your administrator:
OpportunitySubmitForOrderListApproval: execution of AfterUpdate caused
by: System.DmlException: Process failed. First exception on row 0;
first error: ALREADY_IN_PROCESS, This record is currently in an
approval process. A record can be in only one approval process at a
time.: []: Trigger.OpportunitySubmitForOrderListApproval: line 10,
column 1".

this is the trigger

trigger OpportunitySubmitForOrderListApproval on Opportunity(after update) {
    for (Integer i = 0; i < Trigger.new.size(); i++) {
        if ((Trigger.old[i].Integration_fees__c == 0 && Trigger.old[i].Integration_waived__c == True) && (Trigger.new[i].Integration_fees__c == 0 && Trigger.new[i].Integration_waived__c == True)) {
            // create the new approval request to submit
            Approval.ProcessSubmitRequest req = new Approval.ProcessSubmitRequest();
            req.setComments('Submitted for approval. Please approve.');
            req.setObjectId(Trigger.new[i].Id);
            // submit the approval request for processing
            Approval.ProcessResult result = Approval.process(req);
            // display if the reqeust was successful
            System.debug('Submitted for approval successfully: ' + result.isSuccess());
        }
    }
}

this is the entry criteria of the proccess.

(Opportunity: Integration fees EQUALS 0) AND (Opportunity: Integration waived EQUALS True).

Thank you very much to the helpers!!
i'm getting crazy from this problem.

Best Answer

This trigger is not bulkified. You can create a set of records for submission in an initial for loop. That removes any duplicate Ids of records that may already be contained in your trigger. Since that's unlikely, you may need to run a query to see if there's already an approval process going on this record. I responded to the question you asked yesterday and still don't see anything that prevents recursion. So it's likely that you're attempting to create duplicate approval processes on the same records.

Use a 2nd for loop to create your submissions. Be aware that each ProcessSubmitRequest counts as one DML operation. Your execution context can only contain a total of 150 DML operations before you'll exceed governor limits. For that reason, it would be wise to use the limits class to check available DML limits before you proceed.

Compare available DML limits with the number of records that you need to process if you're going to do them individually. That's the only way I've seen this done, but it may be possible to do it using a list or map. I can't say as I've never tried. Otherwise, you'll want to use an @future call to move this to an asynchronous process where you could "chain" them in queuables using loops of no more than 150 records per transaction before calling another queueble to process the remaining records.

For your recursion, you need to first create the following class:

Public class triggerHelper{

  Public static boolean reEntry = false;

}

Now, modify the start of your code as follows:

trigger OpportunitySubmitForOrderListApproval on Opportunity(after update) {
    if(!triggerHelper.reEntry){
        triggerHelper.reEntry = true;

        // now start your for loop
        for (Integer i = 0; i < Trigger.new.size(); i++) {


        } // end of for loop

    } // end if

} // end trigger

The 2nd time your trigger is called in an execution context, the boolean will be true and your trigger won't execute to create an 2nd approval process instance.