Can I add story points to a custom field?

I want to use t-shirt sizes instead of standard story points. Obviously I could create a custom field, but that would not map to reporting. Is there currently a way to resolve this?

7 answers

This widget could not be displayed.

Hello dear reader,


You might try to use our add-on for interactive estimations (via Planning Poker technique): Agile Poker Enterprise for JIRA. It allows you to do the estimating over T-shirt sizes (S, M, L, etc) and map the result to the numerical values (2, 3, 5, etc) while saving to the issue.


Disclaimer: I'm one of the developers behind that add-on, but nonetheless I thought that people looking here might be interested in knowing about that possibility. Feel free to ping me at support@spartez.com if you have any question.


Regards,
Piotr Stefaniak / Spartez Developer

This widget could not be displayed.
Steven Behnke Community Champion May 05, 2015

I am planning doing this very same thing for our instance @Kathleen Shafer. I am planning on using T-Shirt sizes as well! My thoughts are like this:

  • I want to use the default Story Points field at the end of the day
    I do not want any strangeness with JIRA Agile
  • The estimation should be a single-select list with Small (1), Medium(2), Large(4), Extra Large(8)
  • I think here that it would be best to keep it simple. I don't want to code a whole bunch of logic, I just want to streamline the Story create process.

Edits and additions

Hello again @Kathleen Shafer! I have the post-function script working fine, and I think this is good enough for use. I am looking into the Scripted Field option still as well, this just isn't taking a priority. I hope you understand.

System Requirements

This post-function is only available to users of the Script Runner add-on, only available on JIRA Server. The Script Runner add-on lets us run Groovy scripts, for instance, as a post-function. We will leverage this to fulfil the software requirements.

Software Requirements

As a user, I should be able to set Story Points on issue creation using a select-list with T-Shirt estimation-sizing.

Set Up

  1. Get the Custom Field IDs of both the Story Points and T-Shirt Size custom fields
  2. Modify the below Groovy code with the Custom Field IDs that you just obtained
  3. Set field T-Shirt Size on your Create Screen
  4. Set field Story Points on your Edit and View Screens
  5. Add the Groovy code as an inline script, to be attached as a post-function of the Create transition

Use

  1. Open the Create Issue dialog
  2. Choose an option from T-Shirt Size
  3. Press Create
  4. Note the cooresponding value in the Story Points field
// Written by Steve Behnke, BlackPearl PDM
//
// The goal of this post-function is to simplify input of Story Points. Story Points normally, being a number field, allows people to enter any value
// However, without training or experience, these values vary wildly and may not be useful for reporting purposes until some time passes
//
// Using a 't-shirt size' select-list to populate the existing story points field let's us accomplish this in a flexible manner that really doesn't change the actual behavior of the story points field at all. We're just pre-populating it. 
//
// This is as opposed to a scripted field of sorts, which could 'map' the values directly with no room for flexibility.
import com.atlassian.jira.ComponentManager;
import com.atlassian.jira.issue.CustomFieldManager;
import com.atlassian.jira.issue.fields.CustomField;
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.issue.util.IssueChangeHolder
import com.atlassian.jira.issue.ModifiedValue
 
// set up logging
log.setLevel(org.apache.log4j.Level.INFO)

log.info "Executing T-Shirt size > Story Points conversion!"
// gets a reference to the IssueManager and CustomFieldManager manager classes

IssueManager issueManager = ComponentManager.getInstance().getIssueManager();
CustomFieldManager customFieldManager = ComponentManager.getInstance().getCustomFieldManager();

// gets a reference to the custom field objects
// note, that since I reference the fields by internal ID these will need to be modified to work correctly
CustomField tshirtsizeField = customFieldManager.getCustomFieldObject( "customfield_12214" );
CustomField storypointsField = customFieldManager.getCustomFieldObject( "customfield_10004" );

log.debug "get tshirt value"
Object tshirtValue = issue.getCustomFieldValue(tshirtsizeField);
// introduce the changeHolder element, in order to update fields
IssueChangeHolder changeHolder = new DefaultIssueChangeHolder();
 
// create values as doubles, appropriate for "JIRA Number Fields;" Story Points is this type of field
//
// T-Shirt size = Small
Double pSmall = 1
//
// T-Shirt size = Medium
Double pMedium = 4
//
// T-Shirt size = Large
Double pLarge = 9
//
// T-Shirt size = X-Large
Double pXLarge = 16
 
// retrieves the custom field value object from the issue and sets the story point value
if(tshirtValue.toString() == "Small") {
	storypointsField.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(storypointsField), pSmall), changeHolder);
	log.debug "size = Small, value =" + pSmall.toString()
} 
else if(tshirtValue.toString() == "Medium") {
	storypointsField.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(storypointsField), pMedium), changeHolder);
	log.debug "size = Medium, value =" + pMedium.toString()
}
else if(tshirtValue.toString() == "Large") {
	storypointsField.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(storypointsField), pLarge), changeHolder);
	log.debug "size = Large, value =" + pLarge.toString()
} 
else if(tshirtValue.toString() == "X-Large") {
	storypointsField.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(storypointsField), pXLarge), changeHolder);
	log.debug "size = X-Large, value =" + pXLarge.toString()
} 
else {
// do nothing
log.debug "Size was set to null; not setting story points."
};

Ahh...very cool. I think that would work! Would you mind sharing your script when you are finished?

Steven Behnke Community Champion May 05, 2015

Totally would. Let me think about my requirements a bit more. I will save this and get back to you. :)

Steven Behnke Community Champion Jun 07, 2015

@Kathleen Shafer, @Kathleen Shafer, just bumping so you see! smile

This widget could not be displayed.

This is fun and unusual. Since Story points are meant to add up in reporting, like in a Velocity chart, how would that help to put anything but numbers in there? What report exactly would make sense with t-shirt sized instead of numbers? If you explain further what you need to figure out with the reports, we might be able to suggest something.

This widget could not be displayed.
Steven Behnke Community Champion May 05, 2015

Kathleen, are you on JIRA Cloud or JIRA server? If you are on JIRA cloud scriptrunner isn't an option.

This widget could not be displayed.

Yes, it is, somehow. use the standard story points CF & JJUPIN + JJUPIN Agile; on the view screens, you can call a LiveFields lfSet replacing the number with S,M,L,XL, XXL, etc.

However, on the edit screens, I doubt it will work. That value needs to be posted, and it has to be numeric. If you do not mind editing numbers but seeing it as you want, you have this (partial) solution.

This widget could not be displayed.

I am on JIRA server. Yes interesting point on the reporting. So basically on the backend the sizes would map to a number (XS=1, S=2 and so on) so the reporting would pull from numbers. The reporting would still be viewed with numbers, since you couldn't really translate the numbers back into sizes (or maybe someone would like to see that).

This widget could not be displayed.

Interesting approach - might use the exact same script to transfer the T-Shirt sizes in a new custom field to story points. I changed the script slightly and used the event variable using it as a custom script listener in "Script Runner - Script Listeners" for the following Events:

  • Issue Created
  • Issue Updated
// Written by Steve Behnke, BlackPearl PDM, modified by MBe
// Source: https://community.atlassian.com/t5/JIRA-questions/Can-I-add-story-points-to-a-custom-field/qaq-p/25143
//
// The goal of this post-function is to simplify input of Story Points. Story Points normally, being a number field, allows people to enter any value
// However, without training or experience, these values vary wildly and may not be useful for reporting purposes until some time passes
//
// Using a 'T-Shirt size' select-list to populate the existing story points field let's us accomplish this in a flexible manner that really doesn't change the actual behavior of the story points field at all. We're just pre-populating it. 
//
// This is as opposed to a scripted field of sorts, which could 'map' the values directly with no room for flexibility.
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.fields.CustomField;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.issue.util.IssueChangeHolder
import com.atlassian.jira.issue.ModifiedValue
 
// set up logging
log.setLevel(org.apache.log4j.Level.INFO)

log.info "Executing T-Shirt size > Story Points conversion!"

// gets a reference to the custom field objects
// note, that since I reference the fields by internal ID these will need to be modified to work correctly
CustomField tshirtsizeField =  ComponentAccessor.getCustomFieldManager().getCustomFieldObject(10101L);
CustomField storypointsField = ComponentAccessor.getCustomFieldManager().getCustomFieldObject(10102L);

log.debug "get T-Shirt value"
// from an event we first need to get the issue
Issue issue = event.getIssue();
Object tshirtValue = issue.getCustomFieldValue(tshirtsizeField);
// introduce the changeHolder element, in order to update fields
IssueChangeHolder changeHolder = new DefaultIssueChangeHolder();
 
// create values as doubles, appropriate for "JIRA Number Fields;" Story Points is this type of field
//
// T-Shirt size = X-Small
Double pXSmall = 1

// T-Shirt size = Small
Double pSmall = 3
//
// T-Shirt size = Medium
Double pMedium = 5
//
// T-Shirt size = Large
Double pLarge = 8
//
// T-Shirt size = X-Large
Double pXLarge = 13
//
// T-Shirt size = XX-Large
Double pXXLarge = 20
 
// retrieves the custom field value object from the issue and sets the story point value
if(tshirtValue.toString() == "πŸ‘• XS") {
	storypointsField.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(storypointsField), pXSmall), changeHolder);
	log.debug "size = X-Small, value =" + pXSmall.toString()
} 
else if(tshirtValue.toString() == "πŸ‘• S") {
	storypointsField.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(storypointsField), pSmall), changeHolder);
	log.debug "size = Small, value =" + pSmall.toString()
} 
else if(tshirtValue.toString() == "πŸ‘• M") {
	storypointsField.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(storypointsField), pMedium), changeHolder);
	log.debug "size = Medium, value =" + pMedium.toString()
}
else if(tshirtValue.toString() == "πŸ‘• L") {
	storypointsField.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(storypointsField), pLarge), changeHolder);
	log.debug "size = Large, value =" + pLarge.toString()
} 
else if(tshirtValue.toString() == "πŸ‘• XL") {
	storypointsField.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(storypointsField), pXLarge), changeHolder);
	log.debug "size = X-Large, value =" + pXLarge.toString()
} 
else if(tshirtValue.toString() == "πŸ‘• XXL") {
	storypointsField.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(storypointsField), pXXLarge), changeHolder);
	log.debug "size = XX-Large, value =" + pXXLarge.toString()
} 
else {
	// do nothing - just log the provided value for debugging
	log.debug "Size was set to null; not setting story points. provided value was: " + tshirtValue.toString()
};

Changed Story-Points were not updated on the Backlog correctly. Had to reindex the issue using the issueIndexingService.reIndex(issueManager.getIssueObject(issue.id)); call to fix that behavior.

Suggest an answer

Log in or Sign up to answer
Atlassian Summit 2018

Meet the community IRL

Atlassian Summit is an excellent opportunity for in-person support, training, and networking.

Learn more
Community showcase
Posted Wednesday in New to Jira

Are you planning to trial, or are currently trialling Jira Software? - We want to talk to you!

Hello! I'm Rayen, a product manager at Atlassian. My team and I are working hard to improve the trial experience for Jira Software Cloud. We are interested in   talking to 20 people planning t...

224 views 3 0
Join discussion

Atlassian User Groups

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

Find a group

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

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you