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
mi5terymi5tery 

my first trigger

Hi all,

 

I wonder if anyone can help or direct me.

 

I am trying to write my first trigger from scratch (until now I've only really updated existing ones and very rarely at that).

 

I have an object called "Audit" which has a lookup relationship to another object called "Reviewer".

 

What I need to happed is the following.

 

If within the Audit object the lookup for the reviewer changes, then two things need to happen:

 

1. Within the OLD Reviewer object I need to update a field called "Workload" and decrement the value within it by 1.

2. Within the NEW Reviewer object I need to update a field called "Workload" and increment the value within it by 1.

 

(If either old or new are blank/null then do nothing for that step but continue with the other step)

 

I think the above sounds pretty straightforward really but I'm stuck.

 

Any assistance would be gratefully received.

 

Thank you,

 

mi5tery

 

Best Answer chosen by Admin (Salesforce Developers) 
souvik9086souvik9086

Hi,

 

Create a class

public class FutureTriggerController{

public static boolean isFutureUpdate = false;

}

 

Modified Trigger

trigger reAllocateReviewer on AuditResponse__c (after update)
{
string oldReviewerID = null;
string newReviewerID = null;
if(FutureTriggerController.isFutureUpdate != true){
FutureTriggerController.isFutureUpdate =true;
if(Trigger.old[0].Reviewer__c != NULL)
{
oldReviewerID = Trigger.old[0].Reviewer__c;
}

if(Trigger.new[0].Reviewer__c)
{
newReviewerID = Trigger.new[0].Reviewer__c;
}

if (oldReviewerID != null && oldReviewerID != newReviewerID )
{
Reviewer__c oldReviewer = [SELECT Current_workload__c FROM Reviewer__c WHERE ID=:oldReviewerID];
System.debug('Old Reviewer = ' + oldReviewer.Id);
System.debug('Workload = ' + oldReviewer.Current_workload__c);
oldReviewer.Current_workload__c -= 1;
upsert oldReviewer;
}

if (newReviewerID != null && newReviewerID != oldReviewerID )
{
Reviewer__c newReviewer = [SELECT Current_workload__c FROM Reviewer__c WHERE ID=:newReviewerID];
System.debug('New Reviewer = ' + newReviewer.Id);
System.debug('Workload = ' + newReviewer.Current_workload__c);
newReviewer.Current_workload__c += 1;
upsert newReviewer;
}
}

 

THIS WILL PREVENT FROM CALLING THE TRIGGER TWICE

 

If this post is helpful please throw Kudos.If this post solves your problem kindly mark it as solution.

Thanks

 

All Answers

mi5terymi5tery

Here's what I have so far:

 

trigger reAllocateReviewer on AuditResponse__c (after update)
{
	string oldReviewerID = Trigger.oldMap.get(ID).Reviewer__c
	string newReviewerID = Trigger.newMap.get(ID).Reviewer__c
	
	if (oldReviewer != null)
	{
		Reviewer__c oldReviewer = [SELECT Current_workload__c 
					   FROM Reviewer__c
					   WHERE ID=:oldReviewerID];
		System.debug('Old Reviewer = '  + oldReviewer.Id);
		System.debug('Workload = '  + oldReviewer.Current_workload__c);
		oldReviewer.Current_workload__c = oldReviewer.Current_workload__c - 1;
	}
	
	if (newReviewer != null)
	{
		Reviewer__c newReviewer = [SELECT Current_workload__c 
					   FROM Reviewer__c
					   WHERE ID=:newReviewerID];
		System.debug('New Reviewer = '  + newReviewer.Id);
		System.debug('Workload = '  + newReviewer.Current_workload__c);
		newReviewer.Current_workload__c = newReviewer.Current_workload__c + 1;
	}
}

 

gedeefgedeef

I think (but i'm not sure) you could do this with workflows, however it does not look complicated, i would say :

for (integer i=0;i<trigger.new.size();i++)
{
    if ( trigger.new[i].Reviewer__c != trigger.old[i].Reviewer__c)
    {
      if (trigger.new[i].Reviewer__c!=null) trigger.new[i].Reviewer__r.Workload--;
      if (trigger.old[i].Reviewer__c!=null) trigger.old[i].Reviewer__r.Workload++;
    }
}

 

[edit :]

well i'm wrong you probably can't update reviewer from the trigger context, forget this one :)

Neha LundNeha Lund

trigger reAllocateReviewer on SKAResponse__c (before update)
{
  for(SKAResponse__c s:trigger.new)
  {
 string oldReviewerID = Trigger.oldMap.get(ID).Reviewer__c
 string newReviewerID = Trigger.newMap.get(ID).Reviewer__c
 
 Map<Id,String> reviewersMap=new Map<String,Id>();
 if (oldReviewer != null && oldReviewerID!=newReviewerID)
 {
  reviewersMap.put(oldReviewerID,'Old');
  reviewersMap.put(newReviewerID, 'New');
 }
 
 } List<Reviewer__c> reviewers=new List<Reviewer__c>();
 if(reviewersMap.size()>0)
 {
  for(Reviewer r:[SELECT Current_workload__c
        FROM Reviewer__c wHERE ID IN :reviewersMap.keyset()]
        {
          if(reviewersMap.get(r.id)=='Old')
       {
       r.Current_workload__c -=1;
       
       
      
       }
       else
       {
       r.Current_workload__c +=1;
       }
        reviewers.add(r);
       
        }
 }
 if(!reviewers.isEmpty())
  Database.update(reviewers);
 }

souvik9086souvik9086

Try this,

 

trigger reAllocateReviewer on AuditResponse__c (after update)
{

if(Trigger.old(0).Reviewer__c != NULL){
string oldReviewerID = Trigger.old(0).Reviewer__c;

}

if(Trigger.new(0).Reviewer__c){
string newReviewerID = Trigger.new(0).Reviewer__c;
}


if (oldReviewer != null)
{
Reviewer__c oldReviewer = [SELECT Current_workload__c
FROM Reviewer__c
WHERE ID=:oldReviewerID];
System.debug('Old Reviewer = ' + oldReviewer.Id);
System.debug('Workload = ' + oldReviewer.Current_workload__c);
oldReviewer.Current_workload__c = oldReviewer.Current_workload__c - 1;
upsert oldReviewer;
}

if (newReviewer != null)
{
Reviewer__c newReviewer = [SELECT Current_workload__c
FROM Reviewer__c
WHERE ID=:newReviewerID];
System.debug('New Reviewer = ' + newReviewer.Id);
System.debug('Workload = ' + newReviewer.Current_workload__c);
newReviewer.Current_workload__c = newReviewer.Current_workload__c + 1;
upsert newReviewer;
}
}

 

If this post is helpful please throw Kudos.If this post solves your problem kindly mark it as solution.

Thanks

Neha LundNeha Lund

Hey try this

trigger reAllocateReviewer on SKAResponse__c (before update)
{
  for(SKAResponse__c s:trigger.new)
  {
 string oldReviewerID = Trigger.oldMap.get(s.ID).Reviewer__c
 string newReviewerID = Trigger.newMap.get(s.ID).Reviewer__c
 
 Map<Id,String> reviewersMap=new Map<String,Id>();
 if (oldReviewer != null && oldReviewerID!=newReviewerID)
 {
  reviewersMap.put(oldReviewerID,'Old');
  reviewersMap.put(newReviewerID, 'New');
 }
 
 } List<Reviewer__c> reviewers=new List<Reviewer__c>();
 if(reviewersMap.size()>0)
 {
  for(Reviewer r:[SELECT Current_workload__c
        FROM Reviewer__c wHERE ID IN :reviewersMap.keyset()]
        {
          if(reviewersMap.get(r.id)=='Old')
       {
       r.Current_workload__c -=1;
       
       
      
       }
       else
       {
       r.Current_workload__c +=1;
       }
        reviewers.add(r);
       
        }
 }
 if(!reviewers.isEmpty())
  Database.update(reviewers);
 }

mi5terymi5tery
I didn't think you could use a workflow to edit the old object?
mi5terymi5tery

Hi souvik9086,

 

I amended a few typo's (my fault really) and got this:

 

trigger reAllocateReviewer on AuditResponse__c (after update)
{
   string oldReviewerID = null;
   string newReviewerID = null;
   
   if(Trigger.old(0).Reviewer__c != NULL)
   {
      oldReviewerID = Trigger.old(0).Reviewer__c;
   }

   if(Trigger.new(0).Reviewer__c)
   {
      newReviewerID = Trigger.new(0).Reviewer__c;
   }

   if (oldReviewerID != null)
   {
      Reviewer__c oldReviewer = [SELECT Current_workload__c FROM Reviewer__c WHERE ID=:oldReviewerID];
      System.debug('Old Reviewer = ' + oldReviewer.Id);
      System.debug('Workload = ' + oldReviewer.Current_workload__c);
      oldReviewer.Current_workload__c -= 1;
      upsert oldReviewer;
   }

   if (newReviewerID != null)
   {
      Reviewer__c newReviewer = [SELECT Current_workload__c FROM Reviewer__c WHERE ID=:newReviewerID];
      System.debug('New Reviewer = ' + newReviewer.Id);
      System.debug('Workload = ' + newReviewer.Current_workload__c);
      newReviewer.Current_workload__c += 1;
      upsert newReviewer;
   }
}

 Unfortunately for some reason the dev console says: "Variable does not exist: Trigger" - on line 8

Amritesh SinghAmritesh Singh

Hi,

 

Try this

 

I think you are looking for this

 

 

 

Code :

 

trigger reAllocateReviewer on AuditResponse__c (after update)
 {
  for(AuditResponse__c a : Trigger.New)
  {
    string oldReviewerID = Trigger.oldMap.get(a.ID).Reviewer__c;
    string newReviewerID = Trigger.newMap.get(a.ID).Reviewer__c;
    System.debug('@@Old Reviewer = '  + oldReviewerID);
    System.debug('@@Old Reviewer = '  + newReviewerID);
    
    Reviewer__c oldReviewer = [SELECT Current_workload__c FROM Reviewer__c WHERE ID=:oldReviewerID];
    Reviewer__c newReviewer = [SELECT Current_workload__c FROM Reviewer__c WHERE ID=:newReviewerID];
    if (oldReviewer!= null)
     {
        System.debug('Old Reviewer = '  + oldReviewer.Id);
        System.debug('Workload = '  + oldReviewer.Current_workload__c);
        oldReviewer.Current_workload__c = oldReviewer.Current_workload__c - 1;
        update oldReviewer;
     }
    
    if (newReviewer!= null)
     {
        System.debug('New Reviewer = '  + newReviewer.Id);
        System.debug('Workload = '  + newReviewer.Current_workload__c);
        newReviewer.Current_workload__c = newReviewer.Current_workload__c + 1;
        update newReviewer;
     }
    }
}

souvik9086souvik9086

I also do have a little fault there

 

trigger reAllocateReviewer on AuditResponse__c (after update)
{
   string oldReviewerID = null;
   string newReviewerID = null;
   
   if(Trigger.old[0].Reviewer__c != NULL)
   {
      oldReviewerID = Trigger.old[0].Reviewer__c;
   }

   if(Trigger.new[0].Reviewer__c)
   {
      newReviewerID = Trigger.new[0].Reviewer__c;
   }

   if (oldReviewerID != null)
   {
      Reviewer__c oldReviewer = [SELECT Current_workload__c FROM Reviewer__c WHERE ID=:oldReviewerID];
      System.debug('Old Reviewer = ' + oldReviewer.Id);
      System.debug('Workload = ' + oldReviewer.Current_workload__c);
      oldReviewer.Current_workload__c -= 1;
      upsert oldReviewer;
   }

   if (newReviewerID != null)
   {
      Reviewer__c newReviewer = [SELECT Current_workload__c FROM Reviewer__c WHERE ID=:newReviewerID];
      System.debug('New Reviewer = ' + newReviewer.Id);
      System.debug('Workload = ' + newReviewer.Current_workload__c);
      newReviewer.Current_workload__c += 1;
      upsert newReviewer;
   }
}

Can you check now?

 

If this post is helpful please throw Kudos.If this post solves your problem kindly mark it as solution.

Thanks

mi5terymi5tery

Hi Neha Lund,

 

I've tried this:

 

trigger reAllocateReviewer on SKAResponse__c (before update)
{
   for(SKAResponse__c s:trigger.new)
   {
      string oldReviewerID = Trigger.oldMap.get(s.ID).Reviewer__c;
      string newReviewerID = Trigger.newMap.get(s.ID).Reviewer__c;
 
      Map<Id, String> reviewersMap=new Map<Id, String>();
      if (oldReviewerID != null && oldReviewerID!=newReviewerID)
      {
         reviewersMap.put(oldReviewerID,'Old');
         reviewersMap.put(newReviewerID, 'New');
      }
   } 
   List<Reviewer__c> reviewers=new List<Reviewer__c>();
   if(reviewersMap.size()>0)
   {
      for(Reviewer r:[SELECT Current_workload__c FROM Reviewer__c WHERE ID IN :reviewersMap.keyset()])
      {
         if(reviewersMap.get(r.id)=='Old')
         {
            r.Current_workload__c -=1;
         }
         else
         {
            r.Current_workload__c +=1;
         }
         reviewers.add(r);
      }
   }
   if(!reviewers.isEmpty())
      Database.update(reviewers);
 }

 

I changed line 8  from this:

   Map<Id, String> reviewersMap=new Map<String, ID>();

 

as it was throwing this error: "Illegal assignment from MAP<String, ID> to MAP<Id, String>"

 

but now it throws this: "Variable does not exist: Current_workload__c" - line 22  - I have confirmed this is the exact api name.

 

mi5terymi5tery

Hi mritesh,

 

You solution works except... it increments and decrements twice!

 

so previous reviewer workload decreases by 2, and new reviewer workload increases by 2

Amritesh SinghAmritesh Singh

hey

 

I think you r missing something,cos i tried this in mine n its working fine as u wished.

increments by 1 n decrement by 1 .

mi5terymi5tery

Hi souvik 9086,

 

Your solution seems to work too - and as with mritesh the increments and decrements seem to happen twice.

 

I think it might be something on my elnd that I'm missing.

 

Let me get back to you both

gedeefgedeef

the double-run of a trigger is often caused by a workflow who updates the object after the trigger. Have a look on this way ?

Amritesh SinghAmritesh Singh

I think gedeef is right workflow is running this trigger again.Check that

souvik9086souvik9086

Can you change like this

 

trigger reAllocateReviewer on AuditResponse__c (after update)
{
   string oldReviewerID = null;
   string newReviewerID = null;
   
   if(Trigger.old[0].Reviewer__c != NULL)
   {
      oldReviewerID = Trigger.old[0].Reviewer__c;
   }

   if(Trigger.new[0].Reviewer__c)
   {
      newReviewerID = Trigger.new[0].Reviewer__c;
   }

   if (oldReviewerID != null && oldReviewerID != newReviewerID )
   {
      Reviewer__c oldReviewer = [SELECT Current_workload__c FROM Reviewer__c WHERE ID=:oldReviewerID];
      System.debug('Old Reviewer = ' + oldReviewer.Id);
      System.debug('Workload = ' + oldReviewer.Current_workload__c);
      oldReviewer.Current_workload__c -= 1;
      upsert oldReviewer;
   }

   if (newReviewerID != null && newReviewerID != oldReviewerID )
   {
      Reviewer__c newReviewer = [SELECT Current_workload__c FROM Reviewer__c WHERE ID=:newReviewerID];
      System.debug('New Reviewer = ' + newReviewer.Id);
      System.debug('Workload = ' + newReviewer.Current_workload__c);
      newReviewer.Current_workload__c += 1;
      upsert newReviewer;
   }
}

If this post is helpful please throw Kudos.If this post solves your problem kindly mark it as solution.

Thanks

mi5terymi5tery

Looking at the debug log I can see it is definitely running the trigger twice.

 

Is there anyway I can prevent this running twice in the code?  I'm struggling to find the right workflow as there are lots on this object.

gedeefgedeef
Don't think so.
Should be one who updates a field...
souvik9086souvik9086

Hi,

 

Create a class

public class FutureTriggerController{

public static boolean isFutureUpdate = false;

}

 

Modified Trigger

trigger reAllocateReviewer on AuditResponse__c (after update)
{
string oldReviewerID = null;
string newReviewerID = null;
if(FutureTriggerController.isFutureUpdate != true){
FutureTriggerController.isFutureUpdate =true;
if(Trigger.old[0].Reviewer__c != NULL)
{
oldReviewerID = Trigger.old[0].Reviewer__c;
}

if(Trigger.new[0].Reviewer__c)
{
newReviewerID = Trigger.new[0].Reviewer__c;
}

if (oldReviewerID != null && oldReviewerID != newReviewerID )
{
Reviewer__c oldReviewer = [SELECT Current_workload__c FROM Reviewer__c WHERE ID=:oldReviewerID];
System.debug('Old Reviewer = ' + oldReviewer.Id);
System.debug('Workload = ' + oldReviewer.Current_workload__c);
oldReviewer.Current_workload__c -= 1;
upsert oldReviewer;
}

if (newReviewerID != null && newReviewerID != oldReviewerID )
{
Reviewer__c newReviewer = [SELECT Current_workload__c FROM Reviewer__c WHERE ID=:newReviewerID];
System.debug('New Reviewer = ' + newReviewer.Id);
System.debug('Workload = ' + newReviewer.Current_workload__c);
newReviewer.Current_workload__c += 1;
upsert newReviewer;
}
}

 

THIS WILL PREVENT FROM CALLING THE TRIGGER TWICE

 

If this post is helpful please throw Kudos.If this post solves your problem kindly mark it as solution.

Thanks

 

This was selected as the best answer
mi5terymi5tery

It seems someone else had a similar problem:

 

http://boards.developerforce.com/t5/Apex-Code-Development/Apex-Trigger-Firing-Twice-How-to-Prevent/td-p/97897

 

I can't however work out how to apply that solution into mine.

mi5terymi5tery

Hi soivik9086,

 

I'll have a try with your solution

mi5terymi5tery
Adding in the new class worked perfectly.

Thank you everyone for your very speedy responses and assistance.