source: trunk/grails-app/services/TaskReportService.groovy @ 570

Last change on this file since 570 was 545, checked in by gav, 14 years ago

Update report templates, add downloadTemplate action and general tidy up of reports.

File size: 12.4 KB
RevLine 
[533]1
2/**
3* Service class that encapsulates the business logic for Task searches.
4*/
5class TaskReportService {
6
7    boolean transactional = false
8
9    def authService
10    def dateUtilService
11//     def messageSource
12
[544]13    def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()
[533]14
15    def paramsMax = 100000
16
17    /**
18    * Selects and returns the reactive ratio.
[542]19    * @param params The request params, may contain params to specify the search.
[533]20    * @param locale The locale to use when generating result.message.
21    */
22    def getReactiveRatio(params, locale) {
23        def result = [:]
24
25        def namedParams = [:]
26        namedParams.startDate = params.startDate ?: dateUtilService.today
[535]27        namedParams.endDate = params.endDate ?: dateUtilService.today
28        namedParams.endDate++ // Start of next day required.
[533]29        namedParams.immediateCallout = TaskType.read(1)
30        namedParams.unscheduledBreakin = TaskType.read(2)
31        namedParams.preventativeMaintenance = TaskType.read(4)
[535]32        namedParams.notStarted = TaskStatus.read(1)
[533]33
34        result.taskQuery = "from Task as task \
[542]35                                            where (task.trash = false \
36                                                        and task.taskStatus != :notStarted \
37                                                        and task.targetStartDate < :endDate \
38                                                        and task.targetStartDate >= :startDate \
39                                                        and ( \
40                                                            task.taskType = :immediateCallout \
41                                                            or task.taskType = :unscheduledBreakin \
42                                                            or task.taskType = :preventativeMaintenance \
43                                                        ) \
44                                            )"
[533]45
[535]46        result.taskQuery = "select distinct task " + result.taskQuery
47        result.taskList = Task.executeQuery(result.taskQuery, namedParams)
[533]48        result.taskCount = result.taskList.size()
49
[536]50        // Assets on Tasks Count.
[535]51        result.totalAssetsOnTasksCount = 0
[533]52        result.immediateCalloutCount = 0
53        result.unscheduledBreakinCount = 0
54        result.preventativeMaintenanceCount = 0
55
[542]56        // Summary Of Calculations.
[535]57        result.summaryOfCalculationMethod = 'HQL query: \n\n'
58        def tempStringArray = result.taskQuery.split('    ')
59        tempStringArray.each() {
60            if(it != '') result.summaryOfCalculationMethod += it +'\n'
61        }
62        result.summaryOfCalculationMethod += '\n'+'Calculations: '+'\n\n'
63
64        result.summaryOfCalculationMethod += 'totalAssetsOnTasksCount = A count of unique assets on each task. \n'
[533]65        result.taskList.each() { task ->
66            if(task.primaryAsset) {
[535]67                result.totalAssetsOnTasksCount++
[533]68                if(task.taskType == namedParams.immediateCallout) result.immediateCalloutCount++
69                if(task.taskType == namedParams.unscheduledBreakin) result.unscheduledBreakinCount++
70                if(task.taskType == namedParams.preventativeMaintenance) result.preventativeMaintenanceCount++
71            }
72            task.associatedAssets.each() { associatedAsset ->
73                if(associatedAsset.id != task.primaryAsset?.id) {
[535]74                    result.totalAssetsOnTasksCount++
[533]75                    if(task.taskType == namedParams.immediateCallout) result.immediateCalloutCount++
76                    if(task.taskType == namedParams.unscheduledBreakin) result.unscheduledBreakinCount++
77                    if(task.taskType == namedParams.preventativeMaintenance) result.preventativeMaintenanceCount++
78                }
79            }
80        } // each() task
81
[536]82        // Percentage of counts.
[533]83        result.immediateCalloutPercentage = 0
84        result.totalPreventativePercentage = 0
85
[535]86        result.summaryOfCalculationMethod += 'totalPreventativeCount = unscheduledBreakinCount + preventativeMaintenanceCount\n'
[533]87        result.totalPreventativeCount = result.unscheduledBreakinCount + result.preventativeMaintenanceCount
88        try {
[535]89            result.summaryOfCalculationMethod += 'immediateCalloutPercentage = (immediateCalloutCount / totalAssetsOnTasksCount)*100 \n'
90            result.summaryOfCalculationMethod += 'totalPreventativePercentage = (totalPreventativeCount / totalAssetsOnTasksCount)*100 \n'
91            result.immediateCalloutPercentage = (result.immediateCalloutCount / result.totalAssetsOnTasksCount)*100
92            result.totalPreventativePercentage = (result.totalPreventativeCount / result.totalAssetsOnTasksCount)*100
[533]93        }
94        catch(ArithmeticException e) {
[536]95            log.error "Could not calculate: Assets on Tasks Percentages: "+e
[533]96        }
97
[536]98        // Work Done.
99        result.immediateCalloutWorkDone = [total:0, hours:0, minutes:0, percentage:0]
100        result.unscheduledBreakinWorkDone = [total:0, hours:0, minutes:0]
101        result.preventativeMaintenanceWorkDone = [total:0, hours:0, minutes:0]
102        result.totalPreventativeWorkDone = [total:0, hours:0, minutes:0, percentage:0]
103        result.totalWorkDone = [total:0, hours:0, minutes:0]
104
105        result.taskList.each() { task ->
106            task.entries.each() { entry ->
107                // Has assets assigned and is Work Done.
108                if( (task.primaryAsset || task.associatedAssets) && entry.entryType.id == 3L ) {
109                        if(task.taskType == namedParams.immediateCallout)
110                            result.immediateCalloutWorkDone.total += (entry.durationHour*60) + entry.durationMinute
111                        if(task.taskType == namedParams.unscheduledBreakin)
112                            result.unscheduledBreakinWorkDone.total += (entry.durationHour*60) + entry.durationMinute
113                        if(task.taskType == namedParams.preventativeMaintenance)
114                            result.preventativeMaintenanceWorkDone.total += (entry.durationHour*60) + entry.durationMinute
115                }
116            } // each() entry
117        } // each() task
118
119        // Work Done hours and minutes.
120        result.immediateCalloutWorkDone.hours = (result.immediateCalloutWorkDone.total / 60).toInteger()
121        result.immediateCalloutWorkDone.minutes = result.immediateCalloutWorkDone.total % 60
122
123        result.unscheduledBreakinWorkDone.hours = (result.unscheduledBreakinWorkDone.total / 60).toInteger()
124        result.unscheduledBreakinWorkDone.minutes = result.unscheduledBreakinWorkDone.total % 60
125
126        result.preventativeMaintenanceWorkDone.hours = (result.preventativeMaintenanceWorkDone.total / 60).toInteger()
127        result.preventativeMaintenanceWorkDone.minutes = result.preventativeMaintenanceWorkDone.total % 60
128
129        // Work Done Totals.
130        result.totalPreventativeWorkDone.total = result.unscheduledBreakinWorkDone.total + result.preventativeMaintenanceWorkDone.total
131        result.totalPreventativeWorkDone.hours = (result.totalPreventativeWorkDone.total / 60).toInteger()
132        result.totalPreventativeWorkDone.minutes = result.totalPreventativeWorkDone.total % 60
133
134        result.totalWorkDone.total = result.immediateCalloutWorkDone.total + result.totalPreventativeWorkDone.total
135        result.totalWorkDone.hours = (result.totalWorkDone.total / 60).toInteger()
136        result.totalWorkDone.minutes = result.totalWorkDone.total % 60
137
138        // Work Done Percentages.
139        try {
140            result.immediateCalloutWorkDone.percentage = (result.immediateCalloutWorkDone.total / result.totalWorkDone.total)*100
141            result.totalPreventativeWorkDone.percentage = (result.totalPreventativeWorkDone.total / result.totalWorkDone.total)*100
142        }
143        catch(ArithmeticException e) {
144            log.error "Could not calculate: Work Done Percentages: "+e
145        }
146
[533]147        // Success.
148        return result
149
[542]150    } // getReactiveRatio
[533]151
[542]152    /**
153    * Selects and returns Immediate Callouts, grouped by Asset.
154    * @param params The request params, may contain params to specify the search.
155    * @param locale The locale to use when generating result.message.
156    */
157    def getImmediateCallouts(params, locale) {
158        def result = [:]
[533]159
[542]160        def namedParams = [:]
161        namedParams.startDate = params.startDate ?: dateUtilService.today
162        namedParams.endDatePlusOne = (params.endDate ?: dateUtilService.today)+1
163        namedParams.immediateCallout = TaskType.read(1)
164
165        result.taskQuery = "from Task as task \
166                                            where (task.trash = false \
167                                                        and task.targetStartDate < :endDatePlusOne \
168                                                        and task.targetStartDate >= :startDate \
169                                                        and task.taskType = :immediateCallout \
170                                                        ) \
171                                            )"
172
173        result.taskQuery = "select distinct task " + result.taskQuery
[544]174        result.taskQueryList = Task.executeQuery(result.taskQuery, namedParams)
175        result.taskCount = result.taskQueryList.size()
[542]176
177        // Assets on Tasks Count.
178        result.totalAssetsOnTasksCount = 0
[544]179        result.totalDownTime = [total: 0, hours: 0, minutes:0]
[542]180        result.assetList = []
181
[544]182        // Task Details
183        result.taskList = []
[542]184
[544]185        // Add or update lists.
186        def addToLists = { asset, task ->
187
[542]188            def downTime = 0
189            def faultEntries = Entry.findAllByTaskAndEntryType(task, EntryType.read(1))
[544]190            def causeEntries = Entry.findAllByTaskAndEntryType(task, EntryType.read(2))
191            def workDoneEntries = Entry.findAllByTaskAndEntryType(task, EntryType.read(3))
192            def taskDetails = 'Task #'+task.id+' - '+task.description+'\n'
193            faultEntries.each(){
194                taskDetails += '    Faults: '+it.comment+' - '+it.enteredBy+', '+g.formatDate(format: "EEE, dd-MMM-yyyy", date: it.dateDone)+'.\n'
195            }
196            causeEntries.each(){
197                taskDetails += '    Causes: '+it.comment+' - '+it.enteredBy+', '+g.formatDate(format: "EEE, dd-MMM-yyyy", date: it.dateDone)+'.\n'
198            }
199            workDoneEntries.each(){
200                taskDetails += '    Work Done: '+it.comment+' - '+it.enteredBy+', '+g.formatDate(format: "EEE, dd-MMM-yyyy", date: it.dateDone)+'.\n'
201            }
202
[542]203            faultEntries.each() { downTime += (it.durationHour*60 + it.durationMinute) }
[544]204            result.totalDownTime.total += downTime
[542]205
206            def assetDetails = result.assetList.find { it.id == asset.id }
207            if(assetDetails) {
208                assetDetails.immediateCalloutCount++
[544]209                assetDetails.downTime += downTime
210                assetDetails.tasks += taskDetails
[542]211            }
212            else {
213                assetDetails = [id: asset.id,
214                                            name: asset.name,
215                                            immediateCalloutCount: 1,
216                                            downTime: downTime,
[544]217                                            tasks: taskDetails]
[542]218
219                result.assetList << assetDetails
220            }
[544]221        } // addAToLists
[542]222
223        // Summary Of Calculations.
224        result.summaryOfCalculationMethod = 'HQL query: \n\n'
225        def tempStringArray = result.taskQuery.split('    ')
226        tempStringArray.each() {
227            if(it != '') result.summaryOfCalculationMethod += it +'\n'
228        }
229        result.summaryOfCalculationMethod += '\n'+'Calculations: '+'\n\n'
230
231        result.summaryOfCalculationMethod += 'totalAssetsOnTasksCount = A count of unique assets on each task. \n'
[544]232        result.taskQueryList.each() { task ->
[542]233            if(task.primaryAsset) {
234                result.totalAssetsOnTasksCount++
[544]235                addToLists(task.primaryAsset, task)
[542]236            }
237            task.associatedAssets.each() { associatedAsset ->
238                if(associatedAsset.id != task.primaryAsset?.id) {
239                    result.totalAssetsOnTasksCount++
[544]240                    addToLists(associatedAsset, task)
[542]241                }
242            }
243
244        } // each() task
245
[544]246        // Sort assetList by callout count.
[542]247        result.assetList.sort {a, b -> b.immediateCalloutCount.compareTo(a.immediateCalloutCount)}
248
[544]249        // Calculate hours and minutes.
250        result.totalDownTime.hours = (result.totalDownTime.total / 60).toInteger()
251        result.totalDownTime.minutes = result.totalDownTime.total % 60
252
[542]253        // Success.
254        return result
255
256    } // getImmediateCallouts()
257
258
[533]259} // end class
Note: See TracBrowser for help on using the repository browser.