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];
}
}
Within your summarizeOrderPackages method, the following code is setting the 'mrf' and 'oft' variables to the same value.
Afterwards, you are then setting the fields in question to the mrf and otf variables (which have the same value).
Consider adding a wrapper and inner class within your OrderLocationRollupSummary class to solve this problem:
Then call this new inner class within your getOrderPackagesAmountsByLocationId method:
You'll also need to update your summarizeOrderPackages method to be something like this: