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

Last change on this file since 872 was 851, checked in by gav, 14 years ago

Complete and Flag buttons on ajax task entries, first draft.

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