Tempo Account field values with Script Runner?

Timothy Harris
Contributor
February 9, 2016

Would anyone know how I can get the actual value of Tempo plugin's "Account" custom field and not just the index with script runner?

issue.getCustomFieldValue(Account) returns the index and not the value.

Meaning, if I have 3 entries(Bilka, Føtex, Meny) and the value is set to Føtex the above call returns 2.

7 answers

3 votes
Vytautas Chamutovskij April 28, 2020

Hi guys.

I've found a solution how to retreive Tempo account.

Here is the code:

import com.tempoplugin.accounts.account.api.AccountManager; //import AccountManager class

//load Tempo accounts plugin
@WithPlugin(["com.tempoplugin.tempo-accounts"])

//.... your code if needed

//get AccountManager interface instance
// get class first
def cls = ComponentAccessor.getPluginAccessor().getClassLoader().findClass("com.tempoplugin.accounts.account.api.AccountManager");
// get interface instance
def AccountManager aMngr = (AccountManager)ComponentAccessor.getOSGiComponentInstanceOfType(cls);

//retreive all accounts
def allAccounts = aMngr.getAllAccounts();

//search account by it text. Maintenance in this case
def maintenanceAccount = allAccounts?.find { it.getName().contains("Maintenance")};

//use found account value there you need.
issue.setCustomFieldValue(oldValue,maintenanceAccount)
Raul Pelaez _TecnoFor - Marketplace Partner_
Atlassian Partner
April 28, 2020

Bravo! Thanks for share

PeGe6
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
November 25, 2020

here you are my solution:

//import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.atlassian.jira.component.ComponentAccessor
import com.tempoplugin.accounts.account.api.AccountManager //import AccountManager class
import com.tempoplugin.accounts.account.api.Account //import Account class
//import com.tempoplugin.accounts.link.api.AccountLink
//@PluginModule AccountManager accountManager
@WithPlugin("com.tempoplugin.tempo-accounts") //load Tempo accounts plugin
//import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.issue.search.SearchException
import com.atlassian.jira.web.bean.PagerFilter
//import org.apache.log4j.Level
//log.setLevel(Level.INFO)

def currentUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser
//final userKey = currentUser.getName()
//final issueKey = "K2-5579"
//def issueManager = ComponentAccessor.issueManager
//def issue = issueManager.getIssueByCurrentKey(issueKey)
final customFieldName = "Munkaidő projekt"
def customFieldManager = ComponentAccessor.customFieldManager
def customField = customFieldManager.getCustomFieldObjectByName(customFieldName) //.getCustomFieldObjects(issue).find { it.name == customFieldName }
//assert customField: "Could not find custom field with name '$customFieldName' !!!"
if (!customField) { return " n/a " }
//customField.getCustomFieldType() = Tempo Accounts Custom Field (com.tempoplugin.accounts.customfield.account.AccountCustomField)
def issueAccount = (Account) issue.getCustomFieldValue(customField)
//return issueAccount.getMonthlyBudget()
if (!issueAccount) { return null }
def issueAccountId = issueAccount.getId() //=411 //.issueAccount.getLinks()
if (issueAccountId==3) { return "[67]" }
def issuesJQL = "project = 10000 AND 'cf[10800]' = "+issueAccountId
def searchService = ComponentAccessor.getComponentOfType(SearchService)

def M2HM = { int min ->
def hour = ((float)min/60).intValue()
def minute = (min-hour*60).abs()
return (minute)? hour+"h "+minute+"m" : hour+"h"
}

def parseResult = searchService.parseQuery(currentUser, issuesJQL)
if (!parseResult.isValid()) {
//log.error('Invalid JQL query');
return 'Invalid JQL query'
}
try { // Perform the query to get the issues
def results = searchService.search(currentUser, parseResult.query, PagerFilter.unlimitedFilter)
def issues = results.issues
def sumLoggedTime = (int)((float)( issues.sum { Issue it -> it.getTimeSpent() ?: 0 } )/60 )
def sumLoggedTimeHM = M2HM(sumLoggedTime)

if( !issueAccount.getMonthlyBudget() )
return " null ( null - "+sumLoggedTimeHM+" )"
def balanceLoggedTime = issueAccount.getMonthlyBudget()*60-sumLoggedTime
//issues.each { log.info(it.key+" - "+it.getTimeSpent()/3600) }; log.info("Sum: "+sumLoggedTimeHM) //issues*.key //issues*.getTimeSpent() //=10.800sec =3h*3600+0m*60
if( issueAccount.getName().contains("utólag") )
return '<span style="color:SaddleBrown;background-color:Moccasin"> '+M2HM(balanceLoggedTime)+'</span> ('+issueAccount.getMonthlyBudget()+"h - "+sumLoggedTimeHM+")"
if( balanceLoggedTime >= 0 )
return '<span style="color:darkgreen;background-color:PaleGreen"> '+M2HM(balanceLoggedTime)+'</span> ('+issueAccount.getMonthlyBudget()+"h - "+sumLoggedTimeHM+")"
else
return '<span style="color:darkred;background-color:Pink"> '+M2HM(balanceLoggedTime)+'</span> ('+issueAccount.getMonthlyBudget()+"h - "+sumLoggedTimeHM+")"
} catch (SearchException e) {
e.printStackTrace()
'Error'
}
/*
def accountManager = ComponentAccessor.getOSGiComponentInstanceOfType(AccountManager)
//def cls = ComponentAccessor.getPluginAccessor().getClassLoader().findClass("com.tempoplugin.accounts.account.api.AccountManager");
//def AccountManager aMngr = (AccountManager)ComponentAccessor.getOSGiComponentInstanceOfType(cls);
//def allAccounts = accountManager.getAllAccounts();
//def maintenanceAccount = allAccounts?.find { it.getName().contains("MOL")}; //search account by it text. Maintenance in this case
//issue.setCustomFieldValue(oldValue,maintenanceAccount)
def theAccount = accountManager.getAccountByKeyEvenWhenUnknown(issueAccount.getKey())
theAccount.getMonthlyBudget()
*/

 

0 votes
Bert Dombrecht
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
August 23, 2019

Looking at the original question "Would anyone know how I can get the actual value of Tempo plugin's "Account" custom field and not just the index", with Scriptrunner version 5.6.1, 

customFieldManager.getCustomFieldObject("customfield_xxx").getValue(issue);

(where customfield_xxx is the id of the Tempo Account field) does return the actual value and not the id.

I came across this thread while looking for a possibility to copy the Tempo Account value from a source issue onto the 'Create Issue' form with Behaviours.

My use case is: creating a button to easily create a linked issue in another project and copying some of the information from the source issue (such as the Account).

We did struggle to set a value in the Account field (mainly because the logging told us it succeeded while the input field remained unchanged). Based on my observations, I assume there is a difference between the actual customfield 'Account' and the input field in the form. Because of this, setting the value did not change the selection in the input field, but it did correctly set the value in the customfield. On the created, linked issue the Account is set correctly even though in the input form de default was still shown. Eventually we got it to work by getting the selected Account id from the source issue and setting the id into the Account customfield on the form. To avoid confusion, we decided to hide the Account field on the form.

I hope this answers the original question and helps someone trying to set an Account through Scriptrunner / Behaviours.

Note: although we did retrieve the selected Account value from an existing issue, we did not find an easy way to get a full list of existing Accounts, using Groovy.

Here is the code of my Behaviour:

// Imports
import com.atlassian.jira.component.ComponentAccessor;

// Check trigger: Created Linked Issue button

if (getBehaviourContextId() == "createLinkedIssue") {

def issueManager = ComponentAccessor.getIssueManager();
// get origin issue id
def contextIssue = issueManager.getIssueObject(getContextIssueId()); 
// get Tempo Account from origin issue
def accountValue = customFieldManager.getCustomFieldObject("customfield_xxx").getValue(contextIssue);

// check if Tempo Account is set on origin issue
if (accountValue){
// get Tempo Account id from origin issue
def accountId = accountValue.getProperties().id;
// set Tempo Account from origin issue in background
getFieldById("customfield_xxx").setFormValue(accountId).setHidden(true);
} else {
// blank Tempo Account
getFieldById("customfield_xxx").setFormValue(null);
}

// copy Summary from origin issue
getFieldById("summary").setFormValue(contextIssue.summary);
// link to origin issue
getFieldById("issuelinks-linktype").setFormValue("is cause of").setReadOnly(true);
getFieldById("issuelinks-issues").setFormValue(contextIssue.key).setReadOnly(true);
0 votes
Timothy Harris
Contributor
May 19, 2016

@Jamie Echlin (Adaptavist): I have a use case where I would like to ask if this is feasible and maintainable to do with Behaviours. 

Two single select list custom fields. 

Field one: Chain
Field two: Account

The values are dependent upon the selection of the other field. So depending on the selection of "Chain" I need to filter what is visible in "Account" select list. And vice versa, depending on the selection of "Account" I need to set the value of "Chain". There is a one to many relationship from "Chain" to "Account" but a one to one from "Account" to "Chain".

The values of the two fields need to be initialized from other fields. My thought was the following. 

Create a behaviour and add these two fields. 

* initializer Function: Server side groovy script which will read the needed data from two other fields and set the initial values of the two select lists "Chain" and "Account" from the values of two other fields.
* Chain Field: Server side groovy script, which will set the available values(plural) of "Account" select list when "Chain" value is selected.
* Account Field: Server side groovy script, which will set the value of "Chain" select list.

Is this feasible? 
Do you foresee any issues with this approach?

JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 19, 2016

It should be feasible, but after you've chosen the Account field the Chain will effectively be locked as there will only be one option in it. 

I am not sure this is related to the original question, so would be better to post a new one rather than answering a question with a question.

I'll delete your post on disqus if you don't mind. Cross-posting hugely increases our workload.

Timothy Harris
Contributor
May 19, 2016

Sure, go ahead. Didn't mean to increase your work load cheeky

When you say effectively locked, what exactly do you mean? All I really want to do here is to manage the values of the select lists dynamically based on the selection of the other one.

So user goes in and finds some value from "Account" and sets the value. The value of Chain will then be set. He should be able to re open the issue and edit either the "Chain" or the "Account" fields.  Will this not be possible?

Timothy Harris
Contributor
May 19, 2016

Or do you mean that once "Account" is set then we will set chain and he will not be able to change it until he re-opens the issue...

JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 19, 2016

You said one is 1-many and one is 1-1. So if you update both ways, you will be in a situation when one field only has a single option. I think you will be better off if you just update the options for Account field. If the account field changes you can set the Chain, but I would not set the available options.

Timothy Harris
Contributor
May 19, 2016

I get what you mean smile

I think you are right also. No options update on Chain just set the selected option. The options on Account will always be all available or just a subset based on chain. My biggest worry with this is the timing/performance of it. I have to get the Account values through tempo's REST interface.

Thanks for the feedback!

parthiban_selvaraj January 13, 2019

Hi All,

 

Did anyone updated the Tempo Account field through Behaviour or Post Function Workflow.

Kindly suggest the solution. I tried my best but so far I didnt get any solution.

 

Thanks,

Parthiban

Like Christos Moysiadis likes this
Robb F Watkins January 29, 2019

Any update on the account field / account object?  

Like Christos Moysiadis likes this
Christos Moysiadis
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 11, 2019

Something new guys? 

Need this option too

0 votes
Fabrizio Galletti
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 12, 2016

Is there a way to "SET" the value starting from the ACCOUNT KEY and not ID

0 votes
Hlynur Johnsen
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 12, 2016

Unfortunately this method only returns the selected Account id.  We are working on improvements that include  returning the Account object for this method, which will allow you to get to the information you are looking for.  We are hoping to release this improvement in Q1/Q2.

In the meantime, if you are able to use our REST API's in your context, you can retrieve the Account name, or other attributes of the Account, using the Tempo Account API.  Please find information about how to use the Account API here.

Regards,

Hlynur Johnsen

Product Owner - Tempo Books

Timothy Harris
Contributor
February 18, 2016

Hi @Hlynur Johnsen,

Thanks for the reply smile 

I guess I will need to get all accounts and find the on with the matching ID I get back from the getCustomFieldValue() call. Not super efficient but doable I guess. Would be really great if the API had a get Account by Issue ID which would return the selected account. But maybe that comes?

Hlynur Johnsen
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 18, 2016

Hi @Timothy Harris,

Like I mentioned in my comment, we will be changing the return type of the getCustomFieldValue() method to Account, which means that you will have all the information for that account at hand, including the name.  Is that something that will help with your use case?

Regarding your suggestion for getting Account by Issue ID, are you referring to the JIRA Issue API, or the Tempo Account API?  We have no control over the JIRA API, other than what I have described above regarding the return type.  

If you are able to use the Tempo Account (REST) API, you have the option to get the Account by Account ID (which getCustomFieldValue() currently returns).  Technically, we can add a new call to the Account (REST) API, which returns the Account being used by an Issue (Account by Issue ID).  If you are interested in this I suggest that you create an Improvement request in our JIRA instance  Just create a new issue, select Accounts(JTMAC) in the Project field and Improvement in the Issue Type field.  You then need to supply a summary and a description - the more info the better wink - and we will evaluate the request when planning our roadmap.

Hope this helps,

Regards,

Hlynur

JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 22, 2016

Hlynur... what is the internal tempo class that would allow us to get the string or object value from the ID? We don't need to use solely the REST API.

Hlynur Johnsen
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 8, 2016

The REST API uses the AccountService and the getAccountById function to get the Account object.

Timothy Harris
Contributor
May 12, 2016

@Hlynur Johnsen: You mentioned this:

We are working on improvements that include  returning the Account object for this method, which will allow you to get to the information you are looking for.  We are hoping to release this improvement in Q1/Q2.

Do you know what version this will be released in and when it will be released? My customer would wait for this if it is not too far in the future?

 

Timothy Harris
Contributor
May 19, 2016

@Jamie Echlin (Adaptavist): Hi Jamie, I was going to start on a task which was the initial driver for this question. Would you mind perusing the use case below and letting me know what your thoughts are?

Hlynur Johnsen
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 23, 2016

Hi @Timothy Harris, 

Sorry about the late response.  We will be releasing this in our next Tempo Timesheets version, which is scheduled for release in May or early June, so it should be right around the corner.

Regards,

Hlynur

Alexander Richter
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 28, 2018

is there any new information to this?

How am i able to set an Value to the Account Field by using scriptrunner?

0 votes
JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 9, 2016

There is some info on tempo here: https://scriptrunner.adaptavist.com/latest/jira/working-with-tempo.html - but I don't think it's what you want. I think you will need to get the possible values for that field and associate it. I think you can reorder the values though, so it's probably not an index (and indexes are normally zero-based). Hopefully someone from Tempo can point to the right manager/service/class.

Suggest an answer

Log in or Sign up to answer