You need to sign in to do that
Don't have an account?
ChickenOrBeef
After Insert trigger that uses IDs: "Record is read-only"
Hey everyone,
I've written an After Insert trigger that looks at the Created By ID and then transfers the record to a different owner. Here are the issues:
-You can't update the same record in an After trigger or else you'll get the "Record is read-only" error
-I can't use a Before trigger, since my trigger is looking at an ID, which doesn't exist yet in a Before trigger
So how would I go about modifying my code to do what I need? I've heard that I need to either "clone the record" or "query anew", but I'm not exactly sure how to use those approaches with my example.
Please take a look at my trigger and let me know what I should change. (By the way, this trigger also sends an email, as you can see) .
Here is the error when I test it out in the Sandbox:
Here is the trigger (I've bolded the line where the error occurs):
Thanks!
-Greg
I've written an After Insert trigger that looks at the Created By ID and then transfers the record to a different owner. Here are the issues:
-You can't update the same record in an After trigger or else you'll get the "Record is read-only" error
-I can't use a Before trigger, since my trigger is looking at an ID, which doesn't exist yet in a Before trigger
So how would I go about modifying my code to do what I need? I've heard that I need to either "clone the record" or "query anew", but I'm not exactly sure how to use those approaches with my example.
Please take a look at my trigger and let me know what I should change. (By the way, this trigger also sends an email, as you can see) .
Here is the error when I test it out in the Sandbox:
Here is the trigger (I've bolded the line where the error occurs):
public class ClassLibraryTaskEmail{ public void sendEmail(List<Task> tasks){ Set<String> contactsInTrigger = new Set<String>(); Map<String,String> contactMap = new Map<String,String>(); Map<String,String> IDmap = new Map<String,String>(); List<Task> tasksToTransfer = new List<Task>(); FOR(Task tk : tasks){ IF(tk.WhoId != NULL && string.valueOf(tk.WhoId).startsWith('003')){ contactsInTrigger.add(tk.WhoId); contactMap.put(tk.Id,tk.WhoId); } } List<Contact> validContacts = [SELECT Id,AccountId,Account.Assigned_ID__c FROM Contact WHERE Id In: contactsInTrigger]; FOR(Contact c : validContacts){ IDmap.put(c.Id,c.Account.Assigned_ID__c); } FOR(Task tsk : tasks){ IF(string.valueOf(tsk.CreatedById).contains('005A0000002rvG0')){ ID newOwner = IDmap.get(contactMap.get(tsk.Id)); tsk.OwnerId = newOwner; tasksToTransfer.add(tsk); } } List<Messaging.SingleEmailMessage> mails = New List<Messaging.SingleEmailMessage>(); List<String> emails = New List<String>(); List<User> recipients = [SELECT Id, Email FROM User WHERE Library_Task_Recipient__c = TRUE]; FOR(User u : recipients){ IF(u.Email != NULL){ emails.add(u.Email); } } FOR(Task t : tasks){ IF(emails.size() > 0 && string.valueOf(t.CreatedById).contains('005A0000002rvG0')){ Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); List<String> sendTo = New List<String>(); mail.setToAddresses(emails); mail.setReplyTo('greg@offerpop.com'); mail.setSenderDisplayName('Greg Annunziata'); mail.setSubject('Library Contact Has Filled Out Form'); String body = 'Greetings director, <br><br>'; body += 'A contact under a Library account has filled out a form. Please follow up.<br><br>'; body += 'A link to the task can be found here: https://na7.salesforce.com/'+ t.Id; mail.setHtmlBody(body); mails.add(mail); } } Messaging.sendEmail(mails); UPDATE tasksToTransfer; } }
Thanks!
-Greg
I ended up having the trigger transfer the associated Account instead of the Task itself. Transferring an Account also transfers the open tasks, so that worked for me.
Thanks!
-Greg
All Answers
or if you don't need to do it synchronously, you could push it a future method.
Though really, it looks like you could recreate this using workflows.
Thanks for the reponse! A few things...
-These tasks aren't created by a person in Salesforce. They're created by RingLead (a de-duping service) and the Created By is set as a certain user called "Offerpop Marketing". So would I still be able to use UserInfo.getUserId() to get the ID of Offerpop Marketing, even though it's not actually Offerpop Marketing creating the task in Salesforce?
-I'm not familiar with 'future methods'. Can you elaborate a bit on what that is?
-I don't think I can use workflows, since I need to look up a field on the account to know which user to transfer the task to.
Thanks!
-Greg
Future is an annotation you can use to have a certain bit of code execute in the asynchronously. Basically, it places in a queue and executes it in the near future. It's probably the most valuable resource you have, so you want to make sure you use it properly. You can learn a bit more about here but if you can't use UserInfo, this might get you out of this pickle.
https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_classes_annotation_future.htm
Is there a way to get that ID in a Before trigger?
Thanks!
-Greg
I ended up having the trigger transfer the associated Account instead of the Task itself. Transferring an Account also transfers the open tasks, so that worked for me.
Thanks!
-Greg