• Robert Davis 16
  • NEWBIE
  • 130 Points
  • Member since 2016

  • Chatter
    Feed
  • 0
    Best Answers
  • 3
    Likes Received
  • 2
    Likes Given
  • 19
    Questions
  • 30
    Replies
I have a trigger that executes on after insert and after create on the Opportunity that updates fields on the OpportunityLineItem Object. Code works but the test class opportunity does not appear to successfully add a product so the code can not go into a IF statement. I am sure this is something simple but dang if I can figure it out. Your help would be greatly appreciated:
 
TRIGGER

//Case Number 1381 - Provides information about request for Trigger
trigger UpdateOTRev on Opportunity (after insert, after update) {
    Set<id> triggerIds = new Set<id>();
    List<OpportunityLineItem> lstOLIUpdate = new List<OpportunityLineItem>();
    //See if Trigger has only been run once
    if(RecursiveTriggerHandler.isFirstTime){
        RecursiveTriggerHandler.isFirstTime = false;
         //Put all trigger opp ids into a set
         for(Opportunity Opps : Trigger.new){
            triggerIds.add(Opps.Id);
         }//END for (Opportunity Opps)
         //Get all the Opp and Products
         List<Opportunity> lstOpps = [SELECT id, CloseDate, (SELECT id, TotalPrice, One_Time_Revenue__c FROM OpportunityLineItems) FROM Opportunity 
                                      WHERE id in: triggerIds];
             //Loop through Opps
             for(Opportunity opp: lstOpps){
                 //Loop through Products in Opps
                 for(OpportunityLineItem oli : opp.OpportunityLineItems){
                     if(oli.One_Time_Revenue__c == true){
                        //Apply the logic of which fields to update
                        if(opp.CloseDate > Date.valueOf('2017-12-31') && opp.CloseDate < Date.valueOf('2018-04-01')){
                            oli.One_Time_Rev_Q1_2018__c = oli.TotalPrice;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            lstOLIUpdate.add(oli);              
                        }//END if 2018 Q1
                        if(opp.CloseDate > Date.valueOf('2018-03-31') && opp.CloseDate < Date.valueOf('2018-07-01')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = oli.TotalPrice;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            lstOLIUpdate.add(oli);              
                        }//END if 2018 Q2
                        if(opp.CloseDate > Date.valueOf('2018-06-30') && opp.CloseDate < Date.valueOf('2018-10-01')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = oli.TotalPrice;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            lstOLIUpdate.add(oli);              
                        }//END if 2018 Q3
                        if(opp.CloseDate > Date.valueOf('2018-09-30') && opp.CloseDate < Date.valueOf('2019-01-01')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = oli.TotalPrice;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            lstOLIUpdate.add(oli);              
                        }//END if 2018 Q4
                        if(opp.CloseDate > Date.valueOf('2018-12-31') && opp.CloseDate < Date.valueOf('2019-04-01')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = oli.TotalPrice;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            lstOLIUpdate.add(oli);              
                        }//END if 2018 Q1
                        if(opp.CloseDate > Date.valueOf('2019-03-31') && opp.CloseDate < Date.valueOf('2019-07-01')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = oli.TotalPrice;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            lstOLIUpdate.add(oli);              
                        }//END if 2019 Q2
                        if(opp.CloseDate > Date.valueOf('2019-06-30') && opp.CloseDate < Date.valueOf('2019-10-01')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = oli.TotalPrice;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            lstOLIUpdate.add(oli);              
                        }//END if 2019 Q3
                        if(opp.CloseDate > Date.valueOf('2019-09-30') && opp.CloseDate < Date.valueOf('2020-01-01')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = oli.TotalPrice;
                            lstOLIUpdate.add(oli);              
                        }//END if 2019 Q4
                        if(opp.CloseDate > Date.valueOf('2019-12-31')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            
                            lstOLIUpdate.add(oli);
                        }
                         
                     }//END if(oli.One_Time_Revenue__c == true)                     
                 }//END For(OpportunityLineItem)
             }//END for(Opportunity)
    //Update Products if there are any to update
    if(lstOLIUpdate.size()>0){
        update lstOLIUpdate;
    }
    }//END if(RecusiveTriggerHandler.isFirstTime)
}//END Class

TEST CLASS
@isTest
public class UpdateOTRevTest {
    
    public static testMethod void testOppOneTimeRevenue(){
        
        Product2 prod2= new Product2(Name = 'Test Product - OneTime',
                                     Product_Gross_Margin__c = 10,
                                     Delivery_Market__c = 'none' ,
                                     Delivery_Region__c = 'ABCD',
                                     Delivery_Site__c = 'none' ,
                                     Family = 'XTCD',
                                     Description = 'Test Product',
                                     IsActive = true,
                                     Project_Seat_Count__c = 'false',
                                     One_Time_Revenue__c = true);
        insert prod2;
        Id pricebookId = Test.getStandardPricebookId();
        PricebookEntry pbEntry = new PricebookEntry(Pricebook2Id = pricebookId,
                                                    product2Id = prod2.Id,
                                                    isActive = true,
                                                    UnitPrice = 1000);
        insert pbEntry;
       
        Opportunity opp = new Opportunity(Name = 'Test Account - Opportunity',
                                          StageName = '1 - Prospect',
                                          Type = 'New Logo', 
                                          CloseDate = System.Date.today(),
                                          LeadSource = 'BDD/AM/OPS Development',
                                          Referral_Channel__c = 'None',
                                          Auto_Generate_Quarterly_Forecast__c = 'Yes',
                                          Contract_Length_Months__c = 24,
                                          Pricebook2Id = pricebookId,
                                          Amount = 10000000);
        insert opp;
       
        OpportunityLineItem oli = new OpportunityLineItem(OpportunityId = opp.id,
                                                          PricebookEntryId = pbEntry.id,
                                                          Product2Id = prod2.id,
                                                          Quantity = 10, 
                                                          Unit_Price2__c = 20,
                                                          Adjusted_Gross_Margin_Percentage__c = 10,
                                                          Service_Channel__c = 'WIDGET',
                                                          Service_Type__c = 'Care',
                                                          One_Time_Revenue__c = true);
        insert oli;
        
        System.debug('Opportunity Product Total Price '+ oli.TotalPrice);
        System.debug('OpportunityLineItem Id ' +oli.Id);
        System.debug('Product 2 Id '+ oli.Product2Id);
        System.debug('Opportunity Line Item Name : '+ oli.Name);
        System.debug('One Time Revenue : '+oli.One_Time_Revenue__c);
        Date closeDate = System.today();
        opp.CloseDate = Date.newInstance(2018, 01, 25);
       
        update opp;
        System.debug('Opp Close Date : '+opp.CloseDate);
    }//END Method
}//END Class

//https://salesforce.stackexchange.com/questions/72883/how-to-create-opportunity-line-items-in-test-classes

Code coverage is 10 of 103 lines because it does not appear that the OpportunityLineItem ever gets associated with the Opportunity.
User-added image

I would greatly appreciate any help.

Thank you. ​
I have a Trigger on the Opportunity which will update a field on the OpportunityLineItem, which updates the Opportunity which the fires the trigger to update the OpportunityLineItems. I think it is a classic recursion issue my problem is I do not know how to stop it. Please help:
 
trigger UpdateOTRev on Opportunity (after insert, after update) {
    Set<id> triggerIds = new Set<id>();
    List<OpportunityLineItem> lstOLIUpdate = new List<OpportunityLineItem>();
    for(Opportunity Opps : Trigger.new){
        triggerIds.add(Opps.Id);
    }
    List<Opportunity> lstOpps = [SELECT id, CloseDate, (SELECT id, TotalPrice FROM OpportunityLineItems) FROM Opportunity 
                                 WHERE id in: triggerIds];
    for(Opportunity opp: lstOpps){
        for(OpportunityLineItem oli : opp.OpportunityLineItems){
            
            if(opp.CloseDate > Date.valueOf('2017-12-31') && opp.CloseDate < Date.valueOf('2018-04-01')){
                oli.Test_Q1_2018__c = oli.TotalPrice;
                oli.Test_Q2_2018__c = 0;
                oli.Test_Q3_2018__c = 0;
                oli.Test_Q4_2018__c = 0;
                oli.Test_Q1_2019__c = 0;
                oli.Test_Q2_2019__c = 0;
                oli.Test_Q3_2019__c = 0;
                oli.Test_Q4_2019__c = 0;
                lstOLIUpdate.add(oli);              
            }//END if 2018 Q1
            if(opp.CloseDate > Date.valueOf('2018-03-31') && opp.CloseDate < Date.valueOf('2018-07-01')){
                oli.Test_Q1_2018__c = 0;
                oli.Test_Q2_2018__c = oli.TotalPrice;
                oli.Test_Q3_2018__c = 0;
                oli.Test_Q4_2018__c = 0;
                oli.Test_Q1_2019__c = 0;
                oli.Test_Q2_2019__c = 0;
                oli.Test_Q3_2019__c = 0;
                oli.Test_Q4_2019__c = 0;
                lstOLIUpdate.add(oli);              
            }//END if 2018 Q2
            if(opp.CloseDate > Date.valueOf('2018-06-30') && opp.CloseDate < Date.valueOf('2018-10-01')){
                oli.Test_Q1_2018__c = 0;
                oli.Test_Q2_2018__c = 0;
                oli.Test_Q3_2018__c = oli.TotalPrice;
                oli.Test_Q4_2018__c = 0;
                oli.Test_Q1_2019__c = 0;
                oli.Test_Q2_2019__c = 0;
                oli.Test_Q3_2019__c = 0;
                oli.Test_Q4_2019__c = 0;
                lstOLIUpdate.add(oli);              
            }//END if 2018 Q3
            if(opp.CloseDate > Date.valueOf('2018-09-30') && opp.CloseDate < Date.valueOf('2019-01-01')){
                oli.Test_Q1_2018__c = 0;
                oli.Test_Q2_2018__c = 0;
                oli.Test_Q3_2018__c = oli.TotalPrice;
                oli.Test_Q4_2018__c = 0;
                oli.Test_Q1_2019__c = 0;
                oli.Test_Q2_2019__c = 0;
                oli.Test_Q3_2019__c = 0;
                oli.Test_Q4_2019__c = 0;
                lstOLIUpdate.add(oli);              
            }//END if 2018 Q4
        }//END For(OpportunityLineItem)
    }//END for(Opportunity)
    if(lstOLIUpdate.size()){
        update lstOLIUpdate;
    }

}

Thank you,

Robert​
On the OpportunityLineItem I have two triggers: One that updates the Unit Price and another that applies a Discount before the record is Saved and another that Updates a field on the Opportunity. Both work fine separately but when put together the insert after creates a problem where I get the following error message:

OpportunityLineItemTrigger: execution of AfterInsert caused by: System.FinalException: Record is read-only Trigger.OpportunityLineItemTrigger: line 12, column 1
 
trigger OpportunityLineItemTrigger on OpportunityLineItem (before insert, before update, after update, after insert) {
    List<Opportunity> opps = new List<Opportunity>();
    List<Id> oppIds = new List<Id>();
    Decimal contractLengthMonths = 0;

//---------------BEFORE TRIGGER BELOW----------
    if(trigger.isInsert || trigger.isUpdate && trigger.isBefore) {
        List<OpportunityLineItem> oli = new List<OpportunityLineItem>();
        for (OpportunityLineItem oli2: trigger.new){
            if(oli2.Number_of_Months__c > 0){
                oli2.UnitPrice = ((oli2.Number_of_Months__c / 12) * oli2.Unit_Price2__c);
            } else if (oli2.Number_of_Months__c == null || oli2.Number_of_Months__c == 0 ) {
                oli2.UnitPrice = oli2.Unit_Price2__c;
            }
            if(oli2.Adjusted_Gross_Margin_Percentage__c == 0 && oli2.Product_Gross_Margin_Percent2__c != 0 ) {
                if (oli2.Number_of_Months__c > 0) {
                    oli2.Gross_Margin_Dollars__c = (oli2.Unit_Price2__c * oli2.Quantity * (oli2.Number_of_Months__c / 12)) * (oli2.Product_Gross_Margin_Percent2__c/100);
                } else {
                    oli2.Gross_Margin_Dollars__c = (oli2.Unit_Price2__c * oli2.Quantity) * (oli2.Product_Gross_Margin_Percent2__c/100);
                }
             } else if (oli2.Adjusted_Gross_Margin_Percentage__c > 0) {
                if (oli2.Number_of_Months__c > 0) {
                    oli2.Gross_Margin_Dollars__c = (oli2.Unit_Price2__c * oli2.Quantity * (oli2.Number_of_Months__c / 12)) * (oli2.Adjusted_Gross_Margin_Percentage__c/100);
                } else {
                    oli2.Gross_Margin_Dollars__c = (oli2.Unit_Price2__c * oli2.Quantity) * (oli2.Adjusted_Gross_Margin_Percentage__c/100);
                }
            }//END if(oli2.Adjusted_Gross_Margin_Percentage__c == 0 || oli2.Adjusted_Gross_Margin_Percentage__c == null) 
            
        }//END for (OpportunityLineItem oli2: trigger.new)
    }//if(trigger.isInsert || trigger.isUpdate && trigger.isBefore) 

//---------AFTER TRIGGER BELOW--------------

    if(trigger.isAfter) {
        for (OpportunityLineItem oli3: trigger.new){
            oppids.add(oli3.opportunityId);
            
        }//END for (OpportunityLineItem oli3: trigger.new)
        List<OpportunityLineItem> allOLI = [SELECT id, Number_of_Months__c FROM OpportunityLineItem WHERE OpportunityId in: oppids];
        List<Opportunity> oppsToUpdate = [SELECT id, Contract_Length_Months__c FROM Opportunity WHERE id in: oppids];
        if(allOLI.size() > 0){
            for(OpportunityLineItem allOLI2: allOLI){
                if(allOLI2.Number_of_Months__c > contractLengthMonths){
                    contractLengthMonths = allOLI2.Number_of_Months__c;
                } else if (allOLI2.Number_of_Months__c == null) {
                    contractLengthMonths = 12;
                }
            } //END for(OpportunityLineItem allOLI2: allOLI)
            for(Opportunity oppUpdate: oppsToUpdate){
                oppUpdate.Contract_Length_Months__c = contractLengthMonths;
                opps.add(oppUpdate);
            }// END for(Opportunity oppUpdate: oppsToUpdate)
 
        }//END if(allOLI.size() > 0
        update opps;
    }//if(trigger.isAfter)
}//END OpportunityLineItem Class

Your help would be greatly appreciated.

Robert​
I have gotten myself turned around on this trigger and can not figure out how to get it right. I have a custom field on the OpportunityLineItem / Opportunity Product that has the Length of Months that the product will be used for called Number_of_Months__c. I need to update the Opportunity in a field called Contract_Length_Months__c with the maximum date of all the products when a customer enters it.

I would appreciate any help in pointing me in the right direction:
 
trigger OpportunityLineItemTrigger on OpportunityLineItem ( after update) {
    List<Id> oppIds = new List<Id>();
    Decimal contractLengthMonths = 0;

    if(trigger.isAfter) {
        for (OpportunityLineItem oli3: trigger.new){
            oppids.add(oli3.opportunityId);
        }//END for (OpportunityLineItem oli3: trigger.new)
        List<OpportunityLineItem> allOLI = [SELECT id, Number_of_Months__c FROM OpportunityLineItem WHERE OpportunityId in: oppids];
        List<Opportunity> oppsToUpdate = [SELECT id, Contract_Length_Months__c FROM Opportunity WHERE id in: oppids];
        if(allOLI.size() > 0){
            for(OpportunityLineItem allOLI2: allOLI){
                if(allOLI2.Number_of_Months__c > contractLengthMonths){
                    contractLengthMonths = allOLI2.Number_of_Months__c;
                }//END if(allOLI2.Number_of_Months__c > contractLengthMonths)
            } //END for(OpportunityLineItem allOLI2: allOLI)
            for(Opportunity oppUpdate: oppsToUpdate){
                oppUpdate.Contract_Length_Months__c = contractLenghtMonths;
            }// END for(Opportunity oppUpdate: oppsToUpdate)
 
        }
    }//if(trigger.isAfter)
}//END OpportunityLineItem Class

At the line:
oppUpdate.Contract_Length_Months__c = contractLenghtMonths;

I get the following error from the Developer Console IDE : "Variable does not exist: contractLenghtMonths"

Thank you in advance for any help.

Robert
I have the following code that creates a URL to go to another system. I have a date field that I pull from an ApexController but when it appears in the URL it shows today's date and not the one from the field. I do not get an error (that I know about, quite frankly I am not great with how to use the Developer Tools in Chrome)

Any ideas of the error or how to troubleshoot this?
This is the HELPER:
({
	navigate : function(component) {
        var action = component.get("c.getOpportunity");
		var idOpp = component.get("v.recordId");
        var SCMAid = component.get("v.aid");
        var SCMFormId = component.get("v.formId");
		if(!$A.util.isEmpty(idOpp))
		{
			action.setParams({opportunityId: idOpp});
		
			// Create a callback that is executed after 
			// the server-side action returns
			action.setCallback(this, function(response) {
				var state = response.getState();
				if (state === "SUCCESS") {
					var opp = response.getReturnValue();
                    /* Here you can access like opp.Id, opp.FTEs__c, opp.Account.Industry and form the URL */
                    var fullTimeEmployees = opp.Total_FTEs__c;
                    var industry = opp.Account.Industry;
                    var programStartDate = $A.localizationService.formatDate(Date(opp.ProgramStartDate__c),"MM/DD/YYYY");  
                    var opportunityId = opp.Id;
                    var opportunityName = opp.Name;                    
					var filePath = '/Accounts/'+ opp.Account.Name + '/Opportunities/&ru=%2Fatlas%2Fbpm%2FWorkList.aspx'
                    var partOneURL = 'https://na123.springcm.com/atlas/Forms/UpdateFormDoc.aspx?';
					
                    var partTwoURL = 'aid='+SCMAid;
                    var formUid = SCMFormId;
                    if(SCMAid == '9999') {
                        //Sandbox URL
                        var partOneURL = 'https://uatna123.springcm.com/atlas/Forms/UpdateFormDoc.aspx?';
                    } else {
                        //Production URL
                        var partOneURL = 'https://na123.springcm.com/atlas/Forms/UpdateFormDoc.aspx?';
                    }
					var finalURL = partOneURL + partTwoURL 
                    var finalURL = finalURL + '&FormUid=' + formUid;
                    var finalURL = finalURL + '&SFFTE=' + fullTimeEmployees;
                    var finalURL = finalURL + '&SFIND=' + industry;
                    var finalURL = finalURL + '&SFPSD=' + programStartDate;
                    var finalURL = finalURL + '&SFID=' + opp.Id;
                    var finalURL = finalURL + '&SFNAME=' + opportunityName;
                    var finalURL = finalURL + '&SFWF=ABC';
                    var finalURL = finalURL + '&SFCAFTYPE=CAAF';
                    var finalURL = finalURL + '&SFTYPE=Salesforce.Opportunity';
                    var finalURL = finalURL + '&SFPATH=' + filePath;
                    var urlEvent=$A.get("e.force:navigateToURL");
                    urlEvent.setParams({"url": finalURL});
					urlEvent.fire();
				}
				else if (state === "ERROR") {
					var errors = response.getError();
					if (errors) {
						if (errors[0] && errors[0].message) {
							console.log("Error message: " + 
									 errors[0].message);
						}
					} else {
						console.log("Unknown error");
					}
				}
			});

			// optionally set storable, abortable, background flag here

			// A client-side action could cause multiple events, 
			// which could trigger other events and 
			// other server-side action calls.
			// $A.enqueueAction adds the server-side action to the queue.
			$A.enqueueAction(action);
		}
		else
		{
			console.log('===Record Id is not present====');
		}
	}
})
The variable that I am having the issue with is:
 var programStartDate = $A.localizationService.formatDate(Date(opp.ProgramStartDate__c),"MM/DD/YYYY");  

Not sure why I get today's date and not the one from the controller.

Thanks in advance.

Robert
 
Hello, I am hoping some will be able to help. I have a visualforce page that I use to select products from the pricebook. What I would like to do is when a field named Seats__c is updated on the page that it also updates the field value of a field named X2018_Q1_Seats__c. I would like to have it so that if the user would like to over write it they can but it would default to the value in Seats__c by default.

Below is what I have tried, unsuccessfully:
<apex:page standardController="Opportunity" extensions="opportunityProductEntryExtension" action="{!priceBookCheck}" >
    <apex:sectionHeader Title="Manage {!$ObjectType.Product2.LabelPlural}" subtitle="{!opportunity.Name}"/>
    <apex:messages style="color:red"/>

    <style>
        .search{
            font-size:14pt;
            margin-right: 20px;    
        }
        .fyi{
            color:red;
            font-style:italic;
        }
        .label{
            margin-right:10px;
            font-weight:bold;
        }
        
    </style>
    
    <script type='text/javascript'>
    
        // This script assists the search bar functionality
        // It will execute a search only after the user has stopped typing for more than 1 second
        // To raise the time between when the user stops typing and the search, edit the following variable:
        
        var waitTime = 1;
        
    
        var countDown = waitTime+1;
        var started = false;
        
        function resetTimer(){
        
            countDown=waitTime+1;
            
            if(started==false){
                started=true;
                runCountDown();
            }
        }
        
        function runCountDown(){
        
            countDown--;
            
            if(countDown<=0){
                fetchResults();
                started=false;
            }
            else{
                window.setTimeout(runCountDown,1000);
            }
        }
        function updateSeats() {
            var totalSeats = document.getElementById("{!$Component.pageform.mainBody.selected.pageblocktable.seatColumn.Seats}");
            document.getElementById("{!$Component.pageform.mainBody.selected.pageblocktable.yearOneColumn.pageBlockSectionYearOne.result}").value = totalSeats;
            }

               
    </script>

    <apex:form id="pageform" >
    
        <apex:outputPanel id="mainBody">
        
            <apex:outputLabel styleClass="label">PriceBook: </apex:outputLabel>
            <apex:outputText value="{!theBook.Name}"/>&nbsp;
            <apex:commandLink action="{!changePricebook}" value="change" immediate="true"/>
            <br/>
            <!-- not everyone is using multi-currency, so this section may or may not show -->
            <apex:outputPanel rendered="{!multipleCurrencies}">
                <apex:outputLabel styleClass="label">Currency: </apex:outputLabel>
                <apex:outputText value="{!chosenCurrency}"/>
                <br/>
            </apex:outputPanel>
            <br/>
            
<!-- this is the upper table... a.k.a. the "Shopping Cart"-->

            <!-- notice we use a lot of $ObjectType merge fields... I did that because if you have changed the labels of fields or objects it will reflect your own lingo -->
            <apex:pageBlock title="Selected {!$ObjectType.Product2.LabelPlural}" id="selected">
                       
                <apex:pageblockTable value="{!shoppingCart}" var="s" id="pageblocktable">
                
                    <apex:column >
                        <apex:commandLink value="Remove" action="{!removeFromShoppingCart}" reRender="selected,searchResults" immediate="true">
                            <!-- this param is how we send an argument to the controller, so it knows which row we clicked 'remove' on -->
                            <apex:param value="{!s.PriceBookEntryId}" assignTo="{!toUnselect}" name="toUnselect"/>
                        </apex:commandLink>
                    </apex:column>
                    <apex:column headerValue=" " title="{!$ObjectType.Product2.fields.Name.inlineHelpText}"> 
                        <apex:pageBlockSection >
                        <apex:inputField value="{!s.Program_Start_Date__c}" label="Program Start Date :"
                                                                            rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                                                            required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        </apex:pageBlockSection>
                        <apex:outputField value="{!s.PriceBookEntry.Product2.Name}"/><br/>
                        <i>Line Item Description : </i>
                        <apex:inputField value="{!s.Description}" /><br/>
                        
                        
                    </apex:column>
                    <apex:column headerValue="">
                        <br/><br/>
                        # of&nbsp;<apex:outputField value="{!s.PricebookEntry.Product2.Unit_of_Measure_Plural__c}" style="width:180px"/><br/>
                        <apex:outputText value="Svc Channel" rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"></apex:outputText><br/><br/><br/><br/><br/>
                        <apex:outputText value="Qtrly Seat Ramp :" rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"></apex:outputText><br/><br/><br/>
                    </apex:column>
                    <apex:column headerValue=" "
                                 title="{!$ObjectType.OpportunityLineItem.fields.Quantity.inlineHelpText}" id="yearOneColumn">
                        <br/>
                        <apex:inputField value="{!s.Quantity}" style="width:50px" />
                        <apex:inputField value="{!s.Service_Channel__c}" 
                                         rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                         required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        <apex:pageBlockSection id="pageBlockSectionYearOne">
                        
                        <apex:inputField value="{!s.X2018_Q1_Seats__c}" style="width:30px" id="result" 
                                                rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                                required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        <apex:inputField value="{!s.X2018_Q2_Seats__c}" style="width:30px"
                                                rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                                required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        <apex:inputField value="{!s.X2018_Q3_Seats__c}" style="width:30px"
                                                rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                                required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        <apex:inputField value="{!s.X2018_Q4_Seats__c}" style="width:30px"
                                                rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                                required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        </apex:pageBlockSection> 
                     </apex:column>  
                        <apex:outputText value="2018 Q3" rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"></apex:outputText>                    
                    <apex:column headerValue=" "
                                 title="{!$ObjectType.OpportunityLineItem.fields.Number_of_Months__c.inlineHelpText}">
                        <center>
                        <b>Contract Length (Months)</b>
                        <apex:inputField value="{!s.Number_of_Months__c}" style="width:50px"/>
                        </center>
                    </apex:column>
                    <apex:column headerValue="">
                        price per&nbsp;<apex:outputField value="{!s.PricebookEntry.Product2.Unit_of_Measure_Singular__c}" style="width:160px"/><br/>
                        <apex:outputText value="Service Type" rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"></apex:outputText><br/><br/><br/><br/><br/>
                        <apex:outputText value="Qtrly Seat Ramp :" rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"></apex:outputText><br/><br/><br/>
                    </apex:column>
                    
                    <apex:column headerValue=" "
                                 title="{!$ObjectType.OpportunityLineItem.fields.UnitPrice.inlineHelpText}">
                        <apex:inputField value="{!s.Unit_Price2__c}" style="width:70px" required="true"  />
                        <apex:inputField value="{!s.Service_Type__c}"
                                         rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                         required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        <apex:pageBlockSection >
                        
                        <apex:inputField value="{!s.X2019_Q1_Seats__c}" style="width:30px" 
                                                 rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                                 required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        <apex:inputField value="{!s.X2019_Q2_Seats__c}" style="width:30px"
                                                rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                                required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        <apex:inputField value="{!s.X2019_Q3_Seats__c}" style="width:30px"
                                                rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                                required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        <apex:inputField value="{!s.X2019_Q4_Seats__c}" style="width:30px"
                                                rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                                required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        </apex:pageBlockSection>
                    </apex:column>
                    <apex:column headerValue=" " title="Enter Your Specific Margin - Pre-Populated with Avg">
                        <center>
                        <b>Adj GM%</b>
                        <apex:inputField value="{!s.Adjusted_Gross_Margin_Percentage__c}" style="width:30px" />
                        </center>
                    </apex:column>
                    <apex:column headerValue=" "
                                 title="{!$ObjectType.OpportunityLineItem.fields.One_Time_Revenue__c.inlineHelpText}">
                        <center>
                        <b>One-Time Rev</b>
                        <apex:inputCheckbox value="{!s.One_Time_Revenue__c}"  />
                        </center>
                    </apex:column>
                    <apex:column headerValue=" " title=" ">
                        <apex:outputLabel rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}" style="width:50px">Total # of Seats&nbsp;</apex:outputLabel>
                        <br/><br/><br/><br/><br/><br/>
                    </apex:column>

                    <apex:column headerValue=" " title="{!$ObjectType.OpportunityLineItem.fields.Seats__c.inlineHelpText}" id="seatColumn">
                        
                        <apex:inputField value="{!s.Seats__c}"  style="width:50px"  onkeyup="refreshTotals();"  id="Seats" onclick="updateSeats()"
                                      rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                      required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        <br/><br/><br/><br/><br/><br/>
                    </apex:column>

                </apex:pageblockTable>
            
            
                <apex:pageBlockButtons >
                    <apex:commandButton action="{!onSave}" value="Save"/>
                    <apex:commandButton action="{!onCancel}" value="Cancel" immediate="true"/>
                </apex:pageBlockButtons>
            
            </apex:pageBlock>   
            <apex:pageBlock >
                <apex:outputPanel styleClass="search">
                    Search for {!$ObjectType.Product2.LabelPlural}:
                </apex:outputPanel>
                <apex:actionRegion renderRegionOnly="false" immediate="true">
                    <apex:actionFunction name="fetchResults" action="{!updateAvailableList}" reRender="searchResults" status="searchStatus"/>
                    <apex:selectList value="{!selectedProdFamily}" label="Select Product Family : " multiselect="false" size="1">
                        <apex:actionSupport event="onchange" action="{!updateAvailableList}" />
                        <apex:selectOptions value="{!ProductFamily}"  />
                    </apex:selectList>
                    &nbsp;&nbsp;                 
                    <apex:inputText value="{!searchString}" onkeydown="if(event.keyCode==13){this.blur();}else{resetTimer();}" style="width:300px"/>
                    &nbsp;&nbsp;
                                  <apex:actionStatus id="searchStatus" startText="searching..." stopText=" "/>
                    </i>    
                </apex:actionRegion>
            
                <br/>
                <br/>
            
                <apex:outputPanel id="searchResults">
                    <apex:pageBlockTable value="{!AvailableProducts}" var="a">                       
                        <apex:column headerValue="{!$ObjectType.Product2.Fields.Family.Label} / Company" value="{!a.Product2.Family}"/>
                        <apex:column headerValue="{!$ObjectType.Product2.Fields.Name.Label}" value="{!a.Product2.Name}" />                      
                        <apex:column headerValue="{!$ObjectType.Product2.Fields.Product_Gross_Margin__c.Label}" value="{!a.Product2.Product_Gross_Margin__c}"/>                    
                        <apex:column >
                            <!-- command button in a column... neato -->
                            <apex:commandButton value="Select" action="{!addToShoppingCart}" reRender="selected,searchResults" immediate="true">
                                <!-- again we use apex:param to be able to tell the controller which row we are working with -->
                                <apex:param value="{!a.Id}" assignTo="{!toSelect}" name="toSelect"/>
                            </apex:commandButton>
                        </apex:column>               
                    </apex:pageBlockTable>
                    <!-- We put up a warning if results exceed 100 rows -->
                    <apex:outputPanel styleClass="fyi" rendered="{!overLimit}">
                        <br/>
                        Your search returned over 100 results, use a more specific search string if you do not see the desired {!$ObjectType.Product2.Label}.
                        <br/>
                    </apex:outputPanel>            
                </apex:outputPanel>
            </apex:pageBlock>
        </apex:outputPanel>
    </apex:form>
</apex:page>

This is the javascript function that I am trying to use (it is above but thought it would be easier to see) here:
<script>
function updateSeats() {
            var totalSeats = document.getElementById("{!$Component.pageform.mainBody.selected.pageblocktable.seatColumn.Seats}");
            document.getElementById("{!$Component.pageform.mainBody.selected.pageblocktable.yearOneColumn.pageBlockSectionYearOne.result}").value = totalSeats;
            }
</script>

Thank you in advance,

Robert
Using Salesforce Classic I am able to access an Contract Managment System by using a JavaScript Button with the standard Salesforce Page, but when I attempt to use a Visualforce Page with the following code, I get the following error:
 
{!REQUIRESCRIPT("/soap/ajax/10.0/connection.js")} 
{!REQUIRESCRIPT("/soap/ajax/10.0/apex.js")} 

//Should not have to change this at all 
function getEOSInfo(objectid,objecttype,callback) { 

var baseUrl = "{!$Api.Partner_Server_URL_260}".substring(0, "{!$Api.Partner_Server_URL_260}".indexOf("/services")); 
var url = baseUrl +"/services/apexrest/SpringCMEos/eosinfo?objecttype="+objecttype+"&objectid="+objectid; 
var authkey = "Bearer {!$Api.Session_ID}"; 

sforce.connection.remoteFunction({ 
url : url, 
method:"GET",
requestHeaders: {"Authorization":authkey,"Accept":"application/json"}, 
onSuccess : function(response) { 
var eosInfoResponse = JSON.parse(response); 
callback(eosInfoResponse); 
alert(response);
} 
}); 
} 


//Here you write your own code, this is a simple call 
var objectid = "{!Account.Id}"; 
var objecttype = "Account"; 

getEOSInfo(objectid,objecttype,function(eosInfo){ 

var formuid = "ab227d3b-188c-e711-9c0d-3ca82a1e3f41"; 
var url = "https://uatna11.springcm.com/atlas/Forms/UpdateFormDoc.aspx?aid=7284&FormUid=" + formuid + "&SFID=" + eosInfo.SFId + "&SFTYPE=Salesforce.Account&SFPATH=" + eosInfo.FolderPath + "&ru=%2Fatlas%2Fbpm%2FWorkList.aspx"; 

window.open(url); 

});
AJAX Error

Need to desperately get this working, Can you help with pointing me to the right code?

It appears, best I can tell, to be a problem with the function sforce.connection.remoteFunction( ), but I do not really understand what is happening.

Thank you in advance.

Robert
 
I have a Lightning Component that has a button that I would like to click and have it open an external URL with values from the fields from the current Opportunity Record.

I can not figure out how to get the recordId from component to Apex Controller and then the fields back to the Javascript Helper to form the URL.

Javascript Component
<aura:component implements="force:lightningQuickAction,force:appHostable,flexipage:availableForAllPageTypes,force:hasRecordId" access="global" 
                controller="CAFController">
    
    <aura:attribute name="recordId" type="Id" />
    
    <div id="aura-page">
        <div class="container">
			<ui:button class="btn" label="CAF Form" press="{!c.navigate}"/> 
        </div>
    </div>
</aura:component>
Javascript Controller
({
	navigate : function(component, event, helper) {
		helper.navigate(component);
	}
})
Javascript Helper
({
	navigate : function(component) {
        var action = component.get("c.getOpportunity");
        action.setParams({opportunityId: component.get("v.recordId")});
        var urlEvent=$A.get("e.force:navigateToURL");
        var partOneURL = 'https://XXX21.springcm.com/atlas/Forms/UpdateFormDoc.aspx?aid=9124&FormUid=8beXXXXX-d9b0-e611-bb8d-6c3be5XXXXXXX';
        urlEvent.setParams({"url": partOneURL})
        urlEvent.fire();
	}
})
Apex Controller
public class CAFController {

    @AuraEnabled
    public static Opportunity getOpportunity(ID opportunityId){
        if(opportunityId == null) {
            return null;
        }
        List<Opportunity> opps = [SELECT id, 
                                         Opportunity.FTEs__c,
                                         Opportunity.Account.Industry ,
                                         Opportunity.TotalNumberofSeats__c ,
                                         Opportunity.CAPEX_Required__c ,
                                         Opportunity.Amount ,
                                         Opportunity.Annualized_Revenue__c,
                                         Opportunity.ProgramStartDate__c ,
                                         Opportunity.Name
                                  FROM Opportunity
                                  WHERE Id =: opportunityId];
        if(opps.size()>0){
            return opps[0];
        }
        return null;
    }
}

I would appreciate any assistance. Thank you in advance. 

Robert


 
I have a Javascript button in Lightning that needs to go out to SpringCM and pulls a form up that our users complete, it uses fields from the Opportunity that it pass through the URL. I am desperately trying to figure out how to do this and have tried the Trailhead Module: Lightning Alternatives to JavaScript Buttons and either it does not explain for my example or I am unable to understand. Can someone point me to any other solutions?

The Button is below:
{!REQUIRESCRIPT("/soap/ajax/10.0/connection.js")} 
{!REQUIRESCRIPT("/soap/ajax/10.0/apex.js")} 

//Should not have to change this at all 
function getEOSInfo(objectid,objecttype,callback) { 

var baseUrl = "{!$Api.Partner_Server_URL_260}".substring(0, "{!$Api.Partner_Server_URL_260}".indexOf("/services")); 
var url = baseUrl +"/services/apexrest/SpringCMEos/eosinfo?objecttype="+objecttype+"&objectid="+objectid; 
var authkey = "Bearer {!$Api.Session_ID}"; 

sforce.connection.remoteFunction({ 
url : url, 
requestHeaders: {"Authorization":authkey,"Accept":"application/json"}, 
onSuccess : function(response) { 
var eosInfoResponse = JSON.parse(response); 
callback(eosInfoResponse); 
} 
}); 
} 


//Here you write your own code, this is a simple call 
var objectid = "{!Opportunity.Id}"; 
var objecttype = "Opportunity"; 

getEOSInfo(objectid,objecttype,function(eosInfo){ 


var formuid = "8be07531-XXXX-e611-XXXX-6c3be5a7XXXX"; 
var url = "https://XXX21.springcm.com/atlas/Forms/UpdateFormDoc.aspx?aid=9723&FormUid=" + formuid + "&SFFTE={!Opportunity.FTEs__c}&SFIND={!Account.Industry}&SFPSD={!Opportunity.ProgramStartDate__c}&SFID=" + eosInfo.SFId + "&SFNAME={!Opportunity.Name}&SFWF=ABC&SFCAFTYPE=CAAF&SFTYPE=Salesforce.Opportunity&SFPATH=" + eosInfo.FolderPath + "&ru=%2Fatlas%2Fbpm%2FWorkList.aspx"; 

window.open(url); 

});

Your help is greatly appreciated.
The requirement that I have been given is to display a Popup Window when user presses the New button to create an Opportunity. Then depending on the answer redirect to a different page.

I tried to do create a "new" New Opportunity button but can not replace on the Home Opportunity List View. What is the best approach for this?

We are using Salesforce Classic.

Thanks in advance,

Robert
I have a trigger on the Opportunity that creates records on a custom object called the Opportunity_Revenue__c. It takes the revenue from the Opportunity and spreads it out over the quarters during the length of the deal. It works fine for insert triggers, I need to have the ability to let users re-create based on a changing contract length / deal length. 

So when the record is updated I want to delete all the records in the custom object Opportunity_Revenue__c that are related to the Opportunity and then run the insert code to create the new records for the Opportunity_Revenue__c object. But it is doubling the records because once it deletes the old records it see trigger as an update and an insert.

Can you help or suggest what I might do?

Here is the code:
 
public class OpportunityRevenueTrigger2 {

    
    public static void updateOpportuntityRev(List<Opportunity> trig){
         List<ID> opprtnyId = new List<ID>();
         Decimal totRev;
         Decimal totAllottedRev;
         Decimal mRev;
         
         for(Opportunity opp4: trig){
            if(Opp4.Auto_Generate_Quarterly_Forecast__c == 'Yes'){
                opprtnyId.add(opp4.id);
            }
         List<Opportunity_Revenue__c> deleteOR = [SELECT id
                                                 FROM Opportunity_Revenue__c 
                                                 WHERE Opportunity__c in: opprtnyID];
         
        if(deleteOR.size() != 0){
           Delete deleteOR;
         }
        
        List<Opportunity_Revenue__c> oppr = new List<Opportunity_Revenue__c>();
        for(Opportunity opp : trig){
             
             if(opp.amount > 0 && opp.contract_length_Months__c > 0 
               && opp.Auto_Generate_Quarterly_Forecast__c == 'Yes' ){
                   Date sDate = opp.CloseDate;
                   Integer period = opp.Contract_Length_Months__c.intValue();
                   Integer period2 = period / 3;
                   totRev = opp.Amount;
                   mRev = totRev.divide(period2, 2);
                   for(Integer i = 1; i <= period2; i++) {
                   Opportunity_Revenue__c oppr2 = new Opportunity_Revenue__c();
                   oppr2.Account__c = opp.AccountId;
                   oppr2.Opportunity__c = opp.id;
                   System.debug('i '+ i);
                   oppr2.ProjectedRevenue__c = mRev;
                   oppr2.Month__c = sDate;
                       if(sDate.Month()== 1 || sDate.month()==2 || sDate.month() ==3){
                           oppr2.Quarter__c =  'Quarter 1, '+string.valueOf(sDate.Year());   
                       } else if (sDate.Month()== 4 || sDate.month()== 5 || sDate.month() == 6){
                           oppr2.Quarter__c =  'Quarter 2, '+string.valueOf(sDate.Year());
                       } else if (sDate.Month()== 7 || sDate.month()== 8 || sDate.month() == 9){
                           oppr2.Quarter__c =  'Quarter 3, '+string.valueOf(sDate.Year());
                       } else if (sDate.Month()== 10 || sDate.month()==11 || sDate.month() ==12){
                           oppr2.Quarter__c =  'Quarter 4, '+string.valueOf(sDate.Year());
                       }
                   
                   oppr.add(oppr2);
                   sDate = sDate.addMonths(3);
                   }
                  
        
              }
        }
        insert oppr;

    }
}
}
 
trigger OpportunityRevenueTrigger on Opportunity (after insert, after update) {
  
        
        OpportunityRevenueTrigger2.updateOpportuntityRev(trigger.new);
        
 
  }

 
I have a trigger that works when creating and Opportunity that creates a record for each quarter and divides up the revenue. What I would like to do is to flip the flag that indicates to run auto calculate / generate trigger back to no after the records are updated in a new Custom Object called Opportunity_Revenue__c, but I get a recursion error.

How can I get the field named: auto_generate_quarterly_forecast__c back to a no value after I run the insert trigger?

Trigger Code:
trigger OpportunityRevenueTrigger on Opportunity (after insert, after update) {
    if(trigger.isInsert && trigger.isAfter){
        OpportunityRevenueTriggerInsertHandler.OppQuarterlyRevInsert(trigger.new);
        
    }//END is.Insert
    if(trigger.isUpdate && trigger.isAfter){
        OpportunityRevenueTriggerInsertHandler.OppQuarterlyRevDelete(trigger.new);
        OpportunityRevenueTriggerInsertHandler.OppQuarterlyRevInsert(trigger.new); 
    }//END isUpdate
    
}
Trigger Handler Class :
public class OpportunityRevenueTriggerInsertHandler {

    public static void OppQuarterlyRevInsert(List<Opportunity> trig){
        Date eDate; //this is the date that the projection should run through
        Date sDate; //this is the date that the projection should start
        Integer period; // Opp Contract_Length_Months__c is a decimal need to convert
        Decimal dRev; // Revenue per Day
        Decimal mRev; // Revenue per Month
        Decimal qRev; //Revenue per Quarter
        Integer dayDiff;
        Integer dayDiff2;
        List<Opportunity_Revenue__c> oppr = new List<Opportunity_Revenue__c>();
        for(Opportunity opp : trig){
            
            //Month Count Must be greater than 2
            if(opp.amount > 0 && opp.contract_length_Months__c > 0 
               && opp.Auto_Generate_Quarterly_Forecast__c == 'Yes'){
                             
                sDate = opp.CloseDate;
                period = opp.contract_length_months__c.intValue();
                eDate = opp.CloseDate.addMonths(period);
                dayDiff = sDate.daysBetween(eDate);
                System.debug('dayDiff '+dayDiff);
                dRev = opp.Amount /dayDiff;
                System.debug('dRev '+ dRev);
                mRev = opp.Amount / period;
                System.debug('mRev ' +mRev);
                qRev = mRev * 3;
                while (sDate < eDate){
                    Opportunity_Revenue__c oppr2 = new Opportunity_Revenue__c();
                    oppr2.Account__c = opp.AccountId;
                    oppr2.Opportunity__c = opp.id;
                    oppr2.Opportunity_Projected_Revenue__c = opp.Amount;
                    oppr2.Month__c = sDate;
                    if(opp.Contract_Length_Months__c > 2) {
                        if(sDate.Month()== 1 || sDate.month()==2 || sDate.month() ==3) {
                            dayDiff2 = sDate.daysBetween(eDate);
                            System.debug('dayDiff2 '+ dayDiff2);
                            if(sDate.daysBetween(eDate) < 90 ) {
                                dayDiff2 = sDate.daysBetween(eDate);
                                System.debug('dayDiff2 '+ dayDiff2);
                                oppr2.Quarter__c = 'Quarter 1, '+string.valueOf(sDate.Year());
                                oppr2.ProjectedRevenue__c = dRev * sDate.daysBetween(eDate);    
                            } else { //END if(sDate.daysBetween(eDate) <90)
                                dayDiff2 = sDate.daysBetween(eDate);
                                System.debug('dayDiff2 '+ dayDiff2);
                                oppr2.Quarter__c = 'Quarter 1, '+string.valueOf(sDate.Year());
                                oppr2.ProjectedRevenue__c = qRev;}
                        }//END if (sDate.month()==Q1)
                        if(sDate.Month()== 4 || sDate.month()==5 || sDate.month() ==6) {
                            dayDiff2 = sDate.daysBetween(eDate);
                            System.debug('dayDiff2 '+ dayDiff2);
                            if(sDate.daysBetween(eDate) < 90 ) {
                                dayDiff2 = sDate.daysBetween(eDate);
                                System.debug('dayDiff2 '+ dayDiff2);
                                oppr2.Quarter__c = 'Quarter 2, '+string.valueOf(sDate.Year());
                                oppr2.ProjectedRevenue__c = dRev * sDate.daysBetween(eDate);    
                            } else { //END if(sDate.daysBetween(eDate) <90)
                                dayDiff2 = sDate.daysBetween(eDate);
                                System.debug('dayDiff2 '+ dayDiff2);
                                oppr2.Quarter__c = 'Quarter 2, '+string.valueOf(sDate.Year());
                                oppr2.ProjectedRevenue__c = qRev;}
                        }//END if (sDate.month()==Q2)
                        if(sDate.Month()== 7 || sDate.month()==8 || sDate.month() ==9) {
                            dayDiff2 = sDate.daysBetween(eDate);
                            System.debug('dayDiff2 '+ dayDiff2);
                            if(sDate.daysBetween(eDate) < 90 ) {
                                dayDiff2 = sDate.daysBetween(eDate);
                                System.debug('dayDiff2 '+ dayDiff2);
                                oppr2.Quarter__c = 'Quarter 3, '+string.valueOf(sDate.Year());
                                oppr2.ProjectedRevenue__c = dRev * sDate.daysBetween(eDate);    
                            } else { //END if(sDate.daysBetween(eDate) <90)
                                dayDiff2 = sDate.daysBetween(eDate);
                                System.debug('dayDiff2 '+ dayDiff2);
                                oppr2.Quarter__c = 'Quarter 3, '+string.valueOf(sDate.Year());
                                oppr2.ProjectedRevenue__c = qRev;}
                        }//END if (sDate.month()==Q3)
                        if(sDate.Month()== 10 || sDate.month()==11 || sDate.month() ==12) {
                            dayDiff2 = sDate.daysBetween(eDate);
                            System.debug('dayDiff2 '+ dayDiff2);
                            if(sDate.daysBetween(eDate) < 90 ) {
                                dayDiff2 = sDate.daysBetween(eDate);
                                System.debug('dayDiff2 '+ dayDiff2);
                                oppr2.Quarter__c = 'Quarter 4, '+string.valueOf(sDate.Year());
                                oppr2.ProjectedRevenue__c = dRev * sDate.daysBetween(eDate);    
                            } else { //END if(sDate.daysBetween(eDate) <90)
                                dayDiff2 = sDate.daysBetween(eDate);
                                System.debug('dayDiff2 '+ dayDiff2);
                                oppr2.Quarter__c = 'Quarter 4, '+string.valueOf(sDate.Year());
                                oppr2.ProjectedRevenue__c = qRev;}
                        }//END if (sDate.month()==Q4)
                    }//END if(opp.Contract_Length_Months__c > 2)
                    //if the Contract Length is less than a quarter
                    if (opp.contract_length_months__c < 3){
                        if(sDate.Month()== 1 || sDate.month()==2 || sDate.month() ==3) {
                            oppr2.Quarter__c = 'Quarter 1, '+string.valueOf(sDate.Year());
                            oppr2.ProjectedRevenue__c = opp.Amount;
                        }//END if (sDate.month()==Q1)
                        if(sDate.Month()== 4 || sDate.month()==5 || sDate.month() ==6) {
                            oppr2.Quarter__c = 'Quarter 2, '+string.valueOf(sDate.Year());
                            oppr2.ProjectedRevenue__c = opp.Amount;
                        }//END if (sDate.month()==Q2)
                        if(sDate.Month()== 7 || sDate.month()==8 || sDate.month() ==9) {
                            oppr2.Quarter__c = 'Quarter 3, '+string.valueOf(sDate.Year());
                            oppr2.ProjectedRevenue__c = opp.Amount;
                        }//END if (sDate.month()==Q3)
                        if(sDate.Month()== 10 || sDate.month()==11 || sDate.month() ==12) {
                            oppr2.Quarter__c = 'Quarter 4, '+string.valueOf(sDate.Year());
                            oppr2.ProjectedRevenue__c = opp.Amount;
                        }//END if (sDate.month()==Q4)
                    }//END if (opp.contract_length_months__c < 3)   
                    sDate = sDate.addMonths(3);  //increment month / Quarter 
                    oppr.add(oppr2);
                }//END while (sDate < eDate)
            }//END if(opp.amount > 0 && opp.contract_length_Months__c > 0) 
        }//END for(Opportunity opp : trig)
        insert oppr;      
    }//END OppQuarterlyRevInsert

    public static void OppQuarterlyRevDelete(List<Opportunity> trig) {
        
        List<ID> opprtnyId = new List<ID>();
        //Loop through and get all the ids
        for(Opportunity opp: trig){
            //Only put them in the List if you want them to be deleted
            if(Opp.Auto_Generate_Quarterly_Forecast__c == 'Yes'){
                opprtnyId.add(opp.id);
            }//END if
        }//END for(Opportunity opp: trig)
        //Get the Opportunity_Revenue__c records in the table to delete 
        List<Opportunity_Revenue__c> deleteOR = [SELECT id
                                                 FROM Opportunity_Revenue__c 
                                                 WHERE Opportunity__c in: opprtnyID];
        //if there are any records then delete them
        if(deleteOR.size() != 0){
           Delete deleteOR;
        }//END if
    }//END OppQuarterlyRevDelete(List<Opportunity> trig)
    public static void FlipFlag(List<Opportunity> trig){
        List<Opportunity> opp4 = new List<Opportunity>();
        for(Opportunity opp3 : trig){
            opp3.Auto_Generate_Quarterly_Forecast__c ='No';
            opp4.add(opp3);
        }
        update opp4;
    }
}//END OpportunityRevenueTriggerInsertHandler
I have to believe it is something simple I am missing, but dang I can not figure it out.

Thank you in Advance

Robert

 
Thank you in advance
I am attempting to pull the Account Ids from a custom object. Once I have the Account Ids I am attempting to pull all the Contacts associated with the Accounts and update a Account_Relationship_Status__c field, but continue to receive the following error: System.NullPointerException: Attempt to de-reference a null object

I have placed System.debug statements in the code in hopes to figure it out, but that has been unsuccessful. Can someone tell me what I seem to be missing?
 
Public List<Contact> contList;

for(Red_Zone__c rzAcct: [SELECT Account__c, status__c, Escalation__c FROM Red_Zone__c WHERE status__c ='Open' and Escalation__c ='Red Zone']){
    if (rzAcct.Account__c != Null && rzAcct.status__c != Null && rzAcct.Escalation__c != Null){
            System.debug('rzAcct.id '+rzAcct.id);
            System.debug('rzAcct.Account__c '+rzAcct.Account__c);
            System.debug('rzAcct.Status__c '+rzAcct.status__c);
            System.debug('rzAcct.Escalation__c '+rzAcct.Escalation__c);
        for (Contact con: [SELECT account_relationship_status__c, AccountId FROM Contact WHERE AccountId =:rzAcct.Account__c]){
            System.debug('con.id '+con.id);
            System.debug('con.account_relationship_status__c '+con.account_relationship_status__c);
            System.debug('con.AccountID '+con.AccountId);
            
               con.account_relationship_status__c ='Red Zone';
               contList.add(con);
        }
   }
System.debug('contList '+ contList);
Update contList;    
}

Log results of the Debug Statements:
Debug Log
Thank you in advance.
I am attempting to use a SOQL query to query a Grandparent Object (Account), Parent Object (Opportunity), Child Custom Object (EBR_Form__c) but continue to get the following error in the Developer Console's Query Editor: 
 
SELECT id, Name, Opportunity__r.Name, Opportunity__r.Account.Name FROM EBR_Form__c

SELECT id, Name, Opportunity__r.Name, Opportunity__r.Account.Name
                                 ^
ERROR at Row:1:Column:18
Didn't understand relationship 'Opportunity__r' in field path. If you are attempting to use a custom relationship, be sure to append the '__r' after the custom relationship name. Please reference your WSDL or the describe call for the appropriate names.

User-added image

What am I missing. Your help would be appreciated greatly.
 
I have a Apex Controller Extension for a Visualforce Page with a redirect to the AccountTeamMember edit page that I can not seem to get to test in the test class. I can put the url in a Command Link to avoid testing but I really want to figure out how to write a test method:

Visualforce page portion with method in it. On an VF Page with the Account as a Standard Controller and my Controller Extension:
<apex:pageBlockTable value="{!myTeam}" var="r">
                 <apex:column >
                    <apex:commandLink value="Edit" action="{!editRecord}">
                        <apex:param name="myParmEdit" value="{!r.id}" assignTo="{!RecordID}"/>
                    </apex:commandLink>
                </apex:column>
My Controller Extension:
 
public class AcctApexControllerExt {
public List<AccountTeamMember> myTeam { get; set; }
    
    public String acctID {get; set;}
    public String ATMID {get;set;}
    private ApexPages.StandardController stdCtrl {get; set;}
    public String recordID {get; set;}
    
    public AcctApexControllerExt(ApexPages.StandardController controller) {
        stdCtrl= controller;
        setupAccountTeam();
                
    }
    public void setupAccountTeam(){
        myTeam = [SELECT Id,
                         AccountId,
                         TeamMemberRole, 
                         User.Country,
                         UserId, 
                         User.Name, 
                         User.Email, 
                         User.CompanyName, 
                         User.Title, 
                         User.FullPhotoUrl, 
                         User.SmallPhotoUrl 
                  FROM AccountTeamMember 
                  WHERE AccountId =: stdCtrl.getId() LIMIT 200];

    }    
    public PageReference addRedirect(){
        acctID = ApexPages.currentPage().getParameters().get('id');
        PageReference redir = new PageReference('/opp/salesteaminsert.jsp?retURL=%2F'+ acctID + '&id=' +acctID);
        redir.setRedirect(true);
        return redir;
    }
   public PageReference deleteRecord(){
       AccountTeamMember atm1 = new AccountTeamMember(id=ATMId);
       delete atm1;
       setupAccountTeam();
       return null;
    }
    public PageReference editRecord(){
        acctID = ApexPages.currentPage().getParameters().get('id');
        AccountTeamMember u = new AccountTeamMember(id=recordID);
        ID recID = u.id;
        PageReference redir2 = new PageReference('/acc/salesteamedit.jsp?id='+ u.Id + '&retURL='+ acctID);
        redir2.setRedirect(true);
        return redir2;
    }

}
Apex Test Class:
@isTest
public class AcctApexControllerExt_Test {
    
     static testMethod void AcctApexControllerExt_Test1(){
        Account acct = new Account (Name     = 'Test Account',
                                    Industry = 'Retail:Other') ;
        insert acct;
        Profile prof = [select id from profile where name='system Administrator'];
        User usr = new User(alias = 'usr', email='us.name@vmail.com',
                            emailencodingkey='UTF-8', lastname='lstname',
                            timezonesidkey='America/Los_Angeles',
                            languagelocalekey='en_US',
                            localesidkey='en_US', profileid = prof.Id,
                            username='testuser128@testorg.com',MobilePhone='87564231',Phone='451234789');
        insert usr;
        
        PageReference pageRef = Page.tabbedAccount;
        pageRef.getParameters().put('id', acct.id); 
        ApexPages.StandardController stdController = new ApexPages.StandardController(acct);
        AcctApexControllerExt ext = new AcctApexControllerExt(stdController);
        test.setCurrentPage(pageRef);
        ext.addRedirect();
        ext.setupAccountTeam();
        List<AccountTeamMember> results = ext.myTeam;
        system.assertEquals(results.size(), 0);
    }
}


Can not seem to call the editRecord() or the setupAccountTeam() method for the test class.

Your help would be greatly appreciated.
 
I have at least two issues, 1) Having to press the <apex:commandLink> twice inorder to invoke deleteRecord method in Controller Extension, and 2) Method returning an error on Delete but DML statement working to Delete Record. (Error Message Received: Delete failed. First exception on row 0 with id 01Mj0000006bzD3EAI; first error: INSUFFICIENT_ACCESS_OR_READONLY, insufficient access rights on object id: [] )

The goal was to create a tab in my visualforce page that displayed the Account Team Members with a link to their Chatter profile, email address, Company Name, title and Account Team Member Role. To be able to add members, edit members and delete members from this page.

Controller Extension:
public class MyProfilePageController2 {

    public List<AccountTeamMember> myTeam { get; set; }
    public Account acct {get; set;}
    public String acctID {get; set;}
    public String ATMID {get;set;}
    
    public MyProfilePageController2(ApexPages.StandardController controller) {
        Account acct = (Account) controller.getRecord();
        
        myTeam = [SELECT Id,AccountId,TeamMemberRole, User.Country,UserId, User.Name, User.Email, User.CompanyName, User.Title, User.FullPhotoUrl, User.SmallPhotoUrl FROM AccountTeamMember where AccountId =:acct.Id];
        
    }
    public PageReference addRedirect(){
        
        acctID = ApexPages.currentPage().getParameters().get('id');
       
        PageReference redir = new PageReference('/opp/salesteaminsert.jsp?retURL=%2F'+ acctID + '&id=' +acctID);
        redir.setRedirect(true);
        return redir;
    }
   public PageReference deleteRecord(){
        
       AccountTeamMember atm1 = new AccountTeamMember(id=ATMId);
       
       delete atm1;
       
       return null;
    }

}

Visualforce Page:
<apex:page StandardController="Account" extensions="MyProfilePageController2">

  <apex:tabPanel switchType="client">
   
    <!-- first tab - overview of the account with the standard detail component -->
    <apex:tab label="Overview" name="Overview">
      <apex:detail relatedList="false" /> 
    </apex:tab>
      
    <!-- second tab - iterate the contacts related list-->
    <apex:tab label="Contacts" name="Contacts">
      <apex:repeat value="{!Account.contacts}" var="contact">
        <apex:pageBlock title="{!contact.name}">
          <apex:pageBlockSection >
            <apex:pageBlockSectionItem >
              <apex:outputLabel value="Name"/>
              <apex:outputLink value="{!URLFOR($Action.Contact.View, contact.id)}">
                <apex:outputField value="{!contact.name}" />
              </apex:outputLink>
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem />
            <apex:outputField value="{!contact.Email}" />
            <apex:outputField value="{!contact.HasOptedOutOfEmail}" />
            <apex:outputField value="{!Contact.Phone}" />
            <apex:outputField value="{!Contact.DoNotCall}" />
            <apex:outputField value="{!contact.Fax}" />
            <apex:outputField value="{!contact.HasOptedOutOfFax}" />
          </apex:pageBlockSection>
        </apex:pageBlock>
           
        <!-- include the open activities for the contact via the standard relatedList component -->
        <apex:relatedList subject="{!contact}" list="OpenActivities" />
        <br/>
      </apex:repeat>
    </apex:tab>
      
    <!-- third tab - iterate the opportunities related list -->
    <apex:tab label="Open Opportunities" name="Open Opportunities">
      <apex:repeat value="{!Account.Opportunities}" var="opp">
      
        <!-- only show open opportunities -->
        <apex:outputPanel rendered="{!NOT(opp.IsClosed)}">
          <apex:pageBlock title="{!opp.Name}">
            <apex:pageBlockSection >
              <apex:pageBlockSectionItem >
                <apex:outputLabel value="Name"/>
                <apex:outputLink value="{!URLFOR($Action.Opportunity.View, opp.id)}">
                  <apex:outputField value="{!opp.name}" />
                </apex:outputLink>
              </apex:pageBlockSectionItem>
              <apex:pageBlockSectionItem />
              <apex:outputField value="{!opp.CloseDate}" />
              <apex:outputField value="{!opp.Amount}" />
              <apex:outputField value="{!opp.StageName}" />
              <apex:outputField value="{!opp.Probability}" />
            </apex:pageBlockSection>
          </apex:pageBlock>
           
          <!-- include the line items for the opportunity via the standard relatedList component -->
          <apex:relatedList subject="{!opp}" list="OpportunityLineItems" />
        </apex:outputPanel>
      </apex:repeat>
    </apex:tab>
    

    
  <!--Fourth Panel-->

  <apex:tab label="Account Team Members" name="Account Team">
     
<apex:outputPanel >
       <apex:form >  
        <apex:pageBlock >
            <apex:pageBlockSection >
                <apex:commandButton value="Add" action="{!addRedirect}" />
                
            </apex:pageBlockSection>

            <apex:pageBlockTable value="{!myTeam}" var="r">
                <apex:column >
                    <a href="/acc/salesteamedit.jsp?id={!r.id}&retURL={!r.AccountId}">Edit</a>
                </apex:column>
                <apex:column>
                    <apex:commandLink value="Delete" action="{!deleteRecord}">
                       <apex:param name="myParam" value="{!r.id}" assignTo="{!ATMId}"/>
                    </apex:commandLink>
                </apex:column>
                <apex:column >
                    <apex:image id="profileImage" value="{!r.User.SmallPhotoUrl}" />
                </apex:column>
                <apex:column headerValue="Name">
                   <a href="/_ui/core/userprofile/UserProfilePage?u={!r.User.id}">{!r.User.Name}</a>
                </apex:column>
                <apex:column value="{!r.User.Title}"/>
                <apex:column value="{!r.TeamMemberRole}"/>
                <apex:column value="{!r.User.CompanyName}"/>
                <apex:column value="{!r.User.Email}"/>
                <apex:column value="{!r.User.Country}"/>  
            </apex:pageBlockTable>

      </apex:pageBlock>
      </apex:form>
</apex:outputPanel>
     
</apex:tab>
    </apex:tabPanel>
</apex:page>

Am I approaching this wrong?

Your Help is Appreciated.

 
Need to create a link that the user clicks to go to another user's Chatter Profile so they can send a message in Salesforce Classic.

The following is what I have so far but can not figure out how to get the link to the Chatter Profile:
 
<apex:page standardController="AccountTeamMember">
    
    <apex:form>
    
        <apex:pageBlock title="Account Team Members">
            <apex:pageBlockTable value="{!AccountTeamMember}" var="ATM">
                <apex:column headerValue="Account Member Name">
                    <apex:outputField value="{!ATM.User.Name}"/>
                </apex:column>
                <apex:column headerValue="Account Member Title">
                    <apex:outputField value="{!AccountTeamMember.User.Title}" />
                </apex:column>
                <apex:column headerValue="Company Name">
                    <apex:outputField value="{!AccountTeamMember.User.CompanyName}" />
                </apex:column>
                <apex:column headerValue="Account Member Country">
                    <apex:outputField value="{!AccountTeamMember.User.Country}" />
                </apex:column>
                <apex:column headerValue="Account Member Role">
                    <apex:outputField value="{!AccountTeamMember.TeamMemberRole}" />
                </apex:column>
                <apex:column headerValue="Account Member Email">
                    <apex:outputField value="{!AccountTeamMember.User.Email}" />
                </apex:column>
                <apex:column>
                    <apex:image id="profileImage" url="{!AccountTeamMember.User.FullPhotoUrl}" />
                  
                </apex:column>
            </apex:pageBlockTable>
            
        </apex:pageBlock>
    </apex:form>
</apex:page>

 
I am at a lost for how to write a test class for the following Apex Controller:
 
public class AccSearchController {
    public List<Account> acc {get; set;}
    public String searchString {get; set;}
    public AccSearchController(ApexPages.StandardController controller) {  
    }
    public void search(){
        String searchQuery= 'SELECT id, name, owner.name, billingStreet, billingState, billingCity, billingCountry, '+
                            'recordtype.name, industry FROM Account WHERE NAME LIKE \'%'+searchString+'%\'' +
                            'ORDER BY name Limit 200';
        acc = Database.query(searchQuery);
            }
    
    public pageReference reset(){
        this.searchString='';
        acc.clear();
        return null;
    }
    
}

Tried to following the instructions at http://www.jitendrazaa.com/blog/salesforce/apex/faq-writing-test-class-in-salesforce/#Q2

But keep getting an error of Constructor not defined: [AccSearchController].<Constructor>(ApexPages.StandardSetController)

Below is the Test Class that does not work:
 
@isTest
public class AccSearchController_Test {
   @isTest
    public static void testControllerExtension(){
    List<Account> acctList = [SELECT ID FROM Account];
       
    Test.setCurrentPage(Page.SearchAccountPage);
    ApexPages.StandardSetController stdSetController = new     ApexPages.StandardSetController(acctList);
    
    stdSetController.setSelected(acctList);
    
    AccSearchController ext = new AccSearchController(stdSetController);

    
    }

I would appreciate any direction or help. Thanks in advance.

Robert
 
I am trying to create a Visualforce Page that passes in a string to a SOQL query to create a list of Accounts that match the string, but I not able to get any results

Controller:
 
public class AccountSearch_CC {
    
    public String acctName {get; set;}

    public List<AccountWrapper> accountList {
        get {           
            if (accountList == null) {
                accountList = new List<AccountWrapper>();
                for (Account acct : [SELECT  Name, BillingAddress,  Industry, Vertical_Assignment__c FROM Account WHERE NAME =: acctName ]){
                    accountList.add(new AccountWrapper(acct));
                }
            }
            return accountList;
        }
        set;
    }
    public Map<ID, AccountWrapper> selectedAccounts {
        get {
            if (selectedAccounts ==null) {
                selectedAccounts = new Map<Id, AccountWrapper>();
            }
            return selectedAccounts;
        }
        set;
    }
    public PageReference listAccounts(){
        
        selectedAccounts.clear();
        
        for(AccountWrapper acctWpr : accountList) {
            if(acctWpr.checked) {
                selectedAccounts.put(acctWpr.acct.Id, acctWpr);
            }
        }
        if (selectedAccounts.size()>0){
            return Page.AcctSearch;
        } else {
            ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Please select at least one Account'));
            return null;
        }
        
    }
    
    public List<Account> available{
        get {
            if (available == null) {
                available = new List<Account>([SELECT Name, BillingAddress,  Industry, Vertical_Assignment__c FROM Account
                                              WHERE Id IN : selectedAccounts.keySet()]);
            }
            return available;
        }
        set;
    }
    
    public PageReference newSearch() {
        PageReference newPage = Page.SearchAccountPage;
        newPage.setRedirect(true);
        return NewPage;
    }
    
    public class AccountWrapper {
        public Account acct {get; set;}
        public Boolean checked {get; set;}
        
        public AccountWrapper(Account a){
            acct = a;
            checked = false;
        }
    }

}

Visual Search Page:
 
<apex:page controller="AccountSearch_CC" tabStyle="Account">
    <apex:form >
        <apex:pageBlock title="Account Search">
            <apex:pageMessages >
            </apex:pageMessages>
            <apex:pageBlockButtons >
                <apex:commandButton action="{!listAccounts}" value="See Available Accounts" />
            </apex:pageBlockButtons>
            <apex:pageBlockTable var="a" value="{!accountList}">
                <apex:column width="25px" headerValue="Select">
                    
                    <apex:inputCheckbox value="{!a.checked}" />
                </apex:column>
                <apex:column value="{!a.acct.Name}"/>
                
            </apex:pageBlockTable>
        </apex:pageBlock>
    </apex:form>
</apex:page>

List of Results Page:
 
<apex:page controller="AccountSearch_CC">
    <apex:form >
        <apex:pageBlock title="Search for Accounts">
            <apex:pageMessages />
            <apex:pageBlockButtons >
                <apex:commandButton action="{!newSearch}" value="New Search" />   
                <apex:inputText value="{!acctName}" id="SearchString" maxlength="25" size="30"/>
            </apex:pageBlockButtons>
                <apex:pageBlockTable var="avail" value="{!available}">
                    <apex:column value="{!avail.Name}"/>
            
                </apex:pageBlockTable>
        </apex:pageBlock>
    </apex:form>
</apex:page>

Any help would be so appreciated. Thanks. 
I have a trigger that executes on after insert and after create on the Opportunity that updates fields on the OpportunityLineItem Object. Code works but the test class opportunity does not appear to successfully add a product so the code can not go into a IF statement. I am sure this is something simple but dang if I can figure it out. Your help would be greatly appreciated:
 
TRIGGER

//Case Number 1381 - Provides information about request for Trigger
trigger UpdateOTRev on Opportunity (after insert, after update) {
    Set<id> triggerIds = new Set<id>();
    List<OpportunityLineItem> lstOLIUpdate = new List<OpportunityLineItem>();
    //See if Trigger has only been run once
    if(RecursiveTriggerHandler.isFirstTime){
        RecursiveTriggerHandler.isFirstTime = false;
         //Put all trigger opp ids into a set
         for(Opportunity Opps : Trigger.new){
            triggerIds.add(Opps.Id);
         }//END for (Opportunity Opps)
         //Get all the Opp and Products
         List<Opportunity> lstOpps = [SELECT id, CloseDate, (SELECT id, TotalPrice, One_Time_Revenue__c FROM OpportunityLineItems) FROM Opportunity 
                                      WHERE id in: triggerIds];
             //Loop through Opps
             for(Opportunity opp: lstOpps){
                 //Loop through Products in Opps
                 for(OpportunityLineItem oli : opp.OpportunityLineItems){
                     if(oli.One_Time_Revenue__c == true){
                        //Apply the logic of which fields to update
                        if(opp.CloseDate > Date.valueOf('2017-12-31') && opp.CloseDate < Date.valueOf('2018-04-01')){
                            oli.One_Time_Rev_Q1_2018__c = oli.TotalPrice;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            lstOLIUpdate.add(oli);              
                        }//END if 2018 Q1
                        if(opp.CloseDate > Date.valueOf('2018-03-31') && opp.CloseDate < Date.valueOf('2018-07-01')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = oli.TotalPrice;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            lstOLIUpdate.add(oli);              
                        }//END if 2018 Q2
                        if(opp.CloseDate > Date.valueOf('2018-06-30') && opp.CloseDate < Date.valueOf('2018-10-01')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = oli.TotalPrice;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            lstOLIUpdate.add(oli);              
                        }//END if 2018 Q3
                        if(opp.CloseDate > Date.valueOf('2018-09-30') && opp.CloseDate < Date.valueOf('2019-01-01')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = oli.TotalPrice;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            lstOLIUpdate.add(oli);              
                        }//END if 2018 Q4
                        if(opp.CloseDate > Date.valueOf('2018-12-31') && opp.CloseDate < Date.valueOf('2019-04-01')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = oli.TotalPrice;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            lstOLIUpdate.add(oli);              
                        }//END if 2018 Q1
                        if(opp.CloseDate > Date.valueOf('2019-03-31') && opp.CloseDate < Date.valueOf('2019-07-01')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = oli.TotalPrice;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            lstOLIUpdate.add(oli);              
                        }//END if 2019 Q2
                        if(opp.CloseDate > Date.valueOf('2019-06-30') && opp.CloseDate < Date.valueOf('2019-10-01')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = oli.TotalPrice;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            lstOLIUpdate.add(oli);              
                        }//END if 2019 Q3
                        if(opp.CloseDate > Date.valueOf('2019-09-30') && opp.CloseDate < Date.valueOf('2020-01-01')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = oli.TotalPrice;
                            lstOLIUpdate.add(oli);              
                        }//END if 2019 Q4
                        if(opp.CloseDate > Date.valueOf('2019-12-31')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            
                            lstOLIUpdate.add(oli);
                        }
                         
                     }//END if(oli.One_Time_Revenue__c == true)                     
                 }//END For(OpportunityLineItem)
             }//END for(Opportunity)
    //Update Products if there are any to update
    if(lstOLIUpdate.size()>0){
        update lstOLIUpdate;
    }
    }//END if(RecusiveTriggerHandler.isFirstTime)
}//END Class

TEST CLASS
@isTest
public class UpdateOTRevTest {
    
    public static testMethod void testOppOneTimeRevenue(){
        
        Product2 prod2= new Product2(Name = 'Test Product - OneTime',
                                     Product_Gross_Margin__c = 10,
                                     Delivery_Market__c = 'none' ,
                                     Delivery_Region__c = 'ABCD',
                                     Delivery_Site__c = 'none' ,
                                     Family = 'XTCD',
                                     Description = 'Test Product',
                                     IsActive = true,
                                     Project_Seat_Count__c = 'false',
                                     One_Time_Revenue__c = true);
        insert prod2;
        Id pricebookId = Test.getStandardPricebookId();
        PricebookEntry pbEntry = new PricebookEntry(Pricebook2Id = pricebookId,
                                                    product2Id = prod2.Id,
                                                    isActive = true,
                                                    UnitPrice = 1000);
        insert pbEntry;
       
        Opportunity opp = new Opportunity(Name = 'Test Account - Opportunity',
                                          StageName = '1 - Prospect',
                                          Type = 'New Logo', 
                                          CloseDate = System.Date.today(),
                                          LeadSource = 'BDD/AM/OPS Development',
                                          Referral_Channel__c = 'None',
                                          Auto_Generate_Quarterly_Forecast__c = 'Yes',
                                          Contract_Length_Months__c = 24,
                                          Pricebook2Id = pricebookId,
                                          Amount = 10000000);
        insert opp;
       
        OpportunityLineItem oli = new OpportunityLineItem(OpportunityId = opp.id,
                                                          PricebookEntryId = pbEntry.id,
                                                          Product2Id = prod2.id,
                                                          Quantity = 10, 
                                                          Unit_Price2__c = 20,
                                                          Adjusted_Gross_Margin_Percentage__c = 10,
                                                          Service_Channel__c = 'WIDGET',
                                                          Service_Type__c = 'Care',
                                                          One_Time_Revenue__c = true);
        insert oli;
        
        System.debug('Opportunity Product Total Price '+ oli.TotalPrice);
        System.debug('OpportunityLineItem Id ' +oli.Id);
        System.debug('Product 2 Id '+ oli.Product2Id);
        System.debug('Opportunity Line Item Name : '+ oli.Name);
        System.debug('One Time Revenue : '+oli.One_Time_Revenue__c);
        Date closeDate = System.today();
        opp.CloseDate = Date.newInstance(2018, 01, 25);
       
        update opp;
        System.debug('Opp Close Date : '+opp.CloseDate);
    }//END Method
}//END Class

//https://salesforce.stackexchange.com/questions/72883/how-to-create-opportunity-line-items-in-test-classes

Code coverage is 10 of 103 lines because it does not appear that the OpportunityLineItem ever gets associated with the Opportunity.
User-added image

I would greatly appreciate any help.

Thank you. ​
I have a trigger on the Opportunity that creates records on a custom object called the Opportunity_Revenue__c. It takes the revenue from the Opportunity and spreads it out over the quarters during the length of the deal. It works fine for insert triggers, I need to have the ability to let users re-create based on a changing contract length / deal length. 

So when the record is updated I want to delete all the records in the custom object Opportunity_Revenue__c that are related to the Opportunity and then run the insert code to create the new records for the Opportunity_Revenue__c object. But it is doubling the records because once it deletes the old records it see trigger as an update and an insert.

Can you help or suggest what I might do?

Here is the code:
 
public class OpportunityRevenueTrigger2 {

    
    public static void updateOpportuntityRev(List<Opportunity> trig){
         List<ID> opprtnyId = new List<ID>();
         Decimal totRev;
         Decimal totAllottedRev;
         Decimal mRev;
         
         for(Opportunity opp4: trig){
            if(Opp4.Auto_Generate_Quarterly_Forecast__c == 'Yes'){
                opprtnyId.add(opp4.id);
            }
         List<Opportunity_Revenue__c> deleteOR = [SELECT id
                                                 FROM Opportunity_Revenue__c 
                                                 WHERE Opportunity__c in: opprtnyID];
         
        if(deleteOR.size() != 0){
           Delete deleteOR;
         }
        
        List<Opportunity_Revenue__c> oppr = new List<Opportunity_Revenue__c>();
        for(Opportunity opp : trig){
             
             if(opp.amount > 0 && opp.contract_length_Months__c > 0 
               && opp.Auto_Generate_Quarterly_Forecast__c == 'Yes' ){
                   Date sDate = opp.CloseDate;
                   Integer period = opp.Contract_Length_Months__c.intValue();
                   Integer period2 = period / 3;
                   totRev = opp.Amount;
                   mRev = totRev.divide(period2, 2);
                   for(Integer i = 1; i <= period2; i++) {
                   Opportunity_Revenue__c oppr2 = new Opportunity_Revenue__c();
                   oppr2.Account__c = opp.AccountId;
                   oppr2.Opportunity__c = opp.id;
                   System.debug('i '+ i);
                   oppr2.ProjectedRevenue__c = mRev;
                   oppr2.Month__c = sDate;
                       if(sDate.Month()== 1 || sDate.month()==2 || sDate.month() ==3){
                           oppr2.Quarter__c =  'Quarter 1, '+string.valueOf(sDate.Year());   
                       } else if (sDate.Month()== 4 || sDate.month()== 5 || sDate.month() == 6){
                           oppr2.Quarter__c =  'Quarter 2, '+string.valueOf(sDate.Year());
                       } else if (sDate.Month()== 7 || sDate.month()== 8 || sDate.month() == 9){
                           oppr2.Quarter__c =  'Quarter 3, '+string.valueOf(sDate.Year());
                       } else if (sDate.Month()== 10 || sDate.month()==11 || sDate.month() ==12){
                           oppr2.Quarter__c =  'Quarter 4, '+string.valueOf(sDate.Year());
                       }
                   
                   oppr.add(oppr2);
                   sDate = sDate.addMonths(3);
                   }
                  
        
              }
        }
        insert oppr;

    }
}
}
 
trigger OpportunityRevenueTrigger on Opportunity (after insert, after update) {
  
        
        OpportunityRevenueTrigger2.updateOpportuntityRev(trigger.new);
        
 
  }

 
I am attempting to use a SOQL query to query a Grandparent Object (Account), Parent Object (Opportunity), Child Custom Object (EBR_Form__c) but continue to get the following error in the Developer Console's Query Editor: 
 
SELECT id, Name, Opportunity__r.Name, Opportunity__r.Account.Name FROM EBR_Form__c

SELECT id, Name, Opportunity__r.Name, Opportunity__r.Account.Name
                                 ^
ERROR at Row:1:Column:18
Didn't understand relationship 'Opportunity__r' in field path. If you are attempting to use a custom relationship, be sure to append the '__r' after the custom relationship name. Please reference your WSDL or the describe call for the appropriate names.

User-added image

What am I missing. Your help would be appreciated greatly.
 
I have a trigger that executes on after insert and after create on the Opportunity that updates fields on the OpportunityLineItem Object. Code works but the test class opportunity does not appear to successfully add a product so the code can not go into a IF statement. I am sure this is something simple but dang if I can figure it out. Your help would be greatly appreciated:
 
TRIGGER

//Case Number 1381 - Provides information about request for Trigger
trigger UpdateOTRev on Opportunity (after insert, after update) {
    Set<id> triggerIds = new Set<id>();
    List<OpportunityLineItem> lstOLIUpdate = new List<OpportunityLineItem>();
    //See if Trigger has only been run once
    if(RecursiveTriggerHandler.isFirstTime){
        RecursiveTriggerHandler.isFirstTime = false;
         //Put all trigger opp ids into a set
         for(Opportunity Opps : Trigger.new){
            triggerIds.add(Opps.Id);
         }//END for (Opportunity Opps)
         //Get all the Opp and Products
         List<Opportunity> lstOpps = [SELECT id, CloseDate, (SELECT id, TotalPrice, One_Time_Revenue__c FROM OpportunityLineItems) FROM Opportunity 
                                      WHERE id in: triggerIds];
             //Loop through Opps
             for(Opportunity opp: lstOpps){
                 //Loop through Products in Opps
                 for(OpportunityLineItem oli : opp.OpportunityLineItems){
                     if(oli.One_Time_Revenue__c == true){
                        //Apply the logic of which fields to update
                        if(opp.CloseDate > Date.valueOf('2017-12-31') && opp.CloseDate < Date.valueOf('2018-04-01')){
                            oli.One_Time_Rev_Q1_2018__c = oli.TotalPrice;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            lstOLIUpdate.add(oli);              
                        }//END if 2018 Q1
                        if(opp.CloseDate > Date.valueOf('2018-03-31') && opp.CloseDate < Date.valueOf('2018-07-01')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = oli.TotalPrice;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            lstOLIUpdate.add(oli);              
                        }//END if 2018 Q2
                        if(opp.CloseDate > Date.valueOf('2018-06-30') && opp.CloseDate < Date.valueOf('2018-10-01')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = oli.TotalPrice;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            lstOLIUpdate.add(oli);              
                        }//END if 2018 Q3
                        if(opp.CloseDate > Date.valueOf('2018-09-30') && opp.CloseDate < Date.valueOf('2019-01-01')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = oli.TotalPrice;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            lstOLIUpdate.add(oli);              
                        }//END if 2018 Q4
                        if(opp.CloseDate > Date.valueOf('2018-12-31') && opp.CloseDate < Date.valueOf('2019-04-01')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = oli.TotalPrice;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            lstOLIUpdate.add(oli);              
                        }//END if 2018 Q1
                        if(opp.CloseDate > Date.valueOf('2019-03-31') && opp.CloseDate < Date.valueOf('2019-07-01')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = oli.TotalPrice;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            lstOLIUpdate.add(oli);              
                        }//END if 2019 Q2
                        if(opp.CloseDate > Date.valueOf('2019-06-30') && opp.CloseDate < Date.valueOf('2019-10-01')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = oli.TotalPrice;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            lstOLIUpdate.add(oli);              
                        }//END if 2019 Q3
                        if(opp.CloseDate > Date.valueOf('2019-09-30') && opp.CloseDate < Date.valueOf('2020-01-01')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = oli.TotalPrice;
                            lstOLIUpdate.add(oli);              
                        }//END if 2019 Q4
                        if(opp.CloseDate > Date.valueOf('2019-12-31')){
                            oli.One_Time_Rev_Q1_2018__c = 0;
                            oli.One_Time_Rev_Q2_2018__c = 0;
                            oli.One_Time_Rev_Q3_2018__c = 0;
                            oli.One_Time_Rev_Q4_2018__c = 0;
                            oli.One_Time_Rev_Q1_2019__c = 0;
                            oli.One_Time_Rev_Q2_2019__c = 0;
                            oli.One_Time_Rev_Q3_2019__c = 0;
                            oli.One_Time_Rev_Q4_2019__c = 0;
                            
                            lstOLIUpdate.add(oli);
                        }
                         
                     }//END if(oli.One_Time_Revenue__c == true)                     
                 }//END For(OpportunityLineItem)
             }//END for(Opportunity)
    //Update Products if there are any to update
    if(lstOLIUpdate.size()>0){
        update lstOLIUpdate;
    }
    }//END if(RecusiveTriggerHandler.isFirstTime)
}//END Class

TEST CLASS
@isTest
public class UpdateOTRevTest {
    
    public static testMethod void testOppOneTimeRevenue(){
        
        Product2 prod2= new Product2(Name = 'Test Product - OneTime',
                                     Product_Gross_Margin__c = 10,
                                     Delivery_Market__c = 'none' ,
                                     Delivery_Region__c = 'ABCD',
                                     Delivery_Site__c = 'none' ,
                                     Family = 'XTCD',
                                     Description = 'Test Product',
                                     IsActive = true,
                                     Project_Seat_Count__c = 'false',
                                     One_Time_Revenue__c = true);
        insert prod2;
        Id pricebookId = Test.getStandardPricebookId();
        PricebookEntry pbEntry = new PricebookEntry(Pricebook2Id = pricebookId,
                                                    product2Id = prod2.Id,
                                                    isActive = true,
                                                    UnitPrice = 1000);
        insert pbEntry;
       
        Opportunity opp = new Opportunity(Name = 'Test Account - Opportunity',
                                          StageName = '1 - Prospect',
                                          Type = 'New Logo', 
                                          CloseDate = System.Date.today(),
                                          LeadSource = 'BDD/AM/OPS Development',
                                          Referral_Channel__c = 'None',
                                          Auto_Generate_Quarterly_Forecast__c = 'Yes',
                                          Contract_Length_Months__c = 24,
                                          Pricebook2Id = pricebookId,
                                          Amount = 10000000);
        insert opp;
       
        OpportunityLineItem oli = new OpportunityLineItem(OpportunityId = opp.id,
                                                          PricebookEntryId = pbEntry.id,
                                                          Product2Id = prod2.id,
                                                          Quantity = 10, 
                                                          Unit_Price2__c = 20,
                                                          Adjusted_Gross_Margin_Percentage__c = 10,
                                                          Service_Channel__c = 'WIDGET',
                                                          Service_Type__c = 'Care',
                                                          One_Time_Revenue__c = true);
        insert oli;
        
        System.debug('Opportunity Product Total Price '+ oli.TotalPrice);
        System.debug('OpportunityLineItem Id ' +oli.Id);
        System.debug('Product 2 Id '+ oli.Product2Id);
        System.debug('Opportunity Line Item Name : '+ oli.Name);
        System.debug('One Time Revenue : '+oli.One_Time_Revenue__c);
        Date closeDate = System.today();
        opp.CloseDate = Date.newInstance(2018, 01, 25);
       
        update opp;
        System.debug('Opp Close Date : '+opp.CloseDate);
    }//END Method
}//END Class

//https://salesforce.stackexchange.com/questions/72883/how-to-create-opportunity-line-items-in-test-classes

Code coverage is 10 of 103 lines because it does not appear that the OpportunityLineItem ever gets associated with the Opportunity.
User-added image

I would greatly appreciate any help.

Thank you. ​
I have a Trigger on the Opportunity which will update a field on the OpportunityLineItem, which updates the Opportunity which the fires the trigger to update the OpportunityLineItems. I think it is a classic recursion issue my problem is I do not know how to stop it. Please help:
 
trigger UpdateOTRev on Opportunity (after insert, after update) {
    Set<id> triggerIds = new Set<id>();
    List<OpportunityLineItem> lstOLIUpdate = new List<OpportunityLineItem>();
    for(Opportunity Opps : Trigger.new){
        triggerIds.add(Opps.Id);
    }
    List<Opportunity> lstOpps = [SELECT id, CloseDate, (SELECT id, TotalPrice FROM OpportunityLineItems) FROM Opportunity 
                                 WHERE id in: triggerIds];
    for(Opportunity opp: lstOpps){
        for(OpportunityLineItem oli : opp.OpportunityLineItems){
            
            if(opp.CloseDate > Date.valueOf('2017-12-31') && opp.CloseDate < Date.valueOf('2018-04-01')){
                oli.Test_Q1_2018__c = oli.TotalPrice;
                oli.Test_Q2_2018__c = 0;
                oli.Test_Q3_2018__c = 0;
                oli.Test_Q4_2018__c = 0;
                oli.Test_Q1_2019__c = 0;
                oli.Test_Q2_2019__c = 0;
                oli.Test_Q3_2019__c = 0;
                oli.Test_Q4_2019__c = 0;
                lstOLIUpdate.add(oli);              
            }//END if 2018 Q1
            if(opp.CloseDate > Date.valueOf('2018-03-31') && opp.CloseDate < Date.valueOf('2018-07-01')){
                oli.Test_Q1_2018__c = 0;
                oli.Test_Q2_2018__c = oli.TotalPrice;
                oli.Test_Q3_2018__c = 0;
                oli.Test_Q4_2018__c = 0;
                oli.Test_Q1_2019__c = 0;
                oli.Test_Q2_2019__c = 0;
                oli.Test_Q3_2019__c = 0;
                oli.Test_Q4_2019__c = 0;
                lstOLIUpdate.add(oli);              
            }//END if 2018 Q2
            if(opp.CloseDate > Date.valueOf('2018-06-30') && opp.CloseDate < Date.valueOf('2018-10-01')){
                oli.Test_Q1_2018__c = 0;
                oli.Test_Q2_2018__c = 0;
                oli.Test_Q3_2018__c = oli.TotalPrice;
                oli.Test_Q4_2018__c = 0;
                oli.Test_Q1_2019__c = 0;
                oli.Test_Q2_2019__c = 0;
                oli.Test_Q3_2019__c = 0;
                oli.Test_Q4_2019__c = 0;
                lstOLIUpdate.add(oli);              
            }//END if 2018 Q3
            if(opp.CloseDate > Date.valueOf('2018-09-30') && opp.CloseDate < Date.valueOf('2019-01-01')){
                oli.Test_Q1_2018__c = 0;
                oli.Test_Q2_2018__c = 0;
                oli.Test_Q3_2018__c = oli.TotalPrice;
                oli.Test_Q4_2018__c = 0;
                oli.Test_Q1_2019__c = 0;
                oli.Test_Q2_2019__c = 0;
                oli.Test_Q3_2019__c = 0;
                oli.Test_Q4_2019__c = 0;
                lstOLIUpdate.add(oli);              
            }//END if 2018 Q4
        }//END For(OpportunityLineItem)
    }//END for(Opportunity)
    if(lstOLIUpdate.size()){
        update lstOLIUpdate;
    }

}

Thank you,

Robert​
On the OpportunityLineItem I have two triggers: One that updates the Unit Price and another that applies a Discount before the record is Saved and another that Updates a field on the Opportunity. Both work fine separately but when put together the insert after creates a problem where I get the following error message:

OpportunityLineItemTrigger: execution of AfterInsert caused by: System.FinalException: Record is read-only Trigger.OpportunityLineItemTrigger: line 12, column 1
 
trigger OpportunityLineItemTrigger on OpportunityLineItem (before insert, before update, after update, after insert) {
    List<Opportunity> opps = new List<Opportunity>();
    List<Id> oppIds = new List<Id>();
    Decimal contractLengthMonths = 0;

//---------------BEFORE TRIGGER BELOW----------
    if(trigger.isInsert || trigger.isUpdate && trigger.isBefore) {
        List<OpportunityLineItem> oli = new List<OpportunityLineItem>();
        for (OpportunityLineItem oli2: trigger.new){
            if(oli2.Number_of_Months__c > 0){
                oli2.UnitPrice = ((oli2.Number_of_Months__c / 12) * oli2.Unit_Price2__c);
            } else if (oli2.Number_of_Months__c == null || oli2.Number_of_Months__c == 0 ) {
                oli2.UnitPrice = oli2.Unit_Price2__c;
            }
            if(oli2.Adjusted_Gross_Margin_Percentage__c == 0 && oli2.Product_Gross_Margin_Percent2__c != 0 ) {
                if (oli2.Number_of_Months__c > 0) {
                    oli2.Gross_Margin_Dollars__c = (oli2.Unit_Price2__c * oli2.Quantity * (oli2.Number_of_Months__c / 12)) * (oli2.Product_Gross_Margin_Percent2__c/100);
                } else {
                    oli2.Gross_Margin_Dollars__c = (oli2.Unit_Price2__c * oli2.Quantity) * (oli2.Product_Gross_Margin_Percent2__c/100);
                }
             } else if (oli2.Adjusted_Gross_Margin_Percentage__c > 0) {
                if (oli2.Number_of_Months__c > 0) {
                    oli2.Gross_Margin_Dollars__c = (oli2.Unit_Price2__c * oli2.Quantity * (oli2.Number_of_Months__c / 12)) * (oli2.Adjusted_Gross_Margin_Percentage__c/100);
                } else {
                    oli2.Gross_Margin_Dollars__c = (oli2.Unit_Price2__c * oli2.Quantity) * (oli2.Adjusted_Gross_Margin_Percentage__c/100);
                }
            }//END if(oli2.Adjusted_Gross_Margin_Percentage__c == 0 || oli2.Adjusted_Gross_Margin_Percentage__c == null) 
            
        }//END for (OpportunityLineItem oli2: trigger.new)
    }//if(trigger.isInsert || trigger.isUpdate && trigger.isBefore) 

//---------AFTER TRIGGER BELOW--------------

    if(trigger.isAfter) {
        for (OpportunityLineItem oli3: trigger.new){
            oppids.add(oli3.opportunityId);
            
        }//END for (OpportunityLineItem oli3: trigger.new)
        List<OpportunityLineItem> allOLI = [SELECT id, Number_of_Months__c FROM OpportunityLineItem WHERE OpportunityId in: oppids];
        List<Opportunity> oppsToUpdate = [SELECT id, Contract_Length_Months__c FROM Opportunity WHERE id in: oppids];
        if(allOLI.size() > 0){
            for(OpportunityLineItem allOLI2: allOLI){
                if(allOLI2.Number_of_Months__c > contractLengthMonths){
                    contractLengthMonths = allOLI2.Number_of_Months__c;
                } else if (allOLI2.Number_of_Months__c == null) {
                    contractLengthMonths = 12;
                }
            } //END for(OpportunityLineItem allOLI2: allOLI)
            for(Opportunity oppUpdate: oppsToUpdate){
                oppUpdate.Contract_Length_Months__c = contractLengthMonths;
                opps.add(oppUpdate);
            }// END for(Opportunity oppUpdate: oppsToUpdate)
 
        }//END if(allOLI.size() > 0
        update opps;
    }//if(trigger.isAfter)
}//END OpportunityLineItem Class

Your help would be greatly appreciated.

Robert​
I have gotten myself turned around on this trigger and can not figure out how to get it right. I have a custom field on the OpportunityLineItem / Opportunity Product that has the Length of Months that the product will be used for called Number_of_Months__c. I need to update the Opportunity in a field called Contract_Length_Months__c with the maximum date of all the products when a customer enters it.

I would appreciate any help in pointing me in the right direction:
 
trigger OpportunityLineItemTrigger on OpportunityLineItem ( after update) {
    List<Id> oppIds = new List<Id>();
    Decimal contractLengthMonths = 0;

    if(trigger.isAfter) {
        for (OpportunityLineItem oli3: trigger.new){
            oppids.add(oli3.opportunityId);
        }//END for (OpportunityLineItem oli3: trigger.new)
        List<OpportunityLineItem> allOLI = [SELECT id, Number_of_Months__c FROM OpportunityLineItem WHERE OpportunityId in: oppids];
        List<Opportunity> oppsToUpdate = [SELECT id, Contract_Length_Months__c FROM Opportunity WHERE id in: oppids];
        if(allOLI.size() > 0){
            for(OpportunityLineItem allOLI2: allOLI){
                if(allOLI2.Number_of_Months__c > contractLengthMonths){
                    contractLengthMonths = allOLI2.Number_of_Months__c;
                }//END if(allOLI2.Number_of_Months__c > contractLengthMonths)
            } //END for(OpportunityLineItem allOLI2: allOLI)
            for(Opportunity oppUpdate: oppsToUpdate){
                oppUpdate.Contract_Length_Months__c = contractLenghtMonths;
            }// END for(Opportunity oppUpdate: oppsToUpdate)
 
        }
    }//if(trigger.isAfter)
}//END OpportunityLineItem Class

At the line:
oppUpdate.Contract_Length_Months__c = contractLenghtMonths;

I get the following error from the Developer Console IDE : "Variable does not exist: contractLenghtMonths"

Thank you in advance for any help.

Robert
I have the following code that creates a URL to go to another system. I have a date field that I pull from an ApexController but when it appears in the URL it shows today's date and not the one from the field. I do not get an error (that I know about, quite frankly I am not great with how to use the Developer Tools in Chrome)

Any ideas of the error or how to troubleshoot this?
This is the HELPER:
({
	navigate : function(component) {
        var action = component.get("c.getOpportunity");
		var idOpp = component.get("v.recordId");
        var SCMAid = component.get("v.aid");
        var SCMFormId = component.get("v.formId");
		if(!$A.util.isEmpty(idOpp))
		{
			action.setParams({opportunityId: idOpp});
		
			// Create a callback that is executed after 
			// the server-side action returns
			action.setCallback(this, function(response) {
				var state = response.getState();
				if (state === "SUCCESS") {
					var opp = response.getReturnValue();
                    /* Here you can access like opp.Id, opp.FTEs__c, opp.Account.Industry and form the URL */
                    var fullTimeEmployees = opp.Total_FTEs__c;
                    var industry = opp.Account.Industry;
                    var programStartDate = $A.localizationService.formatDate(Date(opp.ProgramStartDate__c),"MM/DD/YYYY");  
                    var opportunityId = opp.Id;
                    var opportunityName = opp.Name;                    
					var filePath = '/Accounts/'+ opp.Account.Name + '/Opportunities/&ru=%2Fatlas%2Fbpm%2FWorkList.aspx'
                    var partOneURL = 'https://na123.springcm.com/atlas/Forms/UpdateFormDoc.aspx?';
					
                    var partTwoURL = 'aid='+SCMAid;
                    var formUid = SCMFormId;
                    if(SCMAid == '9999') {
                        //Sandbox URL
                        var partOneURL = 'https://uatna123.springcm.com/atlas/Forms/UpdateFormDoc.aspx?';
                    } else {
                        //Production URL
                        var partOneURL = 'https://na123.springcm.com/atlas/Forms/UpdateFormDoc.aspx?';
                    }
					var finalURL = partOneURL + partTwoURL 
                    var finalURL = finalURL + '&FormUid=' + formUid;
                    var finalURL = finalURL + '&SFFTE=' + fullTimeEmployees;
                    var finalURL = finalURL + '&SFIND=' + industry;
                    var finalURL = finalURL + '&SFPSD=' + programStartDate;
                    var finalURL = finalURL + '&SFID=' + opp.Id;
                    var finalURL = finalURL + '&SFNAME=' + opportunityName;
                    var finalURL = finalURL + '&SFWF=ABC';
                    var finalURL = finalURL + '&SFCAFTYPE=CAAF';
                    var finalURL = finalURL + '&SFTYPE=Salesforce.Opportunity';
                    var finalURL = finalURL + '&SFPATH=' + filePath;
                    var urlEvent=$A.get("e.force:navigateToURL");
                    urlEvent.setParams({"url": finalURL});
					urlEvent.fire();
				}
				else if (state === "ERROR") {
					var errors = response.getError();
					if (errors) {
						if (errors[0] && errors[0].message) {
							console.log("Error message: " + 
									 errors[0].message);
						}
					} else {
						console.log("Unknown error");
					}
				}
			});

			// optionally set storable, abortable, background flag here

			// A client-side action could cause multiple events, 
			// which could trigger other events and 
			// other server-side action calls.
			// $A.enqueueAction adds the server-side action to the queue.
			$A.enqueueAction(action);
		}
		else
		{
			console.log('===Record Id is not present====');
		}
	}
})
The variable that I am having the issue with is:
 var programStartDate = $A.localizationService.formatDate(Date(opp.ProgramStartDate__c),"MM/DD/YYYY");  

Not sure why I get today's date and not the one from the controller.

Thanks in advance.

Robert
 
Hello, I am hoping some will be able to help. I have a visualforce page that I use to select products from the pricebook. What I would like to do is when a field named Seats__c is updated on the page that it also updates the field value of a field named X2018_Q1_Seats__c. I would like to have it so that if the user would like to over write it they can but it would default to the value in Seats__c by default.

Below is what I have tried, unsuccessfully:
<apex:page standardController="Opportunity" extensions="opportunityProductEntryExtension" action="{!priceBookCheck}" >
    <apex:sectionHeader Title="Manage {!$ObjectType.Product2.LabelPlural}" subtitle="{!opportunity.Name}"/>
    <apex:messages style="color:red"/>

    <style>
        .search{
            font-size:14pt;
            margin-right: 20px;    
        }
        .fyi{
            color:red;
            font-style:italic;
        }
        .label{
            margin-right:10px;
            font-weight:bold;
        }
        
    </style>
    
    <script type='text/javascript'>
    
        // This script assists the search bar functionality
        // It will execute a search only after the user has stopped typing for more than 1 second
        // To raise the time between when the user stops typing and the search, edit the following variable:
        
        var waitTime = 1;
        
    
        var countDown = waitTime+1;
        var started = false;
        
        function resetTimer(){
        
            countDown=waitTime+1;
            
            if(started==false){
                started=true;
                runCountDown();
            }
        }
        
        function runCountDown(){
        
            countDown--;
            
            if(countDown<=0){
                fetchResults();
                started=false;
            }
            else{
                window.setTimeout(runCountDown,1000);
            }
        }
        function updateSeats() {
            var totalSeats = document.getElementById("{!$Component.pageform.mainBody.selected.pageblocktable.seatColumn.Seats}");
            document.getElementById("{!$Component.pageform.mainBody.selected.pageblocktable.yearOneColumn.pageBlockSectionYearOne.result}").value = totalSeats;
            }

               
    </script>

    <apex:form id="pageform" >
    
        <apex:outputPanel id="mainBody">
        
            <apex:outputLabel styleClass="label">PriceBook: </apex:outputLabel>
            <apex:outputText value="{!theBook.Name}"/>&nbsp;
            <apex:commandLink action="{!changePricebook}" value="change" immediate="true"/>
            <br/>
            <!-- not everyone is using multi-currency, so this section may or may not show -->
            <apex:outputPanel rendered="{!multipleCurrencies}">
                <apex:outputLabel styleClass="label">Currency: </apex:outputLabel>
                <apex:outputText value="{!chosenCurrency}"/>
                <br/>
            </apex:outputPanel>
            <br/>
            
<!-- this is the upper table... a.k.a. the "Shopping Cart"-->

            <!-- notice we use a lot of $ObjectType merge fields... I did that because if you have changed the labels of fields or objects it will reflect your own lingo -->
            <apex:pageBlock title="Selected {!$ObjectType.Product2.LabelPlural}" id="selected">
                       
                <apex:pageblockTable value="{!shoppingCart}" var="s" id="pageblocktable">
                
                    <apex:column >
                        <apex:commandLink value="Remove" action="{!removeFromShoppingCart}" reRender="selected,searchResults" immediate="true">
                            <!-- this param is how we send an argument to the controller, so it knows which row we clicked 'remove' on -->
                            <apex:param value="{!s.PriceBookEntryId}" assignTo="{!toUnselect}" name="toUnselect"/>
                        </apex:commandLink>
                    </apex:column>
                    <apex:column headerValue=" " title="{!$ObjectType.Product2.fields.Name.inlineHelpText}"> 
                        <apex:pageBlockSection >
                        <apex:inputField value="{!s.Program_Start_Date__c}" label="Program Start Date :"
                                                                            rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                                                            required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        </apex:pageBlockSection>
                        <apex:outputField value="{!s.PriceBookEntry.Product2.Name}"/><br/>
                        <i>Line Item Description : </i>
                        <apex:inputField value="{!s.Description}" /><br/>
                        
                        
                    </apex:column>
                    <apex:column headerValue="">
                        <br/><br/>
                        # of&nbsp;<apex:outputField value="{!s.PricebookEntry.Product2.Unit_of_Measure_Plural__c}" style="width:180px"/><br/>
                        <apex:outputText value="Svc Channel" rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"></apex:outputText><br/><br/><br/><br/><br/>
                        <apex:outputText value="Qtrly Seat Ramp :" rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"></apex:outputText><br/><br/><br/>
                    </apex:column>
                    <apex:column headerValue=" "
                                 title="{!$ObjectType.OpportunityLineItem.fields.Quantity.inlineHelpText}" id="yearOneColumn">
                        <br/>
                        <apex:inputField value="{!s.Quantity}" style="width:50px" />
                        <apex:inputField value="{!s.Service_Channel__c}" 
                                         rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                         required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        <apex:pageBlockSection id="pageBlockSectionYearOne">
                        
                        <apex:inputField value="{!s.X2018_Q1_Seats__c}" style="width:30px" id="result" 
                                                rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                                required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        <apex:inputField value="{!s.X2018_Q2_Seats__c}" style="width:30px"
                                                rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                                required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        <apex:inputField value="{!s.X2018_Q3_Seats__c}" style="width:30px"
                                                rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                                required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        <apex:inputField value="{!s.X2018_Q4_Seats__c}" style="width:30px"
                                                rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                                required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        </apex:pageBlockSection> 
                     </apex:column>  
                        <apex:outputText value="2018 Q3" rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"></apex:outputText>                    
                    <apex:column headerValue=" "
                                 title="{!$ObjectType.OpportunityLineItem.fields.Number_of_Months__c.inlineHelpText}">
                        <center>
                        <b>Contract Length (Months)</b>
                        <apex:inputField value="{!s.Number_of_Months__c}" style="width:50px"/>
                        </center>
                    </apex:column>
                    <apex:column headerValue="">
                        price per&nbsp;<apex:outputField value="{!s.PricebookEntry.Product2.Unit_of_Measure_Singular__c}" style="width:160px"/><br/>
                        <apex:outputText value="Service Type" rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"></apex:outputText><br/><br/><br/><br/><br/>
                        <apex:outputText value="Qtrly Seat Ramp :" rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"></apex:outputText><br/><br/><br/>
                    </apex:column>
                    
                    <apex:column headerValue=" "
                                 title="{!$ObjectType.OpportunityLineItem.fields.UnitPrice.inlineHelpText}">
                        <apex:inputField value="{!s.Unit_Price2__c}" style="width:70px" required="true"  />
                        <apex:inputField value="{!s.Service_Type__c}"
                                         rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                         required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        <apex:pageBlockSection >
                        
                        <apex:inputField value="{!s.X2019_Q1_Seats__c}" style="width:30px" 
                                                 rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                                 required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        <apex:inputField value="{!s.X2019_Q2_Seats__c}" style="width:30px"
                                                rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                                required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        <apex:inputField value="{!s.X2019_Q3_Seats__c}" style="width:30px"
                                                rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                                required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        <apex:inputField value="{!s.X2019_Q4_Seats__c}" style="width:30px"
                                                rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                                required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        </apex:pageBlockSection>
                    </apex:column>
                    <apex:column headerValue=" " title="Enter Your Specific Margin - Pre-Populated with Avg">
                        <center>
                        <b>Adj GM%</b>
                        <apex:inputField value="{!s.Adjusted_Gross_Margin_Percentage__c}" style="width:30px" />
                        </center>
                    </apex:column>
                    <apex:column headerValue=" "
                                 title="{!$ObjectType.OpportunityLineItem.fields.One_Time_Revenue__c.inlineHelpText}">
                        <center>
                        <b>One-Time Rev</b>
                        <apex:inputCheckbox value="{!s.One_Time_Revenue__c}"  />
                        </center>
                    </apex:column>
                    <apex:column headerValue=" " title=" ">
                        <apex:outputLabel rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}" style="width:50px">Total # of Seats&nbsp;</apex:outputLabel>
                        <br/><br/><br/><br/><br/><br/>
                    </apex:column>

                    <apex:column headerValue=" " title="{!$ObjectType.OpportunityLineItem.fields.Seats__c.inlineHelpText}" id="seatColumn">
                        
                        <apex:inputField value="{!s.Seats__c}"  style="width:50px"  onkeyup="refreshTotals();"  id="Seats" onclick="updateSeats()"
                                      rendered="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"
                                      required="{!IF(s.PriceBookEntry.Product2.Project_Seat_Count__c == 'TRUE', true, false)}"/>
                        <br/><br/><br/><br/><br/><br/>
                    </apex:column>

                </apex:pageblockTable>
            
            
                <apex:pageBlockButtons >
                    <apex:commandButton action="{!onSave}" value="Save"/>
                    <apex:commandButton action="{!onCancel}" value="Cancel" immediate="true"/>
                </apex:pageBlockButtons>
            
            </apex:pageBlock>   
            <apex:pageBlock >
                <apex:outputPanel styleClass="search">
                    Search for {!$ObjectType.Product2.LabelPlural}:
                </apex:outputPanel>
                <apex:actionRegion renderRegionOnly="false" immediate="true">
                    <apex:actionFunction name="fetchResults" action="{!updateAvailableList}" reRender="searchResults" status="searchStatus"/>
                    <apex:selectList value="{!selectedProdFamily}" label="Select Product Family : " multiselect="false" size="1">
                        <apex:actionSupport event="onchange" action="{!updateAvailableList}" />
                        <apex:selectOptions value="{!ProductFamily}"  />
                    </apex:selectList>
                    &nbsp;&nbsp;                 
                    <apex:inputText value="{!searchString}" onkeydown="if(event.keyCode==13){this.blur();}else{resetTimer();}" style="width:300px"/>
                    &nbsp;&nbsp;
                                  <apex:actionStatus id="searchStatus" startText="searching..." stopText=" "/>
                    </i>    
                </apex:actionRegion>
            
                <br/>
                <br/>
            
                <apex:outputPanel id="searchResults">
                    <apex:pageBlockTable value="{!AvailableProducts}" var="a">                       
                        <apex:column headerValue="{!$ObjectType.Product2.Fields.Family.Label} / Company" value="{!a.Product2.Family}"/>
                        <apex:column headerValue="{!$ObjectType.Product2.Fields.Name.Label}" value="{!a.Product2.Name}" />                      
                        <apex:column headerValue="{!$ObjectType.Product2.Fields.Product_Gross_Margin__c.Label}" value="{!a.Product2.Product_Gross_Margin__c}"/>                    
                        <apex:column >
                            <!-- command button in a column... neato -->
                            <apex:commandButton value="Select" action="{!addToShoppingCart}" reRender="selected,searchResults" immediate="true">
                                <!-- again we use apex:param to be able to tell the controller which row we are working with -->
                                <apex:param value="{!a.Id}" assignTo="{!toSelect}" name="toSelect"/>
                            </apex:commandButton>
                        </apex:column>               
                    </apex:pageBlockTable>
                    <!-- We put up a warning if results exceed 100 rows -->
                    <apex:outputPanel styleClass="fyi" rendered="{!overLimit}">
                        <br/>
                        Your search returned over 100 results, use a more specific search string if you do not see the desired {!$ObjectType.Product2.Label}.
                        <br/>
                    </apex:outputPanel>            
                </apex:outputPanel>
            </apex:pageBlock>
        </apex:outputPanel>
    </apex:form>
</apex:page>

This is the javascript function that I am trying to use (it is above but thought it would be easier to see) here:
<script>
function updateSeats() {
            var totalSeats = document.getElementById("{!$Component.pageform.mainBody.selected.pageblocktable.seatColumn.Seats}");
            document.getElementById("{!$Component.pageform.mainBody.selected.pageblocktable.yearOneColumn.pageBlockSectionYearOne.result}").value = totalSeats;
            }
</script>

Thank you in advance,

Robert
I have a Lightning Component that has a button that I would like to click and have it open an external URL with values from the fields from the current Opportunity Record.

I can not figure out how to get the recordId from component to Apex Controller and then the fields back to the Javascript Helper to form the URL.

Javascript Component
<aura:component implements="force:lightningQuickAction,force:appHostable,flexipage:availableForAllPageTypes,force:hasRecordId" access="global" 
                controller="CAFController">
    
    <aura:attribute name="recordId" type="Id" />
    
    <div id="aura-page">
        <div class="container">
			<ui:button class="btn" label="CAF Form" press="{!c.navigate}"/> 
        </div>
    </div>
</aura:component>
Javascript Controller
({
	navigate : function(component, event, helper) {
		helper.navigate(component);
	}
})
Javascript Helper
({
	navigate : function(component) {
        var action = component.get("c.getOpportunity");
        action.setParams({opportunityId: component.get("v.recordId")});
        var urlEvent=$A.get("e.force:navigateToURL");
        var partOneURL = 'https://XXX21.springcm.com/atlas/Forms/UpdateFormDoc.aspx?aid=9124&FormUid=8beXXXXX-d9b0-e611-bb8d-6c3be5XXXXXXX';
        urlEvent.setParams({"url": partOneURL})
        urlEvent.fire();
	}
})
Apex Controller
public class CAFController {

    @AuraEnabled
    public static Opportunity getOpportunity(ID opportunityId){
        if(opportunityId == null) {
            return null;
        }
        List<Opportunity> opps = [SELECT id, 
                                         Opportunity.FTEs__c,
                                         Opportunity.Account.Industry ,
                                         Opportunity.TotalNumberofSeats__c ,
                                         Opportunity.CAPEX_Required__c ,
                                         Opportunity.Amount ,
                                         Opportunity.Annualized_Revenue__c,
                                         Opportunity.ProgramStartDate__c ,
                                         Opportunity.Name
                                  FROM Opportunity
                                  WHERE Id =: opportunityId];
        if(opps.size()>0){
            return opps[0];
        }
        return null;
    }
}

I would appreciate any assistance. Thank you in advance. 

Robert


 
I have a Javascript button in Lightning that needs to go out to SpringCM and pulls a form up that our users complete, it uses fields from the Opportunity that it pass through the URL. I am desperately trying to figure out how to do this and have tried the Trailhead Module: Lightning Alternatives to JavaScript Buttons and either it does not explain for my example or I am unable to understand. Can someone point me to any other solutions?

The Button is below:
{!REQUIRESCRIPT("/soap/ajax/10.0/connection.js")} 
{!REQUIRESCRIPT("/soap/ajax/10.0/apex.js")} 

//Should not have to change this at all 
function getEOSInfo(objectid,objecttype,callback) { 

var baseUrl = "{!$Api.Partner_Server_URL_260}".substring(0, "{!$Api.Partner_Server_URL_260}".indexOf("/services")); 
var url = baseUrl +"/services/apexrest/SpringCMEos/eosinfo?objecttype="+objecttype+"&objectid="+objectid; 
var authkey = "Bearer {!$Api.Session_ID}"; 

sforce.connection.remoteFunction({ 
url : url, 
requestHeaders: {"Authorization":authkey,"Accept":"application/json"}, 
onSuccess : function(response) { 
var eosInfoResponse = JSON.parse(response); 
callback(eosInfoResponse); 
} 
}); 
} 


//Here you write your own code, this is a simple call 
var objectid = "{!Opportunity.Id}"; 
var objecttype = "Opportunity"; 

getEOSInfo(objectid,objecttype,function(eosInfo){ 


var formuid = "8be07531-XXXX-e611-XXXX-6c3be5a7XXXX"; 
var url = "https://XXX21.springcm.com/atlas/Forms/UpdateFormDoc.aspx?aid=9723&FormUid=" + formuid + "&SFFTE={!Opportunity.FTEs__c}&SFIND={!Account.Industry}&SFPSD={!Opportunity.ProgramStartDate__c}&SFID=" + eosInfo.SFId + "&SFNAME={!Opportunity.Name}&SFWF=ABC&SFCAFTYPE=CAAF&SFTYPE=Salesforce.Opportunity&SFPATH=" + eosInfo.FolderPath + "&ru=%2Fatlas%2Fbpm%2FWorkList.aspx"; 

window.open(url); 

});

Your help is greatly appreciated.
The requirement that I have been given is to display a Popup Window when user presses the New button to create an Opportunity. Then depending on the answer redirect to a different page.

I tried to do create a "new" New Opportunity button but can not replace on the Home Opportunity List View. What is the best approach for this?

We are using Salesforce Classic.

Thanks in advance,

Robert
I have a trigger on the Opportunity that creates records on a custom object called the Opportunity_Revenue__c. It takes the revenue from the Opportunity and spreads it out over the quarters during the length of the deal. It works fine for insert triggers, I need to have the ability to let users re-create based on a changing contract length / deal length. 

So when the record is updated I want to delete all the records in the custom object Opportunity_Revenue__c that are related to the Opportunity and then run the insert code to create the new records for the Opportunity_Revenue__c object. But it is doubling the records because once it deletes the old records it see trigger as an update and an insert.

Can you help or suggest what I might do?

Here is the code:
 
public class OpportunityRevenueTrigger2 {

    
    public static void updateOpportuntityRev(List<Opportunity> trig){
         List<ID> opprtnyId = new List<ID>();
         Decimal totRev;
         Decimal totAllottedRev;
         Decimal mRev;
         
         for(Opportunity opp4: trig){
            if(Opp4.Auto_Generate_Quarterly_Forecast__c == 'Yes'){
                opprtnyId.add(opp4.id);
            }
         List<Opportunity_Revenue__c> deleteOR = [SELECT id
                                                 FROM Opportunity_Revenue__c 
                                                 WHERE Opportunity__c in: opprtnyID];
         
        if(deleteOR.size() != 0){
           Delete deleteOR;
         }
        
        List<Opportunity_Revenue__c> oppr = new List<Opportunity_Revenue__c>();
        for(Opportunity opp : trig){
             
             if(opp.amount > 0 && opp.contract_length_Months__c > 0 
               && opp.Auto_Generate_Quarterly_Forecast__c == 'Yes' ){
                   Date sDate = opp.CloseDate;
                   Integer period = opp.Contract_Length_Months__c.intValue();
                   Integer period2 = period / 3;
                   totRev = opp.Amount;
                   mRev = totRev.divide(period2, 2);
                   for(Integer i = 1; i <= period2; i++) {
                   Opportunity_Revenue__c oppr2 = new Opportunity_Revenue__c();
                   oppr2.Account__c = opp.AccountId;
                   oppr2.Opportunity__c = opp.id;
                   System.debug('i '+ i);
                   oppr2.ProjectedRevenue__c = mRev;
                   oppr2.Month__c = sDate;
                       if(sDate.Month()== 1 || sDate.month()==2 || sDate.month() ==3){
                           oppr2.Quarter__c =  'Quarter 1, '+string.valueOf(sDate.Year());   
                       } else if (sDate.Month()== 4 || sDate.month()== 5 || sDate.month() == 6){
                           oppr2.Quarter__c =  'Quarter 2, '+string.valueOf(sDate.Year());
                       } else if (sDate.Month()== 7 || sDate.month()== 8 || sDate.month() == 9){
                           oppr2.Quarter__c =  'Quarter 3, '+string.valueOf(sDate.Year());
                       } else if (sDate.Month()== 10 || sDate.month()==11 || sDate.month() ==12){
                           oppr2.Quarter__c =  'Quarter 4, '+string.valueOf(sDate.Year());
                       }
                   
                   oppr.add(oppr2);
                   sDate = sDate.addMonths(3);
                   }
                  
        
              }
        }
        insert oppr;

    }
}
}
 
trigger OpportunityRevenueTrigger on Opportunity (after insert, after update) {
  
        
        OpportunityRevenueTrigger2.updateOpportuntityRev(trigger.new);
        
 
  }

 
Thank you in advance
I am attempting to pull the Account Ids from a custom object. Once I have the Account Ids I am attempting to pull all the Contacts associated with the Accounts and update a Account_Relationship_Status__c field, but continue to receive the following error: System.NullPointerException: Attempt to de-reference a null object

I have placed System.debug statements in the code in hopes to figure it out, but that has been unsuccessful. Can someone tell me what I seem to be missing?
 
Public List<Contact> contList;

for(Red_Zone__c rzAcct: [SELECT Account__c, status__c, Escalation__c FROM Red_Zone__c WHERE status__c ='Open' and Escalation__c ='Red Zone']){
    if (rzAcct.Account__c != Null && rzAcct.status__c != Null && rzAcct.Escalation__c != Null){
            System.debug('rzAcct.id '+rzAcct.id);
            System.debug('rzAcct.Account__c '+rzAcct.Account__c);
            System.debug('rzAcct.Status__c '+rzAcct.status__c);
            System.debug('rzAcct.Escalation__c '+rzAcct.Escalation__c);
        for (Contact con: [SELECT account_relationship_status__c, AccountId FROM Contact WHERE AccountId =:rzAcct.Account__c]){
            System.debug('con.id '+con.id);
            System.debug('con.account_relationship_status__c '+con.account_relationship_status__c);
            System.debug('con.AccountID '+con.AccountId);
            
               con.account_relationship_status__c ='Red Zone';
               contList.add(con);
        }
   }
System.debug('contList '+ contList);
Update contList;    
}

Log results of the Debug Statements:
Debug Log
Thank you in advance.

Kindly provide a solution to the following : 

 

Details

I as a product manager require a custom search page for my salesforce CRM account. I don’t want to use the standard search functionality for this. Here is what I want to be done:

 

    1. On the VF page, create accustom “search” button and a checkbox with the name “limit to accounts I own”
    2. I should be able to enter and search on the following fields (these are the search criteria fields):
      1. Account name(standard field)
      2. Industry (standard field)
      3. Rating(standard field)
      4. Account  region(custom field)
      5. Account priority(custom filed)
      6. Account summary(text)
    3. The search functionality should be a logical OR of all the above combinations.
    4. The correct search results should be displayed ON THE SAME PAGE only after clicking the “submit” button.Display columns should have these fields: account name, industry, rating, account priority.
    5. If the checkbox “limit to accounts I Own” is checked before clicking on search the display only those accounts where the owner=current logged in user. 

I have developed the following code:

 

<apex:page Controller="AccountSearch">
<apex:form >
 
<apex:outputPanel layout="block">
<label for="checkbox"> Limit to Account I own: </label>
<input id="checkbox" type="checkbox"/>
</apex:outputPanel>
<apex:commandButton action="{!search}" value="Search"/>
 
<apex:pageBlock mode="edit" id="block">
         <apex:pageBlockSection >
            <apex:pageBlockSectionItem >
               <apex:outputLabel for="searchText">Search Text</apex:outputLabel>
               <apex:panelGroup >
                  <apex:inputText id="searchText" value="{!searchText}"/>
                  <apex:commandButton value="Submit" action="{!search}" 
                                      rerender="block"/>
               </apex:panelGroup>
            </apex:pageBlockSectionItem>
        </apex:pageBlockSection>
 <apex:actionStatus id="status" startText="requesting..."/>
<apex:pageBlockSection title="Results" id="results" columns="1">
           <apex:pageBlockTable value="{!results}" var="a"
                               rendered="{!NOT(ISNULL(results))}">
                               
              <apex:column value="{!a.Name}"/>
              <apex:column value="{!a.Industry}"/>
              <apex:column value="{!a.Rating}"/>
              <apex:column value="{!a.Account_Region__c}"/>
              <apex:column value="{!a.Account_Priority__c}"/>
              <apex:column value="{!a.Account_Summary__c}"/>
   </apex:pageBlockTable>
   </apex:pageBlockSection>
</apex:pageBlock>
</apex:form>
</apex:page>
__________________________________________________________________________________________
 
public class AccountSearch {
 
  String searchText;
   List<Account> results;
 
public String getSearchText() {
      return searchText;
   }
 
   public void setSearchText(String s) {
      searchText = s;
   }
 
   public List<Account> getResults() {
      return results;
   }
    public PageReference search() {
    results = (List<Account>)[FIND :searchText RETURNING Account(Name, Industry, Rating, Account_Region__c, Account_Priority__c, Account_Summary__c)][0];  
        return null;
    }
 
}
Please provide the necessary modifications
  • May 27, 2013
  • Like
  • 3

I am working on a trigger that will sum some of the values from the opportunityLineItems and update a field on the opportunity. These are custom fields that do not automatically sum and our org has already used 100% of available roll-up summary fields and there are existing integration pieces that rely on these fields. 

 

Currently they are updated via s-control that has to be manually envoked from a link on each record. 

 

I have some experience with Apex Trigger, but am hoping somebody may be able to help me get started... 

 

So far I have:

trigger Calculate_Products on OpportunityLineItem (after delete, after insert, after undelete, 
after update) {

	//Set the OpportunityID
	Set<id> Ids = new Set<id>();
     for (OpportunityLineItem oli : Trigger.new) {
         Ids.add(oli.OpportunityId);
        }
        
	//Query the OpportunityLineItems
	List<aggregateResult> results = [select sum(margin__c)m from opportunityLineItem where OpportunityId in :Ids];
   
    for (OpportunityLineItem oli : Trigger.new) 
    {     
   	Opportunity Opp = opptys.get(oli.OpportunityId);
    Opp.Margin_Total__c = results.get('m');
    }    
     
	update opp;
} 

 

 but I am not quite sure how to I can sum the margin__c field and update the opportunity total_margin__c field... or how to ensure the trigger is bulk friendly. 

 

Thanks in advance for any help!