Timer commiting to logged hours on a Task via API

Comments

17 comments

  • Avatar
    Nadia Welter

    Hi Lee, 

    Are you using instructions for committing the timer here: https://developer.liquidplanner.com/docs/timers#section-tracking-time-via-a-timer-and-updating-estimates

    If you still can't get it to work, can you please post here the URL and the parameters you are passing, as well as the error message you are getting? Please remember to strip any sensitive information like workspace id if you are posting here. Alternatively, just email all the details to support@liquidplanner.com and we'll take a look. 

    0
    Comment actions Permalink
  • Avatar
    Lee Raybone

    URL is "https://app.liquidplanner.com/api/v1/workspaces/####/tasks/###/timer/commit"

    POSTing to the above with the JSON payload of "{"activity_id":####,"is_done":false,"id":0}"

    and I get the error "The remote server returned an error: (404) Not Found."

    I can send you the data via email if you need the #### values.

    Regards,

     

    Lee

    0
    Comment actions Permalink
  • Avatar
    Nadia Welter

     

    This is because of the "id":0 parameter; it is not one of the available parameters. Let me know if removing it didn't help. 

    0
    Comment actions Permalink
  • Avatar
    Lee Raybone

    Thank you Nadia, that worked.

    am I correct in thinking that to mark the activity as done this would be achieved in Update_assignment rather than in the timer/commit?

     

    0
    Comment actions Permalink
  • Avatar
    Nadia Welter

    Yes, if you want to mark just one assignment done on a multiple owner task, you'll want to use Update_assignment because if you set "is_done" to true on the timer/commit endpoint, you'll mark the whole task done and every assignment will be marked done as a result. 

    0
    Comment actions Permalink
  • Avatar
    Lee Raybone

    Thank you this worked really well

    0
    Comment actions Permalink
  • Avatar
    Ricardo Signes

    I just stumbled across this post, and I guess I have realized I'm in need of guidance.

    I think there are three ways to log time:

    1. start a timer on the task and commit it
    2. use track_time on the task
    3. update the assignment

    #1 is a problem because it doesn't update the estimate.

    #2 will update the estimate, but passing is_done will mark the entire task done, rather than just one assignment.  Also, (and I think this is a new bug report here) if you track_time with is_done:false but no assignment yet exists, the assignment will be created in a done state anyway.

    #3 requires that I know whether or not an assignment exists yet, so to commit the running timer, I need to fetch the task to find that out.  I already had to do that for #1 or #2, though, to get the activity id, so it sounds like to cover all bases, I should always use update_assignment.  This means I'll have to compute the new estimates in the client, but that's no big deal.

    Does this all sound right?

    0
    Comment actions Permalink
  • Avatar
    Ricardo Signes

    …as I went to implement this, I realize that #3 isn't sufficient, because #1 and #2 both accept a "comment" argument to add to the task while updating the time tracking.  So, I think the best universal course of action is:

    • get timer
    • get task for timer
    • create or update assignment for done-ness, hours logged, and estimate
    • add a comment if required

    I'll go implement that

    0
    Comment actions Permalink
  • Avatar
    Ricardo Signes

    …and after some Netflix and then some coding, I find that this doesn't work.  Here's what I get updating the assignment:

    {"type":"Error","error":"BadArgument","message":"Unknown key: :hours_logged. Valid keys are: :controller, :action, :id, :format, :workspace_id, :assignment_id, :_method, :view_id, :page_url, :activity_id, :low_effort, :low_effort_remaining, :high_effort, :high_effort_remaining, :person_id, :team_id, :person_ids, :team_ids, :is_done, :daily_limit"}

    Does this mean that you can't log time by updating the assignment?

    So, given the abstract instruction "commit my timer, with the comment «That was easy.», and mark only my assignment done", the API calls required seem to be:

    • get my timers
    • get the task for the active timer
    • track time against that task
    • update the assignments on that task
    • add a comment to that task

    I'll probably give that a try after Spain beats Russia (🤞🏽) but is this what I'm expected to do for this?

    0
    Comment actions Permalink
  • Avatar
    Lee Raybone

    Hi Ricardo

    I've managed to get a timer function working using the api to start, pause and commit the timer, for individual assignments on a task using the update_assignment

    basically workings is as follows:

    • find the task
    • iterate through assignments to see if users is assigned activity
    • if they are, get the activity id, and assignment id
    • then start, stop or commit the timer using the task id, assignment id, person id and activity id

    works a charm

    0
    Comment actions Permalink
  • Avatar
    Ricardo Signes

    Thanks, Lee.  I think you're suggesting that I can include an assignment_id when calling timer/commit to limit the commit to a single user.  Unfortunately, this only works when the assignment exists before the timer is committed.  A timer can be started for person P on task T before there is an assignment for that combination, so I can't rely on this.  (Also, it isn't documented.)  Because it's not documented or reliable for me, I didn't actually test to be sure I'd understood you and that it'd work.

    Instead, I've updated our code to:

    • (1) get the user's running timer
    • (2) get the task for it
    • (3) track-time on the task for the user, using the amount on the timer, with reduce_estimates, and a comment if provided
    • (never mark it done, which would mark the TASK done)
    • track-time returns the task, from which the assignment can now be pulled
    • (4) update the assignment's in_done
    • (5) restart the timer if needed

    track-time against a task with no preexisting assignment seems to always create the new assignment as done, even with is_done false, so API calls 4 and 5 can be skipped in some cases, but not all.  Maybe I'll draw a flow chart!

    Do you agree that this is the necessary set of steps?

    0
    Comment actions Permalink
  • Avatar
    Nadia Welter

    Thanks for jumping in, Lee! 

    Ricardo - sorry for the delay responding to you. I was out the whole last week celebrating Russia beating Spain ;) 

    When you track time on a task where you don't have an assignment, it is actually expected that the assignment gets created in a done state. It is documented in our Help Guide in the Multiple Owners article here. It does the same thing with the API. Perhaps we could document this behavior better - I see how it can be confusing. 

    As to your steps, I wanted to clarify though - are you using track_time method rather than commit the timer? It sounds like you are stopping the timer but you don't have the step written for it. If you stop the timer and use track_time to apply the accumulated time, you might want to clear the timer then.

    What I think is unnecessary is " track-time returns the task, from which the assignment can now be pulled". You are already getting the task in step (2). If there is an assignment already for your user, you'll see it. If not - you will not need it because you will be skipping your step (4). I think a flow chart would be helpful :) 

    0
    Comment actions Permalink
  • Avatar
    Ricardo Signes

    I actually made that flow chart!

    I'm just posting it now so I don't forget.  Tomorrow I will read your comments, think about it, and say whether I think a step or two can be reliably eliminated.  Thanks!

     

    0
    Comment actions Permalink
  • Avatar
    Ricardo Signes

    Okay!  So, yes, we're using track_time.  That's so we can use "reduce_estimate".  (I actually just found that in getting to the flow shown above, that option got lost!  I've re-added it.)  Committing timers doesn't allow for reduce_estimate. 

    It's true that we have the task, from step two, but it won't have the assignment if one wasn't yet created.  Since the updated task is the return value of track_time, there's no cost to getting the task there.  So, then I wondered:  can I, instead, skip the get_task?  If we have the task id, from the timer, we don't need anything else about the task until it's returned in track_time.

    Nope, can't skip it:  we need to know the activity id for the task to track time.  I think I'll hardcode our (single) activity id.

    0
    Comment actions Permalink
  • Avatar
    Nadia Welter

    Hi Ricardo, nice flow chart! So it sounds like since you only have one activity, you can hard code it and safely skip getting the task. If you do add more activities down the line, you will need to get the task for sure. Also, in that case, you'll want to have some default activity in case the task has none. 

    I still don't see the stopping or clearing timer action on your flow chart - you still do that, right? 

    0
    Comment actions Permalink
  • Avatar
    Ricardo Signes

    Thanks, Nadia. :)  I've re-added the timer-clearing, which had been lost in the shuffle, and updated my flow chart.

    I've abstracted out "get activity id", which does, indeed, get rid of that get-task.  It turns out, though, that I probably need to add one at the end, anyway.

    After logging time, we want to display the result, including a brief summary of the task, which always includes "done or not."  There's a routine that takes a task representation and returns a string suitable for SMS or Slack.  The task's overall is_done might change as a result of updating the assignment.  So, one option is to keep the result of track_time and, if we leave the timer user's assignment done, and if that was the only not-done assignment, before, we just update the structure that came back from track_time, replacing the single assignment and the is_done entry. 

    Probably, though, I'll just put in an unconditional fetch in the presentation layer, to keep life simple.  Our timer committing method can just say  "it worked" and we can decide to re-fetch the task.

    0
    Comment actions Permalink
  • Avatar
    Nadia Welter

    Sounds good! Although the result you get from update_assignment will return task-level information, as well as assignment-level, including the is_done status of the task overall as well as of each of its assignments. 

    0
    Comment actions Permalink

Please sign in to leave a comment.