You need to sign in to do that
Don't have an account?
Trigger: Update Custom Field on Task Based on Related WhatID Record
Goal: use a trigger to update a custom field on the Task (OppNumber) with a field on the Opportunity that is selected in the WhatID field (if an Opp is selected)
I thought this would be easy to do using a lookup and just passing the value, but you apparently cannot create a lookup on the Activity/Task object.
I know I can pull in the record ID for the opp related via the WhatID field, but how can I refer to a specific field on that record? (Such as the Opportunity Number).
Open to suggestions.
Resolved this with a trigger, created step by step with a referral from my customer success rep (amazing support! I am very pleased).
Here's the code:
trigger TaskRelatedToOpp on Task (before insert, before update) { // Goal: Find the opp ID of the opportunity that a task is related to // and update the Opportunity_Number field on the task object with the value // If related to an Opportunity, query to find out the Opportunity number // Create collection of tasks that are related to an opp (where the opp is listed only once) Set<Id> opIds = new Set<Id>(); for(Task t : trigger.new){ String wId = t.WhatId; if(wId!=null && wId.startsWith('006') && !opIds.contains(t.WhatId)){ opIds.add(t.WhatId); } } // Pull in opp ids and related field to populate task record List<Opportunity> taskOps = [Select Id, Opportunity_Number__c from Opportunity where Id in :opIds]; Map<Id, Opportunity> opMap = new Map<Id, Opportunity>(); for(Opportunity o : taskOps){ opMap.put(o.Id,o); } // Update custom task field with custom opp field for(Task t : trigger.new){ String wId = t.WhatId; if(wId!=null && wId.startswith('006')){ Opportunity thisOp = opMap.get(t.WhatId); if(thisOp!=null){t.Opportunity_Number__c = thisOp.Opportunity_Number__c;} } } }
All Answers
Well, I at least determined that I can figure out based on the id if a related record is an opp or not. (I just discovered that there is a standard opp id prefix of "006". Duh)
I added a field ("myWhatId)to my activity object that shows the id of the WhatID record selected in the lookup. I also a field to my activty object for "IsOpp", which looks at the first three characters of the id and returns "True" if it starts with "006."
So, now I just need help with some sort of a trigger that does something like "If IsOpp = true, Task.OppNumber = Opp.OppNumber where Opp.Id = task.myWhatId"
Going to test out on my own. I'm not very familiar with syntax, so if anyone has a tip that would be great.
trigger TaskRelatedToOpp on Task (after insert, after update) {
// Goal: Find the opp ID of the opportunity that a task is related to
// and update the Opportunity_Number field on the task object with the value
// If related to an Opportunity, query to find out the Opportunity number
If(IsOpp__c=='True') {
Opportunity Opp = [SELECT Id, Opportunity_Number__c FROM Opportunity WHERE Id = myWhatID__c]
Opp_Number__c = Opp.Opportunity_Number__c
}
}
(Obviously, this doesn't work.)
Resolved this with a trigger, created step by step with a referral from my customer success rep (amazing support! I am very pleased).
Here's the code:
trigger TaskRelatedToOpp on Task (before insert, before update) { // Goal: Find the opp ID of the opportunity that a task is related to // and update the Opportunity_Number field on the task object with the value // If related to an Opportunity, query to find out the Opportunity number // Create collection of tasks that are related to an opp (where the opp is listed only once) Set<Id> opIds = new Set<Id>(); for(Task t : trigger.new){ String wId = t.WhatId; if(wId!=null && wId.startsWith('006') && !opIds.contains(t.WhatId)){ opIds.add(t.WhatId); } } // Pull in opp ids and related field to populate task record List<Opportunity> taskOps = [Select Id, Opportunity_Number__c from Opportunity where Id in :opIds]; Map<Id, Opportunity> opMap = new Map<Id, Opportunity>(); for(Opportunity o : taskOps){ opMap.put(o.Id,o); } // Update custom task field with custom opp field for(Task t : trigger.new){ String wId = t.WhatId; if(wId!=null && wId.startswith('006')){ Opportunity thisOp = opMap.get(t.WhatId); if(thisOp!=null){t.Opportunity_Number__c = thisOp.Opportunity_Number__c;} } } }
Thanks for posting this J Blaze, switching out opportunity with account works perfectly to update the task object with account custom fields as well.
What does your test class look like?
Here's my test class:
@isTest private class TaskRelatedToOppTriggerTestClass { static testMethod void myUnitTest() { // Run test of code Opportunity o = [select Id from opportunity limit 1]; Task t1 = new Task(subject='test', WhatId = o.id, description = 'test description'); insert t1; } }
Hi I have a same kind of issue . I am sure you may find a easy solution for this ..
"If an activity/task is associated with an opportunity, a territory field on the task should reflect that opportunity."
Write a trigger on Tasks/Event to populate a custom field "Opportuity Territory" on Activities object.
If i can get a bit help on this..
Thanks
You can use the code above making a few minor changes (to get your fields covered)
trigger TaskRelatedToOpp on Task (before insert, before update) { // Goal: Find the opp ID of the opportunity that a task is related to // and update the Opportunity_Number field on the task object with the value // If related to an Opportunity, query to find out the Opportunity number // Create collection of tasks that are related to an opp (where the opp is listed only once) Set<Id> opIds = new Set<Id>(); for(Task t : trigger.new){ String wId = t.WhatId; if(wId!=null && wId.startsWith('006') && !opIds.contains(t.WhatId)){ opIds.add(t.WhatId); } } // Pull in opp ids and related field to populate task record List<Opportunity> taskOps = [Select Id, Opportunity_Number__c from Opportunity where Id in :opIds]; Map<Id, Opportunity> opMap = new Map<Id, Opportunity>(); for(Opportunity o : taskOps){ opMap.put(o.Id,o); } // Update custom task field with custom opp field for(Task t : trigger.new){ String wId = t.WhatId; if(wId!=null && wId.startswith('006')){ Opportunity thisOp = opMap.get(t.WhatId); if(thisOp!=null){t.PUT YOUR TASK FIELD NAME HERE__c = thisOp.PUT YOUR OPPORTUNITY FIELD NAME HERE;} } } }
thecrmninja:
I'm sure it could be optimized. My knowledge about code and test classes is pretty minimal. So, feel free to have at it!
thecrmninja: By the way, thanks for responding to symantecAP with the suggestion to modify my code. It's been awhile since I revisited this, so your response was appreciated.
Ok, i've thrown together something quickly that you could try. I'd love to hear if this improves your results.
Because your trigger was very straightforward (and has only a few lines) it's not going to make a signficant difference. However, this is a great way for you to learn a bit more about test classes so that you can advance your ambitions and create more throroughly vetted code in the future
!!!EDITOR'S NOTE!!! I have made the assumption that your custom field is a Text Field. If it is a number field, this test class will fail. Please let me know if it is and I can adapt the Test Class easily. All that would need to change is removal of quotes from around 123 (in two parts of the code) and to have "STRING t" changed to "INTEGER T"
I've laced this class with comments to try to explain why I made the changes that I did. I just want to make sure that anybody that comes across your great trigger example learns a little about Testing via classes.
Let me know if this works. (I did it quickly, so I might have overlooked something)
@isTest
private class TaskRelatedToOppTriggerTestClass {
static testMethod void myUnitTest() {
// Run test of code
//I'VE REMOVED THIS LINE IN FAVOR OF CREATING AN OPP RECORD IN THIS TEST CLASS THAT IS CATERED TOWARDS THIS TEST CLASS
//Opportunity o = [select Id from opportunity limit 1];
//HERE, WE CREATE AN OPP RECORD PUTTING A VALUE IN THE FIELD THAT YOU CALL IN YOUR TRIGGER
//WE WANT TO TEST THE COMPLETE FUNCTIONALITY OF YOUR TRIGGER SO IT IS IMPORTANT TO VALIDATE, VIA THE TEST CLASS
//THAT YOUR TRIGGER ACHIEVES THE DESIRED RESULTS.. ...UPDATING A FIELD ON A TASK WITH A VALUE FROM AN OPP
//SOME SFDC ORGS HAVE ACCOUNTS AS REQUIRED FIELDS ON OPPS, SO I'M CREATING ONE JUST TO BE SAFE
Account aDS = new Account(name='jbaze');
insert aDS;
//NOW I'M CREATING AN OPP AND PUTTING A VALUE IN THE FIELD THAT YOUR TRIGGER CALLS
Opportunity opTASK = new Opportunity(name='test value to task', Account=aDS, closedate=system.today(), stagename='Prospect',Opportunity_Number__c = '123');
insert opTASK;
//IMPORTANT NOTE!!!!!!!! I'VE MADE AN ASSUMPTION THAT YOUR CUSTOM FIELD IS A TEXT FIELD,
//IF IT IS NOT, REMOVE THE QUOTES AROUND '123'
//NOW, AS IN YOUR ORIGINAL, WE ARE CREATING A TASK ASSIGNED TO THE OPP
Task t1 = new Task(subject='test', WhatId = opTASK.id, description = 'test description');
insert t1;
//NOW, THE CRITICAL PART, WE WILL RUN AN ASSERT CALL TO MAKE SURE THAT THE CUSTOM FIELD ON THE TASK HAS THE VALUE FROM THE OPP
//THIS IS WHAT TESTS THE FUNCTIONALITY OF YOUR TRIGGER
STRING t = [Select Opportunity_Number__c from Task where id = :t1.id];
system.AssertEquals('123', t);
//BEFORE, THE TEST CLASS WAS MERELY CAUSING YOUR TRIGGER TO FIRE, NOT CONFIRMING THAT IT WORKS AS EXPECTED
//NOW, YOU SHOULD SEE AN INCREASE IN YOUR CODE COVERAGE
}
}
I tried using this code to update the field on the related object but it doesnt seem to work. Instead of updating the field on the Task, I want to update the field on my related custom object "Store__c"
Basically, I have a task with several Date fields, and each time I update a date on the task, it should update the date on the Store page as well.
I thought that just reversing that last statement would do the trick...but nothing seems to happen on the Store record:
Let me know if I'm not making sense.
Can you provide the code that will take a custom field from opportunities and update the standard task field called comment?
Bringing it back from the dead but...
One thing to add to this reply on customizing the code though...
You need to change Opportunity_Number__c in line 17 as well.