4

February 26 Update: Still hoping someone can help me with this? Are there any takers?

February 23 Update: Still have issues. The updated helper class code is below (this is exactly what I have in my sandbox). It is still entering wrong values to the account when I mass insert new children but when I go in and edit an individual child record the account does update as expected so the logic works but something is wrong when mass inserting only!! Any ideas please help!!??


Update from February 20: thank you so much for taking the time to help with this. The new code seems to have something wrong with it so I added an extra { bracket. But I am also not 100% sure the end of this line “ accountToRoomTypes.put(result.Hotel_Account__c, New Room_Type__c[])” is right (the “New Room_Type__c[]” specifically I think is wrong but I Can’t figure out why. Here is the error I get:

enter image description here

I forgot to mention that when I edit an individual child record after it has been mass inserted the account does update to be CORRECT everytime! There is something wrong with the mass upload of child records only

Original post: Hello developer community! I have written my first helper class and trigger but when I do a mass upload of records the calculations are not working! They work fine when I do an edit after the records are there, but not at mass upload. I have triged after insert and before insert. I have the debug log too if anyone wants to see it!

here is example of the issues I am seeing: enter image description here

TRIGGER:

trigger RoomTypeTrigger on Room_Type__c (after insert, after update, after delete) {

    set<id> parentid = new set<id>();
    list<Account> plist = new    list<Account>();

    if (Trigger.isUpdate || Trigger.isInsert) {
        AccountRoomRollups.rollupLineItems(trigger.new);
    }

    if (Trigger.isDelete) {
        AccountRoomRollups.rollupLineItems(trigger.old); {
        }
    }

}

HELPER CLASS:

public without sharing class AccountRoomRollups {
public static void rollupLineItems(List<Room_Type__c> lineItems) {
    if (lineItems != null && lineItems.isEmpty() == false) {
        //Get Account Ids
        Set<Id> accountIds = new Set<Id>();

        for (Room_Type__c lineItem : lineItems) {
            if (lineItem.Hotel_Account__c != null) {
                accountIds.add(lineItem.Hotel_Account__c);
            }
        }

        //Get Map of Account
        Map<Id, Account> Accounts = new Map<Id, Account>([SELECT Id, Room_Images_Mapped_Sum__c,
                Rooms_with_Image_Mapped_Count__c,
                Room_Types_Count__c, Rooms_without_Images__c
                FROM Account WHERE Id IN :accountIds]);

        //Aggregate Room_Images_Mapped_Sum__c
        Map<Id, Double> mappedSum = new Map<Id, Double>();
        Map<Id, Double> mappedRmTrue = new Map<Id, Double>();
        Map<Id, Double> countRm = new Map<Id, Double>();
        //List<String> Description = new List<String>();
        Map<Id, String> Description = new Map<Id, String>();

        String Descriptionstring = '';
        Double rollupSum = 0;
        Double mappedTrueSum = 0;
        Double rCountSum = 0;

        Map<ID,Room_Type__c[]> accountToRoomTypes = New Map<ID,Room_Type__c[]>();

        for (Room_Type__c result : [SELECT Hotel_Account__c, Image_Count_mapped__c,
                                    Mapped_Images_True__c,
                                    Room_Type_Count__c ,
                                    Room_Description__c,
                                    Needs_a_mapped_image__c
                                    FROM Room_Type__c WHERE Hotel_Account__c IN :accountIds ]) {

                if(!accountToRoomTypes.containsKey(result.Hotel_Account__c)){
                    accountToRoomTypes.put(result.Hotel_Account__c,New Room_Type__c[]{});

                accountToRoomTypes.get(result.Hotel_Account__c).add(result);
                }
        }

        for(ID acct_id : Accounts.keySet()){

            for(Room_Type__c result : accountToRoomTypes.get(acct_id)){

                Id parentId = (Id) result.get('Hotel_Account__c');

                Double rollupAmount = (Double) result.get('Image_Count_mapped__c');
                rollupSum += rollupAmount;
                Double mappedTrue = (Double) result.get('Mapped_Images_True__c');
                mappedTrueSum += mappedTrue;
                Double rCount = (Double) result.get('Room_Type_Count__c');
                rCountSum += rCount;

                mappedSum.put(parentId, rollupSum);
                mappedRmTrue.put(parentId, mappedTrueSum);
                countRm.put(parentId, rCountSum);

                Boolean needimage = (Boolean) result.get('Needs_a_mapped_image__c');
                String roomdescription = (String) result.get('Room_Description__c');

                IF (needimage == True) {
                    Descriptionstring += roomdescription + '\n';
                    System.debug('Descriptionstring: ' + Descriptionstring);
                }
                Description.put(parentId, Descriptionstring);
            }
        }

        //Map Amounts for Update
        List<Account> accToUpdate = new List<Account>();

        for (Id parentId : Accounts.keySet()) {
            Account acc = Accounts.get(parentId);

            Double rollupAmount = 0;
            Double mappedTrue = 0;
            Double rCount = 0;

            if (mappedSum.containsKey(parentId) || mappedRmTrue.containsKey(parentId) || countRm.containsKey(parentId)) {
                rollupAmount = mappedSum.get(parentId);
                mappedTrue = mappedRmTrue.get(parentId);
                rCount = countRm.get(parentId);
                Descriptionstring = Description.get(parentId);

                System.debug('Rollup Amount: ' + rollupAmount);
                System.debug('Mapped True: ' + mappedTrue);
                System.debug('rCount: ' + rCount);
                System.debug('Descriptionstring: ' + Descriptionstring);

            }

            if (rollupAmount != acc.Room_Images_Mapped_Sum__c || mappedTrue != acc.Rooms_with_Image_Mapped_Count__c || rCount != acc.Room_Types_Count__c) {
                acc.Room_Images_Mapped_Sum__c = rollupAmount;
                acc.Rooms_with_Image_Mapped_Count__c = mappedTrue;
                acc.Room_Types_Count__c = rCount;
                acc.Rooms_without_Images__c = Descriptionstring;
                accToUpdate.add(acc);

                System.debug('Rollup Amount: ' + rollupAmount);
                System.debug('Mapped True: ' + mappedTrue);
                System.debug('rCount: ' + rCount);
                System.debug('Descriptionstring: ' + Descriptionstring);

            }
        }

        //Update Account
        if (accToUpdate.isEmpty() == false) {
            update accToUpdate;
            System.debug('accToUpdate: ' + accToUpdate);
        }
    }
}

}

6
  • Is your trigger aggregating records that are still being loaded? Remember that the trigger will run in successive batches of 200 records (default). The aggregation won't be able to include records that have not yet been loaded.
    – ScottW
    Feb 18, 2015 at 16:14
  • I do have it set to 200 but I only loaded 25 records - it seems the problem is that the numbers are too high not too low! Do you think in general before insert is best or after insert (or both)?? Feb 18, 2015 at 16:17
  • A good rule of thumb would be to ask yourself do you need to use the record's ID? If not, then 'before' insert else 'after' insert.
    – TC Sutton
    Feb 18, 2015 at 16:31
  • Great rule! I do not need the IDs so I will do after. Do you have any ideas on why the counts would work correctly at UPDATE but they are not working when doing a mass insert or new records? Feb 18, 2015 at 16:53
  • Pavel I see you edited my post, did you make a change I should implement or just clean up? Feb 18, 2015 at 18:44

2 Answers 2

1

You do not appear to be resetting your values for each new account. Also, change your trigger context to just AFTER INSERT, AFTER UPDATE as you are performing the work to many times unnecessarily

It may not bee completely correct but basically I added the Room_Types to a map with the Account ID as the Key. Then I cycle through the Keys resetting them for each new key:

public without sharing class AccountRoomRollups {
    public static void rollupLineItems(List<Room_Type__c> lineItems) {
        if (lineItems != null && lineItems.isEmpty() == false) {
            //Get Account Ids
            Set<Id> accountIds = new Set<Id>();

            for (Room_Type__c lineItem : lineItems) {
                if (lineItem.Hotel_Account__c != null) {
                    accountIds.add(lineItem.Hotel_Account__c);
                }
            }

            //Get Map of Account
            Map<Id, Account> Accounts = new Map<Id, Account>([SELECT Id, Room_Images_Mapped_Sum__c,
                    Rooms_with_Image_Mapped_Count__c,
                    Room_Types_Count__c, Rooms_without_Images__c
                    FROM Account WHERE Id IN :accountIds]);

            //Aggregate Room_Images_Mapped_Sum__c
            Map<Id, Double> mappedSum = new Map<Id, Double>();
            Map<Id, Double> mappedRmTrue = new Map<Id, Double>();
            Map<Id, Double> countRm = new Map<Id, Double>();
            //List<String> Description = new List<String>();
            Map<Id, String> Description = new Map<Id, String>();

            String Descriptionstring = '';
            Double rollupSum = 0;
            Double mappedTrueSum = 0;
            Double rCountSum = 0;

            Map<ID,Room_Type__c[]> accountToRoomTypes = New Map<ID,Room_Type__c[]>();

            for (Room_Type__c result : [SELECT Hotel_Account__c, Image_Count_mapped__c,
                                        Mapped_Images_True__c,
                                        Room_Type_Count__c ,
                                        Room_Description__c,
                                        Needs_a_mapped_image__c
                                        FROM Room_Type__c WHERE Hotel_Account__c IN :accountIds ]) {

                    if(!accountToRoomTypes.containsKey(result.Hotel_Account__c))
                        accountToRoomTypes.put(result.Hotel_Account__c,New Room_Type__c[]{});

                    accountToRoomTypes.get(result.Hotel_Account__c).add(result);
            }

            for(ID acct_id : Accounts.keySet()){

                String Descriptionstring = '';
                Double rollupSum = 0;
                Double mappedTrueSum = 0;
                Double rCountSum = 0;

                for(Room_Type__c result : accountToRoomTypes.get(acct_id)){

                    Id parentId = (Id) result.get('Hotel_Account__c');

                    Double rollupAmount = (Double) result.get('Image_Count_mapped__c');
                    rollupSum += rollupAmount;
                    Double mappedTrue = (Double) result.get('Mapped_Images_True__c');
                    mappedTrueSum += mappedTrue;
                    Double rCount = (Double) result.get('Room_Type_Count__c');
                    rCountSum += rCount;

                    mappedSum.put(parentId, rollupSum);
                    mappedRmTrue.put(parentId, mappedTrueSum);
                    countRm.put(parentId, rCountSum);

                    Boolean needimage = (Boolean) result.get('Needs_a_mapped_image__c');
                    String roomdescription = (String) result.get('Room_Description__c');

                    IF (needimage == True) {
                        Descriptionstring += roomdescription + '\n';
                        System.debug('Descriptionstring: ' + Descriptionstring);
                    }
                    Description.put(parentId, Descriptionstring);
                }
            }

            //Map Amounts for Update
            List<Account> accToUpdate = new List<Account>();

            for (Id parentId : Accounts.keySet()) {
                Account acc = Accounts.get(parentId);

                Double rollupAmount = 0;
                Double mappedTrue = 0;
                Double rCount = 0;

                if (mappedSum.containsKey(parentId) || mappedRmTrue.containsKey(parentId) || countRm.containsKey(parentId)) {
                    rollupAmount = mappedSum.get(parentId);
                    mappedTrue = mappedRmTrue.get(parentId);
                    rCount = countRm.get(parentId);
                    Descriptionstring = Description.get(parentId);

                    System.debug('Rollup Amount: ' + rollupAmount);
                    System.debug('Mapped True: ' + mappedTrue);
                    System.debug('rCount: ' + rCount);
                    System.debug('Descriptionstring: ' + Descriptionstring);

                }

                if (rollupAmount != acc.Room_Images_Mapped_Sum__c || mappedTrue != acc.Rooms_with_Image_Mapped_Count__c || rCount != acc.Room_Types_Count__c) {
                    acc.Room_Images_Mapped_Sum__c = rollupAmount;
                    acc.Rooms_with_Image_Mapped_Count__c = mappedTrue;
                    acc.Room_Types_Count__c = rCount;
                    acc.Rooms_without_Images__c = Descriptionstring;
                    accToUpdate.add(acc);

                    System.debug('Rollup Amount: ' + rollupAmount);
                    System.debug('Mapped True: ' + mappedTrue);
                    System.debug('rCount: ' + rCount);
                    System.debug('Descriptionstring: ' + Descriptionstring);

                }
            }

            //Update Account
            if (accToUpdate.isEmpty() == false) {
                update accToUpdate;
                System.debug('accToUpdate: ' + accToUpdate);
            }
        }
    }
}
3
  • thank you so much for taking the time to help with this. The new code seems to have something wrong with it so I added an extra { bracket. But I am also not 100% sure the end of this line “ accountToRoomTypes.put(result.Hotel_Account__c, New Room_Type__c[])” is right (the “New Room_Type__c[]” specifically I think is wrong but I Can’t figure out why. I get the error shown above in my "update from Feb 20". Feb 20, 2015 at 17:56
  • Add "{}" after the array declaration, so that line now looks like: accountToRoomTypes.put(result.Hotel_Account__c, New Room_Type__c[]{})
    – kbentsen
    Feb 20, 2015 at 18:18
  • hi Kbentsen thank you for your help - this cleared the error but the data is still not working, I get the same results as before where all the results are too high in the rollupSum, mappedTrueSum and rCountsum each time (unless I edit an individual room type after it is mass created and then the account updates as expected without issue!!!). Feb 20, 2015 at 23:05
0

I think the issue is that in your trigger you're only checking items within the database to work out the sums, but ignoring other records within the trigger itself.

You're constructing a list of Accounts that are parents of the Room_Type__c records, then querying the database to find all Room_Type__c records associated with those accounts. This will retrieve all Room_Type__c records currently in the database, but not new Room_Type__c records within the same trigger context.

You can add some code to test this out. Add the following after you've populated the accountIds set.

Map<Id, Room_Type__c> inDB = [SELECT Id FROM Room_Type__c WHERE Hotel_Account__c IN :accountIds ];

for (Room_Type__c lineItem : lineItems) {
    system.assertEquals(true, inDB.containsKey(lineItem.Id), 'Room_Type__c ' + lineItem.Id + ' is not in the database');
}

I'm not 100% sure if this is the answer as I can't remember exactly how the after trigger works in cases like this. Let us know if this is or isn't the answer and I'll update this accordingly :)

BTW, is there any reason the Room_Type__c object isn't master/detail to the Account so you can use roll-up summaries?
If it has to be a lookup relationship, there are also other things out there that may help with this:

Don't fall into the trap of the IKEA effect. This seems like a common problem that other people have already solved.

1
  • Thanks Nick! I will try this out. Not trying to recreate the wheel, my understanding is the rollup header and declarative rollup will not enter a string of text pulled from text based on specific criteria like I am doing in this trigger (also standard rollup summary fields can only roll up limited functions as well). I will keep you posted on how this goes - much appreciated!! Feb 26, 2015 at 22:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .