Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in
Deleted user
0 / 0 points
Next:
badges earned

Your Points Tracker
Challenges
Leaderboard
  • Global
  • Feed

Badge for your thoughts?

You're enrolled in our new beta rewards program. Join our group to get the inside scoop and share your feedback.

Join group
Recognition
Give the gift of kudos
You have 0 kudos available to give
Who do you want to recognize?
Why do you want to recognize them?
Kudos
Great job appreciating your peers!
Check back soon to give more kudos.

Past Kudos Given
No kudos given
You haven't given any kudos yet. Share the love above and you'll see it here.

It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

Tempo Account field values with Script Runner?

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

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)

Bravo! Thanks for share

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()
*/

 

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.

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

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?

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

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.

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

@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?

 

@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?

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

is there any new information to this?

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

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

@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?

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.

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?

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...

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.

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!

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

Any update on the account field / account object?  

Like Christos Moysiadis likes this

Something new guys? 

Need this option too

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);

Suggest an answer

Log in or Sign up to answer
TAGS
Community showcase
Published in Confluence

Introducing External Collaboration for Confluence

We’re excited to introduce external collaboration for Confluence, now available in early access. It is available to preview for Confluence Cloud Premium and Enterprise customers. (If you're not on ...

186 views 0 7
Read article

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you