Script listener function failed on event: com.atlassian.jira.event.issue.IssueEvent, file: null

baz89103 May 24, 2023

Hi Community, I am having some difficulty getting the code to work for auto creating tempo plans to users based upon getting assigned.

I referred following link - https://library.adaptavist.com/entity/create-tempo-planning-information-when-issue-is-assigned

for my use case.

Use Case: Auto create tempo plans with Time Tracking and assigned user

However when i am assigning issue to a user i am getting following error:

-----------------------------------------------------------------------------------------------------

*************************************************************************************************

ERROR:

2023-05-24 11:49:29,991 ERROR [runner.AbstractScriptListener]: ************************************************************************************* 2023-05-24 11:49:29,999 ERROR [runner.AbstractScriptListener]: Script function failed on event: com.atlassian.jira.event.issue.IssueEvent, file: null com.atlassian.sal.api.net.ResponseStatusException: Unexpected response received. Status code: 400 at com.atlassian.sal.core.net.HttpClientRequest.lambda$execute$0(HttpClientRequest.java:77) at com.atlassian.sal.core.net.HttpClientRequest.executeAndReturn(HttpClientRequest.java:102) at com.atlassian.sal.core.net.HttpClientTrustedRequest.executeAndReturn(HttpClientTrustedRequest.java:53) at com.atlassian.sal.core.net.HttpClientRequest.execute(HttpClientRequest.java:75) at com.atlassian.sal.api.net.Request$execute$0.call(Unknown Source) at Script1.run(Script1.groovy:59) 

-----------------------------------------------------------------------------------------------------

*************************************************************************************************

 

Script used:

import com.atlassian.sal.api.ApplicationProperties
import com.atlassian.sal.api.UrlMode
import com.atlassian.sal.api.net.Request
import com.atlassian.sal.api.net.TrustedRequestFactory
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import groovy.json.JsonOutput
import groovyx.net.http.URIBuilder

import java.time.LocalDate
import java.time.format.DateTimeFormatter

@WithPlugin('com.tempoplugin.tempo-plan-core')

@PluginModule
ApplicationProperties applicationProperties

@PluginModule
TrustedRequestFactory trustedRequestFactory

// Default start time
final startTime = '09:00'

// Weekends and holidays are not included by default. If a plan needs to be created on weekends and holidays, set this to "true"
final includeNonWorkingDays = false

final today = LocalDate.now()

def issue = event.issue
def endDate = issue.dueDate?.toLocalDateTime()?.toLocalDate()

// Do nothing if the issue has been unassigned
if (!issue.assignee) {
return
}

if (!(issue.estimate && endDate)) {
log.error('Issue requires both an estimate and a due date. Plan not created')
return
}

def url = applicationProperties.getBaseUrl(UrlMode.CANONICAL) + '/rest/tempo-planning/1/plan'
def request = trustedRequestFactory.createTrustedRequest(Request.MethodType.POST, url)

def host = new URIBuilder(url).host
request.addTrustedTokenAuthentication(host)
request.setRequestBody(JsonOutput.toJson([
planItemType : 'ISSUE',
planItemId : issue.id,
assigneeKey : 'admin',
start : DateTimeFormatter.ISO_LOCAL_DATE.format(today),
startTime : startTime,
day : DateTimeFormatter.ISO_LOCAL_DATE.format(today),
end : DateTimeFormatter.ISO_LOCAL_DATE.format(endDate),
includeNonWorkingDays: includeNonWorkingDays,
secondsPerDay : issue.estimate
]), 'application/json')

request.execute()

-----------------------------------------------------------------------------------------------------

*************************************************************************************************

 

Thanks,

BAZ

3 answers

2 votes

Hi Baz!

I've just answered the ticket you raised to Adaptavist Support, but the answer may be beneficial on this Community Post too for other to see :)

Essentially, since the creation of our Library Script, the Tempo API has been updated to require the assigneeKey.

We can modify the Library Script to include this data:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.sal.api.ApplicationProperties
import com.atlassian.sal.api.UrlMode
import com.atlassian.sal.api.net.Request
import com.atlassian.sal.api.net.TrustedRequestFactory
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import groovy.json.JsonOutput
import groovyx.net.http.URIBuilder
import java.time.LocalDate
import java.time.format.DateTimeFormatter

@WithPlugin('com.tempoplugin.tempo-plan-core')
@PluginModule
ApplicationProperties applicationProperties

@PluginModule
TrustedRequestFactory trustedRequestFactory

// Default start time
final startTime = '09:00'

// Weekends and holidays are not included by default. If a plan needs to be created on weekends and holidays, set this to "true"
final includeNonWorkingDays = false

final today = LocalDate.now()

def issue = event.issue

def endDate = issue.dueDate?.toLocalDateTime()?.toLocalDate()

// Do nothing if the issue has been unassigned
if (!issue.assignee) {
return
}

if (!(issue.estimate && endDate)) {
log.error('Issue requires both an estimate and a due date. Plan not created')
return
}

def url = applicationProperties.getBaseUrl(UrlMode.CANONICAL) + '/rest/tempo-planning/1/plan'
def request = trustedRequestFactory.createTrustedRequest(Request.MethodType.POST, url)
def host = new URIBuilder(url).host

request.addTrustedTokenAuthentication(host)

request.setRequestBody(JsonOutput.toJson([
assigneeKey : 'JIRAUSER10000',
assigneeType : 'USER',
day : DateTimeFormatter.ISO_LOCAL_DATE.format(today),
end : DateTimeFormatter.ISO_LOCAL_DATE.format(endDate),
includeNonWorkingDays: includeNonWorkingDays,
planItemId : issue.id,
planItemType : 'ISSUE',
secondsPerDay : issue.estimate,
start : DateTimeFormatter.ISO_LOCAL_DATE.format(today),
startTime : startTime
]), 'application/json')

request.execute()

I'm working on updating the Library Script with this additional variable, as well as make it clearer to use the User's Key for assigneeKey.

If anyone's wondering, you can retrieve the User's Key with the following in the Script Console

import com.atlassian.jira.component.ComponentAccessor 

log.warn ComponentAccessor.userManager.getUser('exampleUsername').getKey()

Hope this helps! :D

Kind regards,

Olly

0 votes
Ram Kumar Aravindakshan _Adaptavist_
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
May 24, 2023

Hi @baz89103

The listener appears to be complaining about the event. Could you please confirm which event you have configured for it?

It would be helpful if you could share a screenshot of the Listener configuration.

I am looking forward to your clarification.

Thank you and Kind regards,

Ram

baz89103 May 24, 2023

Thanks for the reply @Ram Kumar Aravindakshan _Adaptavist_ 

I have configured Issue assigned event, adding snapshotsevent assigned.PNG

snippet.PNG

0 votes
Radek Dostál
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 24, 2023

So basically you need to debug why the endpoint gives you a 400

 

com.atlassian.sal.api.net.ResponseStatusException: Unexpected response received. Status code: 400
 
at com.atlassian.sal.core.net.HttpClientRequest.lambda$execute
...
 at Script1.run(Script1.groovy:59)

 Where groovy:59 refers to your line, the last command in this stack is an execute closure. Putting 2 and 2 together this refers to the method 'requet.execute()' in your code.

 

So, you're sending data to the endpoint, and it returns 400 as a reply, and for whatever reason the http client underneath the "request" throws an exception because of it.

I can't tell you why that is, but probably something in that json is no likey. You should otherwise get a 403 or something if it was not authenticated, but if it gives 400 then the request went through, got to the endpoint, but the endpoint decided something is invalid, so again this makes me think it's something with the data.

So personally I would just take that code apart and only debug the http post, then put it back after finding the flaw.

 

You also might want to compare the json data with the actual documentation - https://www.tempo.io/server-api-documentation/planner#tag/Plan/operation/postPlan

The script in library was written at some point in time, possibly for older versions, so it is quite likely you need to update the template for that endpoint to work.

baz89103 May 24, 2023

Hi @Radek Dostál 

Thanks for your reply, I am new to writing scripts, it will be really helpful if you could point or share some link or docs so that i i can debug this.

baz89103 May 24, 2023

I have changed assigneekey to one of our admin account is this something i am doing correct or it should be the 'admin' itself. After the change error is different.

2023-05-24 14:30:36,538 ERROR [runner.AbstractScriptListener]: ************************************************************************************* 2023-05-24 14:30:36,554 ERROR [runner.AbstractScriptListener]: Script function failed on event: com.atlassian.jira.event.issue.IssueEvent, file: null com.atlassian.sal.api.net.ResponseStatusException: Unexpected response received. Status code: 400 at com.atlassian.sal.core.net.HttpClientRequest.lambda$execute$0(HttpClientRequest.java:77) at com.atlassian.sal.core.net.HttpClientRequest.executeAndReturn(HttpClientRequest.java:102) at com.atlassian.sal.core.net.HttpClientTrustedRequest.executeAndReturn(HttpClientTrustedRequest.java:53) at com.atlassian.sal.core.net.HttpClientRequest.execute(HttpClientRequest.java:75) at com.atlassian.sal.api.net.Request$execute$0.call(Unknown Source) at Script2.run(Script2.groovy:59)assignee key.PNG

Radek Dostál
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 24, 2023

Well it's this part:

def url = applicationProperties.getBaseUrl(UrlMode.CANONICAL) + '/rest/tempo-planning/1/plan'
def request = trustedRequestFactory.createTrustedRequest(Request.MethodType.POST, url)

def host = new URIBuilder(url).host
request.addTrustedTokenAuthentication(host)
request.setRequestBody(JsonOutput.toJson([
planItemType : 'ISSUE',
planItemId : issue.id,
assigneeKey : 'admin',
start : DateTimeFormatter.ISO_LOCAL_DATE.format(today),
startTime : startTime,
day : DateTimeFormatter.ISO_LOCAL_DATE.format(today),
end : DateTimeFormatter.ISO_LOCAL_DATE.format(endDate),
includeNonWorkingDays: includeNonWorkingDays,
secondsPerDay : issue.estimate
]), 'application/json')

request.execute() // <---- this gives 400 Bad Request

 

So I made a few adjustments to fit this into script console so that I can test it:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.sal.api.ApplicationProperties
import com.atlassian.sal.api.UrlMode
import com.atlassian.sal.api.net.Request
import com.atlassian.sal.api.net.TrustedRequestFactory
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import groovy.json.JsonOutput
import groovyx.net.http.URIBuilder
import java.time.LocalDate
import java.time.format.DateTimeFormatter

@PluginModule
ApplicationProperties applicationProperties

@PluginModule
TrustedRequestFactory trustedRequestFactory

// Default start time
final startTime = '09:00'

// Weekends and holidays are not included by default. If a plan needs to be created on weekends and holidays, set this to "true"
final includeNonWorkingDays = false

final today = LocalDate.now()

//def issue = event.issue ; use a specific test issue in console
def issue = ComponentAccessor.getIssueManager().getIssueObject("SENDHELP-1")

def endDate = issue.dueDate?.toLocalDateTime()?.toLocalDate()

// Do nothing if the issue has been unassigned
if (!issue.assignee) {
    return
}

if (!(issue.estimate && endDate)) {
    log.error('Issue requires both an estimate and a due date. Plan not created')
    return
}

def url = applicationProperties.getBaseUrl(UrlMode.CANONICAL) + '/rest/tempo-planning/1/plan'
def request = trustedRequestFactory.createTrustedRequest(Request.MethodType.POST, url)
def host = new URIBuilder(url).host

request.addTrustedTokenAuthentication(host)

/*

    BODY log to console so we can see what's in it

*/

def json = JsonOutput.toJson([
        planItemType : 'ISSUE',
        planItemId : issue.id,
        assigneeKey : 'admin',
        start : DateTimeFormatter.ISO_LOCAL_DATE.format(today),
        startTime : startTime,
        day : DateTimeFormatter.ISO_LOCAL_DATE.format(today),
        end : DateTimeFormatter.ISO_LOCAL_DATE.format(endDate),
        includeNonWorkingDays: includeNonWorkingDays,
        secondsPerDay : issue.estimate
])

log.warn(json.toString())

request.setRequestBody(json, 'application/json')
request.execute()

 

You can just change the issue key, everything else is fine, put it into console, run it, and then switch to Logs to see what's in the json before it's sent to the endpoint.

In my test case, I get:

{"planItemType":"ISSUE","planItemId":3086710,"assigneeKey":"admin","start":"2023-05-24","startTime":"09:00","day":"2023-05-24","end":"2023-05-25","includeNonWorkingDays":false,"secondsPerDay":28800}

 

Now, compare this with the documentation - https://www.tempo.io/server-api-documentation/planner#tag/Plan/operation/postPlan

 

What I see from this is:

  • assigneeType - required, but missing in json

 

Otherwise all other required fields are there, in right format.

Thus, I reckon you just need  to add this to the json:

JsonOutput.toJson([
...
assigneeType: 'string',
...
])

 

Which seems a little weird.. but that's according to what I see in the documentation. Probably this required parameter was added at some point, but the library contains old code.

 

Also, note I can't test it if it really does work - I don't have tempo, this is just coding on paper.

Radek Dostál
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 24, 2023

As for the assigneeKey, if it really is key, remember not to confuse it with the username. Jira has this beautiful age old conflict of what identifier to use..

You can get the user key from:

<baseurl>/rest/api/2/user?username=<username>

Old users will have same key as username, but new users will have something like "JIRAUSER12345" as key!

 

And if you're working with the issue assignee, like this:

def userkey = issue.getAssignee()?.getKey()
baz89103 May 24, 2023

added the code to console, still getting the same error:

***********************************************************************************

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.sal.api.ApplicationProperties
import com.atlassian.sal.api.UrlMode
import com.atlassian.sal.api.net.Request
import com.atlassian.sal.api.net.TrustedRequestFactory
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import groovy.json.JsonOutput
import groovyx.net.http.URIBuilder
import java.time.LocalDate
import java.time.format.DateTimeFormatter

@PluginModule
ApplicationProperties applicationProperties

@PluginModule
TrustedRequestFactory trustedRequestFactory

// Default start time
final startTime = '09:00'

// Weekends and holidays are not included by default. If a plan needs to be created on weekends and holidays, set this to "true"
final includeNonWorkingDays = false

final today = LocalDate.now()

//def issue = event.issue ; use a specific test issue in console
def issue = ComponentAccessor.getIssueManager().getIssueObject("JIRA-2")

def endDate = issue.dueDate?.toLocalDateTime()?.toLocalDate()

// Do nothing if the issue has been unassigned
if (!issue.assignee) {
    return
}

if (!(issue.estimate && endDate)) {
    log.error('Issue requires both an estimate and a due date. Plan not created')
    return
}

def url = applicationProperties.getBaseUrl(UrlMode.CANONICAL) + '/rest/tempo-planning/1/plan'
def request = trustedRequestFactory.createTrustedRequest(Request.MethodType.POST, url)
def host = new URIBuilder(url).host

request.addTrustedTokenAuthentication(host)

/*

    BODY log to console so we can see what's in it

*/

def json = JsonOutput.toJson([
        planItemType : 'ISSUE',
        planItemId : issue.id,
        assigneeKey : 'admin',
        assigneeType: 'string',
        start : DateTimeFormatter.ISO_LOCAL_DATE.format(today),
        startTime : startTime,
        day : DateTimeFormatter.ISO_LOCAL_DATE.format(today),
        end : DateTimeFormatter.ISO_LOCAL_DATE.format(endDate),
        includeNonWorkingDays: includeNonWorkingDays,
        secondsPerDay : issue.estimate
])

log.warn(json.toString())

request.setRequestBody(json, 'application/json')
request.execute()
**************************************************************er console.PNG
Radek Dostál
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 24, 2023

Hm, then perhaps it's with the TrustedRequestFactory.. Frankly, I don't have a good idea anymore.. If the data fits the documentation, the request is authenticated, sounds like a bug in that endpoint.

Have you checked if tempo logs anything to the logs when you make the request? Something that could hint to what it doesn't like.

Alternatively I would try to create a new HttpClient, provide base64 auth to it, and then read the response (maybe it says what it doesn't like), since we cannot see the response because it throws an exception with the request factory client.

 

The documentation also states:

HTTP: basicAuth
HTTP Authorization Scheme: basic

 

So it's entirely possible the vendor has implemented some dog$%&!ery which is unable to properly handle requests from trusted apps. Maybe it really does only work with basic auth.. Well we can test that:

import org.apache.http.HttpEntity
import org.apache.http.HttpHeaders
import org.apache.http.client.methods.CloseableHttpResponse
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.StringEntity
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClientBuilder
import groovy.json.JsonOutput
import org.apache.http.util.EntityUtils

final String name = "admin"
final String pwd = "12345"

String base64auth = new String(Base64.getEncoder().encode((name + ":" + pwd).getBytes()))

CloseableHttpClient closeableHttpClient = HttpClientBuilder.create().build()
try {
HttpPost httpPost = new HttpPost("https://myurl.com/rest/tempo-planning/1/plan")
httpPost.setHeader(HttpHeaders.AUTHORIZATION, "Basic " + base64auth)

def json = JsonOutput.toJson([
planItemType : 'ISSUE',
planItemId : /* set me */,
assigneeKey : 'admin',
assigneeType: 'string',
start : /* set me */,
startTime : /* set me */,
day : /* set me */,
end : /* set me */,
includeNonWorkingDays: /* set me */,
secondsPerDay : /* set me */
])
// P.S.: mind the value types, quotes for Strings, no quotes for integers

httpPost.setEntity(new StringEntity(json))
httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "application/json")
CloseableHttpResponse closeableHttpResponse = closeableHttpClient.execute(httpPost)
try {
int statusCode = closeableHttpResponse.getStatusLine().getStatusCode()
String responseBody = null
HttpEntity entity = closeableHttpResponse.getEntity()
if (entity != null)
responseBody = EntityUtils.toString(entity)

return statusCode + "<br>" + responseBody
}
finally {
closeableHttpResponse.close()
}
}
finally {
closeableHttpClient.close()
}

Again, untested since.. no tempo, but this should theoretically work. Just set the basic auth credentials and fill out the json template with some specific test data (which you can copy from previous test since we logged the contents).

 

NOTE - scriptrunner does store audit logs, so if you want to NOT have those credentials stored anywhere, you need to disable this logging: https://docs.adaptavist.com/sr4js/latest/best-practices/logging/audit-logging

And re-enable it back when you're done since it's generally pretty useful.

 

Now, the idea with this is to test whether the problem is with TrustedRequestFactory (and the endpoint being dumb and not knowing how to handle it), and whether we can get it to work if we adhere to that "basicAuth" requirement they mention.

 

Either, this works, or it doesn't and we may see a message in response, rather than the exception which hides it.

Or, do also verify that tempo doesn't log anything in {jira_home}/log/atlassian-jira.log - maybe it contains a hint when the endpoint returns 400.

 

If this still doesn't work, I would probably open a ticket with Tempo so they can clarify / reproduce / explain what the issue is.

 

Edit: fixed httpclient constructor

(this thread is becoming a bit of a code camp lol)

baz89103 May 28, 2023

sc err.PNGHi @Radek Dostál 

Thank You so much for the support, it was really a code camp for me :)

The script is working, Plans are getting created, However, looks like one issue with the logic. Plans are getting assigned each day for the total estimated hours ex: if i am setting original estimate as 2week it will create plan for 80hrs each day till the due date, if original estimate is 1week, it will create plans for 40hrs each day to the user.

Following script:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.sal.api.ApplicationProperties
import com.atlassian.sal.api.UrlMode
import com.atlassian.sal.api.net.Request
import com.atlassian.sal.api.net.TrustedRequestFactory
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import groovy.json.JsonOutput
import groovyx.net.http.URIBuilder

import java.time.LocalDate
import java.time.format.DateTimeFormatter

@WithPlugin('com.tempoplugin.tempo-plan-core')

@PluginModule
ApplicationProperties applicationProperties

@PluginModule
TrustedRequestFactory trustedRequestFactory

// Default start time
final startTime = '09:00'
// Weekends and holidays are not included by default. If a plan needs to be created on weekends and holidays, set this to "true"
final includeNonWorkingDays = false

final today = LocalDate.now()

def issue = event.issue
def endDate = issue.dueDate?.toLocalDateTime()?.toLocalDate()

// Do nothing if the issue has been unassigned
if (!issue.assignee) {
    return
}

if (!(issue.estimate && endDate)) {
    log.error('Issue requires both an estimate and a due date. Plan not created')
    return
}

def url = applicationProperties.getBaseUrl(UrlMode.CANONICAL) + '/rest/tempo-planning/1/plan'
def request = trustedRequestFactory.createTrustedRequest(Request.MethodType.POST, url)

def host = new URIBuilder(url).host
request.addTrustedTokenAuthentication(host)
request.setRequestBody(JsonOutput.toJson([
    assigneeKey          : 'JIRAUSER10000',
    assigneeType         : 'USER',
    day                  : DateTimeFormatter.ISO_LOCAL_DATE.format(today),
    end                  : DateTimeFormatter.ISO_LOCAL_DATE.format(endDate),
    includeNonWorkingDays: includeNonWorkingDays,
    planItemId           : issue.id,
    planItemType         : 'ISSUE',
    secondsPerDay        : issue.estimate,
    start                : DateTimeFormatter.ISO_LOCAL_DATE.format(today),
    startTime            : startTime
]), 'application/json')

request.execute()
Regards,
BAZ
baz89103 May 28, 2023

Hi @Radek Dostál 

This really got me to learn many things, Thanks for all the support.

The script is creating the plans now, however, looks like there is one small logical error due to which Plans are getting assigned each day for the total estimated hours ex: if i am setting original estimate as 2week it will create plan for 80hrs each day till the due date, if original estimate is 1week, it will create plans for 40hrs each day to the user.

Script :

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.sal.api.ApplicationProperties
import com.atlassian.sal.api.UrlMode
import com.atlassian.sal.api.net.Request
import com.atlassian.sal.api.net.TrustedRequestFactory
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import groovy.json.JsonOutput
import groovyx.net.http.URIBuilder

import java.time.LocalDate
import java.time.format.DateTimeFormatter

@WithPlugin('com.tempoplugin.tempo-plan-core')

@PluginModule
ApplicationProperties applicationProperties

@PluginModule
TrustedRequestFactory trustedRequestFactory

// Default start time
final startTime = '09:00'
// Weekends and holidays are not included by default. If a plan needs to be created on weekends and holidays, set this to "true"
final includeNonWorkingDays = false

final today = LocalDate.now()

def issue = event.issue
def endDate = issue.dueDate?.toLocalDateTime()?.toLocalDate()

// Do nothing if the issue has been unassigned
if (!issue.assignee) {
    return
}

if (!(issue.estimate && endDate)) {
    log.error('Issue requires both an estimate and a due date. Plan not created')
    return
}

def url = applicationProperties.getBaseUrl(UrlMode.CANONICAL) + '/rest/tempo-planning/1/plan'
def request = trustedRequestFactory.createTrustedRequest(Request.MethodType.POST, url)

def host = new URIBuilder(url).host
request.addTrustedTokenAuthentication(host)
request.setRequestBody(JsonOutput.toJson([
    assigneeKey          : 'JIRAUSER10000',
    assigneeType         : 'USER',
    day                  : DateTimeFormatter.ISO_LOCAL_DATE.format(today),
    end                  : DateTimeFormatter.ISO_LOCAL_DATE.format(endDate),
    includeNonWorkingDays: includeNonWorkingDays,
    planItemId           : issue.id,
    planItemType         : 'ISSUE',
    secondsPerDay        : issue.estimate,
    start                : DateTimeFormatter.ISO_LOCAL_DATE.format(today),
    startTime            : startTime
]), 'application/json')

request.execute(sc err.PNG
Radek Dostál
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, 2023

It sounds like this in json

secondsPerDay        : issue.estimate

but I'm not familiar with tempo so I don't know how it works. Not sure what you want to configure there but I guess secondsPerDay param sounds the closest to what you describe?

Shahebaaz Shaikh May 29, 2023

.

baz89103 May 29, 2023

@Radek Dostál  Yeah, I tried setting seconds per the day, however still it is assigning total estimations each day.

Thank You

Suggest an answer

Log in or Sign up to answer