I have some requirements to check when user is creating a new issue. So on creation if they select particular component say "ABC", then duedate should be a mandatory field and if they forget to add that then it should throw an error. And the duedate should always be greater than 3 weeks than the today's date, if not it should display an error and until unless it's greater than 3 weeks they can not create issue.
I did see some inbuilt validators for required fields and duedate but it's applying to all component whereas I need only for particular component. Any suggestion/help ?
Thanks in advance!
If you are using Script runner Plugin, This can be achieved by writing a custom behavior.
For example Script runner Behavior:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.user.util.UserUtil
import java.util.Date.*
def componentField= getFieldByName("component/s")
def dueDate= getFieldByName("Due Date")
dueDate.setRequired(false)
dueDateValue = dueDate.getValue() as Date
def today = new Date()
def threeWeekDate= today.plus(21)
if (componentField.getValue() == "ABC") {
dueDate.setRequired(true)
}
if(dueDateValue.before(threeWeekDate)){
dueDate.setError("You must choose a date after 3 weeks from today")
}
Related
I think this can be achieved with behaviors but I am struggling with the code.
I am trying to make "Cascading list 2" mandatory when an option is picked from "Cascading list 1"
Eg:
On "Cascading list 1" if a user picks option "A" then they have to also fill out "Cascading list 2"
If they pick option "B" on "Cascading list 1" then "Cascading list 2" is not required.
This is some of the code I was playing around with:
def fieldA = getFieldByName('BI Reporting & Analytics Request Categories') //this is cascading list 1
def fieldC = getFieldByName('Reporting') //this is the cascading list 2
def fieldAValuesThatTriggerFieldCRequired = ['Reporting'] //this is the option choosen in cascading list 1
def valueA = fieldA.value
def fieldCIsRequired = valueA in fieldAValuesThatTriggerFieldCRequired
fieldC.setRequired(fieldCIsRequired)
Any assistance is appreciated.
Image on JIRA
Thanks.
If my understanding is correct, they are not cascading field.
The request here is that when field A has particular value saying 'aaa', then field B becomes required (mandatory).
This is a typical use case for Jira plugin Adaptavist ScriptRunner behaviours.
But Behaviours is only available for Jira server or data center version. It is not for Jira cloud.
If your Jira is server version, you can refer to below steps and scripts:
go to behaviours settings, if you don't have a behaviour item for
your workflow, please create it. If behaviour has been created,
click into action/edit.
choose the field A and add it.
click Add server-side script, you will see the black inline edit section.
add below code.
import com.onresolve.jira.groovy.user.FieldBehaviours
import com.onresolve.jira.groovy.user.FormField
import groovy.transform.BaseScript
#BaseScript FieldBehaviours fieldBehaviours
FormField field1 = getFieldById(getFieldChanged()) // we need to capture the change in field 1.
FormField pmAuthor = getFieldByName("field2")
if (field1.getValue()) { // to check if field1 has value as the action on field could be a deleting value operation.
if (field2.getValue()=="A") {
field2.setRequired(true)
} else {
field2.setRequired(false)
}
} else { // if the value was deleted, then remove the requirement.
field2.setRequired(false)
}
I'm struggling a little creating a timestamp in a format that I want using a scripted pipeline in Jenkins. Here's my code from the pipeline:
def cal = Calendar.instance
def dateFormat = 'YYYYMMDD-hhmmss'
def timeZone = TimeZone.getTimeZone('CST')
def timeStamp = cal.time.format(dateFormat,timeZone)
println "Timestamp is: ${timeStamp}"
env.BUILD_TIMESTAMP = timeStamp
When I run via Jenkins, I get the following:
org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: unclassified field java.util.GregorianCalendar time
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.unclassifiedField(SandboxInterceptor.java:387)
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:371)
I've seen mention of similar issues with different fields online, but the workaround of adding it to scriptapproval.xml (and restarting Jenkins) doesn't seem to be working.
Anyone have a method of generating a timestamp in a format similar to what I'm trying to do?
I figured out a way around it. I was accessing the field time directly. If I change the call from cal.time to cal.getTime() Jenkins behaves a lot better. I consolidated it into a one-liner, but the functionality's the same:
def timeStamp = Calendar.getInstance().getTime().format('YYYYMMdd-hhmmss',TimeZone.getTimeZone('CST'))
Thanks to those that had a look.
Or use Date() formatted with SimpleDateFormat():
import java.text.SimpleDateFormat
def dateFormat = new SimpleDateFormat("yyyyMMddHHmmss")
def date = new Date()
def timestamp = dateFormat.format(date)
Lets say, i have a "Book" class with field "availableOn"(as shown below).
class Book {
String availableOn;
}
The fields holds values
"All days" or
String representation of a date. For example "13/06/2012"
How can i get all Books that are available within next two days? The below code would throw an exception ("java.util.Date cannot be cast to java.lang.String")
def books = c.list(){
between('availableOn', new Date(), new Date() + 2)
}
PS : Am working on a legacy DB, and so am not suppose to change the schema :(
I think there are 2 problems which the between statement will have:
availableOn cannot be converted to a Date for comparison when its value is All days
Even when availableOn has a date value in it, it is not converted to a Date for the comparison
I'd try something along the lines of this:
def now = new Date()
def books = Book.findAllByAvailableNotEqual("All days").findAll { book ->
Date.parse('dd/MM/yyyy', book.availableOn) > now && Date.parse('dd/MM/yyyy', book.availableOn) < now+2
}
Clearly, this can be done in a nicer way (adding some methods to the domain class for example), but this should illustrate my idea...
I don't have a criteria based solution, but you can try something like this:
Book.executeQuery(
"select book from Book book where book.availableOn = :availableOn or to_date(book.availableOn, :format) between (:startDate, :endDate) ",
[availableOn:"All days", format: "dd/MM/yyyy", startDate: startDate, endDate:endDate])
The problem with my solution is that this query becomes DB dependent. to_date is an Oracle function. You may want to alter this to fit your database
You can use format on a date to get desired string format of it.
new Date().format('dd/MM/yyyy')
And your criteria would get modified to
def books = c.list(){
def todayDateStr = new Date().format('dd/MM/yyyy')
def twoDaysAfterTodayDateStr = (new Date()+2).format('dd/MM/yyyy')
or{
between('availableOn', todayDateStr, twoDaysAfterTodayDateStr)
eq 'availableOn', 'All Days'
}
}
Test if the str comparison works, otherwise other ways has to be used. Sending from phone, excuse my typos.
UPDATE
The above would fail in peculiar cases when dates are like "01/01/2013" and "07/11/2011".
Alternatively, you can use sqlRestriction but in that case it gets tightly coupled with the underlying database. Something like this can be done if Oracle db is used:
def books = c.list(){
def todayDateStr = new Date().format('dd/MM/yyyy')
def twoDaysAfterTodayDateStr = (new Date()+2).format('dd/MM/yyyy')
or{
sqlRestriction "to_date(available_on, 'DD/MM/YYYY') between to_date(todayDateStr, 'DD/MM/YYYY') and to_date(twoDaysAfterTodayDateStr, 'DD/MM/YYYY')"
eq 'availableOn', 'All Days'
}
}
I have a inetgration test case like this :
void testSomething() {
def cardTable = new CardStorage();
cardTable.cardSecurityCode = "something"
def date = new Date()
System.metaClass.static.currentTimeMillis = {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY,11);
cal.set(Calendar.MINUTE,0);
cal.set(Calendar.SECOND,0);
cal.set(Calendar.MILLISECOND,0);
return date.getTime()
}
assert cardTable.save(flush:true) //this works.
}
The line : cardTable.save(flush:true) is working. It asserts true. But the problem is that the dateCreated field is still the same as (new Date()). I wonder,how this can happen. Because I have coded the currentTimeMillis method as per my req. But still grails doesn't pick it up. But I'm sure that my new currentTimeMillis is working (because making error in it, results in a compilation error).
Where I'm missing? How can I disable the timeStamp feature for testing alone?
Thanks in advance.
Java code in core library in new Date() does not and will never pick up your changes in Groovy metaclass code.
I can recommend using joda-time (make dateCreated a DateTime) and setting current time by its means.
Even better way is not to tie your code to the current time, but to pass the time into your class from outside.
Dont use 'dateCreated', grails will automatically fill it in for you.
I have a database table TableA, which has a column 'theDate' for which the datatype in the database is DATE.
When I save a java.util.Date to 'theDate' through GORM it appears to save just the date value when I look at the data in the table by just executing select * from TableA.
However, when I run a query such as:
select * from TableA where theDate = :myDate
No results are found, but if I run something like;
select * from TableA where theDate <= :myDate
I do get results.
So it's like the Time is relevant.
My question is how do I save a Date and query for a Date ignoring the Time completely and just matching on an exact Date only?
Thanks.
note: I have also tried using sql.Date and util.Calendar but to no success.
clearTime()
You can use clearTime() before saving and before comparing to zero out the time fields:
// zero the time when saving
new MyDomain(theDate: new Date().clearTime()).save()
// zero the target time before comparing
def now = new Date().clearTime()
MyDomain.findAll('SELECT * FROM MyDomain WHERE theDate = :myDate', [myDate: now])
joda-time plugin
An alternative would be to install the joda-time plugin and use the LocalDate type (which only holds date information, no times) instead of Date. For what it's worth, I don't think I've worked on a project with dates without using the Joda plugin. It's completely worth it.
If you have date saved without clearing you could retrieve it using range, as Jordan H. wrote but in more simple way.
def getResults(Date date) {
def from = date.clearTime()
def to = from + 1
def results = MyDomain.findAll("from MyDomain where dateCreated between :start and :stop" ,[start:from,stop:to])
}
Your question may be a duplicate. See Convert datetime in to date. But if anyone has more recent information, that would be great.
If that doesn't help, you can hack it the way I might, with a BETWEEN restriction, e.g.
def today = new Date()
def ymdFmt = new java.text.SimpleDateFormat("yyyy-MM-dd")
def dateYmd = ymdFmt.format(today)
def dateTimeFormat = new java.text.SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
def startDate = dateTimeFormat.parse("${dateYmd} 00:00:00");
def endDate = dateTimeFormat.parse("${dateYmd} 23:59:59");
MyDomain.findAll("from MyDomain where dateCreated between ? and ?", [startDate, endDate])
It's definitely not pretty, but it may get you where you're going.
I figured it out.
I used DateGroovyMethods.clearTime to clear the time value before saving.
You can use the DB type date not datetime , in the filed type