1

My requirement is to find out how much time is being spent by sales rep while working on cases . So I need to track how much time is being spent by sales rep in creating a task record against the case.

Could anyone tell me how to find how much time spent in creating a task record against the a particular case.

Thanks

5
  • In order to get a good answer, pls elaborate on your requirement. What do you mean by "how much time spent in creating a task record against the a particular case."? The time between Case creation and the creation of the first taks? Or the time between creation of a task and closing of the task? Oct 15, 2014 at 12:59
  • @guy, I am sorry if I was not clear. I need to have a timer functionality on the Task Create/Edit page . On the standard Task Create/Edit page, user should be able to start/stop the timer and the time difference should be saved on some custom field. So that in future , user can track how much hours he spent in working on that task. Oct 18, 2014 at 8:51
  • Did you manage to find a solution to your question? If you did, please make sure to post your solution as the answer. Nov 22, 2014 at 4:15
  • Was this ever resolved? None of the answers are accepted. I'm curious because I may need to achieve a similar goal in the future. Mar 5, 2015 at 23:11
  • @ProgrammableMedley I really dont think there is any good solution to achieve this unless its a custom UI. Let me know if you found anything as I am looking to achieve a similar functionality. Oct 1, 2015 at 8:13

2 Answers 2

2

After going over the issue rather thoroughly I believe I came up with a simple (untested) solution.

First thing, I needed was to create three custom DateTime fields on the Task object.

These fields were:

  • StartTime__c
  • EndTime__c
  • TimeElapsed__c

Now that I have the custom fields to store the time differences properly.

The next step was to create a trigger and utility to implement the time tracking functionality.

First, the trigger code:

trigger TaskTrigger on Task(before insert, before update)
{
    if(Trigger.isInsert)
    {
        DateTime startingTimeForTimer = System.Now();

        for(Task singleTask : Trigger.new)
        {
            if(TaskTimeTrackingHandler.NeedsToTrackTime(singleTask))
                singleTask.StartTime__c = startingTimeForTimer;
        }
    }

    if(Trigger.isUpdate)
    {
        List<Task> tasksThatNeedTimeRecorded = new List<Task>();

        for(Task singleTask : Trigger.new)
        {
            if(TaskTimeTrackingHandler.NeedsToStoreTimeDifference(singleTask, Trigger.OldMap.get(singleTask.Id))
                tasksThatNeedTimeRecorded.add(singleTask);
            if(TaskTimeTrackingHandler.NeedsToRestartTimer(singleTask, Trigger.OldMap.get(singleTask.Id))
                singleTask.EndTime__c = null;
        }

        if(tasksThatNeedTimeRecorded.size() > 0)
            TaskTimeTrackingHandler.StoreTimeDifferences(tasksThatNeedTimeRecorded);
    }
}

The trigger code is straight-forward. I used some utility methods in my handler class (TaskTimeTrackingHandler) to handle logic in methods to not clutter up the trigger.

For an insert (a before insert), I will simply check to see if a Task has a Case against it. If it does have a Case against it, I start the timer by placing the System time in the StartTime__c custom field.

For updates, it is a bit trickier, although not too complex.

If the EndTime__c custom field is assigned a value, we will store it in a list to store the time differences in the TimeElapsed__c field. If the StartTime__c has changed, we will reset the timer by setting the EndTime__c to null.

Now let's look at the handler class to see the implementation of the handler methods a bit further:

public with sharing class TaskTimeTrackingHandler
{
    public static String CasePrefix = Case.sObjectType.getDescribe().getKeyPrefix();

    public static Boolean NeedsToTrackTime(Task newTask)
    {
        return newTask.WhatId != null && newTask.WhatId.startsWith(CasePrefix);
    }

    public static Boolean NeedsToStoreTimeDifference(Task newTask, Task oldTask)
    {
        return NeedsToTrackTime(newTask) &&
            newTask.EndTime__c != null &&
            oldTask.EndTime__c == null &&
            newTask.StartTime__c != null;
    }

    public static Boolean NeedsToRestartTimer(Task newTask, Task oldTask)
    {
        return newTask.StartTime__c != oldTask.StartTime__c && NeedsToTrackTime(newTask);
    }

    public static void StoreTimeDifferences(List<Task> tasksThatNeedToStoreTimeDifferences)
    {
        for(Task singleTask : tasksThatNeedToStoreTimeDifferences)
        {
            singleTask.TimeElapsed__c = 
                ((singleTask.TimeElapsed__c == null 
                 ? 0 : singleTask.TimeElapsed__c.getTime()) +
                (singleTask.EndTime__c.getTime() - singleTask.StartTime__c.getTime()));
        }
    }

    private static Boolean TaskHasCaseHours(Task singleTask)
    {
        return NeedsToTrackTime(singleTask) && singleTask.TimeElapsed__c != null;
    }

    public static Long GetHoursSpentOnCase(Task taskToFindHoursOnCase)
    {
        if(TaskHasCaseHours(taskToFindHoursOnCase))
            return taskToFindHoursOnCase.TimeElapsed__c.getTime() / 1000 / 60 / 60 / 24;
        return 0;
    }
}

I placed all the logic to check the Task fields in my handler for a cleaner trigger like I said before. Plus, I was able to reuse some methods, like NeedsToTrackTime.

Everything else is pretty simple now that it is broken down.

I specifically made sure that if the TimeElapsed__ field had a value, any time differences will be accumulated. This was if you consistently start and stop your timer, you will get an accumulative difference in a DateTime value.

Lastly, here is an example below on how to use the trigger to track time, with comments above each one to show what it's doing.

//To start the timer on a particular Task, simply create a Task against a Case object
INSERT taskWithCaseAgainstIt;

//To stop the timer and have the trigger record the time spent on it, simply assign a
//DateTime to the EndTime__c custom field
taskWithCaseAgainstIt.EndTime__c = System.Now();
UPDATE taskWithCaseAgainstIt;

//To restart the timer, assign a new start time (StartTime__c) to your Task with the 
//case against it and it will return the EndTime__c custom field to null.
taskWithCaseAgainstIt.StartTime__c = System.Now();
UPDATE taskWithCaseAgainstIt;

//Now if you set an end time again, the time difference will be accumulated
taskWithCaseAgainstIt.EndTime__c = System.Now();
UPDATE taskWithCaseAgainstIt;

//Now to get the hours spent on a given case, you can use the static method GetHoursSpentOnCase
Long hoursSpentOnCase = TaskTimeTrackingHandler.GetHoursSpentOnCase(taskWithCaseAgainstIt);

There is some room for improvement, such as clearing the TimeElapsed__c field should clear the StartTime__c and EndTime__c fields. Other than that, I believe this will give you the functionality you're looking for.

0

You can achieve this by writing a simple trigger on task:

Trigger TaskAfter on Task(After insert){
    Set<Ids> caseIds = new Set<Ids>();

    for(Task t: tigger.new) {
        if(t.whatID !=null && String.valueOf(t.whatID).substring(0,3) =='500')
            caseIds.add(t.whatID);
    }

    List<case> csLst = [select id,First_Task_created_date__c from Case 
        where First_Task_created_date__c=null && ID IN :caseIds];

    for (Case c : csLst ){
        c.First_Task_created_date__c=System.NOW();
    }

    update csLst;
}

Note: First_Task_created_date__c is a custom field to capture first task created date.

Then you can create a new formula field to calculate the number of days between Case created date and First task created date.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .