Displaying Sum of Worklogs by Work Type

We had https://denizoguz.atlassian.net/wiki/spaces/WLP/pages/1140293633 showed you how to create a checkbox “Overtime” worklog attribute using WorklogPRO and show sum-up of overtimes inside issue view using ScriptRunner. We will create a similar “Scripted Field” but this time we will create a “Single Select” worklog attribute to specify type of work (such as “Coding”, “Testing” etc.) and show sum-up of each work type on issue view.

Using WorklogPRO create a single select worklog attribute as explained here. After that users will able to select type of their work using combobox on “Log Work” dialog. Let's assume that we have configured a “Type of Work” worklog attribute with following values.

 

Next we will create “Scripted Field” using ScriptRunner. To create the field, navigate to “Manage apps/add-ons → ScriptRunner → Fields” setting and press the “Create Script Field” button and than select “Custom Script Field”.

Use following script and Template for “Scripted Field” configuration. This time we also need to write our own template because non of he build-in templates does what we want. Because we want to display an HTML table. Our script is returning Map<String, Long> (A map of “work type” to SUM in seconds) for each “work type” alternative and our template is converting this to HTML. If you now a little bit of Velocity Template Engine it is easy to understand.

Use following Groovy Script. We retrieve worklogs of the current issue using WorklogManager and build-in “issue” variable. We also create our result object (resultTable variable) which is a mapping from work type to sum of effort for that work type. After that we iterate every worklog and check whether that worklog has “Type of Work” attribute specified. If it is we check which value is selected and update corresponding total in our result map.

import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.issue.worklog.Worklog import com.onresolve.scriptrunner.runner.customisers.PluginModule import com.onresolve.scriptrunner.runner.customisers.WithPlugin import com.deniz.jira.worklog.services.attr.*; import com.deniz.jira.worklog.data.attr.*; import java.util.*; @WithPlugin("com.deniz.jira.worklog") @PluginModule AttrTypeService attrTypeService; def worklogManager = ComponentAccessor.getWorklogManager() def worklogs = worklogManager.getByIssue(issue) AttrTypeImp attrTypeImp = getTypeOfWorkAttributeDefinition(attrTypeService); //get "Type of Work" attribute definition Map<String, Long> resultTable = new HashMap<>(); if (attrTypeImp != null) { //run only if we have attribute type defined //process each worklog and categorise "Time Spent" by work type. worklogs.each { worklog -> Optional<AttrWorkLog> attrValueInWorklog = attrTypeService.getWorklogAttribute(attrTypeImp.getId(), worklog.id); if (attrValueInWorklog.isPresent()) { //skip worklog if it does not have a "type of work" specified int valueId = Integer.parseInt(attrValueInWorklog.get().getAttrValue(), 10); //convert string values stored in DB to Integers, like "10" to 10. def text = getTextOfAttributeValue(valueId, attrTypeImp); //this converts from DB id to human format, like 10 to "Coding". //get previous total for work type and put new value into result def totalForValue = resultTable.get(text); if (totalForValue == null) { totalForValue = 0L; } totalForValue += worklog.timeSpent; resultTable.put(text, totalForValue); } } return resultTable; } //Convert from DB id to human readable textual representation. Ex: 10 -> "Coding", 12 -> "Requirement Analysis" def String getTextOfAttributeValue(int attrValue, AttrTypeImp attrType) { return attrType.attributeValues.find({ type -> type.id == attrValue}).name; } //Check whether we have an attribute type with name "Type of Work", if it is return it. def AttrTypeImp getTypeOfWorkAttributeDefinition(AttrTypeService attrTypeService) { def typeOfWorkAttrType = attrTypeService.getAttrTypeWithName("Type of Work"); if (typeOfWorkAttrType.isPresent()) { return attrTypeService.getAttrTypeImpWithId(typeOfWorkAttrType.get().getID()).get(); } else { return null; } }

Paste this code to “Template” field of “Scripted Field” definition.

#if ($value && $value.size() > 0) <table> <tr> <th>Type of Work</th> <th>Sum</th> </tr> #foreach ($typeOfWork in $value.keySet()) #set($sum = $value.get($typeOfWork)) <tr> <td>$typeOfWork</td> <td>$jiraDurationUtils.getFormattedDuration($sum)</td> </tr> #end </table> #end

Of course you need to configure associated screens and issue types/projects for this field to be visible on issue view. You can refer our previous article for more details on this configuration.

At the end, we will able to display sum of efforts for each work type as shown in the following screenshot.