Jira Misc Custom Fields

This page describes advanced Jira and eazyBI integration. If you need help with this please contact eazyBI support.

If you would like to import in eazyBI additional Jira issue fields which are not supported by standard eazyBI functionality then you can install and use Jira Misc Custom Fields plugin which allows definition of additional calculated Jira custom fields which then can be imported in eazyBI.

On this page:

Define additional calculated custom field

Please read Jira Misc Custom Fields documentation to learn more about defining additional Calculated Number FieldCalculated Text FieldCalculated Date/Time FieldTransition Date/Time FieldTransition Caller Field.

As example let's define additional "Fix versions" calculated text field which will return comma separated list of current fix versions for the issue.

Add new custom field and select Calculated Text Field as a type:

Enter "fix versions" as Field Name and in description enter formula for this calculated field:

<!-- @@Formula:
import org.apache.commons.lang.StringUtils;
StringUtils.join(issue.get("fixVersions"), ",");
-->

Please see examples of simple calculated text formulas as well as read more about BeanShell syntax which is very close to Java syntax.

After defining formula select for which issue types and projects this custom field will be used. While debugging the formula add it to issue Default Screen, later you can remove it from this screen if you do not need to show it for users.

After creating new custom field you should re-index Jira as suggested.

Visit issue pages and see if calculated text field is returning expected value. If you do not see custom field on Default Screen it may be caused by exception in formula. Please see Jira log file (log/atlassian-jira.log in home directory or console log) if there are any exceptions logged.

Add calculated custom field to eazyBI advanced settings

If you will define Calculated Date/Time Field or Transition Date/Time Field then they will be recognized by eazyBI as additional custom fields and you will be able to select them in Source Data tab in application import custom field selection.

If you defined Calculated Number Field or Calculated Text Field then you will need to add this field to eazyBI advanced settings. In our "Fix versions" example at first you need to find out custom field ID. If you go to Edit Custom Field Details screen then in URL you will see

.../secure/admin/EditCustomField!default.jspa?id=NNNNN

where NNNNN is custom field ID. Then in eazyBI advanced settings add

[jira.customfield_NNNNN]
data_type = "string"

where NNNNN is replaced by corresponding custom field ID.

Import custom field into eazyBI

After Misc custom field is defined and eazyBI advanced settings are updated, you should see this "Fix versions" custom field in the Source Data tab in application import custom field selection. Select the Import as property option for this custom field. After import, you should see additional "Issue Fix versions" calculated measure in Measures / Calculated members / Issue properties section and you can use it in reports where you have Issue dimension on rows and expanded to detailed issues. And also you can access this custom field with Issue.CurrentMember.get("Fix versions") in your other eazyBI calculation formulas.

Examples

Here are other examples of Misc Custom Field formulas that could be useful for import into eazyBI.

Creator

This Custom Text field formula return the creator of an Issue in the calculated text field.

<!-- @@Formula:
creator = issue.getIssueObject().getCreator();
if (creator == null) return null;
creator.getDisplayName();
-->

To import this field as a dimension, add the following advanced settings (by replacing NNNNN with actual field ID) and then importing this field via eazyBI import settings as dimension.

[jira.customfield_NNNNN]
data_type = "string"
dimension = true

Description

This Custom Text field formula return the Description of an Issue in the calculated text field.

<!-- @@Formula:
description = issue.getIssueObject().description;
if (description == null) return null;
description;
-->

To import this calculated custom field as a property of an issue, add the following advanced settings (by replacing NNNNN with actual field ID from ) 

[jira.customfield_NNNNN]
data_type = "text"

Next, you could select this field via eazyBI import settings to import as the property of an issue.

Now you could find a new measure "Issue Description" in "Measures" dimension that will show the description of an issue for "Issue" dimension (issue level) members.

Environment

This Custom Text field formula return the Environment of an Issue in the calculated text field.

<!-- @@Formula:
environment = issue.getIssueObject().environment;
if (environment == null) return null;
environment;
-->

To import this calculated custom field as a property of an issue, add the following advanced settings (by replacing NNNNN with actual field ID from ) 

[jira.customfield_NNNNN]
data_type = "text"

Next, you could select this field via eazyBI import settings to import as the property of an issue.

Now you could find a new measure "Issue Environment" in "Measures" dimension that will show the description of an issue for "Issue" dimension (issue level) members. 

Starting from the eazyBI version 4.1, you can use issue link import instead of the example below using Misc calculated custom field.

This Custom Text Field formula gets linked issues that are not in Resolved or Closed status with "is blocked by" inward link and returns linked issue keys separated by a comma.

<!-- @@Formula:
import com.atlassian.jira.component.ComponentAccessor;
import org.apache.commons.lang.StringUtils;
BlockingKeys = new ArrayList();
inwardLinks = ComponentAccessor.getIssueLinkManager().getInwardLinks(issue.getIssueObject().getId());
for (issueLink : inwardLinks.iterator()) {
  if (issueLink.getIssueLinkType().getInward().equals("is blocked by")
         && ! issueLink.getSourceObject().getStatusObject().getName().equals("Resolved")
         && ! issueLink.getSourceObject().getStatusObject().getName().equals("Closed")
    ) { BlockingKeys.add(issueLink.getSourceObject().getKey());
  }
}
if (BlockingKeys.isEmpty()) return null;
StringUtils.join(BlockingKeys, ",");
-->

To add this field import as dimension, add the following advanced settings 

[jira.customfield_NNNNN]
data_type = "string"
dimension = true
multiple_values = true
check_calculated_value = true
split_by = ","

where NNNNN is replaced by corresponding custom field ID.

Previous due dates

This Custom Text Field formula will get all previous due dates from issue changelog and will return them as comma separated list with dates in YYYY-MM-DD format.

<!-- @@Formula:
import org.apache.commons.lang.StringUtils;
import com.atlassian.jira.component.ComponentAccessor;
dateStrings = new ArrayList();
items = ComponentAccessor.getChangeHistoryManager().getChangeItemsForField(
  issue.getIssueObject(), "duedate"
);
for (item : items) {
  from = item.getFrom();
  if (from != null) {
    dateStrings.add(from);
  }
}
if (dateStrings.isEmpty()) return null;
StringUtils.join(dateStrings, ",");
-->

You can create similar calculated custom text fields for any other previous field values by replacing "duedate" with different field name.

Project category

This Custom Text Field formula will get issue project category name.

<!-- @@Formula:
category = issue.getIssueObject().getProjectObject().getProjectCategoryObject();
if (category == null) return null;
category.getName();
-->

To import Category and Project in multi-level eazyBI dimension, add following  Misc Calculated Text field that will return both category and project name 

<!-- @@Formula:
String categoryName;
category = issue.getIssueObject().getProjectObject().getProjectCategoryObject();
if (category == null) {
  categoryName = "(none)";
} else {
  categoryName = category.getName();
}
categoryName + "|" + issue.getIssueObject().getProjectObject().getName();
-->

and then import it as a two level dimension hierarchy with following eazyBI advanced options 

[jira.customfield_NNNNN]
data_type = "string"
dimension = true
levels = ["Category", "Project"]
split_by = "|"

Parent issue type

This Custom Text Field formula will get parent issue type for sub-tasks.

<!-- @@Formula:
parent = issue.getIssueObject().getParentObject();
if (parent == null) return null;
parent.getIssueTypeObject().getName();
-->

Parent issue labels

This Custom Text Field formula will get parent issue labels (comma separated string) for sub-tasks.

<!-- @@Formula:
import org.apache.commons.lang.StringUtils;
parent = issue.getIssueObject().getParentObject();
if (parent == null) return null;
labelStrings = new ArrayList();
for (label : parent.getLabels()) {
  labelStrings.add(label.getLabel());
}
if (labelStrings.isEmpty()) return null;
StringUtils.join(labelStrings, ",");
-->

If you would like to import this as multi value custom dimension in eazyBI then in advanced settings specify

[jira.customfield_NNNNN]
data_type = "string"
dimension = true
multiple_values = true
check_calculated_value = true
split_by = ","

Numeric measure with multiple dates

This is example how to build custom field with formula which returns multiple numeric measure values for one issue but split by several dates.

This Daily estimates example formula checks if issue has Original estimated time and due date. If yes then it will distribute estimated hours starting from due date and backwards and using no more than 8 hours per day. For example, if issue had a due date March 14 and had 36.5 estimated hours then calculated field will have the following value (each date on a separate line and first value is date in yyyy-mm-dd format, then comma and then number of hours):

2014-03-14,8
2014-03-13,8
2014-03-12,8
2014-03-11,8
2014-03-10,4.5

This is Custom Text Field formula for Daily estimates custom field that should be used for this example:

<!-- @@Formula:
import org.apache.commons.lang.StringUtils;
import java.text.SimpleDateFormat;
import java.util.Calendar;

dateStrings = new ArrayList();
dateFormat = new SimpleDateFormat("yyyy-MM-dd");

dueDate = issue.get("duedate");
estimate = issue.get("timeoriginalestimate");

if (dueDate != null && estimate != null && estimate > 0) {
  calendar = Calendar.getInstance();
  calendar.setTime(dueDate);
  hours = estimate / 3600.0;

  while (hours > 0) {
    dateHours = hours > 8 ? 8 : hours;
    dateStrings.add(
      dateFormat.format(calendar.getTime()) + "," +
      String.valueOf(dateHours)
    );
    hours -= dateHours;
    calendar.add(Calendar.DATE, -1);
  }
}

if (dateStrings.isEmpty()) return null;
StringUtils.join(dateStrings, "\n");
-->

In advanced settings add the following settings for this custom field:

[jira.customfield_NNNNN]
data_type = "decimal"
measure = true
multiple_dates = true

In eazyBI Source Data tab import this custom field both as measure and as property. 

Original estimated hours history

This example is how to import changes of field "Original estimated hours history" in eazyBI as a separate measure

In order to achieve that, there should be new text type of MISC calculated custom field created.

This is formula for Original estimated hours history custom field that you could put in field description

<!-- @@Formula:
import org.apache.commons.lang.StringUtils;
import com.atlassian.jira.component.ComponentAccessor;
import java.text.SimpleDateFormat;

dateFormat = new SimpleDateFormat("yyyy-MM-dd");
values = new ArrayList();
items = ComponentAccessor.getChangeHistoryManager().getChangeItemsForField(
  issue.getIssueObject(), "timeoriginalestimate"
);
for (item : items) {
  to = item.getTo();
  if (to != null) {
    toNumber = Float.parseFloat(to)/3600;
    values.add(dateFormat.format(item.getCreated()) + "," +toNumber. toString());
  }
}
if (values.isEmpty()) return null;
StringUtils.join(values, "\n");
-->

That should retrieve all the changes for field "Original estimated hours" and return them in string

 After that, in advanced settings add the following settings for this custom field where you place your actual field ID instead of NNNNN.

[jira.customfield_NNNNN]
data_type = "decimal"
measure = true
multiple_dimensions = ["Time"]
split_by = ","

Then In eazyBI Source Data tab import this custom field as measure and use it together with Time Dimension in your eazyBI reports.