+ Start a Discussion
Steve_WSteve_W 

Trigger Creating 2 Task records

Hi, I am working on the trigger below to insert a task when my custom object record has a specific Status value. The below code is what i have been able to piece together.

 

 

trigger SOWCompleteTask on SOW_Request__c (after update) {
List<Task> tsk = new List<Task>();
for (SOW_Request__c sow : Trigger.New)
if (sow.SOW_Status__c == 'SOW Completed'){
tsk.add (new Task(
Subject = 'SoW walkthrough with customer',
Status = 'Waiting on someone else',
ActivityDate = System.today()+10,
WhatId = sow.Id));
}
insert tsk;

}

 

There are 2 main issues i am having.

 

1. the first time the trigger runs it inserts 2 task records

2. additional record edits result in the creation of 1 new task record.

 

How can i stop the creation of the duplicate record? AND How can i prevent the task from being created again when the record is saved and still meets my criteria?

 

any help is greatly appreciated.

fairly new to apex so go easy on me :)

bob_buzzardbob_buzzard

I wouldn't expect that trigger to create two records - that smacks that you have another trigger somewhere in your transaction that is updating the record, causing your trigger to fire again.

 

Do you only want to create a task when the SOW_Status__c field transitions to 'SOW Completed'?  If so, you should compare the previous and current values and only create the task when that happens:

 

for (SOW_Request__c sow : Trigger.New)
  if ( (sow.SOW_Status__c == 'SOW Completed') &&
       (Trigger.oldMap.get(sow.id).SOW_Status__c!='SOW Completed') )
  {
    tsk.add (new Task(
    Subject = 'SoW walkthrough with customer',
    Status = 'Waiting on someone else',
    ActivityDate = System.today()+10,
    WhatId = sow.Id));
  }

 

MellowRenMellowRen

Steve_w

 

For Issue 1:

 

Your code looks correct to me. From your problem description, I would immediately wonder about:

 

  1. Do you have any other triggers on SOW_Request__c?
  2. Do you have any triggers on Task?

Most likely candidate would be the first one. What I am mainly thinking here is that you have accidently updated the record twice and as a result created two tasks (ie your issue 1 is also an offshoot of issue 2). .

 

If you have no other triggers, can you try a rewrite of your code as such:

 

trigger SOWCompleteTask on SOW_Request__c (after update) {
List<Task> tsk = new List<Task>(); for (SOW_Request__c sow : Trigger.New) { if (sow.SOW_Status__c == 'SOW Completed') {     tsk.add (new Task( Subject = 'SOW walkthrough with customer', Status = 'Waiting on someone else', ActivityDate = System.today()+10, WhatId = sow.Id ) ); } } insert tsk; }

 Yes, I am crazy. Yes, it shouldn't make a difference and I don't really think it will change the outcome but it is a two minute exercise :-)

 

For Issue 2:

 

There are a number of ways to tackle this, including using trigger.old or searching for existing tasks but I think the easiest way to understand, for a new programmer, would be to and assuming not knowing what other controls you have in place on the SOW_Request__c:

 

  1. Change the above to a before update trigger (unless there is a reason you require it to be after, in which case let us know).
  2. Create a new checkbox field in SOW_Request__c (default unchecked) with an API name something like "Have_created_Walkthough_Task__c". No need to have it visible in the page layouts.
  3. Change your code above so the the if statement reads like "if (sow.SOW_Status__c == 'SOW Completed'  && !sow.Have_created_Walkthough_Task__c)".
  4. Add a line inside the if statement of  "sow.Have_created_Walkthough_Task__c = true;".

 

Regards

MellowRen

 

EDIT: Man I need to learn to type faster. BB beat me to the punch.

Steve_WSteve_W

Thanks a ton guys this was a big help. Here is where i ended up.

 

trigger SOWCompleteTask on SOW_Request__c (before update) {
  List<Task> tsk = new List<Task>();
  List<SOW_Request__c> SOWs = trigger.new;
  
		for (SOW_Request__c sow : SOWs)
		if ((sow.SOW_Status__c == 'SOW Completed') && (Trigger.oldMap.get(sow.id).SOW_Status__c!='SOW Completed') && (!sow.SOWCompleteTaskCreated__c)){
			tsk.add (new Task(
			Subject = 'SoW walkthrough with customer',
			Status = 'Waiting on someone else',
			ActivityDate = System.today()+10,
			WhatId = sow.Id,
			OwnerId = sow.Primary_Account_Manager__C ));
			sow.SOWCompleteTaskCreated__c = True;
	insert tsk;
		}
	

}

 

The check box was the key to preventing the duplicate thanks to this other trigger i have been working on as a part of the same enhancement.

 

trigger SOWonCreate on SOW_Request__c (before insert, before update) {
	//List<SOW_Request__c> sow = new List<SOW_Request__c>();
	
	for (SOW_Request__c s : Trigger.new){
		if(s.Primary_Account_Manager__c == null){
			s.Primary_Account_Manager__c = UserInfo.getUserId();
			system.debug(+s.Primary_Account_Manager__c);
		}
		}
	
}

 

It is my intent to only have the task created once and only when the record is intially set to the matching status, not on subsequent saves.

 

One question, when i tried the if condition of sow.SOWCompleteTaskCreated__c = false it did not work but when i changed it to !sow.SOWCompleteTaskCreated__c it did, not sure what the difference is but if you have a moment i'd love to know why.

 

In the long run i am thinking i should move these triggers to a helper class and consolidate to remove the need for the check box field but since these are my 1sy and 2nd triggers i think i'll leave that one for later.

MellowRenMellowRen

Steve_W

 

Ahh, yes that’s a bit of fun.

 

Checkboxes in Salesforce, despite their visual representation, are effectively tri-state variables. They can be one of the following values:

 

  1. true                 [   Checked   ]
  2. false               [ Unchecked ]
  3. null                 [ Unchecked ]

 

A quick look at your two versions of your condition and you'll see why they can produce different results (ie when SOWCompleteTaskCreated__c is null).

 

Since you are generally expecting checkboxes to be binary it is safer to use if(checkbox_name) and if(!checkbox_name) when coding rather than if(checkbox_name==true), etc. It also helps if you programmically create a record to specifically set all checkboxes to true or false.

 

Regards

MellowRen