diff --git a/rolluptool/src/classes/RollupService.cls b/rolluptool/src/classes/RollupService.cls index 61b69b7b..84a2163b 100644 --- a/rolluptool/src/classes/RollupService.cls +++ b/rolluptool/src/classes/RollupService.cls @@ -557,6 +557,7 @@ global with sharing class RollupService // Process lookups, // Realtime are added to a list for later LRE context creation and processing, // Scheduled result in parent Id's being emitted to scheduled item object for later processing + Map gd = Schema.getGlobalDescribe(); List realtimeLookups = new List(); List scheduledItems = new List(); for(LookupRollupSummary__c lookup : lookups) @@ -568,15 +569,21 @@ global with sharing class RollupService } else if(lookup.CalculationMode__c == RollupSummaries.CalculationMode.Scheduled.name()) { + // For polymoprhic relationships the master Id list maybe mixed types, associated with the correct rollup + SObjectType parentType = gd.get(lookup.ParentObject__c); + if(parentType==null) + continue; // For scheduled rollups queue the parent Id record for processing for (Id parentId : masterRecordIds) { - LookupRollupSummaryScheduleItems__c scheduledItem = new LookupRollupSummaryScheduleItems__c(); - scheduledItem.Name = parentId; - scheduledItem.LookupRollupSummary__c = lookup.Id; - scheduledItem.ParentId__c = parentId; - scheduledItem.QualifiedParentID__c = parentId + '#' + lookup.Id; - scheduledItems.add(scheduledItem); + if(parentId.getSobjectType() == parentType) { + LookupRollupSummaryScheduleItems__c scheduledItem = new LookupRollupSummaryScheduleItems__c(); + scheduledItem.Name = parentId; + scheduledItem.LookupRollupSummary__c = lookup.Id; + scheduledItem.ParentId__c = parentId; + scheduledItem.QualifiedParentID__c = parentId + '#' + lookup.Id; + scheduledItems.add(scheduledItem); + } } } } diff --git a/rolluptool/src/classes/RollupServiceTest4.cls b/rolluptool/src/classes/RollupServiceTest4.cls index 63794ee0..99e422cb 100644 --- a/rolluptool/src/classes/RollupServiceTest4.cls +++ b/rolluptool/src/classes/RollupServiceTest4.cls @@ -1,3 +1,29 @@ +/** + * Copyright (c) 2013, Andrew Fawcett + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Andrew Fawcett, nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**/ + @IsTest private class RollupServiceTest4 { diff --git a/rolluptool/src/classes/RollupServiceTest4.cls-meta.xml b/rolluptool/src/classes/RollupServiceTest4.cls-meta.xml index 7df4d0bf..8d2569d2 100644 --- a/rolluptool/src/classes/RollupServiceTest4.cls-meta.xml +++ b/rolluptool/src/classes/RollupServiceTest4.cls-meta.xml @@ -1,4 +1,4 @@ - 31.0 + 32.0 \ No newline at end of file diff --git a/rolluptool/src/classes/RollupServiceTest5.cls b/rolluptool/src/classes/RollupServiceTest5.cls new file mode 100644 index 00000000..8b2d4554 --- /dev/null +++ b/rolluptool/src/classes/RollupServiceTest5.cls @@ -0,0 +1,148 @@ +/** + * Copyright (c) 2013, Andrew Fawcett + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Andrew Fawcett, nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**/ + +@IsTest +private class RollupServiceTest5 { + + @IsTest + private static void testPolymorphicRelationshipsRealtime() { + + // Polymorphic lookup between Task and Account + LookupRollupSummary__c rollupSummaryA = new LookupRollupSummary__c(); + rollupSummaryA.Name = 'Test Rollup'; + rollupSummaryA.ParentObject__c = 'Account'; + rollupSummaryA.ChildObject__c = 'Task'; + rollupSummaryA.RelationShipField__c = 'WhatId'; + rollupSummaryA.FieldToAggregate__c = 'Id'; + rollupSummaryA.AggregateOperation__c = RollupSummaries.AggregateOperation.Count.name(); + rollupSummaryA.AggregateResultField__c = 'AnnualRevenue'; + rollupSummaryA.Active__c = true; + rollupSummaryA.CalculationMode__c = 'Realtime'; + insert rollupSummaryA; + + // Polymorphic lookup between Task and Opportunity + LookupRollupSummary__c rollupSummary = new LookupRollupSummary__c(); + rollupSummary.Name = 'Test Rollup'; + rollupSummary.ParentObject__c = 'Opportunity'; + rollupSummary.ChildObject__c = 'Task'; + rollupSummary.RelationShipField__c = 'WhatId'; + rollupSummary.FieldToAggregate__c = 'Id'; + rollupSummary.AggregateOperation__c = RollupSummaries.AggregateOperation.Count.name(); + rollupSummary.AggregateResultField__c = 'TotalOpportunityQuantity'; + rollupSummary.Active__c = true; + rollupSummary.CalculationMode__c = 'Realtime'; + insert rollupSummary; + + // Setup parent test records + Account accountParent = new Account(Name = 'Test Account'); + insert accountParent; + Opportunity opp = new Opportunity(); + opp.Name = 'Test Opportunity'; + opp.StageName = 'Open'; + opp.CloseDate = System.today(); + opp.AccountId = accountParent.Id; + insert opp; + + // Insert a Task for Account and assert + Task task1 = new Task(); + task1.Subject = 'Task A'; + task1.WhatId = accountParent.Id; + insert task1; + System.assertEquals(1, [select AnnualRevenue from Account where id = :accountParent.Id][0].AnnualRevenue); + System.assertEquals(null, [select TotalOpportunityQuantity from Opportunity where id = :opp.Id][0].TotalOpportunityQuantity); + + // Insert a Task for Oppoortunity and assert + Task task2 = new Task(); + task2.Subject = 'Task A'; + task2.WhatId = opp.Id; + insert task2; + System.assertEquals(1, [select AnnualRevenue from Account where id = :accountParent.Id][0].AnnualRevenue); + System.assertEquals(1, [select TotalOpportunityQuantity from Opportunity where id = :opp.Id][0].TotalOpportunityQuantity); + } + + @IsTest + private static void testPolymorphicRelationshipsScheduled() { + + // Polymorphic lookup between Task and Account + LookupRollupSummary__c rollupSummaryAccount = new LookupRollupSummary__c(); + rollupSummaryAccount.Name = 'Test Rollup'; + rollupSummaryAccount.ParentObject__c = 'Account'; + rollupSummaryAccount.ChildObject__c = 'Task'; + rollupSummaryAccount.RelationShipField__c = 'WhatId'; + rollupSummaryAccount.FieldToAggregate__c = 'Id'; + rollupSummaryAccount.AggregateOperation__c = RollupSummaries.AggregateOperation.Count.name(); + rollupSummaryAccount.AggregateResultField__c = 'AnnualRevenue'; + rollupSummaryAccount.Active__c = true; + rollupSummaryAccount.CalculationMode__c = 'Scheduled'; + insert rollupSummaryAccount; + + // Polymorphic lookup between Task and Opportunity + LookupRollupSummary__c rollupSummaryOpp = new LookupRollupSummary__c(); + rollupSummaryOpp.Name = 'Test Rollup'; + rollupSummaryOpp.ParentObject__c = 'Opportunity'; + rollupSummaryOpp.ChildObject__c = 'Task'; + rollupSummaryOpp.RelationShipField__c = 'WhatId'; + rollupSummaryOpp.FieldToAggregate__c = 'Id'; + rollupSummaryOpp.AggregateOperation__c = RollupSummaries.AggregateOperation.Count.name(); + rollupSummaryOpp.AggregateResultField__c = 'TotalOpportunityQuantity'; + rollupSummaryOpp.Active__c = true; + rollupSummaryOpp.CalculationMode__c = 'Scheduled'; + insert rollupSummaryOpp; + + // Setup parent test records + Account accountParent = new Account(Name = 'Test Account'); + insert accountParent; + Opportunity oppParent = new Opportunity(); + oppParent.Name = 'Test Opportunity'; + oppParent.StageName = 'Open'; + oppParent.CloseDate = System.today(); + oppParent.AccountId = accountParent.Id; + insert oppParent; + + // Insert Tasks to generated scheduled job work items + Task task1 = new Task(); + task1.Subject = 'Task A'; + task1.WhatId = accountParent.Id; + Task task2 = new Task(); + task2.Subject = 'Task A'; + task2.WhatId = oppParent.Id; + insert new List { task1, task2 }; + + // Should have two scheduled job work items + System.assertEquals(2, [select Id from LookupRollupSummaryScheduleItems__c].size()); // Assert a scheduled item has been created + System.assertEquals(rollupSummaryAccount.Id, [select LookupRollupSummary__c from LookupRollupSummaryScheduleItems__c where ParentId__c = :accountParent.Id][0].LookupRollupSummary__c); + System.assertEquals(rollupSummaryOpp.Id, [select LookupRollupSummary__c from LookupRollupSummaryScheduleItems__c where ParentId__c = :oppParent.Id][0].LookupRollupSummary__c); + + // Run rollup job + Test.startTest(); + RollupService.runJobToProcessScheduledItems(); + Test.stopTest(); + + // Assert scheduled rollup job did its thing! + System.assertEquals(1, [select AnnualRevenue from Account where id = :accountParent.Id][0].AnnualRevenue); + System.assertEquals(1, [select TotalOpportunityQuantity from Opportunity where id = :oppParent.Id][0].TotalOpportunityQuantity); + } +} \ No newline at end of file diff --git a/rolluptool/src/classes/RollupServiceTest5.cls-meta.xml b/rolluptool/src/classes/RollupServiceTest5.cls-meta.xml new file mode 100644 index 00000000..7df4d0bf --- /dev/null +++ b/rolluptool/src/classes/RollupServiceTest5.cls-meta.xml @@ -0,0 +1,4 @@ + + + 31.0 + \ No newline at end of file diff --git a/rolluptool/src/classes/RollupSummaries.cls b/rolluptool/src/classes/RollupSummaries.cls index f3a365a9..b15760c2 100644 --- a/rolluptool/src/classes/RollupSummaries.cls +++ b/rolluptool/src/classes/RollupSummaries.cls @@ -240,6 +240,8 @@ public with sharing class RollupSummaries extends SObjectDomain return 'RollupServiceTest2Trigger'; else if(Test.isRunningTest() && lookupRollupSummary.ChildObject__c == 'Account') return 'RollupServiceTest3Trigger'; + else if(Test.isRunningTest() && lookupRollupSummary.ChildObject__c == 'Task') + return 'RollupServiceTest4Trigger'; return calculateComponentName(lookupRollupSummary.ChildObject__c, 'Trigger', APEXTRIGGER_NAME_LENGTH); } diff --git a/rolluptool/src/package.xml b/rolluptool/src/package.xml index 4c4e8687..7e40077f 100644 --- a/rolluptool/src/package.xml +++ b/rolluptool/src/package.xml @@ -19,6 +19,7 @@ RollupServiceTest2 RollupServiceTest3 RollupServiceTest4 + RollupServiceTest5 RollupSummaries RollupSummariesSelector RollupSummariesTest @@ -53,6 +54,7 @@ ApexPage + RollupServiceTest4Trigger RollupServiceTest2Trigger RollupServiceTest3Trigger RollupServiceTestTrigger diff --git a/rolluptool/src/triggers/RollupServiceTest4Trigger.trigger b/rolluptool/src/triggers/RollupServiceTest4Trigger.trigger new file mode 100644 index 00000000..0c966614 --- /dev/null +++ b/rolluptool/src/triggers/RollupServiceTest4Trigger.trigger @@ -0,0 +1,12 @@ +/** +* NOTE: DO NOT PACKAGE THIS TRIGGER +**/ + +/** + * Auto Generated and Deployed by the Declarative Lookup Rollup Summaries Tool package (dlrs) + **/ +trigger RollupServiceTest4Trigger on Task + (before delete, before insert, before update, after delete, after insert, after undelete, after update) +{ + RollupService.triggerHandler(); +} \ No newline at end of file diff --git a/rolluptool/src/triggers/RollupServiceTest4Trigger.trigger-meta.xml b/rolluptool/src/triggers/RollupServiceTest4Trigger.trigger-meta.xml new file mode 100644 index 00000000..967dd7d9 --- /dev/null +++ b/rolluptool/src/triggers/RollupServiceTest4Trigger.trigger-meta.xml @@ -0,0 +1,5 @@ + + + 32.0 + Active + \ No newline at end of file