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

Last change on this file since 639 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
RevLine 
[479]1import grails.orm.PagedResultList
2
[476]3/**
4* Service class that encapsulates the business logic for Task searches.
5*/
[143]6class TaskSearchService {
7
8    boolean transactional = false
9
[476]10    def authService
[143]11    def dateUtilService
[476]12    def messageSource
[143]13
[490]14    def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()
15
[476]16    def paramsMax = 100000
[260]17
[476]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 = [:]
[503]25        result.quickSearch = params.quickSearch ?: "plannersRange"
26
[476]27        def currentUser = authService.currentUser
[503]28        def startOfToday = dateUtilService.today
29        def startOfYesterday = dateUtilService.yesterday
30        def startOfTomorrow = dateUtilService.tomorrow
31        def oneWeekAgo = dateUtilService.oneWeekAgo
[476]32
[503]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
[476]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":
[503]44                result.taskInstanceList = getPersonsTasks(params)
[476]45                if(result.taskInstanceList.totalCount > 0)
[503]46                    result.message = getMessage(code:"task.search.text.persons.tasks.message",
47                                                                    args:[currentUser, formattedStartOfToday])
[476]48                else
[503]49                    result.message = getMessage(code:"task.search.text.persons.tasks.none.found",
50                                                                    args:[currentUser, formattedStartOfToday])
[476]51                break
52            case "myYesterdays":
[503]53                result.taskInstanceList = getPersonsTasks(params, currentUser, startOfYesterday, startOfToday)
[476]54                if(result.taskInstanceList.totalCount > 0)
[503]55                    result.message = getMessage(code:"task.search.text.persons.tasks.message",
56                                                                    args:[currentUser, formattedStartOfYesterday])
[476]57                else
[503]58                    result.message = getMessage(code:"task.search.text.persons.tasks.none.found",
59                                                                    args:[currentUser, formattedStartOfYesterday])
[476]60                break
61            case "myTomorrows":
[503]62                result.taskInstanceList = getPersonsTasks(params, currentUser, startOfTomorrow, startOfTomorrow+1)
[476]63                if(result.taskInstanceList.totalCount > 0)
[503]64                    result.message = getMessage(code:"task.search.text.persons.tasks.message",
65                                                                    args:[currentUser, formattedStartOfTomorrow])
[476]66                else
[503]67                    result.message = getMessage(code:"task.search.text.persons.tasks.none.found",
68                                                                    args:[currentUser, formattedStartOfTomorrow])
[476]69                break
70            case "myPastWeek":
[503]71                result.taskInstanceList = getPersonsTasks(params, currentUser, oneWeekAgo, startOfTomorrow)
[476]72                if(result.taskInstanceList.totalCount > 0)
[503]73                    result.message = getMessage(code:"task.search.text.persons.tasks.between.message",
74                                                                    args:[currentUser, formattedOneWeekAgo, formattedStartOfToday])
[476]75                else
[503]76                    result.message = getMessage(code:"task.search.text.persons.tasks.between.none.found",
77                                                                    args:[currentUser, formattedOneWeekAgo, formattedStartOfToday])
[476]78                break
79            case "todays":
[503]80                result.taskInstanceList = getTasks(params)
[476]81                if(result.taskInstanceList.totalCount > 0)
[503]82                    result.message = getMessage(code:"task.search.text.all.tasks.message",
83                                                                    args:[formattedStartOfToday])
[476]84                else
[503]85                    result.message = getMessage(code:"task.search.text.all.tasks.none.found",
86                                                                    args:[formattedStartOfToday])
[476]87                break
88            case "yesterdays":
[503]89                result.taskInstanceList = getTasks(params, startOfYesterday, startOfToday)
[476]90                if(result.taskInstanceList.totalCount > 0)
[503]91                    result.message = getMessage(code:"task.search.text.all.tasks.message",
92                                                                    args:[formattedStartOfYesterday])
[476]93                else
[503]94                    result.message = getMessage(code:"task.search.text.all.tasks.none.found",
95                                                                    args:[formattedStartOfYesterday])
[476]96                break
97            case "tomorrows":
[503]98                result.taskInstanceList = getTasks(params, startOfTomorrow, startOfTomorrow+1)
[476]99                if(result.taskInstanceList.totalCount > 0)
[503]100                    result.message = getMessage(code:"task.search.text.all.tasks.message",
101                                                                    args:[formattedStartOfTomorrow])
[476]102                else
[503]103                    result.message = getMessage(code:"task.search.text.all.tasks.none.found",
104                                                                    args:[formattedStartOfTomorrow])
[476]105                break
106            case "pastWeek":
[503]107                result.taskInstanceList = getTasks(params, oneWeekAgo, startOfTomorrow)
[476]108                if(result.taskInstanceList.totalCount > 0)
[503]109                    result.message = getMessage(code:"task.search.text.all.tasks.between.message",
110                                                                    args:[formattedOneWeekAgo, formattedStartOfToday])
[476]111                else
[503]112                    result.message = getMessage(code:"task.search.text.all.tasks.between.none.found",
113                                                                    args:[formattedOneWeekAgo, formattedStartOfToday])
[476]114                break
115            case "budgetUnplanned":
[503]116                result.taskInstanceList = getBudgetTasks(params, TaskBudgetStatus.read(1), oneWeekAgo, startOfTomorrow)
[476]117                if(result.taskInstanceList.totalCount > 0)
[503]118                    result.message = getMessage(code:"task.search.text.budget.unplanned.message",
119                                                                    args:[formattedOneWeekAgo, formattedStartOfToday])
[476]120                else
[503]121                    result.message = getMessage(code:"task.search.text.budget.unplanned.none.found",
122                                                                    args:[formattedOneWeekAgo, formattedStartOfToday])
[476]123                break
124            case "budgetPlanned":
[503]125                result.taskInstanceList = getBudgetTasks(params, TaskBudgetStatus.read(2), oneWeekAgo, startOfTomorrow)
[476]126                if(result.taskInstanceList.totalCount > 0)
[503]127                    result.message = getMessage(code:"task.search.text.budget.planned.message",
128                                                                    args:[formattedOneWeekAgo, formattedStartOfToday])
[476]129                else
[503]130                    result.message = getMessage(code:"task.search.text.budget.planned.none.found",
131                                                                    args:[formattedOneWeekAgo, formattedStartOfToday])
[476]132                break
133            default:
[503]134                //case "plannersRange":
135                result.taskInstanceList = getTasks(params, oneWeekAgo, startOfToday+15)
[476]136                if(result.taskInstanceList.totalCount > 0)
[503]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)])
[476]140                else
[503]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)])
[476]144                break
145        } // switch.
146
147        // Success.
148        return result
149
150    } // getQuickSearch
151
[479]152    /**
[503]153    * Get all tasks that are not in the trash bin, by default today's tasks.
[479]154    * @param params The request params.
[503]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).
[479]157    */
[503]158    def getTasks(params, startDate=null, endDate=null) {
[512]159        def paginateParams = [:]
160        paginateParams.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
161        paginateParams.offset = params?.offset?.toInteger() ?: 0
[143]162
[582]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"
[143]173
[512]174        def namedParams = [:]
175        namedParams.startDate = startDate ?: dateUtilService.today
176        namedParams.endDate = endDate ?: dateUtilService.tomorrow
[144]177
[512]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
[479]194    /**
[503]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"
[479]197    * @param params The request params.
[503]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).
[479]201    */
[503]202    def getPersonsTasks(params, person=null, startDate=null, endDate=null) {
[479]203        def paginateParams = [:]
204        paginateParams.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
205        paginateParams.offset = params?.offset?.toInteger() ?: 0
[144]206
[582]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"
[476]217
[479]218        def namedParams = [:]
[503]219        namedParams.person = person ?: authService.currentUser
220        namedParams.startDate = startDate ?: dateUtilService.today
221        namedParams.endDate = endDate ?: dateUtilService.tomorrow
[165]222
[479]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 \
[511]229                                        left join task.taskModifications as taskModification \
230                                        left join taskModification.person as createdBy \
231                                        left join taskModification.taskModificationType as taskModificationType \
[479]232                                        where (task.trash = false \
[511]233                                                    and task.targetStartDate < :endDate \
234                                                    and task.targetCompletionDate >= :startDate \
[479]235                                                    and ( \
[511]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                                                            ) \
[479]246                                                        ) \
[511]247                                                    ) \
248                                        )"
[479]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
[503]258    } // getPersonsTasks()
[479]259
260    /**
[503]261    * Get tasks by budget status, by default planned in the last week.
[479]262    * @param params The request params.
[503]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).
[479]266    */
[529]267    def getBudgetTasks(params, taskBudgetStatus=null, startDate=null, endDate=null) {
[524]268        def paginateParams = [:]
269        paginateParams.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
270        paginateParams.offset = params?.offset?.toInteger() ?: 0
[165]271
[524]272        def sort = "task." + (params?.sort ?: "targetStartDate")
273        def order = params?.order == "desc" ? "desc" : "asc"
274        def orderBy = " order by " + sort + ' ' + order
[165]275
[524]276        def namedParams = [:]
[529]277        namedParams.taskBudgetStatus = taskBudgetStatus ?: TaskBudgetStatus.read(2) // Planned.
[524]278        namedParams.startDate = startDate ?: dateUtilService.today
[529]279        namedParams.endDate = endDate ?: dateUtilService.tomorrow
[524]280
281        def baseQuery = "from Task as task \
282                                        where (task.trash = false \
[529]283                                                    and task.taskBudgetStatus = :taskBudgetStatus \
[524]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
[503]296    } // getBudgetTasks()
[476]297
[479]298    /**
[490]299    * Get work done by person and date.
[503]300    * A person ID and date may be specified in params otherwise the current user and today are used.
[490]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
[503]348    } // getWorkDone()
[490]349
350} // end class
Note: See TracBrowser for help on using the repository browser.