Salesforce Update Product Schedule from Opportunity using Apex Trigger

The tutorial below shows how you can use Salesforce Triggers to update the CloseDate of an opportunity and the associated Product Schedule.

First thing is we must create a product Trigger, below is the code for the product trigger:

trigger OpportunityScheduleUpdate on Opportunity (after update) {
  
  for (Opportunity o: Trigger.new) {
        Opportunity oldCloseDate = Trigger.oldMap.get(o.ID);
        if (o.CloseDate != oldCloseDate.CloseDate) {
            Integer dateval = oldCloseDate.CloseDate.daysBetween(o.CloseDate);
            OppScheduleUpdate.ScheduleDateUpdate(o.id, dateval);  
        }
    }
}

The trigger class updates all the Product ScheduleDate by the amount of the days the Opportunity Close Date has changed:

public class OppScheduleUpdate
{
    public static void ScheduleDateUpdate(String oppid, Integer dateval) 
    {
       List idval = [SELECT id FROM OpportunityLineItem WHERE OpportunityId=:oppid];
       List datelist;
       for (Integer i = 0; i < idval.size(); i++)
       {
           datelist = [SELECT ScheduleDate FROM OpportunityLineItemSchedule WHERE OpportunityLineItemId =:idval[i].id];
           for (Integer k = 0; k < datelist.size(); k++)
               {
               System.debug('DateList = ' + datelist[k]);
               Date mydate=Date.newInstance(datelist[k].ScheduleDate.Year(),datelist[k].ScheduleDate.Month(),datelist[k].ScheduleDate.Day());
               mydate=mydate.addDays(dateval);
               datelist[k].ScheduleDate = mydate;
               update datelist;
               //date datediff = date.parse(datelist[k]);
               }
       }      
    }
}

Advertisements

12 Comments on “Salesforce Update Product Schedule from Opportunity using Apex Trigger

  1. Hi Edson, yes I tested multiple opportunities and made sure my schedule updates worked. It was successful in all cases.

  2. yes thanks very much sir, Can you send me the test coverage or unit test for this? Thanks again very helpful.

  3. yes thanks very much sir, Can you send me the test coverage or unit test for this? very much appreciated, Thanks again very helpful.

  4. michael? the test coverage for this or unit test is hard to make, do you have your own test coverage for this?

  5. I added an opportunity line item using custom apex code. The product which I added in the opportunity line item has a default schedule settings. But OpportunityLineItem schedule records are not created for this opportunity line item. what might be the reason?

  6. Hi,
    I need to write test case in which when opportunity product inserted then opportunity product schedule must be inserted.
    Thanks,
    Khillan

  7. Trigger:

    Trigger OpportunityScheduling on Opportunity (after update) {

    if(!Validator_cls.hasAlreadyDone())
    {
    for (Opportunity o: Trigger.new)
    {

    Opportunity oldCloseDate = Trigger.oldMap.get(o.ID);
    if (o.CloseDate != oldCloseDate.CloseDate)
    {
    Integer dateval = oldCloseDate.CloseDate.daysBetween(o.CloseDate);
    OpportunitySchedulingHandler.ScheduleDateUpdate(o.id, dateval);

    }
    }
    }
    }

    Class:

    public with sharing class OpportunitySchedulingHandler {

    public static void ScheduleDateUpdate(String oppid, Integer dateval)
    {
    List idval = [SELECT id FROM OpportunityLineItem WHERE OpportunityId=:oppid];
    List datelist = new List();
    for (Integer i = 0; i < idval.size(); i++)
    {
    datelist = [SELECT ScheduleDate FROM OpportunityLineItemSchedule WHERE OpportunityLineItemId =:idval[i].id];
    for (Integer k = 0; k < datelist.size(); k++)
    {

    Date mydate=Date.newInstance(datelist[k].ScheduleDate.Year(),datelist[k].ScheduleDate.Month(),datelist[k].ScheduleDate.Day());
    mydate=mydate.addDays(dateval);
    datelist[k].ScheduleDate = mydate;
    update datelist;

    }
    }
    }
    }

  8. To new developer: please don’t just copy-paste this code as it is actually not well written.
    One of the most important rule in Apex triggers is to bulkify them to avoid hitting the limits, it means not put SOQL queries or DML operation (save, update, delete) in loops. Here, there is a SOQL query in a double triple and an update operation in a triple loop.
    I work as a Salesforce developer consultant and I am now working on correcting the code of someone who just copy-pasted this one and it’s not even that difficult to bulkify it: use Trigger.newMap and Trigger.OldMap to get the old and new values of the opportunities, put the records to update in lists and actually do the update at the end of the class and never write a trigger in a loop “for(trigger.new)”.
    I can’t share my rectified code because it is for one of our client (so I don’t have the right to make it public), but please stop spreading badly written triggers.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: