Index: trunk/grails-app/services/TaskService.groovy
===================================================================
--- trunk/grails-app/services/TaskService.groovy	(revision 394)
+++ trunk/grails-app/services/TaskService.groovy	(revision 395)
@@ -182,64 +182,54 @@
         Task.withTransaction { status ->
             def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.taskInstance && m.field)
+                    result.taskInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["Entry", params.id] ]
+                return result
+            }
+
             result.entryInstance = new Entry(params)
             result.entryInstance.enteredBy = authService.currentUser
 
-            if(result.entryInstance.validate()) {
+            def taskInstance
+            if(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', "task.notFound")
-                    result.error = true
-                    return result
-                }
-
-                if(taskInstance.taskStatus.id == 3) {
-                    status.setRollbackOnly()
-                    result.entryInstance.errors.rejectValue('task', "task.operationNotPermittedOnCompleteTask")
-                    result.error = true
-                    return result
-                }
-
-                // If task status is "Not Started" and entry type is "Work Done" then we create the started modification and set the status.
-                if(taskInstance.taskStatus.id == 1 && result.entryInstance.entryType.id == 2) {
-
-                    // Create the "Started" task modification, this provides the "Actual started date".
-                    def taskModification = new TaskModification(person: authService.currentUser,
-                                                            taskModificationType: TaskModificationType.get(2),
-                                                            task: taskInstance)
-
-                    if(!taskModification.save()) {
-                        status.setRollbackOnly()
-                        taskInstance.errors.rejectValue("task", "task.modifications.failedToSave")
-                        result.error = true
-                        return result
-                    }
-
-                    // Set task status to "In progress".
-                    taskInstance.taskStatus = TaskStatus.get(2)
-
-                    if(!taskInstance.save()) {
-                        status.setRollbackOnly()
-                        result.entryInstance.errors.rejectValue("task", "task.failedToSave")
-                        result.error = true
-                        return result
-                    }
-                }
-
-                if(!result.entryInstance.save()) {
-                    status.setRollbackOnly()
-                    result.error = true
-                    return result
-                }
-
-                // If we get here all went well.
-                return result
-            }
-            else {
-                result.error = true
-                return result
-            }
+                taskInstance = Task.lock(result.entryInstance.task.id)
+            }
+
+            if(!taskInstance)
+                return fail(field:"task", code:"task.notFound")
+
+            if(result.entryInstance.hasErrors() || !result.entryInstance.save())
+                return fail(code:"default.create.failure")
+
+            if(taskInstance.taskStatus.id == 3)
+                return fail(field:"task", code:"task.operationNotPermittedOnCompleteTask")
+
+            // If task status is "Not Started" and entry type is "Work Done" then we create the started modification and set the status.
+            if(taskInstance.taskStatus.id == 1 && result.entryInstance.entryType.id == 2) {
+
+                // Create the "Started" task modification, this provides the "Actual Started Date".
+                def taskModification = new TaskModification(person: authService.currentUser,
+                                                        taskModificationType: TaskModificationType.get(2),
+                                                        task: taskInstance)
+
+                if(taskModification.hasErrors() || !taskModification.save())
+                    return fail(field:"task", code:"task.modifications.failedToSave")
+
+                // Set task status to "In Progress".
+                taskInstance.taskStatus = TaskStatus.get(2)
+
+                if(taskInstance.hasErrors() || !taskInstance.save())
+                    return fail(field:"task", code:"task.failedToSave")
+            }
+
+            if(result.entryInstance.hasErrors() || !result.entryInstance.save())
+                return fail(field:"task", code:"default.create.failure")
+
+            // Success.
+            return result
 
         } //end withTransaction
@@ -583,3 +573,77 @@
     }  // end renegeApproval()
 
+    /**
+    * Creates a new breakin task with the given params.
+    * @param params The params to use when creating the new task.
+    * @returns A map containing result.error=true (if any error) and result.taskInstance.
+    */
+    def saveBreakin(params) {
+        Task.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.taskInstance && m.field)
+                    result.taskInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["Task", params.id] ]
+                return result
+            }
+
+            // If not supplied.
+            if(!params.taskStatus)
+                params.taskStatus = TaskStatus.get(1) // Not Started.
+
+            result.taskInstance = new Task(params)
+
+            // Always for a breakin.
+            result.taskInstance.taskType = TaskType.get(1) // Unscheduled Breakin.
+            result.taskInstance.taskBudgetStatus = TaskBudgetStatus.get(1) // Unplanned.
+            result.taskInstance.taskPriority = TaskPriority.get(4) // Immediate.
+            result.taskInstance.taskGroup = TaskGroup.get(1) // Engineering Activites.
+            result.taskInstance.approved = true
+            result.taskInstance.leadPerson = authService.currentUser
+
+            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
+                fail(code:"default.create.failure")
+
+            if(!result.error) {
+                def taskModification = new TaskModification(person: authService.currentUser,
+                                                                taskModificationType: TaskModificationType.get(1), // Created.
+                                                                task: result.taskInstance)
+
+                if(taskModification.hasErrors() || !taskModification.save())
+                    fail(field:"taskModifications", code:"task.modifications.failedToSave")
+            }
+
+            def faultParams = [task: result.taskInstance,
+                                            entryType: EntryType.get(1),
+                                            comment: params.entryFault.comment,
+                                            durationHour: params.entryFault.durationHour,
+                                            durationMinute: params.entryFault.durationMinute]
+            def faultResult = saveEntry(faultParams)
+            result.entryFaultInstance = faultResult.entryInstance
+
+            def workDoneParams = [task: result.taskInstance,
+                                                    entryType: EntryType.get(2),
+                                                    comment: params.entryWorkDone.comment,
+                                                    durationHour: params.entryWorkDone.durationHour,
+                                                    durationMinute: params.entryWorkDone.durationMinute]
+            def workDoneResult = saveEntry(workDoneParams)
+            result.entryWorkDoneInstance = workDoneResult.entryInstance
+
+            if(result.error)
+                return result
+
+            if(faultResult.error)
+                return fail(code: "default.create.failure")
+
+            if(workDoneResult.error)
+                return fail(code: "default.create.failure")
+
+            // Success.
+            return result
+
+        } //end withTransaction
+    } // end saveBreakin()
+
 } // end TaskService
