source: trunk/grails-app/services/TaskService.groovy @ 243

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

Implement copying of assigned groups and persons to auto generated sub tasks.
As per ticket #55.

File size: 22.7 KB
Line 
1/**
2* Provides a service class for the Task domain class.
3*
4*/
5class TaskService {
6
7    boolean transactional = false
8
9    def personService
10
11    /**
12    * Determines and returns a possible parent list for a task.
13    * @param taskInstance The task to use when determining the possible parent list.
14    * @returns A list of the possible parents.
15    */
16    def possibleParentList(taskInstance) {
17        def criteria = taskInstance.createCriteria()
18        def possibleParentList = criteria {
19            and {
20                notEqual('trash', true)
21                notEqual('id', taskInstance.id)
22                taskInstance.subTasks.each() { notEqual('id', it.id) }
23                }
24        }
25    }
26
27    /**
28    * Creates a new task with the given params.
29    * @param params The params to use when creating the new task.
30    * @returns A map containing result.error=true (if any error) and result.taskInstance.
31    */
32    def create(params) {
33        Task.withTransaction { status ->
34            def result = [:]
35            // Default status to "not started" if not supplied.
36            params.taskStatus = params.taskStatus ?: TaskStatus.get(1)
37            def taskInstance = new Task(params)
38            result.taskInstance = taskInstance
39
40            if(result.taskInstance.parentTask?.trash) {
41                status.setRollbackOnly()
42                result.taskInstance.errors.rejectValue("parentTask", "task.operationNotPermittedOnTaskInTrash")
43                result.error = true
44                return result
45            }
46
47            if(taskInstance.save()) {
48                def taskModification = new TaskModification(person: personService.currentUser,
49                                                        taskModificationType: TaskModificationType.get(1),
50                                                        task: taskInstance)
51
52                if(!taskModification.save()) {
53                    status.setRollbackOnly()
54                    taskInstance.errors.rejectValue("taskModifications", "task.modifications.failedToSave")
55                    result.error = true
56                    return result
57                }
58
59                //Add the assignedGroups, provided by a new ArrayList(task.assignedGroups)
60                if(params.assignedGroups) {
61                    def assignedGroupInstance
62                    params.assignedGroups.each() {
63                        assignedGroupInstance = new AssignedGroup(personGroup: it.personGroup,
64                                                                                                        task: taskInstance,
65                                                                                                        estimatedHour: it.estimatedHour,
66                                                                                                        estimatedMinute: it.estimatedMinute)
67
68                        if(!assignedGroupInstance.save()) {
69                            status.setRollbackOnly()
70                            taskInstance.errors.rejectValue("assignedGroups", "task.assignedGroups.failedToSave")
71                            result.error = true
72                            return result
73                        }
74                    }
75                }
76
77                //Add the assignedPersons, provided by a new ArrayList(task.assignedPersons)
78                if(params.assignedPersons) {
79                    def assignedPersonInstance
80                    params.assignedPersons.each() {
81                        assignedPersonInstance = new AssignedPerson(person: it.person,
82                                                                                                            task: taskInstance,
83                                                                                                            estimatedHour: it.estimatedHour,
84                                                                                                            estimatedMinute: it.estimatedMinute)
85
86                        if(!assignedPersonInstance.save()) {
87                            status.setRollbackOnly()
88                            taskInstance.errors.rejectValue("assignedPersons", "task.assignedPersons.failedToSave")
89                            result.error = true
90                            return result
91                        }
92                    }
93                }
94
95                // Success.
96                return result
97            }
98            else {
99                result.error = true
100                return result
101            }
102
103        } //end withTransaction
104    } // end create()
105
106    /**
107    * Creates a subTask copying attributes from the parentTask unless otherwise specified.
108    * The taskProcedure is only assigned to the sub task if given in params.
109    * The assignedPersons and assignedGroups are only added to the sub task if given as new ArrayList's in params.
110    * @param parentTask The parent task to get attributes from, also set as the parent.
111    * @param params Overrides the parent task values if specified.
112    * @returns A map containing result.error=true (if any error) and result.taskInstance.
113    */
114    def createSubTask(parentTask, params = [:]) {
115
116        def result = [:]
117
118        //Make our new Task a subTask and set the required properites.
119        def p = [:]
120        p.parentTask = parentTask
121        p.description = params.description ?: parentTask.description
122        p.comment = params.comment ?: parentTask.comment
123
124        p.taskGroup = params.taskGroup ?: parentTask.taskGroup
125        p.taskStatus = TaskStatus.get(1) // A new subTask must always be "Not Started".
126        p.taskPriority = parentTask.taskPriority
127        p.taskType = params.taskType ?: parentTask.taskType
128        p.leadPerson = params.leadPerson ?: parentTask.leadPerson
129        p.primaryAsset = params.primaryAsset ?: parentTask.primaryAsset
130
131        p.targetStartDate = params.targetStartDate ?: parentTask.targetStartDate
132        p.targetCompletionDate = params.targetCompletionDate ?: parentTask.targetCompletionDate
133
134        if(params.taskProcedure) p.taskProcedure = params.taskProcedure
135        if(params.assignedGroups) p.assignedGroups = params.assignedGroups
136        if(params.assignedPersons) p.assignedPersons = params.assignedPersons
137
138        result = create(p)
139
140    } // end createSubTask()
141
142    /**
143    * Creates a new task entry.
144    * @param params The params to use when creating the new entry.
145    * @returns A map containing result.error=true (if any error), result.entryInstance and result.taskId.
146    */
147    def createEntry(params) {
148        Task.withTransaction { status ->
149            def result = [:]
150            result.entryInstance = new Entry(params)
151            result.entryInstance.enteredBy = personService.currentUser
152
153            if(result.entryInstance.validate()) {
154                result.taskId = result.entryInstance.task.id
155                def taskInstance = Task.lock(result.taskId)
156
157                if(!taskInstance) {
158                    status.setRollbackOnly()
159                    result.entryInstance.errors.rejectValue('task', "task.notFound")
160                    result.error = true
161                    return result
162                }
163
164                if(taskInstance.taskStatus.id == 3) {
165                    status.setRollbackOnly()
166                    result.entryInstance.errors.rejectValue('task', "task.operationNotPermittedOnCompleteTask")
167                    result.error = true
168                    return result
169                }
170
171                // If task status is "Not Started" and entry type is "Work Done" then we create the started modification and set the status.
172                if(taskInstance.taskStatus.id == 1 && result.entryInstance.entryType.id == 2) {
173
174                    // Create the "Started" task modification, this provides the "Actual started date".
175                    def taskModification = new TaskModification(person: personService.currentUser,
176                                                            taskModificationType: TaskModificationType.get(2),
177                                                            task: taskInstance)
178
179                    if(!taskModification.save()) {
180                        status.setRollbackOnly()
181                        taskInstance.errors.rejectValue("task", "task.modifications.failedToSave")
182                        result.error = true
183                        return result
184                    }
185
186                    // Set task status to "In progress".
187                    taskInstance.taskStatus = TaskStatus.get(2)
188
189                    if(!taskInstance.save()) {
190                        status.setRollbackOnly()
191                        result.entryInstance.errors.rejectValue("task", "task.failedToSave")
192                        result.error = true
193                        return result
194                    }
195                }
196
197                if(!result.entryInstance.save()) {
198                    status.setRollbackOnly()
199                    result.error = true
200                    return result
201                }
202
203                // If we get here all went well.
204                return result
205            }
206            else {
207                result.error = true
208                return result
209            }
210
211        } //end withTransaction
212    } // end create()
213
214    /**
215    * Updates an existing task.
216    * @param params The params to update for task with id of params.id.
217    * @returns A map containing result.error=true (if any error) and result.taskInstance (if available).
218    */
219    def update(params) {
220        Task.withTransaction { status ->
221            def result = [:]
222
223            def fail = { Object[] args ->
224                status.setRollbackOnly()
225                if(args.size() == 2) result.taskInstance.errors.rejectValue(args[0], args[1])
226                result.error = true
227                return result
228            }
229
230            result.taskInstance = Task.get(params.id)
231
232            if(!result.taskInstance)
233                return fail('id', "task.notFound")
234
235            // Optimistic locking check.
236            if(params.version) {
237                def version = params.version.toLong()
238                if(result.taskInstance.version > version)
239                    return fail("version", "default.optimistic.locking.failure")
240            }
241
242            result.taskInstance.properties = params
243
244            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
245                return fail()
246
247            def taskModification = new TaskModification(person:personService.currentUser,
248                                                    taskModificationType: TaskModificationType.get(3),
249                                                    task: result.taskInstance)
250
251            if(!taskModification.save())
252                return fail("taskModifications", "task.modifications.failedToSave")
253
254            // If we get here all went well.
255            return result
256
257        } //end withTransaction
258    }  // end update()
259
260    /**
261    * Completes an existing task.
262    * @param params The params for task with id of params.id.
263    * @returns A map containing result.error=true (if any error) and result.taskInstance.
264    */
265    def complete(params) {
266        Task.withTransaction { status ->
267            def result = [:]
268            result.taskInstance = Task.get(params.id)
269            if(result.taskInstance) {
270
271                // Optimistic locking check.
272                if(params.version) {
273                    def version = params.version.toLong()
274                    if(result.taskInstance.version > version) {
275                        status.setRollbackOnly()
276                        result.taskInstance.errors.rejectValue("version", "task.optimistic.locking.failure", "Another user has updated this Task while you were editing.")
277                        result.error = true
278                        return result
279                    }
280                }
281
282                result.taskInstance.taskStatus = TaskStatus.get(3)
283                result.taskInstance.taskRecurringSchedule?.enabled = false
284
285                if(result.taskInstance.save()) {
286                    def taskModification = new TaskModification(person:personService.currentUser,
287                                                            taskModificationType: TaskModificationType.get(4),
288                                                            task: result.taskInstance)
289
290                    if(taskModification.save()) {
291                        // All went well.
292                        return result
293                    }
294                    else {
295                        status.setRollbackOnly()
296                        result.taskInstance.errors.rejectValue("taskModifications", "task.modifications.failedToSave")
297                        result.error = true
298                        return result
299                    }
300                }
301            }
302            // Something failed.
303            status.setRollbackOnly()
304            result.error = true
305            return result
306
307        } //end withTransaction
308    }  // end complete()
309
310    /**
311    * Reopens an existing task.
312    * @param params The params for task with id of params.id.
313    * @returns A map containing result.error=true (if any error) and result.taskInstance.
314    */
315    def reopen(params) {
316        Task.withTransaction { status ->
317            def result = [:]
318            result.taskInstance = Task.get(params.id)
319            if(result.taskInstance) {
320
321                // Optimistic locking check.
322                if(params.version) {
323                    def version = params.version.toLong()
324                    if(result.taskInstance.version > version) {
325                        status.setRollbackOnly()
326                        result.taskInstance.errors.rejectValue("version", "task.optimistic.locking.failure", "Another user has updated this Task while you were editing.")
327                        result.error = true
328                        return result
329                    }
330                }
331
332                result.taskInstance.taskStatus = TaskStatus.get(2)
333
334                if(result.taskInstance.save()) {
335                    def taskModification = new TaskModification(person:personService.currentUser,
336                                                            taskModificationType: TaskModificationType.get(5),
337                                                            task: result.taskInstance)
338                    if(taskModification.save()) {
339                        // All went well.
340                        return result
341                    }
342                    else {
343                        status.setRollbackOnly()
344                        result.taskInstance.errors.rejectValue("taskModifications", "task.modifications.failedToSave")
345                        result.error = true
346                        return result
347                    }
348                }
349            }
350            // Something failed.
351            status.setRollbackOnly()
352            result.error = true
353            return result
354
355        } //end withTransaction
356    }  // end reopen()
357
358    /**
359    * Move a task to the trash.
360    * @param params The params for task with id of params.id.
361    * @returns A map containing result.error=true (if any error) and result.taskInstance.
362    */
363    def trash(params) {
364        Task.withTransaction { status ->
365            def result = [:]
366            result.taskInstance = Task.get(params.id)
367            if(result.taskInstance) {
368
369                // Optimistic locking check.
370                if(params.version) {
371                    def version = params.version.toLong()
372                    if(result.taskInstance.version > version) {
373                        status.setRollbackOnly()
374                        result.taskInstance.errors.rejectValue("version", "task.optimistic.locking.failure", "Another user has updated this Task while you were editing.")
375                        result.error = true
376                        return result
377                    }
378                }
379
380                result.taskInstance.trash = true
381                result.taskInstance.taskRecurringSchedule?.enabled = false
382
383                if(result.taskInstance.save()) {
384                    def taskModification = new TaskModification(person:personService.currentUser,
385                                                            taskModificationType: TaskModificationType.get(6),
386                                                            task: result.taskInstance)
387                    if(taskModification.save()) {
388                        // All went well.
389                        return result
390                    }
391                    else {
392                        status.setRollbackOnly()
393                        result.taskInstance.errors.rejectValue("taskModifications", "task.modifications.failedToSave")
394                        result.error = true
395                        return result
396                    }
397                }
398            }
399            // Something failed.
400            status.setRollbackOnly()
401            result.error = true
402            return result
403
404        } //end withTransaction
405    }  // end trash()
406
407    /**
408    * Restore a task from the trash.
409    * @param params The params for task with id of params.id.
410    * @returns A map containing result.error=true (if any error) and result.taskInstance.
411    */
412    def restore(params) {
413        Task.withTransaction { status ->
414            def result = [:]
415            result.taskInstance = Task.get(params.id)
416            if(result.taskInstance) {
417
418                // Optimistic locking check.
419                if(params.version) {
420                    def version = params.version.toLong()
421                    if(result.taskInstance.version > version) {
422                        status.setRollbackOnly()
423                        result.taskInstance.errors.rejectValue("version", "task.optimistic.locking.failure", "Another user has updated this Task while you were editing.")
424                        result.error = true
425                        return result
426                    }
427                }
428
429                result.taskInstance.trash = false
430
431                if(result.taskInstance.save()) {
432                    def taskModification = new TaskModification(person:personService.currentUser,
433                                                            taskModificationType: TaskModificationType.get(7),
434                                                            task: result.taskInstance)
435                    if(taskModification.save()) {
436                        // All went well.
437                        return result
438                    }
439                    else {
440                        status.setRollbackOnly()
441                        result.taskInstance.errors.rejectValue("taskModifications", "task.modifications.failedToSave")
442                        result.error = true
443                        return result
444                    }
445                }
446            }
447            // Something failed.
448            status.setRollbackOnly()
449            result.error = true
450            return result
451
452        } //end withTransaction
453    }  // end restore()
454
455    /**
456    * Approve a task.
457    * @param params The params for task with id of params.id.
458    * @returns A map containing result.error=true (if any error) and result.taskInstance.
459    */
460    def approve(params) {
461        Task.withTransaction { status ->
462            def result = [:]
463            result.taskInstance = Task.get(params.id)
464            if(result.taskInstance) {
465
466                // Optimistic locking check.
467                if(params.version) {
468                    def version = params.version.toLong()
469                    if(result.taskInstance.version > version) {
470                        status.setRollbackOnly()
471                        result.taskInstance.errors.rejectValue("version", "task.optimistic.locking.failure", "Another user has updated this Task while you were editing.")
472                        result.error = true
473                        return result
474                    }
475                }
476
477                result.taskInstance.approved = true
478
479                if(result.taskInstance.save()) {
480                    def taskModification = new TaskModification(person:personService.currentUser,
481                                                            taskModificationType: TaskModificationType.get(8),
482                                                            task: result.taskInstance)
483                    if(taskModification.save()) {
484                        // All went well.
485                        return result
486                    }
487                    else {
488                        status.setRollbackOnly()
489                        result.taskInstance.errors.rejectValue("taskModifications", "task.modifications.failedToSave")
490                        result.error = true
491                        return result
492                    }
493                }
494            }
495            // Something failed.
496            status.setRollbackOnly()
497            result.error = true
498            return result
499
500        } //end withTransaction
501    }  // end approve()
502
503    /**
504    * Remove a previously given approval from a task.
505    * @param params The params for task with id of params.id.
506    * @returns A map containing result.error=true (if any error) and result.taskInstance.
507    */
508    def renegeApproval(params) {
509        Task.withTransaction { status ->
510            def result = [:]
511            result.taskInstance = Task.get(params.id)
512            if(result.taskInstance) {
513
514                // Optimistic locking check.
515                if(params.version) {
516                    def version = params.version.toLong()
517                    if(result.taskInstance.version > version) {
518                        status.setRollbackOnly()
519                        result.taskInstance.errors.rejectValue("version", "task.optimistic.locking.failure", "Another user has updated this Task while you were editing.")
520                        result.error = true
521                        return result
522                    }
523                }
524
525                result.taskInstance.approved = false
526
527                if(result.taskInstance.save()) {
528                    def taskModification = new TaskModification(person:personService.currentUser,
529                                                            taskModificationType: TaskModificationType.get(9),
530                                                            task: result.taskInstance)
531                    if(taskModification.save()) {
532                        // All went well.
533                        return result
534                    }
535                    else {
536                        status.setRollbackOnly()
537                        result.taskInstance.errors.rejectValue("taskModifications", "task.modifications.failedToSave")
538                        result.error = true
539                        return result
540                    }
541                }
542            }
543            // Something failed.
544            status.setRollbackOnly()
545            result.error = true
546            return result
547
548        } //end withTransaction
549    }  // end renegeApproval()
550
551} // end TaskService
Note: See TracBrowser for help on using the repository browser.