Index: trunk/grails-app/services/AssetReportService.groovy
===================================================================
--- trunk/grails-app/services/AssetReportService.groovy	(revision 705)
+++ trunk/grails-app/services/AssetReportService.groovy	(revision 706)
@@ -137,4 +137,20 @@
         result.site = result.section.site
 
+        // Start date.
+        if(params.startDate)
+            params.startDate = dateUtilService.makeDate(params.startDate_year, params.startDate_month, params.startDate_day)
+        else
+            params.startDate = dateUtilService.oneWeekAgo
+
+        // End date.
+        if(params.endDate)
+            params.endDate = dateUtilService.makeDate(params.endDate_year, params.endDate_month, params.endDate_day)
+        else
+            params.endDate = dateUtilService.today
+
+        // Normalise date range.
+        if(params.endDate < params.startDate)
+            params.endDate = params.startDate
+
         // Inner join used to return only attribTypes that are used by AssetSubItemExtendedAttributes.
         // So the result is only assetSubItem extendedAttributeTypes.
@@ -166,10 +182,31 @@
         result.assetsWithoutEquipment = AssetSubItem.executeQuery(assetsWithoutEquipmentQ.query, assetsWithoutEquipmentQ.namedParams)
 
+        // Subquery to count regulatory tasks.
+        def regulatoryTaskCountQ = new HqlBuilder().query {
+
+            select 'count (distinct task)'
+            from 'Task as task',
+                    'left join task.associatedAssets as associatedAsset'
+            where 'task.mandatoryRegulatory = true'
+                and 'task.targetStartDate < :endDate'
+                and 'task.targetCompletionDate >= :startDate'
+                and '(task.primaryAsset.id = asset.id or associatedAsset.id = asset.id)'
+                and 'task.trash = false'
+        }
+
+        def totalRegulatoryTaskCountQ = regulatoryTaskCountQ.query
+
+        regulatoryTaskCountQ.and 'task.taskStatus.id = 3'
+        def completedRegulatoryTaskCountQ = regulatoryTaskCountQ.query
+
         // A result is returned for every level 1 assetSubItem and for any extended attributes.
         def q = new HqlBuilder().query {
+
             select 'new map(asset.name as assetName',
                         'assetSubItem.name as name',
                         'assetSubItem.description as description',
                         'assetSubItem.comment as comment',
+                        "0 as totalRegulatoryTaskCount",
+                        "0 as completedRegulatoryTaskCount",
                         'attribT.name as attribType',
                         'attrib.value as attribValue)'
@@ -187,8 +224,15 @@
         // A result is returned for every asset and for any extended attributes.
         def assetResultsQ = new HqlBuilder().query {
+
+            // Subquery namedParams.
+            namedParams.startDate = params.startDate
+            namedParams.endDate = params.endDate+1
+
             select 'new map(asset.name as assetName',
                         "'   Asset Details' as name", // Place holder 'equipment' name, 3 leading spaces for sorting.
                         'asset.description as description',
                         'asset.comment as comment',
+                        "($totalRegulatoryTaskCountQ) as totalRegulatoryTaskCount",
+                        "($completedRegulatoryTaskCountQ) as completedRegulatoryTaskCount",
                         'attribT.name as attribType',
                         'attrib.value as attribValue)'
@@ -211,11 +255,14 @@
         def rows = [:]
         equipmentResults.each { equipmentResult ->
-            // Create row if it does not exist yet.
+
             def rowKey = equipmentResult.assetName+equipmentResult.name
+
+            // Create new row if it does not exist yet.
             if(!rows.containsKey(rowKey)) {
                 rows[rowKey] = ['assetName': equipmentResult.assetName,
-                                                            'name':equipmentResult.name,
-                                                            'description':equipmentResult.description,
-                                                            'comment':equipmentResult.comment]
+                                            'name':equipmentResult.name,
+                                            'description':equipmentResult.description,
+                                            'comment':equipmentResult.comment,
+                                            'Regulatory Task Completion': ' ']
 
                 // Add all attribType columns.
@@ -223,9 +270,21 @@
                     rows[rowKey][column] = ' '
                 }
-            }
+
+                // Caluculate and assign RegulatoryTaskCompletion, only for Assets.
+                if(params.calculateRegulatoryTaskCompletion) {
+
+                    if(equipmentResult.totalRegulatoryTaskCount) {
+                        def percentComplete = (equipmentResult.completedRegulatoryTaskCount / equipmentResult.totalRegulatoryTaskCount)*100
+                        rows[rowKey]['Regulatory Task Completion'] = "${percentComplete.toInteger()}% (${equipmentResult.completedRegulatoryTaskCount}/${equipmentResult.totalRegulatoryTaskCount})"
+                    }
+                    else if(equipmentResult.name == '   Asset Details')
+                        rows[rowKey]['Regulatory Task Completion'] = 'N/A'
+                }
+
+            } // Create new row.
 
             // Assign value to column.
             rows[rowKey][equipmentResult.attribType] = equipmentResult.attribValue
-        }
+        } // each.
 
         // The value of each row is the dataList used by the report table.
