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
jk51141jk51141 

Create a New Opportunity Record based on Stage = "Closed/Won"

    Hi everyone, I am fairly new to apex language.  I am trying to create a simple script that will create a new Opportunity (Renewal) if the Stage = "closed/won".  So, if an Opportunity Stage = "closed/won" create a new Opportunity, and duplicate any required fields and save the new record.  The trigger would also need to be dependent on Record Type because we have many other divisions using other Page Layouts or by Role. 

I have a hard time programming from scratch, especially on code that I have never written before.  Does anyone have examples of something like this?  Thanks


Message Edited by jk51141 on 05-06-2008 06:37 AM
ckempckemp
I would suggest a trigger that looks something like this:

Code:
trigger makeRenewalOpportunity on Opportunity (after update) {

    // Go through each updated record    
    for (Integer i = 0; i < Trigger.new.size(); i++) {
    
     // Make sure Opportunity has been changed to "Opportunity Won" (e.g. closed)
        if (Trigger.new[i].isWon == true && Trigger.old[i].isWon == false) {
            renewalOpp = Trigger.new[i].clone(false);
            // change the date here
            insert renewalOpp;
        }
    } 
}



jk51141jk51141
So when this trigger executes on Stage = "closed/won" can I store the Opportunity ID in a variable?  Therefore, I can then write a SOQL query to copy over my desired fields?  Basically Clone, but I need to increment the date to next year, and copy about 15 fields onto the new record from the just saved Opportunity. 


Message Edited by jk51141 on 05-06-2008 01:46 PM
ckempckemp
You certainly can store the Opportunity ID in a variable.  In fact, if you make a custom field for the Oppotunity object, say "Original Opportunity", then set this field in the cloned object to the original object, then you can track back to see the original object from the clone.

If you want to increment the date do it after clone() and before the insert of the new object.
jk51141jk51141
Code:
trigger makeRenewalOpportunity on Opportunity (after update) {

    // Go through each updated record    
    for (Integer i = 0; i < Trigger.new.size(); i++) {
    
     // Make sure Opportunity has been changed to "Opportunity Won" (e.g. closed)
        if (Trigger.new[i].isWon == true && Trigger.old[i].isWon == false) {
            renewalOpp = Trigger.new[i].clone(false);
            // change the date here
            insert renewalOpp;
        }
    } 
}

 I'm trying to determine if I am reading this right.  This line:
if (Trigger.new[i].isWon == true && Trigger.old[i].isWon == false)
renewalOpp = Trigger.new[i].clone(false);

This is checking if the new Opportunity is Won, and the old Opportunity is not Won then do not clone? Is this to prevent an infinite
loop? As much as I would want to just clone the previous Opportunity, I cannot. I would need to duplicate some fields from the previous
Opportunity, and also set certain fields like the stage, and type.
Can Trigger.old be used to reference the previous opportunity (like and ID for a SOQL statement).  Is this a unique identifier. 



Message Edited by jk51141 on 05-07-2008 08:33 AM
ckempckemp
Nope.  Trigger.old and Trigger.new are referring to the object BEFORE the update was made and AFTER the update was made (only one object). 

This line will clone the object:
renewalOpp = Trigger.new[i].clone(false);
Then you can do can do something like this:
renewalOpp.Previous_Opportunity__c = Trigger.new[i].Id;
This will make your new custom field in Opportunity (called "Previous Opportunity") for your cloned object point to the original one.
sgoremasgorema

Hello,

I built a very lengthy scontrol to do just this (auto create a renewal oppty when an oppty is closed won) and now would like to re-write this in apex. Am wondering if you figured out how to get the code to work and to update additional fields on the newly created oppty? If so, would you be willing to share your code? thanks!

 

 

 

 

SiriusBlackOpSiriusBlackOp
Not hard at all... what fields are being updated by your s-control and what values are they being set to?  Is there anything else that the current s-control is doing?
sgoremasgorema

Currently the scontrol is copying the value from a bunch of fields and then setting the value in some. Some are standard fields and some are custom. I just cant figure out how to get it to copy the products as well. i have the following Apex code so far which is only setting the Name and pushing out the Close Date by one year.

 

Code:
trigger makeRenewalOpportunity on Opportunity (after update) {

    // Go through each updated record    
    for (Integer i = 0; i < Trigger.new.size(); i++) {
    
     // Make sure Opportunity has been changed to "Opportunity Won" (e.g. closed)
        if (Trigger.new[i].isWon == true && Trigger.old[i].isWon == false) {
            Opportunity renewalOpp = Trigger.new[i].clone(false);
            renewalOpp.Name=Trigger.old[i].Name+ ' Renewal';
            renewalOpp.closedate = Trigger.old[i].closedate.addmonths(12);
            insert renewalOpp;
        }
    } 
}


 



Message Edited by sgorema on 08-12-2008 01:32 PM
SiriusBlackOpSiriusBlackOp

Yea... Ok... but that is also only part of a larger battle.  You just made it more complicated with products.  Also, wouldn't you also want to run this on on a brand new Opportunity?

First, think about Events.  The code you posted only fires when you Modify an Opportunity, not for Inserting a new one.  Furthermore, the code you posted does not fire for modifying or inserting OpportunityLines (products) because event-wise that is not a modification of the Opportunity.

So, you need two triggers.  One for Opportunities on the Insert and Update events (Possibly Delete???).  One for OpportunityLines on the Insert, Update and Delete events.  Those triggers then need to do different things for each of the given events (Insert, Update and Delete).

You need to think about how you want this to behave in all six paths. -- and how all these things might interact and be downstream chained together.  To further complicate the problem, you could very quickly start creating Errors due to exceeding the set salesforce limits.

I guess what I'm saying is that including Products just made this 2-fold, if not more, worse for you.  So I think you may want to think about the process (what users do [events], and what happens as a result) first and then build the code around that.  You might also find that you don't want your users doing certain things at all... like delete for instance.

So Much for Easy, Huh?!?!  :smileysurprised:

sgoremasgorema
hmm...I think I am confused! I only want this new opportunity created when an opportunity has been updated to a stage of Win. And since we have validation rules in place that prevent the user from going past our second sales stage without having products on the oppty there is no way that a user can create a new oppty and set the stage to Won in the intial insert. So why would I need to handle the insert event? Isn't Before Update enough? Also, our users cannot delete opptys, so that would not be needed either. And I just dont understand why i would need to handle the insertion or modification of oppty line items?
 
I simply want a Renewal Oppty created for any opportunity that is closed out as won. Maybe I am missing something???
thanks for your response!
SiriusBlackOpSiriusBlackOp
Ok that is good.  Can they add or delete a product from the opportunity after it is set to Won?
 
Paths:
  1. Insert Opp - No need to handle this due to validation rules.
  2. Update Opp - Look for Status Won and create duplicate Opp with OppLines.  What about changing the pricebook as this wipes out all of the OppLines?
  3. Delete Opp - No need to handle this. Users can not delete.
  4. Insert OppLine - ??? If status of Opp = Won, should we create a new duplicate Opp, or Modify the previously created Opp, or do nothing?
  5. Update OppLine - ??? If status of Opp = Won and If Quantity/price changes, then what? (I don't think you can change the product for the line item)
  6. Delete OppLine - ??? If status of Opp = Won, , should we create a new duplicate Opp, or Modify the previously created Opp, or do nothing?

One thing to make very clear, adding/changing/deleting a Opportunity Line Item no the Opportunity Does NOT fire the Insert/Update/Delete event for the Opportunity itself.  It only fires events for the OpportunityLine object itself.

I'm just trying to help you understand the whole scope of your need up front.  It is still doable, just needs to be very well defined is all.  :)

ckempckemp
You actually don't need two different triggers for both updating and inserting.  You can cover both cases like this:

Code:
trigger MyTrigger on Opportunity (after insert, after update) {

    if (Trigger.isUpdate) {
        // Do update-specific logic 
    } else {
        // Do insert-specific logic
    }
}

 

SiriusBlackOpSiriusBlackOp

Of course that is true... but they do still need a second trigger to handle the same instances for the OpportunityLineItem Object.  The "logical paths" is all that I'm talking about above, so of course you are right that you can combine many of those logical paths into the same trigger as you have shown, but what gets done in each of those user actions still needs to be thought out and explained.

I'm now wondering if the complexity made them want to just stick with the S-Control that they already had running.

pupetootpupetoot

Hi there - I was reading this info on cloning that you posted and I may have a few questions that I was wondering if you could answer.  I am not a developer but I would like to go back to our developer with some research to kick them in gear!! 

When we allow users to clone opportunities, it has opened up a few errors in the way our system works.

 For example:

1) If cloning a closed-won opportunity which has had a export licence check(workflow), the new opportunity created from the action of cloning will have a few errors...

a) The "Export Licence Check Required?" field will already be filled in with same answer as the original opportunity - and if this is Yes, it will trigger the export licence check workflow... i.e. send an email & create a task...

b) The "Export Licence Status" field will already be filled in with the same answer as the original opportunity - this may confuse Export-Control since they will think they have already performed the check....

 

2) If creating a new opportunity, the opportunity can be saved at any step without the validation rules being triggered.

Hence we can have opportunities at Closed-won which have not been filled in correctly!!!

What are we doing wrong and can we still offer cloning?  Can we allow cloning but only allow the opportunity to be cloned at a certain stage  so that the sales guy has to populate all the necessary export control requirements for the cloned opportunity?  What about products, can they clone with products or be prompted to add them once cloning? 

Any help would be greatly appreciated!! 

SiriusBlackOpSiriusBlackOp
If you have an APEX programmer available, then you are going to need them.
 
One issue that you will have to skirt is that APEX has functions like IsUpdate, IsInsert and IsDelete... but nothing that I know on in terms of IsClone.  So you will have to figure that out on your own by doing something like If IsInsert And Export_License_Status Not = null then Assume it is a clone and clear all of the fields.  There is probably more to this, but it gets you going.
 
One thought I just had... I didn't test this, but normally while saving a new record the trigger.old values will be null because it is a new object thus no old values... but in a clone situation you might find that trigger.old has values from the previous object.
 
Anyway, once you determine if it is a clone or not, then you can programatically clear all of the fields you need to and force the user into a situation where they must now be entered in.
 
Clear as mud?


Message Edited by SiriusBlackOp on 10-06-2008 12:41 PM