Quantcast
Channel: Thoughts From a Cloudy Mind
Viewing all articles
Browse latest Browse all 8

Updating Products on Opportunity Close Date Change

$
0
0

I was browsing the Dreamforce App last week and came across a question in the ChallengeUs group from Maria Belli (@msbelli on twitter) :

Dreamforce Question

A few responses had already indicated she would need a trigger and I offered to assist if necessary. I worked with Maria and whipped up a trigger that suited her needs. Since this is functionality that could be applicable to any org I felt it would be worth sharing with my (small) audience.

One item to pay attention to that this trigger only works for certain record types.  I am leaving this in as it is fairly easy to remove the code for this and also provides a good case to learn from.

In this trigger we are looking to set the ServiceDate on the Opportunty Products to the CloseDate of the Opportunity for certain record types when the CloseDate changes.

The first thing we do is get the record type Ids and add them to a Set. Next we loop through the opportunities in trigger.new and add any with a match to the record types in question to another Set. We are also checking to see whether the CloseDate has changed before adding the Opportunity to the Set.

Once you have establish the opportunities that match our record types you can query for those opportunities and their associated Products, which will be a list. You can then loop through the Opportunities and process each list of Products tied to it, setting the Product Service Date to the Opportunity Close Date.

The Trigger:

trigger Opportunity_CloseDate_Update on Opportunity (after update) {
    
    //get the Ids of our two record types and add them to a set
    Set<Id> recTypeIds = new Set<Id>();
    for(RecordType r : [select Id, Name from RecordType where (Name='StandAlone Opportunity' OR Name='Subsidiary Opportunity') AND SobjectType='Opportunity']){
        recTypeIds.add(r.id);
    }
    
    //check the opprtunites in the trigger to see if the Close Date change AND any are of the RecordTypes above. 
    //if so add them to a Set
    Set<Id> StandAloneAndSubsidiaryOppIds = new Set<Id>();
    for(Integer i=0;i<trigger.new.size();i++){
        if(trigger.new[i].CloseDate <> trigger.old[i].CloseDate && recTypeIds.contains(trigger.new[i].RecordTypeId)){
            StandAloneAndSubsidiaryOppIds.add(Trigger.new[i].id);
        }
    }
    
    //Process any opps that have changed
    if(StandAloneAndSubsidiaryOppIds.size() > 0){
	    //get all of the opportunity Line items tied to opportunities in this trigger
	    List<Opportunity> oliList = [select Id, Name, CloseDate, (select Id, ServiceDate, OpportunityId from OpportunityLineItems) from Opportunity where Id IN :StandAloneAndSubsidiaryOppIds];
		
		//create list to hold opportunity line items that need updating.
	    List<OpportunityLineItem> oliUpdateList = new List<OpportunityLineItem>();
	    
	    //loop through opportunites and update all of the opportunity line items. add line items to udpat list.
	    for(Opportunity o : oliList){
	        for(OpportunityLineItem oli : o.OpportunityLineItems){
	            oli.ServiceDate = o.CloseDate;
	            oliUpdateList.add(oli);
	        }
	    }
	    
	    //update the line items
	    if(!oliUpdateList.isEmpty()){
	    	update oliUpdateList;
	    }
    }
}

The Test Class:

@isTest
private class Test_Opportunity_CloseDate_Update {

    static testMethod void myUnitTest() {
        //create a dummy account
        Account a = new Account(Name='Test Account');
        insert a;
                
        //Get the Standard PriceBook and make sure it is active
        PriceBook2 pb = [select Id from PriceBook2 where IsStandard=True];
        pb.IsActive=true;
        update pb;
        
        //create two products 
        List<Product2> prodList = new List<Product2>();
        prodList.add(new Product2(Name='Prod1'));
        prodList.add(new Product2(Name='Prod1'));
        insert prodList;
        
        //Create pricebook entries for the products
        List<PricebookEntry> pbEntryList = new List<PricebookEntry>();
        pbEntryList.add(new PricebookEntry(Pricebook2Id=pb.Id, Product2Id=prodList[0].id, UnitPrice=100.00, IsActive=true));
        pbEntryList.add(new PricebookEntry(Pricebook2Id=pb.Id, Product2Id=prodList[1].id, UnitPrice=200.00, IsActive=true));
        insert pbEntryList;
        
        //Get the two record types we care about plus 1 other one.
        List<RecordType> recTypeList = [select Id, Name from RecordType where (Name='StandAlone Opportunity' OR Name='Subsidiary Opportunity' OR Name='Primary Opportunity' OR Name='Secondary Opportunity') AND SobjectType='Opportunity'];
        
        //Create 200 new opportunities.
        List<Opportunity> newOppList = new List<Opportunity>();
        //  ***MARIA*** be sure to check StageName... set to something you use.
        for(Integer i=1; i<=200; i++){
        	Opportunity o = new Opportunity(Name='Test Oppty ' + i, CloseDate=Date.Today()+1, AccountId=a.id, StageName='asdfasdf',Probability=0.5);
        	//We grabbed four record types above, so set 1/4 of opportunities to each record type. 
        	o.RecordTypeId=recTypeList[Math.mod(i,4)].Id;
        	newOppList.add(o);
        }
        
        //insert our new opportunties
        insert newOppList;
        
        //Now add both products to all of the opportunities
        List<OpportunityLineItem> oliList = new List<OpportunityLineItem>();
        for(Opportunity o : newOppList){
        	oliList.add(new OpportunityLineItem(OpportunityId=o.id, PriceBookEntryId=pbEntryList[0].id,Quantity=1, ServiceDate=Date.Today()+1,UnitPrice=100.00));
        	oliList.add(new OpportunityLineItem(OpportunityId=o.id, PriceBookEntryId=pbEntryList[1].id,Quantity=1, ServiceDate=Date.Today()+1,UnitPrice=200.00));
        }
        
        //insert the opportunity line items
        insert oliList;
        
        //Now that everything has been set up, we can begin the actual test
        Test.startTest();
        //change the close date for all 198 opportunities
        for(Opportunity o : newOppList){
        	o.CloseDate = Date.Today()+7;
        }
        
        //Update the opportuntiies
        update newOppList;
                 
        //get all of the products tied to the opportunites, there should be 396 total
        oliList.clear();
        oliList = [select Id, ServiceDate from OpportunityLineItem where OpportunityId IN :newOppList];
        System.assertEquals(400,oliList.size());
        
        //Now check that the number of Opportunity Line items with service date of Today+7 is 200
        //since half the opportunities should have fired product service date updates
        Integer plus7Counter = 0;
        Integer plus1Counter = 0;
        for(OpportunityLineItem oli : oliList){
        	if(oli.ServiceDate == Date.Today()+7){
        		//increase the count by 1
        		plus7Counter++;        		
        	}
        	if(oli.ServiceDate == Date.Today()+1){
        		plus1Counter++;
        	}
        }
        //make sure the counts are as expected
        System.AssertEquals(200,plus7Counter);
        System.AssertEquals(200,plus1Counter);
        Test.stopTest();
    }
}


Viewing all articles
Browse latest Browse all 8

Latest Images

Trending Articles



Latest Images