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

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

Domain change, first draft of TaskProcedureRevisions.

File size: 41.7 KB
RevLine 
[510]1import grails.util.Environment
2
[202]3/**
4* Provides a service class for the Task domain class.
[196]5*
6*/
[137]7class TaskService {
8
[180]9    boolean transactional = false
[137]10
[291]11    def authService
[515]12    def dateUtilService
[631]13    def authenticateService
[251]14    def assignedGroupService
15    def assignedPersonService
[137]16
[202]17    /**
[203]18    * Determines and returns a possible parent list for a task.
[245]19    * @todo Create and use another method that limits the results to say the latest 20 or 100 tasks?
[202]20    * @param taskInstance The task to use when determining the possible parent list.
[196]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
[202]34    /**
[433]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    /**
[749]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    /**
[433]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    /**
[196]99    * Creates a new task with the given params.
[202]100    * @param params The params to use when creating the new task.
[418]101    * @returns A map containing result.error (if any error) and result.taskInstance.
[196]102    */
[394]103    def save(params) {
[180]104        Task.withTransaction { status ->
105            def result = [:]
[418]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
[180]115            def taskInstance = new Task(params)
116            result.taskInstance = taskInstance
117
[601]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
[418]130            if(result.taskInstance.parentTask?.trash)
131                return fail(field:"parentTask", code:"task.operationNotPermittedOnTaskInTrash")
[196]132
[418]133            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
134                return fail(code:"default.create.failure")
[180]135
[418]136            def taskModification = new TaskModification(person: authService.currentUser,
137                                                taskModificationType: TaskModificationType.get(1),
138                                                task: taskInstance)
[180]139
[418]140            if(taskModification.hasErrors() || !taskModification.save())
141                return fail(field:"taskModifications", code:"task.modifications.failedToSave")
[243]142
[418]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() {
[251]148
[418]149                    assignedGroupParams = [personGroup: it.personGroup,
150                                                                task: taskInstance,
151                                                                estimatedHour: it.estimatedHour,
152                                                                estimatedMinute: it.estimatedMinute]
[251]153
[418]154                    assignedGroupsResult = assignedGroupService.save(assignedGroupParams)
[251]155
[418]156                    if(assignedGroupsResult.error)
157                        return fail(field:"assignedGroups", code:"task.assignedGroups.failedToSave")
158
[243]159                }
[418]160            }
[243]161
[418]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() {
[243]167
[418]168                    assignedPersonsParams = [person: it.person,
169                                                                task: taskInstance,
170                                                                estimatedHour: it.estimatedHour,
171                                                                estimatedMinute: it.estimatedMinute]
[251]172
[418]173                    assignedPersonsResult = assignedPersonService.save(assignedPersonsParams)
[251]174
[418]175                    if(assignedPersonsResult.error)
176                        return fail(field:"assignedPersons", code:"task.assignedPersons.failedToSave")
[251]177
[243]178                }
[180]179            }
180
[418]181            // Success.
182            return result
183
[180]184        } //end withTransaction
[394]185    } // end save()
[180]186
[202]187    /**
[245]188    * Creates a subTask copying sane attributes from the parentTask unless otherwise specified in params.
[515]189    * The targetStartDate and targetCompletionDate default to today since that is the sane thing to do.
[809]190    * The taskProcedureRevision is only assigned to the sub task if supplied in params.
[245]191    * The assignedPersons and assignedGroups are only added to the sub task if supplied in params.
[592]192    * The positiveFault property is never set on the subTask.
[245]193    * Collections in params must be supplied as new ArrayList's.
194    * This method is not intended to be a copyTask method.
[515]195    * There should be no reason to copy tasks, recurrence can be used to create similar tasks.
[196]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
[592]204        //Make our new Task a subTask and set the required properties.
[196]205        def p = [:]
206        p.parentTask = parentTask
207        p.description = params.description ?: parentTask.description
208        p.comment = params.comment ?: parentTask.comment
[515]209        p.targetStartDate = params.targetStartDate ?: dateUtilService.today
210        p.targetCompletionDate = params.targetCompletionDate ?: dateUtilService.today
[196]211
[592]212        p.safetyRequirement = params.safetyRequirement ?: parentTask.safetyRequirement
[728]213        p.regulatoryRequirement = params.regulatoryRequirement ?: parentTask.regulatoryRequirement
214        p.mandatoryRequirement = params.mandatoryRequirement ?: parentTask.mandatoryRequirement
[592]215
[196]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
[749]219
[196]220        p.taskType = params.taskType ?: parentTask.taskType
[749]221         // Convert "Parent PM" tasks to "Preventative Maintenance" tasks.
222        if(p.taskType.id == 6)
223            p.taskType = TaskType.get(4)
224
[196]225        p.leadPerson = params.leadPerson ?: parentTask.leadPerson
226        p.primaryAsset = params.primaryAsset ?: parentTask.primaryAsset
[245]227        p.associatedAssets = params.associatedAssets ?: new ArrayList(parentTask.associatedAssets) // Collection.
[196]228
[245]229        // Supplied by recurring tasks.
[809]230        if(params.taskProcedureRevision) p.taskProcedureRevision = params.taskProcedureRevision
[245]231        if(params.assignedGroups) p.assignedGroups = params.assignedGroups // Collection.
232        if(params.assignedPersons) p.assignedPersons = params.assignedPersons // Collection.
[202]233
[245]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.
[394]240        result = save(p)
[196]241
[478]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
[196]252    } // end createSubTask()
253
[202]254    /**
[510]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
[514]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
[510]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    /**
[196]315    * Creates a new task entry.
[202]316    * @param params The params to use when creating the new entry.
[196]317    * @returns A map containing result.error=true (if any error), result.entryInstance and result.taskId.
318    */
[394]319    def saveEntry(params) {
[186]320        Task.withTransaction { status ->
321            def result = [:]
[395]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
[186]331            result.entryInstance = new Entry(params)
[291]332            result.entryInstance.enteredBy = authService.currentUser
[180]333
[395]334            def taskInstance
[510]335            if(result.entryInstance.task?.id) {
[186]336                result.taskId = result.entryInstance.task.id
[395]337                taskInstance = Task.lock(result.entryInstance.task.id)
338            }
[186]339
[395]340            if(!taskInstance)
341                return fail(field:"task", code:"task.notFound")
[186]342
[395]343            if(result.entryInstance.hasErrors() || !result.entryInstance.save())
344                return fail(code:"default.create.failure")
[186]345
[395]346            if(taskInstance.taskStatus.id == 3)
347                return fail(field:"task", code:"task.operationNotPermittedOnCompleteTask")
[186]348
[631]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
[510]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)) {
[186]359
[395]360                // Create the "Started" task modification, this provides the "Actual Started Date".
361                def taskModification = new TaskModification(person: authService.currentUser,
[510]362                                                        taskModificationType: TaskModificationType.read(2),
[395]363                                                        task: taskInstance)
[186]364
[395]365                if(taskModification.hasErrors() || !taskModification.save())
366                    return fail(field:"task", code:"task.modifications.failedToSave")
[186]367
[395]368                // Set task status to "In Progress".
[510]369                taskInstance.taskStatus = TaskStatus.read(2)
[186]370
[395]371                if(taskInstance.hasErrors() || !taskInstance.save())
372                    return fail(field:"task", code:"task.failedToSave")
[186]373            }
374
[395]375            // Success.
376            return result
377
[482]378        } // end withTransaction
[394]379    } // end saveEntry()
[186]380
[202]381    /**
382    * Updates an existing task.
383    * @param params The params to update for task with id of params.id.
[418]384    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
[202]385    */
[180]386    def update(params) {
387        Task.withTransaction { status ->
388            def result = [:]
[204]389
[418]390            def fail = { Map m ->
[204]391                status.setRollbackOnly()
[418]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] ]
[204]395                return result
396            }
397
[180]398            result.taskInstance = Task.get(params.id)
399
[204]400            if(!result.taskInstance)
[206]401                return fail('id', "task.notFound")
[180]402
[204]403            // Optimistic locking check.
404            if(params.version) {
[418]405                if(result.taskInstance.version > params.version.toLong())
406                    return fail(field:"version", code:"default.optimistic.locking.failure")
[204]407            }
[180]408
[631]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
[204]415            result.taskInstance.properties = params
416
417            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
[418]418                return fail(code:"default.update.failure")
[204]419
[291]420            def taskModification = new TaskModification(person:authService.currentUser,
[204]421                                                    taskModificationType: TaskModificationType.get(3),
422                                                    task: result.taskInstance)
423
[418]424            if(taskModification.hasErrors() || !taskModification.save())
425                return fail(code:"task.modifications.failedToSave")
[204]426
[418]427            // Success.
[180]428            return result
429
430        } //end withTransaction
431    }  // end update()
432
[202]433    /**
434    * Completes an existing task.
435    * @param params The params for task with id of params.id.
[418]436    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
[202]437    */
[181]438    def complete(params) {
439        Task.withTransaction { status ->
440            def result = [:]
[418]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
[181]450            result.taskInstance = Task.get(params.id)
451
[418]452            if(!result.taskInstance)
453                return fail(code:"default.not.found")
[181]454
[418]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            }
[181]460
[631]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
[418]467            result.taskInstance.taskStatus = TaskStatus.get(3)
468            result.taskInstance.attentionFlag = false
469            result.taskInstance.taskRecurringSchedule?.enabled = false
[201]470
[418]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.
[181]483            return result
484
485        } //end withTransaction
[180]486    }  // end complete()
487
[202]488    /**
[418]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
[631]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
[418]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
[631]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
[418]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    /**
[202]593    * Reopens an existing task.
594    * @param params The params for task with id of params.id.
[418]595    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
[202]596    */
[181]597    def reopen(params) {
598        Task.withTransaction { status ->
599            def result = [:]
[418]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
[181]609            result.taskInstance = Task.get(params.id)
610
[418]611            if(!result.taskInstance)
612                return fail(code:"default.not.found")
[181]613
[418]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            }
[181]619
[631]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
[510]626            def isInProgress = false
627            result.taskInstance.entries.each() {
628                if(it.entryType.id == 3 && (it.durationHour + it.durationMinute > 0) )
629                    isInProgress = true
630            }
[418]631
[510]632            if(isInProgress)
633                result.taskInstance.taskStatus = TaskStatus.read(2) // In Progress
634            else
635                result.taskInstance.taskStatus = TaskStatus.read(1) // Not Started
636
[418]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.
[181]648            return result
649
650        } //end withTransaction
[180]651    }  // end reopen()
652
[202]653    /**
654    * Move a task to the trash.
655    * @param params The params for task with id of params.id.
[418]656    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
[202]657    */
[181]658    def trash(params) {
659        Task.withTransaction { status ->
660            def result = [:]
[418]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
[181]670            result.taskInstance = Task.get(params.id)
671
[418]672            if(!result.taskInstance)
673                return fail(code:"default.not.found")
[181]674
[418]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            }
[181]680
[631]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
[802]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
[809]693            // Check for taskProcedureRevision using this task as linkedTask.
694            if(result.taskInstance.taskProcedureRevision?.linkedTask?.id == result.taskInstance.id) {
695                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
696                    return fail(field:"taskProcedureRevision", code:"task.operationNotPermittedOnTaskLinkedToProcedureWithoutAuth")
697            }
[802]698
699            // Check for Parent PM task type.
700            if(result.taskInstance.taskType.id == 6)
[809]701                return fail(field:"taskType", code:"task.operationNotPermittedOnParentPmTask")
[802]702
[418]703            result.taskInstance.trash = true
704            result.taskInstance.attentionFlag = false
705            result.taskInstance.taskRecurringSchedule?.enabled = false
[802]706            result.taskInstance.subTasks.each {
707                it.parentTask = null
708            }
[418]709
710            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
711                return fail(code:"default.update.failure")
712
713            def taskModification = new TaskModification(person:authService.currentUser,
714                                                    taskModificationType: TaskModificationType.get(6),
715                                                    task: result.taskInstance)
716
717            if(taskModification.hasErrors() || !taskModification.save())
718                return fail(code:"task.modifications.failedToSave")
719
720            // Success.
[181]721            return result
722
723        } //end withTransaction
[180]724    }  // end trash()
725
[202]726    /**
727    * Restore a task from the trash.
728    * @param params The params for task with id of params.id.
[418]729    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
[202]730    */
[181]731    def restore(params) {
732        Task.withTransaction { status ->
733            def result = [:]
[418]734
735            def fail = { Map m ->
736                status.setRollbackOnly()
737                if(result.taskInstance && m.field)
738                    result.taskInstance.errors.rejectValue(m.field, m.code)
739                result.error = [ code: m.code, args: ["Task", params.id] ]
740                return result
741            }
742
[181]743            result.taskInstance = Task.get(params.id)
744
[418]745            if(!result.taskInstance)
746                return fail(code:"default.not.found")
[181]747
[418]748            // Optimistic locking check.
749            if(params.version) {
750                if(result.taskInstance.version > params.version.toLong())
751                    return fail(field:"version", code:"default.optimistic.locking.failure")
752            }
[181]753
[631]754            // Check for authorisation on recurring tasks.
755            if(result.taskInstance.taskRecurringSchedule) {
756                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
757                    return fail(field:"taskRecurringSchedule", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
758            }
759
[418]760            result.taskInstance.trash = false
761
762            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
763                return fail(code:"default.update.failure")
764
765            def taskModification = new TaskModification(person:authService.currentUser,
766                                                    taskModificationType: TaskModificationType.get(7),
767                                                    task: result.taskInstance)
768
769            if(taskModification.hasErrors() || !taskModification.save())
770                return fail(code:"task.modifications.failedToSave")
771
772            // Success.
[181]773            return result
774
775        } //end withTransaction
[180]776    }  // end restore()
777
[202]778    /**
779    * Approve a task.
780    * @param params The params for task with id of params.id.
[418]781    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
[202]782    */
[181]783    def approve(params) {
784        Task.withTransaction { status ->
785            def result = [:]
[418]786
787            def fail = { Map m ->
788                status.setRollbackOnly()
789                if(result.taskInstance && m.field)
790                    result.taskInstance.errors.rejectValue(m.field, m.code)
791                result.error = [ code: m.code, args: ["Task", params.id] ]
792                return result
793            }
794
[181]795            result.taskInstance = Task.get(params.id)
796
[418]797            if(!result.taskInstance)
798                return fail(code:"default.not.found")
[181]799
[418]800            // Optimistic locking check.
801            if(params.version) {
802                if(result.taskInstance.version > params.version.toLong())
803                    return fail(field:"version", code:"default.optimistic.locking.failure")
804            }
[181]805
[631]806            // Check for authorisation on recurring tasks.
807            if(result.taskInstance.taskRecurringSchedule) {
808                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
809                    return fail(field:"taskRecurringSchedule", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
810            }
811
[418]812            result.taskInstance.approved = true
813
814            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
815                return fail(code:"default.update.failure")
816
817            def taskModification = new TaskModification(person:authService.currentUser,
818                                                    taskModificationType: TaskModificationType.get(8),
819                                                    task: result.taskInstance)
820
821            if(taskModification.hasErrors() || !taskModification.save())
822                return fail(code:"task.modifications.failedToSave")
823
824            // Success.
[181]825            return result
826
827        } //end withTransaction
[180]828    }  // end approve()
829
[202]830    /**
831    * Remove a previously given approval from a task.
832    * @param params The params for task with id of params.id.
[418]833    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
[202]834    */
[181]835    def renegeApproval(params) {
836        Task.withTransaction { status ->
837            def result = [:]
[418]838
839            def fail = { Map m ->
840                status.setRollbackOnly()
841                if(result.taskInstance && m.field)
842                    result.taskInstance.errors.rejectValue(m.field, m.code)
843                result.error = [ code: m.code, args: ["Task", params.id] ]
844                return result
845            }
846
[181]847            result.taskInstance = Task.get(params.id)
848
[418]849            if(!result.taskInstance)
850                return fail(code:"default.not.found")
[181]851
[418]852            // Optimistic locking check.
853            if(params.version) {
854                if(result.taskInstance.version > params.version.toLong())
855                    return fail(field:"version", code:"default.optimistic.locking.failure")
856            }
[181]857
[631]858            // Check for authorisation on recurring tasks.
859            if(result.taskInstance.taskRecurringSchedule) {
860                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
861                    return fail(field:"taskRecurringSchedule", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
862            }
863
[418]864            result.taskInstance.approved = false
865
866            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
867                return fail(code:"default.update.failure")
868
869            def taskModification = new TaskModification(person:authService.currentUser,
870                                                    taskModificationType: TaskModificationType.get(9),
871                                                    task: result.taskInstance)
872
873            if(taskModification.hasErrors() || !taskModification.save())
874                return fail(code:"task.modifications.failedToSave")
875
876            // Success.
[181]877            return result
878
879        } //end withTransaction
[180]880    }  // end renegeApproval()
881
[395]882    /**
[433]883    * Creates a new unscheduled breakin task with the given params.
884    * @param params The params to use when creating the new task.
885    * @returns A map containing result.error (if any error) and result.taskInstance.
886    */
887    def saveUnscheduled(params) {
888        Task.withTransaction { status ->
889            def result = [:]
890
891            def fail = { Map m ->
892                status.setRollbackOnly()
893                if(result.taskInstance && m.field)
894                    result.taskInstance.errors.rejectValue(m.field, m.code)
895                result.error = [ code: m.code, args: ["Task", params.id] ]
896                return result
897            }
898
899            // If not supplied.
900            if(!params.taskStatus)
901                params.taskStatus = TaskStatus.get(1) // Not Started.
902
903            result.taskInstance = new Task(params)
904
905            // Always for an unscheduled breakin..
906            result.taskInstance.taskType = TaskType.get(2) // Unscheduled Breakin.
907            result.taskInstance.taskBudgetStatus = TaskBudgetStatus.get(1) // Unplanned.
908
909            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
910                fail(code:"default.create.failure")
911
912            if(!result.error) {
913                def taskModification = new TaskModification(person: authService.currentUser,
914                                                                taskModificationType: TaskModificationType.get(1), // Created.
915                                                                task: result.taskInstance)
916
917                if(taskModification.hasErrors() || !taskModification.save())
918                    fail(field:"taskModifications", code:"task.modifications.failedToSave")
919            }
920
921            // Success.
922            return result
923
924        } //end withTransaction
925    } // end saveUnscheduled()
926
927    /**
[418]928    * Creates a new immediate callout task with the given params.
[395]929    * @param params The params to use when creating the new task.
[418]930    * @returns A map containing result.error (if any error) and result.taskInstance.
[395]931    */
[418]932    def saveImmediateCallout(params) {
[395]933        Task.withTransaction { status ->
934            def result = [:]
935
936            def fail = { Map m ->
937                status.setRollbackOnly()
938                if(result.taskInstance && m.field)
939                    result.taskInstance.errors.rejectValue(m.field, m.code)
940                result.error = [ code: m.code, args: ["Task", params.id] ]
941                return result
942            }
943
944            // If not supplied.
945            if(!params.taskStatus)
946                params.taskStatus = TaskStatus.get(1) // Not Started.
947
948            result.taskInstance = new Task(params)
949
[418]950            // Always for an immediate callout.
951            result.taskInstance.taskType = TaskType.get(1) // Immediate Callout.
[395]952            result.taskInstance.taskBudgetStatus = TaskBudgetStatus.get(1) // Unplanned.
[433]953            result.taskInstance.taskPriority = TaskPriority.get(1) // Immediate.
[395]954            result.taskInstance.taskGroup = TaskGroup.get(1) // Engineering Activites.
955            result.taskInstance.approved = true
956            result.taskInstance.leadPerson = authService.currentUser
[432]957            result.taskInstance.targetCompletionDate = result.taskInstance.targetStartDate
[395]958
959            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
960                fail(code:"default.create.failure")
961
962            if(!result.error) {
963                def taskModification = new TaskModification(person: authService.currentUser,
964                                                                taskModificationType: TaskModificationType.get(1), // Created.
965                                                                task: result.taskInstance)
966
967                if(taskModification.hasErrors() || !taskModification.save())
968                    fail(field:"taskModifications", code:"task.modifications.failedToSave")
969            }
970
[431]971            def productionReference
972            if(params.entryFault.productionReference.id.isLong())
973                productionReference = ProductionReference.get(params.entryFault.productionReference.id.toLong())
974
[395]975            def faultParams = [task: result.taskInstance,
976                                            entryType: EntryType.get(1),
977                                            comment: params.entryFault.comment,
[432]978                                            dateDone: result.taskInstance.targetStartDate,
[431]979                                            productionReference: productionReference,
[395]980                                            durationHour: params.entryFault.durationHour,
981                                            durationMinute: params.entryFault.durationMinute]
982            def faultResult = saveEntry(faultParams)
983            result.entryFaultInstance = faultResult.entryInstance
984
[418]985            def causeParams = [task: result.taskInstance,
986                                            entryType: EntryType.get(2),
[432]987                                            dateDone: result.taskInstance.targetStartDate,
[418]988                                            comment: params.entryCause.comment]
989            def causeResult = saveEntry(causeParams)
990            result.entryCauseInstance = causeResult.entryInstance
991
[395]992            def workDoneParams = [task: result.taskInstance,
[418]993                                                    entryType: EntryType.get(3),
[395]994                                                    comment: params.entryWorkDone.comment,
[432]995                                            dateDone: result.taskInstance.targetStartDate,
[395]996                                                    durationHour: params.entryWorkDone.durationHour,
997                                                    durationMinute: params.entryWorkDone.durationMinute]
998            def workDoneResult = saveEntry(workDoneParams)
999            result.entryWorkDoneInstance = workDoneResult.entryInstance
1000
1001            if(result.error)
1002                return result
1003
[418]1004            if(causeResult.error)
1005                return fail(code: "default.create.failure")
1006
[395]1007            if(faultResult.error)
1008                return fail(code: "default.create.failure")
1009
1010            if(workDoneResult.error)
1011                return fail(code: "default.create.failure")
1012
1013            // Success.
1014            return result
1015
1016        } //end withTransaction
[418]1017    } // end saveImmediateCallout()
[395]1018
[180]1019} // end TaskService
Note: See TracBrowser for help on using the repository browser.