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
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(taskInstance.taskStatus.id == 3)
344                return fail(field:"task", code:"task.operationNotPermittedOnCompleteTask")
[186]345
[631]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
[832]352            if(result.entryInstance.hasErrors() || !result.entryInstance.save())
353                return fail(code:"default.create.failure")
354
[838]355            // If task status is "Not Started"
356            // and entry type is "Work Done" or "PM Entry"
357            // and time has been booked.
[510]358            // Then we create the started modification and set task status.
[838]359            if(taskInstance.taskStatus.id == 1
360                && (result.entryInstance.entryType.id == 3 || result.entryInstance.entryType.id == 6)
[510]361                && (result.entryInstance.durationHour + result.entryInstance.durationMinute > 0)) {
[186]362
[395]363                // Create the "Started" task modification, this provides the "Actual Started Date".
364                def taskModification = new TaskModification(person: authService.currentUser,
[510]365                                                        taskModificationType: TaskModificationType.read(2),
[395]366                                                        task: taskInstance)
[186]367
[395]368                if(taskModification.hasErrors() || !taskModification.save())
369                    return fail(field:"task", code:"task.modifications.failedToSave")
[186]370
[395]371                // Set task status to "In Progress".
[510]372                taskInstance.taskStatus = TaskStatus.read(2)
[838]373            }
[186]374
[838]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]
[186]385            }
386
[838]387            if(taskInstance.hasErrors() || !taskInstance.save())
388                return fail(field:"task", code:"task.failedToSave")
389
[395]390            // Success.
391            return result
392
[482]393        } // end withTransaction
[394]394    } // end saveEntry()
[186]395
[202]396    /**
397    * Updates an existing task.
398    * @param params The params to update for task with id of params.id.
[418]399    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
[202]400    */
[180]401    def update(params) {
402        Task.withTransaction { status ->
403            def result = [:]
[204]404
[418]405            def fail = { Map m ->
[204]406                status.setRollbackOnly()
[418]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] ]
[204]410                return result
411            }
412
[180]413            result.taskInstance = Task.get(params.id)
414
[204]415            if(!result.taskInstance)
[206]416                return fail('id', "task.notFound")
[180]417
[204]418            // Optimistic locking check.
419            if(params.version) {
[418]420                if(result.taskInstance.version > params.version.toLong())
421                    return fail(field:"version", code:"default.optimistic.locking.failure")
[204]422            }
[180]423
[631]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
[204]430            result.taskInstance.properties = params
431
[816]432            if(result.taskInstance.taskProcedureRevision?.maintenanceActions && result.taskInstance.isDirty('primaryAsset'))
433                return fail(field:'primaryAsset', code:"tast.operationNotPermittedToChangeAssetWithMaintenanceActions")
434
[204]435            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
[418]436                return fail(code:"default.update.failure")
[204]437
[291]438            def taskModification = new TaskModification(person:authService.currentUser,
[204]439                                                    taskModificationType: TaskModificationType.get(3),
440                                                    task: result.taskInstance)
441
[418]442            if(taskModification.hasErrors() || !taskModification.save())
443                return fail(code:"task.modifications.failedToSave")
[204]444
[418]445            // Success.
[180]446            return result
447
448        } //end withTransaction
449    }  // end update()
450
[202]451    /**
452    * Completes an existing task.
453    * @param params The params for task with id of params.id.
[418]454    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
[202]455    */
[181]456    def complete(params) {
457        Task.withTransaction { status ->
458            def result = [:]
[418]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
[181]468            result.taskInstance = Task.get(params.id)
469
[418]470            if(!result.taskInstance)
471                return fail(code:"default.not.found")
[181]472
[418]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            }
[181]478
[631]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
[418]485            result.taskInstance.taskStatus = TaskStatus.get(3)
486            result.taskInstance.attentionFlag = false
487            result.taskInstance.taskRecurringSchedule?.enabled = false
[201]488
[418]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.
[181]501            return result
502
503        } //end withTransaction
[180]504    }  // end complete()
505
[202]506    /**
[418]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
[631]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
[418]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
[631]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
[418]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    /**
[202]611    * Reopens an existing task.
612    * @param params The params for task with id of params.id.
[418]613    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
[202]614    */
[181]615    def reopen(params) {
616        Task.withTransaction { status ->
617            def result = [:]
[418]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
[181]627            result.taskInstance = Task.get(params.id)
628
[418]629            if(!result.taskInstance)
630                return fail(code:"default.not.found")
[181]631
[418]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            }
[181]637
[631]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
[510]644            def isInProgress = false
645            result.taskInstance.entries.each() {
646                if(it.entryType.id == 3 && (it.durationHour + it.durationMinute > 0) )
647                    isInProgress = true
648            }
[418]649
[510]650            if(isInProgress)
651                result.taskInstance.taskStatus = TaskStatus.read(2) // In Progress
652            else
653                result.taskInstance.taskStatus = TaskStatus.read(1) // Not Started
654
[418]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.
[181]666            return result
667
668        } //end withTransaction
[180]669    }  // end reopen()
670
[202]671    /**
672    * Move a task to the trash.
673    * @param params The params for task with id of params.id.
[418]674    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
[202]675    */
[181]676    def trash(params) {
677        Task.withTransaction { status ->
678            def result = [:]
[418]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
[181]688            result.taskInstance = Task.get(params.id)
689
[418]690            if(!result.taskInstance)
691                return fail(code:"default.not.found")
[181]692
[418]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            }
[181]698
[631]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
[802]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
[809]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            }
[802]716
717            // Check for Parent PM task type.
718            if(result.taskInstance.taskType.id == 6)
[809]719                return fail(field:"taskType", code:"task.operationNotPermittedOnParentPmTask")
[802]720
[418]721            result.taskInstance.trash = true
722            result.taskInstance.attentionFlag = false
723            result.taskInstance.taskRecurringSchedule?.enabled = false
[802]724            result.taskInstance.subTasks.each {
725                it.parentTask = null
726            }
[418]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.
[181]739            return result
740
741        } //end withTransaction
[180]742    }  // end trash()
743
[202]744    /**
745    * Restore a task from the trash.
746    * @param params The params for task with id of params.id.
[418]747    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
[202]748    */
[181]749    def restore(params) {
750        Task.withTransaction { status ->
751            def result = [:]
[418]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
[181]761            result.taskInstance = Task.get(params.id)
762
[418]763            if(!result.taskInstance)
764                return fail(code:"default.not.found")
[181]765
[418]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            }
[181]771
[631]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
[418]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.
[181]791            return result
792
793        } //end withTransaction
[180]794    }  // end restore()
795
[202]796    /**
797    * Approve a task.
798    * @param params The params for task with id of params.id.
[418]799    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
[202]800    */
[181]801    def approve(params) {
802        Task.withTransaction { status ->
803            def result = [:]
[418]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
[181]813            result.taskInstance = Task.get(params.id)
814
[418]815            if(!result.taskInstance)
816                return fail(code:"default.not.found")
[181]817
[418]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            }
[181]823
[631]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
[418]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.
[181]843            return result
844
845        } //end withTransaction
[180]846    }  // end approve()
847
[202]848    /**
849    * Remove a previously given approval from a task.
850    * @param params The params for task with id of params.id.
[418]851    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
[202]852    */
[181]853    def renegeApproval(params) {
854        Task.withTransaction { status ->
855            def result = [:]
[418]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
[181]865            result.taskInstance = Task.get(params.id)
866
[418]867            if(!result.taskInstance)
868                return fail(code:"default.not.found")
[181]869
[418]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            }
[181]875
[631]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
[418]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.
[181]895            return result
896
897        } //end withTransaction
[180]898    }  // end renegeApproval()
899
[395]900    /**
[433]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    /**
[418]946    * Creates a new immediate callout task with the given params.
[395]947    * @param params The params to use when creating the new task.
[418]948    * @returns A map containing result.error (if any error) and result.taskInstance.
[395]949    */
[418]950    def saveImmediateCallout(params) {
[395]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
[418]968            // Always for an immediate callout.
969            result.taskInstance.taskType = TaskType.get(1) // Immediate Callout.
[395]970            result.taskInstance.taskBudgetStatus = TaskBudgetStatus.get(1) // Unplanned.
[433]971            result.taskInstance.taskPriority = TaskPriority.get(1) // Immediate.
[395]972            result.taskInstance.taskGroup = TaskGroup.get(1) // Engineering Activites.
973            result.taskInstance.approved = true
974            result.taskInstance.leadPerson = authService.currentUser
[432]975            result.taskInstance.targetCompletionDate = result.taskInstance.targetStartDate
[395]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
[431]989            def productionReference
990            if(params.entryFault.productionReference.id.isLong())
991                productionReference = ProductionReference.get(params.entryFault.productionReference.id.toLong())
992
[395]993            def faultParams = [task: result.taskInstance,
994                                            entryType: EntryType.get(1),
995                                            comment: params.entryFault.comment,
[432]996                                            dateDone: result.taskInstance.targetStartDate,
[431]997                                            productionReference: productionReference,
[395]998                                            durationHour: params.entryFault.durationHour,
999                                            durationMinute: params.entryFault.durationMinute]
1000            def faultResult = saveEntry(faultParams)
1001            result.entryFaultInstance = faultResult.entryInstance
1002
[418]1003            def causeParams = [task: result.taskInstance,
1004                                            entryType: EntryType.get(2),
[432]1005                                            dateDone: result.taskInstance.targetStartDate,
[418]1006                                            comment: params.entryCause.comment]
1007            def causeResult = saveEntry(causeParams)
1008            result.entryCauseInstance = causeResult.entryInstance
1009
[395]1010            def workDoneParams = [task: result.taskInstance,
[418]1011                                                    entryType: EntryType.get(3),
[395]1012                                                    comment: params.entryWorkDone.comment,
[432]1013                                            dateDone: result.taskInstance.targetStartDate,
[395]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
[418]1022            if(causeResult.error)
1023                return fail(code: "default.create.failure")
1024
[395]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
[418]1035    } // end saveImmediateCallout()
[395]1036
[180]1037} // end TaskService
Note: See TracBrowser for help on using the repository browser.