function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Scott LandesScott Landes 

Invocablemethod Apex Class Rollup Multiple Currency Fields

Hello! I'm a bit new at writing Apex but I'm attempting to create an invocablemethod batch apex class to rollup multiple currency fields on an "Order Package" object to its parent object of "Order Location". Everything seems to be working as expected but I need to rollup multiple fields and I'm running into issues. Can someone show me how I might be able to include multiple fields in the rollup? I attempted to simply add another field but right now it looks like it's assigning the same amount to both fields I included. This seems to be because I am assigning the same "results" to both fields but I can't figure out how I can assign the aggregate query to multiple fields. Any help is greatly 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];
        }
    
    }

 
Best Answer chosen by Scott Landes
Maharajan CMaharajan C
Hi Scott,

Please use the below changes:

Update the method: getOrderPackagesAmountsByLocationId like below:
 
public Map<Id, AggregateResult> getOrderPackagesAmountsByLocationId(Set<Id> OrderLocationIds) {
	Map<id,AggregateResult> resultsByOrderLocationId= new Map<Id,AggregateResult>();

	//Summarize Order Package Amounts by Order Location Id
	AggregateResult[] results = aggregateOrderPackageAmounts(OrderLocationIds);
	for (AggregateResult result : results) {
		Id orderlocationId = (Id) result.get('OrderLocation');
		resultsByOrderLocationId.put(orderlocationId, result );
	}
	return resultsByOrderLocationId;
}

And update the Mathod: summarizeOrderPackages like below:
 
public void summarizeOrderPackages(Set<Id> OrderLocationIds) {
	//Get Order Locations to Update
	List<Order_New_Location__c> orderlocations = queryOrderLocationsById(OrderLocationIds);

	Map<Id, AggregateResult> 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)) {
			AggregateResult ar = results.get(ordloc.Id);
			mrf = (double)ar.get('MRFees');
			otf = (double)ar.get('OTFees');
		}

		//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);
	}
}

If you use Map<Id, double> then value get override and you can't store the multiple amounts for orderlocation , So directly return the AggregateResult from getOrderPackagesAmountsByLocationId then you can access the multiple amounts.


Thanks,
Maharajan.C

All Answers

Maharajan CMaharajan C
Hi Scott,

Please use the below changes:

Update the method: getOrderPackagesAmountsByLocationId like below:
 
public Map<Id, AggregateResult> getOrderPackagesAmountsByLocationId(Set<Id> OrderLocationIds) {
	Map<id,AggregateResult> resultsByOrderLocationId= new Map<Id,AggregateResult>();

	//Summarize Order Package Amounts by Order Location Id
	AggregateResult[] results = aggregateOrderPackageAmounts(OrderLocationIds);
	for (AggregateResult result : results) {
		Id orderlocationId = (Id) result.get('OrderLocation');
		resultsByOrderLocationId.put(orderlocationId, result );
	}
	return resultsByOrderLocationId;
}

And update the Mathod: summarizeOrderPackages like below:
 
public void summarizeOrderPackages(Set<Id> OrderLocationIds) {
	//Get Order Locations to Update
	List<Order_New_Location__c> orderlocations = queryOrderLocationsById(OrderLocationIds);

	Map<Id, AggregateResult> 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)) {
			AggregateResult ar = results.get(ordloc.Id);
			mrf = (double)ar.get('MRFees');
			otf = (double)ar.get('OTFees');
		}

		//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);
	}
}

If you use Map<Id, double> then value get override and you can't store the multiple amounts for orderlocation , So directly return the AggregateResult from getOrderPackagesAmountsByLocationId then you can access the multiple amounts.


Thanks,
Maharajan.C
This was selected as the best answer
Scott LandesScott Landes
Perfect! Thank you so much Maharajan!