I'm not sure this issue can be completely addressed in the scope of an answer, but I see some misconceptions in the question that I'd like to try to address to make it possible for you to move forward.
Incidentally, you can't do the things you want to do in Process Builder alone. You can use Process Builder to launch a Flow, or you can work in Apex.
Tasks, Quick Actions, and Relationships
When a Task is created through an object-specific Quick Action or through a button on a record page, it's already related to that object through its WhoId
(Lead and Contact only) or WhatId
(everything else) relationship field. Generally, you don't need to do any work to associate Tasks with the objects from whose pages they're created. You'd only need to do this work if for some reason the Task is created through a whole different work-stream, or through non-user-initiated automation.
So you don't need to do this:
callplantask.WhatId = opp.Id;
and in fact you can't, because you don't have an opp
in this Task trigger. Luckily, you don't need to; WhatId
should already be populated if this Task came from an Opportunity page.
Populating Fields on a Child Object From a Parent Object
This is a more general way, I think, to describe your objective when you say you want to
map fields from an opportunity to the task that was created from it
This is a common pattern and you'll find plenty of examples if you search SFSE. It's very important as you start implementing to understand Apex bulkification. Your pattern will look something like this:
- Iterate over Tasks and collect Opportunity ids.
- Query Opportunities (one query, outside loop).
- Iterate over Tasks again and populate data from parent Opportunity, usually accessed via a
Map<Id, Opportunity>
.
- If not in
before
context, perform a single update
DML against a List<Task>
to persist the changes.
Right now, you have a DML operation inside a loop. You don't need it there (you're in before insert
context, where no DML is required), but if it were required this would be a bad practice.
Filtering Records to Affect
It's fine to use the Record Type to filter which records you want to modify. This won't work, though:
IF(Task.RecordTypeId = '0121b0000008kSW'){
First of all, you wanted callplantask.RecordTypeId
. Task.RecordTypeId
is a reference to the field definition, and you can't compare that to an Id, nor assign to it. I say that because you've also written an assignment statement here, with one =
sign; should you correct your statement to read callplantask.RecordTypeId
, you'll actually be assigning the RecordTypeId
, not checking it. You need two =
signs:
if (callplantask.RecordTypeId == '0121b0000008kSW') {
It would also be better to use the Describe API to obtain the relevant Record Type Id at runtime rather than hard-coding it.
Specific Data Points
On the task, we would like to populate the account name from the opporunity
You don't need to do that. Tasks have another relationship called AccountId
, which is calculated by the system based on the other relationships. If WhatId
is an Opportunity, AccountId
is that Opportunity's Account. You can just add a formula field to get the Account's name as a text field if you need to.
as well as pull the products from the opp into a custom field called current products.
That adds a fair amount of complexity because, of course, Products (in the form of Opportunity Line Items) are a different child of Opportunity. You'll have to be careful with bulkification of your queries, as above, and remember of course that your field won't update when you add or remove Products from the Opportunity.
Another option would be to roll up the Product names to a field on the Opportunity with DLRS and then just copy that field down to the Task.