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 '17 at 16:29

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. – Dan Wooding Aug 16 '16 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 '16 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? – Dan Wooding Aug 16 '16 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? – Dan Wooding Aug 16 '16 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 '16 at 18:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.