Index: /trunk/grails-app/services/InventoryMovementService.groovy
===================================================================
--- /trunk/grails-app/services/InventoryMovementService.groovy	(revision 406)
+++ /trunk/grails-app/services/InventoryMovementService.groovy	(revision 407)
@@ -8,68 +8,57 @@
         InventoryMovement.withTransaction { status ->
             def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.inventoryMovementInstance && m.field)
+                    result.inventoryMovementInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["InventoryMovement", params.id] ]
+                return result
+            }
+
             result.inventoryMovementInstance = InventoryMovement.lock(params.id)
-            if(result.inventoryMovementInstance) {
 
-                // Used type must have a task that is not complete or in the trash
-                if(result.inventoryMovementInstance.inventoryMovementType.id == 1)  {
+             if(!result.inventoryMovementInstance)
+                fail(code:"default.not.found")
 
-                    // Unlike move, if the task does not exist at all then deletion is still allowed.
-                    if(result.inventoryMovementInstance.task?.trash) {
-                        status.setRollbackOnly()
-                        result.inventoryMovementInstance.errors.rejectValue("task", "task.operationNotPermittedOnTaskInTrash")
-                        result.error = true
-                        return result
-                    }
+            // Fetch to prevent lazy initialization error.
+            result.inventoryMovementInstance.inventoryItem.unitOfMeasure
 
-                    if(result.inventoryMovementInstance.task?.taskStatus?.id == 3) {
-                        status.setRollbackOnly()
-                        result.inventoryMovementInstance.errors.rejectValue('task', "task.operationNotPermittedOnCompleteTask")
-                        result.error = true
-                        return result
-                    }
-                }
+            // Used type must have a task that is not complete or in the trash
+            if(result.inventoryMovementInstance.inventoryMovementType.id == 1)  {
 
-                result.inventoryItemInstance = InventoryItem.lock(result.inventoryMovementInstance.inventoryItem.id)
-                result.taskId = result.inventoryMovementInstance.task?.id
+                // Unlike move, if the task does not exist at all then deletion is still allowed.
+                if(result.inventoryMovementInstance.task?.trash)
+                    return fail(field:"task", code:"task.operationNotPermittedOnTaskInTrash")
 
-                if(!result.inventoryItemInstance) {
-                        status.setRollbackOnly()
-                        result.inventoryMovementInstance.errors.rejectValue('inventoryItem', "inventoryMovement.inventoryItem.notFound")
-                        result.error = true
-                        return result
-                }
+                if(result.inventoryMovementInstance.task?.taskStatus?.id == 3)
+                    return fail(field:"task", code:"task.operationNotPermittedOnCompleteTask")
+            }
 
-                // Reverse the movement of inventory.
-                if(!result.inventoryMovementInstance.inventoryMovementType.incrementsInventory) {
-                    result.inventoryItemInstance.unitsInStock += result.inventoryMovementInstance.quantity
+            result.inventoryItemInstance = InventoryItem.lock(result.inventoryMovementInstance.inventoryItem.id)
+            result.taskId = result.inventoryMovementInstance.task?.id
+
+            if(!result.inventoryItemInstance)
+                return fail(field:"inventoryItem", code:"inventoryMovement.inventoryItem.notFound")
+
+            // Reverse the movement of inventory.
+            if(!result.inventoryMovementInstance.inventoryMovementType.incrementsInventory) {
+                result.inventoryItemInstance.unitsInStock += result.inventoryMovementInstance.quantity
+            }
+            else {
+                if(result.inventoryItemInstance.unitsInStock >= result.inventoryMovementInstance.quantity) {
+                    result.inventoryItemInstance.unitsInStock -= result.inventoryMovementInstance.quantity
                 }
                 else {
-                    if(result.inventoryItemInstance.unitsInStock >= result.inventoryMovementInstance.quantity) {
-                        result.inventoryItemInstance.unitsInStock -= result.inventoryMovementInstance.quantity
-                    }
-                    else {
-                        status.setRollbackOnly()
-                        result.inventoryMovementInstance.errors.rejectValue('quantity', "inventoryMovement.quantity.insufficientItemsInStock")
-                        result.error = true
-                        return result
-                    }
+                    return fail(field:"quantity", code:"inventoryMovement.quantity.insufficientItemsInStock")
                 }
+            }
 
-                if(result.inventoryItemInstance.save() ) {
-                    // All went well if we get to this point.
-                    result.inventoryMovementInstance.delete()
-                    return result
-                }
-                else {
-                    status.setRollbackOnly()
-                    result.error = true
-                    return result
-                }
+            if(!result.inventoryItemInstance.save())
+                return fail(code: "default.delete.failure")
 
-            }
-            else {
-                result.error = true
-                return result
-            }
+            // Success..
+            result.inventoryMovementInstance.delete()
+            return result
 
         } // end withTransaction
@@ -79,75 +68,61 @@
         InventoryMovement.withTransaction { status ->
             def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.inventoryMovementInstance && m.field)
+                    result.inventoryMovementInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["InventoryMovement", params.id] ]
+                return result
+            }
+
             result.inventoryMovementInstance = new InventoryMovement(params)
 
             result.inventoryMovementInstance.person = authService.currentUser
 
+            // Fetch to prevent lazy initialization error.
+            result.inventoryMovementInstance.inventoryItem.unitOfMeasure
+
             // Used type must have a task that is not complete or in the trash
             if(result.inventoryMovementInstance.inventoryMovementType.id == 1)  {
 
-                if(!result.inventoryMovementInstance.task) {
-                    status.setRollbackOnly()
-                    result.inventoryMovementInstance.errors.rejectValue('task', "task.notFound")
-                    result.error = true
-                    return result
+                if(!result.inventoryMovementInstance.task)
+                    return fail(field:"task", code:"task.notFound")
+
+                if(result.inventoryMovementInstance.task.trash)
+                    return fail(field:"task", code:"task.operationNotPermittedOnTaskInTrash")
+
+                if(result.inventoryMovementInstance.task.taskStatus.id == 3)
+                    return fail(field:"task", code:"task.operationNotPermittedOnCompleteTask")
+            }
+
+            // Bail early if validation fails.
+            if(!result.inventoryMovementInstance.validate())
+                return fail(code:"default.create.failure")
+
+            def inventoryItem = InventoryItem.lock(result.inventoryMovementInstance.inventoryItem.id)
+            result.taskId = result.inventoryMovementInstance.task?.id
+
+            if(!inventoryItem)
+                return fail(field:"inventoryItem", code:"inventoryMovement.inventoryItem.notFound")
+
+            // Perform the movement of inventory.
+            if(result.inventoryMovementInstance.inventoryMovementType.incrementsInventory) {
+                inventoryItem.unitsInStock += result.inventoryMovementInstance.quantity
+            }
+            else {
+                if(inventoryItem.unitsInStock >= result.inventoryMovementInstance.quantity) {
+                    inventoryItem.unitsInStock -= result.inventoryMovementInstance.quantity
                 }
-
-                if(result.inventoryMovementInstance.task.trash) {
-                    status.setRollbackOnly()
-                    result.inventoryMovementInstance.errors.rejectValue("task", "task.operationNotPermittedOnTaskInTrash")
-                    result.error = true
-                    return result
-                }
-
-                if(result.inventoryMovementInstance.task.taskStatus.id == 3) {
-                    status.setRollbackOnly()
-                    result.inventoryMovementInstance.errors.rejectValue('task', "task.operationNotPermittedOnCompleteTask")
-                    result.error = true
-                    return result
+                else {
+                    return fail(field:"quantity", code:"inventoryMovement.quantity.insufficientItemsInStock")
                 }
             }
 
-            if(result.inventoryMovementInstance.validate()) {
-                def inventoryItem = InventoryItem.lock(result.inventoryMovementInstance.inventoryItem.id)
-                result.taskId = result.inventoryMovementInstance.task?.id
+            if(!inventoryItem.save() || !result.inventoryMovementInstance.save())
+                return fail(code:"default.create.failure")
 
-                if(!inventoryItem) {
-                    status.setRollbackOnly()
-                    result.inventoryMovementInstance.errors.rejectValue('inventoryItem', "inventoryMovement.inventoryItem.notFound")
-                    result.error = true
-                    return result
-                }
-
-                // Perform the movement of inventory.
-                if(result.inventoryMovementInstance.inventoryMovementType.incrementsInventory) {
-                    inventoryItem.unitsInStock += result.inventoryMovementInstance.quantity
-                }
-                else {
-                    if(inventoryItem.unitsInStock >= result.inventoryMovementInstance.quantity) {
-                        inventoryItem.unitsInStock -= result.inventoryMovementInstance.quantity
-                    }
-                    else {
-                        status.setRollbackOnly()
-                        result.inventoryMovementInstance.errors.rejectValue('quantity', "inventoryMovement.quantity.insufficientItemsInStock")
-                        result.error = true
-                        return result
-                    }
-                }
-
-                if(inventoryItem.save() && result.inventoryMovementInstance.save()) {
-                    // All went well if we get to this point.
-                    return result
-                }
-                else {
-                    status.setRollbackOnly()
-                    result.error = true
-                    return result
-                }
-
-            }
-            else {
-                result.error = true
-                return result
-            }
+            // Success..
+            return result
 
         } // end withTransaction
