source: trunk/grails-app/controllers/InventoryItemDetailedController.groovy @ 613

Last change on this file since 613 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: 22.0 KB
Line 
1import org.codehaus.groovy.grails.plugins.springsecurity.Secured
2import org.codehaus.groovy.grails.commons.ConfigurationHolder
3import com.zeddware.grails.plugins.filterpane.FilterUtils
4import org.springframework.web.servlet.support.RequestContextUtils as RCU
5
6@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager'])
7class InventoryItemDetailedController extends BaseController {
8
9    def filterService
10    def exportService
11    def inventoryCsvService
12    def inventoryItemService
13    def inventoryItemSearchService
14    def inventoryMovementService
15
16    // the delete, save and update actions only accept POST requests
17    static allowedMethods = [delete:'POST', save:'POST', update:'POST', useInventoryItem:'POST']
18
19    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
20    def index = { redirect(action:search, params:params) }
21
22    /**
23    * Set session.inventoryItemSearchParamsMax
24    */
25    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
26    def setSearchParamsMax = {
27        def max = 1000
28        if(params.newMax.isInteger()) {
29            def i = params.newMax.toInteger()
30            if(i > 0 && i <= max)
31                session.inventoryItemSearchParamsMax = params.newMax
32            if(i > max)
33                session.inventoryItemSearchParamsMax = max
34        }
35        forward(action: 'search', params: params)
36    }
37
38    /**
39    * Display the import view.
40    */
41    def importInventory = {
42    }
43
44    /**
45    * Handle the import save.
46    */
47    def importInventorySave = {
48        def result = inventoryCsvService.importInventory(request)
49
50        if(!result.error) {
51            flash.message = g.message(code: "inventory.import.success")
52            redirect(action:search)
53            return
54        }
55
56        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
57        redirect(action: importInventory)
58    }
59
60    /**
61    * Export a csv template.
62    * NOTE: IE has a 'validating' bug in dev mode that causes the export to take a long time!
63    * This does not appear to be a problem once deployed to Tomcat.
64    */
65    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
66    def exportInventoryTemplate = {
67        response.contentType = ConfigurationHolder.config.grails.mime.types["csv"]
68        response.setHeader("Content-disposition", "attachment; filename=InventoryTemplate.csv")
69        def s = inventoryCsvService.buildInventoryTemplate()
70        render s
71    }
72
73    /**
74    * Export a csv test file.
75    */
76    def exportInventoryExample = {
77        response.contentType = ConfigurationHolder.config.grails.mime.types["csv"]
78        response.setHeader("Content-disposition", "attachment; filename=InventoryExample.csv")
79        def s = inventoryCsvService.buildInventoryExample()
80        render s
81    }
82
83    /**
84    * Export the entire inventory as a csv file.
85    */
86    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
87    def exportInventory = {
88
89        def inventoryItemList = InventoryItem.list()
90
91        response.contentType = ConfigurationHolder.config.grails.mime.types["csv"]
92        response.setHeader("Content-disposition", "attachment; filename=Inventory.csv")
93        def s = inventoryCsvService.buildInventory(inventoryItemList)
94        render s
95    }
96
97    /**
98    * Display the import view for purchases.
99    */
100    def importInventoryItemPurchases = {
101    }
102
103    /**
104    * Handle the inventory purchases import save.
105    */
106    def importInventoryItemPurchasesSave = {
107        def result = inventoryCsvService.importInventoryItemPurchases(request)
108
109        if(!result.error) {
110            flash.message = g.message(code: "inventory.import.success")
111            redirect(action:search)
112            return
113        }
114
115        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
116        redirect(action: importInventoryItemPurchases)
117    }
118
119    /**
120    * Search for Inventory items.
121    */
122    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
123    def search = {
124
125        if(session.inventoryItemSearchParamsMax)
126            params.max = session.inventoryItemSearchParamsMax
127
128        // Protect filterPane.
129        params.max = Math.min( params.max ? params.max.toInteger() : 10,  1000)
130
131        def inventoryItemInstanceList = []
132        def inventoryItemInstanceTotal
133        def filterParams = com.zeddware.grails.plugins.filterpane.FilterUtils.extractFilterParams(params)
134        def isFilterApplied = FilterUtils.isFilterApplied(params)
135
136        // Restore default sort if a new text search is requested
137        if(params.newTextSearch) {
138            params.sort = 'id'
139            params.order = 'desc'
140        }
141
142        // Restore search unless a new search is being requested.
143        if(!params.searchText && !params.quickSearch && !filterParams) {
144            if(session.inventoryItemSearchText) {
145                params.searchText = session.inventoryItemSearchText
146                params.searchName = session.inventoryItemSearchName
147                params.searchDescription = session.inventoryItemSearchDescription
148                params.searchComment = session.inventoryItemSearchComment
149                params.searchLocation = session.inventoryItemSearchLocation
150                params.searchGroup = session.inventoryItemSearchGroup
151                params.searchSpareFor = session.inventoryItemSearchSpareFor
152            }
153            else if(session.inventoryItemQuickSearch) {
154                params.quickSearch = session.inventoryItemQuickSearch
155                if(session.inventoryItemQuickSearchDaysBack)
156                    params.daysBack = session.inventoryItemQuickSearchDaysBack.toString()
157            }
158            else if(session.inventoryItemSearchFilterParams) {
159                session.inventoryItemSearchFilterParams.each() { params[it.key] = it.value }
160                params.filter = session.inventoryItemSearchFilter
161                isFilterApplied = FilterUtils.isFilterApplied(params)
162            }
163        }
164
165        // Remember sort if supplied, otherwise try to restore.
166        if(params.sort && params.order) {
167             session.inventoryItemSearchSort = params.sort
168             session.inventoryItemSearchOrder = params.order
169        }
170        else if(session.inventoryItemSearchSort && session.inventoryItemSearchOrder) {
171            params.sort = session.inventoryItemSearchSort
172            params.order = session.inventoryItemSearchOrder
173        }
174
175        if(isFilterApplied) {
176            // filterPane:
177            inventoryItemInstanceList = filterService.filter( params, InventoryItem )
178            inventoryItemInstanceTotal = filterService.count( params, InventoryItem )
179            filterParams = com.zeddware.grails.plugins.filterpane.FilterUtils.extractFilterParams(params)
180            // Remember search.
181            session.inventoryItemSearchFilterParams = new LinkedHashMap(filterParams)
182            session.inventoryItemSearchFilter = new LinkedHashMap(params.filter)
183            // Clear any previous search.
184            session.removeAttribute("inventoryItemSearchText")
185            session.removeAttribute("inventoryItemSearchName")
186            session.removeAttribute("inventoryItemSearchDescription")
187            session.removeAttribute("inventoryItemSearchComment")
188            session.removeAttribute("inventoryItemSearchLocation")
189            session.removeAttribute("inventoryItemSearchGroup")
190            session.removeAttribute("inventoryItemSearchSpareFor")
191            session.removeAttribute("inventoryItemQuickSearch")
192            session.removeAttribute("inventoryItemQuickSearchDaysBack")
193        }
194        else if(params.searchText) {
195            // Quick Search Text:
196            def result = inventoryItemSearchService.getTextSearch(params, RCU.getLocale(request))
197            inventoryItemInstanceList = result.inventoryItemList
198            inventoryItemInstanceTotal = result.inventoryItemList.totalCount
199            params.message = result.message
200            filterParams.searchText = result.searchText
201            // Remember search.
202            session.inventoryItemSearchText = params.searchText
203            session.inventoryItemSearchName = params.searchName
204            session.inventoryItemSearchDescription = params.searchDescription
205            session.inventoryItemSearchComment = params.searchComment
206            session.inventoryItemSearchLocation = params.searchLocation
207            session.inventoryItemSearchGroup = params.searchGroup
208            session.inventoryItemSearchSpareFor = params.searchSpareFor
209            // Clear any previous search.
210            session.removeAttribute("inventoryItemQuickSearch")
211            session.removeAttribute("inventoryItemQuickSearchDaysBack")
212            session.removeAttribute("inventoryItemSearchFilterParams")
213            session.removeAttribute("inventoryItemSearchFilter")
214        }
215        else {
216            // Quick Search Links:
217            if(!params.quickSearch) params.quickSearch = "all"
218            def result = inventoryItemSearchService.getQuickSearch(params, RCU.getLocale(request))
219            inventoryItemInstanceList = result.inventoryItemList
220            inventoryItemInstanceTotal = result.inventoryItemList.totalCount
221            params.message = result.message
222            filterParams.quickSearch = result.quickSearch
223            // Remember search.
224            session.inventoryItemQuickSearch = result.quickSearch
225            if(result.daysBack)
226                session.inventoryItemQuickSearchDaysBack = result.daysBack
227            // Clear any previous search.
228            session.removeAttribute("inventoryItemSearchText")
229            session.removeAttribute("inventoryItemSearchName")
230            session.removeAttribute("inventoryItemSearchDescription")
231            session.removeAttribute("inventoryItemSearchComment")
232            session.removeAttribute("inventoryItemSearchLocation")
233            session.removeAttribute("inventoryItemSearchGroup")
234            session.removeAttribute("inventoryItemSearchSpareFor")
235            session.removeAttribute("inventoryItemSearchFilterParams")
236            session.removeAttribute("inventoryItemSearchFilter")
237        }
238
239        // export plugin:
240        if(params?.format && params.format != "html") {
241
242            def dateFmt = { date ->
243                formatDate(format: "EEE, dd-MMM-yyyy", date: date)
244            }
245
246            String title
247            if(params.quickSearch)
248                title = params.message
249            else
250                title = "Filtered Inventory List."
251
252            response.contentType = ConfigurationHolder.config.grails.mime.types[params.format]
253            response.setHeader("Content-disposition", "attachment; filename=Inventory.${params.extension}")
254            List fields = ["name",
255                                "description",
256                                "inventoryGroup",
257                                "unitsInStock",
258                                "reorderPoint",
259                                "unitOfMeasure",
260                                "inventoryLocation",
261                                "inventoryLocation.inventoryStore"]
262            Map labels = ["name": "Name",
263                                "description": "Description",
264                                "inventoryGroup": "Group",
265                                "unitsInStock":"In Stock",
266                                "reorderPoint":"Reorder Point",
267                                "unitOfMeasure": "UOM",
268                                "inventoryLocation": "Location",
269                                "inventoryLocation.inventoryStore": "Store"]
270
271            Map formatters = [:]
272            Map parameters = [title: title, separator: ","]
273
274            exportService.export(params.format,
275                                                response.outputStream,
276                                                inventoryItemInstanceList.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) },
277                                                fields,
278                                                labels,
279                                                formatters,
280                                                parameters)
281        }
282
283        // Add some basic params to filterParams.
284        filterParams.max = params.max
285        filterParams.offset = params.offset?.toInteger() ?: 0
286        filterParams.sort = params.sort ?: "name"
287        filterParams.order = params.order ?: "asc"
288
289        // Get some associatedProperty values for filterpane.
290        def associatedPropertyValues = [:]
291        def associatedPropertyMax = 10000
292        associatedPropertyValues.inventoryLocationList = InventoryLocation.findAllByIsActive(true, [max:associatedPropertyMax, sort:'name'])
293        associatedPropertyValues.assetList = Asset.findAllByIsActive(true, [max:associatedPropertyMax, sort:'name'])
294        associatedPropertyValues.manufacturerList = Manufacturer.findAllByIsActive(true, [max:associatedPropertyMax, sort:'name'])
295        associatedPropertyValues.supplierList = Supplier.findAllByIsActive(true, [max:associatedPropertyMax, sort:'name'])
296
297        return[ inventoryItemInstanceList: inventoryItemInstanceList,
298                        inventoryItemInstanceTotal: inventoryItemInstanceTotal,
299                        filterParams: filterParams,
300                        params: params,
301                        associatedPropertyValues: associatedPropertyValues ]
302    } // end search()
303
304    /**
305    * Simply assigns a passed in task id to a session variable and redirects to search.
306    */
307    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
308    def findInventoryItemForMovement = {
309        if(!params.task?.id) {
310            flash.message = "No task id supplied, please select a task then the inventory tab."
311            redirect(controller: "taskDetailed", action: "search")
312            return
313        }
314
315        session.inventoryMovementTaskId = params.task.id
316        flash.message = "Please find and then select the inventory item."
317        redirect(action: search)
318    }
319
320    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
321    def show = {
322
323        // In the case of an actionSubmit button, rewrite action name from 'index'.
324        if(params._action_Show)
325            params.action='show'
326
327        def result = inventoryItemService.show(params)
328
329        if(!result.error) {
330
331            def model = [ inventoryItemInstance: result.inventoryItemInstance,
332                                    inventoryMovementList: result.inventoryMovementList,
333                                    inventoryMovementListTotal: result.inventoryMovementListTotal,
334                                    inventoryMovementListMax: result.inventoryMovementListMax,
335                                    inventoryItemPurchases: result.inventoryItemPurchases,
336                                    inventoryItemPurchasesTotal: result.inventoryItemPurchasesTotal,
337                                    showTab: result.showTab]
338
339            if(session.inventoryMovementTaskId) {
340                model.inventoryMovementInstance = new InventoryMovement()
341                model.inventoryMovementInstance.task = Task.get(session.inventoryMovementTaskId)
342                model.inventoryMovementInstance.quantity = 1
343            }
344
345            // Success.
346            return model
347        }
348
349        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
350        redirect(action:search)
351    }
352
353    def delete = {
354        def result = inventoryItemService.delete(params)
355
356        if(!result.error) {
357            flash.message = g.message(code: "default.delete.success", args: ["InventoryItem", params.id])
358            redirect(action:search)
359            return
360        }
361
362        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
363
364        if(result.error.code == "default.not.found") {
365            redirect(action:search)
366            return
367        }
368
369        redirect(action:show, id: params.id)
370    }
371
372    def edit = {
373
374        // In the case of an actionSubmit button, rewrite action name from 'index'.
375        if(params._action_Edit)
376            params.action='edit'
377
378        def result = inventoryItemService.edit(params)
379
380        if(!result.error) {
381            def possibleAlternateItems = inventoryItemService.getPossibleAlternateItems(result.inventoryItemInstance)
382            def suppliers = Supplier.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
383            def manufacturers = Manufacturer.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
384
385            return [ inventoryItemInstance : result.inventoryItemInstance,
386                            possibleAlternateItems: possibleAlternateItems,
387                            suppliers: suppliers,
388                            manufacturers: manufacturers]
389        }
390
391        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
392        redirect(action:search)
393    }
394
395    def update = {
396        def result = inventoryItemService.update(params)
397
398        if(!result.error) {
399            flash.message = g.message(code: "default.update.success", args: ["InventoryItem", params.id])
400            redirect(action:show, id: params.id)
401            return
402        }
403
404        if(result.error.code == "default.not.found") {
405            flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
406            redirect(action:search)
407            return
408        }
409
410        def possibleAlternateItems = inventoryItemService.getPossibleAlternateItems(result.inventoryItemInstance)
411        def suppliers = Supplier.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
412        def manufacturers = Manufacturer.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
413        render(view:'edit', model:[inventoryItemInstance: result.inventoryItemInstance.attach(),
414                                                possibleAlternateItems: possibleAlternateItems,
415                                                suppliers: suppliers,
416                                                manufacturers: manufacturers])
417    }
418
419    def create = {
420        def result = inventoryItemService.create(params)
421        def suppliers = Supplier.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
422        def manufacturers = Manufacturer.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
423
424        if(!result.error)
425            return [inventoryItemInstance: result.inventoryItemInstance,
426                            suppliers: suppliers,
427                            manufacturers: manufacturers]
428
429        //flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
430        redirect(action: search)
431    }
432
433    def save = {
434        def result = inventoryItemService.save(params)
435
436        if(!result.error) {
437            flash.message = g.message(code: "default.create.success", args: ["InventoryItem", result.inventoryItemInstance.id])
438            redirect(action:show, id: result.inventoryItemInstance.id)
439            return
440        }
441
442        def suppliers = Supplier.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
443        def manufacturers = Manufacturer.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
444
445        //flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
446        render(view:'create', model:[inventoryItemInstance: result.inventoryItemInstance,
447                                                    suppliers: suppliers,
448                                                    manufacturers: manufacturers])
449    }
450
451    /**
452    * Handles the use inventory item form submit in the show view.
453    */
454    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
455    def useInventoryItem = {
456
457        params.inventoryMovementType = InventoryMovementType.get(1) // Set type to "Used".
458        def result = inventoryMovementService.move(params)
459
460        if(!result.error) {
461            flash.message = "Inventory Movement for ${result.inventoryMovementInstance.inventoryItem.name.encodeAsHTML()} created."
462            session.inventoryMovementTaskId = null
463            redirect(controller: "taskDetailed",
464                            action: "show",
465                            id: result.taskId,
466                            params: [showTab: "showInventoryTab"])
467            // Success.
468            return
469        }
470
471        // Prepare data for the show view.
472        def p = [:]
473        p.id = result.inventoryMovementInstance.inventoryItem?.id
474        def r = inventoryItemService.show(p)
475
476        // Render show view if data was successfully prepared.
477        if(!r.error) {
478            def model = [ inventoryItemInstance: r.inventoryItemInstance,
479                                    inventoryMovementList: r.inventoryMovementList,
480                                    inventoryMovementListTotal: r.inventoryMovementListTotal,
481                                    inventoryMovementListMax: r.inventoryMovementListMax,
482                                    inventoryItemPurchases: r.inventoryItemPurchases,
483                                    inventoryItemPurchasesTotal: r.inventoryItemPurchasesTotal,
484                                    showTab: r.showTab]
485
486            model.inventoryMovementInstance = result.inventoryMovementInstance // This will pass in the errors.
487
488            render(view: 'show', model: model)
489            return
490        }
491
492        // Could not prepare data for show view so doing the next best thing.
493        flash.errorMessage = g.message(code: r.error.code, args: r.error.args)
494        redirect(action:search)
495
496    } // useInventoryItem
497
498    /**
499    * Clear the use inventory item form in the show view.
500    * Accomplished by clearing the session variable and ajax.
501    */
502    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
503    def clearUseInventoryItem = {
504            session.inventoryMovementTaskId = null
505            render ''
506    }
507
508} // end of class
Note: See TracBrowser for help on using the repository browser.