I want to replace a workflow field update with an APEX method to update the fields. The reason being is that I want to be able to add months to a date field and with formulas it only allows days to be added to the date.

I wrote this method to be included in the triggerhandler class for OpportunityLineItem.

    private void updateRenewalDates(Map<Id, OpportunityLineItem> newMap, Map<Id, OpportunityLineItem> oldMap)
    // Create Lists to hold data
    List<OpportunityLineItem> renewals = new List<OpportunityLineItem>();
    Map<Id,List<OpportunityLineItem>> oppToLineItem = new Map<Id,List<OpportunityLineItem>>();

    // Loop through filter records from the api call and see if they meet the criteria
    for(OpportunityLineItem oli:newMap)
        if((oli.Start_Date__c == oldMap.oli.Start_Date__c) || (oli.End_Date__c == oldMap.oli.End_Date__c))
    // If they do meet the criteria then add them to the list to update         
                List<OpportunityLineItem> oliLst = new List<OpportunityLineItem>();
    // Get the record fields for records where the id is from our list
    renewals = [SELECT Id, Start_Date__c, Start_Date_Renewal__c, End_Date__c, End_Date_Renewal__c, Opportunity.ContractTerm__c 
                FROM OpportunityLineItem 
                WHERE Id in:oppToLineItem.keyset()];

    // Loop through results of the query and update the record with the new value       
    for(OpportunityTeamMember oppLineItem:renewals)
        List<OpportunityLineItem> olis = oppToLineItem.get(oppLineItem.OpportunityId);
        for(OpportunityLineItem line:olis)
    // Update Renewal dates with the start/end date + Contract length       
            line.Start_Date_Renewal__c = oli.Start_Date__c.addMonths(12);
            line.End_Date_Renewal__c = oli.End_Date__c.addMonths(12);


When i try to save the class and have it compile it gives the error:

Initial term of field expression must be a concrete SObject: Map

On the line:

 if((oli.Start_Date__c == oldMap.oli.Start_Date__c) || (oli.End_Date__c == oldMap.oli.End_Date__c))

Where am I going wrong here and is there a simplier way to go about it?

  • Ah, you are learning the formatting ways. :)
    – Adrian Larson
    Jan 10, 2017 at 16:29

1 Answer 1


The oldMap variable does not have a member named oli. Change oldMap.oli to oldMap.get(oli.Id) and you will then have your old record from the map.

To check if the value changed:

if (oli.Start_Date__c != oldMap.get(oli.Id).Start_Date__c)

You can apply the same logic to other fields, such as End_Date__c. You could also look at the Selector package, which lets you do:

Select.Field.haschanged(OpportunityLineItem.Start_Date__c).filter(newRecords, oldMap);
  • I changed the line to if((oli.Start_Date__c == oldMap.get(oli.Start_Date__c)) || (oli.End_Date__c == oldMap.get(oli.End_Date__c))) and get the error Incompatible key type Date for Map<Id,OpportunityLineItem> I know in your answer you said use oli.id which gives the record, but I want to compare to a specific field on the record. Aug 16, 2016 at 15:13
  • That surely won't work. Your map key is Id, and unless your naming conventions are completely alien, the Start_Date__c and End_Date__c fields are of the Date type.
    – Adrian Larson
    Aug 16, 2016 at 15:15
  • Right, I have two date fields and I want to see if they have been changed. So would you not compare the values in new map vs old map? Aug 16, 2016 at 15:19
  • I get an error "Loop must iterate over a collection type: Map<Id, OpportunityLineItem> on the for line. newMap is already set as Map at the top of the method why would i get this error? Aug 16, 2016 at 18:52
  • @Dan Your collection variable needs to be a List<OpportunityLineItem> if your loop variable is of type OpportunityLineItem. In this case, newMap.values() instead of newMap.
    – Adrian Larson
    Aug 16, 2016 at 18:54

You must log in to answer this question.

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