• RandyBarton24
  • NEWBIE
  • 10 Points
  • Member since 2015

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 4
    Questions
  • 2
    Replies
This one is making me a little crazy... I'm sure it's something small I am overlooking, but I can't seem to figure it out.

In my developer sandbox I have the following test class: 
@isTest static void numberOfProvidersUpdatedToLessThan3FromMoreThan3() {
		
		Account a = TestUtilities.insertBasicAccount();
		Opportunity o = TestUtilities.createBasicOpportunity(a.Id);
		o.Number_of_Providers__c = 4;
		
		insert o;
		Test.startTest();
		
		o.Number_of_Providers__c = 1;
		update o;

		Test.stopTest();

		Opportunity o2 = TestUtilities.getOppData(o.Id);

		Map<String, Decimal> oppLineItemQty = new Map<String, Decimal>();
		Map<String, Decimal> oppLineItemPrice = new Map<String, Decimal>();

		if(o2.HasOpportunityLineItem) {
			
			for(OpportunityLineItem oppLi : o2.OpportunityLineItems) {
				oppLineItemQty.put(oppLi.PricebookEntry.Name, oppLi.Quantity);
				oppLineItemPrice.put(oppLi.PricebookEntry.Name, oppLi.TotalPrice);
			}
		}
		System.assertNotEquals(o2.Pricebook2Id, null, 'The Pricebook was not set');
		System.assert(o2.HasOpportunityLineItem, 'The Opportunity does not have any products');
		System.assertEquals(2, o2.OpportunityLineItems.size(), 'Two products were expected on this Opportunity');
		System.assert(oppLineItemPrice.containsKey('Monthly Service Fee'), 'The MSF Product was not added');
		System.assert(oppLineItemPrice.containsKey('Setup Fee'), 'The SF Product was not added');
		System.assert(!oppLineItemPrice.containsKey('Additional Providers'), 'The AP Product should have been removed');
		System.assertEquals(1, oppLineItemQty.get('Monthly Service Fee'), 'The MSF quantity is incorrect');
		System.assertEquals(1, oppLineItemQty.get('Setup Fee'), 'The SF quantity is incorrect');
		System.assertEquals(379, oppLineItemPrice.get('Monthly Service Fee'), 'The MSF price is incorrect');
		System.assertEquals(399, oppLineItemPrice.get('Setup Fee'), 'The SF price is incorrect');
	}

The method I am testing is as follows:
 
public static void updateAPProductForNumberOfProvidersChange(Opportunity[] updatedOpps, Map<ID, Opportunity> oldOpportunityMap, Map<ID, Opportunity> newOpportunityMap) {

    	Boolean hasAdditionalProviderLineItem = false;
    	Map<Id, OpportunityLineItem> mapInsertOppLis = new Map<Id, OpportunityLineItem>();
    	Map<Id, OpportunityLineItem> mapUpdateOppLis = new Map<Id, OpportunityLineItem>();
    	Map<Id, OpportunityLineItem> mapDeleteOppLis = new Map<Id, OpportunityLineItem>();

    	if(!FlowControl.InClass1) {

    		FlowControl.InClass1 = true;
	    	
	    	for(Opportunity o : updatedOpps) {

	    		System.debug(o.Number_of_Providers__c);
	    		System.debug(oldOpportunityMap.get(o.Id).Number_of_Providers__c);
	    		System.debug(newOppDataMap.get(o.Id).Number_of_Providers__c);

	    		if(o.RecordTypeId != DEFAULT_RENEWAL_RECORD_TYPE.getRecordTypeId()){

		    		if(o.Number_of_Providers__c != oldOpportunityMap.get(o.Id).Number_of_Providers__c){

		    			if(o.HasOpportunityLineItem) {

			    			for(OpportunityLineItem oppLi : newOppDataMap.get(o.Id).OpportunityLineItems) {

			    				if(oppLi.PricebookEntry.Product2.ProductCode == APProduct) {
			    					oppLi.Quantity = o.Number_of_Providers__c > 3 ? o.Number_of_Providers__c - 3 : 0;
			    					oppLi.UnitPrice = oppLi.PricebookEntry.UnitPrice;
			    					hasAdditionalProviderLineItem = true;

			    					if(oppLi.Quantity == 0) {
			    						mapDeleteOppLis.put(oppLi.Id, oppLi);
			    						System.debug(mapDeleteOppLis);
			    					} else {
			    						mapUpdateOppLis.put(oppLi.Id, oppLi);
			    						System.debug(mapUpdateOppLis);
			    					} 
			    				}
			    			}

			    			if(!hasAdditionalProviderLineItem && o.Number_of_Providers__c > 3) {

			    				for(PriceBookEntry pbEntry : STANDARD_PRICEBOOK) {

			    					if(pbEntry.Product2.ProductCode == APProduct) {
			    						OpportunityLineItem newOppLi = OpportunityUtilities.addOpportunityLineItem(o, pbEntry, o.Number_of_Providers__c -3);
			    						mapInsertOppLis.put(pbEntry.Id, newOppLi);
			    					}
			    				}
			    			}

			    		} else if(o.Number_of_Providers__c > 3 && o.Pricebook2Id != null) {
			    			
			    			for(PriceBookEntry pbEntry : STANDARD_PRICEBOOK) {

			    				if(pbEntry.Product2.ProductCode == APProduct) {
			    					OpportunityLineItem newOppLi = OpportunityUtilities.addOpportunityLineItem(o, pbEntry, o.Number_of_Providers__c -3);
			    					mapInsertOppLis.put(pbEntry.Id, newOppLi);
			    				}
			    			}
			    		}
		    		}
		    	}
	    	}
	    	SRUtilities.runDml(mapInsertOppLis, mapUpdateOppLis, mapDeleteOppLis, 'OpportunityUtilities.updateAPProductForNumberOfProvidersChange');
        	if(!mapUpdateOppLis.isEmpty() || !mapInsertOppLis.isEmpty() || !mapDeleteOppLis.isEmpty()) OpportunityTriggerHandler.oppDataMap = OpportunityUtilities.getOppData(newOppDataMap);
        	FlowControl.InClass1 = false;
        }
    }

The 3 Debug statements return the following:

System.debug(o.Number_of_Providers__c); = 4
System.debug(oldOpportunityMap.get(o.Id).Number_of_Providers__c); = 4
System.debug(newOppDataMap.get(o.Id).Number_of_Providers__c); = 4

When I am expecting:

System.debug(o.Number_of_Providers__c); = 1
System.debug(oldOpportunityMap.get(o.Id).Number_of_Providers__c); = 4
System.debug(newOppDataMap.get(o.Id).Number_of_Providers__c); = 1

As a sanity check, I put the same code in a fresh dev org, run the test, and I get the results I am expecting.  Any ideas??  Thank you in advance for your help.
Hey Everyone,

I'm wondering if this is possible or if there is a better solution.  I am trying to access PricebookEntries from an Opportunity SOQL query.  Let me try to explain with an example:
Opportunity[] updatedOpps = [SELECT Id, 
		RecordTypeId,
		Number_of_Providers__c, 
		RecurSoft__Contract_Signed_Date__c, 
		RecurSoft__Contract_Term_Start_Date1__c, 
		RecurSoft__Trial_End_Date1__c, 
        Name, 
        RecurSoft__Initial_Contract_Term__c, 
        RecurSoft__Number_of_Free_Months__c,  
        RecurSoft__Trial__c, 
        HasOpportunityLineItem, 
        Number_of_SF_products__c, 
        Number_of_MSF_products__c, 
        CampaignId,
        	Campaign.Product_1_Name1__c,
	    	Campaign.Product_2_Name_2__c,
	    	Campaign.Name,
	    	Campaign.Type,
	    	Campaign.Trial_Period__c,
	    	Campaign.Free_Months__c,
	    	Campaign.Free_Months_Setting__c,
	    	Campaign.Promo_Product1__c,
	    	Campaign.Product_1_Sales_Price__c,
	    	Campaign.Product_2_Sale_Price__c, 
	    Pricebook2Id,
    		Pricebook2.Name,
    		Pricebook2.IsStandard,
    		(select Id,
	    		Product2Id,
	    		UnitPrice,
	    		ProductCode
	    		from PricebookEntries),
		(SELECT Id,
	    	Is_Promo_Item__c,
	    	ListPrice,
	    	UnitPrice,
	    	OpportunityId,
	    	PricebookEntryId,
	    	PriceBookEntry.Name,
	    	PriceBookEntry.UnitPrice,
	    	PricebookEntry.Product2Id, 
	    	PricebookEntry.Product2.Name,
	    	PricebookEntry.Pricebook2Id
	    	FROM OpportunityLineItems)
        FROM Opportunity 
        WHERE Id IN :oppIds]);
The query isn't working because there isn't a direct relationship between the Opportunity and PricebookEntry SObjects.  I can access PricebookEntries through the OpportunityLineItem SObject, but what I really am looking to access is a list of all PricebookEntries in an Opportunities current Pricebook in order to add OpportunityLineItems.  I really want to avoid looping through a separate query to get the PricebookEntries. 

I am trying to access the info in order to auto-add products to an Opportunity in the following method (the "updatedOpps" parameter is the list returned from the above SOQL query; the method is called by an After Insert trigger on the Opportunity):
public static void addStandardProducts(Opportunity[] updatedOpps) {

    	Set<String> currentOpportunityLineItems = new Set<String>();
    	Map<Id, OpportunityLineItem> mapInsertOppLis = new Map<Id, OpportunityLineItem>();

    	for(Opportunity o : updatedOpps) {

    		if(o.RecordTypeId != DEFAULT_RENEWAL_RECORD_TYPE.getRecordTypeId()){

	    		if(o.HasOpportunityLineItem) {

	    			for(OpportunityLineItem oppLi : o.OpportunityLineItems) {
	    				currentOpportunityLineItems.add(oppLi.PricebookEntry.ProductCode);
	    			}
	    		}

	    		for(PriceBookEntry pbEntry : o.Pricebook2.PricebookEntries) {

	    			if(pbEntry.ProductCode == SFProduct && !currentOpportunityLineItems.contains(SFProduct)) {
	    				OpportunityLineItem newOppLi = OpportunityUtilities.addOpportunityLineItem(o, pbEntry, 1);
	    				mapInsertOppLis.put(pbEntry.Id, newOppLi);
	    			}

	    			if(pbEntry.ProductCode == MSFProduct && !currentOpportunityLineItems.contains(MSFProduct)) {
	    				OpportunityLineItem newOppLi = OpportunityUtilities.addOpportunityLineItem(o, pbEntry, 1);
	    				mapInsertOppLis.put(pbEntry.Id, newOppLi);
	    			}

	    			if(pbEntry.ProductCode == APProduct && !currentOpportunityLineItems.contains(APProduct) && o.Number_of_Providers__c > 3) {
	    				Decimal q = o.Number_of_Providers__c - 3;
	    				OpportunityLineItem newOppLi = OpportunityUtilities.addOpportunityLineItem(o, pbEntry, q);
	    				mapInsertOppLis.put(pbEntry.Id, newOppLi);
	    			}
	    		}
	    	}
	    	insert mapInsertOppLis.values();
	    	currentOpportunityLineItems.clear();
    	}
    }
Any ideas of how this could be possible without a separate query?  Or any ideas of a better solution altogether?

Thanks in advance for your help!