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 = [:] def currentUser = authService.currentUser result.quickSearch = params.quickSearch ?: "searchPlannersRange" def getMessage = { Map m -> messageSource.getMessage(m.code, m.args == null ? null : m.args.toArray(), locale) } switch (result.quickSearch) { case "myTodays": result.taskInstanceList = getMyTodays(params) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.my.todays", args:[currentUser]) else result.message = getMessage(code:"task.search.text.my.todays.none.found", args:[currentUser]) break case "myYesterdays": result.taskInstanceList = getMyTodays(params, -1) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.my.yesterdays", args:[currentUser]) else result.message = getMessage(code:"task.search.text.my.yesterdays.none.found", args:[currentUser]) break case "myTomorrows": result.taskInstanceList = getMyTodays(params, 1) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.my.tomorrows", args:[currentUser]) else result.message = getMessage(code:"task.search.text.my.tomorrows.none.found", args:[currentUser]) break case "myPastWeek": result.taskInstanceList = getMyPastWeek(params) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.my.past.week", args:[currentUser]) else result.message = getMessage(code:"task.search.text.my.past.week.none.found", args:[currentUser]) break case "todays": result.taskInstanceList = getTodays(params) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.todays") else result.message = getMessage(code:"task.search.text.todays.none.found") break case "yesterdays": result.taskInstanceList = getTodays(params, -1) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.yesterdays") else result.message = getMessage(code:"task.search.text.yesterdays.none.found") break case "tomorrows": result.taskInstanceList = getTodays(params, 1) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.tomorrows") else result.message = getMessage(code:"task.search.text.tomorrows.none.found") break case "pastWeek": result.taskInstanceList = getPastWeek(params) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.past.week") else result.message = getMessage(code:"task.search.text.past.week.none.found") break case "budgetUnplanned": result.taskInstanceList = getBudgetUnplanned(params) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.budget.unplanned") else result.message = getMessage(code:"task.search.text.budget.unplanned.none.found") break case "budgetPlanned": result.taskInstanceList = getBudgetPlanned(params) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.budget.planned") else result.message = getMessage(code:"task.search.text.budget.planned.none.found") break default: result.taskInstanceList = getPlannersRange(params) if(result.taskInstanceList.totalCount > 0) result.message = getMessage(code:"task.search.text.planners.range") else result.message = getMessage(code:"task.search.text.planners.range.none.found") break } // switch. // Success. return result } // getQuickSearch /** * Get all tasks that are not in the trash, by default today's tasks. * @param params The request params. * @param dayAdjustment The number of days to adjust from today, defaults to 0. */ def getTodays(params, dayAdjustment=0) { params.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax) params.offset = params?.offset?.toInteger() ?: 0 params.sort = params?.sort ?: "attentionFlag" params.order = params?.order ?: "desc" def taskInstanceList = Task.createCriteria().list( max: params.max, offset: params.offset, sort: params.sort, order: params.order) { lt("targetStartDate", dateUtilService.tomorrow+dayAdjustment) ge("targetCompletionDate", dateUtilService.today+dayAdjustment) eq("trash", false) } // createCriteria } /** * Get current user's tasks, by default today's tasks. * "Approved tasks where I am the lead or have been assigned" * @param params The request params. * @param dayAdjustment The number of days to adjust from today, defaults to 0. */ def getMyTodays(params, dayAdjustment=0) { 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.currentUser = authService.currentUser namedParams.startOfDay = dateUtilService.today+dayAdjustment namedParams.startOfNextDay = dateUtilService.tomorrow+dayAdjustment 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 \ where (task.trash = false \ and task.approved = true \ and ( \ task.targetStartDate < :startOfNextDay \ and task.targetCompletionDate >= :startOfDay \ ) \ and ( \ task.leadPerson = :currentUser \ or assignedPerson = :currentUser \ or assignedPersonViaGroup = :currentUser \ ) \ )" 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 } // getMyTodays /** * Get all tasks that are not in the trash, during the past week. * @param params The request params. */ def getPastWeek(params) { params.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax) params.offset = params?.offset?.toInteger() ?: 0 params.sort = params?.sort ?: "attentionFlag" params.order = params?.order ?: "desc" def taskInstanceList = Task.createCriteria().list( max: params.max, offset: params.offset, sort: params.sort, order: params.order) { lt("targetStartDate", dateUtilService.tomorrow) ge("targetCompletionDate", dateUtilService.oneWeekAgo) eq("trash", false) } // createCriteria } /** * Get current user's tasks in the past week. * "Approved tasks where I am the lead or have been assigned" * @param params The request params. */ def getMyPastWeek(params) { 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.currentUser = authService.currentUser namedParams.startOfDay = dateUtilService.oneWeekAgo namedParams.startOfNextDay = 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 \ where (task.trash = false \ and task.approved = true \ and ( \ task.targetStartDate < :startOfNextDay \ and task.targetCompletionDate >= :startOfDay \ ) \ and ( \ task.leadPerson = :currentUser \ or assignedPerson = :currentUser \ or assignedPersonViaGroup = :currentUser \ ) \ )" 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 } // getMyTodays /** * "Tasks with budget status of Planned, in the past week." * @param params The request params. */ def getBudgetPlanned(params) { 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" def taskInstanceList = Task.createCriteria().list( max: params.max, offset: params.offset, sort: params.sort, order: params.order) { eq("taskBudgetStatus", TaskBudgetStatus.read(2)) lt("targetStartDate", dateUtilService.tomorrow) ge("targetCompletionDate", dateUtilService.oneWeekAgo) eq("trash", false) } // createCriteria } /** * "Tasks with budget status of Unplanned, in the past week." * @param params The request params. */ def getBudgetUnplanned(params) { 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" def taskInstanceList = Task.createCriteria().list( max: params.max, offset: params.offset, sort: params.sort, order: params.order) { eq("taskBudgetStatus", TaskBudgetStatus.read(1)) lt("targetStartDate", dateUtilService.tomorrow) ge("targetCompletionDate", dateUtilService.oneWeekAgo) eq("trash", false) } // createCriteria } /** * "Tasks in the past week and two weeks ahead." * @param params The request params. */ def getPlannersRange(params) { 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" def taskInstanceList = Task.createCriteria().list( max: params.max, offset: params.offset, sort: params.sort, order: params.order) { ge("targetStartDate", dateUtilService.oneWeekAgo) lt("targetStartDate", dateUtilService.today + 15) eq("trash", false) } // createCriteria } /** * Get work done by person and date. * A person ID and date may be specified in params otherwise the currentUser 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 } } // end class