0

I have an Object called Customer which has related object Purchase. Every Purchase has Account owner. Under one Customer there can be many purchase from different Account. From each purchase I need to create one record of Purchase under one account owner where the Purchase gets attached back to the same Customer. I calculate 3 fields for the purchase and account:

  • Gross_Commission__c
  • Debit__c
  • Credit__c

My batch is able to create calcualtions but while attaching it back to the Purchase record, it is only creating one single record and giving all the calculations under one Account owner.

For example 1 Customer has 15 Purchases in which 10 Purchases has Account 1 as owner and 5 purchase has Account 2 as owner. Now I want to calculate sum of 3 fields from purchase which has same owner and create one single record and attach it back under customer. i.e. there will be 2 new records with calculations of 10 purchases under Account owner 1 and calculation of 5 purchases under account 2 as owner. Also, owner is a custom field.

global class ArchiveAggregateAL_Batch implements database.Batchable<SObject> {

global String CustomerRecordID ;
global set<String> AccountId = new Set <String>();

global  Double CommissionTotals = 0;
global Double debitTotals = 0;
global Double creditTotals = 0;

global  Id CT = Schema.SObjectType.purchase__c.getRecordTypeInfosByName().get('Commission Transactions').getRecordTypeId();
//Manual Adjustment 

global  Id MA = Schema.SObjectType.purchase__c.getRecordTypeInfosByName().get('Manual Adjustment').getRecordTypeId();    


public ArchiveAggregateAL_Batch(String CusID, Set<String> AdvId){
    this.CustomerRecordID = CusID;
    this.AccountId = advId;

}

global database.QueryLocator Start(Database.BatchableContext bc){

    System.debug('In Start Method');
    String query = 'Select Gross_Commission__c, Debit__c, Credit__c ,RecordtypeId ,Advisor__c  from purchase__c  WHERE '+
        ' RecordtypeId = :CT AND Advisor__c = :AccountId '+ 
        ' AND Customer__c = :CustomerRecordID AND Object_Backup__c = TRUE';

    return Database.getQueryLocator(query);
} 

global void execute(Database.BatchableContext bc, List<purchase__c> scope){

    List<purchase__c> ALList = new List<purchase__c>();
    System.debug('In execute Method');
    //   purchase__c AggAdv = new purchase__c();
    String advId;
    for (purchase__c AL : scope) {
        if(AL.Gross_Commission__c!=NULL){
        CommissionTotals +=  AL.payout__Gross_Commission__c;
            }
         if(AL.Debit__c!=NULL){
        debitTotals +=  Al.payout__Debit__c ;
         }
        if(AL.Credit__c!=NULL){
        creditTotals +=  AL.payout__Credit__c;
        }
        advId = AL.Advisor__c;



    }

    for (purchase__c AL : scope) {
        purchase__c AggAdv = new purchase__c();
        AggAdv.Gross_Commission__c = CommissionTotals;
        AggAdv.Debit__c = debitTotals;
        AggAdv.Credit__c = creditTotals;
        AggAdv.RecordTypeId = MA;
        AggAdv.Customer__c = CustomerRecordID;
        AggAdv.Advisor__c = AL.payout__Advisor__c;
        ALList.add(AggAdv);
    } 
    insert ALList;
}

public void finish(Database.BatchableContext BC){
}

}
4
  • Is Advisor__c the custom account owner field you mention in your question? If so, you'll need to do sorting on that field, not just the purchase__c
    – crmprogdev
    Commented Mar 26, 2019 at 13:34
  • (A side note: you don't need to make the class or any of its members global unless you are making it visible in a different context.)
    – Phil W
    Commented Mar 26, 2019 at 14:09
  • @PhilW yes I'm accessing it in another context as well :) Commented Mar 27, 2019 at 7:28
  • (I noted the public constructor and assumed you were only using the batch in the same context as it is defined - e.g. in a package or on an org, but not across package boundaries)
    – Phil W
    Commented Mar 27, 2019 at 7:32

2 Answers 2

2

As far as I am understanding, you want to group the purchase records by Account and summarize the information on one record for each account.

For that, you will have to use Maps instead of double variables as you will have to group the records based on the Account.

You will need these 4 variables in your batch class

global  Map<Id,Double> mapCommissionTotals = new Map<Id,Double>();
global  Map<Id,Double> mapDebitTotals = new Map<Id,Double>();
global  Map<Id,Double> mapCreditTotals = new Map<Id,Double>();
global  set<Id> setAccounts = new set<Id>();

And this is how your execute method should look like

global void execute(Database.BatchableContext bc, List<purchase__c> scope){

    List<purchase__c> ALList = new List<purchase__c>();
    System.debug('In execute Method');
    //   purchase__c AggAdv = new purchase__c();
    String advId;
    for (purchase__c AL : scope) {
        if(AL.Gross_Commission__c!=NULL){
            if(mapCommissionTotals.containsKey(AL.Advisor__c)){
                Double comm = mapCommissionTotals.get(AL.Advisor__c) + AL.payout__Gross_Commission__c;
                mapCommissionTotals.put(AL.Advisor__c, comm);
            } else {
                mapCommissionTotals.put(AL.Advisor__c,AL.payout__Gross_Commission__c)
            }
        }

        if(AL.Debit__c!=NULL){
            if(mapDebitTotals.containsKey(AL.Advisor__c)){
                Double debt = mapDebitTotals.get(AL.Advisor__c) + AL.payout__Debit__c;
                mapDebitTotals.put(AL.Advisor__c, debt);
            } else {
                mapDebitTotals.put(AL.Advisor__c,AL.payout__Debit__c)
            }
        }

        if(AL.Credit__c!=NULL){
            if(mapCreditTotals.containsKey(AL.Advisor__c)){
                Double cred = mapCreditTotals.get(AL.Advisor__c) + AL.payout__Credit__c;
                mapCreditTotals.put(AL.Advisor__c, cred);
            } else {
                mapCreditTotals.put(AL.Advisor__c,AL.payout__Credit__c)
            }
        }
        setAccounts.add(AL.Advisor__c);

    }

    for (Id AL : setAccounts) {
        purchase__c AggAdv = new purchase__c();
        AggAdv.Gross_Commission__c = mapCommissionTotals.containsKey(AL) ? mapCommissionTotals.get(AL) : 0;
        AggAdv.Debit__c = mapDebitTotals.containsKey(AL) ? mapDebitTotals.get(AL) : 0;
        AggAdv.Credit__c = mapCreditTotals.containsKey(AL) ? mapCreditTotals.get(AL) : 0;
        AggAdv.RecordTypeId = MA;
        AggAdv.Customer__c = CustomerRecordID;
        AggAdv.Advisor__c = AL;
        ALList.add(AggAdv);
    } 
    insert ALList;
}

Note: Customer and Account will already have related purchase records i.e. as per your example, Customer will have 15 related purchase records, Account 1 will have 10 purchase records and Account 2 will have 5 purchase records. By running this batch class, it will create 2 more additional purchase records under Customer which will be summarized one. Account 1 will have 1 summarized purchase record and Account 2 will have 1 summarized purchase record.

1
  • Thank you @Vijay for your help calculations are working now :) ! Commented Mar 27, 2019 at 7:27
0

It appears to me that you do not have the actual account owner field in your query or in your code. I only see the account Id in your code or in your loops. Your code Advisor__c = :AccountId tells me the Advisor__c is the AccountId and the Purchase__c.AccountId is your variable advId variable. Its as though you're saying the account and account owner are the same. We have no way of knowing if more than one user owns multiple accounts (or if it matters). Assuming there's a 1 to 1 relationship between account and account owner, you'll need to have a loop that iterates on the account first, then the purchase. To do that, I think you'll need a map of accountId to purchase.

List<purchase__c> AllPurch = new List<purchase__c>();
List<purchase__c> ALList = new List<purchase__c>();
System.debug('In execute Method');
//   purchase__c AggAdv = new purchase__c();
// String advId;
map<string, purchase__c> AccountIdToPurchase = new map<string,purchase__c>():
for (purchase__c AL : scope) {
    if(AL.Gross_Commission__c!=NULL){
    CommissionTotals +=  AL.payout__Gross_Commission__c;
        }
     if(AL.Debit__c!=NULL){
    debitTotals +=  Al.payout__Debit__c ;
     }
    if(AL.Credit__c!=NULL){
    creditTotals +=  AL.payout__Credit__c;
    }
    put.PurchaseToAccountId(AL, AL.Advisor__c);

    AllPurch.add(AL);

}

for (purchase__c AllPurch : AL) {
   // adjust this method accordingly to use your map to add correct account
   // can create inner loop if you want for each account to get the purchase__c
   // on an account basis if desired to sum for customer by account
    purchase__c AggAdv = AL;
    AggAdv.Gross_Commission__c = CommissionTotals;
    AggAdv.Debit__c = debitTotals;
    AggAdv.Credit__c = creditTotals;
    AggAdv.RecordTypeId = MA;
    AggAdv.Customer__c = CustomerRecordID;
    AggAdv.Advisor__c = AL.payout__Advisor__c;
    ALList.add(AggAdv);
} 
insert ALList;
}
1
  • Yes it is child relationship name. ! Thanks for the help. Issue is now solved. Commented Mar 27, 2019 at 7:29

You must log in to answer this question.

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