source: trunk/grails-app/services/AssetReportService.groovy @ 706

Last change on this file since 706 was 706, checked in by gav, 13 years ago

Implement ticket #88 - "Implement Regulatory Task Completion on Equipmet Register Report OH&S"

File size: 12.9 KB
Line 
1import net.kromhouts.HqlBuilder
2
3/**
4* Service class that encapsulates the business logic for Asset Reports.
5*/
6class AssetReportService {
7
8    boolean transactional = false
9
10    def authService
11    def dateUtilService
12//     def messageSource
13
14    def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()
15
16    def paramsMax = 100000
17
18    /**
19    * Selects and returns the assets and their details.
20    * @param params The request params, may contain params to specify the search.
21    * @param locale The locale to use when generating result.message.
22    */
23    def getAssetRegister(params, locale) {
24        def result = [:]
25
26        result.section = Section.get(params.section.id.toLong())
27        result.site = result.section.site
28
29        // Inner join used to return only attribTypes that are used by AssetExtendedAttributes.
30        // So the result is only asset extendedAttributeTypes.
31//         def attribTypesQ = new HqlBuilder().query {
32//             select 'distinct attribT.name'
33//             from 'AssetExtendedAttribute attrib',
34//                     'join attrib.extendedAttributeType as attribT'
35//             order 'by attribT.name asc'
36//         }
37
38        // All active ExtendedAttributes.
39        def attribTypesQ = new HqlBuilder().query {
40            select 'distinct attribT.name'
41            from 'ExtendedAttributeType attribT'
42            where 'attribT.isActive = true'
43            order 'by attribT.name asc'
44        }
45        result.attribTypes = ExtendedAttributeType.executeQuery(attribTypesQ.query, attribTypesQ.namedParams)
46
47        // A result is returned for every asset and for any extended attributes.
48        def q = new HqlBuilder().query {
49            select 'new map(asset.name as name',
50                        'asset.description as description',
51                        'asset.comment as comment',
52                        'attribT.name as attribType',
53                        'attrib.value as attribValue)'
54            from 'Asset asset',
55                    'left join asset.assetExtendedAttributes as attrib',
56                    'left join attrib.extendedAttributeType as attribT'
57            where 'asset.section = :section'
58                    namedParams.section = result.section
59            order 'by asset.name asc, attribT.name asc'
60        }
61        def assetResults = Asset.executeQuery(q.query, q.namedParams)
62
63        // Build the report table row for each asset.
64        // Rows are keyed by asset.name and the value is a Map of the attributes.
65        def rows = [:]
66        assetResults.each { assetResult ->
67            // Create row if it does not exist yet.
68            if(!rows.containsKey(assetResult.name)) {
69                rows[assetResult.name] = ['name':assetResult.name,
70                                                            'description':assetResult.description,
71                                                            'comment':assetResult.comment]
72
73                // Add all attribType columns.
74                result.attribTypes.each { column ->
75                    rows[assetResult.name][column] = ' '
76                }
77            }
78
79            // Assign value to column.
80            rows[assetResult.name][assetResult.attribType] = assetResult.attribValue
81        }
82
83        // The value of each row is the dataList used by the report table.
84        result.dataList = rows.collect {it.value}
85
86        // Success.
87        return result
88
89    } // getAssetRegister
90
91    /**
92    * Selects and returns an asset (or all) and its details.
93    * @param params The request params, may contain params to specify the search.
94    * @param locale The locale to use when generating result.message.
95    */
96    def getAssetDetail(params, locale) {
97        //def result = [:]
98        def result
99
100        //result.summaryOfCalculationMethod = ''
101
102        // A result is returned for every asset and for any extended attributes.
103        // The report then groups by asset.name
104        def q = new HqlBuilder().query {
105            select 'new map(asset.name as name',
106                        'asset.description as description',
107                        'asset.comment as comment',
108                        'attribT.name as attribType',
109                        'attrib.value as attribValue)'
110            from 'Asset asset',
111                    'left join asset.assetExtendedAttributes as attrib',
112                    'left join attrib.extendedAttributeType as attribT'
113            if(params.section instanceof Section) {
114                namedParams.section = params.section
115                where 'asset.section = :section'
116            }
117            order 'by asset.name asc, attribT.name asc'
118        }
119
120        // result.dataList = Asset.list()
121        result = Asset.executeQuery(q.query, q.namedParams)
122
123        // Success.
124        return result
125
126    } // getAssetDetail
127
128    /**
129    * Selects and returns level 1 sub items (aka machines or equipment) and their details.
130    * @param params The request params, may contain params to specify the search.
131    * @param locale The locale to use when generating result.message.
132    */
133    def getEquipmentRegister(params, locale) {
134        def result = [:]
135
136        result.section = Section.get(params.section.id.toLong())
137        result.site = result.section.site
138
139        // Start date.
140        if(params.startDate)
141            params.startDate = dateUtilService.makeDate(params.startDate_year, params.startDate_month, params.startDate_day)
142        else
143            params.startDate = dateUtilService.oneWeekAgo
144
145        // End date.
146        if(params.endDate)
147            params.endDate = dateUtilService.makeDate(params.endDate_year, params.endDate_month, params.endDate_day)
148        else
149            params.endDate = dateUtilService.today
150
151        // Normalise date range.
152        if(params.endDate < params.startDate)
153            params.endDate = params.startDate
154
155        // Inner join used to return only attribTypes that are used by AssetSubItemExtendedAttributes.
156        // So the result is only assetSubItem extendedAttributeTypes.
157//         def attribTypesQ = new HqlBuilder().query {
158//             select 'distinct attribT.name'
159//             from 'AssetSubItemExtendedAttribute attrib',
160//                     'join attrib.extendedAttributeType as attribT'
161//             order 'by attribT.name asc'
162//         }
163
164        // All active ExtendedAttributes.
165        def attribTypesQ = new HqlBuilder().query {
166            select 'distinct attribT.name'
167            from 'ExtendedAttributeType attribT'
168            where 'attribT.isActive = true'
169            order 'by attribT.name asc'
170        }
171        result.attribTypes = ExtendedAttributeType.executeQuery(attribTypesQ.query, attribTypesQ.namedParams)
172
173        // A useful list of assets without subItems to be given to the user.
174        def assetsWithoutEquipmentQ = new HqlBuilder().query {
175            select 'distinct asset'
176            from 'Asset asset',
177                    'left join asset.assetSubItems as assetSubItem'
178            where 'assetSubItem = null'
179                namedParams.section = result.section
180                and 'asset.section = :section'
181        }
182        result.assetsWithoutEquipment = AssetSubItem.executeQuery(assetsWithoutEquipmentQ.query, assetsWithoutEquipmentQ.namedParams)
183
184        // Subquery to count regulatory tasks.
185        def regulatoryTaskCountQ = new HqlBuilder().query {
186
187            select 'count (distinct task)'
188            from 'Task as task',
189                    'left join task.associatedAssets as associatedAsset'
190            where 'task.mandatoryRegulatory = true'
191                and 'task.targetStartDate < :endDate'
192                and 'task.targetCompletionDate >= :startDate'
193                and '(task.primaryAsset.id = asset.id or associatedAsset.id = asset.id)'
194                and 'task.trash = false'
195        }
196
197        def totalRegulatoryTaskCountQ = regulatoryTaskCountQ.query
198
199        regulatoryTaskCountQ.and 'task.taskStatus.id = 3'
200        def completedRegulatoryTaskCountQ = regulatoryTaskCountQ.query
201
202        // A result is returned for every level 1 assetSubItem and for any extended attributes.
203        def q = new HqlBuilder().query {
204
205            select 'new map(asset.name as assetName',
206                        'assetSubItem.name as name',
207                        'assetSubItem.description as description',
208                        'assetSubItem.comment as comment',
209                        "0 as totalRegulatoryTaskCount",
210                        "0 as completedRegulatoryTaskCount",
211                        'attribT.name as attribType',
212                        'attrib.value as attribValue)'
213            from 'AssetSubItem assetSubItem',
214                    'inner join assetSubItem.assets as asset',
215                    'left join assetSubItem.assetSubItemExtendedAttributes as attrib',
216                    'left join attrib.extendedAttributeType as attribT'
217            where 'asset != null' // ensure that only level 1 assetSubItems are returned.
218                namedParams.section = result.section
219                and 'asset.section = :section'
220            order 'by asset.name asc, assetSubItem.name asc, attribT.name asc'
221        }
222        def equipmentResults = AssetSubItem.executeQuery(q.query, q.namedParams)
223
224        // A result is returned for every asset and for any extended attributes.
225        def assetResultsQ = new HqlBuilder().query {
226
227            // Subquery namedParams.
228            namedParams.startDate = params.startDate
229            namedParams.endDate = params.endDate+1
230
231            select 'new map(asset.name as assetName',
232                        "'   Asset Details' as name", // Place holder 'equipment' name, 3 leading spaces for sorting.
233                        'asset.description as description',
234                        'asset.comment as comment',
235                        "($totalRegulatoryTaskCountQ) as totalRegulatoryTaskCount",
236                        "($completedRegulatoryTaskCountQ) as completedRegulatoryTaskCount",
237                        'attribT.name as attribType',
238                        'attrib.value as attribValue)'
239            from 'Asset asset',
240                    'left join asset.assetExtendedAttributes as attrib',
241                    'left join attrib.extendedAttributeType as attribT'
242            where 'asset.section = :section'
243                    namedParams.section = result.section
244            order 'by asset.name asc, attribT.name asc'
245        }
246        def assetResults = Asset.executeQuery(assetResultsQ.query, assetResultsQ.namedParams)
247
248        // Add asset details to equipmentResults.
249        equipmentResults.addAll(assetResults)
250        equipmentResults.sort { p1, p2 -> p1.assetName.compareToIgnoreCase(p2.assetName) ?: p1.name.compareToIgnoreCase(p2.name) }
251
252        // Build the report table rows.
253        // Rows are keyed by equipmentResult.assetName+equipmentResult.name` while the value is a Map of the attributes.
254        // The report table then groups by assetName.
255        def rows = [:]
256        equipmentResults.each { equipmentResult ->
257
258            def rowKey = equipmentResult.assetName+equipmentResult.name
259
260            // Create new row if it does not exist yet.
261            if(!rows.containsKey(rowKey)) {
262                rows[rowKey] = ['assetName': equipmentResult.assetName,
263                                            'name':equipmentResult.name,
264                                            'description':equipmentResult.description,
265                                            'comment':equipmentResult.comment,
266                                            'Regulatory Task Completion': ' ']
267
268                // Add all attribType columns.
269                result.attribTypes.each { column ->
270                    rows[rowKey][column] = ' '
271                }
272
273                // Caluculate and assign RegulatoryTaskCompletion, only for Assets.
274                if(params.calculateRegulatoryTaskCompletion) {
275
276                    if(equipmentResult.totalRegulatoryTaskCount) {
277                        def percentComplete = (equipmentResult.completedRegulatoryTaskCount / equipmentResult.totalRegulatoryTaskCount)*100
278                        rows[rowKey]['Regulatory Task Completion'] = "${percentComplete.toInteger()}% (${equipmentResult.completedRegulatoryTaskCount}/${equipmentResult.totalRegulatoryTaskCount})"
279                    }
280                    else if(equipmentResult.name == '   Asset Details')
281                        rows[rowKey]['Regulatory Task Completion'] = 'N/A'
282                }
283
284            } // Create new row.
285
286            // Assign value to column.
287            rows[rowKey][equipmentResult.attribType] = equipmentResult.attribValue
288        } // each.
289
290        // The value of each row is the dataList used by the report table.
291        result.dataList = rows.collect {it.value}
292        // Print formatting, since we are done with these as objects.
293        result.attribTypes = result.attribTypes.join(', ')
294        result.assetsWithoutEquipment = result.assetsWithoutEquipment.collect {it.name}.join(', ')
295
296        // Success.
297        return result
298
299    } // getEquipmentRegister
300
301} // end class
Note: See TracBrowser for help on using the repository browser.