source: trunk/grails-app/services/InventoryMovementService.groovy @ 407

Last change on this file since 407 was 407, checked in by gav, 14 years ago

Fix lazy initialization error during failed inventory movement.
Refactor InventoryMovementService to use the fail closure.

File size: 5.4 KB
RevLine 
[177]1class InventoryMovementService {
2
3    boolean transactional = false
4
[291]5    def authService
[217]6
[177]7    def reverseMove(params) {
8        InventoryMovement.withTransaction { status ->
9            def result = [:]
[407]10
11            def fail = { Map m ->
12                status.setRollbackOnly()
13                if(result.inventoryMovementInstance && m.field)
14                    result.inventoryMovementInstance.errors.rejectValue(m.field, m.code)
15                result.error = [ code: m.code, args: ["InventoryMovement", params.id] ]
16                return result
17            }
18
[191]19            result.inventoryMovementInstance = InventoryMovement.lock(params.id)
[225]20
[407]21             if(!result.inventoryMovementInstance)
22                fail(code:"default.not.found")
[225]23
[407]24            // Fetch to prevent lazy initialization error.
25            result.inventoryMovementInstance.inventoryItem.unitOfMeasure
[225]26
[407]27            // Used type must have a task that is not complete or in the trash
28            if(result.inventoryMovementInstance.inventoryMovementType.id == 1)  {
[225]29
[407]30                // Unlike move, if the task does not exist at all then deletion is still allowed.
31                if(result.inventoryMovementInstance.task?.trash)
32                    return fail(field:"task", code:"task.operationNotPermittedOnTaskInTrash")
[177]33
[407]34                if(result.inventoryMovementInstance.task?.taskStatus?.id == 3)
35                    return fail(field:"task", code:"task.operationNotPermittedOnCompleteTask")
36            }
[177]37
[407]38            result.inventoryItemInstance = InventoryItem.lock(result.inventoryMovementInstance.inventoryItem.id)
39            result.taskId = result.inventoryMovementInstance.task?.id
[177]40
[407]41            if(!result.inventoryItemInstance)
42                return fail(field:"inventoryItem", code:"inventoryMovement.inventoryItem.notFound")
43
44            // Reverse the movement of inventory.
45            if(!result.inventoryMovementInstance.inventoryMovementType.incrementsInventory) {
46                result.inventoryItemInstance.unitsInStock += result.inventoryMovementInstance.quantity
47            }
48            else {
49                if(result.inventoryItemInstance.unitsInStock >= result.inventoryMovementInstance.quantity) {
50                    result.inventoryItemInstance.unitsInStock -= result.inventoryMovementInstance.quantity
[177]51                }
52                else {
[407]53                    return fail(field:"quantity", code:"inventoryMovement.quantity.insufficientItemsInStock")
[177]54                }
55            }
56
[407]57            if(!result.inventoryItemInstance.save())
58                return fail(code: "default.delete.failure")
59
60            // Success..
61            result.inventoryMovementInstance.delete()
62            return result
63
[177]64        } // end withTransaction
65    } //end reverseMove()
66
67    def move(params) {
68        InventoryMovement.withTransaction { status ->
69            def result = [:]
[407]70
71            def fail = { Map m ->
72                status.setRollbackOnly()
73                if(result.inventoryMovementInstance && m.field)
74                    result.inventoryMovementInstance.errors.rejectValue(m.field, m.code)
75                result.error = [ code: m.code, args: ["InventoryMovement", params.id] ]
76                return result
77            }
78
[191]79            result.inventoryMovementInstance = new InventoryMovement(params)
[177]80
[291]81            result.inventoryMovementInstance.person = authService.currentUser
[217]82
[407]83            // Fetch to prevent lazy initialization error.
84            result.inventoryMovementInstance.inventoryItem.unitOfMeasure
85
[225]86            // Used type must have a task that is not complete or in the trash
87            if(result.inventoryMovementInstance.inventoryMovementType.id == 1)  {
[177]88
[407]89                if(!result.inventoryMovementInstance.task)
90                    return fail(field:"task", code:"task.notFound")
[177]91
[407]92                if(result.inventoryMovementInstance.task.trash)
93                    return fail(field:"task", code:"task.operationNotPermittedOnTaskInTrash")
[225]94
[407]95                if(result.inventoryMovementInstance.task.taskStatus.id == 3)
96                    return fail(field:"task", code:"task.operationNotPermittedOnCompleteTask")
[225]97            }
[191]98
[407]99            // Bail early if validation fails.
100            if(!result.inventoryMovementInstance.validate())
101                return fail(code:"default.create.failure")
[225]102
[407]103            def inventoryItem = InventoryItem.lock(result.inventoryMovementInstance.inventoryItem.id)
104            result.taskId = result.inventoryMovementInstance.task?.id
[225]105
[407]106            if(!inventoryItem)
107                return fail(field:"inventoryItem", code:"inventoryMovement.inventoryItem.notFound")
[177]108
[407]109            // Perform the movement of inventory.
110            if(result.inventoryMovementInstance.inventoryMovementType.incrementsInventory) {
111                inventoryItem.unitsInStock += result.inventoryMovementInstance.quantity
112            }
113            else {
114                if(inventoryItem.unitsInStock >= result.inventoryMovementInstance.quantity) {
115                    inventoryItem.unitsInStock -= result.inventoryMovementInstance.quantity
[177]116                }
117                else {
[407]118                    return fail(field:"quantity", code:"inventoryMovement.quantity.insufficientItemsInStock")
[177]119                }
120            }
121
[407]122            if(!inventoryItem.save() || !result.inventoryMovementInstance.save())
123                return fail(code:"default.create.failure")
124
125            // Success..
126            return result
127
[177]128        } // end withTransaction
129    } // end move()
130
131} // end class
Note: See TracBrowser for help on using the repository browser.