Two way to communicate with the Tempo Timesheets plugin

Jira Server / Data Center

The Tempo plugin is probably the most popular Jira add-on for work time managing. Except worklogs, it offers a various number of functions to support users and managers: workload schemes, holidays and other time-off days, period management, calculating costs, access to individual functionalities based on user roles, and many, many more.

However, the plugin as a functional tool nowadays is on the top, the way it integrates with Jira implies some potential problems, which appear while coding. In short, Tempo doesn’t pay more attention to be polite, but brutally rapes the Jira ecosystem with its own worklogs, user base, roles, etc. As a result, the system has worklogs, users and permissions individually controlled by the Tempo and Jira.

The plugin offers two methods for retrieving and modifying data outside the GUI. It could be used for automatic script operations.

Tempo REST API

The Jira Server / Data Center users can use a quite extensive REST API. Nowadays, it contains seven interfaces to send requests from Groovy scripts (ScriptRunner, JMWE) and from external applications after appropriate authorization.

Tempo REST API, https://www.tempo.io/server-api-documentation

The request execution contains JSON body preparation (as it was described in the REST API documentation) and sending it using the GET, POST, PUT, or DEL method. Depending on an operation type, you can process the retrieved data or get information about the execution status.

The following example performs an insert worklog into the Tempo Timesheet for any user. To accomplish this, you should look for the Creates worklog endpoint documentation and implement it using a Groovy script or a standalone application.

Groovy
import java.text.SimpleDateFormat;  
import com.atlassian.jira.component.ComponentAccessor;

// 1. Initialize a start and the end date for a worklog.
def worklogStartDate = new SimpleDateFormat("yyyy-MM-dd").parse("2023-01-04");  
def worklogEndDate = new SimpleDateFormat("yyyy-MM-dd").parse("2023-01-04");  

// 2. Get a user object for a worklog.
def worker = ComponentAccessor.getUserManager().getUserByName("jkalinowski");

// 3. Prepare a JSON body of the request.
// originTaskId - the Jira issue key where you insert worklog data.
// timeSpentSeconds, billableSeconds - one day equals 28800 seconds.
def body = """
  {           
    "attributes": { },
    "billableSeconds": 28800,
    "comment": "Praca w ${worklogStartDate.format("yyyy-MM-dd")}",
    "endDate": "${worklogEndDate.format("yyyy-MM-dd")}",
    "originTaskId": "TASK-123",
    "remainingEstimate": 0,
    "started": "${worklogStartDate.format("yyyy-MM-dd")}",
    "timeSpentSeconds": 28800,
    "worker": "${worker.getKey()}"
  }          
""";      


// 4. Send a request.
def urlHttp = new URL('https://jira/rest/tempo-timesheets/4/worklogs').openConnection() as HttpURLConnection;
urlHttp.setRequestMethod("POST");
urlHttp.doOutput = true;
urlHttp.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
// Way to generate a hashcode: ("<username>:<password>").getBytes().encodeBase64().toString();
urlHttp.addRequestProperty("Authorization", "Basic <hashcode>");
urlHttp.getOutputStream().write(body.getBytes("UTF-8"));
urlHttp.connect();
// Return a response code.
return urlHttp.getResponseCode();

Tempo Java API

The second way to communicate with the Tempo is Tempo’s Java API. Unfortunately, there is no documentation except some guidance in the Atlassian Community or in old ScriptRunner websites. The following example shows a similar insert operation using the Java API and ScriptRunner.

Groovy
import java.text.SimpleDateFormat;  
import com.atlassian.jira.component.ComponentAccessor;
import com.onresolve.scriptrunner.runner.customisers.WithPlugin;
import com.tempoplugin.worklog.v4.rest.TimesheetWorklogBean;
import com.onresolve.scriptrunner.runner.customisers.PluginModule;
import com.tempoplugin.worklog.v4.rest.InputWorklogsFactory;
import com.tempoplugin.worklog.v4.services.WorklogService;

// 1. Map Java libraries from the Tempo plugin.
@WithPlugin("is.origo.jira.tempo-plugin") 

// 2. Inject the InputWorklogsFactory component from the Tempo plugin.
@PluginModule
InputWorklogsFactory inputWorklogsFactory;

// 3. Inject the WorklogService component from the Tempo plugin.
@PluginModule
WorklogService worklogService;

// 4. Set a start and end date of the worklog.
def worklogStartDate = new SimpleDateFormat("yyyy-MM-dd").parse("2023-01-04");  
def worklogEndDate = new SimpleDateFormat("yyyy-MM-dd").parse("2023-01-04");  

// 5. Get a user object for a worklog.
def worker = ComponentAccessor.getUserManager().getUserByName("jkalinowski");

// 6. Insert a worklog.

// Initialize a worklog object.
def timesheetWorklogBean = new TimesheetWorklogBean.Builder()
  .issueIdOrKey("TASK-123")
  .comment("Praca w ${worklogStartDate.format("yyyy-MM-dd")}")
  .startDate(worklogStartDate.format("yyyy-MM-dd"))
  .workerKey(worker.getKey())
  .timeSpentSeconds(28800)
  .remainingEstimate(0)
  .build();			
def inputWorklogs = inputWorklogsFactory.buildForCreate(timesheetWorklogBean);

// Insert the worklog to an issue.
worklogService.createTempoWorklogs(inputWorklogs);

Summary

If you test both modification methods on large datasets, you will see that operation using the Java API execute significantly faster. It could be make a difference for some solutions. It is also important how possible errors look like in both methods. It is quite possible that we will try to set up a worklog for a person without proper permissions to add it one, or something like that. Both solutions return an error message, but in different way.

REST API – return a response code and body. In this case (the first example script), the application will not stop. It just does not insert a worklog.

Java API – the createTempoWorklogs() throws an exception and stops application, so you should handle this exception e.g. using a try… catch… block.

Go to top