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
JD2010JD2010 

Help updating task before insert

I'm trying to do something I think is relatively simple. I am basically monitoring the insersts on a Task object. If one of the subjects of those inserts meets a certain criteria, I want to update the Comments field (Description) and have the new comments area inserted along with the rest of the Task information.

 

Been racking my brain on this, searched across the board and all but still haven't had much luck. If you have any insight, it's much appreciated!

 

The code below is runs without issue, I have a unit test and that's fine. Even when I throw in debugs in there, everything executes as it should. But still, the field never shows up updated.

 

 

trigger task_StoreMassEmailBody_upd on Task (before insert) {
	if(Trigger.isBefore) {
		for(Task t : Trigger.new) {
		    Boolean LogBody = Trigger.new[0].Subject.contains('special subject');
			if(LogBody) { t.Description = 'Win'; }
		}
	}
}

 What am I missing here? I've also tried it with an after update, and create a set of all the trigger.new ID's related to the task, and then iterate through those and do an update after (since, iirc, after insert the fields are ready only) but still no luck.

 

 

Thanks in advance!

Best Answer chosen by Admin (Salesforce Developers) 
orikkerorikker

Yeah, I think we are at dead end here... I don't see how you can do it, unless you want completly rewrite mass email functionallity... We had to do for lead conversion process in our org... There is a mass email class for apex... give it a shot.

 

I would start a new thread at this point. :)

All Answers

gm_sfdc_powerdegm_sfdc_powerde

This should work in case of a single task.  A batch insert could fail though since you are always checking the first record for the special subject.  If this is failing for single task too, you might want to check whether the trigger is active (setup -> activities -> task triggers -> "Is active" checkbox)

JD2010JD2010

Good call on the bulk. Updated it so it works in bulk instances. Unfortunately, it's still not working properly. And unfortuantely, the trigger is active. I wish that would have been the problem ; )

 

Updated code (for reference to bulk)

 

trigger task_StoreMassEmailBody_upd on Task (before insert) {
	if(Trigger.isBefore) {
		Integer i=0;
		for(Task t : Trigger.new) {
		    Boolean LogBody = Trigger.new[i].Subject.contains('special subject');
			if(LogBody) { t.Description = 'Win'; }
			i++;
		}
	}
}

 

 

Bhawani SharmaBhawani Sharma

Can you please try this :

 

trigger task_StoreMassEmailBody_upd on Task (before insert) {
if(Trigger.isBefore) {
for(Integer i = 0; i < Trigger.new.size(); i++) {
Boolean LogBody = Trigger.new[i].Subject.contains('special subject');
if(LogBody) { Trigger.new[i].Description = 'Win'; }
}
}
}
JD2010JD2010

Runs without errors, but oddly enough, the Comments (Description) field is still not being updated with 'Win'. Ran debug on it, too to check to make sure it's entering the LogBody area and it is. Not sure where the disconnect is happening.

 

Is it perhaps because of how it's being ran before insert? Would doing an after insert potentially be more effective? Though I'd hate to be making unnecessary queries.

 

Thanks again for the help thus far!

orikkerorikker

 

trigger task_StoreMassEmailBody_upd on Task (before insert) {
	
		for(Task t: Trigger.New) {
		 Boolean LogBody =t.Subject.contains('special subject');
			if(LogBody) { t.Description = 'Win'; }
		}
	
}

 Try this.

 

JD2010JD2010

I think that snippet will run into a batch issue as described by one of the earlier posters. That said, I tried using that, as well as modifying it some, again, compiles fine, but for some reason is still leaving the field untouched.

orikkerorikker

This is a bulk trigger, so it will work fine. The only part I am not sure about it t.subject.contains... does not seem like this will work...

 

could you chage it to and send me the log?

 

trigger task_StoreMassEmailBody_upd on Task (before insert) {

for(Task t: Trigger.New) {

String sub = t.subject;
Boolean LogBody =sub.contains('special subject');

 

system.debug ('***************************' + t.id + ' - ' + sub + ' - ' + logbody );


if(LogBody) {

t.Description = 'Win';

System.debug('#####################################' + t.Description); }


}

}

Bhawani SharmaBhawani Sharma

Hi ,

 

I am trying the exact trigger in my local org , what I have posted  and it really working fine for me:

 

trigger task_StoreMassEmailBody_upd on Task (before insert) {
if(Trigger.isBefore) {
for(Integer i = 0; i < Trigger.new.size(); i++) {
Boolean LogBody = Trigger.new[i].Subject.contains('special subject');
if(LogBody) { Trigger.new[i].Description = 'Win'; }
}
}
}

 

So i would suggest you to

  1. check data or your task being inserted.
  2. if the subject is in the same case as with you are comparing to.
  3. Do you have any custom field which has comments label.
  4. Workflow on the task , who is doing againg a field update.
orikkerorikker

Questions:

 

Why do you check if it's before?

why not use

 

for (task t:Trigger.New) {

if(t.subject.contains('special')) t.description = 'win';

}

 

just curious... any advantages?

Bhawani SharmaBhawani Sharma

It's always good to put the condition in the trigger.

JD2010JD2010

TechForce - I'll make those tests and see.  Thanks!

 

Orikker - I could be totally wrong in my thinking (given that I'm still new to SF). But the reason I run the check before insert as opposed to any of the after calls is to reduce CPU usage/run less code. If I do the check after insert, then I have to make an extra call to bypass read-only stuff (iirc), which I'd prefer avoiding since I'd rather just insert it all in one straight shot. If I do the call after update, it's unnecessary checking / cycles being used because I that comments field in this specific instance won't change once it's been inserted. It's strictly for logging purposes.

JD2010JD2010

TechForce - After doing a few checks, you're right that the trigger is in fact working. What's strange, however, is that it doesn't work when an activity is inserted via the mass mail run. Eg: If I do send an email and add "special subject" it runs fine. If I do a mass email whose subject contains (via the template) "special subject" it does't trigger.

Bhawani SharmaBhawani Sharma

One more suggestion:)

You can do the same thing from the workflow also and that will be a more convenient solution and I am 100% sure this will work with the Mail scenerio also.

JD2010JD2010

Ohh, brilliant idea. Only issue is that I am actually trying to update the Description to that of another field (using Win was just a simple way to test that it's working). Blast! So close.

Bhawani SharmaBhawani Sharma

Thanks dude, Please mark it resolved once you achieved.

JD2010JD2010

Still not resolved but I am wondering if this may be a bug in SF involving their mass email stuff since as far as I can tell - it should be working, and it does work when it's ran "normally" as it were.

orikkerorikker

Maybe I am wrong, but your code says

 

trigger task_StoreMassEmailBody_upd on Task (before insert) {

that is - it will only execute BEFORE INSERT... that condition check is good when you use trigger task_StoreMassEmailBody_upd on Task (before insert, after update) {

 

:)

orikkerorikker

Now I am really interested in figuring it out... Can you tell us the whole layout... What exactly are you trying to do...You obviously not going to use "special subject" and "win" in the descripton... :) 

 

So what is the end result?  

JD2010JD2010

I actually don't want it to run after the update, as there's really no purpose in it since I'm pretty much just using it as a log once.

 

Basically, the whole purpose of this is we use salesforce's mass email functionality at our company. What we're doing is actually combining merge fields with the mass email templates to send dynamically generated emails to particular customers of ours. However, for our service department, it's important for them to be able to know what was emailed in the event of a support request. Unfortunately, mass email doesn't log the body by default -- which is what I am trying to do. When the mass email is sent (and we know it's the right one based on our subject line), store the specific field data in the body of the new activity (as it's being created during the mass email activity update).

 

Let me know if that doesn't make sense. I've dealt so much with it, I sometimes get too deep in the explanation ; )

orikkerorikker

I think I get it. You send out mass email and when activity is logged, you need to put mass email content into task.

 

So how do you get the content of the mass email?

JD2010JD2010

Correct. Getting the contest of the mass email isn't an issue, since we dont really want the whole template. We actually just want the "meaty" data that our system generates, which is stored in a field at the Account level (which we can easily access since we're running this through Apex). The issue moreso is (I think), how come we can't put the content into the task that's created by the mass email activity, whether it's from a field or static?

orikkerorikker

Ok. then how do you query account from task trigger? here is were the problem might be. could you send me your code as is, whatever you have setup right now?

JD2010JD2010

Good question, hah. Didn't actually go that far yet, mainly because just getting it to update with the static 'Win' never worked, so I didn't progress it past that given if something static works, something dynamic obviously won't.

 

What I've posted is actually what I have as is currently (except the subject is slightly different). Otherwise I never wrote the rest given that it never worked with the static 'Win' and if doesn't work with that, it won't work with something dynamic. If I got the win to work, what I'd most likely do is back into the Account table. IE: I have the contactId that the task was created for, so I'd query the contact table, grab the accountId based on the contactId, and then grab the respective field.

JD2010JD2010

Anyone have any additional thoughts? Wondering if this shouldn't be chalked up to a bug.

JD2010JD2010

Been working on a potentially different avenue to explore this. Just to answer your question, below is the code I am currently utilizing and how I would go about it (although I am currently getting a concrete sObject error on Account[] acct = [Select...

 

 

trigger task_StoreMassEmailBody_upd on Task (before insert) {
	if(Trigger.isBefore) {
		for(Integer i = 0; i < Trigger.new.size(); i++) {
		    Boolean LogBody = Trigger.new[i].Subject.contains('special subject');
			if(LogBody) { 
				try {
					Contact[] con = [Select AccountId, Id From Contact Where Id =:Trigger.new[i].WhoId limit 1];
					Account[] acct = [Select Id, Account_Review__c From Account Where Id =:con.AccountId];
					
					if(acct.size()>0) {
						acct.Account_Review__c = acct.Account_Review__c + 'Test';
						update acct;
					}
				} catch (System.QueryException e){
	 				System.debug(e);
				}
			}
		}
	}
}

 

 

orikkerorikker

The error you get is because you declare an array but access it as object... from what I see the code will not work.

 here is what you should have in order for it to work.  Give it a shot. I am heading out right now, so I will take a look at this post once I am home.

 

trigger task_StoreMassEmailBody_upd on Task (before insert) {
	
	List<Account> accountsToUpdate = new List <Account> ();
	Set <id> taskContactIds = new Set <id> ();
	Set <id> contactAccountIds = new Set <Id> (); 

		for(Task t: Trigger.new) {
		    Boolean LogBody = t.Subject.contains('special subject');
			if(LogBody && t.WhoId.startsWith('003')) { //you need to make sure you 
								//query contacts with contact id's only and not nulls either otherwise you will get error 
				taskContactIds.add(t.WhoId);
				} //end if
		}//end for t
	
		if (!taskContactIds) { //make sure you had tasks that were assigned to contact
			for (Contact c: [SELECT Id, AccountId FROM Contact where id IN :taskContactIds]) {
				contactAccounts.add(c.AccountId); //this will create a set of account ids to be updated, you don;t need to update same account twice if more than one contact got a task.
			}//end for c
		
		
			for (Account a: [SELECT id,Account_Review__c FROM Account WHERE Id IN:contactAccounts ]) {
				a.Account_Review__c = 'TEST'; //assuming this is a text field.
				acccountsToUpdate.add(a);
			}//end for a
		

			try {
				update accountsToUpdate;
			}catch (System.DMLException e) {
				System.debug (e);
			}

		}//end if 

	
	}

 

 

 

 

 

JD2010JD2010

Aha. I get what you're doing.

 

Working with it now. Only thing I forsee right off is the startsWith will probably error since that deals with a string as opposed to an Id. Neat trick on checking if it's an ID though.

 

i'll give the rest a whirl. I'm hoping the bug is only that I cannot update the same task that's being triggered, so I can at least log the activity information elsewhere. I plan on creating it as a PDF and inserting it as an attachment (cleanest way, I think).

orikkerorikker

you should be able to update any values on the task that is created, that is why you trigger it on before insert. i'd be happy to take a look at your sandbox if you'd like or we can do a webex or something - it's bugging me too much :)

JD2010JD2010

I've got it running (though the unit test is worse for wear). What's weird though is that it still doesn't trigger, regardless of what the subject is, etc. Working on trying to figure that out now. I've also tried triggering it via mass email (how it will normally happen) and through just adding a new task with a contact.

orikkerorikker

Ok... I forgot this, but after you brought up mass email topic again... here it is:

 

Operations That Do Not Invoke Triggers

Triggers are only invoked for data manipulation language (DML) operations that are initiated or processed by the Java application server. Consequently, some system bulk operations do not currently invoke triggers. Some examples include:
  • Cascading delete operations. Records that did not initiate a delete do not cause trigger evaluation.
  • Cascading updates of child records that are reparented as a result of a merge operation
  • Mass campaign status changes
  • Mass division transfers
  • Mass address updates
  • Mass approval request transfers
  • Mass email actions
  • Modifying custom field data types
  • Renaming or replacing picklists
  • Managing price books
  • Changing a user's default division with the transfer division option checked
  • Changes to the following objects:
    • BrandTemplate
    • MassEmailTemplate
    • Folder

JD2010JD2010

That sucks on the mass email portion. Especially given they don't store the body of the e-mail. Blah.

 

That said, strange on the modifying custom fields, since I have certainly used Apex Loader to on custom fields for the purpose of executing a trigger en mass. The new question for me then is, what's an effect way to be able to cycle through and store the body of the email (which is already stored) on a specific date for all those emails that were sent out and logged.

orikkerorikker

I think this is an overkill with triggers to just save mass email content... When you create a template for mass email , there is a description field. put something like " --- MASS EMAIL TEMPLATE ID === and then template id or name  " . This is what's going to show up on the subject line in task that was created during mass email. users then can easyly access the template and see the content. Would that work?

JD2010JD2010

I'd say it would be overkill in most cases. The reason we can't just reference the template is for 2 reasons:

 

1) We're actually putting dynamically generated content into it (which we have)

2) We need to log (in an easy to find manner) what that content is on the date of sending for our records

 

That make sense?

orikkerorikker

Yeah, I think we are at dead end here... I don't see how you can do it, unless you want completly rewrite mass email functionallity... We had to do for lead conversion process in our org... There is a mass email class for apex... give it a shot.

 

I would start a new thread at this point. :)

This was selected as the best answer
JD2010JD2010

Fair, but unfortunate. I'd really rather not re-write their entire mass-email function. About how long did i it take for you all to do that at your org? I'm debating whether it would be better to just interface with an app exchange app like vertical response to accomplish what we're looking to do. Though we'd ideally like to not have to pay more to do mass emailing.

 

Only other thing I can think of to accomplish it is to run a mass trigger update (or batch job?) that accomplishes the same.

 

 

orikkerorikker

Not sure how would you do that (batch job to update the tasks)...

 

As far as rewrite, we changed lead conversion and it was only one page, mass email is a more complex UI.