+ Start a Discussion
Alexander BorosAlexander Boros 

Understanding Apex code

Hi all,

I wonder if you can help me. Very recently we started having issues with an Apex script that is used to populated the Montly obtainment value in a daily report.

The value is supposed to let the Sales rep know their sales amount so far this month. However, the value that it calculates flunctuates wildly from working correctly, to being off by thousands.

The script itself was originally written several years ago by an agency that is no longer around. We are trying to get a better understanding on what it exactly does so we can implement a fix. 

The Apex code being used is found below.

global with sharing class Forecast_Batch implements Database.Batchable<sObject>, Database.Stateful{
    Map<String, Decimal> amountMap = new Map<String, Decimal>();
    List<Id> accountOwnerIds = new List<Id>();

        global Database.QueryLocator start(Database.BatchableContext BC)
        {
            
            return Database.getQueryLocator([SELECT Id,OwnerId FROM Account]); //Query all accounts for ID and OwnerId
            
        }

    global void execute(Database.BatchableContext BC, List<SObject> scope)
    {        
        Map<Id, Map<String,Decimal>> accountAmountMap = new Map<Id,Map<String,Decimal>>();

        //List<Id> accountOwnerIds = new List<Id>();
        Set<Id> accountIds = new Set<Id>();
        
        system.debug('+++ SCOPE SIZE ' + scope.size());
        
        for (SObject s : scope) {
            
            Account acc = (Account)s;
            if(!accountIds.contains(acc.Id)){
                accountIds.add(acc.Id);
            }
            
        }
        
        
        for (Account acc : [SELECT OwnerId,(SELECT Name,SA_Net_Amount__c,InvoiceDate__c,OwnerDetails__c,Inv_Yr__c FROM Invoice__r WHERE OwnerDetails__c != null and SA_Net_Amount__c !=null ) FROM Account WHERE Id in : accountIds]) {
            
            for (Invoice__c inv : acc.Invoice__r) {
                
                System.debug(inv.name);
          Decimal amount = 0;
                
          if(amountMap.containsKey(inv.OwnerDetails__c)){
              amount = amountMap.get(inv.OwnerDetails__c);
          }
    
          amountMap.put(inv.OwnerDetails__c, inv.SA_Net_Amount__c + amount);
      }
            //accountAmountMap.put(acc.Id, amountMap);
            accountOwnerIds.add(acc.OwnerID);
            
        }
        System.debug(accountOwnerIds);
        


        
    }  

    global void finish(Database.BatchableContext BC){
        
        // Query list of forecast details record based on Account's owner Id
        List<H_Forecast_Details__c> forecastdetails = new List<H_Forecast_Details__c>();

        // Iterate accounts in for loop
        // iterate forecast details record
        // get invoice amount based on account id and forcast month.
        // update in forecast detail record.
        for (H_Forecast_Details__c forecastDet : [SELECT ID,Name,Month_Obtainment__c,OwnerID__c,FDOwnerDets__c from H_Forecast_Details__c where OwnerID__c IN : accountOwnerIds]) {
            if(amountMap.containsKey(forecastDet.FDOwnerDets__c)){
                Decimal amount  = amountMap.get(forecastDet.FDOwnerDets__c);  
                forecastDet.Month_Obtainment__c = amount;
                System.debug('match');
                System.debug(amount);

    forecastdetails.add(forecastDet);
            }
        }

  System.debug(forecastdetails);
  if(forecastdetails!=null&&forecastdetails.size()>0){
          update forecastdetails;
  }
    }
}

Kind regards,

Alex

Sai PraveenSai Praveen (Salesforce Developers) 
Hi Alex,

Is the code working preperly now. Because amountMap is not defined but the values were added to that map . 

Initilation of accountOwnerIds is not done but it is used to add the ownerid field. 

So I guess this is not working at all.

Thanks,
 
Alexander BorosAlexander Boros

Hi Sai, 

Thank you for your response. The code is currently working, but not working properly in the last two weeks or so. (i.e:) The month obtainment value one day will show 80,000 then the next day it will show 50,000 then go back to the correct number before going down again (or show a much higher number). In short, it's become inconsistent even though no changes were done with it / related reports in years. 

Kind regards,

Alex

Colin KenworthyColin Kenworthy
Looks to me that if the OwnerId on Accounts and H_Forecast_Details__c were misaligned OR if the OwnerDetails on Invoice__c and H_Forecast_Details__c were misaligned, then you might have amounts that do not get reported on in your H Forcast Details...

Have there been any changes recently to the Owner of Account/H Forcast or changes to OwnerDetails of Invoice/H Forecast ?

Everything looks fine until the Finish() method at the end of the batch where only existing H Forecast records are updated but no new ones are created for missing OwnerDetails.  Also note that a single SOQL statement can only read 2,000 records so if you have over 2,000 H Forcast records then some might not get updated.
https://developer.salesforce.com/docs/atlas.en-us.salesforce_app_limits_cheatsheet.meta/salesforce_app_limits_cheatsheet/salesforce_app_limits_platform_soslsoql.htm
Alexander BorosAlexander Boros

Thanks Colin! Greatly appreciated. You bring up a few items that we need to consider and test!

Kind regards,

Alex