+ Start a Discussion
Smike25Smike25 

Stuck trying to bulkifying code from prior developer

Hello Everyone, 

I've been trying to work on code that was left to our ORG by a developer who is no longer supporting us.  Not being too familiar with Apex, this is proving to be a daunting task for us and blocking us from implementing the triggers/classes that we've been working on.  I know it's a lengthy bit of code, but if someone could offer some assistance we'd be really grateful.  Currently we're getting the SQOL 101 errors with this code:
 
trigger UpdateTruckInventoryByOpportunity_Trgr on Opportunity (before update,before insert,after update, after insert, after delete, after undelete) {
    List<Truck_Inventory__c> lstTruck2Update = new List<Truck_Inventory__c>();
    
    Set<String> rt2bypass = new Set<String>{'Used Truck Quote','Accessory Order'};     
    Map<Id,RecordType> usedTruckQuoteRT = new Map<Id,RecordType>([Select SobjectType,Name,Id From RecordType Where SobjectType ='Opportunity' and Name in :rt2bypass]);
    
    RecordType usedRT = [Select SobjectType,Name,Id From RecordType Where SobjectType ='Truck_Inventory__c' and Name = 'Used' LIMIT 1];
    Map<Id,Truck_Inventory__c> mapNotUsedTruckInv = new Map<Id,Truck_Inventory__c>([Select Id,RecordTypeId From Truck_Inventory__c Where RecordTypeId =:usedRT.Id]);
    Set<String> setTruckInventories = new Set<String>();
    
    if(Trigger.isAfter){
        if(Trigger.isUpdate){
            for(Opportunity opp:Trigger.new){
                if(usedTruckQuoteRT.get(opp.RecordTypeId)==null){
                    

                     if(opp.Truck_Inventory__c!=null){
                        if(opp.StageName == 'Lost Deal - Truck Built' || opp.StageName == 'Lost Deal - Truck Not Built'){
                            lstTruck2Update.add(new Truck_Inventory__c(Id=opp.Truck_Inventory__c,Sold__c=false, Related_Quote_SO__c=null, Customer__c = null));
                        }else if(opp.StageName == 'Sales Order - Pending' || opp.StageName == 'Sales Order - Complete'){
                            lstTruck2Update.add(new Truck_Inventory__c(Id = opp.Truck_Inventory__c,Customer__c = opp.AccountId, Sold__c=true,Related_Quote_SO__c=opp.Id));
                        }else{
                            lstTruck2Update.add(new Truck_Inventory__c(Id=opp.Truck_Inventory__c, Sold__c=true,Related_Quote_SO__c=opp.Id));
                        }
                    }
                    
                    Opportunity oldOpp = Trigger.oldmap.get(opp.Id);
                    if(oldOpp.Truck_Inventory__c!=null && oldOpp.Truck_Inventory__c != opp.Truck_Inventory__c){
                        lstTruck2Update.add(new Truck_Inventory__c(Id=oldOpp.Truck_Inventory__c,Sold__c=false, Related_Quote_SO__c=null, Customer__c = null));
                    }
                    
                }
            }
        }else if(Trigger.isInsert || Trigger.isUndelete){
            for(Opportunity opp:Trigger.new){
                if(usedTruckQuoteRT.get(opp.RecordTypeId)==null) {
                    if(opp.Truck_Inventory__c!=null){         
                        lstTruck2Update.add(new Truck_Inventory__c(Id=opp.Truck_Inventory__c, Sold__c=true,Related_Quote_SO__c=opp.Id));
                    }
                }
            }
        }else if(Trigger.isDelete){
            for(Opportunity opp:Trigger.old){
                if(usedTruckQuoteRT.get(opp.RecordTypeId)==null){
                    if(opp.Truck_Inventory__c!=null){
                        lstTruck2Update.add(new Truck_Inventory__c(id=opp.Truck_Inventory__c,Sold__c=false, Related_Quote_SO__c=null));
                    }
                }
            }
        }
        if(!lstTruck2Update.isEmpty()){
            update lstTruck2Update;
        }
    
    }
    else{
        
        for(Opportunity opp:Trigger.new){
            if(usedTruckQuoteRT.get(opp.RecordTypeId)==null) {
                if(opp.Truck_Inventory__c!=null){
                    if(!mapNotUsedTruckInv.containsKey(opp.Truck_Inventory__c)){    
                        setTruckInventories.add(opp.Truck_Inventory__c);
                    }          
                }
            }
        }
        
        if(!setTruckInventories.isEmpty()){
            Map<String,String> mTruckInParent = new Map<String,String>();
            for(Truck_Inventory__c ti :[Select Truck__c, Id From Truck_Inventory__c where Id in :setTruckInventories]){
                mTruckInParent.put(ti.Id, ti.Truck__c);
            }
         
            for(Opportunity opp:Trigger.new){
                if(usedTruckQuoteRT.get(opp.RecordTypeId)==null) {
                    opp.Truck__c = mTruckInParent.get(opp.Truck_Inventory__c);
                }
            }
        }
    }
}

 
Best Answer chosen by Smike25
pigginsbpigginsb
One thing that stands out right away is the fact that RecordTypes are being queried every time this trigger fires, and it will certainly fire twice per update or insert. An approach that we will typically take when we need to query things like RecordTypes or any data item that is not going to change over the course of the execution, or is not dependent on information from the trigger records, is to use static helper class properties and Lazy Initialization to provide these items.

Consider a helper class such as the one below (which is based on your trigger). The UsedTruckQuoteRTMap is a static property, which once populated remains available for the duration of your transaction. The GetUsedTruckQuoteRTMap() method populates this map the first time it's called, but each time it's called after that it will simply return the map. The same pattern can be applied to the UsedRT value in your trigger also, as is shown in the helper class code.
public class RecordTypeHelper {
	// private map property, returned by the "Get" method below
	private static Map<Id, RecordType> UsedTruckQuoteRTMap;
	
	// this method will return the map, and a call to this method can be treated as the map itself
	public static Map<Id, RecordType> GetUsedTruckQuoteRTMap() {
		
		// this is the lazy initialization part, if the property is null it will be populated
		if (UsedTruckQuoteRTMap == null) {
			Set<String> rt2bypass = new Set<String>{'Used Truck Quote','Accessory Order'};
			UsedTruckQuoteRTMap = new Map<Id,RecordType>([Select SobjectType,Name,Id From RecordType Where SobjectType ='Opportunity' and Name in :rt2bypass]);
		}
		
		// the map is then returned, if already populated it will simply be returned
		return UsedTruckQuoteRTMap;
	}
	
	// same pattern can be applied to the Used Truck Inventory RecordType...
	private static RecordType UsedTruckInvType;
	
	public static RecordType GetUsedTruckInvType() {
		if (UsedTruckInvType == null)
			UsedTruckInvType = [Select SobjectType,Name,Id From RecordType Where SobjectType ='Truck_Inventory__c' and Name = 'Used' LIMIT 1]
		
		return UsedTruckInvType;
	}
}
Once you have this class in place, you can replace some lines of code in your trigger, which will reduce your SOQL query count if the trigger fires more than once in a transaction.

Lines 4 and 5 in your trigger above can be replaced with the following,
Map<Id,RecordType> usedTruckQuoteRT = RecordTypeHelper.GetUsedTruckQuoteRTMap();
and Line 7 can be replaced with this line,
RecordType usedRT = RecordTypeHelper.GetUsedTruckInvType();
Without knowing more about your system, I could add that this same lazy initialization pattern can be used to replace the query in line 8 also.

This is one approach that can be taken to reduce the number of SOQL queries executed in a single transaction. It may not get you past your current limit error, but you may find that there are other triggers querying for stable records such as record types or profile ids, which could also be improved by this pattern.

The thing about these "too many SOQL" errors is that the query that causes the error may not be the problem at all. It may be that it simply had the misfortune of being the 101st query to execute, like the straw that broke the camel's back.

If you can capture a debug log of the execution and search for all SOQL statements, you might find that certain ones are being called repeatedly. It may be that better query management is needed, or that you are needlessly entering a loop and the fix would be to avoid the loop altogether.

I hope this gives you some insight and another tool to work with. I look forward to hearing how it goes!

 

All Answers

ericmonteericmonte

Can you paste the full line error and what line number you are hitting the error?! I'm going to quickly go make and make sense of the code and will get back to you.
pigginsbpigginsb
One thing that stands out right away is the fact that RecordTypes are being queried every time this trigger fires, and it will certainly fire twice per update or insert. An approach that we will typically take when we need to query things like RecordTypes or any data item that is not going to change over the course of the execution, or is not dependent on information from the trigger records, is to use static helper class properties and Lazy Initialization to provide these items.

Consider a helper class such as the one below (which is based on your trigger). The UsedTruckQuoteRTMap is a static property, which once populated remains available for the duration of your transaction. The GetUsedTruckQuoteRTMap() method populates this map the first time it's called, but each time it's called after that it will simply return the map. The same pattern can be applied to the UsedRT value in your trigger also, as is shown in the helper class code.
public class RecordTypeHelper {
	// private map property, returned by the "Get" method below
	private static Map<Id, RecordType> UsedTruckQuoteRTMap;
	
	// this method will return the map, and a call to this method can be treated as the map itself
	public static Map<Id, RecordType> GetUsedTruckQuoteRTMap() {
		
		// this is the lazy initialization part, if the property is null it will be populated
		if (UsedTruckQuoteRTMap == null) {
			Set<String> rt2bypass = new Set<String>{'Used Truck Quote','Accessory Order'};
			UsedTruckQuoteRTMap = new Map<Id,RecordType>([Select SobjectType,Name,Id From RecordType Where SobjectType ='Opportunity' and Name in :rt2bypass]);
		}
		
		// the map is then returned, if already populated it will simply be returned
		return UsedTruckQuoteRTMap;
	}
	
	// same pattern can be applied to the Used Truck Inventory RecordType...
	private static RecordType UsedTruckInvType;
	
	public static RecordType GetUsedTruckInvType() {
		if (UsedTruckInvType == null)
			UsedTruckInvType = [Select SobjectType,Name,Id From RecordType Where SobjectType ='Truck_Inventory__c' and Name = 'Used' LIMIT 1]
		
		return UsedTruckInvType;
	}
}
Once you have this class in place, you can replace some lines of code in your trigger, which will reduce your SOQL query count if the trigger fires more than once in a transaction.

Lines 4 and 5 in your trigger above can be replaced with the following,
Map<Id,RecordType> usedTruckQuoteRT = RecordTypeHelper.GetUsedTruckQuoteRTMap();
and Line 7 can be replaced with this line,
RecordType usedRT = RecordTypeHelper.GetUsedTruckInvType();
Without knowing more about your system, I could add that this same lazy initialization pattern can be used to replace the query in line 8 also.

This is one approach that can be taken to reduce the number of SOQL queries executed in a single transaction. It may not get you past your current limit error, but you may find that there are other triggers querying for stable records such as record types or profile ids, which could also be improved by this pattern.

The thing about these "too many SOQL" errors is that the query that causes the error may not be the problem at all. It may be that it simply had the misfortune of being the 101st query to execute, like the straw that broke the camel's back.

If you can capture a debug log of the execution and search for all SOQL statements, you might find that certain ones are being called repeatedly. It may be that better query management is needed, or that you are needlessly entering a loop and the fix would be to avoid the loop altogether.

I hope this gives you some insight and another tool to work with. I look forward to hearing how it goes!

 
This was selected as the best answer
Smike25Smike25

ericmonte,

Error is coming at line 18, column 1.  If you want me to flush out what this trigger is suppose to accomplish let me know! And thank you for taking a look!
Error at line 18


bjpiggins,

First, thank you for taking the time to write out some updated code for us to try.  As someone completely new to Apex coding, this looks like a daunting task, but i'll go over what you posted and look up online what I can find out about implenting this.  It's been a major set back for us losing our support on this, so thank you.  I've got the debug log handy if you'd like/want to review it if it would help you understand any better about what is going on.

 

Smike25Smike25
bjpiggins, 

When I go to save the RecordTypeHelper class, I get a compile error: "Compile Error: unexpected token: 'return' at line 25 column 8"
pigginsbpigginsb
Sorry about that, I left a semicolon off the end of line 23. It should be...
UsedTruckInvType = [Select SobjectType,Name,Id From RecordType Where SobjectType ='Truck_Inventory__c' and Name = 'Used' LIMIT 1];
...including the semicolon at the end.
 
Smike25Smike25
Added in the class and replaced the lines 4, 5, and 7.  Tests passed successfully.  Looking at breaking down line 8 like you said
 
Map<Id,Truck_Inventory__c> mapNotUsedTruckInv = new Map<Id,Truck_Inventory__c>([Select Id,RecordTypeId From Truck_Inventory__c Where RecordTypeId =:usedRT.Id]);

Truck_Inventory__c is our custom object where we house our actualy inventory.  This gets placed inside our opportunities and depletes our available to sell inventory.  We have 3 record types for Truck Inventory... "Stock" (012i0000001IXAo), "Custom" (012i0000001IXHg) and "Used" (012i0000001IXAt).

I would have assumed that I would break down line 8 above by doing what you did to lines 4&5, but didn't we already account for the "Used" record type with 
 
private static RecordType UsedTruckInvType;
	
	public static RecordType GetUsedTruckInvType() {
		if (UsedTruckInvType == null)
			UsedTruckInvType = [Select SobjectType,Name,Id From RecordType Where SobjectType ='Truck_Inventory__c' and Name = 'Used' LIMIT 1]
		
		return UsedTruckInvType;

Not quite sure where to proceed
pigginsbpigginsb
Your line 8 is used to populate a map, based on Truck_Inventory__c records where the RecordTypeId is the usedRT.Id value that is obtained in your line 7.
Map<Id,Truck_Inventory__c> mapNotUsedTruckInv = new Map<Id,Truck_Inventory__c>([Select Id,RecordTypeId From Truck_Inventory__c Where RecordTypeId =:usedRT.Id]);
If you wanted to use the helper class and lazy initialization for this, you would follow the same pattern of having a private static Map<Id, Truck_Inventory__c> property, and a public method that returns the map.
private static Map<Id,Truck_Inventory__c> UsedTruckInvMap;
	
public static Map<Id,Truck_Inventory__c> GetUsedTruckInvMap() {
	if (UsedTruckInvMap == null)
		UsedTruckInvMap = new Map<Id,Truck_Inventory__c>([Select Id,RecordTypeId From Truck_Inventory__c Where RecordTypeId = :GetUsedTruckInvType().Id]);

	return UsedTruckInvMap;
}
You may notice that instead of referencing the Used Record Type directly, this method is also using the GetUsedTruckInvType() call. That way if the RecordType property has already been populated it will be returned without being requeried.
 
Smike25Smike25
public class RecordTypeHelper {
    // private map property, returned by the "Get" method below
    private static Map<Id, RecordType> UsedTruckQuoteRTMap;
    
    // this method will return the map, and a call to this method can be treated as the map itself
    public static Map<Id, RecordType> GetUsedTruckQuoteRTMap() {
        
        // this is the lazy initialization part, if the property is null it will be populated
        if (UsedTruckQuoteRTMap == null) {
            Set<String> rt2bypass = new Set<String>{'Used Truck Quote','Accessory Order'};
            UsedTruckQuoteRTMap = new Map<Id,RecordType>([Select SobjectType,Name,Id From RecordType Where SobjectType ='Opportunity' and Name in :rt2bypass]);
        }
        
        // the map is then returned, if already populated it will simply be returned
        return UsedTruckQuoteRTMap;
    }
    
    // same pattern can be applied to the Used Truck Inventory RecordType...
    private static RecordType UsedTruckInvType;
    
    public static RecordType GetUsedTruckInvType() {
        if (UsedTruckInvType == null)
            UsedTruckInvType = [Select SobjectType,Name,Id From RecordType Where SobjectType ='Truck_Inventory__c' and Name = 'Used' LIMIT 1];
        
        return UsedTruckInvType;
    }
    
    private static Map<Id,Truck_Inventory__c> UsedTruckInvMap;
    
public static Map<Id,Truck_Inventory__c> GetUsedTruckInvMap() {
    if (UsedTruckInvMap == null)
        UsedTruckInvMap = new Map<Id,Truck_Inventory__c>([Select Id,RecordTypeId From Truck_Inventory__c Where RecordTypeId = :GetUsedTruckInvType().Id]);

    return UsedTruckInvMap;
}
}

So that is the current RecordTypeHelper class based on the above.  I'm trying to replace the line 8 in the trigger:
Map<Id,Truck_Inventory__c> mapNotUsedTruckInv = new Map<Id,Truck_Inventory__c>([Select Id,RecordTypeId From Truck_Inventory__c Where RecordTypeId =:usedRT.Id]);

Im assuming it would be replaced similarly as " Map<Id,RecordType> usedTruckQuoteRT = RecordTypeHelper.GetUsedTruckQuoteRTMap();"
pigginsbpigginsb
That's right. The new static method returns the same map that is currently being assigned to your variable in line 8, so instead of querying for the map in line 8, you can assign the return value from the method call.

As a side note... I'm not sure why the map would be called "mapNotUsedTruckInv" when the query returns Truck Inventory records where the RecordType is the "Used" record type Id. It seems to be an inaccurate name, but the method will return the same map as was found in the existing code.
Smike25Smike25
Using the above RecordTypeHelper class, I'm getting a compiule error: Method does not exist or incorrect signature: RecordTypeHelper.UsedTruckInnMap() at line 7 column 53 currently:
 
trigger UpdateTruckInventoryByOpportunity_Trgr on Opportunity (before update,before insert,after update, after insert, after delete, after undelete) {
    List<Truck_Inventory__c> lstTruck2Update = new List<Truck_Inventory__c>();
    
    Map<Id,RecordType> usedTruckQuoteRT = RecordTypeHelper.GetUsedTruckQuoteRTMap();
    RecordType usedRT = RecordTypeHelper.GetUsedTruckInvType();

    Map<Id,Truck_Inventory__c> mapNotUsedTruckInv = RecordTypeHelper.UsedTruckInvMap();
        
    Set<String> setTruckInventories = new Set<String>();
    
    if(Trigger.isAfter){
        if(Trigger.isUpdate){
            for(Opportunity opp:Trigger.new){
                if(usedTruckQuoteRT.get(opp.RecordTypeId)==null){
                    
               
                     if(opp.Truck_Inventory__c!=null){
                        if(opp.StageName == 'Lost Deal - Truck Built' || opp.StageName == 'Lost Deal - Truck Not Built'){
                            lstTruck2Update.add(new Truck_Inventory__c(Id=opp.Truck_Inventory__c,Sold__c=false, Related_Quote_SO__c=null, Customer__c = null));
                        }else if(opp.StageName == 'Sales Order - Pending' || opp.StageName == 'Sales Order - Complete'){
                            lstTruck2Update.add(new Truck_Inventory__c(Id = opp.Truck_Inventory__c,Customer__c = opp.AccountId, Sold__c=true,Related_Quote_SO__c=opp.Id));
                        }else{
                            lstTruck2Update.add(new Truck_Inventory__c(Id=opp.Truck_Inventory__c, Sold__c=true,Related_Quote_SO__c=opp.Id));
                        }
                    }
                    
                    Opportunity oldOpp = Trigger.oldmap.get(opp.Id);
                    if(oldOpp.Truck_Inventory__c!=null && oldOpp.Truck_Inventory__c != opp.Truck_Inventory__c){
                        lstTruck2Update.add(new Truck_Inventory__c(Id=oldOpp.Truck_Inventory__c,Sold__c=false, Related_Quote_SO__c=null, Customer__c = null));
                    }
                    
                }
            }
        }else if(Trigger.isInsert || Trigger.isUndelete){
            for(Opportunity opp:Trigger.new){
                if(usedTruckQuoteRT.get(opp.RecordTypeId)==null) {
                    if(opp.Truck_Inventory__c!=null){         
                        lstTruck2Update.add(new Truck_Inventory__c(Id=opp.Truck_Inventory__c, Sold__c=true,Related_Quote_SO__c=opp.Id));
                    }
                }
            }
        }else if(Trigger.isDelete){
            for(Opportunity opp:Trigger.old){
                if(usedTruckQuoteRT.get(opp.RecordTypeId)==null){
                    if(opp.Truck_Inventory__c!=null){
                        lstTruck2Update.add(new Truck_Inventory__c(id=opp.Truck_Inventory__c,Sold__c=false, Related_Quote_SO__c=null));
                    }
                }
            }
        }
        if(!lstTruck2Update.isEmpty()){
            update lstTruck2Update;
        }
    
    }
    else{
        
        for(Opportunity opp:Trigger.new){
            if(usedTruckQuoteRT.get(opp.RecordTypeId)==null) {
                if(opp.Truck_Inventory__c!=null){
                    if(!mapNotUsedTruckInv.containsKey(opp.Truck_Inventory__c)){    
                        setTruckInventories.add(opp.Truck_Inventory__c);
                    }          
                }
            }
        }
        
        if(!setTruckInventories.isEmpty()){
            Map<String,String> mTruckInParent = new Map<String,String>();
            for(Truck_Inventory__c ti :[Select Truck__c, Id From Truck_Inventory__c where Id in :setTruckInventories]){
                mTruckInParent.put(ti.Id, ti.Truck__c);
            }
         
            for(Opportunity opp:Trigger.new){
                if(usedTruckQuoteRT.get(opp.RecordTypeId)==null) {
                    opp.Truck__c = mTruckInParent.get(opp.Truck_Inventory__c);
                }
            }
        }
    }

 
pigginsbpigginsb
Your method is called GetUsedTruckInvMap(), but your code is trying to call UsedTruckInvMap() in line 7 above. You just need to call the method correctly.
Smike25Smike25
Updated and was successfully able to deploy the code, however immedately upon being able to deploy our ORG throws this error everytime an opportunity is saved

"UpdateTruckInventoryByOpportunity_Trgr: execution of BeforeUpdate caused by: System.TypeException: Cannot call test methods in non-test context External entry point Trigger.UpdateTruckInventoryByOpportunity_Trgr: line 15, column 1"
 
trigger UpdateTruckInventoryByOpportunity_Trgr on Opportunity (before update,before insert,after update, after insert, after delete, after undelete) {
    List<Truck_Inventory__c> lstTruck2Update = new List<Truck_Inventory__c>();
    
   Map<Id,RecordType> usedTruckQuoteRT = RecordTypeHelper.GetUsedTruckQuoteRTMap();
    RecordType usedRT = RecordTypeHelper.GetUsedTruckInvType();

    Map<Id,Truck_Inventory__c> mapNotUsedTruckInv = RecordTypeHelper.GetUsedTruckInvMap();
    
    Set<String> setTruckInventories = new Set<String>();
    
    if(Trigger.isAfter){
        if(Trigger.isUpdate){
            for(Opportunity opp:Trigger.new){
                if(usedTruckQuoteRT.get(opp.RecordTypeId)==null){
                    
 
                     if(opp.Truck_Inventory__c!=null){
                        if(opp.StageName == 'Lost Deal - Truck Built' || opp.StageName == 'Lost Deal - Truck Not Built'){
                            lstTruck2Update.add(new Truck_Inventory__c(Id=opp.Truck_Inventory__c,Sold__c=false, Related_Quote_SO__c=null, Customer__c = null));
                        }else if(opp.StageName == 'Sales Order - Pending' || opp.StageName == 'Sales Order - Complete'){
                            lstTruck2Update.add(new Truck_Inventory__c(Id = opp.Truck_Inventory__c,Customer__c = opp.AccountId, Sold__c=true,Related_Quote_SO__c=opp.Id));
                        }else{
                            lstTruck2Update.add(new Truck_Inventory__c(Id=opp.Truck_Inventory__c, Sold__c=true,Related_Quote_SO__c=opp.Id));
                        }
                    }
                    
                    Opportunity oldOpp = Trigger.oldmap.get(opp.Id);
                    if(oldOpp.Truck_Inventory__c!=null && oldOpp.Truck_Inventory__c != opp.Truck_Inventory__c){
                        lstTruck2Update.add(new Truck_Inventory__c(Id=oldOpp.Truck_Inventory__c,Sold__c=false, Related_Quote_SO__c=null, Customer__c = null));
                    }
                    
                }
            }
        }else if(Trigger.isInsert || Trigger.isUndelete){
            for(Opportunity opp:Trigger.new){
                if(usedTruckQuoteRT.get(opp.RecordTypeId)==null) {
                    if(opp.Truck_Inventory__c!=null){         
                        lstTruck2Update.add(new Truck_Inventory__c(Id=opp.Truck_Inventory__c, Sold__c=true,Related_Quote_SO__c=opp.Id));
                    }
                }
            }
        }else if(Trigger.isDelete){
            for(Opportunity opp:Trigger.old){
                if(usedTruckQuoteRT.get(opp.RecordTypeId)==null){
                    if(opp.Truck_Inventory__c!=null){
                        lstTruck2Update.add(new Truck_Inventory__c(id=opp.Truck_Inventory__c,Sold__c=false, Related_Quote_SO__c=null));
                    }
                }
            }
        }
        if(!lstTruck2Update.isEmpty()){
            update lstTruck2Update;
        }
    
    }
    else{
        
        for(Opportunity opp:Trigger.new){
            if(usedTruckQuoteRT.get(opp.RecordTypeId)==null) {
                if(opp.Truck_Inventory__c!=null){
                    if(!mapNotUsedTruckInv.containsKey(opp.Truck_Inventory__c)){    
                        setTruckInventories.add(opp.Truck_Inventory__c);
                    }          
                }
            }
        }
        
        if(!setTruckInventories.isEmpty()){
            Map<String,String> mTruckInParent = new Map<String,String>();
            for(Truck_Inventory__c ti :[Select Truck__c, Id From Truck_Inventory__c where Id in :setTruckInventories]){
                mTruckInParent.put(ti.Id, ti.Truck__c);
            }
         
            for(Opportunity opp:Trigger.new){
                if(usedTruckQuoteRT.get(opp.RecordTypeId)==null) {
                    opp.Truck__c = mTruckInParent.get(opp.Truck_Inventory__c);
                }
            }
        }
    }
}

class:
@isTest
private class UpdateTruckInventoryByOpportunity_Test {
    
    // method setup data
    private Static String TrkId;
    private Static String recordId;
    static void setupdata() {
      Account acc = new Account(Name = 'acc@test.com', Status__c = 'Prospect-Not Yet Purchased', Phone = '010909090');
        insert acc;
        Account acc1 = new Account(Name = 'acc1@test1.com', Status__c = 'Prospect-Not Yet Purchased', Phone = '070707070');
        insert acc1;
                                                            
        Truck__c Trk = new Truck__c(Name = 'test', Unit_Price__c = 250, Make__c = 'Peterbilt', Wheel_Description__c = 'test', Wheelbase__c = 2,
                                    Tire_Size__c = 'M', Rear_End_Ratio__c = 2, X5th_Wheel__c = 'test', Tank_Passenger__c = 2, Tank_Driver__c = 2, Suspension_Front__c = 'test', Interior__c = 'DIAMOND, TUFTED GRAY. BLACK LEATHER HEATED');
        insert Trk;
        TrkId = Trk.Id;
        Option__c opt = new Option__c(Name = 'Test',Type__c='Transmission');
        insert opt;
        
        Opportunity opp = new Opportunity(Name = 'Test', Engine_Color__c = 'Red', Engine_Type__c = 'In-House', StageName = 'Quote', 
                                          CloseDate = System.today(), AccountId = acc1.Id, Doc_Fee__c = 250, Trans__c = opt.Id, Truck__c = Trk.Id);
        insert opp;
        
        RecordType record = [select Id from RecordType where SobjectType='Truck_Inventory__c' and Name='Stock' limit 1];
        recordId = record.Id;
        Truck_Inventory__c Tr = new Truck_Inventory__c(Date_Delivered_Under_Warranty__c = System.today(),Truck_Color__c ='Red', Related_Quote_SO__c = opp.Id, Stock_Number__c = '123',     Truck__c = Trk.Id, RecordTypeId = record.Id,
                                                            Status__c = 'Ordered', Full_VIN__c = '123', Trans_Number__c = '122345', Engine_Warranty_Custom__c='3 YEAR STANDARD');
        insert Tr;
    }
    
    // testMethod update StageName = Lost Deal - Truck Not Built
    static testMethod void testUpdateOppStageName3(){
       setupdata();
       Account acc = [Select Id, Name From Account Where Name = 'acc@test.com'];
      Truck_Inventory__c Tr = [Select Id, Name From Truck_Inventory__c limit 1];
      //Opportunity opp = new Opportunity(Name = 'Test', Engine_Color__c = 'Red', Engine_Type__c = 'In-House', Truck_Inventory__c = Tr.Id,
        //                                    StageName = 'Quote', CloseDate = System.today(), AccountId = acc.Id, Doc_Fee__c = 250);
        //insert opp;
        //opp.StageName= 'Lost Deal - Truck Not Built';
        List<Opportunity> lstOPP = [Select StageName, AccountId, Truck_Inventory__c From Opportunity limit 1];
        
        lstOPP[0].StageName= 'Lost Deal - Truck Not Built';
        lstOPP[0].Truck_Inventory__c= Tr.Id;
        update lstOPP[0];
        
        Truck_Inventory__c Tr1 = new Truck_Inventory__c(Date_Delivered_Under_Warranty__c = System.today(),Truck_Color__c ='Red', Related_Quote_SO__c = lstOPP[0].Id, Stock_Number__c = '123333',
                                                        Truck__c = TrkId, RecordTypeId = recordId, Status__c = 'Ordered', Full_VIN__c = '12333', 
                                                        Trans_Number__c = '1223456', Engine_Warranty_Custom__c='3 YEAR STANDARD');
        insert Tr1;
        
        lstOPP[0].StageName= 'Lost Deal - Truck Not Built';
        lstOPP[0].Truck_Inventory__c= Tr1.Id;
        Test.startTest();
        update lstOPP[0];
        Test.stopTest();
        Tr = [Select Id, Name, Related_Quote_SO__c From Truck_Inventory__c Where Id =: lstOPP[0].Truck_Inventory__c limit 1];
        System.assertEquals(Tr.Related_Quote_SO__c, null);
    }
     
    // testMethod update opp.Truck_Inventory__c and delete opp
    static testMethod void testUpdateOppTruckInventory() {
      
      setupdata();
      Opportunity opp = [Select Id, Truck_Inventory__c, StageName From Opportunity limit 1];
      Truck_Inventory__c Tr = [Select Id, Name From Truck_Inventory__c limit 1];
        opp.StageName= 'Funded (Sold)';
        opp.Truck_Inventory__c = Tr.Id;
        Test.startTest();
        update opp;
        Tr = [Select Id, Sold__c, Related_Quote_SO__c From Truck_Inventory__c Where Id = :opp.Truck_Inventory__c];
        System.assertEquals(Tr.Sold__c, true);
        System.assertEquals(Tr.Related_Quote_SO__c, opp.Id);
        
        delete opp;
        Test.stopTest();
        Tr = [Select Id, Sold__c, Related_Quote_SO__c From Truck_Inventory__c Where Id = :opp.Truck_Inventory__c];
        
        System.assertEquals(Tr.Sold__c, false);
        System.assertEquals(Tr.Related_Quote_SO__c, null);
    }
    
    //testMethod update StageName = Sales Order- Pending
    static testMethod void testUpdateOppStageName1(){
       setupdata();
       Account acc = [Select Id, Name From Account Where Name = 'acc@test.com'];
      Truck_Inventory__c Tr = [Select Id, Name From Truck_Inventory__c limit 1];
      //Opportunity opp = new Opportunity(Name = 'Test', Engine_Color__c = 'Red', Engine_Type__c = 'In-House', Truck_Inventory__c = Tr.Id,
        //                                    StageName = 'Quote', CloseDate = System.today(), AccountId = acc.Id, Doc_Fee__c = 250);
        //insert opp;
        
        List<Opportunity> lstOPP = [Select StageName, AccountId, Truck_Inventory__c From Opportunity limit 1];
        
        lstOPP[0].StageName= 'Sales Order - Pending';
        lstOPP[0].Truck_Inventory__c = Tr.Id;
        //opp.StageName= 'Sales Order - Pending';
        Test.startTest();
        update lstOPP[0];
        Test.stopTest();
        Tr = [Select Id, Customer__c From Truck_Inventory__c Where Id =: lstOPP[0].Truck_Inventory__c];
        System.assertEquals(Tr.Customer__c, lstOPP[0].AccountId);
     }
     
     //testMethod update opp.Truck_Inventory__c = null
  /*   static testMethod void testUpdateOppStageName2(){
       setupdata();
       Account acc = [Select Id, Name From Account Where Name = 'acc@test.com'];
      Truck_Inventory__c Tr = [Select Id, Name From Truck_Inventory__c limit 1];
      Opportunity opp = new Opportunity(Name = 'Test', Engine_Color__c = 'Red', Engine_Type__c = 'In-House', Truck_Inventory__c = Tr.Id,
                                            StageName = 'Quote', CloseDate = System.today(), AccountId = acc.Id, Doc_Fee__c = 250);
        insert opp;
        
        opp.Truck_Inventory__c= null;
        Test.startTest();
        update opp;
        Test.stopTest();
        
        Tr = [Select Id, Sold__c, Related_Quote_SO__c, Customer__c From Truck_Inventory__c Where Id = : Tr.Id];
        System.assertEquals(Tr.Sold__c, false);
        System.assertEquals(Tr.Customer__c, null);
        System.assertEquals(Tr.Related_Quote_SO__c, null);
     }
*/     
     
    
/*    static testMethod void myUnitTest() {
      
      /*
      Test.startTest();
      
        //Take Truck record type, Truck inventory record type and opportunity record type
        Id truckRT = [Select Id From RecordType Where SObjectType='Truck__c' limit 1].Id;
        Id truckInRT = [Select Id From RecordType Where SObjectType='Truck_Inventory__c' limit 1].Id;
        Id oppRT = [Select Id From RecordType Where SObjectType='Opportunity' limit 1].Id;
        
        //Create Truck
        Truck__c t = new Truck__c(RecordTypeId=truckRT, Name='New Truck 001', Make__c = 'Cab', Unit_Price__c = 100, Tire_Size__c = '1234', Wheel_Description__c = 'abc',
                                  X5th_Wheel__c = 'cdef', Wheelbase__c = 3, Suspension_Front__c = 'efg', Suspension_Rear__c = 'hello',
                                  Exhaust_Type__c = 'DSOC', Rear_End_Ratio__c = 1.2, Interior__c = 'PLATINUM GRAY, CLOTH SEATS', 
                                  Tank_Driver__c = 4, Tank_Passenger__c = 2);
        Insert t;
        //Create Truck Inventory
        List<Truck_Inventory__c> lstTruckIns = new List<Truck_Inventory__c>();
        Truck_Inventory__c ti = new Truck_Inventory__c(RecordTypeId=truckInRT, Truck__c=t.Id, Name='Truck Inventory 001', Truck_Color__c='Red');
        lstTruckIns.add(ti);
        
        Truck_Inventory__c ti1 = new Truck_Inventory__c(RecordTypeId=truckInRT, Truck__c=t.Id, Name='Truck Inventory 002', Truck_Color__c='Red');
        lstTruckIns.add(ti1);
        
        insert lstTruckIns;
        
        //Create Account
        Account acc = new Account(Name='Account 001', Phone='09393837474', Status__c='Prospect - Not Yet Purchased');
        insert acc;
        
        //Create Opportunity
        Opportunity opp1 = new Opportunity(Name='Opportunity 001', AccountId=acc.Id, CloseDate=system.today().addMonths(4), StageName='Quote',
                                          Truck__c=t.Id,Truck_Color__c = 'Blue', Truck_Year_Model__c = '2012', Doc_Fee__c=25);
        insert opp1;
        
        Opportunity opp2 = new Opportunity(Name='Opportunity 002', AccountId=acc.Id, CloseDate=system.today().addMonths(3), StageName='Quote', 
                                          Truck__c=t.Id,Truck_Color__c = 'Blue', Truck_Year_Model__c = '2012', Doc_Fee__c=25, Truck_Inventory__c=lstTruckIns[1].id);
        insert opp2;
        
        lstTruckIns = [Select Id, Sold__c, Related_Quote_SO__c From Truck_Inventory__c Where Id in:lstTruckIns];
        system.assertEquals(lstTruckIns[0].Sold__c, false);
        system.assertEquals(lstTruckIns[0].Related_Quote_SO__c, null);
        system.assertEquals(lstTruckIns[1].Sold__c, true);
        system.assertEquals(lstTruckIns[1].Related_Quote_SO__c, opp2.Id);
        
        //update opportunity
        //set Truck inventor on opportunity to null
        opp1.Truck_Inventory__c = lstTruckIns[0].id;
        update opp1;
        
        opp2.Truck_Inventory__c = null;
        update opp2;
        
        lstTruckIns = [Select Id, Sold__c, Related_Quote_SO__c From Truck_Inventory__c Where Id in:lstTruckIns];
        system.assertEquals(lstTruckIns[0].Sold__c, true);
        system.assertEquals(lstTruckIns[0].Related_Quote_SO__c, opp1.Id);
        system.assertEquals(lstTruckIns[1].Sold__c, false);
        system.assertEquals(lstTruckIns[1].Related_Quote_SO__c, null);
        
        //delete Opportunity
        delete opp1;
        lstTruckIns = [Select Id, Sold__c, Related_Quote_SO__c From Truck_Inventory__c Where Id in:lstTruckIns];
        system.assertEquals(lstTruckIns[0].Sold__c, false);
        system.assertEquals(lstTruckIns[0].Related_Quote_SO__c, null);
        
        Test.stopTest();
        
        */
    //}
}

 
Smike25Smike25
I had added @IsTest in the recordtype helper. After removing it, it seems to be working
Smike25Smike25
Thanks again bjpiggins, I was finally able to get enough code coverage to be able to update and edit what was needed.  Thank you!  I have some more work to do adding some new validation rules from opportunites into some existing code, but i'm going to open up a new thread for that one.