Search code examples
salesforceapexsalesforce-developmentsalesforce-developer

Invocablemethod Apex Class Rollup Multiple Currency Fields


I'm writing an invocablemethod batch apex class to rollup multiple currency fields on an "Order Package" object to its parent object of "Order Location". I thought I got everything added properly but it seems to be updating both the "Package_Monthly_Recurring_Fees__c" and the "Package_One_Time_Fees__c" to the same price from the Package_Monthly_Recurring_Fees__c field. Can someone help me identify why it's using the same price for both fields? Any help is much appreciated!

global class OrderLocationRollupSummary implements Database.Batchable<sObject>, Schedulable {
    
        //Invocable Method
        @InvocableMethod(label='Rollup All Order Packages to Locations')
        global static void rollupAllorderpackages(List<Order_Location_Package__c> orderpackages) {
            rollupOrderPackages(orderpackages);
        }
    
        //Batchable Methods
        global Database.QueryLocator start(Database.BatchableContext bc) {
            return Database.getQueryLocator([SELECT Id FROM Order_New_Location__c]);
        }
    
        global void execute(Database.BatchableContext context, List<sObject> batch){
            Set<Id> OrderLocationIds = new Set<Id>();
    
            for (sObject ordloc : batch) {
                OrderLocationIds.add(ordloc.Id);
            }
    
            summarizeOrderPackages(OrderLocationIds);
        }
    
        global void finish(Database.BatchableContext context) {}
    
        //Schedulable Methods
        global void execute(SchedulableContext context){
            OrderLocationRollupSummary batchJob = new OrderLocationRollupSummary();
            Database.executeBatch(batchJob);
        }
    
        //Static Methods
        public static void rollupOrderPackages(List<Order_Location_Package__c> orderpackages) {
            Set<Id> OrderLocationIds = new Set<Id>();
    
            //Get Order Location Ids from specified orderpackages
            for (Order_Location_Package__c ordpckg : orderpackages) {
                OrderLocationIds.add(ordpckg.New_Location_Name__c);
            }
    
            if (OrderLocationIds.isEmpty() == false) {
                /*Execute as a future call so that the user doesn't have to wait around for
                the rollup to finish. Unless, already in a future or batch call state then
                just perform the rollup.*/
                if (System.isFuture() == false && System.isBatch() == false) {
                    summarizeOrderPackagesAsync(OrderLocationIds);
                }
                else {
                    new OrderLocationRollupSummary().summarizeOrderPackages(OrderLocationIds);
                }
            }
        }
    
        @future
        public static void summarizeOrderPackagesAsync(Set<Id> OrderLocationIds) {
            new OrderLocationRollupSummary().summarizeOrderPackages(OrderLocationIds);
        }
    
        //Public Methods
        public void summarizeOrderPackages(Set<Id> OrderLocationIds) {
            //Get Order Locations to Update
            List<Order_New_Location__c> orderlocations = queryOrderLocationsById(OrderLocationIds);
    
            Map<Id, double> results = getOrderPackagesAmountsByLocationId(OrderLocationIds);
    
            //Loop Order Locations and set Amounts
            List<Order_New_Location__c> orderlocationsToUpdate = new List<Order_New_Location__c>();
            for (Order_New_Location__c ordloc : orderlocations) {
                double mrf = 0;
                double otf = 0;
    
                if (results.containsKey(ordloc.Id)) {
                    mrf = results.get(ordloc.Id);
                    otf = results.get(ordloc.Id);
                }
    
                //Determine if Amounts have Changed
                if (ordloc.Package_Monthly_Recurring_Fees__c != mrf || 
                    ordloc.Package_One_Time_Fees__c != otf) {
                    
                    ordloc.Package_Monthly_Recurring_Fees__c = mrf;
                    ordloc.Package_One_Time_Fees__c = otf;
                    orderlocationsToUpdate.add(ordloc); //Add location to collection to be updated
                }
            }
    
            if(orderlocationsToUpdate.isEmpty() == false) {
                Database.SaveResult[] saveResults = Database.update(orderlocationsToUpdate, false);
                System.debug(saveResults);
            }
        }
    
        //Private Methods
        public Map<Id, double> getOrderPackagesAmountsByLocationId(Set<Id> OrderLocationIds) {
            Map<Id, double> resultsByOrderLocationId = new Map<Id, double>();
    
            //Summarize Order Package Amounts by Order Location Id
            AggregateResult[] results = aggregateOrderPackageAmounts(OrderLocationIds);
            for (AggregateResult result : results) {
                Id orderlocationId = (Id) result.get('OrderLocation');
                double mrf = (double) result.get('MRFees');
                double otf = (double) result.get('OTFees');
    
                resultsByOrderLocationId.put(orderlocationId, mrf);
                resultsByOrderLocationId.put(orderlocationId, otf);
            }
            return resultsByOrderLocationId;
        }
    
        //Query Methods
        private List<Order_New_Location__c> queryOrderLocationsById(Set<Id> OrderLocationIds) {
            return [SELECT 
                    Id 
                    ,Package_Monthly_Recurring_Fees__c
                    ,Package_One_Time_Fees__c
                FROM 
                    Order_New_Location__c 
                WHERE 
                    Id IN :OrderLocationIds];
        }
    
        private AggregateResult[] aggregateOrderPackageAmounts(Set<Id> OrderLocationIds) {
            return [SELECT 
                     New_Location_Name__c OrderLocation
                    ,SUM(Monthly_Recurring_Fees__c) MRFees
                    ,SUM(One_Time_Fees__c) OTFees
                FROM 
                    Order_Location_Package__c
                WHERE
                    New_Location_Name__c IN :OrderLocationIds
                GROUP BY 
                    New_Location_Name__c];
        }
    
    }

Solution

  • Within your summarizeOrderPackages method, the following code is setting the 'mrf' and 'oft' variables to the same value.

            if (results.containsKey(ordloc.Id)) {
                mrf = results.get(ordloc.Id);
                otf = results.get(ordloc.Id);
            }
    

    Afterwards, you are then setting the fields in question to the mrf and otf variables (which have the same value).

            //Determine if Amounts have Changed
            if (ordloc.Package_Monthly_Recurring_Fees__c != mrf || 
                ordloc.Package_One_Time_Fees__c != otf) {
                
                ordloc.Package_Monthly_Recurring_Fees__c = mrf;
                ordloc.Package_One_Time_Fees__c = otf;
                orderlocationsToUpdate.add(ordloc); //Add location to collection to be updated
            }
    

    Consider adding a wrapper and inner class within your OrderLocationRollupSummary class to solve this problem:

      public class Order_New_Location_Wrapper {
        Id orderlocationId = {get;set;}
        Double mrf = {get;set;}
        Double otf = {get;set;}
        public class Order_New_Location_Wrapper (Id arg1, Double arg2, Double arg3)
        orderlocationId = arg1;
        mrf = arg2;
        otf = arg3;
      }
    

    Then call this new inner class within your getOrderPackagesAmountsByLocationId method:

    public Map<Id, Order_New_Location_Wrapper> getOrderPackagesAmountsByLocationId(Set<Id> OrderLocationIds) {
    
    //create a list of orderlocations to represent the collection objects coming from the wrapper 
            
            resultsByOrderLocationId = new Map<Id, Order_New_Location_Wrapper>();
    
            //Summarize Order Package Amounts by Order Location Id
            AggregateResult[] results = aggregateOrderPackageAmounts(OrderLocationIds);
            for (AggregateResult result : results) {
                Id orderlocationId = (Id) result.get('OrderLocation');
                double mrf = (double) result.get('MRFees');
                double otf = (double) result.get('OTFees');
    
                resultsByOrderLocationId.add(orderlocationId, new OpportunityWrapper(orderlocationId, mrg, otf));
            }
            return resultsByOrderLocationId;
        }
    

    You'll also need to update your summarizeOrderPackages method to be something like this:

    public void summarizeOrderPackages(Set<Id> OrderLocationIds) {
        //Get Order Locations to Update
        List<Order_New_Location__c> orderlocations = queryOrderLocationsById(OrderLocationIds);
    
        Map<Id, Order_New_Location_Wrapper> results = getOrderPackagesAmountsByLocationId(OrderLocationIds);
    
        //Loop Order Locations and set Amounts
        List<Order_New_Location__c> orderlocationsToUpdate = new List<Order_New_Location__c>();
        for (Order_New_Location__c ordloc : orderlocations) {
            double mrf = 0;
            double otf = 0;
    
            if (results.containsKey(ordloc.Id)) {
                mrf = (Order_New_Location__c) results.get(ordloc.Id).mrf;
                otf = (Order_New_Location__c) results.get(ordloc.Id).otf;
            }
    
            //Determine if Amounts have Changed
            if (ordloc.Package_Monthly_Recurring_Fees__c != mrf || 
                ordloc.Package_One_Time_Fees__c != otf) {
                
                ordloc.Package_Monthly_Recurring_Fees__c = mrf;
                ordloc.Package_One_Time_Fees__c = otf;
                orderlocationsToUpdate.add(ordloc); //Add location to collection to be updated
            }
        }
    
        if(orderlocationsToUpdate.isEmpty() == false) {
            Database.SaveResult[] saveResults = Database.update(orderlocationsToUpdate, false);
            System.debug(saveResults);
        }
    }