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

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

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

File size: 5.4 KB
Line 
1class InventoryMovementService {
2
3    boolean transactional = false
4
5    def authService
6
7    def reverseMove(params) {
8        InventoryMovement.withTransaction { status ->
9            def result = [:]
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
19            result.inventoryMovementInstance = InventoryMovement.lock(params.id)
20
21             if(!result.inventoryMovementInstance)
22                fail(code:"default.not.found")
23
24            // Fetch to prevent lazy initialization error.
25            result.inventoryMovementInstance.inventoryItem.unitOfMeasure
26
27            // Used type must have a task that is not complete or in the trash
28            if(result.inventoryMovementInstance.inventoryMovementType.id == 1)  {
29
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")
33
34                if(result.inventoryMovementInstance.task?.taskStatus?.id == 3)
35                    return fail(field:"task", code:"task.operationNotPermittedOnCompleteTask")
36            }
37
38            result.inventoryItemInstance = InventoryItem.lock(result.inventoryMovementInstance.inventoryItem.id)
39            result.taskId = result.inventoryMovementInstance.task?.id
40
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
51                }
52                else {
53                    return fail(field:"quantity", code:"inventoryMovement.quantity.insufficientItemsInStock")
54                }
55            }
56
57            if(!result.inventoryItemInstance.save())
58                return fail(code: "default.delete.failure")
59
60            // Success..
61            result.inventoryMovementInstance.delete()
62            return result
63
64        } // end withTransaction
65    } //end reverseMove()
66
67    def move(params) {
68        InventoryMovement.withTransaction { status ->
69            def result = [:]
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
79            result.inventoryMovementInstance = new InventoryMovement(params)
80
81            result.inventoryMovementInstance.person = authService.currentUser
82
83            // Fetch to prevent lazy initialization error.
84            result.inventoryMovementInstance.inventoryItem.unitOfMeasure
85
86            // Used type must have a task that is not complete or in the trash
87            if(result.inventoryMovementInstance.inventoryMovementType.id == 1)  {
88
89                if(!result.inventoryMovementInstance.task)
90                    return fail(field:"task", code:"task.notFound")
91
92                if(result.inventoryMovementInstance.task.trash)
93                    return fail(field:"task", code:"task.operationNotPermittedOnTaskInTrash")
94
95                if(result.inventoryMovementInstance.task.taskStatus.id == 3)
96                    return fail(field:"task", code:"task.operationNotPermittedOnCompleteTask")
97            }
98
99            // Bail early if validation fails.
100            if(!result.inventoryMovementInstance.validate())
101                return fail(code:"default.create.failure")
102
103            def inventoryItem = InventoryItem.lock(result.inventoryMovementInstance.inventoryItem.id)
104            result.taskId = result.inventoryMovementInstance.task?.id
105
106            if(!inventoryItem)
107                return fail(field:"inventoryItem", code:"inventoryMovement.inventoryItem.notFound")
108
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
116                }
117                else {
118                    return fail(field:"quantity", code:"inventoryMovement.quantity.insufficientItemsInStock")
119                }
120            }
121
122            if(!inventoryItem.save() || !result.inventoryMovementInstance.save())
123                return fail(code:"default.create.failure")
124
125            // Success..
126            return result
127
128        } // end withTransaction
129    } // end move()
130
131} // end class
Note: See TracBrowser for help on using the repository browser.