source: branches/features/taskProcedureRework/grails-app/services/TaskProcedureService.groovy @ 774

Last change on this file since 774 was 774, checked in by gav, 13 years ago

Use transactional service for TaskProcedure update to prevent maintenanceActions leaking into database when procedureStepNumber fails validation.

File size: 3.3 KB
Line 
1/**
2* Provides a service class for the TaskProcedure domain class.
3*/
4class TaskProcedureService {
5
6    boolean transactional = false
7
8    def authService
9
10    /**
11    * Updates an existing taskProcedure.
12    * @param params The params to update for taskProcedure with id of params.id.
13    * @returns A map containing result.error (if any error) and result.taskProcedureInstance (if available).
14    */
15    def update(params) {
16        TaskProcedure.withTransaction { status ->
17            def result = [:]
18
19            def fail = { Map m ->
20                status.setRollbackOnly()
21                if(result.taskProcedureInstance && m.field)
22                    result.taskProcedureInstance.errors.rejectValue(m.field, m.code)
23                result.error = [ code: m.code, args: ["TaskProcedure", params.id] ]
24                return result
25            }
26
27            result.taskProcedureInstance = TaskProcedure.get(params.id)
28
29            if(!result.taskProcedureInstance)
30                return fail(code:"default.not.found")
31
32            // Optimistic locking check.
33            if(params.version) {
34                if(result.taskProcedureInstance.version > params.version.toLong())
35                    return fail(field:"version", code:"default.optimistic.locking.failure")
36            }
37
38            result.taskProcedureInstance.properties = params
39            result.taskProcedureInstance.lastUpdatedBy = authService.currentUser
40            result.taskProcedureInstance.lastUpdated = new Date() // Required to trigger version increment.
41
42            // Gaps in the html index's can be created by adding 2 items and removing the first one.
43            // This creates a gap at the missing index where LazyList will return a null.
44            def nullMaintenanceActions = result.taskProcedureInstance.maintenanceActions.findAll {!it}
45            if (nullMaintenanceActions) {
46                result.taskProcedureInstance.maintenanceActions.removeAll(nullMaintenanceActions)
47            }
48
49            // Save for restoration if validation fails.
50            def savedMaintenanceActions = new ArrayList(result.taskProcedureInstance.maintenanceActions)
51
52            // Remove toBeDeleted before validation.
53            def toBeDeleted = result.taskProcedureInstance.maintenanceActions.findAll {it.toBeDeleted}
54            if (toBeDeleted) {
55                result.taskProcedureInstance.maintenanceActions.removeAll(toBeDeleted)
56            }
57
58            if(result.taskProcedureInstance.hasErrors() || !result.taskProcedureInstance.save()) {
59                // Restore the saved items, some of which contain toBeDeleted flags but
60                // have not been deleted yet since validation failed.
61                // The toBeDeleted items are hidden in the view.
62                result.taskProcedureInstance.maintenanceActions = savedMaintenanceActions
63                // Populate maintenanceAction errors for display.
64                result.taskProcedureInstance.maintenanceActions.each { it.validate() }
65                // Fetch to prevent lazy initialization error.
66                result.taskProcedureInstance.linkedTask.primaryAsset
67                result.taskProcedureInstance.createdBy
68                return fail(code:"default.update.failure")
69            }
70
71            // Success.
72            return result
73
74        } //end withTransaction
75    }  // end update()
76
77} // end class
Note: See TracBrowser for help on using the repository browser.