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
Mike DeMilleMike DeMille 

trigger help!

I'm trying to write a trigger on task that when a new task is created, two fields on the opportunity are updated (opportunity 'Last Sales Activity' = task.createdDate, and opportunity 'Last Sales Activity Type = task.Type

How can I point it to the opportunity fields? Do I have to query for parent data first?  This is what I have:

trigger updateOpportunityActivityFieldsFromTask on Task (before insert) {
    
    for(task t:trigger.new) {
        if(t.whatid != null && t.whatid.getsobjecttype() == opportunity.sobjecttype) {
            t.WhatId.Last_Sales_Activity__c=t.CreatedDate;
            t.whatid.Last_Sales_Activity_Type__c=t.Type;
        }
    }
   
}
Best Answer chosen by Mike DeMille
James LoghryJames Loghry
Fields across relationships aren't available in a trigger. Typically, in this case, you would need to requery the records.   However, since you're just updating opportunity records, you can use some magic like below to update the parent opportunities:
 
trigger updateOpportunityActivityFieldsFromTask on Task (before insert) {
    
    Map<Id,Opportunity> opportunities = new Map<Id,Opportunity>();
    for(task t:trigger.new) {
        if(t.whatid != null && t.whatid.getsobjecttype() == opportunity.sobjecttype) {
            opportunities.add(
                new Opportunity(
                    Id=t.whatId
                    ,Last_Activity_Date__c = t.CreatedDate
                    ,Last_Sales_Activity_Type__c=t.Type
                )
            );
        }
    }

    update opportunities.values();
}

 

All Answers

James LoghryJames Loghry
Fields across relationships aren't available in a trigger. Typically, in this case, you would need to requery the records.   However, since you're just updating opportunity records, you can use some magic like below to update the parent opportunities:
 
trigger updateOpportunityActivityFieldsFromTask on Task (before insert) {
    
    Map<Id,Opportunity> opportunities = new Map<Id,Opportunity>();
    for(task t:trigger.new) {
        if(t.whatid != null && t.whatid.getsobjecttype() == opportunity.sobjecttype) {
            opportunities.add(
                new Opportunity(
                    Id=t.whatId
                    ,Last_Activity_Date__c = t.CreatedDate
                    ,Last_Sales_Activity_Type__c=t.Type
                )
            );
        }
    }

    update opportunities.values();
}

 
This was selected as the best answer
Mike DeMilleMike DeMille
James,

Thank you so much for the help!  I'm very grateful.  

I need to convert t.CreatedDate from datetime to date.  My 'Last_Activity_Date__c field is a date field.  Do you know the best way to do this? 
Mike DeMilleMike DeMille
I changed it to t.CreatedDate.date() and now I'm getting 'method does not exist or incorrect signature: void add(Opportunity) from the type Map<Id, Opportunity> at line 6 column 27

User-added image
Mike DeMilleMike DeMille
James, 

I made a couple of slight tweaks and it accepts it.  I will test and get back. 

trigger updateOpportunityActivityFieldsFromTask on Task (before insert) {
    
    Map<Id,Opportunity> opportunities = new Map<Id,Opportunity>();
    for(task t:trigger.new) {
        if(t.whatid != null && t.whatid.getsobjecttype() == opportunity.sobjecttype) {
            opportunities.put(t.WhatId,
                new Opportunity(
                    Id=t.whatId
                    ,Last_Sales_Activity__c = t.CreatedDate.date()
                    ,Last_Sales_Activity_Type__c=t.Type));
        }
    }

    update opportunities.values();
}
Mike DeMilleMike DeMille
I also changed it to after insert and that works.  THANKS James!
James LoghryJames Loghry
Yeah, I just noticed the syntax error.  My bad. Glad you figured it out!
Mike DeMilleMike DeMille
James, I've added something to it and can't get my test class coverage.  I've added the requirement that the task owner role be 'ADM'.  I use runAs in the test class and run as a user with role = ADM.  

Here is my trigger 

trigger updateOpportunityActivityFieldsFromTask on Task (after insert) {
    
    Map<Id,Opportunity> opportunities = new Map<Id,Opportunity>();
    for(task t:trigger.new) {
        if(t.Owner.UserRole.Name == 'ADM' && t.whatid != null && t.whatid.getsobjecttype() == opportunity.sobjecttype) {
            opportunities.put(t.WhatId,
                new Opportunity(
                    Id=t.whatId
                    ,Last_Sales_Activity__c = t.CreatedDate.date()
                    ,Last_Sales_Activity_Type__c=t.Type));
        }
    }

    update opportunities.values();
}


And here is my test class:

@isTest
private class updateOpportunityActivityTest {
    
    @isTest static void updateOpportunityActivityFieldsFromTask() {
    
    User Polson;
   
  
    
    for(User usr : [Select Id
                    From User                   
                    WHERE LastName = 'Polson'                   
                    limit 1]){
      Polson = usr;
    }
    System.runAs(Polson){
        Account acc = new Account();
        acc.Name = 'Tester 18';
        insert acc;
        
       
        Opportunity opp = new Opportunity();
        opp.Name = 'Test Oppty';
        opp.Amount = 5;
        opp.CloseDate = system.now().date();   
        opp.AccountId = acc.Id;
        opp.StageName = 'Stage 0: Scheduled';
        insert opp;
        
        Task tsk = new Task();
        tsk.WhatId = opp.Id;
        tsk.Subject = 'Test 18';
        tsk.Type = 'Call';
        insert tsk;
       
        

       }
    
}
}


I'm only getting 44% coverage, but if I take out the t.Owner.UserRole.Name == 'ADM' part then it gets 100%. 

Can you help me reword this to work? 
 
James LoghryJames Loghry
Hi Mike, 

I just saw this, apologize for the late-ish response.

In your unit test, you need to create a user with a UserRole set to "ADM", and use the System.runAs method to run your unit test as the user creating the task record.
 
@isTest
private class updateOpportunityActivityTest {
    
    static testmethod void updateOpportunityActivityFieldsFromTask() {
    
        User u = new User(
            Alias = 'batman',
            Email='bruce.wayne@mytestorg123.com',
            EmailEncodingKey='UTF-8',
            LastName='Wayne',
            LanguageLocaleKey='en_US',
            LocaleSidKey='en_US',
            ProfileId = [Select Id From Profile Where Name='System Administrator'],
            TimeZoneSidKey='America/Los_Angeles',
            UserName='bruce.wayne@mytestorg123.com',
            UserRoleId = [Select Id From UserRole Where Name='ADM']
        );
        insert u;

        //Declare the  task up  here, because we are going to use System.assert against it, outside of the System.runAs code block.
        System.runAs(u){
            Account acc = new Account(Name='Tester 18');
            insert acc;
        
            Opportunity opp = new Opportunity(
                Name = 'Test Oppty',
                Amount = 5,
                CloseDate = system.now().date(),  
                AccountId = acc.Id,
                StageName = 'Stage 0: Scheduled'
            );
            insert opp;
        
            //Since we are testing the task trigger, use Test.startTest here to reset all the DML limits, etc.
            Test.startTest();
            Task tsk = new Task(
                 WhatId = opp.Id,
                 Subject = 'Test 18',
                 Type = 'Call'
             );
             insert tsk;
             Test.stopTest();
        }

        //Begin assertion logic, to make sure our trigger performed as expected....
        Task t = [Select CreatedDate From Task];

        Opportunity o = [Select Last_Sales_Activity__c, Last_Sales_Activity_Type__c From Opportunity];

        System.assertEquals(t.CreatedDate,o.Last_Sales_Activity__c);
        System.assertEquals('Call',o.Last_Sales_Activity_Type__c);
    }
}


I also added in some "best practices" of unit testing in Apex, such as using Test.startTest / Test.stopTest and assertions for your unit test.  The code above is untested, so you might encounter compiler and other errors, but it should set you down the right path of getting your unit test working.

Cheers,
- James
Mike DeMilleMike DeMille
James, 

Thanks so much for the help.  I keep getting the following error:  
Error: Compile Error: Illegal assignment from List<UserRole> to Id at line 6 column 14

 
Mike DeMilleMike DeMille
James,

Nevermind.  I got it figured out.  I had to change the trigger to reference formula fields on TASK that referenced the t.owner.role.name

THANKS