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
dash27dash27 

Problem with Visualforce and Forecasts - Error: Argument 1 cannot be null

Hi all,

 

My goal is to create a simple report that shows several key bits of information along with a Rep's current forecast.  Everything works wonderfully in my sandbox, but I am unable to successfully deploy to my production site.  I'm pretty sure its because I am doing something odd in the test.

 

Visualforce page:

<apex:page standardController="RevenueForecast" extensions="WeeklyForecastExtension">
    <apex:sectionHeader Title="Pipeline Report"/>
    Click on a person's name below to edit or see more details on his or her forecast.
    <apex:pageBlock >
        <apex:pageBlockTable value="{!forecastList}" var="forecast" >
			<apex:column headerValue="Owner" width="300"> 
			    <apex:outputLink value="https://cs13.salesforce.com/027/s?forecastUserId_lkid={!forecast.OwnerId}&mode=view" id="theLink">
			        {!salesRepName[forecast.OwnerId]}
			    </apex:outputLink>
			</apex:column>
			<apex:column headerValue="{!year} YTD Sales" width="300" style="text-align:right" > 
			    <apex:outputText value="{!repSalesForYear[forecast.OwnerId]}"/>
			</apex:column>
			<apex:column headerValue="{!quarter} QTD Sales" width="300" style="text-align:right" > 
			    <apex:outputText value="{!repSalesForQuarter[forecast.OwnerId]}"/>
			</apex:column>
			<apex:column headerValue="Commit" width="300" style="text-align:right" > 
			    <apex:outputField value="{!forecast.Commit}"/>
			</apex:column>
			<apex:column headerValue="Best Case" width="300" style="text-align:right" > 
			    <apex:outputField value="{!forecast.Upside}"/>
			</apex:column>
			<apex:column headerValue="{!quarter} Pipeline" width="300" style="text-align:right"> 
			    <apex:outputField value="{!forecast.Pipeline}"/>
			</apex:column>
			<apex:column headerValue="{!Year} Pipeline" width="300" style="text-align:right"> 
			    <apex:outputText value="{!repOppsOver30[forecast.OwnerId]}"/>
			</apex:column>
        </apex:pageBlockTable>
    </apex:pageBlock>
</apex:page>

 Forecast Extension:

public class WeeklyForecastExtension {
	
	//Create containers and variables needed on Visualforce page
    public list<RevenueForecast> forecastList {get; set;}
    public list<Opportunity> allOpportunities{get; set;}
    public list<user> salesReps {get; set;}
    public map<id, string> salesRepName {get; set;}
    public map<id, string> repSalesForYear{get; set;}
    public map<id, string> repSalesForQuarter {get; set;} 
    public map<id, string> repOppsOver30 {get; set;}
    public integer year {get; set;}
    public string quarter {get; set;}
    
    
    public WeeklyForecastExtension(ApexPages.StandardController controller) {       
        
        
        //Determine date variables (Current Quarter, Year and today's date)
        string forecastDateString = '';
        date today = date.today();
        year = today.year();
        boolean isQ1 = false;
        boolean isQ2 = false;
        boolean isQ3 = false;
        boolean isQ4 = false;
        if(today.month()== 1 || today.month()== 2 || today.month()== 3 ){
            isQ1 = true;
            quarter = 'Q1';
            forecastDateString = year + '-1-1';
        }
        else if(today.month()== 4 || today.month()== 5 || today.month()== 6 ){
            isQ2 =true;
            quarter = 'Q2';
            forecastDateString = year + '-4-1';
        }
        else if(today.month()== 7 || today.month()== 8 || today.month()== 9 ){
            isQ3 =true;
            quarter = 'Q3';
            forecastDateString = year + '-7-1';
        }
        else if(today.month()== 10 || today.month()== 11 || today.month()== 12 ){
            isQ4 =true;
            quarter = 'Q4';
            forecastDateString = year + '-10-1';
        }        
        date forecastPeriod = date.valueOf(forecastDateString);
        
        //Collect User information into a list
        UserRole salesRepRole = [select id from UserRole where Name =: 'Sales'];
        id roleId = salesRepRole.id;
        salesReps = new List<user>([select FirstName, Id, LastName, isActive from User where userRoleId =: salesRepRole.id and isActive = true 
                and ForecastEnabled = true]);
        
        //Collect all relevant forecasts into a list
        forecastList = new list<RevenueForecast>([select OwnerId, StartDate, Quota, Commit, Pipeline, Upside, Closed from RevenueForecast 
                where StartDate =: forecastPeriod and OwnerId in :salesReps]);
        allOpportunities = new List<Opportunity>([select OwnerId, Amount, IsWon, CloseDate, Close_Year__c, ForecastCategoryName, Probability,  
                isClosed from Opportunity where Close_Year__c =: year]);
        
        //Define maps collections
        salesRepName = new map<id, string>();     
        repSalesForYear = new map<id, string>();
        repSalesForQuarter = new map<id, string>();
        repOppsOver30 = new map<id, string>();
        
        //Loop through each Sales Rep and determine his/ her name, YTD Amount, QTD Amount and ProbabilityAbove30Amount by looping through each
        //opportunity and adding up the relevant values.
        for(integer x = 0; x < salesReps.size(); x++){
        	//Determine the name of the sales rep
            string salesRepNameString =  salesReps[x].FirstName + ' ' + salesReps[x].LastName;
            salesRepName.put(salesReps[x].id, salesRepNameString);
            
            //Set initial values.
            decimal ytdAmount = 0;
            decimal qtdAmount = 0;
            decimal probabilityAbove30Amount = 0;
            
            //Loop through each opportunity in the list.
            for(integer y = 0; y < allOpportunities.size(); y++){
                if(salesReps[x].id == allOpportunities[y].OwnerId){
                    if(allOpportunities[y].isWon){
                    	//If the Oppoortunity belongs to the current SalesRep and is Won, add the Opportunity's Amount to the rep's YTD AMount.
                        ytdAmount += allOpportunities[y].Amount;
                        
                        //If the Oppoortunity belongs to the current SalesRep, is Won and was closed this quarter, add the Opportunity's Amount to 
                        //the rep's QTD AMount.
                        date closeDate = allOpportunities[y].CloseDate;
                        boolean isCurrentQuarter = false;
                        if((closeDate.month()== 1 || closeDate.month()== 2 || closeDate.month()== 3 )&& isQ1){
                            qtdAmount += allOpportunities[y].Amount;
                        }
                        else if((closeDate.month()== 4 || closeDate.month()== 5 || closeDate.month()== 6 ) && isQ2){
                            qtdAmount += allOpportunities[y].Amount;
                        }
                        else if((closeDate.month()== 7 || closeDate.month()== 8 || closeDate.month()== 9 )&& isQ3){
                            qtdAmount += allOpportunities[y].Amount;
                        }
                        else if((closeDate.month()== 10 || closeDate.month()== 11 || closeDate.month()== 12 )&& isQ4){
                            qtdAmount += allOpportunities[y].Amount;
                        }
                    }
                    
                    //If the Opp is open and has a probability of >= 30%, add the Opp's Amount to the rep's probabilityAbove30Amount
                    if(allOpportunities[y].Probability >= 30 && !allOpportunities[y].isWon && !allOpportunities[y].isClosed){
                        probabilityAbove30Amount += allOpportunities[y].Amount;
                    }
                }
            }
            //Enter in the Rep's ID and total values into these map collections
            repSalesForYear.put(salesReps[x].id, Global_Variables.convertToCurrencyFormat(ytdAmount.setScale(2)) ); 
            repSalesForQuarter.put(salesReps[x].id, Global_Variables.convertToCurrencyFormat(qtdAmount.setScale(2)) );
            repOppsOver30.put(salesReps[x].id, Global_Variables.convertToCurrencyFormat(probabilityAbove30Amount.setScale(2)) ); 
        }

    
    }//End constructor
}

 

Test Class:

@isTest
private class WeeklyForecast_Test {

    static testMethod void myUnitTest() {
    System.debug('Begining WeeklyForecast_Test');
    	
        UserRole salesRepRole = [select id from UserRole where Name =: 'Sales'];
        
        Profile p = [select id from profile where name='Standard User'];
        User thisUser = [ select Id from User where Id = :UserInfo.getUserId() ];
        System.runAs ( thisUser ) {
        	//Create users for test
	        User salesRep1 = new User(alias = 'standt', email='salesRep1@testorg.com', emailencodingkey='UTF-8', profileId = p.id,  
	                firstname = 'Sales', lastname='Rep1', languagelocalekey='en_US',localesidkey='en_US', userRoleId = salesRepRole.id, 
	                timezonesidkey='America/Los_Angeles', username='salesRep1@testorg.com', isActive = true, ForecastEnabled = true);
	        insert salesRep1;
	        
	        User salesRep2 = new User(alias = 'standt', email='salesRep2@testorg.com', emailencodingkey='UTF-8', profileId = p.id,  
	                firstname = 'Sales', lastname='Rep2', languagelocalekey='en_US',localesidkey='en_US', userRoleId = salesRepRole.id, 
	                timezonesidkey='America/Los_Angeles', username='salesRep2@testorg.com', isActive = true, ForecastEnabled = true);
	        insert salesRep2;
	        
	        //Create Opportunities for Test
	        list<Opportunity> oppsToInsert = new list<Opportunity>();
	        Opportunity SalesRep1_Closed_Quarter = new Opportunity(name = 'SalesRep1_Closed_Quarter', StageName = '100% - Closed Won', OwnerId = salesRep1.id, 
	                CloseDate = date.valueOf('2012-4-15'), Amount = 100);
	        oppsToInsert.add(SalesRep1_Closed_Quarter);
	        
	        Opportunity SalesRep1_Closed_Year = new Opportunity(name = 'SalesRep1_Closed_Year', StageName = '100% - Closed Won', OwnerId = salesRep1.id, 
	                CloseDate = date.valueOf('2012-1-15'), Amount = 300);
	        oppsToInsert.add(SalesRep1_Closed_Year);
	        
	        Opportunity SalesRep1_Under30 = new Opportunity(name = 'SalesRep1_Under30', StageName = '20% - Conference / E-Lead', OwnerId = salesRep1.id, 
	                CloseDate = date.valueOf('2012-6-15'), Amount = 20);
	        oppsToInsert.add(SalesRep1_Under30);
	        
	        Opportunity SalesRep1_30 = new Opportunity(name = 'SalesRep1_30', StageName = '30% - Appt Set', OwnerId = salesRep1.id, 
	                CloseDate = date.valueOf('2012-4-25'), Amount = 30);
	        oppsToInsert.add(SalesRep1_30);
	        
	        Opportunity SalesRep1_Best = new Opportunity(name = 'SalesRep1_Best', StageName = '50% - Renewal', OwnerId = salesRep1.id, 
	                CloseDate = date.valueOf('2012-5-5'), Amount = 500);
	        oppsToInsert.add(SalesRep1_Best);
	        
	        Opportunity SalesRep1_Commit = new Opportunity(name = 'SalesRep1_Commit', StageName = '80% - PO in Process', OwnerId = salesRep1.id, 
	                CloseDate = date.valueOf('2012-5-15'), Amount = 500);
	        oppsToInsert.add(SalesRep1_Commit);
	        
	        insert oppsToInsert;
	        
	        //Calculate Totals
	        decimal rep1YearTotal = SalesRep1_Closed_Quarter.Amount + SalesRep1_Closed_Year.Amount;
	        decimal rep1QuarterTotal = SalesRep1_Closed_Quarter.Amount;
	        decimal rep1Commit =  SalesRep1_Closed_Quarter.Amount + SalesRep1_Commit.Amount;
	        decimal rep1Best = SalesRep1_Closed_Quarter.Amount + SalesRep1_Commit.Amount + SalesRep1_Best.Amount;
	        decimal rep1Pipeline = SalesRep1_Commit.Amount + SalesRep1_Best.Amount;
	        decimal rep1Closed = SalesRep1_Closed_Quarter.Amount;     
	        decimal rep1Over30 = SalesRep1_30.Amount + SalesRep1_Commit.Amount + SalesRep1_Best.Amount;
	        
	        RevenueForecast rep1Forecast = new RevenueForecast(OwnerId = salesRep1.id, StartDate = date.valueOf('2012-4-1'), Quota = 0);
	                
	        insert rep1Forecast;
	
	        //Initialize variables
	        PageReference pref = Page.WeeklyForecast;
	        Test.setCurrentPage(pref);
	        
	        ApexPages.StandardController con = new ApexPages.StandardController(rep1Forecast);
	        WeeklyForecastExtension ext = new WeeklyForecastExtension(con);
	        
	        /*****************************
	        /*   Start Test
	        /*****************************/
	        Test.startTest();
	        
	        //Clone Map container from extension
	        map<id, string> test_salesRepName = new map<id,String>();
	        test_salesRepName = ext.salesRepName.clone();
	        String string_rep1Name = test_salesRepName.get(salesRep1.id);
	        //Verify values are as expected.
	        system.assertEquals(string_rep1Name, 'Sales Rep1');
	        
	        //Clone Map container from extension
	        map<id, string> test_repSalesForYear = new map<id,String>();
	        test_repSalesForYear = ext.repSalesForYear.clone();
	        String string_repSalesForYear = test_repSalesForYear.get(salesRep1.id);
	        //Verify values are as expected.
	        system.assertEquals(string_repSalesForYear, Global_Variables.convertToCurrencyFormat(rep1YearTotal.setScale(2)));
	        
	        //Clone Map container from extension
	        map<id, string> test_repSalesForQuarter = new map<id,String>();
	        test_repSalesForQuarter = ext.repSalesForQuarter.clone();
	        String string_repSalesForQuarter = test_repSalesForQuarter.get(salesRep1.id);
	        //Verify values are as expected.
	        system.assertEquals(string_repSalesForQuarter, Global_Variables.convertToCurrencyFormat(rep1QuarterTotal.setScale(2)));
	        
	        //Clone Map container from extension
	        map<id, string> test_repOppsOver30 = new map<id,String>();
	        test_repOppsOver30 = ext.repOppsOver30.clone();
	        String string_repOver30 = test_repOppsOver30.get(salesRep1.id);
	        //Verify values are as expected.
	        system.assertEquals(string_repOver30, Global_Variables.convertToCurrencyFormat(rep1Over30.setScale(2)));

        }
    }
}

 

The page should not require a parameter and therefore I'm not sure what to put in when defining the Controller.

 

Any help is greatly appreciated.

Best Answer chosen by Admin (Salesforce Developers) 
dash27dash27

I figured it out.  The issue I was having was that I was including Opportunities that had null for the Amount value.  Once i filtered these Opportunities out, everything worked GREAT!