source: trunk/grails-app/services/TaskSearchService.groovy @ 582

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

New defaultSort for Tasks, sort by status then priority then target start date.
Small improvement to custom:sortableColumnWithImg to allow imgTitle to be specified.

File size: 18.9 KB
Line 
1import grails.orm.PagedResultList
2
3/**
4* Service class that encapsulates the business logic for Task searches.
5*/
6class TaskSearchService {
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 correct search results based on the supplied quickSearch.
20    * @param params The request params, may contain params.quickSearch string to specify the search.
21    * @param locale The locale to use when generating result.message.
22    */
23    def getQuickSearch(params, locale) {
24        def result = [:]
25        result.quickSearch = params.quickSearch ?: "plannersRange"
26
27        def currentUser = authService.currentUser
28        def startOfToday = dateUtilService.today
29        def startOfYesterday = dateUtilService.yesterday
30        def startOfTomorrow = dateUtilService.tomorrow
31        def oneWeekAgo = dateUtilService.oneWeekAgo
32
33        def formattedStartOfToday = g.formatDate(format: "EEE, dd-MMM-yyyy", date: startOfToday)
34        def formattedStartOfYesterday = g.formatDate(format: "EEE, dd-MMM-yyyy", date: startOfYesterday)
35        def formattedStartOfTomorrow = g.formatDate(format: "EEE, dd-MMM-yyyy", date: startOfTomorrow)
36        def formattedOneWeekAgo = g.formatDate(format: "EEE, dd-MMM-yyyy", date: oneWeekAgo)
37
38        def getMessage = { Map m ->
39            messageSource.getMessage(m.code, m.args == null ? null : m.args.toArray(), locale)
40        }
41
42        switch (result.quickSearch) {
43            case "myTodays":
44                result.taskInstanceList = getPersonsTasks(params)
45                if(result.taskInstanceList.totalCount > 0)
46                    result.message = getMessage(code:"task.search.text.persons.tasks.message",
47                                                                    args:[currentUser, formattedStartOfToday])
48                else
49                    result.message = getMessage(code:"task.search.text.persons.tasks.none.found",
50                                                                    args:[currentUser, formattedStartOfToday])
51                break
52            case "myYesterdays":
53                result.taskInstanceList = getPersonsTasks(params, currentUser, startOfYesterday, startOfToday)
54                if(result.taskInstanceList.totalCount > 0)
55                    result.message = getMessage(code:"task.search.text.persons.tasks.message",
56                                                                    args:[currentUser, formattedStartOfYesterday])
57                else
58                    result.message = getMessage(code:"task.search.text.persons.tasks.none.found",
59                                                                    args:[currentUser, formattedStartOfYesterday])
60                break
61            case "myTomorrows":
62                result.taskInstanceList = getPersonsTasks(params, currentUser, startOfTomorrow, startOfTomorrow+1)
63                if(result.taskInstanceList.totalCount > 0)
64                    result.message = getMessage(code:"task.search.text.persons.tasks.message",
65                                                                    args:[currentUser, formattedStartOfTomorrow])
66                else
67                    result.message = getMessage(code:"task.search.text.persons.tasks.none.found",
68                                                                    args:[currentUser, formattedStartOfTomorrow])
69                break
70            case "myPastWeek":
71                result.taskInstanceList = getPersonsTasks(params, currentUser, oneWeekAgo, startOfTomorrow)
72                if(result.taskInstanceList.totalCount > 0)
73                    result.message = getMessage(code:"task.search.text.persons.tasks.between.message",
74                                                                    args:[currentUser, formattedOneWeekAgo, formattedStartOfToday])
75                else
76                    result.message = getMessage(code:"task.search.text.persons.tasks.between.none.found",
77                                                                    args:[currentUser, formattedOneWeekAgo, formattedStartOfToday])
78                break
79            case "todays":
80                result.taskInstanceList = getTasks(params)
81                if(result.taskInstanceList.totalCount > 0)
82                    result.message = getMessage(code:"task.search.text.all.tasks.message",
83                                                                    args:[formattedStartOfToday])
84                else
85                    result.message = getMessage(code:"task.search.text.all.tasks.none.found",
86                                                                    args:[formattedStartOfToday])
87                break
88            case "yesterdays":
89                result.taskInstanceList = getTasks(params, startOfYesterday, startOfToday)
90                if(result.taskInstanceList.totalCount > 0)
91                    result.message = getMessage(code:"task.search.text.all.tasks.message",
92                                                                    args:[formattedStartOfYesterday])
93                else
94                    result.message = getMessage(code:"task.search.text.all.tasks.none.found",
95                                                                    args:[formattedStartOfYesterday])
96                break
97            case "tomorrows":
98                result.taskInstanceList = getTasks(params, startOfTomorrow, startOfTomorrow+1)
99                if(result.taskInstanceList.totalCount > 0)
100                    result.message = getMessage(code:"task.search.text.all.tasks.message",
101                                                                    args:[formattedStartOfTomorrow])
102                else
103                    result.message = getMessage(code:"task.search.text.all.tasks.none.found",
104                                                                    args:[formattedStartOfTomorrow])
105                break
106            case "pastWeek":
107                result.taskInstanceList = getTasks(params, oneWeekAgo, startOfTomorrow)
108                if(result.taskInstanceList.totalCount > 0)
109                    result.message = getMessage(code:"task.search.text.all.tasks.between.message",
110                                                                    args:[formattedOneWeekAgo, formattedStartOfToday])
111                else
112                    result.message = getMessage(code:"task.search.text.all.tasks.between.none.found",
113                                                                    args:[formattedOneWeekAgo, formattedStartOfToday])
114                break
115            case "budgetUnplanned":
116                result.taskInstanceList = getBudgetTasks(params, TaskBudgetStatus.read(1), oneWeekAgo, startOfTomorrow)
117                if(result.taskInstanceList.totalCount > 0)
118                    result.message = getMessage(code:"task.search.text.budget.unplanned.message",
119                                                                    args:[formattedOneWeekAgo, formattedStartOfToday])
120                else
121                    result.message = getMessage(code:"task.search.text.budget.unplanned.none.found",
122                                                                    args:[formattedOneWeekAgo, formattedStartOfToday])
123                break
124            case "budgetPlanned":
125                result.taskInstanceList = getBudgetTasks(params, TaskBudgetStatus.read(2), oneWeekAgo, startOfTomorrow)
126                if(result.taskInstanceList.totalCount > 0)
127                    result.message = getMessage(code:"task.search.text.budget.planned.message",
128                                                                    args:[formattedOneWeekAgo, formattedStartOfToday])
129                else
130                    result.message = getMessage(code:"task.search.text.budget.planned.none.found",
131                                                                    args:[formattedOneWeekAgo, formattedStartOfToday])
132                break
133            default:
134                //case "plannersRange":
135                result.taskInstanceList = getTasks(params, oneWeekAgo, startOfToday+15)
136                if(result.taskInstanceList.totalCount > 0)
137                    result.message = getMessage(code:"task.search.text.all.tasks.between.message",
138                                                                    args:[formattedOneWeekAgo,
139                                                                            g.formatDate(format: "EEE, dd-MMM-yyyy", date: startOfToday+14)])
140                else
141                    result.message = getMessage(code:"task.search.text.all.tasks.between.none.found",
142                                                                    args:[formattedOneWeekAgo,
143                                                                            g.formatDate(format: "EEE, dd-MMM-yyyy", date: startOfToday+14)])
144                break
145        } // switch.
146
147        // Success.
148        return result
149
150    } // getQuickSearch
151
152    /**
153    * Get all tasks that are not in the trash bin, by default today's tasks.
154    * @param params The request params.
155    * @param startDate The start date to get tasks for, defaults to the start of today and is inclusive (greater than or equal to).
156    * @param endDate The end date to get tasks for, defaults to the start of tomorrow and is exclusive (less than).
157    */
158    def getTasks(params, startDate=null, endDate=null) {
159        def paginateParams = [:]
160        paginateParams.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
161        paginateParams.offset = params?.offset?.toInteger() ?: 0
162
163        def orderBy = ''
164        if(params.sort?.contains('.')) // protect against filterpane bug.
165            params.sort = null
166        if(params.sort && params.order) {
167            def sort = "task." + params.sort
168            def order = (params.order == "asc") ? "asc" : "desc"
169            orderBy = " order by " + sort + ' ' + order
170        }
171        else
172            orderBy = " order by task.taskStatus, task.taskPriority, task.targetStartDate"
173
174        def namedParams = [:]
175        namedParams.startDate = startDate ?: dateUtilService.today
176        namedParams.endDate = endDate ?: dateUtilService.tomorrow
177
178        def baseQuery = "from Task as task \
179                                        where (task.trash = false \
180                                                    and task.targetStartDate < :endDate \
181                                                    and task.targetCompletionDate >= :startDate \
182                                        )"
183
184        def searchQuery = "select distinct task " + baseQuery + orderBy
185        def list = Task.executeQuery(searchQuery, namedParams, paginateParams)
186
187        def countQuery = "select count(distinct task) as taskCount " + baseQuery
188        def totalCount = Task.executeQuery(countQuery, namedParams)[0].toInteger()
189
190        def taskInstanceList = new PagedResultList(list, totalCount)
191        return taskInstanceList
192    } // getPTasks()
193
194    /**
195    * Get a person's tasks, by default current user and today's tasks.
196    * "My tasks and approved tasks that I am assigned to"
197    * @param params The request params.
198    * @param person The person to get tasks for, defaults to current user.
199    * @param startDate The start date to get tasks for, defaults to the start of today and is inclusive (greater than or equal to).
200    * @param endDate The end date to get tasks for, defaults to the start of tomorrow and is exclusive (less than).
201    */
202    def getPersonsTasks(params, person=null, startDate=null, endDate=null) {
203        def paginateParams = [:]
204        paginateParams.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
205        paginateParams.offset = params?.offset?.toInteger() ?: 0
206
207        def orderBy = ''
208        if(params.sort?.contains('.')) // protect against filterpane bug.
209            params.sort = null
210        if(params.sort && params.order) {
211            def sort = "task." + params.sort
212            def order = (params.order == "asc") ? "asc" : "desc"
213            orderBy = " order by " + sort + ' ' + order
214        }
215        else
216            orderBy = " order by task.taskStatus, task.taskPriority, task.targetStartDate"
217
218        def namedParams = [:]
219        namedParams.person = person ?: authService.currentUser
220        namedParams.startDate = startDate ?: dateUtilService.today
221        namedParams.endDate = endDate ?: dateUtilService.tomorrow
222
223        def baseQuery = "from Task as task \
224                                        left join task.assignedPersons as assignedPersonOfTask \
225                                        left join assignedPersonOfTask.person as assignedPerson \
226                                        left join task.assignedGroups as assignedGroupOfTask \
227                                        left join assignedGroupOfTask.personGroup as personGroup \
228                                        left join personGroup.persons as assignedPersonViaGroup \
229                                        left join task.taskModifications as taskModification \
230                                        left join taskModification.person as createdBy \
231                                        left join taskModification.taskModificationType as taskModificationType \
232                                        where (task.trash = false \
233                                                    and task.targetStartDate < :endDate \
234                                                    and task.targetCompletionDate >= :startDate \
235                                                    and ( \
236                                                        (taskModificationType.id = 1 \
237                                                        and createdBy = :person \
238                                                        and task.leadPerson = :person) \
239                                                        or ( \
240                                                            task.approved = true \
241                                                            and ( \
242                                                                task.leadPerson = :person \
243                                                                or assignedPerson = :person \
244                                                                or assignedPersonViaGroup = :person \
245                                                            ) \
246                                                        ) \
247                                                    ) \
248                                        )"
249
250        def searchQuery = "select distinct task " + baseQuery + orderBy
251        def list = Task.executeQuery(searchQuery, namedParams, paginateParams)
252
253        def countQuery = "select count(distinct task) as taskCount " + baseQuery
254        def totalCount = Task.executeQuery(countQuery, namedParams)[0].toInteger()
255
256        def taskInstanceList = new PagedResultList(list, totalCount)
257        return taskInstanceList
258    } // getPersonsTasks()
259
260    /**
261    * Get tasks by budget status, by default planned in the last week.
262    * @param params The request params.
263    * @param budgetStatus Defaults to planned.
264    * @param startDate The start date to get tasks for, defaults to the start of today and is inclusive (greater than or equal to).
265    * @param endDate The end date to get tasks for, defaults to the start of tomorrow and is exclusive (less than).
266    */
267    def getBudgetTasks(params, taskBudgetStatus=null, startDate=null, endDate=null) {
268        def paginateParams = [:]
269        paginateParams.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
270        paginateParams.offset = params?.offset?.toInteger() ?: 0
271
272        def sort = "task." + (params?.sort ?: "targetStartDate")
273        def order = params?.order == "desc" ? "desc" : "asc"
274        def orderBy = " order by " + sort + ' ' + order
275
276        def namedParams = [:]
277        namedParams.taskBudgetStatus = taskBudgetStatus ?: TaskBudgetStatus.read(2) // Planned.
278        namedParams.startDate = startDate ?: dateUtilService.today
279        namedParams.endDate = endDate ?: dateUtilService.tomorrow
280
281        def baseQuery = "from Task as task \
282                                        where (task.trash = false \
283                                                    and task.taskBudgetStatus = :taskBudgetStatus \
284                                                    and task.targetStartDate < :endDate \
285                                                    and task.targetCompletionDate >= :startDate \
286                                        )"
287
288        def searchQuery = "select distinct task " + baseQuery + orderBy
289        def list = Task.executeQuery(searchQuery, namedParams, paginateParams)
290
291        def countQuery = "select count(distinct task) as taskCount " + baseQuery
292        def totalCount = Task.executeQuery(countQuery, namedParams)[0].toInteger()
293
294        def taskInstanceList = new PagedResultList(list, totalCount)
295        return taskInstanceList
296    } // getBudgetTasks()
297
298    /**
299    * Get work done by person and date.
300    * A person ID and date may be specified in params otherwise the current user and today are used.
301    * @param params The request params.
302    * @returns A map containing entries, totalEntries, startOfDay, person, totalHours, totalMinutes.
303    */
304    def getWorkDone(params, locale) {
305        def result = [:]
306        result.person = params.person?.id ? Person.get(params.person.id.toInteger()) : authService.currentUser
307
308        if(params.date_year && params.date_month && params.date_day)
309            result.startOfDay = dateUtilService.makeDate(params.date_year, params.date_month, params.date_day)
310        else
311            result.startOfDay = dateUtilService.today
312
313        result.startOfNextDay = result.startOfDay + 1
314
315        def formattedStartOfDay = g.formatDate(format: "EEE, dd-MMM-yyyy", date: result.startOfDay)
316
317        def getMessage = { Map m ->
318            messageSource.getMessage(m.code, m.args == null ? null : m.args.toArray(), locale)
319        }
320
321        result.entries = Entry.createCriteria().list() {
322            eq("enteredBy", result.person)
323            ge("dateDone", result.startOfDay)
324            lt("dateDone", result.startOfNextDay)
325            entryType {
326                eq("id", 3L)
327            }
328        } // createCriteria
329
330        result.totalEntries = result.entries.size()
331
332        if(result.totalEntries > 0)
333            result.message = getMessage(code:"task.search.text.work.done.message",
334                                                                args:[result.person, formattedStartOfDay])
335        else
336            result.message = getMessage(code:"task.search.text.work.done.none.found",
337                                                                args:[result.person, formattedStartOfDay])
338
339        result.totalHours = 0
340        result.totalMinutes = 0
341        result.entries.each() {
342            result.totalMinutes += (it.durationHour*60) + it.durationMinute
343        }
344        result.totalHours = (result.totalMinutes / 60).toInteger()
345        result.totalMinutes = result.totalMinutes % 60
346
347        return result
348    } // getWorkDone()
349
350} // end class
Note: See TracBrowser for help on using the repository browser.