• travis.truett
  • NEWBIE
  • 70 Points
  • Member since 2014
  • CEO
  • Ambition

  • Chatter
    Feed
  • 0
    Best Answers
  • 1
    Likes Received
  • 0
    Likes Given
  • 35
    Questions
  • 76
    Replies
It's a pretty standard summary report with a couple lines of logic. Report runs fine in Salesforce but I can't run it programmatically. Any idea where to start debugging?
My apex text class for a trigger I wrote has started failing ever since I added code to the trigger to avoid recursion. As I understand it, I need to update my test in order to ensure the class I wrote to stop the recursion in the trigger is covered. Here's the class I'm using. My trigger calls it before it runs to ensure the trigger only fires once:

public Class checkRecursive{
    private static boolean run = true;
    public static boolean runOnce(){
    if(run){
     run=false;
     return true;
    }else{
        return run;
    }
    }
}


And here's the test class:

@isTest (seeAllData=true)
private class testEditSchedule{

static testMethod void testUpdateSchedule() {
 
List<Account> aList = new List<Account>();    
Account a = new Account(
      Name = 'Test Account'
    );
    aList.add(a);
    
    insert aList;
    

List<Opportunity> oList = new List<Opportunity>();
Opportunity o = new Opportunity(
      Name = 'Test Opportunity', 
      StageName = 'Discovery', 
      CloseDate = Date.today(),
      Contract_Start_Date__c = Date.today(), 
      AccountId = a.Id
    );
    
    oList.add(o);
    insert oList;
    
        //Create Product
        Product2 prod = new Product2();
        prod.IsActive = true;
        prod.Name = 'Onboarding';
        prod.CanUseRevenueSchedule=true;
        insert prod;
        //Create PriceBook
        Pricebook2 pb = new Pricebook2();
        pb.Name = 'Test';
        pb.IsActive = true;
        insert pb;
        List<Pricebook2> PbList = [Select Id, Name, IsActive From Pricebook2 where IsStandard = true LIMIT 1];
    //Pricebook2 standardpb = [Select Id, Name, IsActive From Pricebook2 where IsStandard = true LIMIT 1];
        
            
        PricebookEntry standardpbe = new PricebookEntry();
        standardpbe.Pricebook2Id = PbList[0].Id;
        standardpbe.Product2Id = prod.Id;
        standardpbe.UnitPrice = 10000;
        standardpbe.IsActive = true;
        standardpbe.UseStandardPrice = false;
        insert standardpbe;
        
        PricebookEntry pbe = new PricebookEntry();
        pbe.Pricebook2Id = pb.Id;
        pbe.Product2Id = prod.Id;
        pbe.UnitPrice = 10000;
        pbe.IsActive = true;
        pbe.UseStandardPrice = false;
        insert pbe;
        
List<OpportunityLineItem> oliList = new List<OpportunityLineItem>(); 
List<OpportunityLineItem> oliAnnuallyList = new List<OpportunityLineItem>(); 
List<OpportunityLineItem> oliQuarterlyList = new List<OpportunityLineItem>(); 
List<OpportunityLineItem> oliMonthlyList = new List<OpportunityLineItem>(); 
       
OpportunityLineItem oliAnnually = new OpportunityLineItem(
        OpportunityId = o.Id,  
        PricebookEntryId = pbe.id,
        TotalPrice = 1,
        Quantity=2,
        Payment_Terms__c ='Annually',
        Duration__c = 12
        
    );
    OpportunityLineItem oliMonthly= new OpportunityLineItem(
        OpportunityId = o.Id,  
        PricebookEntryId = pbe.id,
        TotalPrice = 1,
        Quantity=2,
        Payment_Terms__c ='Monthly',
        Duration__c = 1
        
    );
    OpportunityLineItem oliQuarterly= new OpportunityLineItem(
        OpportunityId = o.Id,  
        PricebookEntryId = pbe.id,
        TotalPrice = 1,
        Quantity=2,
        Payment_Terms__c ='Quarterly',
        Duration__c = 3
        
    );
    OpportunityLineItem oli= new OpportunityLineItem(
        OpportunityId = o.Id,  
        PricebookEntryId = pbe.id,
        TotalPrice = 1,
        Quantity=2,
        Payment_Terms__c = 'Up Front',
        Duration__c = 12
        
    );
    oliAnnuallyList.add(oliAnnually);
    oliMonthlyList.add(oliMonthly);
    oliQuarterlyList.add(oliQuarterly);
    oliList.add(oli);
    insert oliList;
    insert oliAnnuallyList;
    insert oliQuarterlyList;
    insert oliMonthlyList;
    
    //Your trigger should have OpportunityLineItemSchedule logic then following asert will pass else it will fail
    List<OpportunityLineItem> lstOptyLi =[SELECT HasRevenueSchedule from OpportunityLineItem where Id =:oli.id];
    System.assertEquals(True, lstOptyLi[0].HasRevenueSchedule);
    List<OpportunityLineItem> lstOptyLi_2 =[SELECT HasRevenueSchedule from OpportunityLineItem where Id =:oliAnnually.id];
    System.assertEquals(True, lstOptyLi_2[0].HasRevenueSchedule);
    List<OpportunityLineItem> lstOptyLi_3 =[SELECT HasRevenueSchedule from OpportunityLineItem where Id =:oliQuarterly.id];
    System.assertEquals(True, lstOptyLi_3[0].HasRevenueSchedule);
    List<OpportunityLineItem> lstOptyLi_4 =[SELECT HasRevenueSchedule from OpportunityLineItem where Id =:oliMonthly.id];
    System.assertEquals(True, lstOptyLi_4[0].HasRevenueSchedule);
   
  }
    
}


What do I need to do to add coverage for the new class?

Thanks
I wrote the following class to call from my triggers and ensure they don't run recursively. This is the code:

public Class checkRecursive{
    private static boolean run = true;
    public static boolean runOnce(){
    if(run){
     run=false;
     return true;
    }else{
        return run;
    }
    }
}

Do I need to write a test class for this class in order to push it to our instance? If so, can someone point me in the right direction? Thanks.
My trigger was throwing some errors when we would try to update opportunities, and it was suggested to me that I create a class to make sure the trigger only runs once, and then reference that class in my trigger. This is the class: 

public Class checkRecursive{
    private static boolean run = true;
    public static boolean runOnce(){
    if(run){
     run=false;
     return true;
    }else{
        return run;
    }
    }
}

When I try to test my code coverage for my trigger now, it fails, and I'm not sure why. He's the code for the trigger:

trigger editSchedule on OpportunityLineItem (after insert) {

if(checkRecursive.runOnce())
    {

if(Trigger.isInsert){

Map<Id, Opportunity> opportunities = new Map<Id, Opportunity>();
Date myDate = Date.newInstance(1990, 2, 17);

for(OpportunityLineItem oli: Trigger.new) {
    opportunities.put(oli.OpportunityId, null);
}
opportunities.putAll([SELECT Contract_Start_Date__c FROM Opportunity WHERE Id in :opportunities.keySet()]);
for(OpportunityLineItem oli: Trigger.new) {
     Opportunity thisLineItemOpp = opportunities.get(oli.OpportunityId);
     myDate = thisLineItemOpp.Contract_Start_Date__c;
      // thisLineItemOpp.CloseDate is the close date you're looking for
}

List<OpportunityLineItemSchedule> listOLIS = new List<OpportunityLineItemSchedule>();




for (OpportunityLineItem oli: Trigger.new){
Set<Id> setOpptyOLI = new set<Id>();
setOpptyOLI.add(oli.Id);
List<OpportunityLineItem> OpptyOlilst=[Select Product2.Family FROM OpportunityLineItem WHERE Id IN:setOpptyOLI ];

Decimal DiscountedPrice;



DiscountedPrice = oli.Discounted_Price__c;


if(oli.Payment_Terms__c == 'Monthly'){

for(OpportunityLineItem record : OpptyOlilst){
if(record.Product2.Family=='Services'){
    
    
for(Integer duration = (Integer)oli.Duration__c; duration > 0; duration--){

listOLIS.add(new OpportunityLineItemSchedule(OpportunityLineItemId = oli.Id, Revenue = DiscountedPrice*oli.Quantity/oli.Duration__c, ScheduleDate = myDate, Type = 'Revenue'));
myDate = myDate.addMonths(1);

}//end of loop
    
    }//end of inner IF
    
else {
for(Integer duration = (Integer)oli.Duration__c; duration > 0; duration--){

listOLIS.add(new OpportunityLineItemSchedule(OpportunityLineItemId = oli.Id, Revenue = DiscountedPrice*oli.Quantity, ScheduleDate = myDate, Type = 'Revenue'));
myDate = myDate.addMonths(1);

}//end of loop

}//end of else

}//end of OpptyOlilstForLoop

}//end of Monthly IF


    else if(oli.Payment_Terms__c == 'Quarterly'){
    
for(OpportunityLineItem record : OpptyOlilst){
if(record.Product2.Family=='Services'){
    
for(Integer duration = (Integer)oli.Duration__c/3; duration > 0; duration--){

listOLIS.add(new OpportunityLineItemSchedule(OpportunityLineItemId = oli.Id, Revenue = DiscountedPrice*oli.Quantity*3/oli.Duration__c, ScheduleDate = myDate, Type = 'Revenue'));
myDate = myDate.addMonths(3);

}//end of loop
    
    }//end of inner IF

else{
for(Integer duration = (Integer)oli.Duration__c/3; duration > 0; duration--){

listOLIS.add(new OpportunityLineItemSchedule(OpportunityLineItemId = oli.Id, Revenue = DiscountedPrice*oli.Quantity*3, ScheduleDate = myDate, Type = 'Revenue'));
myDate = myDate.addMonths(3);

}//end of loop

}//end of else

}//end of OpptyOlilstForLoop

}//end of Quarterly IF


    else if(oli.Payment_Terms__c == 'Annually'){
    
for(OpportunityLineItem record : OpptyOlilst){
if(record.Product2.Family=='Services'){
          
    
for(Integer duration = (Integer)oli.Duration__c/12; duration > 0; duration--){

listOLIS.add(new OpportunityLineItemSchedule(OpportunityLineItemId = oli.Id, Revenue = DiscountedPrice*oli.Quantity*12/oli.Duration__c, ScheduleDate = myDate, Type = 'Revenue'));
myDate = myDate.addYears(1);

}//end of loop
    
    }//end of inner IF

else{
for(Integer duration = (Integer)oli.Duration__c/12; duration > 0; duration--){

listOLIS.add(new OpportunityLineItemSchedule(OpportunityLineItemId = oli.Id, Revenue = DiscountedPrice*oli.Quantity*12, ScheduleDate = myDate, Type = 'Revenue'));
myDate = myDate.addYears(1);

}//end of loop

}//end of else

}//end of OpptyOlilstForLoop

}//end of Annually IF


    else if(oli.Payment_Terms__c == 'Up Front'){
    
for(OpportunityLineItem record : OpptyOlilst){
if(record.Product2.Family=='Services'){
    
    
listOLIS.add(new OpportunityLineItemSchedule(OpportunityLineItemId = oli.Id, Revenue = DiscountedPrice*oli.Quantity, ScheduleDate = myDate, Type = 'Revenue'));
  
    }//end of inner IF

else{
listOLIS.add(new OpportunityLineItemSchedule(OpportunityLineItemId = oli.Id, Revenue = DiscountedPrice*oli.Quantity*oli.Duration__c, ScheduleDate = myDate, Type = 'Revenue'));

}//end of else

}//end of OpptyOlilstForLoop

}//end of Up Front IF 


insert listOLIS;



}//end of isInsert

}//end of runOnce

}//end of checkRecursive

}//end of trigger

As you can see, my trigger now references the class I wrote to avoid recursion. 
The first time I tested the trigger, I got the following exception: 
System.DmlException: Insert failed. First exception on row 0; first error: UNABLE_TO_LOCK_ROW, unable to obtain exclusive access to this record: []
Class.testEditSchedule.testUpdateSchedule: line 48, column 1

The second time, I tested it by itself, and got this exception:
System.AssertException: Assertion Failed: Expected: true, Actual: false
Class.testEditSchedule.testUpdateSchedule: line 112, column 1

Lastly, here's the code for my test class:

@isTest (seeAllData=true)
private class testEditSchedule{

static testMethod void testUpdateSchedule() {
 
List<Account> aList = new List<Account>();    
Account a = new Account(
      Name = 'Test Account'
    );
    aList.add(a);
    
    insert aList;
    

List<Opportunity> oList = new List<Opportunity>();
Opportunity o = new Opportunity(
      Name = 'Test Opportunity', 
      StageName = 'Discovery', 
      CloseDate = Date.today(),
      Contract_Start_Date__c = Date.today(), 
      AccountId = a.Id
    );
    
    oList.add(o);
    insert oList;
    
        //Create Product
        Product2 prod = new Product2();
        prod.IsActive = true;
        prod.Name = 'Onboarding';
        prod.CanUseRevenueSchedule=true;
        insert prod;
        //Create PriceBook
        Pricebook2 pb = new Pricebook2();
        pb.Name = 'Test';
        pb.IsActive = true;
        insert pb;
        List<Pricebook2> PbList = [Select Id, Name, IsActive From Pricebook2 where IsStandard = true LIMIT 1];
    //Pricebook2 standardpb = [Select Id, Name, IsActive From Pricebook2 where IsStandard = true LIMIT 1];
        
            
        PricebookEntry standardpbe = new PricebookEntry();
        standardpbe.Pricebook2Id = PbList[0].Id;
        standardpbe.Product2Id = prod.Id;
        standardpbe.UnitPrice = 10000;
        standardpbe.IsActive = true;
        standardpbe.UseStandardPrice = false;
        insert standardpbe;
        
        PricebookEntry pbe = new PricebookEntry();
        pbe.Pricebook2Id = pb.Id;
        pbe.Product2Id = prod.Id;
        pbe.UnitPrice = 10000;
        pbe.IsActive = true;
        pbe.UseStandardPrice = false;
        insert pbe;
        
List<OpportunityLineItem> oliList = new List<OpportunityLineItem>(); 
List<OpportunityLineItem> oliAnnuallyList = new List<OpportunityLineItem>(); 
List<OpportunityLineItem> oliQuarterlyList = new List<OpportunityLineItem>(); 
List<OpportunityLineItem> oliMonthlyList = new List<OpportunityLineItem>(); 
       
OpportunityLineItem oliAnnually = new OpportunityLineItem(
        OpportunityId = o.Id,  
        PricebookEntryId = pbe.id,
        TotalPrice = 1,
        Quantity=2,
        Payment_Terms__c ='Annually',
        Duration__c = 12
        
    );
    OpportunityLineItem oliMonthly= new OpportunityLineItem(
        OpportunityId = o.Id,  
        PricebookEntryId = pbe.id,
        TotalPrice = 1,
        Quantity=2,
        Payment_Terms__c ='Monthly',
        Duration__c = 1
        
    );
    OpportunityLineItem oliQuarterly= new OpportunityLineItem(
        OpportunityId = o.Id,  
        PricebookEntryId = pbe.id,
        TotalPrice = 1,
        Quantity=2,
        Payment_Terms__c ='Quarterly',
        Duration__c = 3
        
    );
    OpportunityLineItem oli= new OpportunityLineItem(
        OpportunityId = o.Id,  
        PricebookEntryId = pbe.id,
        TotalPrice = 1,
        Quantity=2,
        Payment_Terms__c = 'Up Front',
        Duration__c = 12
        
    );
    oliAnnuallyList.add(oliAnnually);
    oliMonthlyList.add(oliMonthly);
    oliQuarterlyList.add(oliQuarterly);
    oliList.add(oli);
    insert oliList;
    insert oliAnnuallyList;
    insert oliQuarterlyList;
    insert oliMonthlyList;
    
    //Your trigger should have OpportunityLineItemSchedule logic then following asert will pass else it will fail
    List<OpportunityLineItem> lstOptyLi =[SELECT HasRevenueSchedule from OpportunityLineItem where Id =:oli.id];
    System.assertEquals(True, lstOptyLi[0].HasRevenueSchedule);
    List<OpportunityLineItem> lstOptyLi_2 =[SELECT HasRevenueSchedule from OpportunityLineItem where Id =:oliAnnually.id];
    System.assertEquals(True, lstOptyLi_2[0].HasRevenueSchedule);
    List<OpportunityLineItem> lstOptyLi_3 =[SELECT HasRevenueSchedule from OpportunityLineItem where Id =:oliQuarterly.id];
    System.assertEquals(True, lstOptyLi_3[0].HasRevenueSchedule);
    List<OpportunityLineItem> lstOptyLi_4 =[SELECT HasRevenueSchedule from OpportunityLineItem where Id =:oliMonthly.id];
    System.assertEquals(True, lstOptyLi_4[0].HasRevenueSchedule);
   
  }
    
}

I'm not sure why adding that little bit of code caused my test to stop working, but it thinks my trigger is messed up now. Can someone help me figure out how to fix it?

Thanks
I'm getting the following error when I try to set an opportunity to closed won:

Error:Apex trigger Create_followup caused an unexpected exception, contact your administrator: Create_followup: execution of BeforeUpdate caused by: System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, editSchedule: execution of AfterInsert caused by: System.DmlException: Insert failed. First exception on row 0 with id 00oU0000002ulNkIAI; first error: INVALID_FIELD_FOR_INSERT_UPDATE, cannot specify Id in an insert call: [Id] Trigger.editSchedule: line 144, column 1: []: Trigger.Create_followup: line 88, column 1

The two triggers mentioned in the error are both triggers I wrote. Can anyone tell me what this type of error might be caused by?

Thanks
I'm working with a trigger I wrote a few months back, but we want to change the way a particular line works. Currently, the trigger duplicates opportunities when they close and creates a followup opportunity for the following year. We want to change our naming convention for the new opportunities. Currently, this is how they're named:

oppNew.Name = oppNew.Name.substringBefore('-')  + ' - Annual ' + o.CloseDate.year();

Instead of this, we want to pull some data from the opportunity product attached to the opportunity. Specifically, the number of users, the duration of the product, and the price per user for the product. So here's what the change would look like:

"CompanyName - Annual 2015" ---> "CompanyName 15.3.30"
Where 15 is the number of users, 3 is the duration in months, and 30 is the price per seat.
All of that information is available in the opportunity product object, I just forgot how to query for it because I haven't worked with apex in half a year.

Thanks
I have a trigger that, among other things, is creating some events on new opportunities. Here's that section of the trigger:
eventList.add(new Event(whatid=o.id,startdatetime=myDateTime,subject='Account Management Follow-Up', EndDateTime=myDateTime, IsAllDayEvent=true, OwnerId = 'cwilli'));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(2),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(2), IsAllDayEvent=true/*, OwnerId = 'cwilli'*/));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(4),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(4), IsAllDayEvent=true/*, OwnerId = 'cwilli'*/));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(6),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(6), IsAllDayEvent=true/*, OwnerId = 'cwilli'*/));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(8),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(8), IsAllDayEvent=true/*, OwnerId = 'cwilli'*/));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(10),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(10), IsAllDayEvent=true/*, OwnerId = 'cwilli'*/));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(10),subject='Renewal',EndDateTime=myDateTime.addMonths(10), IsAllDayEvent=true/*, OwnerId = 'cwilli'*/));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(9),subject='Sales Contract Follow-Up',EndDateTime=myDateTime.addMonths(9), IsAllDayEvent=true/*, OwnerId = 'cwilli'*/));

As you can see, I was trying to use the OwnerId field with a specific user's alias, but that was essentially destroying my trigger. I just need to know the correct syntax for specifying the assigned to field when I create these events. Thanks.
I'm getting the following error from my trigger that duplicates opportunities when we close them:

Error:Apex trigger Create_followup caused an unexpected exception, contact your administrator: Create_followup: execution of BeforeUpdate caused by: System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, editSchedule: execution of AfterInsert caused by: System.DmlException: Insert failed. First exception on row 0 with id 00oK0000000UInZIAW; first error: INVALID_FIELD_FOR_INSERT_UPDATE, cannot specify Id in an insert call: [Id] Trigger.editSchedule: line 144, column 1: []: Trigger.Create_followup: line 80, column 1

Essentially, I have a trigger that's duplicating the closed opp and adding the products from the old opp over to the new one. This is the section of the code that's throwing the error:

          List<OpportunityLineItem> oliList = [SELECT OpportunityId, PricebookEntryId, UnitPrice, Quantity, Duration__c, Payment_Terms__c, Discount FROM OpportunityLineItem WHERE OpportunityId IN :Trigger.New];
          List<OpportunityLineItem> newoliList = new List<OpportunityLineItem>();
          
          if(!oliList.isEmpty()) {
                Map<Id, Id> oldOpNewOpIdMap2 = new Map<Id, Id>();
               for(Opportunity opNew : listOppor) {
                    oldOpNewOpIdMap2.put(opNew.Parent_Opportunity__c, opNew.Id);
                }   
                
                for(OpportunityLineItem oli : oliList) {
                    
                    OpportunityLineItem newOli = new OpportunityLineItem();
                    newOli.UnitPrice = oli.UnitPrice;
                    
                    newOli.PricebookEntryId = oli.PricebookEntryId;
                    newOli.Quantity = oli.Quantity;
                    newOli.Duration__c = 12;
                   
                    newOli.Payment_Terms__c = oli.Payment_Terms__c;
                    newOli.Discount = oli.Discount;
                    
                    newOli.OpportunityId = oldOpNewOpIdMap2.get(oli.OpportunityId);
                    
                    
                    newoliList.add(newOli);
                }
                
                insert newoliList;

I'm having trouble figuring out why this is happenning and I really need to fix it. Thanks in advance for your help!
I wrote a couple of triggers that duplicate opportunities when we set their stage to closed won, and then automatically create revenue schedules based on the products those opportunities have. They have been working well, but I started getting a weird error whenever I try to close an opp with more than one product. Here's a screenshot of the error:

User-added image

For some reason, when it tries to duplicate this opp, if I only have one product on it, it will work, but once I add a second, it throws and error. I'll also attach the code for the "Create_Followup" trigger. I can upload the "EditSchedule" trigger too if that turns out to be part of the problem. Thanks for the help.

here's create_Followup. It's throwing an error when it tries to insert the opp product list.

trigger Create_followup on Opportunity (before update, after insert) {
    List<Pricebook2> standardBook = [SELECT Id FROM Pricebook2 WHERE Name = :'Ambition'];//Create an instance of the standard pricebook
    
    if(Trigger.isUpdate){
        List<Opportunity> listOppor = new List<Opportunity>();
        for (Opportunity o: Trigger.new){
            if (o.StageName == 'Closed Won' && o.Stage_Change__c == false){

                Opportunity oppNew = o.clone();
                oppNew.Name = oppNew.Name  + ' - Annual ' + o.CloseDate.year();
                
                if(o.Renewal_Date__c != null){
                oppNew.Renewal_Date__c = o.Renewal_Date__c.addYears(1);
                oppNew.CloseDate = o.Renewal_Date__c;
                oppNew.Contract_Start_Date__c = o.Renewal_Date__c;}
                
                oppNew.StageName = 'Discovery';
                oppNew.Probability = 25;
                oppNew.Parent_Opportunity__c = o.Id;
                
                
                oppNew.Pricebook2Id = standardBook[0].Id;//associate the standard pricebook with this opportunity
                
                oppNew.Is_Clone__c = true;
                listOppor.add(oppNew);
                o.Stage_Change__c = true;
                
            }

        }//end of for loop

        if(listOppor.size() > 0){
            insert listOppor;
            
            List<OpportunityContactRole> ocrList = [SELECT OpportunityId, ContactId, Role FROM OpportunityContactRole WHERE OpportunityId IN :Trigger.New];
            List<OpportunityContactRole> newOcrList = new List<OpportunityContactRole>();

            if(!ocrList.isEmpty()) {
                Map<Id, Id> oldOpNewOpIdMap = new Map<Id, Id>();
                for(Opportunity opNew : listOppor) {
                    oldOpNewOpIdMap.put(opNew.Parent_Opportunity__c, opNew.Id);
                }   
                for(OpportunityContactRole ocr : ocrList) {
                    OpportunityContactRole newOcr = new OpportunityContactRole();
                    newOcr.ContactId = ocr.ContactId;
                    newOcr.Role = ocr.Role;
                    newOcr.OpportunityId = oldOpNewOpIdMap.get(ocr.OpportunityId);
                    newOcrList.add(newOcr);
                }
                insert newOcrList;
            }
            
          List<OpportunityLineItem> oliList = [SELECT OpportunityId, PricebookEntryId, UnitPrice, Quantity, Duration__c, Payment_Terms__c, Discount FROM OpportunityLineItem WHERE OpportunityId IN :Trigger.New];
          List<OpportunityLineItem> newoliList = new List<OpportunityLineItem>();
          
          if(!oliList.isEmpty()) {
                Map<Id, Id> oldOpNewOpIdMap2 = new Map<Id, Id>();
                for(Opportunity opNew : listOppor) {
                    oldOpNewOpIdMap2.put(opNew.Parent_Opportunity__c, opNew.Id);
                }   
                for(OpportunityLineItem oli : oliList) {
                    OpportunityLineItem newOli = new OpportunityLineItem();
                    newOli.UnitPrice = oli.UnitPrice;
                    
                    newOli.PricebookEntryId = oli.PricebookEntryId;
                    newOli.Quantity = oli.Quantity;
                    newOli.Duration__c = 12;
                   
                    newOli.Payment_Terms__c = oli.Payment_Terms__c;
                    newOli.Discount = oli.Discount;
                    newOli.OpportunityId = oldOpNewOpIdMap2.get(oli.OpportunityId);
                    
                    
                    newoliList.add(newOli);
                }
                insert newoliList;
            }

            
        }
        
        

    }

    if(trigger.isInsert){
        try{
            //OpportunityLineItem[] lines = new OpportunityLineItem[0];
            //PricebookEntry entry = [SELECT Id, UnitPrice FROM PricebookEntry WHERE Pricebook2Id = :standardBook.Id AND Product2.ProductCode = 'ENTERPRISE_ANNUAL_UPFRONT'];
            List<Event> eventList = new List<Event>();
            //List<Note> noteList = new List<Note>();


            for(Opportunity o: Trigger.new){
                if(o.Is_Clone__c == true){

                    //noteList.add(new Note(ParentId=o.id,Title='Matt is the Apex_God',Body='Matt is the Apex_God',isPrivate=false));

                    //lines.add(new OpportunityLineItem(PricebookEntryId=entry.Id, OpportunityId=o.Id, UnitPrice=entry.UnitPrice, Quantity=1));

                    if(o.Renewal_Date__c != null){

                        DateTime myDateTime = o.Renewal_Date__c.addMonths(-10);
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime,subject='Account Management Follow-Up', EndDateTime=myDateTime, IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(2),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(2), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(4),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(4), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(6),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(6), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(8),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(8), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(10),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(10), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(10),subject='Renewal',EndDateTime=myDateTime.addMonths(10), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(9),subject='Sales Contract Follow-Up',EndDateTime=myDateTime.addMonths(9), IsAllDayEvent=true));

                    }//end of if

                }
            }
            //insert lines;
            insert eventList;
            //insert noteList;

        }
        catch(Exception e){

        }
    }
}
I've been looking for some help accessing the account name of an opportunity in my trigger, but none of the suggestions I've gotten so far have helped. This trigger duplicates opportunities in order to create followup opps. Currently we just append "annual 2015" or whatever year it is to the end of the opportunity name, but we want to make it so that the name of the new opp has the account name of the original opp followed by the word annual and the year. So rather than "oppNew.Name = oppNew.Name  + ' - Annual ' + o.CloseDate.year();" it would be "oppNew.Name = o.Account.Name + ' - Annual" + o.CloseDate.year();" or something like that. The suggestions I already tried either created opps with "null" for the account part of the name, or completely stopped duplicating opps altogether. Any help on figuring this out would be greatly appreciated. Thanks!

trigger Create_followup on Opportunity (before update, after insert) {
    List<Pricebook2> standardBook = [SELECT Id FROM Pricebook2 WHERE Name = :'Ambition'];//Create an instance of the standard pricebook
    
    if(Trigger.isUpdate){
        List<Opportunity> listOppor = new List<Opportunity>();
        for (Opportunity o: Trigger.new){
            if (o.StageName == 'Closed Won' && o.Stage_Change__c == false){

                Opportunity oppNew = o.clone();
                oppNew.Name = oppNew.Name  + ' - Annual ' + o.CloseDate.year();
                
                if(o.Renewal_Date__c != null){
                oppNew.Renewal_Date__c = o.Renewal_Date__c.addYears(1);
                oppNew.CloseDate = o.Renewal_Date__c;}
                
                oppNew.StageName = 'Discovery';
                oppNew.Probability = 25;
                oppNew.Parent_Opportunity__c = o.Id;
                
                
                oppNew.Pricebook2Id = standardBook[0].Id;//associate the standard pricebook with this opportunity
                
                oppNew.Is_Clone__c = true;
                listOppor.add(oppNew);
                o.Stage_Change__c = true;
                
            }

        }//end of for loop

        if(listOppor.size() > 0){
            insert listOppor;
            
            List<OpportunityContactRole> ocrList = [SELECT OpportunityId, ContactId, Role FROM OpportunityContactRole WHERE OpportunityId IN :Trigger.New];
            List<OpportunityContactRole> newOcrList = new List<OpportunityContactRole>();

            if(!ocrList.isEmpty()) {
                Map<Id, Id> oldOpNewOpIdMap = new Map<Id, Id>();
                for(Opportunity opNew : listOppor) {
                    oldOpNewOpIdMap.put(opNew.Parent_Opportunity__c, opNew.Id);
                }   
                for(OpportunityContactRole ocr : ocrList) {
                    OpportunityContactRole newOcr = new OpportunityContactRole();
                    newOcr.ContactId = ocr.ContactId;
                    newOcr.Role = ocr.Role;
                    newOcr.OpportunityId = oldOpNewOpIdMap.get(ocr.OpportunityId);
                    newOcrList.add(newOcr);
                }
                insert newOcrList;
            }
            
          List<OpportunityLineItem> oliList = [SELECT OpportunityId, PricebookEntryId, UnitPrice, Quantity, Duration__c, Payment_Terms__c, Discount FROM OpportunityLineItem WHERE OpportunityId IN :Trigger.New];
          List<OpportunityLineItem> newoliList = new List<OpportunityLineItem>();
          
          if(!oliList.isEmpty()) {
                Map<Id, Id> oldOpNewOpIdMap2 = new Map<Id, Id>();
                for(Opportunity opNew : listOppor) {
                    oldOpNewOpIdMap2.put(opNew.Parent_Opportunity__c, opNew.Id);
                }   
                for(OpportunityLineItem oli : oliList) {
                    OpportunityLineItem newOli = new OpportunityLineItem();
                    newOli.UnitPrice = oli.UnitPrice;
                    
                    newOli.PricebookEntryId = oli.PricebookEntryId;
                    newOli.Quantity = oli.Quantity;
                    newOli.Duration__c = 12;
                   
                    newOli.Payment_Terms__c = oli.Payment_Terms__c;
                    newOli.Discount = oli.Discount;
                    newOli.OpportunityId = oldOpNewOpIdMap2.get(oli.OpportunityId);
                    
                    
                    newoliList.add(newOli);
                }
                insert newoliList;
            }

            
        }
        
        

    }

    if(trigger.isInsert){
        try{
            //OpportunityLineItem[] lines = new OpportunityLineItem[0];
            //PricebookEntry entry = [SELECT Id, UnitPrice FROM PricebookEntry WHERE Pricebook2Id = :standardBook.Id AND Product2.ProductCode = 'ENTERPRISE_ANNUAL_UPFRONT'];
            List<Event> eventList = new List<Event>();
            //List<Note> noteList = new List<Note>();


            for(Opportunity o: Trigger.new){
                if(o.Is_Clone__c == true){

                    //noteList.add(new Note(ParentId=o.id,Title='Matt is the Apex_God',Body='Matt is the Apex_God',isPrivate=false));

                    //lines.add(new OpportunityLineItem(PricebookEntryId=entry.Id, OpportunityId=o.Id, UnitPrice=entry.UnitPrice, Quantity=1));

                    if(o.Renewal_Date__c != null){

                        DateTime myDateTime = o.Renewal_Date__c.addMonths(-10);
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime,subject='Account Management Follow-Up', EndDateTime=myDateTime, IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(2),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(2), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(4),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(4), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(6),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(6), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(8),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(8), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(10),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(10), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(10),subject='Renewal',EndDateTime=myDateTime.addMonths(10), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(9),subject='Sales Contract Follow-Up',EndDateTime=myDateTime.addMonths(9), IsAllDayEvent=true));

                    }//end of if

                }
            }
            //insert lines;
            insert eventList;
            //insert noteList;

        }
        catch(Exception e){

        }
    }
}
I have a trigger that duplicates opportunities when we close them. Currently, the trigger just appends the word Annual and the current year to the end of the name of the duplicated opp for the name of the new opp. What I would like to do, however, is use the name of the opportunity's associated account instead. Is there an easy way to pull that info in and access the account's name? Here's my code, with the section I'm talking about bolded: 

trigger Create_followup on Opportunity (before update, after insert) {
    List<Pricebook2> standardBook = [SELECT Id FROM Pricebook2 WHERE Name = :'Ambition'];//Create an instance of the standard pricebook
    
    if(Trigger.isUpdate){
        List<Opportunity> listOppor = new List<Opportunity>();
        for (Opportunity o: Trigger.new){
            if (o.StageName == 'Closed Won' && o.Stage_Change__c == false){

                Opportunity oppNew = o.clone();
                oppNew.Name = oppNew.Name  + ' - Annual ' + o.CloseDate.year();
                
                if(o.Renewal_Date__c != null){
                oppNew.Renewal_Date__c = o.Renewal_Date__c.addYears(1);
                oppNew.CloseDate = o.Renewal_Date__c;}
                
                oppNew.StageName = 'Discovery';
                oppNew.Probability = 25;
                oppNew.Parent_Opportunity__c = o.Id;
                
                
                oppNew.Pricebook2Id = standardBook[0].Id;//associate the standard pricebook with this opportunity
                
                oppNew.Is_Clone__c = true;
                listOppor.add(oppNew);
                o.Stage_Change__c = true;
                
            }

        }//end of for loop

        if(listOppor.size() > 0){
            insert listOppor;
            
            List<OpportunityContactRole> ocrList = [SELECT OpportunityId, ContactId, Role FROM OpportunityContactRole WHERE OpportunityId IN :Trigger.New];
            List<OpportunityContactRole> newOcrList = new List<OpportunityContactRole>();

            if(!ocrList.isEmpty()) {
                Map<Id, Id> oldOpNewOpIdMap = new Map<Id, Id>();
                for(Opportunity opNew : listOppor) {
                    oldOpNewOpIdMap.put(opNew.Parent_Opportunity__c, opNew.Id);
                }   
                for(OpportunityContactRole ocr : ocrList) {
                    OpportunityContactRole newOcr = new OpportunityContactRole();
                    newOcr.ContactId = ocr.ContactId;
                    newOcr.Role = ocr.Role;
                    newOcr.OpportunityId = oldOpNewOpIdMap.get(ocr.OpportunityId);
                    newOcrList.add(newOcr);
                }
                insert newOcrList;
            }
            
          List<OpportunityLineItem> oliList = [SELECT OpportunityId, PricebookEntryId, UnitPrice, Quantity, Duration__c, Payment_Terms__c, Discount FROM OpportunityLineItem WHERE OpportunityId IN :Trigger.New];
          List<OpportunityLineItem> newoliList = new List<OpportunityLineItem>();
          
          if(!oliList.isEmpty()) {
                Map<Id, Id> oldOpNewOpIdMap2 = new Map<Id, Id>();
                for(Opportunity opNew : listOppor) {
                    oldOpNewOpIdMap2.put(opNew.Parent_Opportunity__c, opNew.Id);
                }   
                for(OpportunityLineItem oli : oliList) {
                    OpportunityLineItem newOli = new OpportunityLineItem();
                    newOli.UnitPrice = oli.UnitPrice;
                    
                    newOli.PricebookEntryId = oli.PricebookEntryId;
                    newOli.Quantity = oli.Quantity;
                    newOli.Duration__c = 12;
                   
                    newOli.Payment_Terms__c = oli.Payment_Terms__c;
                    newOli.Discount = oli.Discount;
                    newOli.OpportunityId = oldOpNewOpIdMap2.get(oli.OpportunityId);
                    
                    
                    newoliList.add(newOli);
                }
                insert newoliList;
            }

            
        }
        
        

    }

    if(trigger.isInsert){
        try{
            //OpportunityLineItem[] lines = new OpportunityLineItem[0];
            //PricebookEntry entry = [SELECT Id, UnitPrice FROM PricebookEntry WHERE Pricebook2Id = :standardBook.Id AND Product2.ProductCode = 'ENTERPRISE_ANNUAL_UPFRONT'];
            List<Event> eventList = new List<Event>();
            //List<Note> noteList = new List<Note>();


            for(Opportunity o: Trigger.new){
                if(o.Is_Clone__c == true){

                    //noteList.add(new Note(ParentId=o.id,Title='Matt is the Apex_God',Body='Matt is the Apex_God',isPrivate=false));

                    //lines.add(new OpportunityLineItem(PricebookEntryId=entry.Id, OpportunityId=o.Id, UnitPrice=entry.UnitPrice, Quantity=1));

                    if(o.Renewal_Date__c != null){

                        DateTime myDateTime = o.Renewal_Date__c.addMonths(-10);
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime,subject='Account Management Follow-Up', EndDateTime=myDateTime, IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(2),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(2), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(4),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(4), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(6),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(6), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(8),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(8), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(10),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(10), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(10),subject='Renewal',EndDateTime=myDateTime.addMonths(10), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(9),subject='Sales Contract Follow-Up',EndDateTime=myDateTime.addMonths(9), IsAllDayEvent=true));

                    }//end of if

                }
            }
            //insert lines;
            insert eventList;
            //insert noteList;

        }
        catch(Exception e){

        }
    }
}
I wrote a trigger and a test class for it. The code coverage is 83% in the sandbox. When I try to roll it out, however, I get an error saying my code coverage is only 65% and that I can't deploy. I'm not sure why this is happening...

User-added image

Don't understand why my coverage changes when I go from the sandbox to deployment. I'm someone could help me figure this out, I'd appreciate it. Thanks
I wrote a trigger that duplicates Opportunities when their stage is updated to "Closed Won." The trigger also copies over some associated objects from the duplicated opp, changes the name of the new opp, and populates a field in the "Child Opportunity" called Parent_Opportunity__c, which contains the Id of the parent. The following code is my test, which I can't get to work right. It fails at the assertion statement. I'm trying to create an opportunity, add a product to it, and then change the stage to Closed Won, which should run the trigger, and then test that there exists a new opportunity with the original opportunity's Id as its Parent Opportunity.

Thanks in advance for the help. Here's the code:

@isTest (seeAllData=true)
private class testCreateFollowup{

static testMethod void test_Create_Followup() {

List<Account> aList = new List<Account>();    
Account a = new Account(
      Name = 'Test Account'
    );
    aList.add(a);
    
    insert aList;
    

List<Opportunity> oList = new List<Opportunity>();
Opportunity o = new Opportunity(
      Name = 'Test Opportunity', 
      StageName = 'Discovery', 
      CloseDate = Date.today(), 
      AccountId = a.Id
    );
    
    oList.add(o);
    insert oList;


        //Create Product
        Product2 prod = new Product2();
        prod.IsActive = true;
        prod.Name = 'Onboarding';
        prod.CanUseRevenueSchedule=true;
        insert prod;
        //Create PriceBook
        Pricebook2 pb = new Pricebook2();
        pb.Name = 'Test';
        pb.IsActive = true;
        insert pb;
    Pricebook2 standardpb = [Select Id, Name, IsActive From Pricebook2 where IsStandard = true LIMIT 1];
        
            
        PricebookEntry standardpbe = new PricebookEntry();
        standardpbe.Pricebook2Id = standardpb.Id;
        standardpbe.Product2Id = prod.Id;
        standardpbe.UnitPrice = 10000;
        standardpbe.IsActive = true;
        standardpbe.UseStandardPrice = false;
        insert standardpbe;
        
        PricebookEntry pbe = new PricebookEntry();
        pbe.Pricebook2Id = pb.Id;
        pbe.Product2Id = prod.Id;
        pbe.UnitPrice = 10000;
        pbe.IsActive = true;
        pbe.UseStandardPrice = false;
        insert pbe;
        

List<OpportunityLineItem> oliAnnuallyList = new List<OpportunityLineItem>(); 
       
OpportunityLineItem oliAnnually = new OpportunityLineItem(
        OpportunityId = o.Id,  
        PricebookEntryId = pbe.id,
        TotalPrice = 1,
        Quantity=2,
        Payment_Terms__c ='Annually',
        Duration__c = 12
        
    );
    
    oliAnnuallyList.add(oliAnnually);
    
    insert oliAnnuallyList;
    
    o.Stagename = 'Closed Won';

 List<Opportunity> lstOpty =[SELECT Parent_Opportunity__c from Opportunity];
 System.assertequals(lstOpty[0].Parent_Opportunity__c, o.Id);

}
}
I've written a trigger that duplicates an opportunity when we change its status to "Closed-Won." The idea is that every time we close an opportunity, we want to create a follow-up opportunity for pursuing that client again. My trigger makes a clone of the opportunity, adds some new products and schedule items, sets the status to discovery, and a couple of other minor things. As of right now, the trigger doesn't actually copy any objects associated with opportunity. Ideally, if there's a way to do this, I want to copy all of the existing Contact Roles from the closed Opp to the new one. Here's my code...let me know if you have any questions about it or need to know anything about our setup. 

​Thanks! 

trigger Create_followup on Opportunity (before update, after insert) {

Pricebook2 standardBook = [SELECT Id FROM Pricebook2 WHERE Name = :'Ambition'];//Create an instance of the standard pricebook


if(Trigger.isUpdate){


List<Opportunity> listOppor = new List<Opportunity>();
for (Opportunity o: Trigger.new){

    if (o.StageName == 'Closed Won' && o.Stage_Change__c == false && o.Is_Clone__c == false){

        Opportunity oppNew = o.clone();
        oppNew.Name = oppNew.Name  + ' - Annual ' + o.CloseDate.year();
        
        if(o.Renewal_Date__c != null){
        oppNew.Renewal_Date__c = o.Renewal_Date__c.addYears(1);
        oppNew.CloseDate = o.Renewal_Date__c.addYears(1);}
        
        oppNew.StageName = 'Discovery';
        oppNew.Probability = 25;
       
        
        
        oppNew.Pricebook2Id = standardBook.Id;//associate the standard pricebook with this opportunity
        
        oppNew.Is_Clone__c = true;
        listOppor.add(oppNew);
        o.Stage_Change__c = true;
        
}

 
}//end of for loop

   if(listOppor.size() > 0){
 insert listOppor;       
        
}

}

if(trigger.isInsert){

try{
OpportunityLineItem[] lines = new OpportunityLineItem[0];
PricebookEntry entry = [SELECT Id, UnitPrice FROM PricebookEntry WHERE Pricebook2Id = :standardBook.Id AND Product2.ProductCode = 'ENTERPRISE_ANNUAL_UPFRONT'];
List<Event> eventList = new List<Event>();
//List<Note> noteList = new List<Note>();


for(Opportunity o: Trigger.new){
if(o.Is_Clone__c == true){

//noteList.add(new Note(ParentId=o.id,Title='Matt is the Apex_God',Body='Matt is the Apex_God',isPrivate=false));

lines.add(new OpportunityLineItem(PricebookEntryId=entry.Id, OpportunityId=o.Id, UnitPrice=entry.UnitPrice, Quantity=1));

if(o.Renewal_Date__c != null){

DateTime myDateTime = o.Renewal_Date__c.addMonths(-10);
 

eventList.add(new Event(whatid=o.id,startdatetime=myDateTime,subject='Account Management Follow-Up', EndDateTime=myDateTime, IsAllDayEvent=true));
eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(2),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(2), IsAllDayEvent=true));
eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(4),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(4), IsAllDayEvent=true));
eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(6),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(6), IsAllDayEvent=true));
eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(8),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(8), IsAllDayEvent=true));
eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(10),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(10), IsAllDayEvent=true));
eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(10),subject='Renewal',EndDateTime=myDateTime.addMonths(10), IsAllDayEvent=true));
eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(9),subject='Sales Contract Follow-Up',EndDateTime=myDateTime.addMonths(9), IsAllDayEvent=true));

}//end of if

}
}
insert lines;
insert eventList;
//insert noteList;

}
catch(Exception e){

}
}


}
I have an OpportunityLineItem trigger, and I am trying to write an IF statement that basicaly says "if this OpportunityLineItem's associated product belongs to the family 'Services', do X.

Right now, my IF statement looks like this:

 if(oli.Product2.Family == 'Services')

When I debug, this IF statement is never being entered, so I know my syntax is wrong somehow, I'm just not sure how to express what I want to in the code.

Thanks in advance for the help 
I have a trigger in my company's salesforce instance that I need to disable. I was told that in order to do this, I simply need to mark the trigger as inactive in my sandbox and then upload it again via a change set. When I do this, however, I get an error and it doesn't deploy my code. Here's the error:

System.AssertException: Assertion Failed: Expected: true, Actual: false 
Stack Trace: Class.testEditSchedule.testUpdateSchedule: line 108, column 1

The reason that the error is being thrown is because when I try to upload the deactivated trigger, my test class, which is uploaded with my trigger in my initial change set, fails at its assertion statement. I thought that maybe I needed to deactivate the test and re-upload that along with the deactivated trigger, but I can't figure out how to do that. 

I need to get this trigger down, because it's interfering with our company's ability to make new opportunity products. Hopefully someone can figure out why I can't manage to disable it.

Thanks
I wrote a trigger that adds schedule items to opportunity products when they're created, based on which product they are, how many are purchased, and for what duration. Our company has two different types of products right now: enterprise products and services. In my trigger, I need to handle the services differently than the enterprise products. They way I have been handling that is with an if statement that catches them by ID:

ID OnboardingPBE = [select id from PricebookEntry where product2.name='Onboarding' LIMIT 1].id;
ID TrainingPBE = [select id from PricebookEntry where product2.name='Training' LIMIT 1].id;

if(oli.PricebookEntryId == OnboardingPBE || oli.PricebookEntryId == TrainingPBE)

This logic is broken for some reason, and the above if statement never runs. Furthermore, it would be more efficient if I could figure out a way to just enter the if statement based on whether product family == 'services'...Is there a way I can do this?

If you need to see my whole trigger, I can upload it here. 

​Thanks
I deployed a trigger today, and it's running smoothly, but I forgot about a change I wanted to make to it in order to make it run more smoothly/avoid bugs. How do I actually remove an apex trigger from salesforce? Thanks
I posted a question about this yesterday, but didn't get any help...if anyone could just quickly walk me through this, I'd greatly appreciate it. I wrote a trigger that automatically creates revenue schedule items for opportunity products when those opp products are created. I'm trying to move it from the sandbox to my company's instance, but I need to test it first. This is my test class. As of now, it's not working. It's fairly straightforward/simple, which is why I'm confused that it's not working. If you need to see my trigger's source code, just let me know.

@isTest
private class testEditSchedule{

static testMethod void testUpdateSchedule() {
 
List<Account> aList = new List<Account>();    
Account a = new Account(
      Name = 'Test Account'
    );
    aList.add(a);
    
    insert aList;
    

List<Opportunity> oList = new List<Opportunity>();
Opportunity o = new Opportunity(
      Name = 'Test Opportunity', 
      StageName = 'Discovery', 
      CloseDate = Date.today(), 
      AccountId = a.Id
    );
    
    oList.add(o);
    insert oList;
        
List<OpportunityLineItem> oliList = new List<OpportunityLineItem>();        
OpportunityLineItem oli = new OpportunityLineItem(
        OpportunityId = o.Id,  
        PricebookEntryId = [select id from PricebookEntry where product2.name='Onboarding' LIMIT 1].id,
        TotalPrice = 1
    );
    oliList.add(oli);
    insert oliList;
    
    System.assertEquals(True, oli.HasRevenueSchedule);
    
  }
    
}
I wrote a trigger that automatically adds a revenue schedule to an opportunity product when that opp product is created.I need to release it into my company's salesforce instance, but cannot for the life of me figure out how testing works in order to get my code coverage up to the standard. Here's my test class as of now: 

@isTest
private class testEditSchedule{

static testMethod void testUpdateSchedule() {
 
List<Account> aList = new List<Account>();    
Account a = new Account(
      Name = 'Test Account'
    );
    aList.add(a);
    
    insert aList;
    

List<Opportunity> oList = new List<Opportunity>();
Opportunity o = new Opportunity(
      Name = 'Test Opportunity', 
      StageName = 'Discovery', 
      CloseDate = Date.today(), 
      AccountId = a.Id
    );
    
    oList.add(o);
    insert oList;
        
List<OpportunityLineItem> oliList = new List<OpportunityLineItem>();        
OpportunityLineItem oli = new OpportunityLineItem(
        OpportunityId = o.Id,  
        PricebookEntryId = [select id from PricebookEntry where product2.name='Onboarding' LIMIT 1].id,
        TotalPrice = 1
    );
    oliList.add(oli);
    insert oliList;
    
    System.assertEquals(True, oli.HasRevenueSchedule);
    
  }
    
}//end of test class

System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, Create_followup: execution of AfterInsert caused by: System.QueryException: List has no rows for assignment to SObject Trigger.Create_followup: line 3, column 1: []

When I run my test, I get the above exception, although I imagine this is not the only issue with my test. I would really appreciate some help figuring out how to correctly test a trigger. I can also provice the code for my trigger if need be. 


 
We believe that life is too short for work to feel small and we're looking for an experienced Salesforce developer who feels the same way. 

What We Do:
Ambition is a productivity platform for metric-based organizations. We focus on aligning incentives between employees and managers to drive sustainable performance while increasing transparency, accountability, and collaboration. Our primary method for doing this is through a "Fantasy Footall" type system where management chooses/benchmarks/weights activities for employee-based teams to compete over week-to-week across seasons. The result is a fundamental shift in company culture (through promotion of team dynamics, active coaching, and emphasis on daily behavior not quarterly goals). 

Interactive Demo: http://demoambition.com

What We Need:
Experienced Salesforce developer comfortable/knowledgable with Apex/REST/Metadata and the platform in general. We've pieced together our initial offering (now live in the AppExchange) and we're looking for somebody to own the Salesforce product moving forward. 

Who You Are:
You enjoy responsibility and learning new things. You find yourself constantly figuring out ways to combine Salesforce functionality to automate the user experience and raise the bar. You enjoy challenges and working alongside engineers who feel the same way. Ideally, you're familiar with Python and Django. 

Who We Are:
15 person team based in Chattanooga, Tennessee. We just graduated from the Y Combinator tech incubator and recently closed a round of funding from investors including Google Ventures, SV Angel, Redpoint, and Promus. We're scaling our customer base, revenue, team, product and looking for passionate people to join the team. We come from places like Google, HP, NASA, and Cisco and pride ourselves on clean code, open-source contributions, and solving impossible problems. 

If any of the above sounds interesting we would love to discuss the opportunity further. Feel free to email us with a resume and brief description as to why Ambition sounds interesting and what motivated you to reach out!

careers@ambition.com
My apex text class for a trigger I wrote has started failing ever since I added code to the trigger to avoid recursion. As I understand it, I need to update my test in order to ensure the class I wrote to stop the recursion in the trigger is covered. Here's the class I'm using. My trigger calls it before it runs to ensure the trigger only fires once:

public Class checkRecursive{
    private static boolean run = true;
    public static boolean runOnce(){
    if(run){
     run=false;
     return true;
    }else{
        return run;
    }
    }
}


And here's the test class:

@isTest (seeAllData=true)
private class testEditSchedule{

static testMethod void testUpdateSchedule() {
 
List<Account> aList = new List<Account>();    
Account a = new Account(
      Name = 'Test Account'
    );
    aList.add(a);
    
    insert aList;
    

List<Opportunity> oList = new List<Opportunity>();
Opportunity o = new Opportunity(
      Name = 'Test Opportunity', 
      StageName = 'Discovery', 
      CloseDate = Date.today(),
      Contract_Start_Date__c = Date.today(), 
      AccountId = a.Id
    );
    
    oList.add(o);
    insert oList;
    
        //Create Product
        Product2 prod = new Product2();
        prod.IsActive = true;
        prod.Name = 'Onboarding';
        prod.CanUseRevenueSchedule=true;
        insert prod;
        //Create PriceBook
        Pricebook2 pb = new Pricebook2();
        pb.Name = 'Test';
        pb.IsActive = true;
        insert pb;
        List<Pricebook2> PbList = [Select Id, Name, IsActive From Pricebook2 where IsStandard = true LIMIT 1];
    //Pricebook2 standardpb = [Select Id, Name, IsActive From Pricebook2 where IsStandard = true LIMIT 1];
        
            
        PricebookEntry standardpbe = new PricebookEntry();
        standardpbe.Pricebook2Id = PbList[0].Id;
        standardpbe.Product2Id = prod.Id;
        standardpbe.UnitPrice = 10000;
        standardpbe.IsActive = true;
        standardpbe.UseStandardPrice = false;
        insert standardpbe;
        
        PricebookEntry pbe = new PricebookEntry();
        pbe.Pricebook2Id = pb.Id;
        pbe.Product2Id = prod.Id;
        pbe.UnitPrice = 10000;
        pbe.IsActive = true;
        pbe.UseStandardPrice = false;
        insert pbe;
        
List<OpportunityLineItem> oliList = new List<OpportunityLineItem>(); 
List<OpportunityLineItem> oliAnnuallyList = new List<OpportunityLineItem>(); 
List<OpportunityLineItem> oliQuarterlyList = new List<OpportunityLineItem>(); 
List<OpportunityLineItem> oliMonthlyList = new List<OpportunityLineItem>(); 
       
OpportunityLineItem oliAnnually = new OpportunityLineItem(
        OpportunityId = o.Id,  
        PricebookEntryId = pbe.id,
        TotalPrice = 1,
        Quantity=2,
        Payment_Terms__c ='Annually',
        Duration__c = 12
        
    );
    OpportunityLineItem oliMonthly= new OpportunityLineItem(
        OpportunityId = o.Id,  
        PricebookEntryId = pbe.id,
        TotalPrice = 1,
        Quantity=2,
        Payment_Terms__c ='Monthly',
        Duration__c = 1
        
    );
    OpportunityLineItem oliQuarterly= new OpportunityLineItem(
        OpportunityId = o.Id,  
        PricebookEntryId = pbe.id,
        TotalPrice = 1,
        Quantity=2,
        Payment_Terms__c ='Quarterly',
        Duration__c = 3
        
    );
    OpportunityLineItem oli= new OpportunityLineItem(
        OpportunityId = o.Id,  
        PricebookEntryId = pbe.id,
        TotalPrice = 1,
        Quantity=2,
        Payment_Terms__c = 'Up Front',
        Duration__c = 12
        
    );
    oliAnnuallyList.add(oliAnnually);
    oliMonthlyList.add(oliMonthly);
    oliQuarterlyList.add(oliQuarterly);
    oliList.add(oli);
    insert oliList;
    insert oliAnnuallyList;
    insert oliQuarterlyList;
    insert oliMonthlyList;
    
    //Your trigger should have OpportunityLineItemSchedule logic then following asert will pass else it will fail
    List<OpportunityLineItem> lstOptyLi =[SELECT HasRevenueSchedule from OpportunityLineItem where Id =:oli.id];
    System.assertEquals(True, lstOptyLi[0].HasRevenueSchedule);
    List<OpportunityLineItem> lstOptyLi_2 =[SELECT HasRevenueSchedule from OpportunityLineItem where Id =:oliAnnually.id];
    System.assertEquals(True, lstOptyLi_2[0].HasRevenueSchedule);
    List<OpportunityLineItem> lstOptyLi_3 =[SELECT HasRevenueSchedule from OpportunityLineItem where Id =:oliQuarterly.id];
    System.assertEquals(True, lstOptyLi_3[0].HasRevenueSchedule);
    List<OpportunityLineItem> lstOptyLi_4 =[SELECT HasRevenueSchedule from OpportunityLineItem where Id =:oliMonthly.id];
    System.assertEquals(True, lstOptyLi_4[0].HasRevenueSchedule);
   
  }
    
}


What do I need to do to add coverage for the new class?

Thanks
I wrote the following class to call from my triggers and ensure they don't run recursively. This is the code:

public Class checkRecursive{
    private static boolean run = true;
    public static boolean runOnce(){
    if(run){
     run=false;
     return true;
    }else{
        return run;
    }
    }
}

Do I need to write a test class for this class in order to push it to our instance? If so, can someone point me in the right direction? Thanks.
I'm getting the following error when I try to set an opportunity to closed won:

Error:Apex trigger Create_followup caused an unexpected exception, contact your administrator: Create_followup: execution of BeforeUpdate caused by: System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, editSchedule: execution of AfterInsert caused by: System.DmlException: Insert failed. First exception on row 0 with id 00oU0000002ulNkIAI; first error: INVALID_FIELD_FOR_INSERT_UPDATE, cannot specify Id in an insert call: [Id] Trigger.editSchedule: line 144, column 1: []: Trigger.Create_followup: line 88, column 1

The two triggers mentioned in the error are both triggers I wrote. Can anyone tell me what this type of error might be caused by?

Thanks
I've been looking for some help accessing the account name of an opportunity in my trigger, but none of the suggestions I've gotten so far have helped. This trigger duplicates opportunities in order to create followup opps. Currently we just append "annual 2015" or whatever year it is to the end of the opportunity name, but we want to make it so that the name of the new opp has the account name of the original opp followed by the word annual and the year. So rather than "oppNew.Name = oppNew.Name  + ' - Annual ' + o.CloseDate.year();" it would be "oppNew.Name = o.Account.Name + ' - Annual" + o.CloseDate.year();" or something like that. The suggestions I already tried either created opps with "null" for the account part of the name, or completely stopped duplicating opps altogether. Any help on figuring this out would be greatly appreciated. Thanks!

trigger Create_followup on Opportunity (before update, after insert) {
    List<Pricebook2> standardBook = [SELECT Id FROM Pricebook2 WHERE Name = :'Ambition'];//Create an instance of the standard pricebook
    
    if(Trigger.isUpdate){
        List<Opportunity> listOppor = new List<Opportunity>();
        for (Opportunity o: Trigger.new){
            if (o.StageName == 'Closed Won' && o.Stage_Change__c == false){

                Opportunity oppNew = o.clone();
                oppNew.Name = oppNew.Name  + ' - Annual ' + o.CloseDate.year();
                
                if(o.Renewal_Date__c != null){
                oppNew.Renewal_Date__c = o.Renewal_Date__c.addYears(1);
                oppNew.CloseDate = o.Renewal_Date__c;}
                
                oppNew.StageName = 'Discovery';
                oppNew.Probability = 25;
                oppNew.Parent_Opportunity__c = o.Id;
                
                
                oppNew.Pricebook2Id = standardBook[0].Id;//associate the standard pricebook with this opportunity
                
                oppNew.Is_Clone__c = true;
                listOppor.add(oppNew);
                o.Stage_Change__c = true;
                
            }

        }//end of for loop

        if(listOppor.size() > 0){
            insert listOppor;
            
            List<OpportunityContactRole> ocrList = [SELECT OpportunityId, ContactId, Role FROM OpportunityContactRole WHERE OpportunityId IN :Trigger.New];
            List<OpportunityContactRole> newOcrList = new List<OpportunityContactRole>();

            if(!ocrList.isEmpty()) {
                Map<Id, Id> oldOpNewOpIdMap = new Map<Id, Id>();
                for(Opportunity opNew : listOppor) {
                    oldOpNewOpIdMap.put(opNew.Parent_Opportunity__c, opNew.Id);
                }   
                for(OpportunityContactRole ocr : ocrList) {
                    OpportunityContactRole newOcr = new OpportunityContactRole();
                    newOcr.ContactId = ocr.ContactId;
                    newOcr.Role = ocr.Role;
                    newOcr.OpportunityId = oldOpNewOpIdMap.get(ocr.OpportunityId);
                    newOcrList.add(newOcr);
                }
                insert newOcrList;
            }
            
          List<OpportunityLineItem> oliList = [SELECT OpportunityId, PricebookEntryId, UnitPrice, Quantity, Duration__c, Payment_Terms__c, Discount FROM OpportunityLineItem WHERE OpportunityId IN :Trigger.New];
          List<OpportunityLineItem> newoliList = new List<OpportunityLineItem>();
          
          if(!oliList.isEmpty()) {
                Map<Id, Id> oldOpNewOpIdMap2 = new Map<Id, Id>();
                for(Opportunity opNew : listOppor) {
                    oldOpNewOpIdMap2.put(opNew.Parent_Opportunity__c, opNew.Id);
                }   
                for(OpportunityLineItem oli : oliList) {
                    OpportunityLineItem newOli = new OpportunityLineItem();
                    newOli.UnitPrice = oli.UnitPrice;
                    
                    newOli.PricebookEntryId = oli.PricebookEntryId;
                    newOli.Quantity = oli.Quantity;
                    newOli.Duration__c = 12;
                   
                    newOli.Payment_Terms__c = oli.Payment_Terms__c;
                    newOli.Discount = oli.Discount;
                    newOli.OpportunityId = oldOpNewOpIdMap2.get(oli.OpportunityId);
                    
                    
                    newoliList.add(newOli);
                }
                insert newoliList;
            }

            
        }
        
        

    }

    if(trigger.isInsert){
        try{
            //OpportunityLineItem[] lines = new OpportunityLineItem[0];
            //PricebookEntry entry = [SELECT Id, UnitPrice FROM PricebookEntry WHERE Pricebook2Id = :standardBook.Id AND Product2.ProductCode = 'ENTERPRISE_ANNUAL_UPFRONT'];
            List<Event> eventList = new List<Event>();
            //List<Note> noteList = new List<Note>();


            for(Opportunity o: Trigger.new){
                if(o.Is_Clone__c == true){

                    //noteList.add(new Note(ParentId=o.id,Title='Matt is the Apex_God',Body='Matt is the Apex_God',isPrivate=false));

                    //lines.add(new OpportunityLineItem(PricebookEntryId=entry.Id, OpportunityId=o.Id, UnitPrice=entry.UnitPrice, Quantity=1));

                    if(o.Renewal_Date__c != null){

                        DateTime myDateTime = o.Renewal_Date__c.addMonths(-10);
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime,subject='Account Management Follow-Up', EndDateTime=myDateTime, IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(2),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(2), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(4),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(4), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(6),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(6), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(8),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(8), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(10),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(10), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(10),subject='Renewal',EndDateTime=myDateTime.addMonths(10), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(9),subject='Sales Contract Follow-Up',EndDateTime=myDateTime.addMonths(9), IsAllDayEvent=true));

                    }//end of if

                }
            }
            //insert lines;
            insert eventList;
            //insert noteList;

        }
        catch(Exception e){

        }
    }
}
I have a trigger that duplicates opportunities when we close them. Currently, the trigger just appends the word Annual and the current year to the end of the name of the duplicated opp for the name of the new opp. What I would like to do, however, is use the name of the opportunity's associated account instead. Is there an easy way to pull that info in and access the account's name? Here's my code, with the section I'm talking about bolded: 

trigger Create_followup on Opportunity (before update, after insert) {
    List<Pricebook2> standardBook = [SELECT Id FROM Pricebook2 WHERE Name = :'Ambition'];//Create an instance of the standard pricebook
    
    if(Trigger.isUpdate){
        List<Opportunity> listOppor = new List<Opportunity>();
        for (Opportunity o: Trigger.new){
            if (o.StageName == 'Closed Won' && o.Stage_Change__c == false){

                Opportunity oppNew = o.clone();
                oppNew.Name = oppNew.Name  + ' - Annual ' + o.CloseDate.year();
                
                if(o.Renewal_Date__c != null){
                oppNew.Renewal_Date__c = o.Renewal_Date__c.addYears(1);
                oppNew.CloseDate = o.Renewal_Date__c;}
                
                oppNew.StageName = 'Discovery';
                oppNew.Probability = 25;
                oppNew.Parent_Opportunity__c = o.Id;
                
                
                oppNew.Pricebook2Id = standardBook[0].Id;//associate the standard pricebook with this opportunity
                
                oppNew.Is_Clone__c = true;
                listOppor.add(oppNew);
                o.Stage_Change__c = true;
                
            }

        }//end of for loop

        if(listOppor.size() > 0){
            insert listOppor;
            
            List<OpportunityContactRole> ocrList = [SELECT OpportunityId, ContactId, Role FROM OpportunityContactRole WHERE OpportunityId IN :Trigger.New];
            List<OpportunityContactRole> newOcrList = new List<OpportunityContactRole>();

            if(!ocrList.isEmpty()) {
                Map<Id, Id> oldOpNewOpIdMap = new Map<Id, Id>();
                for(Opportunity opNew : listOppor) {
                    oldOpNewOpIdMap.put(opNew.Parent_Opportunity__c, opNew.Id);
                }   
                for(OpportunityContactRole ocr : ocrList) {
                    OpportunityContactRole newOcr = new OpportunityContactRole();
                    newOcr.ContactId = ocr.ContactId;
                    newOcr.Role = ocr.Role;
                    newOcr.OpportunityId = oldOpNewOpIdMap.get(ocr.OpportunityId);
                    newOcrList.add(newOcr);
                }
                insert newOcrList;
            }
            
          List<OpportunityLineItem> oliList = [SELECT OpportunityId, PricebookEntryId, UnitPrice, Quantity, Duration__c, Payment_Terms__c, Discount FROM OpportunityLineItem WHERE OpportunityId IN :Trigger.New];
          List<OpportunityLineItem> newoliList = new List<OpportunityLineItem>();
          
          if(!oliList.isEmpty()) {
                Map<Id, Id> oldOpNewOpIdMap2 = new Map<Id, Id>();
                for(Opportunity opNew : listOppor) {
                    oldOpNewOpIdMap2.put(opNew.Parent_Opportunity__c, opNew.Id);
                }   
                for(OpportunityLineItem oli : oliList) {
                    OpportunityLineItem newOli = new OpportunityLineItem();
                    newOli.UnitPrice = oli.UnitPrice;
                    
                    newOli.PricebookEntryId = oli.PricebookEntryId;
                    newOli.Quantity = oli.Quantity;
                    newOli.Duration__c = 12;
                   
                    newOli.Payment_Terms__c = oli.Payment_Terms__c;
                    newOli.Discount = oli.Discount;
                    newOli.OpportunityId = oldOpNewOpIdMap2.get(oli.OpportunityId);
                    
                    
                    newoliList.add(newOli);
                }
                insert newoliList;
            }

            
        }
        
        

    }

    if(trigger.isInsert){
        try{
            //OpportunityLineItem[] lines = new OpportunityLineItem[0];
            //PricebookEntry entry = [SELECT Id, UnitPrice FROM PricebookEntry WHERE Pricebook2Id = :standardBook.Id AND Product2.ProductCode = 'ENTERPRISE_ANNUAL_UPFRONT'];
            List<Event> eventList = new List<Event>();
            //List<Note> noteList = new List<Note>();


            for(Opportunity o: Trigger.new){
                if(o.Is_Clone__c == true){

                    //noteList.add(new Note(ParentId=o.id,Title='Matt is the Apex_God',Body='Matt is the Apex_God',isPrivate=false));

                    //lines.add(new OpportunityLineItem(PricebookEntryId=entry.Id, OpportunityId=o.Id, UnitPrice=entry.UnitPrice, Quantity=1));

                    if(o.Renewal_Date__c != null){

                        DateTime myDateTime = o.Renewal_Date__c.addMonths(-10);
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime,subject='Account Management Follow-Up', EndDateTime=myDateTime, IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(2),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(2), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(4),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(4), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(6),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(6), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(8),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(8), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(10),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(10), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(10),subject='Renewal',EndDateTime=myDateTime.addMonths(10), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(9),subject='Sales Contract Follow-Up',EndDateTime=myDateTime.addMonths(9), IsAllDayEvent=true));

                    }//end of if

                }
            }
            //insert lines;
            insert eventList;
            //insert noteList;

        }
        catch(Exception e){

        }
    }
}
I wrote a trigger and a test class for it. The code coverage is 83% in the sandbox. When I try to roll it out, however, I get an error saying my code coverage is only 65% and that I can't deploy. I'm not sure why this is happening...

User-added image

Don't understand why my coverage changes when I go from the sandbox to deployment. I'm someone could help me figure this out, I'd appreciate it. Thanks
I wrote a trigger that duplicates Opportunities when their stage is updated to "Closed Won." The trigger also copies over some associated objects from the duplicated opp, changes the name of the new opp, and populates a field in the "Child Opportunity" called Parent_Opportunity__c, which contains the Id of the parent. The following code is my test, which I can't get to work right. It fails at the assertion statement. I'm trying to create an opportunity, add a product to it, and then change the stage to Closed Won, which should run the trigger, and then test that there exists a new opportunity with the original opportunity's Id as its Parent Opportunity.

Thanks in advance for the help. Here's the code:

@isTest (seeAllData=true)
private class testCreateFollowup{

static testMethod void test_Create_Followup() {

List<Account> aList = new List<Account>();    
Account a = new Account(
      Name = 'Test Account'
    );
    aList.add(a);
    
    insert aList;
    

List<Opportunity> oList = new List<Opportunity>();
Opportunity o = new Opportunity(
      Name = 'Test Opportunity', 
      StageName = 'Discovery', 
      CloseDate = Date.today(), 
      AccountId = a.Id
    );
    
    oList.add(o);
    insert oList;


        //Create Product
        Product2 prod = new Product2();
        prod.IsActive = true;
        prod.Name = 'Onboarding';
        prod.CanUseRevenueSchedule=true;
        insert prod;
        //Create PriceBook
        Pricebook2 pb = new Pricebook2();
        pb.Name = 'Test';
        pb.IsActive = true;
        insert pb;
    Pricebook2 standardpb = [Select Id, Name, IsActive From Pricebook2 where IsStandard = true LIMIT 1];
        
            
        PricebookEntry standardpbe = new PricebookEntry();
        standardpbe.Pricebook2Id = standardpb.Id;
        standardpbe.Product2Id = prod.Id;
        standardpbe.UnitPrice = 10000;
        standardpbe.IsActive = true;
        standardpbe.UseStandardPrice = false;
        insert standardpbe;
        
        PricebookEntry pbe = new PricebookEntry();
        pbe.Pricebook2Id = pb.Id;
        pbe.Product2Id = prod.Id;
        pbe.UnitPrice = 10000;
        pbe.IsActive = true;
        pbe.UseStandardPrice = false;
        insert pbe;
        

List<OpportunityLineItem> oliAnnuallyList = new List<OpportunityLineItem>(); 
       
OpportunityLineItem oliAnnually = new OpportunityLineItem(
        OpportunityId = o.Id,  
        PricebookEntryId = pbe.id,
        TotalPrice = 1,
        Quantity=2,
        Payment_Terms__c ='Annually',
        Duration__c = 12
        
    );
    
    oliAnnuallyList.add(oliAnnually);
    
    insert oliAnnuallyList;
    
    o.Stagename = 'Closed Won';

 List<Opportunity> lstOpty =[SELECT Parent_Opportunity__c from Opportunity];
 System.assertequals(lstOpty[0].Parent_Opportunity__c, o.Id);

}
}