+ Start a Discussion
Joe BBJoe BB 

Trigger Bizzare bihavior with and without Data Loader

Hello Fellas,

 

I was advised to post here. Maybe you will be able to help.

I cannot get this trigger to work upon Data Loader Account upsert.

It works when I do the changes within the application (UI), but it does not when I change the account owner of using the Data Loader.  When I use the Data Loader to upsert account ownership, it changes ownership of ALL opportunities in ALL accounts no matter whether account owner for a particular opportunity has changed or not.

 

Objective: After A Data Loader account upsert - Check IF an owner of an opportunity is NOT the owner of the account and a sharing person of the account,
THEN change owner of that opportunity to the NEW owner of the account to which that opportunity pertains.


For this purpose there is a custom field in account called SLS2__c,  which is updated each time accounts are upserted. This field contains the 15 character SF UserID of the person who shares the account.

 

trigger updateOppOwner on Account (after insert, after update) {
  if (Trigger.isAfter) {
  Set<Id> acctIds = new Set<Id>();
    for (Account acct : Trigger.new) {
       acctIds.add(acct.Id);
       }    
 
    List<Opportunity> optyList = [SELECT OwnerId  FROM Opportunity WHERE AccountId in :acctIds];
    if ( !optyList.isEmpty() ) {
    for (Account acct : Trigger.new) {
        for(Opportunity opty : optyList ) {      
            if(opty.OwnerId != acct.OwnerId && opty.OwnerId != acct.SLS2__c){
               opty.OwnerId = acct.OwnerID;
                    } else {
                      opty.OwnerId = opty.OwnerId ;
           }
            }
        update optyList;
        }
    }
   }
}

 


Again, the trigger works when account ownership is changed manually, but when I use the Data Loader, it changes ownership of ALL opportunities in ALL accounts no matter whether account owner for a particular opportunity has changed or not.


Do you have any suggestions?

arizonaarizona

One thing that is troubling to me is that you are updating the optylist inside the for loops.

 

You should update the list outside of the for loops.

Vinit_KumarVinit_Kumar

Joe,

 

Arizona is right you should be updating the list outside the for loop.

 

Another thing,I can see you can check that if event is insert or update.What I mean to say is :

 

if(Trigger.isInsert){

 

// do your coding here

 

}

 

else if (Trigger.Isupdate){

 

for (Account newAcc: Trigger.new){

Account oldAcc = trigger.oldmap.get(newAcc.id);

if(oldAcc.OwnerId != newAcc.ownerId){ // this would check whether Account owner has been updated or not.

 

// do your coding here

}

 

}

 

}

Joe BBJoe BB

Thank you for the response.

 

<<Another thing,I can see you can check that if event is insert or update.>>

 

I am not sure exactly what you mean. I am not very familiar with programming. 

 

Currently, with Data Loader Upsert, the trigger updates all opportunities, even those that are not updated or inserted.

 

 

But the thing is that all existing accounts should be updated on a daily basis with account information such as statistics, no matter whether they change owners or not. So basically all accounts are updated. New accounts are inserted. Therefore we will have to use upsert.

 

Is there a solution with this Data Loader issue in your opinion?

 

 

 

 

 

Vinit_KumarVinit_Kumar

Joe,

 

I was saying that in your Trigger you can check whether it is an update event or insert event and based on that you can manipulate your code as per your requirement.

 

Please go through the below link to know more about Trigger context variables i.e. isInsert or isUpdate

 

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_triggers_context_variables.htm

Joe BBJoe BB

Thanks.

 

I will substitute isAfter with isUpdate and will test it.

But I cannot code it any further. I lack the knowledge to do so.

Joe BBJoe BB

This is another explanation that I received from the community board:

 

<<The error is in the following line.
 if(opty.OwnerId != acct.OwnerId && opty.OwnerId != acct.SLS2__c){

Say I have Account A, with OppA, Opp B and Account C with OppD, OppE

First it checks whether the oppty owner id of OppA!=Acccount A OwnerId

Then it checks whether oppty owner id of OppA!=Account B OwnerId

and hence it updates all the oppty ids with the new account id.

There should be an additional check whether the Account is the related account of the opportunity being compared. >>

 

Does  anyone have any idea how to fix that?

Vinit_KumarVinit_Kumar

Change your code from 

 

 List<Opportunity> optyList = [SELECT OwnerId  FROM Opportunity WHERE AccountId in :acctIds];
    if ( !optyList.isEmpty() ) {
    for (Account acct : Trigger.new) {
        for(Opportunity opty : optyList ) {      
            if(opty.OwnerId != acct.OwnerId && opty.OwnerId != acct.SLS2__c){
               opty.OwnerId = acct.OwnerID;
                    } else {
                      opty.OwnerId = opty.OwnerId ;
           }
            }
        update optyList;
        }
    }
   }
}

 

 

to

 


Map<Id,Opportunity> optyMap = new Map<Id,Opportunit>([SELECT OwnerId FROM Opportunity WHERE AccountId in :acctIds]);
if ( !optyMap.isEmpty() ) {
for (Account acct : Trigger.new) {
if(optyMap.containsKey(acct.id)){ //this would check all the opportunity is with the related account
if(opty.OwnerId != acct.OwnerId && opty.OwnerId != acct.SLS2__c){

// Do your coding here
}
}
}
}

 

Joe BBJoe BB

Thank you again Vinit.

 

I pasted your trigger:

============

trigger updateOppOwner on Account (after insert, after update) {
  if (Trigger.isAfter) {
  Set<Id> acctIds = new Set<Id>();
    for (Account acct : Trigger.new) {
       acctIds.add(acct.Id);
       }    
 
Map<Id,Opportunity> optyMap = new Map<Id,Opportunity>([SELECT OwnerId FROM Opportunity WHERE AccountId in :acctIds]);
if ( !optyMap.isEmpty() ) {
for (Account acct : Trigger.new) {
if(optyMap.containsKey(acct.id)){
//this would check all the opportunity is with the related account
if(opty.OwnerId != acct.OwnerId && opty.OwnerId != acct.SLS2__c){
               opty.OwnerId = acct.OwnerID;
                    } else {
                      opty.OwnerId = opty.OwnerId ;
           }
            }
        update optyList;
        }
    }
   }
}

===============

It returned an error:

Error: Compile Error: Variable does not exist: opty.OwnerId at line 14 column 16 

Line 14:  opty.OwnerId = acct.OwnerID;

Vinit_KumarVinit_Kumar

My bad,I forgot to add one line ,Please use below one :-

 

Map<Id,Opportunity> optyMap = new Map<Id,Opportunit>([SELECT OwnerId FROM Opportunity WHERE AccountId in :acctIds]);
if ( !optyMap.isEmpty() ) {
for (Account acct : Trigger.new) {
if(optyMap.containsKey(acct.id)){//this would check all the opportunity is with the related account

for(Opportunity opty : optyMap.values())

if(opty.OwnerId != acct.OwnerId && opty.OwnerId != acct.SLS2__c){

// Do your coding here
}

}
}
}
}

Joe BBJoe BB

Thanks again.

 

I just tested it with the DL. It did not update any opportunity at all.

 

This is the trigger:

====

trigger updateOppOwner on Account (after insert, after update) {

  if (Trigger.isAfter) {

  Set<Id> acctIds = new Set<Id>();

    for (Account acct : Trigger.new) {

       acctIds.add(acct.Id);

       }    

Map<Id,Opportunity> optyMap = new Map<Id,Opportunit>([SELECT OwnerId FROM Opportunity WHERE AccountId in :acctIds]);
if ( !optyMap.isEmpty() ) {
for (Account acct : Trigger.new) {
if(optyMap.containsKey(acct.id)){//this would check all the opportunity is with the related account

for(Opportunity opty : optyMap.values())

if(opty.OwnerId != acct.OwnerId && opty.OwnerId != acct.SLS2__c){

               opty.OwnerId = acct.OwnerID;

                    } else {

                      opty.OwnerId = opty.OwnerId ;

           }

            }

        }

    }

   }

}

====

 

I just removed : <<update optyList;>> from the end because it was returning an error.

 

Vinit_KumarVinit_Kumar

You are not updating any opportunity on ur code.so how u expect the opportunity to be updated.

 

After the for loop,please put below code : -

 

 update optyMap.values(); 

I forgot to addd,this should work 

Joe BBJoe BB

Unfortunately, still cannot get this to work.

 

I included the  update optyMap.values();

so the trigger looks like this:

<<<

trigger updateOppOwner on Account (after insert, after update) {
  if (Trigger.isAfter) {
  Set<Id> acctIds = new Set<Id>();
    for (Account acct : Trigger.new) {
       acctIds.add(acct.Id);
       }    
Map<Id,Opportunity> optyMap = new Map<Id,Opportunity>([SELECT OwnerId FROM Opportunity WHERE AccountId in :acctIds]);
if ( !optyMap.isEmpty() ) {
for (Account acct : Trigger.new) {
if(optyMap.containsKey(acct.id)){//this would check all the opportunity is with the related account
for(Opportunity opty : optyMap.values())
if(opty.OwnerId != acct.OwnerId && opty.OwnerId != acct.SLS2__c){
               opty.OwnerId = acct.OwnerID;
                    } else {
                      opty.OwnerId = opty.OwnerId ;
        }
       }
      update optyMap.values();
       }
     }
   }
}

>>>

 

I tested upserting with Data Loader - It updated Account owner as it should, but did NOT update Opportunity owner when account owner had changed.

 

I also tried by removing the following:

} else {
                      opty.OwnerId = opty.OwnerId ;

 

It did not work either.