Come for the products,
stay for the community

The Atlassian Community can help you and your team get more value out of Atlassian products and practices.

Atlassian Community about banner
4,364,443
Community Members
 
Community Events
168
Community Groups

Capture time when a custom field in an issue is updated and no. of weekdays since it is last updated

Dear @Alexey Matveev _Appfire_ as you always help me every time. Would you be able to look into my issue, Please. 

I want to capture time when a custom field in an issue is updated and no. of weekdays since it is last updated. It's returning null. 

I found this code in the community pages: it is not working for me. I need your advise.

import com.atlassian.jira.component.ComponentAccessor

def issueManager = ComponentAccessor.getIssueManager()
def changeHistoryManager = ComponentAccessor.getChangeHistoryManager()

def issue = issueManager.getIssueObject("PT-12867")
def previousTransitison = changeHistoryManager.getChangeItemsForField(issue, 'customFieldId=10013')
previousTransitison*.created.max(){}

 

Result is null.

3 answers

1 accepted

Hello, @Marija Ušakova.

The answer of @Ivan Tovbin is a valid answer. I would like just to add, that your script did not work, because you passed 'customFieldId=10013' to the getChangeItemsForField method. You should pass the name of your custom field in the method.

Also the script of Ivan will return your the date difference with weekends, but I guess, you wanted to exclude weekdays. I would suggest you the following script:

import com.atlassian.jira.component.ComponentAccessor
import java.sql.Timestamp
import java.util.Calendar

Calendar endCal = Calendar.getInstance();
Calendar startCal = Calendar.getInstance();
def issueManager = ComponentAccessor.getIssueManager()
def changeHistoryManager = ComponentAccessor.getChangeHistoryManager()
def issue = issueManager.getIssueObject("PT-12867")
def previousTransitison = changeHistoryManager.getChangeItemsForField(issue, 'yourCustomFieldName')
startCal.setTime(previousTransitison*.created.max())

int workDays = 0
while (startCal.getTimeInMillis() < endCal.getTimeInMillis()) {

startCal.add(Calendar.DAY_OF_MONTH, 1);
if (startCal.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY && startCal.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {
++workDays;
}

} ;
log.error("n. of working days: " + workDays)

 

So may I ask, how to use this in jql query as there are many issues using this custom field and I should have mentioned earlier this problem like in the program we only pass the issue one at a time vs scan all issues. As always thank you.

You should change your script to this one

import com.atlassian.jira.component.ComponentAccessor
import java.sql.Timestamp
import java.util.Calendar

Calendar endCal = Calendar.getInstance();
Calendar startCal = Calendar.getInstance();
def issueManager = ComponentAccessor.getIssueManager()
def changeHistoryManager = ComponentAccessor.getChangeHistoryManager()
def issue = issueManager.getIssueObject("PT-12867")
def previousTransitison = changeHistoryManager.getChangeItemsForField(issue, 'yourCustomFieldName')
startCal.setTime(previousTransitison*.created.max())

int workDays = 0
while (startCal.getTimeInMillis() < endCal.getTimeInMillis()) {

startCal.add(Calendar.DAY_OF_MONTH, 1);
if (startCal.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY && startCal.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {
++workDays;
}

} ;
return workDay

Then you should set Number searcher or Number range searcher for the custom field and then you can use the field in your JQL queries.

@Alexey Matveev _Appfire_ My current issue with that setting is I do not have the custom field as a number searcher, but it is a text field and I wish to see the timestamp of it when it was last updated and put the difference in number or use now() in jql search and please do note that I don't know how to rewrite the code to search for all issues not just PT-12867. As always thank you very much.

1. JQL result is always a list of issues. You can define custom fields, which you want to see in the list. You can not add any additional information. That is why if you want to show a timestamp, when a field was changed, then you need to add a scirpted custom field, which would show you the information.

2. If you want to filter issues, where a number of days passed since the last update, in JQL then you have 2 choices

- you can create a scripted custom field with the Number searcher and make it the Number type

- you can write your own JQL function, let s say (myFieldChangedWithin(Number numberOfDays)), which will return you all issues, changed within the number of Days.

In my opinion, the first method is prefferable. Because it is easy to write and you will not have performance problems.

The second method is difficult to write and prone to poor performance.

If you take the first method (create a scripted field), then your script will look like this.

import com.atlassian.jira.component.ComponentAccessor
import java.sql.Timestamp
import java.util.Calendar

Calendar endCal = Calendar.getInstance();
Calendar startCal = Calendar.getInstance();
def issueManager = ComponentAccessor.getIssueManager()
def changeHistoryManager = ComponentAccessor.getChangeHistoryManager()
def previousTransitison = changeHistoryManager.getChangeItemsForField(issue, 'yourCustomFieldName')
startCal.setTime(previousTransitison*.created.max())

int workDays = 0
while (startCal.getTimeInMillis() < endCal.getTimeInMillis()) {

startCal.add(Calendar.DAY_OF_MONTH, 1);
if (startCal.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY && startCal.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {
++workDays;
}

} ;
return workDay

Suppose, you added a custom field called NDaysFromLastUpdate. Then you can write in JQL like this

NDaysFromLastUpdate = 2

It will mean, that you want to find all issues, where the number of days since last update equals 2.

Thank you @Alexey Matveev _Appfire_ it worked. Can you help me with another question, I want to create mock user groups and users for testing out permissions. 

Something like this: 

import com.atlassian.jira.component.ComponentAccessor;
def mu = ComponentAccessor.getUserUtil()
def user = mu.getUserByName("test.user_ad1")
def group = mu.getGroupObject("jira-developers")
uu.addUserToGroup(group, user.getDirectoryUser())

.... I do need your input..

But i need to add groups as well to local jira group and also Active Directory. Many Thanks

You want to create groups in a script or you want to add users to already created groups?

if you want to add users to local groups, then there will be no problems. If you want to add users to AD groups, then your user directory must be setup as Read/Write and the user, under which you connect to the AD in the user directory settings, must have permissions to add users to group in AD.

 

I had a look at your script. I guess you are on the right way. If something does not work, then let me know.

@Alexey Matveev _Appfire_ I did succeed adding new users in the internal directory but, so now I need your help creating new 'group' to the internal directory.

 

You can create a group like this

 

import com.atlassian.jira.component.ComponentAccessor

ComponentAccessor.getGroupManager().createGroup("group name")

That helps and works@Alexey Matveev _Appfire_ Many many thanks.

Here is another example using html to format the old strings from the new strings for a custom field. I've tested the timestamp of the custom field doesn't update if the overall Jira issue is updated

{code}


//define classes
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.changehistory.ChangeHistoryItem
import com.atlassian.jira.issue.history.ChangeItemBean

IssueManager issueManager = ComponentAccessor.getIssueManager();

// definitions
def changeHistoryManager = ComponentAccessor.getChangeHistoryManager();
def changeItems = changeHistoryManager.getChangeItemsForField(issue, "<custom field name>);

// def userUtil = ComponentAccessor.getUserUtil(); // if you want to show the respective JiraUser object which executed the change

def last_change = changeItems.last();
def lastModifiedCF = last_change["field"];
def fromValue = last_change["fromString"];
def toValue = last_change["toString"];
def timeStamp = last_change["created"];

// HTML function to add bold and color text to categories: fromValue will be Bold Red, toValue will be Bold Green, Timestamp will be Bold Black

def String formatted = """
<server>
<p><strong>Modified Field:</strong> $lastModifiedCF</p>
<p><strong><span style="color: rgb(226, 80, 65);">From Value:</span></strong> $fromValue</p>
<p><strong><span style="color: rgb(65, 168, 95);">To Value:</span></strong> $toValue</p>
<p><strong>TimeStamp:&nbsp;</strong> $timeStamp</p>
</server>
"""
return formatted;
{code}

Hi Marija,

Assuming you want this returned as a scripted field value, here's the code to do it:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.changehistory.ChangeHistoryManager
import java.sql.Timestamp

ChangeHistoryManager changeHistoryManager = ComponentAccessor.getChangeHistoryManager()
List changes = changeHistoryManager.getChangeItemsForField(issue, "yourCustomFieldName")
Timestamp currentTime = new Timestamp(System.currentTimeMillis())
int daysSinceLastChange = currentTime - changes[changes.size()-1].getCreated()
return daysSinceLastChange

This'll return the number of days since your custom field last update.

Thank you very much and I needed this input. As I have additional question and I need some guidance for scanning all the issues and putting it in the jql query.

Suggest an answer

Log in or Sign up to answer
TAGS

Atlassian Community Events