import org.codehaus.groovy.runtime.TimeCategory class TaskRecurringSchedule { Task lastGeneratedSubTask Period recurPeriod Period generateAheadPeriod Period taskDurationPeriod Integer recurEvery = 1 Integer taskDuration = 0 Integer generateAhead = 1 Date startDate = new Date() Date lastGeneratedDate Date nextTargetStartDate = new Date() Date nextTargetCompletionDate = new Date() Date nextGenerationDate = new Date() boolean isEnabled = true // static hasMany = [] static belongsTo = [task: Task] static constraints = { // startDate(validator: {return (it > new Date())}) recurEvery(min:0, max:365) taskDuration(min:0, max:365) generateAhead(min:0, max:365) lastGeneratedDate(blank:true, nullable:true) lastGeneratedSubTask(blank:true, nullable:true) } String toString() { "Recur every ${recurEvery} ${recurPeriod}" } //As of Grails 1.1 this does not fire/pass before validation. //But setting defaults above and placing this code here in the hope that this will be fixed in future versions. def beforeInsert = { def now = new Date() nextTargetStartDate = startDate //nextGenerationDate switch (generateAheadPeriod.period) { case "Day(s)": use(TimeCategory) { nextGenerationDate = nextTargetStartDate - generateAhead.days } break case "Week(s)": use(TimeCategory) { nextGenerationDate = nextTargetStartDate - generateAhead.weeks } break case "Month(s)": use(TimeCategory) { nextGenerationDate = nextTargetStartDate - generateAhead.months } break case "Year(s)": use(TimeCategory) { nextGenerationDate = nextTargetStartDate - generateAhead.years } break default: break } if( nextGenerationDate < now) {nextGenerationDate = now} //nextTargetCompletionDate switch (taskDurationPeriod.period) { case "Day(s)": use(TimeCategory) { nextTargetCompletionDate = nextTargetStartDate + taskDuration.days } break case "Week(s)": use(TimeCategory) { nextTargetCompletionDate = nextTargetStartDate + taskDuration.weeks } break case "Month(s)": use(TimeCategory) { nextTargetCompletionDate = nextTargetStartDate + taskDuration.months } break case "Year(s)": use(TimeCategory) { nextTargetCompletionDate = nextTargetStartDate + taskDuration.years } break default: break } } }