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

Last change on this file since 430 was 418, checked in by gav, 15 years ago

Add attentionFlag to Task domain along with views and logic to suite.
Add entry type 'cause', refactor as required.
Refactor task types.
Move createBreakin to createImmediateCallout.

File size: 29.3 KB
Line 
1/**
2* Provides a service class for the Task domain class.
3*
4*/
5class TaskService {
6
7    boolean transactional = false
8
9    def authService
10    def assignedGroupService
11    def assignedPersonService
12
13    /**
14    * Determines and returns a possible parent list for a task.
15    * @todo Create and use another method that limits the results to say the latest 20 or 100 tasks?
16    * @param taskInstance The task to use when determining the possible parent list.
17    * @returns A list of the possible parents.
18    */
19    def possibleParentList(taskInstance) {
20        def criteria = taskInstance.createCriteria()
21        def possibleParentList = criteria {
22            and {
23                notEqual('trash', true)
24                notEqual('id', taskInstance.id)
25                taskInstance.subTasks.each() { notEqual('id', it.id) }
26                }
27        }
28    }
29
30    /**
31    * Creates a new task with the given params.
32    * @param params The params to use when creating the new task.
33    * @returns A map containing result.error (if any error) and result.taskInstance.
34    */
35    def save(params) {
36        Task.withTransaction { status ->
37            def result = [:]
38
39            def fail = { Map m ->
40                status.setRollbackOnly()
41                if(result.taskInstance && m.field)
42                    result.taskInstance.errors.rejectValue(m.field, m.code)
43                result.error = [ code: m.code, args: ["Task", params.id] ]
44                return result
45            }
46
47            // Default status to "not started" if not supplied.
48            params.taskStatus = params.taskStatus ?: TaskStatus.get(1)
49
50            // Set budgetStatus.
51            if(params.taskType?.id?.toLong() == 1 || params.taskType?.id?.toLong() == 2) // Immediate Callout or Unsheduled Breakin.
52                params.taskBudgetStatus = params.taskBudgetStatus ?: TaskBudgetStatus.get(1) // Unplanned.
53            else
54                params.taskBudgetStatus = params.taskBudgetStatus ?: TaskBudgetStatus.get(2) // Planned.
55
56            def taskInstance = new Task(params)
57            result.taskInstance = taskInstance
58
59            if(result.taskInstance.parentTask?.trash)
60                return fail(field:"parentTask", code:"task.operationNotPermittedOnTaskInTrash")
61
62            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
63                return fail(code:"default.create.failure")
64
65            def taskModification = new TaskModification(person: authService.currentUser,
66                                                taskModificationType: TaskModificationType.get(1),
67                                                task: taskInstance)
68
69            if(taskModification.hasErrors() || !taskModification.save())
70                return fail(field:"taskModifications", code:"task.modifications.failedToSave")
71
72            //Add the assignedGroups, provided by a new ArrayList(task.assignedGroups)
73            if(params.assignedGroups) {
74                def assignedGroupsResult
75                def assignedGroupParams = [:]
76                params.assignedGroups.each() {
77
78                    assignedGroupParams = [personGroup: it.personGroup,
79                                                                task: taskInstance,
80                                                                estimatedHour: it.estimatedHour,
81                                                                estimatedMinute: it.estimatedMinute]
82
83                    assignedGroupsResult = assignedGroupService.save(assignedGroupParams)
84
85                    if(assignedGroupsResult.error)
86                        return fail(field:"assignedGroups", code:"task.assignedGroups.failedToSave")
87
88                }
89            }
90
91            //Add the assignedPersons, provided by a new ArrayList(task.assignedPersons)
92            if(params.assignedPersons) {
93                def assignedPersonsResult
94                def assignedPersonsParams = [:]
95                params.assignedPersons.each() {
96
97                    assignedPersonsParams = [person: it.person,
98                                                                task: taskInstance,
99                                                                estimatedHour: it.estimatedHour,
100                                                                estimatedMinute: it.estimatedMinute]
101
102                    assignedPersonsResult = assignedPersonService.save(assignedPersonsParams)
103
104                    if(assignedPersonsResult.error)
105                        return fail(field:"assignedPersons", code:"task.assignedPersons.failedToSave")
106
107                }
108            }
109
110            // Success.
111            return result
112
113        } //end withTransaction
114    } // end save()
115
116    /**
117    * Creates a subTask copying sane attributes from the parentTask unless otherwise specified in params.
118    * The taskProcedure is only assigned to the sub task if supplied in params.
119    * The assignedPersons and assignedGroups are only added to the sub task if supplied in params.
120    * Collections in params must be supplied as new ArrayList's.
121    * This method is not intended to be a copyTask method.
122    * There should be no reason to copy tasks, try to find a better solution.
123    * @param parentTask The parent task to get attributes from, also set as the parent.
124    * @param params Overrides the parent task values if specified.
125    * @returns A map containing result.error=true (if any error) and result.taskInstance.
126    */
127    def createSubTask(parentTask, params = [:]) {
128
129        def result = [:]
130
131        //Make our new Task a subTask and set the required properites.
132        def p = [:]
133        p.parentTask = parentTask
134        p.description = params.description ?: parentTask.description
135        p.comment = params.comment ?: parentTask.comment
136        p.targetStartDate = params.targetStartDate ?: parentTask.targetStartDate
137        p.targetCompletionDate = params.targetCompletionDate ?: parentTask.targetCompletionDate
138
139        p.taskGroup = params.taskGroup ?: parentTask.taskGroup
140        p.taskStatus = TaskStatus.get(1) // A new subTask must always be "Not Started".
141        p.taskPriority = parentTask.taskPriority
142        p.taskType = params.taskType ?: parentTask.taskType
143        p.leadPerson = params.leadPerson ?: parentTask.leadPerson
144        p.primaryAsset = params.primaryAsset ?: parentTask.primaryAsset
145        p.associatedAssets = params.associatedAssets ?: new ArrayList(parentTask.associatedAssets) // Collection.
146
147        // Only if supplied, otherwise this would be copying.
148        if(params.scheduled) p.scheduled = params.scheduled
149        if(params.approved) p.approved = params.approved
150
151        // Supplied by recurring tasks.
152        if(params.taskProcedure) p.taskProcedure = params.taskProcedure
153        if(params.assignedGroups) p.assignedGroups = params.assignedGroups // Collection.
154        if(params.assignedPersons) p.assignedPersons = params.assignedPersons // Collection.
155
156        // trash: A new subTask must always have trash=false, which is already the domain class default.
157
158        // These would be considered copying, hence not done.
159        // taskRecurringSchedule, entries, taskModifications, subTasks, inventoryMovements.
160
161        // Create the sub task and return the result.
162        result = save(p)
163
164    } // end createSubTask()
165
166    /**
167    * Creates a new task entry.
168    * @param params The params to use when creating the new entry.
169    * @returns A map containing result.error=true (if any error), result.entryInstance and result.taskId.
170    */
171    def saveEntry(params) {
172        Task.withTransaction { status ->
173            def result = [:]
174
175            def fail = { Map m ->
176                status.setRollbackOnly()
177                if(result.taskInstance && m.field)
178                    result.taskInstance.errors.rejectValue(m.field, m.code)
179                result.error = [ code: m.code, args: ["Entry", params.id] ]
180                return result
181            }
182
183            result.entryInstance = new Entry(params)
184            result.entryInstance.enteredBy = authService.currentUser
185
186            def taskInstance
187            if(result.entryInstance.task.id) {
188                result.taskId = result.entryInstance.task.id
189                taskInstance = Task.lock(result.entryInstance.task.id)
190            }
191
192            if(!taskInstance)
193                return fail(field:"task", code:"task.notFound")
194
195            if(result.entryInstance.hasErrors() || !result.entryInstance.save())
196                return fail(code:"default.create.failure")
197
198            if(taskInstance.taskStatus.id == 3)
199                return fail(field:"task", code:"task.operationNotPermittedOnCompleteTask")
200
201            // If task status is "Not Started" and entry type is "Work Done" then we create the started modification and set the status.
202            if(taskInstance.taskStatus.id == 1 && result.entryInstance.entryType.id == 3) {
203
204                // Create the "Started" task modification, this provides the "Actual Started Date".
205                def taskModification = new TaskModification(person: authService.currentUser,
206                                                        taskModificationType: TaskModificationType.get(2),
207                                                        task: taskInstance)
208
209                if(taskModification.hasErrors() || !taskModification.save())
210                    return fail(field:"task", code:"task.modifications.failedToSave")
211
212                // Set task status to "In Progress".
213                taskInstance.taskStatus = TaskStatus.get(2)
214
215                if(taskInstance.hasErrors() || !taskInstance.save())
216                    return fail(field:"task", code:"task.failedToSave")
217            }
218
219            if(result.entryInstance.hasErrors() || !result.entryInstance.save())
220                return fail(field:"task", code:"default.create.failure")
221
222            // Success.
223            return result
224
225        } //end withTransaction
226    } // end saveEntry()
227
228    /**
229    * Updates an existing task.
230    * @param params The params to update for task with id of params.id.
231    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
232    */
233    def update(params) {
234        Task.withTransaction { status ->
235            def result = [:]
236
237            def fail = { Map m ->
238                status.setRollbackOnly()
239                if(result.taskInstance && m.field)
240                    result.taskInstance.errors.rejectValue(m.field, m.code)
241                result.error = [ code: m.code, args: ["Task", params.id] ]
242                return result
243            }
244
245            result.taskInstance = Task.get(params.id)
246
247            if(!result.taskInstance)
248                return fail('id', "task.notFound")
249
250            // Optimistic locking check.
251            if(params.version) {
252                if(result.taskInstance.version > params.version.toLong())
253                    return fail(field:"version", code:"default.optimistic.locking.failure")
254            }
255
256            result.taskInstance.properties = params
257
258            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
259                return fail(code:"default.update.failure")
260
261            def taskModification = new TaskModification(person:authService.currentUser,
262                                                    taskModificationType: TaskModificationType.get(3),
263                                                    task: result.taskInstance)
264
265            if(taskModification.hasErrors() || !taskModification.save())
266                return fail(code:"task.modifications.failedToSave")
267
268            // Success.
269            return result
270
271        } //end withTransaction
272    }  // end update()
273
274    /**
275    * Completes an existing task.
276    * @param params The params for task with id of params.id.
277    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
278    */
279    def complete(params) {
280        Task.withTransaction { status ->
281            def result = [:]
282
283            def fail = { Map m ->
284                status.setRollbackOnly()
285                if(result.taskInstance && m.field)
286                    result.taskInstance.errors.rejectValue(m.field, m.code)
287                result.error = [ code: m.code, args: ["Task", params.id] ]
288                return result
289            }
290
291            result.taskInstance = Task.get(params.id)
292
293            if(!result.taskInstance)
294                return fail(code:"default.not.found")
295
296            // Optimistic locking check.
297            if(params.version) {
298                if(result.taskInstance.version > params.version.toLong())
299                    return fail(field:"version", code:"default.optimistic.locking.failure")
300            }
301
302            result.taskInstance.taskStatus = TaskStatus.get(3)
303            result.taskInstance.attentionFlag = false
304            result.taskInstance.taskRecurringSchedule?.enabled = false
305
306            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
307                return fail(code:"default.update.failure")
308
309            def taskModification = new TaskModification(person:authService.currentUser,
310                                                    taskModificationType: TaskModificationType.get(4),
311                                                    task: result.taskInstance)
312
313
314            if(taskModification.hasErrors() || !taskModification.save())
315                return fail(code:"task.modifications.failedToSave")
316
317            // Success.
318            return result
319
320        } //end withTransaction
321    }  // end complete()
322
323    /**
324    * Sets the attentionFlag on an existing task.
325    * @param params The params for task with id of params.id.
326    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
327    */
328    def setAttentionFlag(params) {
329        Task.withTransaction { status ->
330            def result = [:]
331
332            def fail = { Map m ->
333                status.setRollbackOnly()
334                if(result.taskInstance && m.field)
335                    result.taskInstance.errors.rejectValue(m.field, m.code)
336                result.error = [ code: m.code, args: ["Task", params.id] ]
337                return result
338            }
339
340            result.taskInstance = Task.get(params.id)
341
342            if(!result.taskInstance)
343                return fail(code:"default.not.found")
344
345            // Optimistic locking check.
346            if(params.version) {
347                if(result.taskInstance.version > params.version.toLong())
348                    return fail(field:"version", code:"default.optimistic.locking.failure")
349            }
350
351            result.taskInstance.attentionFlag = true
352
353            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
354                return fail(code:"default.update.failure")
355
356            def taskModification = new TaskModification(person:authService.currentUser,
357                                                    taskModificationType: TaskModificationType.get(12),
358                                                    task: result.taskInstance)
359
360            if(taskModification.hasErrors() || !taskModification.save())
361                return fail(code:"task.modifications.failedToSave")
362
363            // Success.
364            return result
365
366        } //end withTransaction
367    }  // end flag()
368
369    /**
370    * Clears the attentionFlag on an existing task.
371    * @param params The params for task with id of params.id.
372    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
373    */
374    def clearAttentionFlag(params) {
375        Task.withTransaction { status ->
376            def result = [:]
377
378            def fail = { Map m ->
379                status.setRollbackOnly()
380                if(result.taskInstance && m.field)
381                    result.taskInstance.errors.rejectValue(m.field, m.code)
382                result.error = [ code: m.code, args: ["Task", params.id] ]
383                return result
384            }
385
386            result.taskInstance = Task.get(params.id)
387
388            if(!result.taskInstance)
389                return fail(code:"default.not.found")
390
391            // Optimistic locking check.
392            if(params.version) {
393                if(result.taskInstance.version > params.version.toLong())
394                    return fail(field:"version", code:"default.optimistic.locking.failure")
395            }
396
397            result.taskInstance.attentionFlag = false
398
399            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
400                return fail(code:"default.update.failure")
401
402            def taskModification = new TaskModification(person:authService.currentUser,
403                                                    taskModificationType: TaskModificationType.get(13),
404                                                    task: result.taskInstance)
405
406            if(taskModification.hasErrors() || !taskModification.save())
407                return fail(code:"task.modifications.failedToSave")
408
409            // Success.
410            return result
411
412        } //end withTransaction
413    }  // end clearFlag()
414
415    /**
416    * Reopens an existing task.
417    * @param params The params for task with id of params.id.
418    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
419    */
420    def reopen(params) {
421        Task.withTransaction { status ->
422            def result = [:]
423
424            def fail = { Map m ->
425                status.setRollbackOnly()
426                if(result.taskInstance && m.field)
427                    result.taskInstance.errors.rejectValue(m.field, m.code)
428                result.error = [ code: m.code, args: ["Task", params.id] ]
429                return result
430            }
431
432            result.taskInstance = Task.get(params.id)
433
434            if(!result.taskInstance)
435                return fail(code:"default.not.found")
436
437            // Optimistic locking check.
438            if(params.version) {
439                if(result.taskInstance.version > params.version.toLong())
440                    return fail(field:"version", code:"default.optimistic.locking.failure")
441            }
442
443            result.taskInstance.taskStatus = TaskStatus.get(2)
444
445            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
446                return fail(code:"default.update.failure")
447
448            def taskModification = new TaskModification(person:authService.currentUser,
449                                                    taskModificationType: TaskModificationType.get(5),
450                                                    task: result.taskInstance)
451
452            if(taskModification.hasErrors() || !taskModification.save())
453                return fail(code:"task.modifications.failedToSave")
454
455            // Success.
456            return result
457
458        } //end withTransaction
459    }  // end reopen()
460
461    /**
462    * Move a task to the trash.
463    * @param params The params for task with id of params.id.
464    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
465    */
466    def trash(params) {
467        Task.withTransaction { status ->
468            def result = [:]
469
470            def fail = { Map m ->
471                status.setRollbackOnly()
472                if(result.taskInstance && m.field)
473                    result.taskInstance.errors.rejectValue(m.field, m.code)
474                result.error = [ code: m.code, args: ["Task", params.id] ]
475                return result
476            }
477
478            result.taskInstance = Task.get(params.id)
479
480            if(!result.taskInstance)
481                return fail(code:"default.not.found")
482
483            // Optimistic locking check.
484            if(params.version) {
485                if(result.taskInstance.version > params.version.toLong())
486                    return fail(field:"version", code:"default.optimistic.locking.failure")
487            }
488
489            result.taskInstance.trash = true
490            result.taskInstance.attentionFlag = false
491            result.taskInstance.taskRecurringSchedule?.enabled = false
492
493            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
494                return fail(code:"default.update.failure")
495
496            def taskModification = new TaskModification(person:authService.currentUser,
497                                                    taskModificationType: TaskModificationType.get(6),
498                                                    task: result.taskInstance)
499
500            if(taskModification.hasErrors() || !taskModification.save())
501                return fail(code:"task.modifications.failedToSave")
502
503            // Success.
504            return result
505
506        } //end withTransaction
507    }  // end trash()
508
509    /**
510    * Restore a task from the trash.
511    * @param params The params for task with id of params.id.
512    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
513    */
514    def restore(params) {
515        Task.withTransaction { status ->
516            def result = [:]
517
518            def fail = { Map m ->
519                status.setRollbackOnly()
520                if(result.taskInstance && m.field)
521                    result.taskInstance.errors.rejectValue(m.field, m.code)
522                result.error = [ code: m.code, args: ["Task", params.id] ]
523                return result
524            }
525
526            result.taskInstance = Task.get(params.id)
527
528            if(!result.taskInstance)
529                return fail(code:"default.not.found")
530
531            // Optimistic locking check.
532            if(params.version) {
533                if(result.taskInstance.version > params.version.toLong())
534                    return fail(field:"version", code:"default.optimistic.locking.failure")
535            }
536
537            result.taskInstance.trash = false
538
539            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
540                return fail(code:"default.update.failure")
541
542            def taskModification = new TaskModification(person:authService.currentUser,
543                                                    taskModificationType: TaskModificationType.get(7),
544                                                    task: result.taskInstance)
545
546            if(taskModification.hasErrors() || !taskModification.save())
547                return fail(code:"task.modifications.failedToSave")
548
549            // Success.
550            return result
551
552        } //end withTransaction
553    }  // end restore()
554
555    /**
556    * Approve a task.
557    * @param params The params for task with id of params.id.
558    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
559    */
560    def approve(params) {
561        Task.withTransaction { status ->
562            def result = [:]
563
564            def fail = { Map m ->
565                status.setRollbackOnly()
566                if(result.taskInstance && m.field)
567                    result.taskInstance.errors.rejectValue(m.field, m.code)
568                result.error = [ code: m.code, args: ["Task", params.id] ]
569                return result
570            }
571
572            result.taskInstance = Task.get(params.id)
573
574            if(!result.taskInstance)
575                return fail(code:"default.not.found")
576
577            // Optimistic locking check.
578            if(params.version) {
579                if(result.taskInstance.version > params.version.toLong())
580                    return fail(field:"version", code:"default.optimistic.locking.failure")
581            }
582
583            result.taskInstance.approved = true
584
585            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
586                return fail(code:"default.update.failure")
587
588            def taskModification = new TaskModification(person:authService.currentUser,
589                                                    taskModificationType: TaskModificationType.get(8),
590                                                    task: result.taskInstance)
591
592            if(taskModification.hasErrors() || !taskModification.save())
593                return fail(code:"task.modifications.failedToSave")
594
595            // Success.
596            return result
597
598        } //end withTransaction
599    }  // end approve()
600
601    /**
602    * Remove a previously given approval from a task.
603    * @param params The params for task with id of params.id.
604    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
605    */
606    def renegeApproval(params) {
607        Task.withTransaction { status ->
608            def result = [:]
609
610            def fail = { Map m ->
611                status.setRollbackOnly()
612                if(result.taskInstance && m.field)
613                    result.taskInstance.errors.rejectValue(m.field, m.code)
614                result.error = [ code: m.code, args: ["Task", params.id] ]
615                return result
616            }
617
618            result.taskInstance = Task.get(params.id)
619
620            if(!result.taskInstance)
621                return fail(code:"default.not.found")
622
623            // Optimistic locking check.
624            if(params.version) {
625                if(result.taskInstance.version > params.version.toLong())
626                    return fail(field:"version", code:"default.optimistic.locking.failure")
627            }
628
629            result.taskInstance.approved = false
630
631            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
632                return fail(code:"default.update.failure")
633
634            def taskModification = new TaskModification(person:authService.currentUser,
635                                                    taskModificationType: TaskModificationType.get(9),
636                                                    task: result.taskInstance)
637
638            if(taskModification.hasErrors() || !taskModification.save())
639                return fail(code:"task.modifications.failedToSave")
640
641            // Success.
642            return result
643
644        } //end withTransaction
645    }  // end renegeApproval()
646
647    /**
648    * Creates a new immediate callout task with the given params.
649    * @param params The params to use when creating the new task.
650    * @returns A map containing result.error (if any error) and result.taskInstance.
651    */
652    def saveImmediateCallout(params) {
653        Task.withTransaction { status ->
654            def result = [:]
655
656            def fail = { Map m ->
657                status.setRollbackOnly()
658                if(result.taskInstance && m.field)
659                    result.taskInstance.errors.rejectValue(m.field, m.code)
660                result.error = [ code: m.code, args: ["Task", params.id] ]
661                return result
662            }
663
664            // If not supplied.
665            if(!params.taskStatus)
666                params.taskStatus = TaskStatus.get(1) // Not Started.
667
668            result.taskInstance = new Task(params)
669
670            // Always for an immediate callout.
671            result.taskInstance.taskType = TaskType.get(1) // Immediate Callout.
672            result.taskInstance.taskBudgetStatus = TaskBudgetStatus.get(1) // Unplanned.
673            result.taskInstance.taskPriority = TaskPriority.get(4) // Immediate.
674            result.taskInstance.taskGroup = TaskGroup.get(1) // Engineering Activites.
675            result.taskInstance.approved = true
676            result.taskInstance.leadPerson = authService.currentUser
677
678            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
679                fail(code:"default.create.failure")
680
681            if(!result.error) {
682                def taskModification = new TaskModification(person: authService.currentUser,
683                                                                taskModificationType: TaskModificationType.get(1), // Created.
684                                                                task: result.taskInstance)
685
686                if(taskModification.hasErrors() || !taskModification.save())
687                    fail(field:"taskModifications", code:"task.modifications.failedToSave")
688            }
689
690            def faultParams = [task: result.taskInstance,
691                                            entryType: EntryType.get(1),
692                                            comment: params.entryFault.comment,
693                                            durationHour: params.entryFault.durationHour,
694                                            durationMinute: params.entryFault.durationMinute]
695            def faultResult = saveEntry(faultParams)
696            result.entryFaultInstance = faultResult.entryInstance
697
698            def causeParams = [task: result.taskInstance,
699                                            entryType: EntryType.get(2),
700                                            comment: params.entryCause.comment]
701            def causeResult = saveEntry(causeParams)
702            result.entryCauseInstance = causeResult.entryInstance
703
704            def workDoneParams = [task: result.taskInstance,
705                                                    entryType: EntryType.get(3),
706                                                    comment: params.entryWorkDone.comment,
707                                                    durationHour: params.entryWorkDone.durationHour,
708                                                    durationMinute: params.entryWorkDone.durationMinute]
709            def workDoneResult = saveEntry(workDoneParams)
710            result.entryWorkDoneInstance = workDoneResult.entryInstance
711
712            if(result.error)
713                return result
714
715            if(causeResult.error)
716                return fail(code: "default.create.failure")
717
718            if(faultResult.error)
719                return fail(code: "default.create.failure")
720
721            if(workDoneResult.error)
722                return fail(code: "default.create.failure")
723
724            // Success.
725            return result
726
727        } //end withTransaction
728    } // end saveImmediateCallout()
729
730} // end TaskService
Note: See TracBrowser for help on using the repository browser.