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

Last change on this file since 913 was 873, checked in by gav, 13 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.