Index: /trunk/grails-app/controllers/TaskDetailedController.groovy
===================================================================
--- /trunk/grails-app/controllers/TaskDetailedController.groovy	(revision 179)
+++ /trunk/grails-app/controllers/TaskDetailedController.groovy	(revision 180)
@@ -6,4 +6,5 @@
     def authenticateService
     def dateUtilService
+    def taskService
     def taskSearchService
     def filterService
@@ -186,4 +187,6 @@
 
             def inventoryMovementList = InventoryMovement.findAllByTask(taskInstance, [max:100, sort:"id", order:"desc", offset:0])
+
+            def taskModificationList = TaskModification.findAllByTask(taskInstance, [max:100, sort:"id", order:"asc", offset:0])
 
             def taskProcedureInstance = TaskProcedure.get(taskInstance.taskProcedure?.id)
@@ -215,5 +218,6 @@
                             taskRecurringScheduleInstance: taskRecurringScheduleInstance,
                             taskRecurringScheduleExits: taskRecurringScheduleExits,
-                            inventoryMovementList: inventoryMovementList]
+                            inventoryMovementList: inventoryMovementList,
+                            taskModificationList: taskModificationList]
         }
     }
@@ -263,29 +267,54 @@
 
     def update = {
-        def taskInstance = Task.get( params.id )
-        if(taskInstance) {
-            if(params.version) {
-                def version = params.version.toLong()
-                if(taskInstance.version > version) {
-
-                    taskInstance.errors.rejectValue("version", "task.optimistic.locking.failure", "Another user has updated this Task while you were editing.")
-                    render(view:'edit',model:[taskInstance:taskInstance])
-                    return
-                }
-            }
-            taskInstance.properties = params
-            if(!taskInstance.hasErrors() && taskInstance.save(flush: true)) {
+
+        if(!Task.exists(params.id)) {
+            flash.message = "Task not found with id ${params.id}"
+            redirect(action:'search')
+        }
+
+        def result = taskService.update(params)
+
+        if(!result.error) {
                 flash.message = "Task ${params.id} updated"
-                redirect(action:show,id:taskInstance.id)
-            }
-            else {
-                render(view:'edit',model:[taskInstance:taskInstance])
-            }
-        }
-        else {
-            flash.message = "Task not found with id ${params.id}"
-            redirect(action:edit,id:params.id)
-        }
-    }
+                redirect(action:show,id:result.taskInstance.id)
+        }
+        else {
+            if(result.taskInstance) {
+                render(view:'edit',model:[taskInstance:result.taskInstance])
+            }
+            else {
+                flash.message = "Task could not be updated."
+                redirect(action:'search')
+            }
+        }
+
+    }
+
+//     def update = {
+//         def taskInstance = Task.get( params.id )
+//         if(taskInstance) {
+//             if(params.version) {
+//                 def version = params.version.toLong()
+//                 if(taskInstance.version > version) {
+// 
+//                     taskInstance.errors.rejectValue("version", "task.optimistic.locking.failure", "Another user has updated this Task while you were editing.")
+//                     render(view:'edit',model:[taskInstance:taskInstance])
+//                     return
+//                 }
+//             }
+//             taskInstance.properties = params
+//             if(!taskInstance.hasErrors() && taskInstance.save(flush: true)) {
+//                 flash.message = "Task ${params.id} updated"
+//                 redirect(action:show,id:taskInstance.id)
+//             }
+//             else {
+//                 render(view:'edit',model:[taskInstance:taskInstance])
+//             }
+//         }
+//         else {
+//             flash.message = "Task not found with id ${params.id}"
+//             redirect(action:edit,id:params.id)
+//         }
+//     }
 
     def create = {
@@ -296,11 +325,19 @@
 
     def save = {
-        def taskInstance = new Task(params)
-        if(!taskInstance.hasErrors() && taskInstance.save(flush: true)) {
-            flash.message = "Task ${taskInstance.id} created"
-            redirect(action:show,id:taskInstance.id)
-        }
-        else {
-            render(view:'create',model:[taskInstance:taskInstance])
+        def result = taskService.create(params)
+
+        if(!result.error) {
+            flash.message = "Task ${result.taskInstance.id} created."
+            redirect(action: show,id: result.taskInstance.id)
+        }
+        else {
+            if(result.taskInstance) {
+                render(view:'create',model:[taskInstance:result.taskInstance])
+            }
+            else {
+                flash.message = "Could not create task."
+                redirect(action:"search")
+            }
+
         }
     }
Index: /trunk/grails-app/domain/Asset.groovy
===================================================================
--- /trunk/grails-app/domain/Asset.groovy	(revision 179)
+++ /trunk/grails-app/domain/Asset.groovy	(revision 180)
@@ -15,5 +15,5 @@
 
     static constraints = {
-        name(unique:true)
+        name(unique:true, blank:false)
     }
 
Index: /trunk/grails-app/domain/TaskModification.groovy
===================================================================
--- /trunk/grails-app/domain/TaskModification.groovy	(revision 179)
+++ /trunk/grails-app/domain/TaskModification.groovy	(revision 180)
@@ -1,2 +1,4 @@
+import java.text.SimpleDateFormat
+
 class TaskModification {
     Person person
@@ -4,5 +6,5 @@
     Task task
     Date date = new Date()
-    String comment
+    String comment = ""
 
     static belongsTo = [Person, TaskModificationType, Task]
@@ -16,4 +18,7 @@
     }
 
-    static optionals = ["comment"]
+    String toString() {
+        def date = new SimpleDateFormat("EEE, dd-MMM-yyyy").format(this.date)
+        "${taskModificationType} by ${person} on ${date}."
+    }
 }
Index: /trunk/grails-app/i18n/messages.properties
===================================================================
--- /trunk/grails-app/i18n/messages.properties	(revision 179)
+++ /trunk/grails-app/i18n/messages.properties	(revision 180)
@@ -24,4 +24,6 @@
 assignedPerson.estimatedDuration=Estimated Duration
 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.assignedPersons=Assigned Persons
Index: /trunk/grails-app/services/CreateDataService.groovy
===================================================================
--- /trunk/grails-app/services/CreateDataService.groovy	(revision 179)
+++ /trunk/grails-app/services/CreateDataService.groovy	(revision 180)
@@ -1,9 +1,14 @@
 /**
 * Provides a data service to create base and demo data.
+* Beware that most, if not all, base data is referenced by "Id" throughout the program.
+* This allows changing the text of the 'name' property to something of the same meaning.
+* But be sure to maintain the correct Id during creation, indicated by #1, #2 etc.
 */
 class  CreateDataService {
 
+    boolean transactional = false
+
     def authenticateService
-    boolean transactional = false
+    def taskService
 
 /*******************************************
@@ -40,9 +45,10 @@
         createBaseManufacturerType()
         // Tasks
+        createBaseTaskGroups()
         createBaseTaskStatus()
         createBaseTaskPriorities()
         createBaseTaskTypes()
+        createBaseTaskModificationTypes()
         createBaseEntryTypes()
-        createBaseModificationTypes()
         // Inventory
         createBaseInventoryTypes()
@@ -66,5 +72,4 @@
         createDemoManufacturers()
         // Tasks
-        createDemoTaskGroups() /// @todo: Perhaps this should be BaseData?
         createDemoTasks()
         createDemoEntries()
@@ -383,5 +388,5 @@
 *********************/
 
-    def createDemoTaskGroups() {
+    def createBaseTaskGroups() {
         //TaskGroup
         def taskGroupInstance
@@ -454,22 +459,38 @@
     }
 
+    def createBaseTaskModificationTypes() {
+
+        //ModificationType
+        def taskModificationTypeInstance
+        taskModificationTypeInstance = new TaskModificationType(name:"Created").save()  // #1
+        taskModificationTypeInstance = new TaskModificationType(name:"Started").save()  // #2
+        taskModificationTypeInstance = new TaskModificationType(name:"Modified").save()  // #3
+        taskModificationTypeInstance = new TaskModificationType(name:"Completed").save()  // #4
+        taskModificationTypeInstance = new TaskModificationType(name:"Reopened").save()  // #5
+        taskModificationTypeInstance = new TaskModificationType(name:"Trashed").save()  // #6
+        taskModificationTypeInstance = new TaskModificationType(name:"Restored").save()  // #7
+        taskModificationTypeInstance = new TaskModificationType(name:"Approved").save()  // #8
+        taskModificationTypeInstance = new TaskModificationType(name:"Renege approval").save()  // #9
+    }
+
     def createDemoTasks() {
 
-        //Task
-        def taskInstance
+        def taskResult
+        def p = [:]
 
         //Task #1
-        taskInstance = new Task(taskGroup:TaskGroup.findByName("Engineering Activites"),
-                 taskStatus:TaskStatus.findByName("Not Started"),
-                 taskPriority:TaskPriority.get(2),
-                 taskType:TaskType.get(1),
-                 leadPerson:Person.get(2),
-                 description:"Check specific level sensor",
-                 comment:"Has been noted as problematic, try recalibrating.",
-                targetStartDate:new Date())
-        saveAndTest(taskInstance)
+        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
+                taskStatus:TaskStatus.findByName("Not Started"),
+                taskPriority:TaskPriority.get(2),
+                taskType:TaskType.get(1),
+                leadPerson:Person.get(2),
+                description:"Check specific level sensor",
+                comment:"Has been noted as problematic, try recalibrating.",
+                targetStartDate:new Date()]
+
+        taskResult = taskService.create(p)
 
         //Task #2
-        taskInstance = new Task(taskGroup:TaskGroup.findByName("Engineering Activites"),
+        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
                 taskStatus:TaskStatus.findByName("Not Started"),
                 taskPriority:TaskPriority.get(2),
@@ -479,9 +500,10 @@
                 comment:"Some help required",
                 targetStartDate:new Date()+1,
-                parentTask: Task.get(1))
-        saveAndTest(taskInstance)
+                parentTask: Task.get(1)]
+
+        taskResult = taskService.create(p)
 
         //Task #3
-        taskInstance = new Task(taskGroup:TaskGroup.findByName("Engineering Activites"),
+        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
                 taskStatus:TaskStatus.findByName("Not Started"),
                 taskPriority:TaskPriority.get(2),
@@ -491,9 +513,10 @@
                 comment:"Some help required",
                 targetStartDate:new Date()-1,
-                parentTask: Task.get(1))
-        saveAndTest(taskInstance)
+                parentTask: Task.get(1)]
+
+        taskResult = taskService.create(p)
 
         //Task #4
-        taskInstance = new Task(taskGroup:TaskGroup.findByName("Engineering Activites"),
+        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
                  taskStatus:TaskStatus.findByName("Not Started"),
                  taskPriority:TaskPriority.get(2),
@@ -503,9 +526,10 @@
                  comment:"Nothing else has worked.",
                 targetStartDate:new Date()+7,
-                parentTask: Task.get(1))
-        saveAndTest(taskInstance)
+                parentTask: Task.get(1)]
+
+        taskResult = taskService.create(p)
 
         //Task #5
-        taskInstance = new Task(taskGroup:TaskGroup.findByName("Production Activites"),
+        p = [taskGroup:TaskGroup.findByName("Production Activites"),
                  taskStatus:TaskStatus.findByName("Not Started"),
                  taskPriority:TaskPriority.get(2),
@@ -514,9 +538,10 @@
                  description:"Production Report",
                  comment:"Production report for specific production run or shift",
-                targetStartDate:new Date()-7)
-        saveAndTest(taskInstance)
+                targetStartDate:new Date()-7]
+
+        taskResult = taskService.create(p)
 
         //Task #6
-        taskInstance = new Task(taskGroup:TaskGroup.findByName("New Projects"),
+        p = [taskGroup:TaskGroup.findByName("New Projects"),
                  taskStatus:TaskStatus.findByName("Not Started"),
                  taskPriority:TaskPriority.get(2),
@@ -525,6 +550,7 @@
                  description:"Make killer CMMS app",
                  comment:"Use Grails and get a move on!",
-                targetStartDate:new Date()-6)
-        saveAndTest(taskInstance)
+                targetStartDate:new Date()-6]
+
+        taskResult = taskService.create(p)
     }
 
@@ -575,19 +601,4 @@
                                                     durationMinute: 20)
         saveAndTest(entryInstance)
-    }
-
-    def createBaseModificationTypes() {
-
-        //ModificationType
-        def taskModificationTypeInstance
-        taskModificationTypeInstance = new TaskModificationType(name:"Created").save()
-        taskModificationTypeInstance = new TaskModificationType(name:"Completed").save()
-        taskModificationTypeInstance = new TaskModificationType(name:"Closed").save()
-        taskModificationTypeInstance = new TaskModificationType(name:"Altered").save()
-        taskModificationTypeInstance = new TaskModificationType(name:"TargetDateModified").save()
-        taskModificationTypeInstance = new TaskModificationType(name:"ScheduledDateModified").save()
-        taskModificationTypeInstance = new TaskModificationType(name:"DescriptionModified").save()
-        taskModificationTypeInstance = new TaskModificationType(name:"AssignedToModified").save()
-        taskModificationTypeInstance = new TaskModificationType(name:"NameModified").save()
     }
 
Index: /trunk/grails-app/services/DateUtilService.groovy
===================================================================
--- /trunk/grails-app/services/DateUtilService.groovy	(revision 179)
+++ /trunk/grails-app/services/DateUtilService.groovy	(revision 180)
@@ -2,7 +2,7 @@
 
     boolean transactional = false
-    static scope = "request"
-	
-	public static Date getToday() {
+    //static scope = "request"
+
+    public static Date getToday() {
         return setMidnight(new Date())
     }
Index: /trunk/grails-app/services/TaskSearchService.groovy
===================================================================
--- /trunk/grails-app/services/TaskSearchService.groovy	(revision 179)
+++ /trunk/grails-app/services/TaskSearchService.groovy	(revision 180)
@@ -2,5 +2,4 @@
 
     boolean transactional = false
-    static scope = "request"
 
     def dateUtilService
Index: /trunk/grails-app/services/TaskService.groovy
===================================================================
--- /trunk/grails-app/services/TaskService.groovy	(revision 179)
+++ /trunk/grails-app/services/TaskService.groovy	(revision 180)
@@ -1,11 +1,112 @@
 class TaskService {
 
-    boolean transactional = true
-    static scope = "request"
+    boolean transactional = false
 
     def dateUtilService
+    def authenticateService
 
-    def taskDates(taskInstance, params) {
-        println "yes"
-    }
-}
+    def create(params) {
+        Task.withTransaction { status ->
+            def result = [:]
+            def taskInstance = new Task(params)
+            result.taskInstance = taskInstance
+
+            // Get person in a safe way to avoid a null userDomain during bootstrap.
+            def userDomain = authenticateService.userDomain()
+            def person = userDomain ? Person.get(userDomain.id) : Person.get(1)
+
+            if(taskInstance.save()) {
+                def taskModification = new TaskModification(person:person,
+                                                        taskModificationType: TaskModificationType.get(1),
+                                                        task: taskInstance)
+
+                if(!taskModification.save()) {
+                    status.setRollbackOnly()
+                    taskInstance.errors.rejectValue("taskModifications", "task.modifications.failedToSave")
+                    result.error = true
+                    return result
+                }
+
+                return result
+            }
+            else {
+                result.error = true
+                return result
+            }
+
+        } //end withTransaction
+    } // end create()
+
+    def start() {
+        //TaskModificationType.get(2)
+    }  // end start()
+
+    def update(params) {
+        Task.withTransaction { status ->
+            def result = [:]
+            result.taskInstance = Task.get(params.id)
+            if(result.taskInstance) {
+
+                // Optimistic locking check.
+                if(params.version) {
+                    def version = params.version.toLong()
+                    if(result.taskInstance.version > version) {
+                        status.setRollbackOnly()
+                        result.taskInstance.errors.rejectValue("version", "task.optimistic.locking.failure", "Another user has updated this Task while you were editing.")
+                        result.error = true
+                        return result
+                    }
+                }
+
+
+                result.taskInstance.properties = params
+
+                if(result.taskInstance.save()) {
+                    def taskModification = new TaskModification(person:Person.get(authenticateService.userDomain().id),
+                                                            taskModificationType: TaskModificationType.get(3),
+                                                            task: result.taskInstance)
+                    if(taskModification.save()) {
+                        // All went well.
+                        return result
+                    }
+                    else {
+                        status.setRollbackOnly()
+                        result.taskInstance.errors.rejectValue("taskModifications", "task.modifications.failedToSave")
+                        result.error = true
+                        return result
+                    }
+                }
+            }
+            // Something failed.
+            status.setRollbackOnly()
+            result.error = true
+            return result
+
+        } //end withTransaction
+    }  // end update()
+
+    def complete() {
+        //TaskModificationType.get(4)
+    }  // end complete()
+
+    def reopen() {
+        //TaskModificationType.get(5)
+    }  // end reopen()
+
+    def trash() {
+        //TaskModificationType.get(6)
+    }  // end trash()
+
+    def restore() {
+        //TaskModificationType.get(7)
+    }  // end restore()
+
+    def approve() {
+        //TaskModificationType.get(8)
+    }  // end approve()
+
+    def renegeApproval() {
+        //TaskModificationType.get(9)
+    }  // end renegeApproval()
+
+} // end TaskService
Index: /trunk/grails-app/views/taskDetailed/create.gsp
===================================================================
--- /trunk/grails-app/views/taskDetailed/create.gsp	(revision 179)
+++ /trunk/grails-app/views/taskDetailed/create.gsp	(revision 180)
@@ -21,5 +21,5 @@
             </g:hasErrors>
 
-            <g:form id='createTaskForm' name='createTaskForm' action="save" method="post" >
+            <g:form action="save" method="post" >
                 <div class="dialog">
                     <table>
Index: /trunk/grails-app/views/taskDetailed/show.gsp
===================================================================
--- /trunk/grails-app/views/taskDetailed/show.gsp	(revision 179)
+++ /trunk/grails-app/views/taskDetailed/show.gsp	(revision 180)
@@ -4,4 +4,5 @@
         <meta name="layout" content="main" />
         <title>Show Task</title>
+        <g:javascript src="overlayPane.js" />
         <nav:resources override="true"/>
         <resource:tabView skin="tabviewCustom" />
@@ -15,7 +16,7 @@
             <div class="message">${flash.message}</div>
             </g:if>
-            <g:hasErrors bean="${taskProcedureInstance}">
+            <g:hasErrors bean="${taskInstance}">
             <div class="errors">
-                <g:renderErrors bean="${taskProcedureInstance}" as="list" />
+                <g:renderErrors bean="${taskInstance}" as="list" />
             </div>
             </g:hasErrors>
@@ -41,11 +42,4 @@
 
                                     <tr class="prop">
-                                        <td valign="top" class="name">Id:</td>
-
-                                        <td valign="top" class="value">${fieldValue(bean:taskInstance, field:'id')}</td>
-
-                                    </tr>
-
-                                    <tr class="prop">
                                         <td valign="top" class="name">Description:</td>
 
@@ -62,5 +56,5 @@
 
                                     <tr class="prop">
-                                        <td valign="top" class="name">Target Start Date:</td>
+                                        <td valign="top" class="name">Target Start:</td>
 
                                         <td valign="top" class="value"><g:formatDate date="${taskInstance.targetStartDate}" format="EEE, dd-MMM-yyyy"/></td>
@@ -69,9 +63,40 @@
 
                                     <tr class="prop">
-                                        <td valign="top" class="name">Target Completion Date:</td>
+                                        <td valign="top" class="name">Target Completion:</td>
 
                                         <td valign="top" class="value"><g:formatDate date="${taskInstance.targetCompletionDate}" format="EEE, dd-MMM-yyyy"/></td>
 
                                     </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="name">
+                                            <div id="modControlClosed">
+                                                <a href='' onclick="showElement('modifications');
+                                                                                    showElement('modControlOpened');
+                                                                                    hideElement('modControlClosed'); return false;">
+                                                    Modifications <img  src="${resource(dir:'images/skin',file:'sorted_asc.gif')}" alt="Show" />
+                                                </a>
+                                            </div>
+                                            <div id="modControlOpened" style="display:none;">
+                                                <a href='' onclick="hideElement('modifications');
+                                                                                    hideElement('modControlOpened');
+                                                                                    showElement('modControlClosed');
+                                                                                    return false;">
+                                                    Modifications <img  src="${resource(dir:'images/skin',file:'sorted_desc.gif')}" alt="Show" />
+                                                </a>
+                                            </div>
+                                        </td>
+
+                                        <td  valign="top" style="text-align:left;" class="value">
+                                            <div id="modifications" style="display:none;">
+                                                <ul>
+                                                <g:each var="a" in="${taskModificationList}">
+                                                    <li>${a?.encodeAsHTML()}</li>
+                                                </g:each>
+                                                </ul>
+                                            </div>
+                                        </td>
+                                    </tr>
+
 
                                     <tr class="prop">
@@ -103,5 +128,5 @@
 
                                     <tr class="prop">
-                                        <td valign="top" class="name">Task Priority:</td>
+                                        <td valign="top" class="name">Priority:</td>
 
                                         <td valign="top" class="value">${taskInstance?.taskPriority?.encodeAsHTML()}</td>
@@ -110,5 +135,5 @@
 
                                     <tr class="prop">
-                                        <td valign="top" class="name">Task Status:</td>
+                                        <td valign="top" class="name">Status:</td>
 
                                         <td valign="top" class="value">${taskInstance?.taskStatus?.encodeAsHTML()}</td>
@@ -117,5 +142,5 @@
 
                                     <tr class="prop">
-                                        <td valign="top" class="name">Is Active:</td>
+                                        <td valign="top" class="name">Active:</td>
 
                                         <td valign="top" class="value">${fieldValue(bean:taskInstance, field:'isActive')}</td>
@@ -124,5 +149,5 @@
 
                                     <tr class="prop">
-                                        <td valign="top" class="name">Is Approved:</td>
+                                        <td valign="top" class="name">Approved:</td>
 
                                         <td valign="top" class="value">${fieldValue(bean:taskInstance, field:'isApproved')}</td>
@@ -131,5 +156,5 @@
 
                                     <tr class="prop">
-                                        <td valign="top" class="name">Is Scheduled:</td>
+                                        <td valign="top" class="name">Scheduled:</td>
 
                                         <td valign="top" class="value">${fieldValue(bean:taskInstance, field:'isScheduled')}</td>
@@ -145,5 +170,5 @@
 
                                     <tr class="prop">
-                                        <td valign="top" class="name">Task Group:</td>
+                                        <td valign="top" class="name">Group:</td>
 
                                         <td valign="top" class="value">${taskInstance?.taskGroup?.encodeAsHTML()}</td>
@@ -152,5 +177,5 @@
 
                                     <tr class="prop">
-                                        <td valign="top" class="name">Task Type:</td>
+                                        <td valign="top" class="name">Type:</td>
 
                                         <td valign="top" class="value">${taskInstance?.taskType?.encodeAsHTML()}</td>
