Skip to content

Person Account fields not supported in Entry Criteria Formula #194

@TrangOul

Description

@TrangOul

Person Account fields defined on Contact, both standard ones, prefixed with PersonContact and custom ones, suffixed with __pc, cannot be used in the Entry Criteria Formula.

There is a bug that does not allow us to use Person Account fields in Account formulae:

Example:

NOT(ISBLANK(PersonOtherPhone))

Result:
AccountTrigger: execution of BeforeUpdate caused by: System.IllegalArgumentException: Something is wrong with the filter on the Trigger_Action__mdt record with DeveloperName = TaLogBU on the Account sObject. It could be the case that the AccountTriggerRecord class which is specified in the TriggerRecord_Class_Name__c referenced on the SObject_Trigger_Setting__mdt is not global, or it could be that the formula is syntactically invalid : NOT(ISBLANK(record.PersonOtherPhone)) Class.FormulaFilter.getFormulaInstance: line 164, column 1 Class.FormulaFilter.filterByEntryCriteria: line 90, column 1 Class.MetadataTriggerHandler.executeActions: line 409, column 1 Class.MetadataTriggerHandler.beforeUpdate: line 213, column 1 Class.TriggerBase.run: line 230, column 1 Class.TriggerHandler.run: line 17, column 1 Class.TriggerHandler.run: line 3, column 1 Trigger.AccountTrigger: line 2, column 1

(after un-wrapping the FormulaFilter class:
Error on line 104, column 1: System.FormulaValidationException: Field PersonOtherPhone does not exist. Check spelling. (System Code)
)


There is a workaround, described in the link above: use Contact relationship:

NOT(ISBLANK(PersonContact.OtherPhone))

...but since we're in the trigger context, we only have the shallow Account fields, and the field evaluates to null and the entire formula to false.


We can make a workaround by querying the related Contact in the AccountTriggerRecord class:

global class AccountTriggerRecord extends TriggerRecord {
	global Account record {
		get {
			return (Account) [
				SELECT Id,
					PersonContact.Phone
					// other fields used by Account Trigger Actions
				FROM Account
				WHERE Id = :this.newSobject.Id
			];
		}
	}
	
	// same for recordPrior
}

... but this wastes a query, and we'd need to query all the fields used in all Trigger Actions' formulae on this SObject (unless we traversed the Schema to build the query dynamically with all the fields, which has its own drawbacks).


Since we already have the data in the Account's fields, and it's only the formula that cannot access them, we can expose them as TriggerRecord properties:

global class AccountTriggerRecord extends TriggerRecord {
	global String personOtherPhone {
		get {
			Account acc = (Account) this.newSobject;
			return acc.PersonOtherPhone;
		}
	}
	
	// other properties

and use the formula

NOT(ISBLANK(personOtherPhone))

This works, but deviates from the SObject data model, and, again, requires us to explicitly list all the fields used in Trigger Actions formulae, one by one. Twice, for new and old record...


Is there a way to make TriggerRecord a dynamic getter for a Person Account, compatible with FormulaInstance, without querying the related Contact and listing all the fields manually (hence dynamic)?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions