looking for a date field to display the value of another custom field plus 10 days in date format

Philemon Nkafu September 8, 2020

I have a transition timestamp field (Medical Record Requested) that captures the date of a specific transition. I would like script runner to help me enable another field to display date of the transition field + 10 days.  I have created a scripted field using script runner  but it is displaying an error.

Below is the script:

import com.atlassian.jira.component.ComponentAccessor

final String customField = "Medical Record Requested"

def startDate = Calendar.instance
def endDate = Calendar.instance

def changeHistoryManager = ComponentAccessor.changeHistoryManager
def transition = changeHistoryManager.getChangeItemsForField(issue, customField)

startDate.setTime(transition*.created.max())

int weekDays = 10
while (startDate.timeInMillis < endDate.timeInMillis) {
startDate.add(Calendar.DAY_OF_MONTH, 1)
startDate.get(Calendar.DAY_OF_WEEK) in [Calendar.SATURDAY, Calendar.SUNDAY] ? null : ++weekDays
}

weekDays

 

Below is the error am getting after I execute the targeted transition:

$dateFormatterWithoutTime.format($value)

 

Please I would need some help 

5 answers

3 accepted

0 votes
Answer accepted
Philemon Nkafu September 28, 2020

Hello Gustavo,

I ran to a problem with the script and I hope you may be able to help. The script is not returning a due date for "Medical Record Requested" value entered in the past. I basically want to have the field populate due dates for past tickets. Right now, it is only returning for values entered now.

Appreciate your help.

Gustavo Félix
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.
September 28, 2020

I'm not sure if I understand .
When the scriptfield is executed you want to get past values for "Medical Record Requested. Then, you want to populate other tickets with this values?

Philemon Nkafu September 29, 2020

Hello Gustavo,

Am getting the following error message 

Time (on server): Tue Sep 29 2020 11:58:12 GMT-0500 (Central Daylight Time)

The following log information was produced by this execution. Use statements like:log.info("...") to record logging information.

2020-09-29 11:58:12,576 ERROR [customfield.GroovyCustomField]: *************************************************************************************
2020-09-29 11:58:12,576 ERROR [customfield.GroovyCustomField]: Script field failed on issue: CSL-78632, field: Medical Record Due
java.lang.ArrayIndexOutOfBoundsException: -1
 at java_util_List$get$3.call(Unknown Source)
 at Script11.run(Script11.groovy:14)

Medical Record Due failed executions.JPG

Gustavo Félix
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.
September 29, 2020

I guess the line 14 is

startDate.setTime(transitions.get(transitions.size()-1).created)

This is because when you create an issue , your transition size is 0.
That's why the -1. 

So, do you need this to work when the issue is created?

Philemon Nkafu September 29, 2020

@Gustavo Félix 

This field only gets created after a specific transition after the  ticket is created. Basically, from the "CREATED" Status, there are 3 outbound statuses. It is only one of those statuses that would update the field "Medical Record Requested" from which value, the [scripted] am seeking help with, will calculate 10 days out and populate. 

Hope that clarify my requirement. Would putting the transition ID in there make a difference?

Gustavo Félix
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.
September 29, 2020

Yes, but just to be clear

Your requirement is to calculate this scripted field based on when medical record requested gets updated or with the value that is on medical record requested?

I understood that is when it gets updated. 
So, if I'm right,
List<ChangeItemBean> transitions = changeHistoryManager.getChangeItemsForField(issue,"Medical Record Requested")
This method is going to work when your field gets updated, in an edit for example.
But if its on creation, its going to fail, because your field is not being updated. 

So, I think you should add an if to validate when your transitions size is >= 1(to be sure is an update)
if(transitions.size()>=1){
startDate.setTime(transitions.get(transitions.size()-1).created)
....
....
}
But you also have to handle when it is a creation.
So you could add another if to get your medical record field in a creation. If its not null, then you could take your start date when the issue is created. 
Something like this:

... 
//your initial code
...
def medicalRequestedField= ComponentAccessor.getCustomFieldManager.getCustomFieldObjectByName("Medical Record Requested")
if(issue.getCustomFieldValue(medicalRequestedField)!=null){

if(transitions.size()>=1){
startDate.setTime(transitions.get(transitions.size()-1).created)
}else{
startDate.setTime(issue.getCreated()) 
}
int weekDays = 10
int i = 0;
while(i<weekDays){
     startDate.add(Calendar.DAY_OF_MONTH,1)
     //If its saturday or sunday it add one more day 
     if(startDate.get(Calendar.DAY_OF_WEEK)==Calendar.SATURDAY ||                                startDate.get(Calendar.DAY_OF_WEEK)==Calendar.SUNDAY){
        weekDays++
      }
     i++
}
return startDate.getTime()
}

Let me know if this is what you needed. 


Philemon Nkafu September 29, 2020

@Gustavo Félix  The "Medical Record Requested" CF only gets updated (through the JSU Update any field i.e transition datetime stamp) during a specific transition after the ticket is created and is only on the issue view screen. At no time will that ever have value during issue creation. 

Please help me get this out.

Thanks for your help.

Gustavo Félix
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.
September 29, 2020

Ok,  I dont know how JSU works but based on what you say I still think that the code will work.

Can you try and let me know if it worked.

Philemon Nkafu September 30, 2020

@Gustavo Félix Appreciate your patience with a script learner. Will the below do the trick?

import com.atlassian.jira.issue.changehistory.ChangeHistoryManager;
import com.atlassian.jira.issue.history.ChangeItemBean;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.Issue;

def medicalRequestedField= ComponentAccessor.getCustomFieldManager.getCustomFieldObjectByName("Medical Record Requested")
if(issue.getCustomFieldValue(medicalRequestedField)!=null){

if(transitions.size()>=1){
startDate.setTime(transitions.get(transitions.size()-1).created)
}else{
startDate.setTime(issue.getCreated()) 
}

int weekDays = 10
int i = 0;
while(i<weekDays){
     startDate.add(Calendar.DAY_OF_MONTH,1)
     //If its saturday or sunday it add one more day 
     if(startDate.get(Calendar.DAY_OF_WEEK)==Calendar.SATURDAY ||                                startDate.get(Calendar.DAY_OF_WEEK)==Calendar.SUNDAY){
        weekDays++
      }
     i++
}
return startDate.getTime()

Philemon Nkafu September 30, 2020

@Gustavo Félix I just tried the above script and am getting an error on line 24 column 31 i.e the very last line .

"expecting '}', found ' ' @ line 24 column 31. @ line 24 column 31."

Gustavo Félix
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.
September 30, 2020

You are missing a "}" after return startDate.getTime()

Like this:

return startDate.getTime() 
}

Philemon Nkafu September 30, 2020

@Gustavo Félix I just added "}" at the end and got errors on multiple lines.

Gustavo Félix
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.
September 30, 2020

Ok, I see the error.

You are missing the transitions , startDate and changeHistoryManager declarations.
Let me know if this fixes it or if it shows you any other error.

import com.atlassian.jira.issue.changehistory.ChangeHistoryManager;
import com.atlassian.jira.issue.history.ChangeItemBean;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.Issue;

def changeHistoryManager = ComponentAccessor.changeHistoryManager

def startDate = Calendar.instance


//This gets the change history of your custom field
List<ChangeItemBean> transitions = changeHistoryManager.getChangeItemsForField(issue,"Medical Record Requested")

def medicalRequestedField= ComponentAccessor.getCustomFieldManager.getCustomFieldObjectByName("Medical Record Requested")
if(issue.getCustomFieldValue(medicalRequestedField)!=null){

if(transitions.size()>=1){
startDate.setTime(transitions.get(transitions.size()-1).created)
}else{
startDate.setTime(issue.getCreated())
}
int weekDays = 10
int i = 0;
while(i<weekDays){
startDate.add(Calendar.DAY_OF_MONTH,1)
//If its saturday or sunday it add one more day
if(startDate.get(Calendar.DAY_OF_WEEK)==Calendar.SATURDAY || startDate.get(Calendar.DAY_OF_WEEK)==Calendar.SUNDAY){
weekDays++
}
i++
}
return startDate.getTime()
}

Philemon Nkafu October 1, 2020

@Gustavo Félix This getting error on lines 14 & 15 columns 28 & 4 respectively i.e

 

Line 14 column 28

Line 15 column Lines 14 and 15  Columns 28 and 4 errors.JPG

Gustavo Félix
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.
October 1, 2020

Sorry, that was my mistake. 
I cant copy from my jira instance  , so I missed the () 
def medicalRequestedField = ComponentAccessor.getCustomFieldManager().....

When those type of error appears, you can type ComponentAccessor , then ctrl space bar and it will show you the "options" you can type. 

Gustavo Félix
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.
October 1, 2020

ComponentAccessor with a dot then ctrl space bar *

Philemon Nkafu October 1, 2020

@Gustavo Félix I got the it working with no errors. A million Thanks for your help. Below is the final script.

import com.atlassian.jira.issue.changehistory.ChangeHistoryManager;
import com.atlassian.jira.issue.history.ChangeItemBean;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.Issue;

def changeHistoryManager = ComponentAccessor.changeHistoryManager

def startDate = Calendar.instance


//This gets the change history of your custom field
List<ChangeItemBean> transitions = changeHistoryManager.getChangeItemsForField(issue,"Medical Record Requested")

def medicalRequestedField= ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName("Medical Record Requested")
if(issue.getCustomFieldValue(medicalRequestedField)!=null){

if(transitions.size()>=1){
startDate.setTime(transitions.get(transitions.size()-1).created)
}else{
startDate.setTime(issue.getCreated())
}
int weekDays = 10
int i = 0;
while(i<weekDays){
startDate.add(Calendar.DAY_OF_MONTH,1)
//If its saturday or sunday it add one more day
if(startDate.get(Calendar.DAY_OF_WEEK)==Calendar.SATURDAY || startDate.get(Calendar.DAY_OF_WEEK)==Calendar.SUNDAY){
weekDays++
}
i++
}
return startDate.getTime()
}

Like Gustavo Félix likes this
0 votes
Answer accepted
Gustavo Félix
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.
September 23, 2020

Im almost sure is this line:

startDate.setTime(transition*.created.max())

Based on this:
https://community.atlassian.com/t5/Jira-questions/Not-able-to-get-last-custom-field-value-using/qaq-p/854451

I tried this and it returned the date:

List<ChangeItemBean> transitions = changeHistoryManager.getChangeItemsForField(issue,"your field name")
return transitions.get(transitions.size()-1).created

so, I guess this + your code could work
List<ChangeItemBean> transitions = changeHistoryManager.getChangeItemsForField(issue,"your field name")
startDate.setTime(transitions.get(transitions.size()-1).created)

int weekDays = 10
while (startDate.timeInMillis < endDate.timeInMillis) {
startDate.add(Calendar.DAY_OF_MONTH, 1)
startDate.get(Calendar.DAY_OF_WEEK) in [Calendar.SATURDAY, Calendar.SUNDAY] ? null : ++weekDays
}

Let me know if it works.

Philemon Nkafu September 24, 2020

Scripted Field Error 9.24.2020.JPGI am getting the following error. I am creating a scripted field, could that be the issue? It seem you want me to do a post function instead.

Also, my requirement is not 10 days from issue creation date. It is from a Custom field (Medical Record Requested) that only gets completed at a different transition. 

Gustavo Félix
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.
September 24, 2020

Sorry , I forgot to add the import.
import com.atlassian.jira.issue.history.ChangeItemBean
I was also using a scripted field.
The 10 days that I add, was just to test the code, you can modify that part with your code.

Let me know if it works

Philemon Nkafu September 24, 2020

Evenning modification scripted field for 10 days from date type CF value.JPG

Philemon Nkafu September 24, 2020

Hi Gustavo,

Not sure what am not getting right but below is the exact script I wrote and still getting the above error

import com.atlassian.jira.issue.changehistory.ChangeHistoryManager;
import com.atlassian.jira.issue.history.ChangeItemBean;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.Issue;

list<ChangeItemBean> transitions = changeHistoryManager.getChangeItemsForField(issue,"Medical Record Requested")
startDate.setTime(transitions.get(transitions.size()-1).created)

int weekDays = 10
while (startDate.timeInMillis < endDate.timeInMillis) {
startDate.add(Calendar.DAY_OF_MONTH, 1)
startDate.get(Calendar.DAY_OF_WEEK) in [Calendar.SATURDAY, Calendar.SUNDAY] ? null : ++weekDays
}

Gustavo Félix
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.
September 24, 2020

Its because you have "list" instead of "List".

Philemon Nkafu September 25, 2020

Hi Gustavo,

I have attempted to no success. 

Gustavo Félix
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.
September 25, 2020

Just saw that you dont have this
def changeHistoryManager = ComponentAccessor.changeHistoryManager


Philemon Nkafu September 25, 2020

Where exactly should I fit this line? Can you please just provide me the completed script. 

Thanks 

Gustavo Félix
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.
September 25, 2020

import com.atlassian.jira.issue.changehistory.ChangeHistoryManager;
import com.atlassian.jira.issue.history.ChangeItemBean;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.Issue;

def changeHistoryManager = ComponentAccessor.changeHistoryManager

//This gets the change history of your custom field
List<ChangeItemBean> transitions = changeHistoryManager.getChangeItemsForField(issue,"Medical Record Requested")

def startDate = Calendar.instance

//Start date starts based on the last modification of your field
startDate.setTime(transitions.get(transitions.size()-1).created)

int weekDays = 10
int i = 0;
while(i<weekDays){
     startDate.add(Calendar.DAY_OF_MONTH,1)
     //If its saturday or sunday it add one more day 
     if(startDate.get(Calendar.DAY_OF_WEEK)==Calendar.SATURDAY ||                                startDate.get(Calendar.DAY_OF_WEEK)==Calendar.SUNDAY){
        weekDays++
      }
     i++
}
return startDate.getTime()

Let me know if this works for you

Philemon Nkafu September 25, 2020

Thanks a million Gustavo. It worked

Like Gustavo Félix likes this
0 votes
Answer accepted
Philemon Nkafu September 22, 2020

Hi Gustavo,

The log does not show any error. 

Gustavo Félix
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.
September 22, 2020

Ok, two questions:
What template are you using for your scripted field? 
If you go to issues->custom Fields-> edit your custom field... what search template are you using? 

Philemon Nkafu September 22, 2020

I am using the Date Time template 

and the searcher is the date time range picker 

0 votes
Philemon Nkafu October 1, 2020

Hi @Gustavo Félix 

I have another issue with a separate script. I am calculating the age of a person based on the DOB value. The script is fine except that am getting a NULL Pointer exception error. I will need some help with adding a line that would return a NULL if the field is empty or better still ignore empty field. Below is the script I have and would appreciate your input. 

import com.atlassian.jira.component.ComponentAccessor
import java.time.Period
import java.time.LocalDate
import java.time.ZoneId

def customFieldManager = ComponentAccessor.customFieldManager
def dob = customFieldManager.getCustomFieldObjectsByName("DOB")[0]
def dobValue = dob.getValue(issue) as Date

static def convertToLocalDateViaInstant(Date dateToConvert) {
return dateToConvert.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate()
}

def today = LocalDate.now()
def birthday = convertToLocalDateViaInstant(dobValue) as LocalDate

def age = Period.between(birthday, today)

return String.format("%d years", age.getYears())

0 votes
Gustavo Félix
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.
September 9, 2020

Hi @Philemon Nkafu 
Does the log shows you the line were it fails ? 

Suggest an answer

Log in or Sign up to answer