Index: trunk/grails-app/services/TaskRecurringScheduleService.groovy
===================================================================
--- trunk/grails-app/services/TaskRecurringScheduleService.groovy	(revision 441)
+++ trunk/grails-app/services/TaskRecurringScheduleService.groovy	(revision 445)
@@ -15,6 +15,4 @@
     def generateAll() {
 
-        def taskRecurringScheduleList = TaskRecurringSchedule.findAllByEnabled(true)
-
         // Prevent errors if base data has not yet been created.
         if(!appConfigService.exists("baseDataCreated")) {
@@ -26,32 +24,77 @@
         }
 
-        taskRecurringScheduleList.each() {
+        def p = [:]
+        def targetCompletionDate
+        def nextTargetCompletionDate
+        def tomorrow = dateUtilService.tomorrow
+
+        def taskRecurringScheduleList = TaskRecurringSchedule.findAllByEnabled(true)
+
+        // Stop generation if max reached.
+        def maxSubTasksReached = {
+            if( (it.maxSubTasks > 0) && (it.subTasksGenerated >= it.maxSubTasks) ) {
+                it.enabled = false
+                return true
+            }
+            return false
+        }
+
+        // Stop generation by targetCompletionDate.
+        def targetCompletionDateReached = {
+            if( it.useTargetCompletionDate) {
+                targetCompletionDate = dateUtilService.getMidnight(it.task.targetCompletionDate)
+                nextTargetCompletionDate = dateUtilService.getMidnight(it.nextTargetCompletionDate)
+                if(nextTargetCompletionDate > targetCompletionDate) {
+                    it.enabled = false
+                    return true
+                }
+            }
+            return false
+        }
+
+        // Main loop.
+        for(it in taskRecurringScheduleList) {
+
+            if(maxSubTasksReached(it))
+                continue
+
+            if(targetCompletionDateReached(it))
+                continue
 
             if (dateUtilService.tomorrow > it.nextGenerationDate) {
-                    def p = [:]
+                p = [:]
 
-                    // Build the required params.
-                    p.targetStartDate = it.nextTargetStartDate
-                    p.targetCompletionDate = it.nextTargetCompletionDate
-                    if(it.task.taskProcedure) p.taskProcedure = it.task.taskProcedure
-                    if(it.task.assignedGroups) p.assignedGroups = new ArrayList(it.task.assignedGroups)
-                    if(it.task.assignedPersons) p.assignedPersons = new ArrayList(it.task.assignedPersons)
+                // Build the subTask params.
+                p.targetStartDate = it.nextTargetStartDate
+                p.targetCompletionDate = it.nextTargetCompletionDate
+                if(it.task.taskProcedure) p.taskProcedure = it.task.taskProcedure
+                if(it.task.assignedGroups) p.assignedGroups = new ArrayList(it.task.assignedGroups)
+                if(it.task.assignedPersons) p.assignedPersons = new ArrayList(it.task.assignedPersons)
 
-                    def result = taskService.createSubTask(it.task, p)
-                    if( !result.error ) {
-                        it.lastGeneratedSubTask = result.taskInstance
-                        it.subTasksGenerated++
-                        it.setNextTargetStartDate()
-                        it.setNextGenerationDate()
-                        it.setNextTargetCompletionDate()
-                    }
-                    else {
-                        log.error "Sub task generation for recurring schedule ${it.id} failed."
-                        log.error result.taskInstance.errors
-                    }
+                def result = taskService.createSubTask(it.task, p)
+                if( !result.error ) {
+                    it.lastGeneratedSubTask = result.taskInstance
+                    it.subTasksGenerated++
+                    it.setNextTargetStartDate()
+                    it.setNextGenerationDate()
+                    it.setNextTargetCompletionDate()
+                }
+                else {
+                    log.error "Sub task generation for recurring schedule ${it.id} failed."
+                    log.error result.taskInstance.errors
+                }
             }
 
-        }
-    }
+            // Run the completion reached checks for a second time so
+            // that this recurring schedule does not run again if
+            // there are no more subTasks to be generated.
+            if(maxSubTasksReached(it))
+                continue
+
+            if(targetCompletionDateReached(it))
+                continue
+
+        } // for()
+    } // generateAll()
 
     /**
