source: trunk/grails-app/services/InventoryItemSearchService.groovy @ 566

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

Improvements to inventory text search, add inventoryGroup and hide Limit Search unless one of the values is true.

File size: 10.4 KB
Line 
1import grails.orm.PagedResultList
2import org.compass.core.engine.SearchEngineQueryParseException
3
4/**
5* Service class that encapsulates the business logic for InventoryItem searches.
6*/
7class InventoryItemSearchService {
8
9    boolean transactional = false
10
11    def dateUtilService
12    def messageSource
13
14    def paramsMax = 100000
15
16    /**
17    * Selects and returns the correct search results based on the supplied quickSearch.
18    * @param params The request params, may contain params.quickSearch string to specify the search.
19    * @param locale The locale to use when generating result.message.
20    */
21    def getQuickSearch(params, locale) {
22        def result = [:]
23        result.quickSearch = params.quickSearch ?: "all"
24
25        def getMessage = { Map m ->
26            messageSource.getMessage(m.code, m.args == null ? null : m.args.toArray(), locale)
27        }
28
29        switch (result.quickSearch) {
30            case "inventoryBelowReorder":
31                result.inventoryItemList = getInventoryBelowReorder(params)
32                if(result.inventoryItemList.totalCount > 0)
33                    result.message = getMessage(code:"inventoryItem.search.text.below.reorder.description")
34                else
35                    result.message = getMessage(code:"inventoryItem.search.text.below.reorder.none.found")
36                break
37            case "inventoryBelowReorderAll":
38                result.inventoryItemList = getInventoryBelowReorder(params, false)
39                if(result.inventoryItemList.totalCount > 0)
40                    result.message = getMessage(code:"inventoryItem.search.text.below.reorder.all.description")
41                else
42                    result.message = getMessage(code:"inventoryItem.search.text.below.reorder.none.found")
43                break
44            case "recentlyUsed":
45                result.daysBack = params.daysBack?.isInteger() ? params.daysBack.toInteger() : 14
46                result.inventoryItemList = getRecentlyUsed(params, result.daysBack)
47                if(result.inventoryItemList.totalCount > 0)
48                    result.message = getMessage(code:"inventoryItem.search.text.recently.used.description", args:[result.daysBack])
49                else
50                    result.message = getMessage(code:"inventoryItem.search.text.recently.used.none.found", args:[result.daysBack])
51                break
52            default:
53                result.inventoryItemList = getAll(params)
54                if(result.inventoryItemList.totalCount > 0)
55                    result.message = getMessage(code:"inventoryItem.search.text.all.description")
56                else
57                    result.message = getMessage(code:"inventoryItem.search.text.all.none.found")
58                break
59        } // switch.
60
61        // Success.
62        return result
63
64    } // getQuickSearch
65
66    /**
67    * Get all inventory items.
68    * @param params The request params.
69    */
70    def getAll(params) {
71        params.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
72        params.offset = params?.offset?.toInteger() ?: 0
73        params.sort = params?.sort ?: "name"
74        params.order = params?.order ?: "asc"
75
76        def inventoryItemList = InventoryItem.createCriteria().list(
77            max: params.max,
78            offset: params.offset,
79            sort: params.sort,
80            order: params.order) {
81            } // createCriteria
82    } // getAll
83
84    /**
85    * List inventory items that are below reorder point.
86    * @param params The request params.
87    * @param onlyReorderEnabled Only include items with reorder enabled, defaults to true.
88    */
89    def getInventoryBelowReorder(params, onlyReorderEnabled=true) {
90        params.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
91        params.offset = params?.offset?.toInteger() ?: 0
92        params.sort = params?.sort ?: "name"
93        params.order = params?.order ?: "asc"
94
95        def inventoryItemList = InventoryItem.createCriteria().list(
96            max: params.max,
97            offset: params.offset,
98            sort: params.sort,
99            order: params.order) {
100                eq("isActive", true)
101                if(onlyReorderEnabled)
102                    eq("enableReorder", true)
103                leProperty("unitsInStock", "reorderPoint")
104            } // createCriteria
105    } // getInventoryBelowReorder
106
107    /**
108    * Get a list of recently used inventory items.
109    * @param params The request params.
110    * @param daysBack The number of days back to get results for.
111    */
112    def getRecentlyUsed(params, daysBack) {
113        def paginateParams = [:]
114        paginateParams.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
115        paginateParams.offset = params?.offset?.toInteger() ?: 0
116
117        def sort = "inventoryItem." + (params?.sort ?: "name")
118        def order = params?.order == "desc" ? "desc" : "asc"
119        def orderBy = " order by " + sort + ' ' + order
120
121        def namedParams = [:]
122        namedParams.startOfDay = dateUtilService.today - daysBack
123
124        def baseQuery = "from InventoryItem as inventoryItem \
125                                        left join inventoryItem.inventoryMovements as inventoryMovement \
126                                        where (inventoryItem.isActive = true \
127                                                    and inventoryMovement.date > :startOfDay \
128                                                    and inventoryMovement.inventoryMovementType = 1 \
129                                                    )"
130
131        def searchQuery = "select distinct inventoryItem " + baseQuery + orderBy
132        def list = InventoryItem.executeQuery(searchQuery, namedParams, paginateParams)
133
134        def countQuery = "select count(distinct inventoryItem) as inventoryItemCount " + baseQuery
135        def totalCount = InventoryItem.executeQuery(countQuery, namedParams)[0].toInteger()
136
137        def inventoryItemInstanceList = new PagedResultList(list, totalCount)
138        return inventoryItemInstanceList
139    } // getRecentlyUsed
140
141    /**
142    * Get a list of inventory items by search text.
143    * @param params The request params.
144    * @param locale The locale to use when generating result.message.
145    */
146    def getTextSearch(params, locale) {
147        def result = [:]
148        result.searchText = params.searchText.trim() ?: ""
149
150        def getMessage = { Map m ->
151            messageSource.getMessage(m.code, m.args == null ? null : m.args.toArray(), locale)
152        }
153
154        params.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
155        params.offset = params?.offset?.toInteger() ?: 0
156        params.sort = params?.sort ?: "id"
157        params.order = params?.order ?: "asc"
158
159        // Build searchableParams.
160        // Do not include params.sort, since not all properites are indexed.
161        def searchableParams = [:]
162        searchableParams.max = params.max
163        searchableParams.offset = params.offset
164        searchableParams.reload = true
165        searchableParams.defaultOperator =  'or'
166        def properitesList = []
167        if(params.searchName)
168            properitesList << '$/InventoryItem/name'
169        if(params.searchDescription)
170            properitesList << '$/InventoryItem/description'
171        if(params.searchComment)
172            properitesList << '$/InventoryItem/comment'
173        if(params.searchLocation)
174            properitesList << '$/InventoryItem/inventoryLocation/name'
175        if(params.searchGroup)
176            properitesList << '$/InventoryItem/inventoryGroup/name'
177        if(params.searchSpareFor) {
178            properitesList << '$/InventoryItem/spareFor/name'
179            properitesList << '$/InventoryItem/spareFor/description'
180            properitesList << '$/InventoryItem/spareFor/comment'
181        }
182        if(properitesList)
183            searchableParams.properties = properitesList
184
185        // Require isActive and isObsolete.
186        def queryString = '( '+result.searchText+' )'+ ' AND isActive:"true" AND isObsolete:"false"'
187
188        // Perform the searchable query.
189        try {
190            result.inventoryItemList = InventoryItem.search(queryString, searchableParams)
191
192            // Would be nice if this worked.
193//             result.inventoryItemList = InventoryItem.search(result.searchText, searchableParams) {
194//                 must(term("isActive", true))
195//                 must(term("isObsolete", false))
196//             }
197
198        } catch (e) {
199            log.error e
200            result.inventoryItemList = [:]
201            result.inventoryItemList.results = []
202            result.inventoryItemList.total = 0
203        }
204
205        // Sort the returned instances.
206        if(params.sort != 'id') {
207            if(params.order == 'asc') {
208                if(params.sort == 'name' || params.sort == 'description')
209                    result.inventoryItemList.results.sort { p1, p2 -> p1[params.sort].compareToIgnoreCase(p2[params.sort]) }
210                else if(params.sort == 'inventoryGroup') {
211                    result.inventoryItemList.results.sort { p1, p2 ->
212                        p1.inventoryGroup.name.compareToIgnoreCase(p2.inventoryGroup.name)
213                    }
214                }
215                else if(params.sort == 'unitsInStock')
216                    result.inventoryItemList.results.sort {p1, p2 -> p1[params.sort]  <=> p2[params.sort] }
217            } // asc.
218            else {
219                if(params.sort == 'name' || params.sort == 'description')
220                    result.inventoryItemList.results.sort { p1, p2 -> p2[params.sort].compareToIgnoreCase(p1[params.sort]) }
221                else if(params.sort == 'inventoryGroup') {
222                    result.inventoryItemList.results.sort { p1, p2 ->
223                        p2.inventoryGroup.name.compareToIgnoreCase(p1.inventoryGroup.name)
224                    }
225                }
226                else if(params.sort == 'unitsInStock')
227                    result.inventoryItemList.results.sort {p1, p2 -> p2[params.sort] <=> p1[params.sort]}
228            } // desc.
229        } // sort.
230
231        // Create a PagedResultList.
232        result.inventoryItemList = new PagedResultList(result.inventoryItemList.results, result.inventoryItemList.total)
233
234        // Get the result message.
235        if(result.inventoryItemList.totalCount > 0)
236            result.message = getMessage(code:"inventoryItem.search.text.found", args: [result.searchText])
237        else
238            result.message = getMessage(code:"inventoryItem.search.text.none.found", args: [result.searchText])
239
240        // Success.
241        return result
242
243    } // getTextSearch()
244
245} // end class
Note: See TracBrowser for help on using the repository browser.