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

create a new opportunity trigger

HI,

I am new to apex and having ago at my first trigger.

We have a set of support contracts that need new opportunities each year and I would like to try and automate this so once an opporuntity is set to closed won, a new opportunity, with the type of 'renewal', creates a new opportunity and eventually a quote also...

I have tried my first trigger and test class as below and getting an error that no rows are found so think I maybe missing a select statement or somethign obvious: -

trigger NewOppAndQuote on Opportunity (After Insert, After Update) {

    List<Opportunity> ListOpp = New List<Opportunity>();
    for(Opportunity o  : Trigger.new)
    {
        If(o.Opportunity_Type__c == 'Contract Renewal' &&
           o.StageName == 'Won' &&
           o.Remaining_Opportunity_Days__c == 73) 
     {
     
     Opportunity OppNew = New Opportunity();
     OppNew.Name = 'Opportunity.Account + TODAY()';
     OppNew.StageName = 'Pipeline';
     OppNew.AccountId = o.AccountId;
     OppNew.Opportunity_Type__c = 'Contract Renewal';
     OppNew.Estimated_Value__c = 100;
     OppNew.Opportunity_Submission_Date__c = Date.TODAY();
     OppNew.CloseDate = Date.TODAY() + 365;
     OppNew.Probability__c = '80-100%';
     OppNew.Solution_Summary__c = 'Maintinence';
     OppNew.Description = 'Renewal Contract for the next financial year';
     OppNew.Outcome_Status__c = 'Bid Submission Approved';
     
         ListOpp.add(OppNew);
          }
       }
     if (listOpp.size() > 0)
     insert listOpp;
}

test class which errors no rows are found: -

@IsTest

Private Class testNewOppAndQuote {
    static testMethod void testNewOppAndQuote(){
    
    Account a = [select Id from Account];
    Opportunity o = new Opportunity();
    
    o.AccountId = a.Id;
    o.StageName = 'Pipeline';
    o.Name = 'Opportunity.Account + TODAY()';
    o.Opportunity_Type__c = 'Contract Renewal';
    o.Estimated_Value__c = 100;
    o.Opportunity_Submission_Date__c = Date.TODAY();
    o.CloseDate = Date.TODAY() + 365;
    o.Probability__c = '80-100%';
    o.Solution_Summary__c = 'Maintinence';
    o.Description = 'Renewal Contract for the next financial year';
    o.Outcome_Status__c = 'Bid Submission Approved';
    
    insert o;
    
}

}

Any help appreciated and also any useful books or sourced to learn this a bit more is also good as although this is not workingI am enjoying doing it
Thanks
Best Answer chosen by Cushty
Amit Chaudhary 8Amit Chaudhary 8
PLease try below.
@IsTest

Private Class testNewOppAndQuote 
{
    static testMethod void testNewOppAndQuote()
	{
		
		Account a = new Account();
		a.name ='demo';
		insert a;
		Opportunity o = new Opportunity();
		
		o.AccountId = a.Id;
		o.StageName = 'Won';
		o.Name = 'Opportunity.Account + TODAY()';
		o.Opportunity_Type__c = 'Contract Renewal';
		o.Estimated_Value__c = 100;
		o.Opportunity_Submission_Date__c = Date.TODAY();
		o.CloseDate = Date.TODAY() + 365;
		o.Probability__c = '80-100%';
		o.Solution_Summary__c = 'Maintinence';
		o.Description = 'Renewal Contract for the next financial year';
		o.Outcome_Status__c = 'Bid Submission Approved';
		//o.Remaining_Opportunity_Days__c  = 73; please uncomment this line if this number field not formula
		insert o;
    
	}
}

 

All Answers

Michał Zadrużyński 2Michał Zadrużyński 2
When writing test class you need to provide test data first. In context of test there is no accounts at all. Test do not have access to real data in your org unless you you mark test (SeeAllData=true). My suggestion is to insert account in first line of test method and use it in test. Good practise is to add also User with standard profile and do all changes Test.runAs()
JeffreyStevensJeffreyStevens
Also a couple of other thought.

So, if I close the opportunty when the remaining days is 72 or 74, or anything other than 73 - the new opportuity won't be created.  I assume that's not what you are wanting.

Also, Did you look at doing this with process builder?  I think it could be done that way also - saving you custom code work. 
Amit Chaudhary 8Amit Chaudhary 8
PLease try below.
@IsTest

Private Class testNewOppAndQuote 
{
    static testMethod void testNewOppAndQuote()
	{
		
		Account a = new Account();
		a.name ='demo';
		insert a;
		Opportunity o = new Opportunity();
		
		o.AccountId = a.Id;
		o.StageName = 'Won';
		o.Name = 'Opportunity.Account + TODAY()';
		o.Opportunity_Type__c = 'Contract Renewal';
		o.Estimated_Value__c = 100;
		o.Opportunity_Submission_Date__c = Date.TODAY();
		o.CloseDate = Date.TODAY() + 365;
		o.Probability__c = '80-100%';
		o.Solution_Summary__c = 'Maintinence';
		o.Description = 'Renewal Contract for the next financial year';
		o.Outcome_Status__c = 'Bid Submission Approved';
		//o.Remaining_Opportunity_Days__c  = 73; please uncomment this line if this number field not formula
		insert o;
    
	}
}

 
This was selected as the best answer
CushtyCushty
That worked once I added in any mandatory fields on account.  I cannot get the Opportuntiy Name to default to the Account Name + lastyear/this year + todays date....so basically Test Account - 2016/2017 - 10/02/2015

The 73 days was just to test it, what I am trying to do is auto create renewal opportunities.  So we get a lot of Opps which we want to auto create (including products) in January each year that are marked as 'renewals' opportunities and then auto create a quote for each at the same time as the creation of the opportunity

Do you think it would be more user friendly to either have a new visualforce page where I query all the current 'Contract renewal' opportunties and show them in a list and then a button clones them all with products and creates quotes or maybe try the flows and process builder for auto cloning all of the previous years contract renewal opps and quotes (if possible)?

Thanks for your help