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
David SilvaDavid Silva 

Error: Initial term of field expression must be a concrete sObject.

public class TotalExpenseComputation { 
   
   
 
    /*
     * The totalExpense method calculates the total of all the approved expenses as well as the amount left
     *
     * for both the marketing and sales budget.
     * */
public static void totalExpense(Expense__c[] expenses)
{
    //Query to get  Initial Amount,Total Expense and Remaining Amount field from respective budgets.
 
    List<Budget__c> typeList = new List<Budget__c>();
   
for(Budget__c[] b:[SELECT Name,Initial_Amount__c,Total_Expenses__c,Remaining_Amount__c,Type__c FROM Budget__c])
{
for(Expense__c exp:expenses)
    {
        if(exp.Type__c.equals('Marketing')&& exp.Budget_LookUp__c.equals(b.Name))
        {
             if(exp.Status__c.equals('Approved'))
             {
                
              b.Total_Expenses__c= exp.Amount__c+b.Total_Expenses__c;
               b.Remaining_Amount__c=b.Initial_Amount__c-b.Total_Expenses__c;
               typeList.add(b);
                
             }
              
        }
       
        if(exp.Type__c.equals('Sales')&& exp.Budget_LookUp__c.equals(b.Name))
        {
            if(exp.Status__c.equals('Approved'))
            {
              
                b.Total_Expenses__c  =exp.Amount__c+b.Total_Expenses__c;
                b.Remaining_Amount__c=b.Initial_Amount__c-b.Total_Expenses__c;
              typeList.add(b);
               
              }
        }
       
    }update typeList;}
   
 
Best Answer chosen by David Silva
Mahesh DMahesh D
Hi David,

I reviewed the code and modified accordingly.

Here I considered:

(1) Naming Convention.
(2) Alignment.
(3) Added the comments.
(4) Corrected the logic to bulkify the code.

 
public class TotalExpenseComputation { 
    /*
     * The totalExpense method calculates the total of all the approved expenses as well as the amount left
     *
     * for both the marketing and sales budget.
     * */
    public static void totalExpense(Expense__c[] expenses) {
        Set<Id> budIdSet = new Set<Id>();
        
        for(Expense__c exp:expenses) {
            if(exp.Budget_LookUp__c != null)
                budIdSet.add(exp.Budget_LookUp__c);
        }
        
        // Check whether the budget lookup set is empty or not.
        if(!budIdSet.isEmpty()) {
            // Query the corresponding Budget records.
            Map<Id, Budget__c> budMap = new Map<Id, Budget__c>([SELECT Id, Name, Initial_Amount__c, Total_Expenses__c, Remaining_Amount__c, Type__c FROM Budget__c where ID IN: budIdSet]);
            // Iterate through the input expenses.
            for(Expense__c exp:expenses) {
                Budget__c bud = budMap.get(exp.Budget_LookUp__c);
                if(bud != null && exp.Status__c == 'Approved' && (exp.Type__c == 'Marketing' || exp.Type__c == 'Sales')) {
                    bud.Total_Expenses__c = exp.Amount__c + bud.Total_Expenses__c;
                    bud.Remaining_Amount__c = bud.Initial_Amount__c - bud.Total_Expenses__c;
                }
            }
            update budMap.values();
        }
    }
}

I couldn't test is as I don't have setup in my DE environment.

Please do let me know if it helps you.

Regards,
Mahesh

All Answers

JethaJetha
Hi Please try modified code :
public class TotalExpenseComputation { 
   
   
 
    /*
     * The totalExpense method calculates the total of all the approved expenses as well as the amount left
     *
     * for both the marketing and sales budget.
     * */
public static void totalExpense(Expense__c[] expenses)
{
    //Query to get  Initial Amount,Total Expense and Remaining Amount field from respective budgets.
 
    List<Budget__c> typeList = new List<Budget__c>();
   
for(Budget__c b:[SELECT Name,Initial_Amount__c,Total_Expenses__c,Remaining_Amount__c,Type__c FROM Budget__c])
{
for(Expense__c exp:expenses)
    {
        if(exp.Type__c.equals('Marketing')&& exp.Budget_LookUp__c.equals(b.Name))
        {
             if(exp.Status__c.equals('Approved'))
             {
                
              b.Total_Expenses__c= exp.Amount__c+b.Total_Expenses__c;
               b.Remaining_Amount__c=b.Initial_Amount__c-b.Total_Expenses__c;
               typeList.add(b);
                
             }
              
        }
       
        if(exp.Type__c.equals('Sales')&& exp.Budget_LookUp__c.equals(b.Name))
        {
            if(exp.Status__c.equals('Approved'))
            {
              
                b.Total_Expenses__c  =exp.Amount__c+b.Total_Expenses__c;
                b.Remaining_Amount__c=b.Initial_Amount__c-b.Total_Expenses__c;
              typeList.add(b);
               
              }
        }
       
    }update typeList;}

 
Mahesh DMahesh D
Hi David,

I reviewed the code and modified accordingly.

Here I considered:

(1) Naming Convention.
(2) Alignment.
(3) Added the comments.
(4) Corrected the logic to bulkify the code.

 
public class TotalExpenseComputation { 
    /*
     * The totalExpense method calculates the total of all the approved expenses as well as the amount left
     *
     * for both the marketing and sales budget.
     * */
    public static void totalExpense(Expense__c[] expenses) {
        Set<Id> budIdSet = new Set<Id>();
        
        for(Expense__c exp:expenses) {
            if(exp.Budget_LookUp__c != null)
                budIdSet.add(exp.Budget_LookUp__c);
        }
        
        // Check whether the budget lookup set is empty or not.
        if(!budIdSet.isEmpty()) {
            // Query the corresponding Budget records.
            Map<Id, Budget__c> budMap = new Map<Id, Budget__c>([SELECT Id, Name, Initial_Amount__c, Total_Expenses__c, Remaining_Amount__c, Type__c FROM Budget__c where ID IN: budIdSet]);
            // Iterate through the input expenses.
            for(Expense__c exp:expenses) {
                Budget__c bud = budMap.get(exp.Budget_LookUp__c);
                if(bud != null && exp.Status__c == 'Approved' && (exp.Type__c == 'Marketing' || exp.Type__c == 'Sales')) {
                    bud.Total_Expenses__c = exp.Amount__c + bud.Total_Expenses__c;
                    bud.Remaining_Amount__c = bud.Initial_Amount__c - bud.Total_Expenses__c;
                }
            }
            update budMap.values();
        }
    }
}

I couldn't test is as I don't have setup in my DE environment.

Please do let me know if it helps you.

Regards,
Mahesh
This was selected as the best answer
David SilvaDavid Silva
Hi Jetha.

Thanks for the help.
That issue is resolved.
The new issue is: on program execution

Error: Invalid Data.
Review all error messages below to correct your data.
Apex trigger TotalExpenseComputationtrigger caused an unexpected exception, contact your administrator: TotalExpenseComputationtrigger: execution of AfterInsert caused by: System.NullPointerException: Attempt to de-reference a null object: Class.TotalExpenseComputation.totalExpense: line 25, column 1.

With Regards,
   Nisha
Mahesh DMahesh D
Hi Nisha,

Please try the code which I posed above.

Regards,
Mahesh
JethaJetha
Please try below : 
public class TotalExpenseComputation { 
   
   
 
    /*
     * The totalExpense method calculates the total of all the approved expenses as well as the amount left
     *
     * for both the marketing and sales budget.
     * */
public static void totalExpense(Expense__c[] expenses)
{
    //Query to get  Initial Amount,Total Expense and Remaining Amount field from respective budgets.
 
    List<Budget__c> typeList = new List<Budget__c>();
   
for(Budget__c b:[SELECT Name,Initial_Amount__c,Total_Expenses__c,Remaining_Amount__c,Type__c FROM Budget__c])
{
for(Expense__c exp:expenses)
    {
        if(exp.Type__c.equals('Marketing')&& exp.Budget_LookUp__c.equals(b.Name))
        {
             if(exp.Status__c.equals('Approved'))
             {
               if (exp.Amount__c != null)
			   {
					b.Total_Expenses__c= exp.Amount__c+b.Total_Expenses__c;
               }
               b.Remaining_Amount__c=b.Initial_Amount__c-b.Total_Expenses__c;
               typeList.add(b);
                
             }
              
        }
       
        if(exp.Type__c.equals('Sales')&& exp.Budget_LookUp__c.equals(b.Name))
        {
            if(exp.Status__c.equals('Approved'))
            {
              
                b.Total_Expenses__c  =exp.Amount__c+b.Total_Expenses__c;
                b.Remaining_Amount__c=b.Initial_Amount__c-b.Total_Expenses__c;
              typeList.add(b);
               
              }
        }
       
    }update typeList;}
David SilvaDavid Silva
Hi Mahesh,

Thanks fo the guidance.
Problem is solved.
Could u explain this step.

  Budget__c bud = budMap.get(exp.Budget_LookUp__c);
                if(bud != null && exp.Status__c == 'Approved' && (exp.Type__c == 'Marketing' || exp.Type__c == 'Sales')) {
                    bud.Total_Expenses__c = exp.Amount__c + bud.Total_Expenses__c;
                    bud.Remaining_Amount__c = bud.Initial_Amount__c - bud.Total_Expenses__c;
               
With Regards,
   Nisha
 
Mahesh DMahesh D
Hi Nisha,

// Here I am passing the Budget Lookup and get the corresponding Budget record.
Budget__c bud = budMap.get(exp.Budget_LookUp__c);
// Here I am checking the corresponding budget record exists or not. Also checking the other parameters.
if(bud != null && exp.Status__c == 'Approved' && (exp.Type__c == 'Marketing' || exp.Type__c == 'Sales')) {
// Here your business logic for the calculation.
 bud.Total_Expenses__c = exp.Amount__c + bud.Total_Expenses__c;
 bud.Remaining_Amount__c = bud.Initial_Amount__c - bud.Total_Expenses__c;

Regards,
Mahesh
David SilvaDavid Silva
Hi Mahesh,

Understood.Thank You very much.
I am just a beginner:
Could u help me  in designing the test class for it :
/////////////////////////////////////////////
Trigger

trigger TotalExpenseComputationtrigger on Expense__c (after insert,after update) {
Expense__c[] expenses = Trigger.New;
    TotalExpenseComputation.totalExpense(expenses);

}
///////////////////////////////////////////////////////////
Test Class I wrote:
isTest public class TotalExpenseTestClass {
    @ isTest public static  void TesttotalExpense()
    {
Expense__c exp = new Expense__c(Name='Mar',Type__c='Marketing',Amount__c=200,Status__c='Approved',Budget_LookUp__c='Marketing 2');
        //TotalExpenseComputation.totalExpense(exp);
      
    }

}

With Regards,
   Nisha.
 
Mahesh DMahesh D
Hi Nisha,

You need to create a Budget record first then insert the Expense record by assigning the Budget_Lookup__c with the created id.
It will automatically fire the trigger.

Regards,
Mahesh
David SilvaDavid Silva

Hi Mahesh,

@isTest public class TotalExpenseTestClass {
    @ isTest public static  void TesttotalExpense()
    {
  Budget__c budg= new Budget__c(Name='Sales2',Type__c='Sales',Initial_Amount__c = 50000,Total_Expense__c= 0,Remaining_Amount__c=0);
   insert budg;
       
  Expense__c exp = new Expense__c(Name='Mar',Type__c='Marketing',Amount__c=200,Status__c='Approved',Budget_LookUp__c.Id=budg.Id);
        insert exp;
       
      
    }

}

The above code is not working.

With Regards,
    Nisha

 
David SilvaDavid Silva
   
Hi Mahesh,

Budget__c budg= new Budget__c(Name='Sales2',Initial_Amount__c = 50000,Valid_From__c='1/1/2016',Valid_To__c='12/1/2016',Description__c='Budget',
                                Type__c='Sales',Budget_Owner__c='David Silva',Total_Expenses__c= 0,Remaining_Amount__c=0);
   insert budg;
    
  Expense__c exp = new Expense__c(Name='Mar',Expense_id__c=257,Reason__c='Travel',Amount__c=200,Date__c='5/22/2016',
                                 Other_Expense__c='Certification',
                                  Status__c='Approved',Type__c='Sales',Budget.LookUP__c.Id=budg.Id);
        insert exp;


Error:

Invalid field initializer: Budget.LookUP__c.IdDisplay Error
Display Error

With Regards,
   Nisha
 
Mahesh DMahesh D
Hi Nisha,

Please find the below code:

If your field is Budget_LookUP__c
Budget__c budg= new Budget__c(Name='Sales2',Initial_Amount__c = 50000,Valid_From__c='1/1/2016',Valid_To__c='12/1/2016',Description__c='Budget',
                                Type__c='Sales',Budget_Owner__c='David Silva',Total_Expenses__c= 0,Remaining_Amount__c=0);
insert budg;
    
Expense__c exp = new Expense__c(Name='Mar',Expense_id__c=257,Reason__c='Travel',Amount__c=200,Date__c='5/22/2016',
        Other_Expense__c='Certification', Status__c='Approved',Type__c='Sales',Budget_LookUP__c=budg.Id);
insert exp;

If your field is LookUP__c​
 
Budget__c budg= new Budget__c(Name='Sales2',Initial_Amount__c = 50000,Valid_From__c='1/1/2016',Valid_To__c='12/1/2016',Description__c='Budget',
                                Type__c='Sales',Budget_Owner__c='David Silva',Total_Expenses__c= 0,Remaining_Amount__c=0);
insert budg;
    
Expense__c exp = new Expense__c(Name='Mar',Expense_id__c=257,Reason__c='Travel',Amount__c=200,Date__c='5/22/2016',
        Other_Expense__c='Certification', Status__c='Approved',Type__c='Sales',LookUP__c=budg.Id);
insert exp;

Regards,
Mahesh
David SilvaDavid Silva
Hi Mahesh,

Thanks a lot for your  help.
But it is not taking the date,I gave system.today() and run the program.The test passed and 86%code coverage.
The budget and the expense  that  created through the testclass is not there in the actual salesforce UI.
Is it like that?

With Regards
 Nisha.
Mahesh DMahesh D
Hi Nisha,

Yes, whatever we insert / update / delete the records in Test Methods will not commit to the Salesforce database. It will just simulate the operation.

Regards,
Mahesh
David SilvaDavid Silva
Hi Mahesh,
Thank You for the help.


With Regards,
    Nisha.