Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Advanced Rollup API Reqiurement: Count of Child on Parent, Child Re-parent, Old Parent Count not Correct #167

Closed
daveerickson opened this issue May 11, 2015 · 12 comments

Comments

@daveerickson
Copy link

This is certainly a more complicated scenario, but I have child Account records looking up to Parent Account records through a custom lookup field. I created a number field to hold the count of the children on the parent. I set the Calculation Mode to Process Builder. When adding a child record to the parent, the parent gets updated correctly. When a child is moved to a new parent the new parent is updated correctly, but the old parent is left with an incorrect count.

I can image there would need to be some capturing of the referred parent from the Trigger.oldmap to update that record as well as the value in the Trigger.new record. I haven't looked through the code, so I don't know how hard this would be to implement. As a workaround would I need to make my calculate mode Developer and add such logic on my own?

EDIT: It does pick up and correct the old parent if I run the scheduled job for that rule, fwiw.

@afawcett
Copy link
Collaborator

Hmmm i need to reproduce this to confirm, but quite possibly your correct. In the meantime, have you had a read through this blog about building Account Hierarchy rollups. If you get it working using Realtime mode, then switch to Process Builder mode.

@daveerickson
Copy link
Author

So I started to look into the code and it appears that if I deploy the Child Trigger that the dlrs.RollupService.triggerHandler() will indeed collect the old parent and new parent id's to be recalculated. Let me step back to what I ultimately want to get working...

I found your articles regarding Apex Enterprise Patterns and love them. I want to build a basic domain and selector class for all of our objects, and collect all triggers into the single trigger and domain class. Where would dlrs fit into the enterprise patterns? I was going to go the route of Process Builder to not have to mess with figuring this out. But, since you have intimate knowledge of both projects... :)

I think setting it up in Realtime with another trigger could introduce some inconsistent behaviors in some conditions so I'd rather avoid that. Setting it to developer seems to be an option, but where does the logic belong to identify the parent id's, in the domain, or a separate service class?

I appreciate your thoughts on this matter.

@afawcett
Copy link
Collaborator

Thanks @daveerickson, glad you like the articles and great question! 👍

I included Developer mode to allow for integration into existing processes or triggers. Now I've not tried this actually myself, so keen to see how this works out for you and what feedback you have...

But you can do is call this method from your Child Domain class method onAfterInsert, onAfterUpdate and onAfterUpdate. Note the method returns master records you will need to update via DML. Roughly.... something like

public override void onAfterInsert() {
    update dlrs.RollupService.rollup(Records);
}

public override void onAfterUpdate() {
    update dlrs.RollupService.rollup(Records);
}

public override void onAfterDelete() {
    update dlrs.RollupService.rollup(Records);
}

This API will seek out Rollups set to Developer mode automatically, so once you have set added the API calls to your own triggers/domain classes you can declaratively add to as many rollups from the child object as you like.

Note also that the API will not like the Realtime mode, check the child records to see if anything has changed, since it does not have the old and new versions. So be sure to call the API only when you feel the child records contain changes. There has not been much use of the API tbh, so i'm keen to get feedback.... writing this i wonder if the API should allow the caller to pass in old and new and let it do the same checking as the Realtime mode...

@afawcett
Copy link
Collaborator

@daveerickson Did this help?

@daveerickson
Copy link
Author

My apologies for not responding sooner. I plan to work on and test this out this week. Bigger fish got in this one's way.

@daveerickson
Copy link
Author

Unfortunately the Developer API version does not recalculate the old parent, similar to the Process Builder method. What does work is to create a domain class like this:

public with sharing class Accounts extends fflib_SObjectDomain
{
    public Accounts(List<Account> sObjectList)
    {
        super(sObjectList);
    }

    public override void onAfterInsert()
    {
        dlrs.RollupService.triggerHandler();
    }

    public override void onAfterUpdate(Map<Id,SObject> existingRecords)
    {
        dlrs.RollupService.triggerHandler();
    }

    public override void onAfterDelete()
    {
        dlrs.RollupService.triggerHandler();
    }

    public class Constructor implements fflib_SObjectDomain.IConstructable
    {
        public fflib_SObjectDomain construct(List<SObject> sObjectList)
        {
            return new Accounts(sObjectList);
        }
    }
}

Then I have to deploy the child trigger and disable it so it doesn't actually fire. The Lookup Rollup Summary record is saved as Realtime.

I'm not sure the best way to correct the deficiency in dlrs. It seems like repeating the logic to do the rollups in 3 places may not be the best if it can be avoided. The logic seems most correct when fired from the triggerHandler() method. The caveat is the record needs to be saved with Realtime, which it can't do unless the trigger is deployed. Not awful, but it would be preferable to not require the trigger so I could put the logic elsewhere.

Thanks for your help. For now I have a workable solution. :)

@afawcett
Copy link
Collaborator

afawcett commented Jun 6, 2015

Yes, i've mark this as an enhancement now, need to improve the API to have this functionality, though the caller will need to pass in the old master record ID as the system has no way of figuring this out. I will also expose a method that can be called from a trigger without having to have the requirements of Realtime in terms of activation.

@afawcett
Copy link
Collaborator

afawcett commented Jun 6, 2015

Also take a look at this, i think its more or less asking the same thing?

@daveerickson
Copy link
Author

Yes, that would satisfy my requirements. Thank you.

@jondavis9898
Copy link
Contributor

Hello @daveerickson - If I'm understanding your situation, I think #236 & #221 should provide what you need. The new developer API will behave just like triggerHandler including old/new parent checking, etc.

@afawcett
Copy link
Collaborator

Good spot @jondavis9898, @daveerickson this will be in the next managed package release coming up very soon! 👍

@afawcett afawcett changed the title Count of Child on Parent, Child Re-parent, Old Parent Count not Correct Advanced Rollup API Reqiurement: Count of Child on Parent, Child Re-parent, Old Parent Count not Correct Aug 30, 2015
@afawcett
Copy link
Collaborator

Fixed in v1.23

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants