import org.codehaus.groovy.runtime.TimeCategory // the above will be deprecated and replaced by: groovy.time.TimeCategory class TaskRecurringSchedule { Task lastGeneratedSubTask Period recurPeriod Period taskDurationPeriod Integer recurEvery = 1 Integer taskDuration = 0 Integer generateAhead = 1 Integer subTasksGenerated = 0 Integer maxSubTasks = 0 Date nextGenerationDate = new Date() Date nextTargetStartDate = new Date()+1 Date nextTargetCompletionDate = new Date() boolean enabled = true boolean useTargetCompletionDate = false // static hasMany = [] static belongsTo = [task: Task] static constraints = { recurEvery(min:1, max:365) taskDuration(min:0, max:365) generateAhead(min:0, max:62) lastGeneratedSubTask(nullable:true) } String toString() { "Recur every ${recurEvery} ${recurPeriod}" } // Events do not fire/pass before validation, since they are called during flushing. // Defaults set above to pass validation. def beforeInsert = { setNextGenerationDate() setNextTargetCompletionDate() } public void setNextTargetStartDate() { switch (recurPeriod.period) { case "Day(s)": use(TimeCategory) { nextTargetStartDate = nextTargetStartDate + recurEvery.days } break case "Week(s)": use(TimeCategory) { nextTargetStartDate = nextTargetStartDate + recurEvery.weeks } break case "Month(s)": use(TimeCategory) { nextTargetStartDate = nextTargetStartDate + recurEvery.months } break case "Year(s)": use(TimeCategory) { nextTargetStartDate = nextTargetStartDate + recurEvery.years } break default: log.error "No case for recurPeriod.period: ${recurPeriod.period}" break } } public void setNextGenerationDate() { use(TimeCategory) { nextGenerationDate = nextTargetStartDate - generateAhead.days } def now = new Date() if( nextGenerationDate < now) {nextGenerationDate = now} } public void setNextTargetCompletionDate() { 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: log.error "No case for taskDurationPeriod.period: ${taskDurationPeriod.period}" break } } }