In the Salesforce , Field Service Lightning application there is a Dispatcher console with multiple status fields in it. I created a custom field in it and called it 'Responded'. What do I wanna do with this? I want to create a trigger that as soon as I log in a call and set it to 'complete' that my status in the Console goes from 'schedule' to 'complete'. Here's an example of the code I've made so far.

trigger New_Task_Completed on Task (after Insert) {
    for ( Task T : System.Trigger.new) {
        if (T.Status == 'Completed'){
             ServiceAppointment SA = new ServiceAppointment(Id = T.Status,Status = 'Responded');
             Update SA;
  • 3
    What is the issue you are exactly facing? I can see that you have got few things wrong here as you are assigning a field's string value in Id field, which won't work at all. Take a moment to Hot to Ask and edit your question to provide more details around your issue for anyone to be able to help you. – Jayant Das Oct 26 '18 at 15:36
  • I want to change the Service Appointment Status to 'Responded' as soon as I Log a Call as 'Completed'. Much more like a chain effect. What I'm not sure about is the Trigger I made and It's become difficult to test. Any suggestions? Thank You ! – Reinaldo G Rodriguez Malave Oct 26 '18 at 15:39
  • You will need to fetch the related service appointment for the task and then accordingly update the status. As of now you are not doing that. – Jayant Das Oct 26 '18 at 15:44
  • Also collect the objects to be updated in a list and update them outside the loop. – Keith C Oct 26 '18 at 15:47

Below is some sample code that is aiming to achieve what I believe you want. I have not tested it but it is fundamentally correct.

The biggest mistake that you're making in your original code is that you have a trigger that is reviewing inserted (i.e. new) tasks. It isn't reviewing tasks that have been updated and it isn't then subsequently going to find the related ServiceAppointment records to update those. The code below is broken down in to three parts:

  1. Loop through each of the task records in the trigger and determine a few things: there is a related service appointment record on the task (service_appointment__c != null), the task status is completed (t.status == completed) and it is either: a newly inserted record; or it is an update and the status wasn't previously completed.
  2. Retrieve service appointments related to the tasks. This assumes you have a lookup relationship from the task to the ServiceAppointment with a field called service_appointment__c. Loop through those retrieved records and set a checkbox with an API name of responded__c to true.
  3. Update the records in the database.

It is very likely that your record names and field names do not exactly match those I've used in the code. You will need to correct this.

trigger New_Task_Completed on Task (after Insert, after update) {
    List<Id> serviceApptId = new List<Id>();
    List<ServiceAppointment> updatedSas = new List<ServiceAppointment>();
    // Loop through tasks and retrieve any that are either new and set as completed or updated and changed to completed
    for (Task t : Trigger.new) {
        if ((t.service_appointment__c != null && t.status == 'Completed') && (trigger.isInsert || (trigger.isUpdate && trigger.oldMap.get(t.Id).status != 'Completed'))) { 

    // Retrieve list of service appointments and mark them as responded = true.
    if (serviceApptId.size() > 0) {
        List<ServiceAppointment> serviceAppointments = [Select Id From ServiceAppointment where Id in :serviceApptId];
        for (ServiceAppointment sa : serviceAppointments) {
            sa.Responded__c = true;

    if (updatedSas.size() > 0) {
        update updatedSas;

Lastly, is there a reason you're not doing this in the process builder? This would negate the use of code entirely. There are reasons not to - notably, the process builder isn't terribly efficient. However, this also applies to Apex. Task records tend to be the most often used records (an account may have dozens) so attaching workflows, process, and code to tasks should be given careful thought (this applies to any record but particularly those with high transaction volumes).


While I am not sure how is your ServiceAppointment related to Task, I assume its using ParentId.

Conidering that to be the case, this is how you will need to make the update on the status of all service appointments related to your completed tasks.

List<Id> allCompleteTaskIds = new List<Id>(); // create a list of completed tasks
for (Task T : Trigger.new) {
    if (T.Status == 'Completed') {

// now fetch all related service appointments
List<ServiceAppointment> svcAppts = [select Id, Status from ServiceAppointment where ParentId IN :allCompleteTaskIds];
for(ServiceAppointment svcA : svcAppts) {
    svcA.Status = 'Responded'; // set related appointments to updated

update svcAppts;
  • 1
    if(svcAppts.size() > 0) is no longer required nor optimal. An empty list does not use any DML governor limits. – sfdcfox Oct 26 '18 at 17:03
  • Some habit just takes time to go :) Modified though, so that this can be shared further. Thanks for your review comments. – Jayant Das Oct 26 '18 at 17:06
  • 1
    Just to save some processing time, you could add "and Status <> 'Responded' the query to avoid updating ones that are already in that status. – Jochen Oct 26 '18 at 20:02

Not the answer you're looking for? Browse other questions tagged or ask your own question.