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

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

Add work done by person and date feature with view and search logic.

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