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
Karthik Sundara RajKarthik Sundara Raj 

What is wrong with this Trigger?

Hi All,
I would like to map same data Vehicle Object to Service work order Object which have master-details relationship.I tried that code but it not working,Please find the code and correct in below:It is in bold and italic:

trigger ServiceLifeTimeValue on Service_Work_Order__c (after insert, after update)
{
    
    if (Trigger.isAfter && (Trigger.isInsert || Trigger.isUpdate))
    {
        Set<String> setStrVINNumber = new Set<String>();
        Set<String> setStrVINNumber1 = new Set<String>();
        Map<String, Decimal> mapStrVINNumToTotal = new Map<String, Decimal>();
        List<Vehicle__c> lstVehicleToUpdate = new List<Vehicle__c>();
        
        // iterate over SWOs and collect VIN numbers
        for(Service_Work_Order__c objSWO : Trigger.New)
        {
            setStrVINNumber.add(objSWO.Workorder_VIN_Number__c);
        }
        
        // calculate sum
        for(AggregateResult objAR : [   SELECT SUM(Test_Total_Work_Order_Cost_ExGST__c) total,  Workorder_VIN_Number__c VIN
                                        FROM Service_Work_Order__c 
                                        WHERE Workorder_VIN_Number__c IN :setStrVINNumber GROUP BY Workorder_VIN_Number__c] )
        {
            mapStrVINNumToTotal.put((String)objAR.get('VIN'),(Decimal)objAR.get('total'));
        }
        
        // iterate over matching vehicles and update the total amount.
        for(Vehicle__c objVehicle : [   SELECT Id,Test_service_life_time_value__c ,Name
                                        FROM Vehicle__c 
                                        WHERE Name IN :setStrVINNumber])
        {
        
            if(mapStrVINNumToTotal.containsKey(objVehicle.Name))
            {
                objVehicle.Test_service_life_time_value__c =  mapStrVINNumToTotal.get(objVehicle.Name);
                lstVehicleToUpdate.add(objVehicle);
                
              /*/////////////////////////////////////////////////////////////*/
                       for(Vehicle__c objVehicle1 : [   SELECT Id,Test_service_life_time_value__c ,Name
                                        FROM Vehicle__c 
                                        WHERE Name IN :setStrVINNumber])
        {
        setStrVINNumber1.add(objVehicle1.Id);
       
              
              
              for(Vehicle_Ownership__c objAVO : [   SELECT Id,VIN__c,Test_Roll__c ,Name
                                        FROM Vehicle_Ownership__c 
                                        WHERE VIN__c IN :setStrVINNumber1 AND Customer_Vehicle_Relationship_Status__c='Active'])
             
                  {                      
                  objAVO.Test_Roll__c=objVehicle1.Test_service_life_time_value__c ;
                //lstVehicleToUpdate.add(objVehicle);       }                
                     }
                /*/////////////////////////////////////////////////////////////*/

                     }
        }
        
        // update vehicles - If any exception occurs, it throw an error - so passed 'true' 
        if(lstVehicleToUpdate.size() > 0 ) // check list size before DML
        {
            DataBase.Update(lstVehicleToUpdate, true);
        }                    
            
              
        }
    }
}
mritzimritzi
Following piece of code raises suspision, have a look
(on having first look at the bold text, it seems fine)
 
for(AggregateResult objAR : [   SELECT SUM(Test_Total_Work_Order_Cost_ExGST__c) total,  Workorder_VIN_Number__c VIN
                                        FROM Service_Work_Order__c 
                                        WHERE Workorder_VIN_Number__c IN :setStrVINNumber GROUP BY Workorder_VIN_Number__c] )
        {
            mapStrVINNumToTotal.put(String.valueOf(objAR.get('VIN')),Decimal.valueOf(objAR.get('total')));
        }
        
        // iterate over matching vehicles and update the total amount.
        for(Vehicle__c objVehicle : [   SELECT Id,Test_service_life_time_value__c ,Name
                                        FROM Vehicle__c 
                                        WHERE Name IN :setStrVINNumber])
        {
        
            if(mapStrVINNumToTotal.containsKey(objVehicle.Name))
You are storing  Workorder_VIN_Number__c in Map as Key and then in the last line, you are comparing that VIN with Vehicle Name.
(That may be the issue, if Name field in Vehicle__c object is not an auto number field. Because then, you are comparing a number with name which won't match)
Check it.

Moreover i have changed following line in the code
 mapStrVINNumToTotal.put((String)objAR.get('VIN'),(Decimal)objAR.get('total'));

Let me know what happens next.
 
Karthik Sundara RajKarthik Sundara Raj
Hi mritzi,
Thanks for you reply,The problem is that point.Let me Explain Full secnario.
Sum of all objSWO's Test_Total_Work_Order_Cost_ExGST__c suppose to map with ObjVechicle's Test_service_life_time_value__c.It is working well,But I want to get map with ObjAVO's objAVO.Test_Roll__c.
Hint:ObjVechicle(Master) and ObjAVO(Detail)
mritzimritzi
Are you sure that following line evaluates to true.
if(mapStrVINNumToTotal.containsKey(objVehicle.Name))

If this line is not evaluating to true then logic inside this condition won't execute

Consider using LIST, as SET is an unordered collection of elements, and soql result may be jumbled.

In following code:
for(Vehicle__c objVehicle1 : [   SELECT Id,Test_service_life_time_value__c ,Name
                FROM Vehicle__c 
                WHERE Name IN :setStrVINNumber])
{
	setStrVINNumber1.add(objVehicle1.Id);
	for(Vehicle_Ownership__c objAVO : [   SELECT Id,VIN__c,Test_Roll__c ,Name
                    FROM Vehicle_Ownership__c 
                    WHERE VIN__c IN :setStrVINNumber1 AND Customer_Vehicle_Relationship_Status__c='Active'])
         
	{                      
		objAVO.Test_Roll__c=objVehicle1.Test_service_life_time_value__c ;
		//lstVehicleToUpdate.add(objVehicle);       }                
                }
		/*/////////////////////////////////////////////////////////////*/
            }

Suppose there are 5 records in Vehicle__c and each has 2 related records in Vehicle_Ownership__c
Iteration one:
setStrVINNumber1.size() == 1 ->next loop runs twice, and updates test_roll__c field on both these entries
Iteration two:
setStrVINNumber1.size() == 2 ->next loop runs four times, and updates test_roll__c field on all four entries, overwriting two fields of previous iteration
Iteration three:
setStrVINNumber1.size() == 3 ->next loop runs six times, and updates test_roll__c field on all six entries, overwriting four fields of previous iteration
Iteration four:
setStrVINNumber1.size() == 4 ->next loop runs eight times, and updates test_roll__c field on all eight entries, overwriting six fields of previous iteration
Iteration five:
setStrVINNumber1.size() == 5 ->next loop runs ten times, and updates test_roll__c field on all ten entries, overwriting eight fields of previous iteration

Only the last two records on last iteration would be mapped correctly.

Hope, that this is of some help.
(Tell me if i made mistake in understanding your case)

As a sidenote, always print values in loop using System.debug to check that correct values were passed.


Hit LIKE if this answer helps you in anyway, Select it as Best Answer if it solves your problem
Karthik Sundara RajKarthik Sundara Raj
Hi Mritzi,
When you write the following code you get only one record always:
 SELECT Id,VIN__c,Test_Roll__c ,Name FROM Vehicle_Ownership__c WHERE VIN__c IN :setStrVINNumber1 ANDCustomer_Vehicle_Relationship_Status__c='Active'.
So no need to worry about loops.I hope now that you understand my requirement.

Thanks for quick response.

                   
                   
mritzimritzi
I am still not convinced that this line will fetch only one record (assuming that one vehicle__c record is associated with only one Vehicle_Relationship_Status__c record)
because this line fetches all those Vehicle_Relationship_Status records whose VIN__c is present in setStrVINNumber1. And in the very second iteration, this set will have two IDs

Your best bet is to place System.debug statement below each of these assigment statements to see what values are being fetched and how many times this loop is executing.

Something like this:
if(mapStrVINNumToTotal.containsKey(objVehicle.Name))
{
    Sytem.debug('if block '+ObjVehicle.Name);
                objVehicle.Test_service_life_time_value__c =  mapStrVINNumToTotal.get(objVehicle.Name);
                lstVehicleToUpdate.add(objVehicle);
                
              /*/////////////////////////////////////////////////////////////*/
                for(Vehicle__c objVehicle1 : [   SELECT Id,Test_service_life_time_value__c ,Name
                    FROM Vehicle__c 
                    WHERE Name IN :setStrVINNumber])
				{
					setStrVINNumber1.add(objVehicle1.Id);
                    system.debug(setStrVINNumber1.size());
					for(Vehicle_Ownership__c objAVO : [   SELECT Id,VIN__c,Test_Roll__c ,Name
                        FROM Vehicle_Ownership__c 
                        WHERE VIN__c IN :setStrVINNumber1 AND Customer_Vehicle_Relationship_Status__c='Active'])
             
					{                      
						objAVO.Test_Roll__c=objVehicle1.Test_service_life_time_value__c ;
                        system.debug(objAVO.Name+ ' '+objAVO.Test_Roll__c+' '+objVehicle1.Id);
						//lstVehicleToUpdate.add(objVehicle);       }                
                    }
						/*/////////////////////////////////////////////////////////////*/
                }
			}
        
			// update vehicles - If any exception occurs, it throw an error - so passed 'true' 
			if(lstVehicleToUpdate.size() > 0 ) // check list size before DML
			{
				DataBase.Update(lstVehicleToUpdate, true);
			}

Hope it helps