+ Start a Discussion
larrmill59larrmill59 

Approval process help please

I am trying to use a trigger to do 2 things upon creation of a new custom object record. First it needs to fill in a field with the name of the account owner. The second is after that field is filled in, it will fire the approval process, since the account owner needs to be specified to the approvers.

 

Thanks to several of you here, I'm getting closer, but still not able to get this to work. Now my trigger compiles fine, but when I create a new record and click Save, it gives me the following error.

 

Error: Invalid Data.
Review all error messages below to correct your data.
Apex trigger Approval caused an unexpected exception, contact your administrator: Approval: execution of AfterInsert caused by: System.DmlException: Process failed. First exception on row 0; first error: NO_APPLICABLE_PROCESS, No applicable approval process found.: []: Trigger.Approval: line 33, column 9

 

My code is below. What am I missing here?

 

trigger Approval on RME__c (before insert, after insert) {
    /* Modify the new object here */
    if(Trigger.isBefore) {
        Set<Id> accountIDs = new Set<Id>();
    for(RME__c c:Trigger.new) {
            if(c.account__c != null) {
                accountIDs.add(c.Account__c);
            }
        

        List<Account> accountList = new List<Account>([SELECT Owner.Firstname, Owner.LastName FROM Account WHERE id IN :accountIDs]);
        for(Account a:accountList) {
                  //set your field values here.
   c.Account_Executive__c = a.owner.FirstName + ' ' + a.owner.LastName;
   Database.update(accountList);
        }
        }
       
        }
    /* Perform the approval submit in the after */
    else {

        List<Approval.ProcessRequest> requests = new List<Approval.ProcessRequest>();

        for(RME__c c:Trigger.new) {

            Approval.ProcessSubmitRequest req = new Approval.ProcessSubmitRequest();
            req.setComments('The comment');
            req.setObjectId(c.id);
            requests.add(req);
        }

        Approval.process(requests);
    }

}

Best Answer chosen by Admin (Salesforce Developers) 
larrmill59larrmill59

The problem was that my approval process had entry criteria where it depends on the region, and I didn't cover that in the trigger. Once I added that line to the "before insert" code, it worked perfectly. Below is the final version.

 

 

 

trigger Approval on RME__c (before insert, after insert) {
    /* Modify the new object here */
    if(Trigger.isBefore) {
        Set<Id> accountIDs = new Set<Id>();
    for(RME__c c:Trigger.new) {
            if(c.account__c != null) {
                accountIDs.add(c.Account__c);
            }
        List<Account> accountList = new List<Account>([SELECT Owner.Firstname, Owner.LastName, Region__c FROM Account WHERE id IN :accountIDs]);
        for(Account a:accountList) {
                  //set your field values here.
   c.Account_Executive__c = a.owner.FirstName + ' ' + a.owner.LastName;
   c.Region__c = a.Region__c;
          }
        }
              } 
    /* Perform the approval submit in the after */
    else {
        for(RME__c c:Trigger.new) {
       c = [ select ID from RME__c where id in :Trigger.new ];
            Approval.ProcessSubmitRequest req = new Approval.ProcessSubmitRequest();
            req.setComments('The comment');
            req.setObjectId(c.id);
            Approval.ProcessResult result = Approval.process(req); 
         System.assert(result.isSuccess());
                 }
          }
}

All Answers

dmchengdmcheng

Why not just create a formula field in RME that looks up the Account owner name fields?

 

If you've tried that already and the formula field is not evaluated before the trigger (I can't remember the order), then your before trigger code is not correct.

 

trigger Approval on RME__c (before insert, after insert) {
    /* Modify the new object here */
    if(Trigger.isBefore) {
        Set<Id> accountIDs = new Set<Id>();

		for(RME__c c:Trigger.new) {
			if(c.account__c != null) {
				accountIDs.add(c.Account__c);
			}
		}

		Map<Id, Account> acctMap = new Map<Id, Account>([SELECT Owner.Firstname, Owner.LastName FROM Account WHERE id IN :accountIDs]);
    
        for(RME__c c:Trigger.new) {
			if(c.account__c != null) {
			   c.Account_Executive__c = acctMap.get(c.account__c).owner.FirstName + ' ' + acctMap.get(c.account__c).owner.LastName;
	        }
        }

	}       
}

 

 

 

 

larrmill59larrmill59

The problem was that my approval process had entry criteria where it depends on the region, and I didn't cover that in the trigger. Once I added that line to the "before insert" code, it worked perfectly. Below is the final version.

 

 

 

trigger Approval on RME__c (before insert, after insert) {
    /* Modify the new object here */
    if(Trigger.isBefore) {
        Set<Id> accountIDs = new Set<Id>();
    for(RME__c c:Trigger.new) {
            if(c.account__c != null) {
                accountIDs.add(c.Account__c);
            }
        List<Account> accountList = new List<Account>([SELECT Owner.Firstname, Owner.LastName, Region__c FROM Account WHERE id IN :accountIDs]);
        for(Account a:accountList) {
                  //set your field values here.
   c.Account_Executive__c = a.owner.FirstName + ' ' + a.owner.LastName;
   c.Region__c = a.Region__c;
          }
        }
              } 
    /* Perform the approval submit in the after */
    else {
        for(RME__c c:Trigger.new) {
       c = [ select ID from RME__c where id in :Trigger.new ];
            Approval.ProcessSubmitRequest req = new Approval.ProcessSubmitRequest();
            req.setComments('The comment');
            req.setObjectId(c.id);
            Approval.ProcessResult result = Approval.process(req); 
         System.assert(result.isSuccess());
                 }
          }
}
This was selected as the best answer
dmchengdmcheng

Ah yes.  However, you also have SOQL statements inside your for loops and that can cause you to exceed governor limits.