Skip to content

Interplay between onValidate and onAfterInsert/Update #14

@cropredy

Description

@cropredy

By way of example, I've excerpted from the samplecode Domain Opportunities.cls.

Is this by design?

If onValidate() places an error via opp.Type.addError(error(msg,opp,fieldToken)) on some record in the batch, say record 22, then when the onAfterInsert comes along, the Accounts related to all opportunities in the batch including record 22, will go through the update via uow.commitWork().

This seems flawed, - if there is a onValidate() handler error, the affected records should be excluded in the sample code from inclusion in accountIds.

It would be nice if there were an easy way to communicate the erroneous records between handlers in the framework, but the errors(...) method only saves the errors in a list, not a map keyed by the record.ID.

I could, I guess, introduce my own error(...) into a subclass of fflib_SObjectDomain that in turn is extended by Opportunities.cls. My version of error(..) would capture the errorneous record id in a map for inspection by the onAfterInsert and onAfterUpdate handlers.

But I'm wondering if I'm missing something provided by the Domain layer that would obviate this seemingly basic feature.

    public override void onValidate(Map<Id,SObject> existingRecords)
    {
        // Validate changes to Opportunities
        for(Opportunity opp : (List<Opportunity>) Records)
        {
            Opportunity existingOpp = (Opportunity) existingRecords.get(opp.Id);
            if(opp.Type != existingOpp.Type)
            {
                opp.Type.addError( error('You cannot change the Opportunity type once it has been created.', opp, Opportunity.Type) );
            }
        }
    }

    public override void onAfterInsert()
    {
        // Related Accounts
        List<Id> accountIds = new List<Id>();
        for(Opportunity opp : (List<Opportunity>) Records)
            if(opp.AccountId!=null) // ?! what about excluding the opps that had their type changed ?
                accountIds.add(opp.AccountId);

        // Update last Opportunity activity on the related Accounts (via the Accounts domain class)
        fflib_SObjectUnitOfWork uow = new fflib_SObjectUnitOfWork(new Schema.SObjectType[] { Account.SObjectType }); 
        Accounts accounts = new Accounts([select Id, Name from Account where id in :accountIds]);
        accounts.updateOpportunityActivity(uow);
        uow.commitWork();               
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions