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

Last change on this file since 967 was 873, checked in by gav, 9 years ago

Refactor logic into TaskService.checkCreateEntry().
Prevent entry creation on recurring tasks altogether.
Prevent entry creation other than PM Entries on tasks with a procedure.

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