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

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

Task trash improvements.
Allow trashed parentTask to break subTask links (only with auth).
Prevent trashing of tasks linked to taskProcedure or Parent PM type tasks.

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