Index: trunk/grails-app/controllers/TaskRecurringScheduleDetailedController.groovy
===================================================================
--- trunk/grails-app/controllers/TaskRecurringScheduleDetailedController.groovy	(revision 202)
+++ trunk/grails-app/controllers/TaskRecurringScheduleDetailedController.groovy	(revision 203)
@@ -6,4 +6,5 @@
 
     def dateUtilService
+    def taskRecurringScheduleService
 
     def index = { redirect(action:list,params:params) }
@@ -112,48 +113,24 @@
 
     def create = {
-        try {
-            def taskInstance = Task.get(params.taskInstance.id)
-            def taskRecurringScheduleInstance = new TaskRecurringSchedule()
-            taskRecurringScheduleInstance.task = taskInstance
-            return [taskRecurringScheduleInstance: taskRecurringScheduleInstance]
+        if(!params.task?.id || !Task.exists(params.task?.id)) {
+            flash.message = "Please select a task, then Create a Recurring Schedule for it."
+            redirect(controller:"taskDetailed", action:"search")
+            return
         }
-        catch(Exception e) {
-            flash.message = "Please select a task, then Create a Recurring Schedule for it"
-            redirect(controller:"taskDetailed", action:"search")
-        }
+        def taskRecurringScheduleInstance = new TaskRecurringSchedule()
+        taskRecurringScheduleInstance.properties = params
+        return [taskRecurringScheduleInstance: taskRecurringScheduleInstance]
     } // end create()
 
     def save = {
-        def taskRecurringScheduleInstance = new TaskRecurringSchedule(params)
-        def taskInstance = Task.get(params.task.id)
+        def result = taskRecurringScheduleService.create(params)
 
-        if(taskInstance.taskRecurringSchedule) {
-            flash.message = "This task already has a recurring schedule"
-            redirect(controller:"taskDetailed", action:"show", id: params.task.id)
+        if(!result.error) {
+            flash.message = "Recurring Schedule ${result.taskRecurringScheduleInstance.id} created."
+            redirect(action:show, id: result.taskRecurringScheduleInstance.id)
         }
         else {
-
-            if(taskRecurringScheduleInstance.nextTargetStartDate < dateUtilService.getToday()) {
-                taskRecurringScheduleInstance.errors.rejectValue("nextTargetStartDate", "taskRecurring.nextTargetStartDate.NotInTheFuture")
-            }
-
-            if(!taskRecurringScheduleInstance.hasErrors() && taskRecurringScheduleInstance.save(flush: true)) {
-
-                taskInstance.taskRecurringSchedule = taskRecurringScheduleInstance
-
-                if(taskInstance.save(flush: true)) {
-                    flash.message = "Recurring Schedule ${taskRecurringScheduleInstance.id} created"
-                    redirect(action:show,id:taskRecurringScheduleInstance.id)
-                }
-                else {
-                    flash.message = "Task could not be saved and therefore the Recurring Schedule has been disgarded, cause unknown."	
-                    render(view:'create',model:[taskRecurringScheduleInstance:taskRecurringScheduleInstance])
-                }
-            }
-            else {
-                render(view:'create',model:[taskRecurringScheduleInstance:taskRecurringScheduleInstance])
-            }
+            render(view:'create',model:[taskRecurringScheduleInstance: result.taskRecurringScheduleInstance])
         }
-
     } // end save()
 
Index: trunk/grails-app/i18n/messages.properties
===================================================================
--- trunk/grails-app/i18n/messages.properties	(revision 202)
+++ trunk/grails-app/i18n/messages.properties	(revision 203)
@@ -25,7 +25,10 @@
 assignedPerson.estimatedDuration.help=The estimated amount of time (hh:mm) that you would like to assign this person to the task.
 
-task.modifications.failedToSave=Could not complete operation, as task modification record failed to save.
+task.notFound=Could not complete operation, task not found.
 task.operationNotPermittedOnCompleteTask=This operation is not permitted on a complete task.
 task.operationNotPermittedOnTaskInTrash=This operation is not permitted on a task that is in the trash.
+task.failedToSave=Could not complete operation, task failed to save.
+task.modifications.failedToSave=Could not complete operation, as task modification record failed to save.
+tast.taskRecurringSchedule.alreadyExists=This task already has a recurring schedule.
 
 task.assignedPersons=Assigned Persons
@@ -53,8 +56,4 @@
 inventoryMovement.quantity.insufficientItemsInStock=Could not complete operation, insufficient items in stock.
 inventoryMovement.inventoryItem.notFound=Inventory Item not found.
-
-entry.task.notFound=Could not complete operation, task not found.
-entry.task.failedToSave=Could not complete operation, task failed to save.
-entry.task.failedToSaveTaskModification=Could not complete operation, task modification failed to save.
 
 default.doesnt.match.message=Property [{0}] of class [{1}] with value [{2}] does not match the required pattern [{3}]
Index: trunk/grails-app/services/TaskRecurringScheduleService.groovy
===================================================================
--- trunk/grails-app/services/TaskRecurringScheduleService.groovy	(revision 202)
+++ trunk/grails-app/services/TaskRecurringScheduleService.groovy	(revision 203)
@@ -6,7 +6,9 @@
     def taskService
 
+    /**
+    * Generate all enabled recurring tasks.
+    */
     def generateAll() {
 
-        /// @todo: disable recurringSchedule when moving a task to trash.
         def taskRecurringScheduleList = TaskRecurringSchedule.findAllByEnabled(true)
 
@@ -17,4 +19,5 @@
                     p.targetStartDate = it.nextTargetStartDate
                     p.targetCompletionDate = it.nextTargetCompletionDate
+                    if(it.task.taskProcedure) p.taskProcedure = it.task.taskProcedure
                     def result = taskService.createSubTask(it.task, p)
                     if( !result.error ) {
@@ -26,5 +29,6 @@
                     }
                     else {
-                        log.error result
+                        log.error "Sub task generation for recurring schedule ${it.id} failed."
+                        log.error result.taskInstance.errors
                     }
             }
@@ -33,3 +37,53 @@
     }
 
+    /**
+    * Creates a new recurring schedule for a task with the given params.
+    * @param params The params to use when creating the new recurring schedule.
+    * @returns A map containing result.error=true (if any error) and result.taskRecurringScheduleInstance and result.taskId.
+    */
+    def create(params) {
+        TaskRecurringSchedule.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Object[] args ->
+                status.setRollbackOnly()
+                if(args.size() == 2) result.taskRecurringScheduleInstance.errors.rejectValue(args[0], args[1])
+                result.error = true
+                return result
+            }
+
+            result.taskRecurringScheduleInstance = new TaskRecurringSchedule(params)
+            result.taskId = result.taskRecurringScheduleInstance.task.id
+
+            if(!result.taskRecurringScheduleInstance.validate())
+                return fail()
+
+            def taskInstance = Task.lock(result.taskId)
+
+            if(!taskInstance)
+                return fail('task', "task.notFound")
+
+            if(taskInstance.taskRecurringSchedule)
+                return fail('task', "tast.taskRecurringSchedule.alreadyExists")
+
+            if(taskInstance.taskStatus.id == 3)
+                return fail('task', "task.operationNotPermittedOnCompleteTask")
+
+            if(taskInstance.trash)
+                return fail('task', "task.operationNotPermittedOnTaskInTrash")
+
+            if(result.taskRecurringScheduleInstance.nextTargetStartDate < dateUtilService.getToday())
+                return fail("nextTargetStartDate", "taskRecurring.nextTargetStartDate.NotInTheFuture")
+
+            taskInstance.taskRecurringSchedule = result.taskRecurringScheduleInstance
+
+            if(!result.taskRecurringScheduleInstance.save() || !taskInstance.save())
+                return fail()
+
+            // All went well if we get to here.
+            return result
+
+        } //end withTransaction
+    } // end create()
+
 } // end of class
Index: trunk/grails-app/services/TaskService.groovy
===================================================================
--- trunk/grails-app/services/TaskService.groovy	(revision 202)
+++ trunk/grails-app/services/TaskService.groovy	(revision 203)
@@ -11,5 +11,5 @@
 
     /**
-    * Determines and returns a possible parent list
+    * Determines and returns a possible parent list for a task.
     * @param taskInstance The task to use when determining the possible parent list.
     * @returns A list of the possible parents.
@@ -123,10 +123,10 @@
 
             if(result.entryInstance.validate()) {
-                def taskInstance = Task.lock(result.entryInstance.task.id)
                 result.taskId = result.entryInstance.task.id
+                def taskInstance = Task.lock(result.taskId)
 
                 if(!taskInstance) {
                     status.setRollbackOnly()
-                    result.entryInstance.errors.rejectValue('task', "entry.task.notFound")
+                    result.entryInstance.errors.rejectValue('task', "task.notFound")
                     result.error = true
                     return result
@@ -150,5 +150,5 @@
                     if(!taskModification.save()) {
                         status.setRollbackOnly()
-                        taskInstance.errors.rejectValue("task", "entry.task.failedToSaveTaskModification")
+                        taskInstance.errors.rejectValue("task", "task.modifications.failedToSave")
                         result.error = true
                         return result
@@ -160,5 +160,5 @@
                     if(!taskInstance.save()) {
                         status.setRollbackOnly()
-                        result.entryInstance.errors.rejectValue("task", "entry.task.failedToSave")
+                        result.entryInstance.errors.rejectValue("task", "task.failedToSave")
                         result.error = true
                         return result
Index: trunk/grails-app/views/taskDetailed/show.gsp
===================================================================
--- trunk/grails-app/views/taskDetailed/show.gsp	(revision 202)
+++ trunk/grails-app/views/taskDetailed/show.gsp	(revision 203)
@@ -344,5 +344,5 @@
                             <br />
                             <g:form controller="taskProcedureDetailed" >
-                                <input type="hidden" name="taskInstance.id" value="${taskInstance?.id}" />
+                                <g:hiddenField name="taskInstance.id" value="${taskInstance?.id}" />
 
                                 <div class="buttons">
@@ -442,5 +442,5 @@
                             <br />
                             <g:form controller="taskRecurringScheduleDetailed" >
-                                <input type="hidden" name="taskInstance.id" value="${taskInstance?.id}" />
+                                <g:hiddenField name="task.id" value="${taskInstance.id}" />
 
                                 <div class="buttons">
