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

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

Domain change, rename InventoryItem property enableReorder to enableReorderListing as per ticket #75.

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("enableReorderListing", 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.