1

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;
}
  • Can someone help me figure out why the code is creating 2 ops instead of one? If you create an ops with at win it only makes one clone.. but if you create the op at any other stage and then go back and update the stage it creates two. – Merry Stambaugh May 24 '13 at 23:28
  • I asked this question as a new question. – Merry Stambaugh May 25 '13 at 1:06
1

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;
}

}
|improve this answer|||||
  • Thanks! I could not access the link, but I would love to read it. I am just learning all of this (as you could tell by this and every other questions I ask!) I do have one question.. where does the variable (toCheck.id) come from? – Merry Stambaugh May 14 '13 at 2:57
  • sorry needs to be record.AccountId not toCheck.Id force.siddheshkabe.co.in/2012/01/… – Seb Wagner May 14 '13 at 5:46
  • Now I get this error.. time to sit down and learn this stuff! Thanks for your help! Error:Apex trigger partnerOpClone caused an unexpected exception, contact your administrator: partnerOpClone: execution of AfterUpdate caused by: System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, partnerOpClone: execution of AfterUpdate caused by: System.NullPointerException: Attempt to de-reference a null object Trigger.partnerOpClone: line 45, column 1: []: Trigger.partnerOpClone: line 49, column 1 – Merry Stambaugh May 14 '13 at 16:53
  • you didnt replace toCheck.Id with record.AccountId? in addition modify the code from line 46 with the following theClone.Name = accountMap.containsKey(record.AccountId) ? accountMap.get(record.AccountId).Name + ' Partner' : ' Partner Opp'; theClone.StageName = 'Training'l – Seb Wagner May 14 '13 at 22:07
  • Thanks again! That worked, the opp saved just fine, but now it makes 2 clones. This is fun, huh? I just cannot figure out why it is making 2 opps. – Merry Stambaugh May 15 '13 at 17:54
0

i think you're getting the error because when you use the syntax limit 1 states that there is in fact 1 record meeting your criteria. since you have more than 1, i think that's why you're erroring out. Change your syntax to a list of records, and then iterate through the list.

|improve this answer|||||
-1

The code below shows the difference between one rrecord returned in query vs many records returned in query. You need to story multiple records in a list of objects than a single object, in order to access & modify them one by one in a iterator:

Account acc = [select id , name from account limit 1] ; List conLst = new List() ; conLst = [select id , lastName from Contact where AccountId =: acc.Id] ; for(Contact c : conLst) { c.lastName = acc.name ; } update conLst ;

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.