[SalesForce] Cloning Opportunities

I have a quick question that I hope you can help me with. I have built a trigger that seems to work theoretically. When we have a partner op go to a win, I need the op to be cloned with a new stage, new name and no amount (other than those fields everything else can be the same) This trigger does that – however, after cloning the first opp, all opps clone to the account associated with the first opp. When I try to remove the 'LIMIT 1' I get the error below – I appreciate any help.

Error:Apex trigger partnerOpClone caused an unexpected exception,
contact your administrator: partnerOpClone: execution of AfterUpdate
caused by: System.QueryException: List has more than 1 row for
assignment to SObject: Trigger.partnerOpClone: line 2, column 1

Here is the trigger:

trigger partnerOpClone on Opportunity (after update) {
Opportunity opp = [select Id, closedate, account.name, account.id from Opportunity where StageName = '09-Win' and type = 'Reseller / Partner Registration'  LIMIT 1];
Opportunity newOpp = opp.clone(false, true);
newOpp.StageName='Training';
newOpp.amount=null;
String oppname = opp.account.Name +' Partner'; 
newopp.Name = oppname;
newOpp.closedate=opp.closedate;
newOpp.account.id=opp.account.id;
insert newOpp;
}

Best Answer

merry you get the exception, because you run out of opportunities that meet the criteria StageName = '09-Win' and Type 'Reseller / Partner Registration'. That is because your code does not necessarily clones the opportunity the user updates, but the first opportunity that is returned by your query

Opportunity opp = [select Id, closedate, account.name, account.id from Opportunity where StageName = '09-Win' and type = 'Reseller / Partner Registration'  LIMIT 1];

I strongly recommend you read https://force.siddheshkabe.co.in/2012/01/basic-of-writing-apex-trigger.html

Below the code, that archives what you are looking for

trigger partnerOpClone on Opportunity (after update) {

// accounts ids to query
Set<Id> oppAccountIds = new Set<Id>();
// opportunities we have to clone
Opportunity[] oppsToClone = new Opportunity[]{};
// clones to save
Opportunity[] oppsToSave = new Opportunity[]{};

String STAGE_WON = '09-Win';
String TYPE_PARTNER = 'Reseller / Partner Registration';

// bulkified handling
for (Opportunity record:trigger.new)
{

    // make sure the opportunity stage has been changed to new
    if (record.StageName == STAGE_WON && trigger.oldMap.get(record.Id).StageName !=  STAGE_WON
    && record.Type == TYPE_PARTNER)

    // keep for query
    oppAccountIds.add(toCheck.Id);

    // keep opps that meet the criteria for further processing
    oppsToClone.add(record);
}


// make sure we only continue , if there are any opps we have to cline
if (oppsToClone.size() > 0)
{

    // query accounts and store by there name to lookup it up quickly
    Map<Id,Account> accountMap = new Map<Id,Account>([
        select Id
             , Name
          from Account
         where Id IN: oppAccountIds]);

    // clone the opps
    for (Opportunity record:oppsToClone)
    {
        Opportunity theClone = record.clone(false,true);
        theClone.Amount = null;
        theClone.Name = accountMap.get(record.AccountId).Name + ' Partner';
        oppsToSave.add(theClone);
    }

    insert oppsToSave;
}

}