Index: /trunk/grails-app/conf/BootStrap.groovy
===================================================================
--- /trunk/grails-app/conf/BootStrap.groovy	(revision 135)
+++ /trunk/grails-app/conf/BootStrap.groovy	(revision 136)
@@ -32,4 +32,5 @@
     {
         println "BootStrapping demo data..."
+        3.times{println it}
 
 /***********************
@@ -415,6 +416,10 @@
         taskRecurringScheduleInstance = new TaskRecurringSchedule(task: Task.get(1),
                                                                                                     recurEvery: 1,
-                                                                                                    period: Period.get(1),
-                                                                                                    nextDueDate: new Date())
+                                                                                                    recurPeriod: Period.get(1),
+                                                                                                    startDate: new Date(),
+                                                                                                    generateAhead: 1,
+                                                                                                    generateAheadPeriod: Period.get(1),
+                                                                                                    taskDuration: 1,
+                                                                                                    taskDurationPeriod: Period.get(1))
         BootStrapSaveAndTest(taskRecurringScheduleInstance)
 
@@ -422,6 +427,10 @@
         taskRecurringScheduleInstance = new TaskRecurringSchedule(task: Task.get(2),
                                                                                                     recurEvery: 1,
-                                                                                                    period: Period.get(1),
-                                                                                                    nextDueDate: new Date())
+                                                                                                    recurPeriod: Period.get(1),
+                                                                                                    startDate: new Date(),
+                                                                                                    generateAhead: 1,
+                                                                                                    generateAheadPeriod: Period.get(1),
+                                                                                                    taskDuration: 1,
+                                                                                                    taskDurationPeriod: Period.get(1))
         BootStrapSaveAndTest(taskRecurringScheduleInstance)
 
Index: /trunk/grails-app/controllers/PersonController.groovy
===================================================================
--- /trunk/grails-app/controllers/PersonController.groovy	(revision 135)
+++ /trunk/grails-app/controllers/PersonController.groovy	(revision 136)
@@ -39,5 +39,5 @@
 	/**
 	 * Person delete action. Before removing an existing person,
-	 * he should be removed from those authorities which he is involved.
+	 * they should be removed from those authorities which they are involved.
 	 */
 	def delete = {
Index: /trunk/grails-app/controllers/TaskRecurringScheduleDetailedController.groovy
===================================================================
--- /trunk/grails-app/controllers/TaskRecurringScheduleDetailedController.groovy	(revision 135)
+++ /trunk/grails-app/controllers/TaskRecurringScheduleDetailedController.groovy	(revision 136)
@@ -1,3 +1,4 @@
 import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+import org.codehaus.groovy.runtime.TimeCategory
 
 class TaskRecurringScheduleDetailedController extends BaseController {
@@ -66,5 +67,7 @@
                 }
             }
-            taskRecurringScheduleInstance.properties = params
+//             taskRecurringScheduleInstance.properties = params
+            setUpdateProperties()
+                    
             if(!taskRecurringScheduleInstance.hasErrors() && taskRecurringScheduleInstance.save()) {
                 flash.message = "TaskRecurringSchedule ${params.id} updated"
@@ -104,8 +107,4 @@
 		else {
 			
-			taskRecurringScheduleInstance.nextDueDate = new Date()
-				
-// 			taskRecurringScheduleInstance.nextDueDate = calculateNextDueDate(new Date()) 
-			
 			if(!taskRecurringScheduleInstance.hasErrors() && taskRecurringScheduleInstance.save()) {
 				
@@ -127,22 +126,47 @@
 
     }
-	
-// 	private Date calculateNextDueDate(nextDue) {
-// // 		def now = new Date()
-// // 		def calculatedDays = new Integer()
-// // 		def nextDue = new Date()
-// 				
-// // 		switch (period) {
-// // 			case "Day(s)":
-// // 				calculatedDays = period
-// // 				nextDue = now + calculatedDays
-// // 			case "Week(s)":
-// // 				calculatedDays = period * 7
-// // 				nextDue = now + calculatedDays
-// // // 			default:
-// // 		}
-// 		nextDue = nextDue + 1
-// 		return nextDue
-// 	}
-	
+                
+    private setUpdateProperties() {
+        def originalStartDate = taskRecurringScheduleInstance.startDate
+        
+        if(taskRecurringScheduleInstance.startDate == params.startDate) {
+            taskRecurringScheduleInstance.properties = params
+        }
+        else {
+            taskRecurringScheduleInstance.properties = params
+            taskRecurringScheduleInstance.nextTargetStartDate = params.startDate
+        }
+        
+    }
+
+/*    
+    private Date calculateNextDueDate(recurEvery, period, startDate) {
+        def nextDue = new Date()
+        
+        switch (period) {
+            case "Day(s)":
+                use(TimeCategory) {
+                    nextDue = startDate + recurEvery.days
+                }
+                return nextDue
+            case "Week(s)":
+                use(TimeCategory) {
+                    nextDue = startDate + recurEvery.weeks
+                }
+                return nextDue
+            case "Month(s)":
+                use(TimeCategory) {
+                    nextDue = startDate + recurEvery.months
+                }
+                return nextDue
+            case "Year(s)":
+                use(TimeCategory) {
+                    nextDue = startDate + recurEvery.years
+                }
+                return nextDue
+            default:
+                return nextDue
+        }
+        
+    }*/
 }
Index: /trunk/grails-app/domain/Period.groovy
===================================================================
--- /trunk/grails-app/domain/Period.groovy	(revision 135)
+++ /trunk/grails-app/domain/Period.groovy	(revision 136)
@@ -5,7 +5,9 @@
 
     static hasMany = [taskRecurringSchedules: TaskRecurringSchedule]
-// 
+    
+    static mappedBy = [taskRecurringSchedules:"recurPeriod"]
+
 //     static belongsTo = []
-// 
+
 //     static constraints = {
 // 
Index: /trunk/grails-app/domain/TaskRecurringSchedule.groovy
===================================================================
--- /trunk/grails-app/domain/TaskRecurringSchedule.groovy	(revision 135)
+++ /trunk/grails-app/domain/TaskRecurringSchedule.groovy	(revision 136)
@@ -1,11 +1,19 @@
+import org.codehaus.groovy.runtime.TimeCategory
+
 class TaskRecurringSchedule {
 
     Task lastGeneratedSubTask
-    Period period
+    Period recurPeriod
+    Period generateAheadPeriod
+    Period taskDurationPeriod
 
     Integer recurEvery = 1
+    Integer taskDuration = 0
+    Integer generateAhead = 1
     Date startDate = new Date()
     Date lastGeneratedDate
-    Date nextDueDate
+    Date nextTargetStartDate = new Date()
+    Date nextTargetCompletionDate = new Date()
+    Date nextGenerationDate = new Date()
     boolean isEnabled = true
 
@@ -15,4 +23,8 @@
 
     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)
@@ -20,6 +32,70 @@
 
     String toString() {
-        "Recur every ${recurEvery} ${period}"
+        "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
+        }
+        
+    }
+
 }
 
