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

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

Added integration test for TaskSearchService.getPersonsTasks().
Extended TaskService.delete() to handle assignedPersons and assignedGroups.
Use safe collection navigation in AssignedGroupService and AssignedPersonService?.

File size: 35.9 KB
RevLine 
[510]1import grails.util.Environment
2
[202]3/**
4* Provides a service class for the Task domain class.
[196]5*
6*/
[137]7class TaskService {
8
[180]9    boolean transactional = false
[137]10
[291]11    def authService
[251]12    def assignedGroupService
13    def assignedPersonService
[137]14
[202]15    /**
[203]16    * Determines and returns a possible parent list for a task.
[245]17    * @todo Create and use another method that limits the results to say the latest 20 or 100 tasks?
[202]18    * @param taskInstance The task to use when determining the possible parent list.
[196]19    * @returns A list of the possible parents.
20    */
21    def possibleParentList(taskInstance) {
22        def criteria = taskInstance.createCriteria()
23        def possibleParentList = criteria {
24            and {
25                notEqual('trash', true)
26                notEqual('id', taskInstance.id)
27                taskInstance.subTasks.each() { notEqual('id', it.id) }
28                }
29        }
30    }
31
[202]32    /**
[433]33    * Determines and returns a list of possible task types for scheduled tasks.
34    * @returns A list of the possible task types.
35    */
36    def getScheduledTaskTypes() {
37        def criteria = TaskType.createCriteria()
38        def scheduledTaskTypes = criteria {
39            and {
40                eq('isActive', true)
41                gt('id', 2L)
42                }
43        }
44    }
45
46    /**
47    * Determines and returns a list of possible task priorites for Scheduled tasks.
48    * @returns A list of the possible task priorites.
49    */
50    def getScheduledTaskPriorities() {
51        def criteria = TaskPriority.createCriteria()
52        def scheduledTaskPriorities = [:]
53        scheduledTaskPriorities.list = criteria {
54            and {
55                eq('isActive', true)
56                gt('id', 1L)
57                }
58        }
59        scheduledTaskPriorities.default = scheduledTaskPriorities.list.find { it.id == 4L } //  1-Normal.
60        return scheduledTaskPriorities
61    }
62
63    /**
64    * Determines and returns a list of possible task priorites for Unscheduled tasks.
65    * @returns A map containing a list of the possible task priorites and the default priority.
66    */
67    def getUnscheduledTaskPriorities() {
68        def criteria = TaskPriority.createCriteria()
69        def unscheduledTaskPriorities = [:]
70        unscheduledTaskPriorities.list = criteria {
71            and {
72                eq('isActive', true)
73                lt('id', 5L)
74                ne('id', 1L)
75            }
76        }
77        unscheduledTaskPriorities.default = unscheduledTaskPriorities.list.find { it.id == 3L } // 2-High.
78        return unscheduledTaskPriorities
79    }
80
81    /**
[196]82    * Creates a new task with the given params.
[202]83    * @param params The params to use when creating the new task.
[418]84    * @returns A map containing result.error (if any error) and result.taskInstance.
[196]85    */
[394]86    def save(params) {
[180]87        Task.withTransaction { status ->
88            def result = [:]
[418]89
90            def fail = { Map m ->
91                status.setRollbackOnly()
92                if(result.taskInstance && m.field)
93                    result.taskInstance.errors.rejectValue(m.field, m.code)
94                result.error = [ code: m.code, args: ["Task", params.id] ]
95                return result
96            }
97
[181]98            // Default status to "not started" if not supplied.
99            params.taskStatus = params.taskStatus ?: TaskStatus.get(1)
[252]100
101            // Set budgetStatus.
[418]102            if(params.taskType?.id?.toLong() == 1 || params.taskType?.id?.toLong() == 2) // Immediate Callout or Unsheduled Breakin.
[252]103                params.taskBudgetStatus = params.taskBudgetStatus ?: TaskBudgetStatus.get(1) // Unplanned.
104            else
105                params.taskBudgetStatus = params.taskBudgetStatus ?: TaskBudgetStatus.get(2) // Planned.
106
[180]107            def taskInstance = new Task(params)
108            result.taskInstance = taskInstance
109
[418]110            if(result.taskInstance.parentTask?.trash)
111                return fail(field:"parentTask", code:"task.operationNotPermittedOnTaskInTrash")
[196]112
[418]113            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
114                return fail(code:"default.create.failure")
[180]115
[418]116            def taskModification = new TaskModification(person: authService.currentUser,
117                                                taskModificationType: TaskModificationType.get(1),
118                                                task: taskInstance)
[180]119
[418]120            if(taskModification.hasErrors() || !taskModification.save())
121                return fail(field:"taskModifications", code:"task.modifications.failedToSave")
[243]122
[418]123            //Add the assignedGroups, provided by a new ArrayList(task.assignedGroups)
124            if(params.assignedGroups) {
125                def assignedGroupsResult
126                def assignedGroupParams = [:]
127                params.assignedGroups.each() {
[251]128
[418]129                    assignedGroupParams = [personGroup: it.personGroup,
130                                                                task: taskInstance,
131                                                                estimatedHour: it.estimatedHour,
132                                                                estimatedMinute: it.estimatedMinute]
[251]133
[418]134                    assignedGroupsResult = assignedGroupService.save(assignedGroupParams)
[251]135
[418]136                    if(assignedGroupsResult.error)
137                        return fail(field:"assignedGroups", code:"task.assignedGroups.failedToSave")
138
[243]139                }
[418]140            }
[243]141
[418]142            //Add the assignedPersons, provided by a new ArrayList(task.assignedPersons)
143            if(params.assignedPersons) {
144                def assignedPersonsResult
145                def assignedPersonsParams = [:]
146                params.assignedPersons.each() {
[243]147
[418]148                    assignedPersonsParams = [person: it.person,
149                                                                task: taskInstance,
150                                                                estimatedHour: it.estimatedHour,
151                                                                estimatedMinute: it.estimatedMinute]
[251]152
[418]153                    assignedPersonsResult = assignedPersonService.save(assignedPersonsParams)
[251]154
[418]155                    if(assignedPersonsResult.error)
156                        return fail(field:"assignedPersons", code:"task.assignedPersons.failedToSave")
[251]157
[243]158                }
[180]159            }
160
[418]161            // Success.
162            return result
163
[180]164        } //end withTransaction
[394]165    } // end save()
[180]166
[202]167    /**
[245]168    * Creates a subTask copying sane attributes from the parentTask unless otherwise specified in params.
169    * The taskProcedure is only assigned to the sub task if supplied in params.
170    * The assignedPersons and assignedGroups are only added to the sub task if supplied in params.
171    * Collections in params must be supplied as new ArrayList's.
172    * This method is not intended to be a copyTask method.
173    * There should be no reason to copy tasks, try to find a better solution.
[196]174    * @param parentTask The parent task to get attributes from, also set as the parent.
175    * @param params Overrides the parent task values if specified.
176    * @returns A map containing result.error=true (if any error) and result.taskInstance.
177    */
178    def createSubTask(parentTask, params = [:]) {
179
180        def result = [:]
181
182        //Make our new Task a subTask and set the required properites.
183        def p = [:]
184        p.parentTask = parentTask
185        p.description = params.description ?: parentTask.description
186        p.comment = params.comment ?: parentTask.comment
[245]187        p.targetStartDate = params.targetStartDate ?: parentTask.targetStartDate
188        p.targetCompletionDate = params.targetCompletionDate ?: parentTask.targetCompletionDate
[478]189        p.scheduled = params.scheduled ?:  parentTask.scheduled
[196]190
191        p.taskGroup = params.taskGroup ?: parentTask.taskGroup
192        p.taskStatus = TaskStatus.get(1) // A new subTask must always be "Not Started".
193        p.taskPriority = parentTask.taskPriority
194        p.taskType = params.taskType ?: parentTask.taskType
195        p.leadPerson = params.leadPerson ?: parentTask.leadPerson
196        p.primaryAsset = params.primaryAsset ?: parentTask.primaryAsset
[245]197        p.associatedAssets = params.associatedAssets ?: new ArrayList(parentTask.associatedAssets) // Collection.
[196]198
[245]199        // Supplied by recurring tasks.
[202]200        if(params.taskProcedure) p.taskProcedure = params.taskProcedure
[245]201        if(params.assignedGroups) p.assignedGroups = params.assignedGroups // Collection.
202        if(params.assignedPersons) p.assignedPersons = params.assignedPersons // Collection.
[202]203
[245]204        // trash: A new subTask must always have trash=false, which is already the domain class default.
205
206        // These would be considered copying, hence not done.
207        // taskRecurringSchedule, entries, taskModifications, subTasks, inventoryMovements.
208
209        // Create the sub task and return the result.
[394]210        result = save(p)
[196]211
[478]212        // Approve.
213        if(!result.error && parentTask.approved) {
214            p = [:]
215            p.id = result.taskInstance.id
216            approve(p)
217        }
218
219        // Success.
220        return result
221
[196]222    } // end createSubTask()
223
[202]224    /**
[510]225    * In production tasks are NEVER deleted, only the trash flag is set!
226    * However during testing it may be required to delete a task and that
227    * is why this method exists.
228    */
229    def delete(params) {
230        Task.withTransaction { status ->
231            def result = [:]
232
233            def fail = { Map m ->
234                status.setRollbackOnly()
235                if(result.taskInstance && m.field)
236                    result.taskInstance.errors.rejectValue(m.field, m.code)
237                result.error = [ code: m.code, args: ["Task", params.id] ]
238                return result
239            }
240
241            if(Environment.current == Environment.PRODUCTION)
242                return fail(code:"task.delete.failure.production")
243
244            result.taskInstance = Task.get(params.id)
245
246            if(!result.taskInstance)
247                return fail(code:"default.not.found")
248
249            // Handle taskModifications.
250            def taskModifications = TaskModification.findAllByTask(result.taskInstance)
251            taskModifications.each() {
252                result.taskInstance.removeFromTaskModifications(it)
253                it.delete()
254            }
255
[514]256            // Handle assignedPersons.
257            def taskAssignedPersons = AssignedPerson.findAllByTask(result.taskInstance)
258            taskAssignedPersons.each() {
259                result.taskInstance.removeFromAssignedPersons(it)
260                it.delete()
261            }
262
263            // Handle assignedGroups.
264            def taskAssignedGroups = AssignedGroup.findAllByTask(result.taskInstance)
265            taskAssignedGroups.each() {
266                result.taskInstance.removeFromAssignedGroups(it)
267                it.delete()
268            }
269
[510]270            if(result.error)
271                return result
272
273            try {
274                result.taskInstance.delete(flush:true)
275                return result //Success.
276            }
277            catch(org.springframework.dao.DataIntegrityViolationException e) {
278                return fail(code:"default.delete.failure")
279            }
280
281        } // end withTransaction
282    } // delete()
283
284    /**
[196]285    * Creates a new task entry.
[202]286    * @param params The params to use when creating the new entry.
[196]287    * @returns A map containing result.error=true (if any error), result.entryInstance and result.taskId.
288    */
[394]289    def saveEntry(params) {
[186]290        Task.withTransaction { status ->
291            def result = [:]
[395]292
293            def fail = { Map m ->
294                status.setRollbackOnly()
295                if(result.taskInstance && m.field)
296                    result.taskInstance.errors.rejectValue(m.field, m.code)
297                result.error = [ code: m.code, args: ["Entry", params.id] ]
298                return result
299            }
300
[186]301            result.entryInstance = new Entry(params)
[291]302            result.entryInstance.enteredBy = authService.currentUser
[180]303
[395]304            def taskInstance
[510]305            if(result.entryInstance.task?.id) {
[186]306                result.taskId = result.entryInstance.task.id
[395]307                taskInstance = Task.lock(result.entryInstance.task.id)
308            }
[186]309
[395]310            if(!taskInstance)
311                return fail(field:"task", code:"task.notFound")
[186]312
[395]313            if(result.entryInstance.hasErrors() || !result.entryInstance.save())
314                return fail(code:"default.create.failure")
[186]315
[395]316            if(taskInstance.taskStatus.id == 3)
317                return fail(field:"task", code:"task.operationNotPermittedOnCompleteTask")
[186]318
[510]319            // If task status is "Not Started" and entry type is "Work Done" and time has been booked.
320            // Then we create the started modification and set task status.
321            if(taskInstance.taskStatus.id == 1 && result.entryInstance.entryType.id == 3
322                && (result.entryInstance.durationHour + result.entryInstance.durationMinute > 0)) {
[186]323
[395]324                // Create the "Started" task modification, this provides the "Actual Started Date".
325                def taskModification = new TaskModification(person: authService.currentUser,
[510]326                                                        taskModificationType: TaskModificationType.read(2),
[395]327                                                        task: taskInstance)
[186]328
[395]329                if(taskModification.hasErrors() || !taskModification.save())
330                    return fail(field:"task", code:"task.modifications.failedToSave")
[186]331
[395]332                // Set task status to "In Progress".
[510]333                taskInstance.taskStatus = TaskStatus.read(2)
[186]334
[395]335                if(taskInstance.hasErrors() || !taskInstance.save())
336                    return fail(field:"task", code:"task.failedToSave")
[186]337            }
338
[395]339            // Success.
340            return result
341
[482]342        } // end withTransaction
[394]343    } // end saveEntry()
[186]344
[202]345    /**
346    * Updates an existing task.
347    * @param params The params to update for task with id of params.id.
[418]348    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
[202]349    */
[180]350    def update(params) {
351        Task.withTransaction { status ->
352            def result = [:]
[204]353
[418]354            def fail = { Map m ->
[204]355                status.setRollbackOnly()
[418]356                if(result.taskInstance && m.field)
357                    result.taskInstance.errors.rejectValue(m.field, m.code)
358                result.error = [ code: m.code, args: ["Task", params.id] ]
[204]359                return result
360            }
361
[180]362            result.taskInstance = Task.get(params.id)
363
[204]364            if(!result.taskInstance)
[206]365                return fail('id', "task.notFound")
[180]366
[204]367            // Optimistic locking check.
368            if(params.version) {
[418]369                if(result.taskInstance.version > params.version.toLong())
370                    return fail(field:"version", code:"default.optimistic.locking.failure")
[204]371            }
[180]372
[204]373            result.taskInstance.properties = params
374
375            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
[418]376                return fail(code:"default.update.failure")
[204]377
[291]378            def taskModification = new TaskModification(person:authService.currentUser,
[204]379                                                    taskModificationType: TaskModificationType.get(3),
380                                                    task: result.taskInstance)
381
[418]382            if(taskModification.hasErrors() || !taskModification.save())
383                return fail(code:"task.modifications.failedToSave")
[204]384
[418]385            // Success.
[180]386            return result
387
388        } //end withTransaction
389    }  // end update()
390
[202]391    /**
392    * Completes an existing task.
393    * @param params The params for task with id of params.id.
[418]394    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
[202]395    */
[181]396    def complete(params) {
397        Task.withTransaction { status ->
398            def result = [:]
[418]399
400            def fail = { Map m ->
401                status.setRollbackOnly()
402                if(result.taskInstance && m.field)
403                    result.taskInstance.errors.rejectValue(m.field, m.code)
404                result.error = [ code: m.code, args: ["Task", params.id] ]
405                return result
406            }
407
[181]408            result.taskInstance = Task.get(params.id)
409
[418]410            if(!result.taskInstance)
411                return fail(code:"default.not.found")
[181]412
[418]413            // Optimistic locking check.
414            if(params.version) {
415                if(result.taskInstance.version > params.version.toLong())
416                    return fail(field:"version", code:"default.optimistic.locking.failure")
417            }
[181]418
[418]419            result.taskInstance.taskStatus = TaskStatus.get(3)
420            result.taskInstance.attentionFlag = false
421            result.taskInstance.taskRecurringSchedule?.enabled = false
[201]422
[418]423            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
424                return fail(code:"default.update.failure")
425
426            def taskModification = new TaskModification(person:authService.currentUser,
427                                                    taskModificationType: TaskModificationType.get(4),
428                                                    task: result.taskInstance)
429
430
431            if(taskModification.hasErrors() || !taskModification.save())
432                return fail(code:"task.modifications.failedToSave")
433
434            // Success.
[181]435            return result
436
437        } //end withTransaction
[180]438    }  // end complete()
439
[202]440    /**
[418]441    * Sets the attentionFlag on an existing task.
442    * @param params The params for task with id of params.id.
443    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
444    */
445    def setAttentionFlag(params) {
446        Task.withTransaction { status ->
447            def result = [:]
448
449            def fail = { Map m ->
450                status.setRollbackOnly()
451                if(result.taskInstance && m.field)
452                    result.taskInstance.errors.rejectValue(m.field, m.code)
453                result.error = [ code: m.code, args: ["Task", params.id] ]
454                return result
455            }
456
457            result.taskInstance = Task.get(params.id)
458
459            if(!result.taskInstance)
460                return fail(code:"default.not.found")
461
462            // Optimistic locking check.
463            if(params.version) {
464                if(result.taskInstance.version > params.version.toLong())
465                    return fail(field:"version", code:"default.optimistic.locking.failure")
466            }
467
468            result.taskInstance.attentionFlag = true
469
470            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
471                return fail(code:"default.update.failure")
472
473            def taskModification = new TaskModification(person:authService.currentUser,
474                                                    taskModificationType: TaskModificationType.get(12),
475                                                    task: result.taskInstance)
476
477            if(taskModification.hasErrors() || !taskModification.save())
478                return fail(code:"task.modifications.failedToSave")
479
480            // Success.
481            return result
482
483        } //end withTransaction
484    }  // end flag()
485
486    /**
487    * Clears the attentionFlag on an existing task.
488    * @param params The params for task with id of params.id.
489    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
490    */
491    def clearAttentionFlag(params) {
492        Task.withTransaction { status ->
493            def result = [:]
494
495            def fail = { Map m ->
496                status.setRollbackOnly()
497                if(result.taskInstance && m.field)
498                    result.taskInstance.errors.rejectValue(m.field, m.code)
499                result.error = [ code: m.code, args: ["Task", params.id] ]
500                return result
501            }
502
503            result.taskInstance = Task.get(params.id)
504
505            if(!result.taskInstance)
506                return fail(code:"default.not.found")
507
508            // Optimistic locking check.
509            if(params.version) {
510                if(result.taskInstance.version > params.version.toLong())
511                    return fail(field:"version", code:"default.optimistic.locking.failure")
512            }
513
514            result.taskInstance.attentionFlag = false
515
516            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
517                return fail(code:"default.update.failure")
518
519            def taskModification = new TaskModification(person:authService.currentUser,
520                                                    taskModificationType: TaskModificationType.get(13),
521                                                    task: result.taskInstance)
522
523            if(taskModification.hasErrors() || !taskModification.save())
524                return fail(code:"task.modifications.failedToSave")
525
526            // Success.
527            return result
528
529        } //end withTransaction
530    }  // end clearFlag()
531
532    /**
[202]533    * Reopens an existing task.
534    * @param params The params for task with id of params.id.
[418]535    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
[202]536    */
[181]537    def reopen(params) {
538        Task.withTransaction { status ->
539            def result = [:]
[418]540
541            def fail = { Map m ->
542                status.setRollbackOnly()
543                if(result.taskInstance && m.field)
544                    result.taskInstance.errors.rejectValue(m.field, m.code)
545                result.error = [ code: m.code, args: ["Task", params.id] ]
546                return result
547            }
548
[181]549            result.taskInstance = Task.get(params.id)
550
[418]551            if(!result.taskInstance)
552                return fail(code:"default.not.found")
[181]553
[418]554            // Optimistic locking check.
555            if(params.version) {
556                if(result.taskInstance.version > params.version.toLong())
557                    return fail(field:"version", code:"default.optimistic.locking.failure")
558            }
[181]559
[510]560            def isInProgress = false
561            result.taskInstance.entries.each() {
562                if(it.entryType.id == 3 && (it.durationHour + it.durationMinute > 0) )
563                    isInProgress = true
564            }
[418]565
[510]566            if(isInProgress)
567                result.taskInstance.taskStatus = TaskStatus.read(2) // In Progress
568            else
569                result.taskInstance.taskStatus = TaskStatus.read(1) // Not Started
570
[418]571            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
572                return fail(code:"default.update.failure")
573
574            def taskModification = new TaskModification(person:authService.currentUser,
575                                                    taskModificationType: TaskModificationType.get(5),
576                                                    task: result.taskInstance)
577
578            if(taskModification.hasErrors() || !taskModification.save())
579                return fail(code:"task.modifications.failedToSave")
580
581            // Success.
[181]582            return result
583
584        } //end withTransaction
[180]585    }  // end reopen()
586
[202]587    /**
588    * Move a task to the trash.
589    * @param params The params for task with id of params.id.
[418]590    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
[202]591    */
[181]592    def trash(params) {
593        Task.withTransaction { status ->
594            def result = [:]
[418]595
596            def fail = { Map m ->
597                status.setRollbackOnly()
598                if(result.taskInstance && m.field)
599                    result.taskInstance.errors.rejectValue(m.field, m.code)
600                result.error = [ code: m.code, args: ["Task", params.id] ]
601                return result
602            }
603
[181]604            result.taskInstance = Task.get(params.id)
605
[418]606            if(!result.taskInstance)
607                return fail(code:"default.not.found")
[181]608
[418]609            // Optimistic locking check.
610            if(params.version) {
611                if(result.taskInstance.version > params.version.toLong())
612                    return fail(field:"version", code:"default.optimistic.locking.failure")
613            }
[181]614
[418]615            result.taskInstance.trash = true
616            result.taskInstance.attentionFlag = false
617            result.taskInstance.taskRecurringSchedule?.enabled = false
618
619            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
620                return fail(code:"default.update.failure")
621
622            def taskModification = new TaskModification(person:authService.currentUser,
623                                                    taskModificationType: TaskModificationType.get(6),
624                                                    task: result.taskInstance)
625
626            if(taskModification.hasErrors() || !taskModification.save())
627                return fail(code:"task.modifications.failedToSave")
628
629            // Success.
[181]630            return result
631
632        } //end withTransaction
[180]633    }  // end trash()
634
[202]635    /**
636    * Restore a task from the trash.
637    * @param params The params for task with id of params.id.
[418]638    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
[202]639    */
[181]640    def restore(params) {
641        Task.withTransaction { status ->
642            def result = [:]
[418]643
644            def fail = { Map m ->
645                status.setRollbackOnly()
646                if(result.taskInstance && m.field)
647                    result.taskInstance.errors.rejectValue(m.field, m.code)
648                result.error = [ code: m.code, args: ["Task", params.id] ]
649                return result
650            }
651
[181]652            result.taskInstance = Task.get(params.id)
653
[418]654            if(!result.taskInstance)
655                return fail(code:"default.not.found")
[181]656
[418]657            // Optimistic locking check.
658            if(params.version) {
659                if(result.taskInstance.version > params.version.toLong())
660                    return fail(field:"version", code:"default.optimistic.locking.failure")
661            }
[181]662
[418]663            result.taskInstance.trash = false
664
665            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
666                return fail(code:"default.update.failure")
667
668            def taskModification = new TaskModification(person:authService.currentUser,
669                                                    taskModificationType: TaskModificationType.get(7),
670                                                    task: result.taskInstance)
671
672            if(taskModification.hasErrors() || !taskModification.save())
673                return fail(code:"task.modifications.failedToSave")
674
675            // Success.
[181]676            return result
677
678        } //end withTransaction
[180]679    }  // end restore()
680
[202]681    /**
682    * Approve a task.
683    * @param params The params for task with id of params.id.
[418]684    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
[202]685    */
[181]686    def approve(params) {
687        Task.withTransaction { status ->
688            def result = [:]
[418]689
690            def fail = { Map m ->
691                status.setRollbackOnly()
692                if(result.taskInstance && m.field)
693                    result.taskInstance.errors.rejectValue(m.field, m.code)
694                result.error = [ code: m.code, args: ["Task", params.id] ]
695                return result
696            }
697
[181]698            result.taskInstance = Task.get(params.id)
699
[418]700            if(!result.taskInstance)
701                return fail(code:"default.not.found")
[181]702
[418]703            // Optimistic locking check.
704            if(params.version) {
705                if(result.taskInstance.version > params.version.toLong())
706                    return fail(field:"version", code:"default.optimistic.locking.failure")
707            }
[181]708
[418]709            result.taskInstance.approved = true
710
711            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
712                return fail(code:"default.update.failure")
713
714            def taskModification = new TaskModification(person:authService.currentUser,
715                                                    taskModificationType: TaskModificationType.get(8),
716                                                    task: result.taskInstance)
717
718            if(taskModification.hasErrors() || !taskModification.save())
719                return fail(code:"task.modifications.failedToSave")
720
721            // Success.
[181]722            return result
723
724        } //end withTransaction
[180]725    }  // end approve()
726
[202]727    /**
728    * Remove a previously given approval from a task.
729    * @param params The params for task with id of params.id.
[418]730    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
[202]731    */
[181]732    def renegeApproval(params) {
733        Task.withTransaction { status ->
734            def result = [:]
[418]735
736            def fail = { Map m ->
737                status.setRollbackOnly()
738                if(result.taskInstance && m.field)
739                    result.taskInstance.errors.rejectValue(m.field, m.code)
740                result.error = [ code: m.code, args: ["Task", params.id] ]
741                return result
742            }
743
[181]744            result.taskInstance = Task.get(params.id)
745
[418]746            if(!result.taskInstance)
747                return fail(code:"default.not.found")
[181]748
[418]749            // Optimistic locking check.
750            if(params.version) {
751                if(result.taskInstance.version > params.version.toLong())
752                    return fail(field:"version", code:"default.optimistic.locking.failure")
753            }
[181]754
[418]755            result.taskInstance.approved = false
756
757            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
758                return fail(code:"default.update.failure")
759
760            def taskModification = new TaskModification(person:authService.currentUser,
761                                                    taskModificationType: TaskModificationType.get(9),
762                                                    task: result.taskInstance)
763
764            if(taskModification.hasErrors() || !taskModification.save())
765                return fail(code:"task.modifications.failedToSave")
766
767            // Success.
[181]768            return result
769
770        } //end withTransaction
[180]771    }  // end renegeApproval()
772
[395]773    /**
[433]774    * Creates a new unscheduled breakin task with the given params.
775    * @param params The params to use when creating the new task.
776    * @returns A map containing result.error (if any error) and result.taskInstance.
777    */
778    def saveUnscheduled(params) {
779        Task.withTransaction { status ->
780            def result = [:]
781
782            def fail = { Map m ->
783                status.setRollbackOnly()
784                if(result.taskInstance && m.field)
785                    result.taskInstance.errors.rejectValue(m.field, m.code)
786                result.error = [ code: m.code, args: ["Task", params.id] ]
787                return result
788            }
789
790            // If not supplied.
791            if(!params.taskStatus)
792                params.taskStatus = TaskStatus.get(1) // Not Started.
793
794            result.taskInstance = new Task(params)
795
796            // Always for an unscheduled breakin..
797            result.taskInstance.taskType = TaskType.get(2) // Unscheduled Breakin.
798            result.taskInstance.taskBudgetStatus = TaskBudgetStatus.get(1) // Unplanned.
799
800            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
801                fail(code:"default.create.failure")
802
803            if(!result.error) {
804                def taskModification = new TaskModification(person: authService.currentUser,
805                                                                taskModificationType: TaskModificationType.get(1), // Created.
806                                                                task: result.taskInstance)
807
808                if(taskModification.hasErrors() || !taskModification.save())
809                    fail(field:"taskModifications", code:"task.modifications.failedToSave")
810            }
811
812            // Success.
813            return result
814
815        } //end withTransaction
816    } // end saveUnscheduled()
817
818    /**
[418]819    * Creates a new immediate callout task with the given params.
[395]820    * @param params The params to use when creating the new task.
[418]821    * @returns A map containing result.error (if any error) and result.taskInstance.
[395]822    */
[418]823    def saveImmediateCallout(params) {
[395]824        Task.withTransaction { status ->
825            def result = [:]
826
827            def fail = { Map m ->
828                status.setRollbackOnly()
829                if(result.taskInstance && m.field)
830                    result.taskInstance.errors.rejectValue(m.field, m.code)
831                result.error = [ code: m.code, args: ["Task", params.id] ]
832                return result
833            }
834
835            // If not supplied.
836            if(!params.taskStatus)
837                params.taskStatus = TaskStatus.get(1) // Not Started.
838
839            result.taskInstance = new Task(params)
840
[418]841            // Always for an immediate callout.
842            result.taskInstance.taskType = TaskType.get(1) // Immediate Callout.
[395]843            result.taskInstance.taskBudgetStatus = TaskBudgetStatus.get(1) // Unplanned.
[433]844            result.taskInstance.taskPriority = TaskPriority.get(1) // Immediate.
[395]845            result.taskInstance.taskGroup = TaskGroup.get(1) // Engineering Activites.
846            result.taskInstance.approved = true
847            result.taskInstance.leadPerson = authService.currentUser
[432]848            result.taskInstance.targetCompletionDate = result.taskInstance.targetStartDate
[395]849
850            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
851                fail(code:"default.create.failure")
852
853            if(!result.error) {
854                def taskModification = new TaskModification(person: authService.currentUser,
855                                                                taskModificationType: TaskModificationType.get(1), // Created.
856                                                                task: result.taskInstance)
857
858                if(taskModification.hasErrors() || !taskModification.save())
859                    fail(field:"taskModifications", code:"task.modifications.failedToSave")
860            }
861
[431]862            def productionReference
863            if(params.entryFault.productionReference.id.isLong())
864                productionReference = ProductionReference.get(params.entryFault.productionReference.id.toLong())
865
[395]866            def faultParams = [task: result.taskInstance,
867                                            entryType: EntryType.get(1),
868                                            comment: params.entryFault.comment,
[432]869                                            dateDone: result.taskInstance.targetStartDate,
[431]870                                            productionReference: productionReference,
[395]871                                            durationHour: params.entryFault.durationHour,
872                                            durationMinute: params.entryFault.durationMinute]
873            def faultResult = saveEntry(faultParams)
874            result.entryFaultInstance = faultResult.entryInstance
875
[418]876            def causeParams = [task: result.taskInstance,
877                                            entryType: EntryType.get(2),
[432]878                                            dateDone: result.taskInstance.targetStartDate,
[418]879                                            comment: params.entryCause.comment]
880            def causeResult = saveEntry(causeParams)
881            result.entryCauseInstance = causeResult.entryInstance
882
[395]883            def workDoneParams = [task: result.taskInstance,
[418]884                                                    entryType: EntryType.get(3),
[395]885                                                    comment: params.entryWorkDone.comment,
[432]886                                            dateDone: result.taskInstance.targetStartDate,
[395]887                                                    durationHour: params.entryWorkDone.durationHour,
888                                                    durationMinute: params.entryWorkDone.durationMinute]
889            def workDoneResult = saveEntry(workDoneParams)
890            result.entryWorkDoneInstance = workDoneResult.entryInstance
891
892            if(result.error)
893                return result
894
[418]895            if(causeResult.error)
896                return fail(code: "default.create.failure")
897
[395]898            if(faultResult.error)
899                return fail(code: "default.create.failure")
900
901            if(workDoneResult.error)
902                return fail(code: "default.create.failure")
903
904            // Success.
905            return result
906
907        } //end withTransaction
[418]908    } // end saveImmediateCallout()
[395]909
[180]910} // end TaskService
Note: See TracBrowser for help on using the repository browser.