import grails.orm.PagedResultList /** * Service class that encapsulates the business logic for Task searches. */ class TaskSearchService { boolean transactional = false def authService def dateUtilService def messageSource def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib() def paramsMax = 100000 /** * Selects and returns the correct search results based on the supplied quickSearch. * @param params The request params, may contain params.quickSearch string to specify the search. * @param locale The locale to use when generating result.message. */ def getQuickSearch(params, locale) { def result = [:] result.quickSearch = params.quickSearch ?: "plannersRange" def currentUser = authService.currentUser def startOfToday = dateUtilService.today def startOfYesterday = dateUtilService.yesterday def startOfTomorrow = dateUtilService.tomorrow def oneWeekAgo = dateUtilService.oneWeekAgo def formattedStartOfToday = g.formatDate(format: "EEE, dd-MMM-yyyy", date: startOfToday) def formattedStartOfYesterday = g.formatDate(format: "EEE, dd-MMM-yyyy", date: startOfYesterday) def formattedStartOfTomorrow = g.formatDate(format: "EEE, dd-MMM-yyyy", date: startOfTomorrow) def formattedOneWeekAgo = g.formatDate(format: "EEE, dd-MMM-yyyy", date: oneWeekAgo) def getMessage = { Map m -> messageSource.getMessage(m.code, m.args == null ? null : m.args.toArray(), locale) } switch (result.quickSearch) { case "myTodays": result.taskInstanceList = getPersonsTasks(params) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.persons.tasks.message", args:[currentUser, formattedStartOfToday]) else result.message = getMessage(code:"task.search.text.persons.tasks.none.found", args:[currentUser, formattedStartOfToday]) break case "myYesterdays": result.taskInstanceList = getPersonsTasks(params, currentUser, startOfYesterday, startOfToday) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.persons.tasks.message", args:[currentUser, formattedStartOfYesterday]) else result.message = getMessage(code:"task.search.text.persons.tasks.none.found", args:[currentUser, formattedStartOfYesterday]) break case "myTomorrows": result.taskInstanceList = getPersonsTasks(params, currentUser, startOfTomorrow, startOfTomorrow+1) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.persons.tasks.message", args:[currentUser, formattedStartOfTomorrow]) else result.message = getMessage(code:"task.search.text.persons.tasks.none.found", args:[currentUser, formattedStartOfTomorrow]) break case "myPastWeek": result.taskInstanceList = getPersonsTasks(params, currentUser, oneWeekAgo, startOfTomorrow) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.persons.tasks.between.message", args:[currentUser, formattedOneWeekAgo, formattedStartOfToday]) else result.message = getMessage(code:"task.search.text.persons.tasks.between.none.found", args:[currentUser, formattedOneWeekAgo, formattedStartOfToday]) break case "todays": result.taskInstanceList = getTasks(params) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.all.tasks.message", args:[formattedStartOfToday]) else result.message = getMessage(code:"task.search.text.all.tasks.none.found", args:[formattedStartOfToday]) break case "yesterdays": result.taskInstanceList = getTasks(params, startOfYesterday, startOfToday) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.all.tasks.message", args:[formattedStartOfYesterday]) else result.message = getMessage(code:"task.search.text.all.tasks.none.found", args:[formattedStartOfYesterday]) break case "tomorrows": result.taskInstanceList = getTasks(params, startOfTomorrow, startOfTomorrow+1) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.all.tasks.message", args:[formattedStartOfTomorrow]) else result.message = getMessage(code:"task.search.text.all.tasks.none.found", args:[formattedStartOfTomorrow]) break case "pastWeek": result.taskInstanceList = getTasks(params, oneWeekAgo, startOfTomorrow) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.all.tasks.between.message", args:[formattedOneWeekAgo, formattedStartOfToday]) else result.message = getMessage(code:"task.search.text.all.tasks.between.none.found", args:[formattedOneWeekAgo, formattedStartOfToday]) break case "budgetUnplanned": result.taskInstanceList = getBudgetTasks(params, TaskBudgetStatus.read(1), oneWeekAgo, startOfTomorrow) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.budget.unplanned.message", args:[formattedOneWeekAgo, formattedStartOfToday]) else result.message = getMessage(code:"task.search.text.budget.unplanned.none.found", args:[formattedOneWeekAgo, formattedStartOfToday]) break case "budgetPlanned": result.taskInstanceList = getBudgetTasks(params, TaskBudgetStatus.read(2), oneWeekAgo, startOfTomorrow) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.budget.planned.message", args:[formattedOneWeekAgo, formattedStartOfToday]) else result.message = getMessage(code:"task.search.text.budget.planned.none.found", args:[formattedOneWeekAgo, formattedStartOfToday]) break default: //case "plannersRange": result.taskInstanceList = getTasks(params, oneWeekAgo, startOfToday+15) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.all.tasks.between.message", args:[formattedOneWeekAgo, g.formatDate(format: "EEE, dd-MMM-yyyy", date: startOfToday+14)]) else result.message = getMessage(code:"task.search.text.all.tasks.between.none.found", args:[formattedOneWeekAgo, g.formatDate(format: "EEE, dd-MMM-yyyy", date: startOfToday+14)]) break } // switch. // Success. return result } // getQuickSearch /** * Get all tasks that are not in the trash bin, by default today's tasks. * @param params The request params. * @param startDate The start date to get tasks for, defaults to the start of today and is inclusive (greater than or equal to). * @param endDate The end date to get tasks for, defaults to the start of tomorrow and is exclusive (less than). */ def getTasks(params, startDate=null, endDate=null) { def paginateParams = [:] paginateParams.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax) paginateParams.offset = params?.offset?.toInteger() ?: 0 def sort = "task." + (params?.sort ?: "attentionFlag") def order = params?.order == "asc" ? "asc" : "desc" def orderBy = " order by " + sort + ' ' + order def namedParams = [:] namedParams.startDate = startDate ?: dateUtilService.today namedParams.endDate = endDate ?: dateUtilService.tomorrow def baseQuery = "from Task as task \ where (task.trash = false \ and task.targetStartDate < :endDate \ and task.targetCompletionDate >= :startDate \ )" def searchQuery = "select distinct task " + baseQuery + orderBy def list = Task.executeQuery(searchQuery, namedParams, paginateParams) def countQuery = "select count(distinct task) as taskCount " + baseQuery def totalCount = Task.executeQuery(countQuery, namedParams)[0].toInteger() def taskInstanceList = new PagedResultList(list, totalCount) return taskInstanceList } // getPTasks() /** * Get a person's tasks, by default current user and today's tasks. * "My tasks and approved tasks that I am assigned to" * @param params The request params. * @param person The person to get tasks for, defaults to current user. * @param startDate The start date to get tasks for, defaults to the start of today and is inclusive (greater than or equal to). * @param endDate The end date to get tasks for, defaults to the start of tomorrow and is exclusive (less than). */ def getPersonsTasks(params, person=null, startDate=null, endDate=null) { def paginateParams = [:] paginateParams.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax) paginateParams.offset = params?.offset?.toInteger() ?: 0 def sort = "task." + (params?.sort ?: "attentionFlag") def order = params?.order == "asc" ? "asc" : "desc" def orderBy = " order by " + sort + ' ' + order def namedParams = [:] namedParams.person = person ?: authService.currentUser namedParams.startDate = startDate ?: dateUtilService.today namedParams.endDate = endDate ?: dateUtilService.tomorrow def baseQuery = "from Task as task \ left join task.assignedPersons as assignedPersonOfTask \ left join assignedPersonOfTask.person as assignedPerson \ left join task.assignedGroups as assignedGroupOfTask \ left join assignedGroupOfTask.personGroup as personGroup \ left join personGroup.persons as assignedPersonViaGroup \ left join task.taskModifications as taskModification \ left join taskModification.person as createdBy \ left join taskModification.taskModificationType as taskModificationType \ where (task.trash = false \ and task.targetStartDate < :endDate \ and task.targetCompletionDate >= :startDate \ and ( \ (taskModificationType.id = 1 \ and createdBy = :person \ and task.leadPerson = :person) \ or ( \ task.approved = true \ and ( \ task.leadPerson = :person \ or assignedPerson = :person \ or assignedPersonViaGroup = :person \ ) \ ) \ ) \ )" def searchQuery = "select distinct task " + baseQuery + orderBy def list = Task.executeQuery(searchQuery, namedParams, paginateParams) def countQuery = "select count(distinct task) as taskCount " + baseQuery def totalCount = Task.executeQuery(countQuery, namedParams)[0].toInteger() def taskInstanceList = new PagedResultList(list, totalCount) return taskInstanceList } // getPersonsTasks() /** * Get tasks by budget status, by default planned in the last week. * @param params The request params. * @param budgetStatus Defaults to planned. * @param startDate The start date to get tasks for, defaults to the start of today and is inclusive (greater than or equal to). * @param endDate The end date to get tasks for, defaults to the start of tomorrow and is exclusive (less than). */ def getBudgetTasks(params, budgetStatus=null, startDate=null, endDate=null) { params.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax) params.offset = params?.offset?.toInteger() ?: 0 params.sort = params?.sort ?: "targetStartDate" params.order = params?.order ?: "asc" budgetStatus = budgetStatus ?: TaskBudgetStatus.read(2) // Planned. startDate = startDate ?: dateUtilService.today endDate = endDate ?: dateUtilService.tomorrow def taskInstanceList = Task.createCriteria().list( max: params.max, offset: params.offset, sort: params.sort, order: params.order) { eq("taskBudgetStatus", budgetStatus) lt("targetStartDate", dateUtilService.tomorrow) ge("targetCompletionDate", dateUtilService.oneWeekAgo) eq("trash", false) } // createCriteria } // getBudgetTasks() /** * Get work done by person and date. * A person ID and date may be specified in params otherwise the current user and today are used. * @param params The request params. * @returns A map containing entries, totalEntries, startOfDay, person, totalHours, totalMinutes. */ def getWorkDone(params, locale) { def result = [:] result.person = params.person?.id ? Person.get(params.person.id.toInteger()) : authService.currentUser if(params.date_year && params.date_month && params.date_day) result.startOfDay = dateUtilService.makeDate(params.date_year, params.date_month, params.date_day) else result.startOfDay = dateUtilService.today result.startOfNextDay = result.startOfDay + 1 def formattedStartOfDay = g.formatDate(format: "EEE, dd-MMM-yyyy", date: result.startOfDay) def getMessage = { Map m -> messageSource.getMessage(m.code, m.args == null ? null : m.args.toArray(), locale) } result.entries = Entry.createCriteria().list() { eq("enteredBy", result.person) ge("dateDone", result.startOfDay) lt("dateDone", result.startOfNextDay) entryType { eq("id", 3L) } } // createCriteria result.totalEntries = result.entries.size() if(result.totalEntries > 0) result.message = getMessage(code:"task.search.text.work.done.message", args:[result.person, formattedStartOfDay]) else result.message = getMessage(code:"task.search.text.work.done.none.found", args:[result.person, formattedStartOfDay]) result.totalHours = 0 result.totalMinutes = 0 result.entries.each() { result.totalMinutes += (it.durationHour*60) + it.durationMinute } result.totalHours = (result.totalMinutes / 60).toInteger() result.totalMinutes = result.totalMinutes % 60 return result } // getWorkDone() } // end class