function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
pmozz01pmozz01 

Trigger - would appreciate any help!

Hi All,

 

I am at the end of my patience with myself here, cause I cannot figure out what I am missing. 

 

This is a custom object, Work Order, that has a look up to an Opportunity.  There can be many Work Orders related to the same opportunity.

 

Trigger fires when

  • the Work Order stage field is updated to either one of the closed values;
  • if all of the Work Orders related to that opportunity are closed, then update the opportunity stage, if not, do nothing.

I can get this to save, run the test, but it never updates anything.  I have changed this code so many times, I have no idea where I am screwing up and would appreciate some pointer.

 

At present - I am getting an error on line 24:         Map <ID, Opportunity> updateOpps = new Map <ID, Opportunity> ([SELECT id, stageName, (select ID, Opportunity__c from Work_Orders__r)
        from Opportunity where id in :affectedOpps]);

 

Error reads:  IN Operator must be used with iterable expression.

 

I am stil very much a beginner, so please be explicit if you are telling me something I need to do:)

 

Thanks!!!!

 

 

Trigger CheckOpportunityWorkorders on Work_Order__c (after insert, after update) {

   set<id> oppids = new set<id>();

     	
	    if(Trigger.isInsert || Trigger.isUpdate)
   		    	for (Work_Order__c wo: Trigger.new) {
            if (wo.stage__c == 'Work Order Closed - Quickbooks' ||  wo.stage__c == 'Job Completed' ){
      		oppids.add(wo.Opportunity__c);
      		String oid = wo.Opportunity__c;
      		
 	    if(oppIDs .size() > 0) {
 
  Map <ID, Opportunity> affectedOpps = new Map <ID, Opportunity> ([select id, stageName, (select id, Opportunity__c from Work_Orders__r 
  	where Work_Order__c.stage__c != 'Work Order Closed - Quickbooks' OR stage__c != 'Job Completed') 
	from Opportunity where id in :oppids]);

	
	System.debug('Opportunity: '+affectedOpps.get(oid).StageName);     		
   

      	if (affectedOpps .size()==0){	
		
		Map <ID, Opportunity> updateOpps = new Map <ID, Opportunity> ([SELECT id, stageName, (select ID, Opportunity__c from Work_Orders__r)
		from Opportunity where id in :affectedOpps]);
		String upID = wo.Opportunity__c;
		 	if(updateOpps.containskey(upID))
		 	
 //       	d = updateOpps.get(upID);
				 
			upID.stageName = 'Job Complete';
			
			update updateOpps;
      	}
		
		
 
}
}
}
}

 

public with sharing class testCheckOpportunityWorkOrders {

    static testMethod void myTest() {

		Account a = new Account(name='test', type = 'customer');
		insert a;
       //Insert a test opportunity
		
       Opportunity o = new Opportunity();
       o.AccountId = a.id;
       o.StageName='Target';
       o.Name='test';
       o.closeDate=Date.today();

       insert o;
       
       system.debug('opportunity id' + Opportunity.ID);
       
         //Insert a Work_Order

       Work_Order__c wo = new Work_Order__c();

       wo.Opportunity__c = o.id;
       
       wo.Stage__c = 'Job Completed';
       wo.Close_Date_WO__c=Date.today();

  
       insert wo;
 		system.debug('workorder' + wo.ID);
 		      
       Work_Order__c ww = new Work_Order__c();

       ww.Opportunity__c = o.id;
       
       ww.Stage__c = 'Return Trip Needed';
       ww.Close_Date_WO__c=Date.today();
  
       insert ww;
       
       ww.Stage__c = 'Work Order Closed - Quickbooks';
       update ww;
       
       wo.Stage__c = 'Work Order Closed - Quickbooks';
       update wo;
       
		system.debug('workorder' + ww.ID + ww.Stage__c);
		
       Opportunity updated_Opportunity = [SELECT ID, WO_Count__c FROM Opportunity WHERE Id = :o.Id];

       //Verify that the values of the opp were changed by the trigger
       
  //System.assertEquals(opportunity, [Select WO_Count__c from Opportunity Where ID = :o.ID].wo_count__c);
  
 
     }
static testMethod void testBulkInsert() {

  List<Opportunity> opps = new List<Opportunity>();
  
 }

}

 

 

 

EtienneCoutantEtienneCoutant

Hi,

 

I noticed that affectedOpps is a Map, not a list of Id.

Can you try to replace from Opportunity where id in :affectedOpps by from Opportunity where id in :affectedOpps.keySet()

 

Hope that helps.

pmozz01pmozz01

Thank you for your response.  I was now able to save, but I am still not getting the field updated.  I cannot figure out from the test either what it going wrong.  The test shows on the final debug that the opportunity stage remains set at target.

 

Here's my trigger and test:

 

Trigger CheckOpportunityWorkorders on Work_Order__c (after insert, after update) {

   set<id> oppids = new set<id>();

     	
	    if(Trigger.isInsert || Trigger.isUpdate)
   		    	for (Work_Order__c wo: Trigger.new) {
            if (wo.stage__c == 'Work Order Closed - Quickbooks' ||  wo.stage__c == 'Job Completed' ){
      		oppids.add(wo.Opportunity__c);
      		String oid = wo.Opportunity__c;
      		
 	    if(oppIDs .size() > 0) {
 
  Map <ID, Opportunity> affectedOpps = new Map <ID, Opportunity> ([select id, stageName, (select id, Opportunity__c from Work_Orders__r 
  	where Work_Order__c.stage__c != 'Work Order Closed - Quickbooks' OR stage__c != 'Job Completed') 
	from Opportunity where id in :oppids]);

	Opportunity d = null;
	
	System.debug('Opportunity: '+affectedOpps.get(oid).StageName);     		
   

      	if (affectedOpps .size()==0){	

 	      	
		Map <ID, Opportunity> updateOpps = new Map <ID, Opportunity> ([SELECT id, stageName, (select ID, Opportunity__c from Work_Orders__r)
		 from Opportunity where id in :affectedOpps.keySet()]);
		

			String upID = wo.Opportunity__c;
		 	if(updateOpps.containskey(upID))

	      	d = updateOpps.get(upID);
	      	
				 
			d.StageName = 'Job Complete';
			updateOpps.put(upID, d);
			
			update d;
      	}
		
		
 
}
}
}
}

 

public with sharing class testCheckOpportunityWorkOrders {

    static testMethod void myTest() {

		Account a = [select Id, account.OwnerId, account.Name from Account limit 1];
		system.debug('Account' + Account.ID);
       //Insert a test opportunity
		
       Opportunity o = new Opportunity();
       o.AccountId = a.id;
       o.OwnerID = a.OwnerId;
       o.StageName='Target';
       o.Name='test';
       o.closeDate=Date.today();

       insert o;
       
       system.debug('opportunity id' + Opportunity.ID);
       
         //Insert a Work_Order

       Work_Order__c wo = new Work_Order__c();

       wo.Opportunity__c = o.id;
       
       wo.Stage__c = 'Job Completed';
       wo.Close_Date_WO__c=Date.today();

  
       insert wo;
 		system.debug('workorder' + wo.ID);
 		      
       Work_Order__c ww = new Work_Order__c();

       ww.Opportunity__c = o.id;
       
       ww.Stage__c = 'Return Trip Needed';
       ww.Close_Date_WO__c=Date.today();
  
       insert ww;
       
       ww.Stage__c = 'Work Order Closed - Quickbooks';
       update ww;
       
       wo.Stage__c = 'Work Order Closed - Quickbooks';
       update wo;
       
		system.debug('workorder' + ww.ID + ww.Stage__c);
		
       Opportunity updated_Opportunity = [SELECT ID, StageName FROM Opportunity WHERE Id = :o.Id];

       //Verify that the values of the opp were changed by the trigger
       
   System.debug('updated_Opportunity' + o.StageName);
  
 
     }
static testMethod void testBulkInsert() {

  List<Opportunity> opps = new List<Opportunity>();
  
 }

}

 

EtienneCoutantEtienneCoutant

Hi,

 

Can you try the following:

 

 

Trigger CheckOpportunityWorkorders on Work_Order__c (after insert, after update) {

    List<Opportunity> opportunitiesToUpdate = new List<Opportunity>();
	
    Set<Id> oppIds = new Set<Id>();
	
    //Store Opportunity Id for each Work_Order__c
    for(Work_Order__c workOrder : Trigger.new)
    {
       if (workOrder.stage__c == 'Work Order Closed - Quickbooks' ||  workOrder.stage__c == 'Job Completed' ) oppIds.add(workOrder.Opportunity__c);
    }

	if(oppIds.size() > 0)
	{
		//Retrieve all the Opportunities and related Work Orders regardless the status
		List<Opportunity> opportunities = new List<Opportunity> ([SELECT Id, StageName, (SELECT Id, Opportunity__c FROM Work_Orders__r) FROM Opportunity WHERE Id IN :oppIds]);

		for (Opportunity opportunity : opportunities) {

			Boolean allCompleted = true;
			for(Work_Order__c workOrder:opportunity.Work_Orders__r)
			{
				if(workOrder.stage__c != 'Work Order Closed - Quickbooks' || workOrder.stage__c != 'Job Completed'){
					allCompleted = false;
					break;
				}
			}
			
			if(allCompleted) 
			{
				opportunity.StageName = 'Job Complete';
				opportunitiesToUpdate.add(opportunity);
			}
		}
	}
	
	if(opportunitiesToUpdate.size() > 0) update opportunitiesToUpdate;
}

 

 

 

pmozz01pmozz01

Thanks for spending so much time on this!  I really didn't mean for anyone to work so hard. Unfortunately, it still won't update, but I will work on it this weekend and see if I can get it from here.

EtienneCoutantEtienneCoutant

Hi,

 

No problem at all. I am glad if that can help.

I saw 2 errors in the code i gave you. If you update the following that should work:

 

 

 

List<Opportunity> opportunities = new List<Opportunity> ([SELECT Id, StageName, (SELECT Id, Opportunity__c FROM Work_Orders__r) FROM Opportunity WHERE Id IN :oppIds]);

BY


List<Opportunity> opportunities = new List<Opportunity> ([SELECT Id, StageName, (SELECT Id, stage__c, Opportunity__c FROM Work_Orders__r) FROM Opportunity WHERE Id IN :oppIds]);

  and

 

 

if(workOrder.stage__c != 'Work Order Closed - Quickbooks' || workOrder.stage__c != 'Job Completed')

BY

if(workOrder.stage__c != 'Work Order Closed - Quickbooks' && workOrder.stage__c != 'Job Completed')

 

 

 

pmozz01pmozz01

Thanks, I had caught the first one, but did not make the second change. This is working in that, if any 1 workorder related to an opportunity is changed to Job Completed or Closed Quickbooks, but I need to have it check for all of the workorders associated with a single opportunity to be either Job Completed or Closed Quickbooks before the opportunity is updated.  Do you think that I need another list after the 'allcompleted = true to ge the opportunity ids of those workorders that were all completed?

EtienneCoutantEtienneCoutant

Hi,

 

The code I sent you already has this behavior. It will only update the Opportunity if all the related Work Order are either Job Completed or Closed Quickbooks.

It actually takes it the other way around and will not update the opportunity if one Work Order is neither Job Completed, nor Closed Quickbooks. But the result is the same.

 

Hope that answers your question.