+ Start a Discussion
Bard09Bard09 

Batch Apex triggering validation rule with ISCHANGED() exemption?

Hey all,

 

First time using Batch Apex to do a large bulk update.  I'm hoping to be able to run this monthly as a kind of cron job to keep a static financial field synced up each month.

 

global class MonthlyOpportunityAAV implements Database.Batchable <sObject>, Database.Stateful {

	public List <Opportunity> updateOpportunityList;

	global database.querylocator start(Database.BatchableContext BC) {
    
    	updateOpportunityList = new List <Opportunity> ();
    	
    	return Database.getQueryLocator('SELECT Id, Annualized_Value__c, Monthly_AV__c, Monthly_AV_Match__c FROM Opportunity WHERE Monthly_AV_Match__c=\'False\'');
    	
    }

    global void execute(Database.BatchableContext BC, List <sObject> scope) {

		for (sObject s : scope) {
    		
    		Opportunity o = (Opportunity)s;
    		
    		if (o.Annualized_Value__c != o.Monthly_AV__c) {
    		
	    		o.Monthly_AV__c = o.Annualized_Value__c;
	    		updateOpportunityList.add(o);
	    		
    		}
    		
    	}
    	
    	if (!updateOpportunityList.isEmpty()) {
    		
    		try {
    			update updateOpportunityList;
	    	}
	    	catch (DmlException e) {
	    		for (Integer i = 0; i < e.getNumDml(); i++) {
			    	System.debug('DMLERROR for ' + e.getDmlId(i) + ': ' + e.getDmlMessage(i));
			    }
	    	}
    		
    	}
    	

    }

}

 

I've kicked off this Batch Apex a few times, and it appears to work for a few hundred Opportunities, but then it gets hung up on a bunch of Opps that fail due to validation rules.  Here's an example of one of those rules:

 

IF(ISCHANGED(Monthly_AV__c),

FALSE,

BlahBlahBlah

)

 

As you can see, I've tried to exempt the rule from being executed if it detects an update to the Monthly AV field.  Unfortunately, this doesn't seem to be working in my code.  When I've reviewed some of the errors I get during the Batch Apex update, here's what I see.  (this is an example)

 

10:47:32.818 (186818515000)|EXCEPTION_THROWN|[33]|System.DmlException: Update failed. First exception on row 5 with id 0065000000FLPqjAAH; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, A Payment Type ID is required for this Payment Type.: [Payment_Type_Id__c]
10:47:32.989 (186989044000)|SYSTEM_METHOD_ENTRY|[36]|Exception.getNumDml()
10:47:32.989 (186989074000)|SYSTEM_METHOD_EXIT|[36]|Exception.getNumDml()
10:47:32.989 (186989103000)|SYSTEM_METHOD_ENTRY|[37]|Exception.getDmlId(Integer)
10:47:32.989 (186989130000)|SYSTEM_METHOD_EXIT|[37]|Exception.getDmlId(Integer)
10:47:32.989 (186989172000)|SYSTEM_METHOD_ENTRY|[37]|Exception.getDmlMessage(Integer)
10:47:32.989 (186989189000)|SYSTEM_METHOD_EXIT|[37]|Exception.getDmlMessage(Integer)
10:47:32.989 (186989211000)|SYSTEM_METHOD_ENTRY|[37]|System.debug(ANY)
10:47:32.989 (186989221000)|USER_DEBUG|[37]|DEBUG|DMLERROR for 0065000000FLPqjAAH: A Payment Type ID is required for this Payment Type.
10:47:32.989 (186989228000)|SYSTEM_METHOD_EXIT|[37]|System.debug(ANY)
10:47:32.989 (186989238000)|SYSTEM_METHOD_ENTRY|[36]|Exception.getNumDml()
10:47:32.989 (186989248000)|SYSTEM_METHOD_EXIT|[36]|Exception.getNumDml()
10:47:32.989 (186989259000)|SYSTEM_METHOD_ENTRY|[37]|Exception.getDmlId(Integer)
10:47:32.989 (186989270000)|SYSTEM_METHOD_EXIT|[37]|Exception.getDmlId(Integer)
10:47:32.989 (186989281000)|SYSTEM_METHOD_ENTRY|[37]|Exception.getDmlMessage(Integer)
10:47:32.989 (186989291000)|SYSTEM_METHOD_EXIT|[37]|Exception.getDmlMessage(Integer)
10:47:32.989 (186989301000)|SYSTEM_METHOD_ENTRY|[37]|System.debug(ANY)
10:47:32.989 (186989306000)|USER_DEBUG|[37]|DEBUG|DMLERROR for 0065000000FLQ0oAAH: A Payment Type ID is required for this Payment Type.

 

Can anyone help me out with what's happening here?  Am I missing something obvious?  Order of execution issue?  Exception-handling issue?

 

Kind of at a loss :\

bob_buzzardbob_buzzard

Is this definitely coming from a validation rule?  It looks like a simple save error, which could be coming from a trigger.  Failing that, are there any triggers on opportunity?

Bard09Bard09

As far as I can tell, it is coming from a validation rule, no?  That's what the "FIELD_CUSTOM_VALIDATION_EXCEPTION" means in the debug output I posted-- and the same message appears to be popping for other records in the batch as well.

 

I do have other triggers on Opportunities that could theoretically execute but according to the rest of the debug log, they aren't.

 

The main thing I'm wondering about is-- if my ISCHANGED() part of the Validation rule is working appropriately, why is this error getting triggered.  The only thing I'm updating is the Monthly_AV__c field.

 

Maybe this will help; these are the two lines before the Exception on my debug log.  I'm not an expert in parsing logs, but does this mean the DML update is finished when these errors are occuring?  (meaning that for some reason the Opp is being updated a 2nd time, when the Monthly_AV__c field is NOT changing?)

 

10:47:25.283 (179283023000)|CODE_UNIT_FINISHED|Workflow:Opportunity
10:47:32.818 (186818289000)|DML_END|[33]
10:47:32.818 (186818515000)|EXCEPTION_THROWN|[33]|System.DmlException: Update failed. First exception on row 5 with id 0065000000FLPqjAAH; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, A Payment Type ID is required for this Payment Type.: [Payment_Type_Id__c]

 

Any suggestions will help.  I'm just stymied what could be triggering this error!

 

 

Bard09Bard09

Looks like the issue might have been the Monthly_AV_Match__c formula field I was using in my SOQL query.  I was using it to detect mismatches between the two fields, but it wasn't working as I'd expected it to.  Even though both fields were resolving to 2 decimal places, I needed to add ROUND(number, 2) to each of them in order to get the correct amount of precision.

 

Running the batch Apex now appears to work without any errors.  Fingers are crossed :)