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

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

Update service, controller and view logic to hand Task and Entry highestSeverity.
Also remove associatedAssets from task search panes.

File size: 42.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 taskProcedureRevision 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.taskProcedureRevision) p.taskProcedureRevision = params.taskProcedureRevision
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(taskInstance.taskStatus.id == 3)
344                return fail(field:"task", code:"task.operationNotPermittedOnCompleteTask")
345
346            // Check for authorisation on recurring tasks.
347            if(taskInstance.taskRecurringSchedule) {
348                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
349                    return fail(field:"task", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
350            }
351
352            if(result.entryInstance.hasErrors() || !result.entryInstance.save())
353                return fail(code:"default.create.failure")
354
355            // If task status is "Not Started"
356            // and entry type is "Work Done" or "PM Entry"
357            // and time has been booked.
358            // Then we create the started modification and set task status.
359            if(taskInstance.taskStatus.id == 1
360                && (result.entryInstance.entryType.id == 3 || result.entryInstance.entryType.id == 6)
361                && (result.entryInstance.durationHour + result.entryInstance.durationMinute > 0)) {
362
363                // Create the "Started" task modification, this provides the "Actual Started Date".
364                def taskModification = new TaskModification(person: authService.currentUser,
365                                                        taskModificationType: TaskModificationType.read(2),
366                                                        task: taskInstance)
367
368                if(taskModification.hasErrors() || !taskModification.save())
369                    return fail(field:"task", code:"task.modifications.failedToSave")
370
371                // Set task status to "In Progress".
372                taskInstance.taskStatus = TaskStatus.read(2)
373            }
374
375            // If PM Entry update task.highestSeverity
376            if(result.entryInstance.entryType.id == 6) {
377                def clist = []
378                taskInstance.entries.each { entry ->
379                    if(entry.entryType.id == 6)
380                        clist << entry.highestSeverity
381                }
382
383                if(clist)
384                    taskInstance.highestSeverity = clist.sort{p1,p2 -> p2.id <=> p1.id}[0]
385            }
386
387            if(taskInstance.hasErrors() || !taskInstance.save())
388                return fail(field:"task", code:"task.failedToSave")
389
390            // Success.
391            return result
392
393        } // end withTransaction
394    } // end saveEntry()
395
396    /**
397    * Updates an existing task.
398    * @param params The params to update for task with id of params.id.
399    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
400    */
401    def update(params) {
402        Task.withTransaction { status ->
403            def result = [:]
404
405            def fail = { Map m ->
406                status.setRollbackOnly()
407                if(result.taskInstance && m.field)
408                    result.taskInstance.errors.rejectValue(m.field, m.code)
409                result.error = [ code: m.code, args: ["Task", params.id] ]
410                return result
411            }
412
413            result.taskInstance = Task.get(params.id)
414
415            if(!result.taskInstance)
416                return fail('id', "task.notFound")
417
418            // Optimistic locking check.
419            if(params.version) {
420                if(result.taskInstance.version > params.version.toLong())
421                    return fail(field:"version", code:"default.optimistic.locking.failure")
422            }
423
424            // Check for authorisation on recurring tasks.
425            if(result.taskInstance.taskRecurringSchedule) {
426                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
427                    return fail(field:"taskRecurringSchedule", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
428            }
429
430            result.taskInstance.properties = params
431
432            if(result.taskInstance.taskProcedureRevision?.maintenanceActions && result.taskInstance.isDirty('primaryAsset'))
433                return fail(field:'primaryAsset', code:"tast.operationNotPermittedToChangeAssetWithMaintenanceActions")
434
435            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
436                return fail(code:"default.update.failure")
437
438            def taskModification = new TaskModification(person:authService.currentUser,
439                                                    taskModificationType: TaskModificationType.get(3),
440                                                    task: result.taskInstance)
441
442            if(taskModification.hasErrors() || !taskModification.save())
443                return fail(code:"task.modifications.failedToSave")
444
445            // Success.
446            return result
447
448        } //end withTransaction
449    }  // end update()
450
451    /**
452    * Completes an existing task.
453    * @param params The params for task with id of params.id.
454    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
455    */
456    def complete(params) {
457        Task.withTransaction { status ->
458            def result = [:]
459
460            def fail = { Map m ->
461                status.setRollbackOnly()
462                if(result.taskInstance && m.field)
463                    result.taskInstance.errors.rejectValue(m.field, m.code)
464                result.error = [ code: m.code, args: ["Task", params.id] ]
465                return result
466            }
467
468            result.taskInstance = Task.get(params.id)
469
470            if(!result.taskInstance)
471                return fail(code:"default.not.found")
472
473            // Optimistic locking check.
474            if(params.version) {
475                if(result.taskInstance.version > params.version.toLong())
476                    return fail(field:"version", code:"default.optimistic.locking.failure")
477            }
478
479            // Check for authorisation on recurring tasks.
480            if(result.taskInstance.taskRecurringSchedule) {
481                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
482                    return fail(field:"taskRecurringSchedule", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
483            }
484
485            result.taskInstance.taskStatus = TaskStatus.get(3)
486            result.taskInstance.attentionFlag = false
487            result.taskInstance.taskRecurringSchedule?.enabled = false
488
489            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
490                return fail(code:"default.update.failure")
491
492            def taskModification = new TaskModification(person:authService.currentUser,
493                                                    taskModificationType: TaskModificationType.get(4),
494                                                    task: result.taskInstance)
495
496
497            if(taskModification.hasErrors() || !taskModification.save())
498                return fail(code:"task.modifications.failedToSave")
499
500            // Success.
501            return result
502
503        } //end withTransaction
504    }  // end complete()
505
506    /**
507    * Sets the attentionFlag on an existing task.
508    * @param params The params for task with id of params.id.
509    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
510    */
511    def setAttentionFlag(params) {
512        Task.withTransaction { status ->
513            def result = [:]
514
515            def fail = { Map m ->
516                status.setRollbackOnly()
517                if(result.taskInstance && m.field)
518                    result.taskInstance.errors.rejectValue(m.field, m.code)
519                result.error = [ code: m.code, args: ["Task", params.id] ]
520                return result
521            }
522
523            result.taskInstance = Task.get(params.id)
524
525            if(!result.taskInstance)
526                return fail(code:"default.not.found")
527
528            // Optimistic locking check.
529            if(params.version) {
530                if(result.taskInstance.version > params.version.toLong())
531                    return fail(field:"version", code:"default.optimistic.locking.failure")
532            }
533
534            // Check for authorisation on recurring tasks.
535            if(result.taskInstance.taskRecurringSchedule) {
536                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
537                    return fail(field:"taskRecurringSchedule", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
538            }
539
540            result.taskInstance.attentionFlag = true
541
542            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
543                return fail(code:"default.update.failure")
544
545            def taskModification = new TaskModification(person:authService.currentUser,
546                                                    taskModificationType: TaskModificationType.get(12),
547                                                    task: result.taskInstance)
548
549            if(taskModification.hasErrors() || !taskModification.save())
550                return fail(code:"task.modifications.failedToSave")
551
552            // Success.
553            return result
554
555        } //end withTransaction
556    }  // end flag()
557
558    /**
559    * Clears the attentionFlag on an existing task.
560    * @param params The params for task with id of params.id.
561    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
562    */
563    def clearAttentionFlag(params) {
564        Task.withTransaction { status ->
565            def result = [:]
566
567            def fail = { Map m ->
568                status.setRollbackOnly()
569                if(result.taskInstance && m.field)
570                    result.taskInstance.errors.rejectValue(m.field, m.code)
571                result.error = [ code: m.code, args: ["Task", params.id] ]
572                return result
573            }
574
575            result.taskInstance = Task.get(params.id)
576
577            if(!result.taskInstance)
578                return fail(code:"default.not.found")
579
580            // Optimistic locking check.
581            if(params.version) {
582                if(result.taskInstance.version > params.version.toLong())
583                    return fail(field:"version", code:"default.optimistic.locking.failure")
584            }
585
586            // Check for authorisation on recurring tasks.
587            if(result.taskInstance.taskRecurringSchedule) {
588                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
589                    return fail(field:"taskRecurringSchedule", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
590            }
591
592            result.taskInstance.attentionFlag = false
593
594            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
595                return fail(code:"default.update.failure")
596
597            def taskModification = new TaskModification(person:authService.currentUser,
598                                                    taskModificationType: TaskModificationType.get(13),
599                                                    task: result.taskInstance)
600
601            if(taskModification.hasErrors() || !taskModification.save())
602                return fail(code:"task.modifications.failedToSave")
603
604            // Success.
605            return result
606
607        } //end withTransaction
608    }  // end clearFlag()
609
610    /**
611    * Reopens an existing task.
612    * @param params The params for task with id of params.id.
613    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
614    */
615    def reopen(params) {
616        Task.withTransaction { status ->
617            def result = [:]
618
619            def fail = { Map m ->
620                status.setRollbackOnly()
621                if(result.taskInstance && m.field)
622                    result.taskInstance.errors.rejectValue(m.field, m.code)
623                result.error = [ code: m.code, args: ["Task", params.id] ]
624                return result
625            }
626
627            result.taskInstance = Task.get(params.id)
628
629            if(!result.taskInstance)
630                return fail(code:"default.not.found")
631
632            // Optimistic locking check.
633            if(params.version) {
634                if(result.taskInstance.version > params.version.toLong())
635                    return fail(field:"version", code:"default.optimistic.locking.failure")
636            }
637
638            // Check for authorisation on recurring tasks.
639            if(result.taskInstance.taskRecurringSchedule) {
640                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
641                    return fail(field:"taskRecurringSchedule", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
642            }
643
644            def isInProgress = false
645            result.taskInstance.entries.each() {
646                if(it.entryType.id == 3 && (it.durationHour + it.durationMinute > 0) )
647                    isInProgress = true
648            }
649
650            if(isInProgress)
651                result.taskInstance.taskStatus = TaskStatus.read(2) // In Progress
652            else
653                result.taskInstance.taskStatus = TaskStatus.read(1) // Not Started
654
655            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
656                return fail(code:"default.update.failure")
657
658            def taskModification = new TaskModification(person:authService.currentUser,
659                                                    taskModificationType: TaskModificationType.get(5),
660                                                    task: result.taskInstance)
661
662            if(taskModification.hasErrors() || !taskModification.save())
663                return fail(code:"task.modifications.failedToSave")
664
665            // Success.
666            return result
667
668        } //end withTransaction
669    }  // end reopen()
670
671    /**
672    * Move a task to the trash.
673    * @param params The params for task with id of params.id.
674    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
675    */
676    def trash(params) {
677        Task.withTransaction { status ->
678            def result = [:]
679
680            def fail = { Map m ->
681                status.setRollbackOnly()
682                if(result.taskInstance && m.field)
683                    result.taskInstance.errors.rejectValue(m.field, m.code)
684                result.error = [ code: m.code, args: ["Task", params.id] ]
685                return result
686            }
687
688            result.taskInstance = Task.get(params.id)
689
690            if(!result.taskInstance)
691                return fail(code:"default.not.found")
692
693            // Optimistic locking check.
694            if(params.version) {
695                if(result.taskInstance.version > params.version.toLong())
696                    return fail(field:"version", code:"default.optimistic.locking.failure")
697            }
698
699            // Check for authorisation on recurring tasks.
700            if(result.taskInstance.taskRecurringSchedule) {
701                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
702                    return fail(field:"taskRecurringSchedule", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
703            }
704
705            // Check for authorisation on tasks having subTasks.
706            if(result.taskInstance.subTasks) {
707                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
708                    return fail(field:"subTasks", code:"task.operationNotPermittedOnTaskHavingSubTasksWithoutAuth")
709            }
710
711            // Check for taskProcedureRevision using this task as linkedTask.
712            if(result.taskInstance.taskProcedureRevision?.linkedTask?.id == result.taskInstance.id) {
713                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
714                    return fail(field:"taskProcedureRevision", code:"task.operationNotPermittedOnTaskLinkedToProcedureWithoutAuth")
715            }
716
717            // Check for Parent PM task type.
718            if(result.taskInstance.taskType.id == 6)
719                return fail(field:"taskType", code:"task.operationNotPermittedOnParentPmTask")
720
721            result.taskInstance.trash = true
722            result.taskInstance.attentionFlag = false
723            result.taskInstance.taskRecurringSchedule?.enabled = false
724            result.taskInstance.subTasks.each {
725                it.parentTask = null
726            }
727
728            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
729                return fail(code:"default.update.failure")
730
731            def taskModification = new TaskModification(person:authService.currentUser,
732                                                    taskModificationType: TaskModificationType.get(6),
733                                                    task: result.taskInstance)
734
735            if(taskModification.hasErrors() || !taskModification.save())
736                return fail(code:"task.modifications.failedToSave")
737
738            // Success.
739            return result
740
741        } //end withTransaction
742    }  // end trash()
743
744    /**
745    * Restore a task from the trash.
746    * @param params The params for task with id of params.id.
747    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
748    */
749    def restore(params) {
750        Task.withTransaction { status ->
751            def result = [:]
752
753            def fail = { Map m ->
754                status.setRollbackOnly()
755                if(result.taskInstance && m.field)
756                    result.taskInstance.errors.rejectValue(m.field, m.code)
757                result.error = [ code: m.code, args: ["Task", params.id] ]
758                return result
759            }
760
761            result.taskInstance = Task.get(params.id)
762
763            if(!result.taskInstance)
764                return fail(code:"default.not.found")
765
766            // Optimistic locking check.
767            if(params.version) {
768                if(result.taskInstance.version > params.version.toLong())
769                    return fail(field:"version", code:"default.optimistic.locking.failure")
770            }
771
772            // Check for authorisation on recurring tasks.
773            if(result.taskInstance.taskRecurringSchedule) {
774                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
775                    return fail(field:"taskRecurringSchedule", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
776            }
777
778            result.taskInstance.trash = false
779
780            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
781                return fail(code:"default.update.failure")
782
783            def taskModification = new TaskModification(person:authService.currentUser,
784                                                    taskModificationType: TaskModificationType.get(7),
785                                                    task: result.taskInstance)
786
787            if(taskModification.hasErrors() || !taskModification.save())
788                return fail(code:"task.modifications.failedToSave")
789
790            // Success.
791            return result
792
793        } //end withTransaction
794    }  // end restore()
795
796    /**
797    * Approve a task.
798    * @param params The params for task with id of params.id.
799    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
800    */
801    def approve(params) {
802        Task.withTransaction { status ->
803            def result = [:]
804
805            def fail = { Map m ->
806                status.setRollbackOnly()
807                if(result.taskInstance && m.field)
808                    result.taskInstance.errors.rejectValue(m.field, m.code)
809                result.error = [ code: m.code, args: ["Task", params.id] ]
810                return result
811            }
812
813            result.taskInstance = Task.get(params.id)
814
815            if(!result.taskInstance)
816                return fail(code:"default.not.found")
817
818            // Optimistic locking check.
819            if(params.version) {
820                if(result.taskInstance.version > params.version.toLong())
821                    return fail(field:"version", code:"default.optimistic.locking.failure")
822            }
823
824            // Check for authorisation on recurring tasks.
825            if(result.taskInstance.taskRecurringSchedule) {
826                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
827                    return fail(field:"taskRecurringSchedule", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
828            }
829
830            result.taskInstance.approved = true
831
832            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
833                return fail(code:"default.update.failure")
834
835            def taskModification = new TaskModification(person:authService.currentUser,
836                                                    taskModificationType: TaskModificationType.get(8),
837                                                    task: result.taskInstance)
838
839            if(taskModification.hasErrors() || !taskModification.save())
840                return fail(code:"task.modifications.failedToSave")
841
842            // Success.
843            return result
844
845        } //end withTransaction
846    }  // end approve()
847
848    /**
849    * Remove a previously given approval from a task.
850    * @param params The params for task with id of params.id.
851    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
852    */
853    def renegeApproval(params) {
854        Task.withTransaction { status ->
855            def result = [:]
856
857            def fail = { Map m ->
858                status.setRollbackOnly()
859                if(result.taskInstance && m.field)
860                    result.taskInstance.errors.rejectValue(m.field, m.code)
861                result.error = [ code: m.code, args: ["Task", params.id] ]
862                return result
863            }
864
865            result.taskInstance = Task.get(params.id)
866
867            if(!result.taskInstance)
868                return fail(code:"default.not.found")
869
870            // Optimistic locking check.
871            if(params.version) {
872                if(result.taskInstance.version > params.version.toLong())
873                    return fail(field:"version", code:"default.optimistic.locking.failure")
874            }
875
876            // Check for authorisation on recurring tasks.
877            if(result.taskInstance.taskRecurringSchedule) {
878                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
879                    return fail(field:"taskRecurringSchedule", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
880            }
881
882            result.taskInstance.approved = false
883
884            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
885                return fail(code:"default.update.failure")
886
887            def taskModification = new TaskModification(person:authService.currentUser,
888                                                    taskModificationType: TaskModificationType.get(9),
889                                                    task: result.taskInstance)
890
891            if(taskModification.hasErrors() || !taskModification.save())
892                return fail(code:"task.modifications.failedToSave")
893
894            // Success.
895            return result
896
897        } //end withTransaction
898    }  // end renegeApproval()
899
900    /**
901    * Creates a new unscheduled breakin task with the given params.
902    * @param params The params to use when creating the new task.
903    * @returns A map containing result.error (if any error) and result.taskInstance.
904    */
905    def saveUnscheduled(params) {
906        Task.withTransaction { status ->
907            def result = [:]
908
909            def fail = { Map m ->
910                status.setRollbackOnly()
911                if(result.taskInstance && m.field)
912                    result.taskInstance.errors.rejectValue(m.field, m.code)
913                result.error = [ code: m.code, args: ["Task", params.id] ]
914                return result
915            }
916
917            // If not supplied.
918            if(!params.taskStatus)
919                params.taskStatus = TaskStatus.get(1) // Not Started.
920
921            result.taskInstance = new Task(params)
922
923            // Always for an unscheduled breakin..
924            result.taskInstance.taskType = TaskType.get(2) // Unscheduled Breakin.
925            result.taskInstance.taskBudgetStatus = TaskBudgetStatus.get(1) // Unplanned.
926
927            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
928                fail(code:"default.create.failure")
929
930            if(!result.error) {
931                def taskModification = new TaskModification(person: authService.currentUser,
932                                                                taskModificationType: TaskModificationType.get(1), // Created.
933                                                                task: result.taskInstance)
934
935                if(taskModification.hasErrors() || !taskModification.save())
936                    fail(field:"taskModifications", code:"task.modifications.failedToSave")
937            }
938
939            // Success.
940            return result
941
942        } //end withTransaction
943    } // end saveUnscheduled()
944
945    /**
946    * Creates a new immediate callout task with the given params.
947    * @param params The params to use when creating the new task.
948    * @returns A map containing result.error (if any error) and result.taskInstance.
949    */
950    def saveImmediateCallout(params) {
951        Task.withTransaction { status ->
952            def result = [:]
953
954            def fail = { Map m ->
955                status.setRollbackOnly()
956                if(result.taskInstance && m.field)
957                    result.taskInstance.errors.rejectValue(m.field, m.code)
958                result.error = [ code: m.code, args: ["Task", params.id] ]
959                return result
960            }
961
962            // If not supplied.
963            if(!params.taskStatus)
964                params.taskStatus = TaskStatus.get(1) // Not Started.
965
966            result.taskInstance = new Task(params)
967
968            // Always for an immediate callout.
969            result.taskInstance.taskType = TaskType.get(1) // Immediate Callout.
970            result.taskInstance.taskBudgetStatus = TaskBudgetStatus.get(1) // Unplanned.
971            result.taskInstance.taskPriority = TaskPriority.get(1) // Immediate.
972            result.taskInstance.taskGroup = TaskGroup.get(1) // Engineering Activites.
973            result.taskInstance.approved = true
974            result.taskInstance.leadPerson = authService.currentUser
975            result.taskInstance.targetCompletionDate = result.taskInstance.targetStartDate
976
977            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
978                fail(code:"default.create.failure")
979
980            if(!result.error) {
981                def taskModification = new TaskModification(person: authService.currentUser,
982                                                                taskModificationType: TaskModificationType.get(1), // Created.
983                                                                task: result.taskInstance)
984
985                if(taskModification.hasErrors() || !taskModification.save())
986                    fail(field:"taskModifications", code:"task.modifications.failedToSave")
987            }
988
989            def productionReference
990            if(params.entryFault.productionReference.id.isLong())
991                productionReference = ProductionReference.get(params.entryFault.productionReference.id.toLong())
992
993            def faultParams = [task: result.taskInstance,
994                                            entryType: EntryType.get(1),
995                                            comment: params.entryFault.comment,
996                                            dateDone: result.taskInstance.targetStartDate,
997                                            productionReference: productionReference,
998                                            durationHour: params.entryFault.durationHour,
999                                            durationMinute: params.entryFault.durationMinute]
1000            def faultResult = saveEntry(faultParams)
1001            result.entryFaultInstance = faultResult.entryInstance
1002
1003            def causeParams = [task: result.taskInstance,
1004                                            entryType: EntryType.get(2),
1005                                            dateDone: result.taskInstance.targetStartDate,
1006                                            comment: params.entryCause.comment]
1007            def causeResult = saveEntry(causeParams)
1008            result.entryCauseInstance = causeResult.entryInstance
1009
1010            def workDoneParams = [task: result.taskInstance,
1011                                                    entryType: EntryType.get(3),
1012                                                    comment: params.entryWorkDone.comment,
1013                                            dateDone: result.taskInstance.targetStartDate,
1014                                                    durationHour: params.entryWorkDone.durationHour,
1015                                                    durationMinute: params.entryWorkDone.durationMinute]
1016            def workDoneResult = saveEntry(workDoneParams)
1017            result.entryWorkDoneInstance = workDoneResult.entryInstance
1018
1019            if(result.error)
1020                return result
1021
1022            if(causeResult.error)
1023                return fail(code: "default.create.failure")
1024
1025            if(faultResult.error)
1026                return fail(code: "default.create.failure")
1027
1028            if(workDoneResult.error)
1029                return fail(code: "default.create.failure")
1030
1031            // Success.
1032            return result
1033
1034        } //end withTransaction
1035    } // end saveImmediateCallout()
1036
1037} // end TaskService
Note: See TracBrowser for help on using the repository browser.