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

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

Small fix to inventory search so that limit search selects work with pagination.

File size: 22.6 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            // Text Search:
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            // Place limit search selects in filterParams for pagination.
202            if(params.searchName)
203                filterParams.searchName = params.searchName
204            if(params.searchDescription)
205                filterParams.searchDescription = params.searchDescription
206            if(params.searchComment)
207                filterParams.searchComment = params.searchComment
208            if(params.searchLocation)
209                filterParams.searchLocation = params.searchLocation
210            if(params.searchGroup)
211                filterParams.searchGroup = params.searchGroup
212            if(params.searchSpareFor)
213                filterParams.searchSpareFor = params.searchSpareFor
214            // Remember search.
215            session.inventoryItemSearchText = params.searchText
216            session.inventoryItemSearchName = params.searchName
217            session.inventoryItemSearchDescription = params.searchDescription
218            session.inventoryItemSearchComment = params.searchComment
219            session.inventoryItemSearchLocation = params.searchLocation
220            session.inventoryItemSearchGroup = params.searchGroup
221            session.inventoryItemSearchSpareFor = params.searchSpareFor
222            // Clear any previous search.
223            session.removeAttribute("inventoryItemQuickSearch")
224            session.removeAttribute("inventoryItemQuickSearchDaysBack")
225            session.removeAttribute("inventoryItemSearchFilterParams")
226            session.removeAttribute("inventoryItemSearchFilter")
227        }
228        else {
229            // Quick Search Links:
230            if(!params.quickSearch) params.quickSearch = "all"
231            def result = inventoryItemSearchService.getQuickSearch(params, RCU.getLocale(request))
232            inventoryItemInstanceList = result.inventoryItemList
233            inventoryItemInstanceTotal = result.inventoryItemList.totalCount
234            params.message = result.message
235            filterParams.quickSearch = result.quickSearch
236            // Remember search.
237            session.inventoryItemQuickSearch = result.quickSearch
238            if(result.daysBack)
239                session.inventoryItemQuickSearchDaysBack = result.daysBack
240            // Clear any previous search.
241            session.removeAttribute("inventoryItemSearchText")
242            session.removeAttribute("inventoryItemSearchName")
243            session.removeAttribute("inventoryItemSearchDescription")
244            session.removeAttribute("inventoryItemSearchComment")
245            session.removeAttribute("inventoryItemSearchLocation")
246            session.removeAttribute("inventoryItemSearchGroup")
247            session.removeAttribute("inventoryItemSearchSpareFor")
248            session.removeAttribute("inventoryItemSearchFilterParams")
249            session.removeAttribute("inventoryItemSearchFilter")
250        }
251
252        // export plugin:
253        if(params?.format && params.format != "html") {
254
255            def dateFmt = { date ->
256                formatDate(format: "EEE, dd-MMM-yyyy", date: date)
257            }
258
259            String title
260            if(params.quickSearch)
261                title = params.message
262            else
263                title = "Filtered Inventory List."
264
265            response.contentType = ConfigurationHolder.config.grails.mime.types[params.format]
266            response.setHeader("Content-disposition", "attachment; filename=Inventory.${params.extension}")
267            List fields = ["name",
268                                "description",
269                                "inventoryGroup",
270                                "unitsInStock",
271                                "reorderPoint",
272                                "unitOfMeasure",
273                                "inventoryLocation",
274                                "inventoryLocation.inventoryStore"]
275            Map labels = ["name": "Name",
276                                "description": "Description",
277                                "inventoryGroup": "Group",
278                                "unitsInStock":"In Stock",
279                                "reorderPoint":"Reorder Point",
280                                "unitOfMeasure": "UOM",
281                                "inventoryLocation": "Location",
282                                "inventoryLocation.inventoryStore": "Store"]
283
284            Map formatters = [:]
285            Map parameters = [title: title, separator: ","]
286
287            exportService.export(params.format,
288                                                response.outputStream,
289                                                inventoryItemInstanceList.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) },
290                                                fields,
291                                                labels,
292                                                formatters,
293                                                parameters)
294        }
295
296        // Add some basic params to filterParams.
297        filterParams.max = params.max
298        filterParams.offset = params.offset?.toInteger() ?: 0
299        filterParams.sort = params.sort ?: "name"
300        filterParams.order = params.order ?: "asc"
301
302        // Get some associatedProperty values for filterpane.
303        def associatedPropertyValues = [:]
304        def associatedPropertyMax = 10000
305        associatedPropertyValues.inventoryLocationList = InventoryLocation.findAllByIsActive(true, [max:associatedPropertyMax, sort:'name'])
306        associatedPropertyValues.assetList = Asset.findAllByIsActive(true, [max:associatedPropertyMax, sort:'name'])
307        associatedPropertyValues.manufacturerList = Manufacturer.findAllByIsActive(true, [max:associatedPropertyMax, sort:'name'])
308        associatedPropertyValues.supplierList = Supplier.findAllByIsActive(true, [max:associatedPropertyMax, sort:'name'])
309
310        return[ inventoryItemInstanceList: inventoryItemInstanceList,
311                        inventoryItemInstanceTotal: inventoryItemInstanceTotal,
312                        filterParams: filterParams,
313                        params: params,
314                        associatedPropertyValues: associatedPropertyValues ]
315    } // end search()
316
317    /**
318    * Simply assigns a passed in task id to a session variable and redirects to search.
319    */
320    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
321    def findInventoryItemForMovement = {
322        if(!params.task?.id) {
323            flash.message = "No task id supplied, please select a task then the inventory tab."
324            redirect(controller: "taskDetailed", action: "search")
325            return
326        }
327
328        session.inventoryMovementTaskId = params.task.id
329        flash.message = "Please find and then select the inventory item."
330        redirect(action: search)
331    }
332
333    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
334    def show = {
335
336        // In the case of an actionSubmit button, rewrite action name from 'index'.
337        if(params._action_Show)
338            params.action='show'
339
340        def result = inventoryItemService.show(params)
341
342        if(!result.error) {
343
344            def model = [ inventoryItemInstance: result.inventoryItemInstance,
345                                    inventoryMovementList: result.inventoryMovementList,
346                                    inventoryMovementListTotal: result.inventoryMovementListTotal,
347                                    inventoryMovementListMax: result.inventoryMovementListMax,
348                                    inventoryItemPurchases: result.inventoryItemPurchases,
349                                    inventoryItemPurchasesTotal: result.inventoryItemPurchasesTotal,
350                                    showTab: result.showTab]
351
352            if(session.inventoryMovementTaskId) {
353                model.inventoryMovementInstance = new InventoryMovement()
354                model.inventoryMovementInstance.task = Task.get(session.inventoryMovementTaskId)
355                model.inventoryMovementInstance.quantity = 1
356            }
357
358            // Success.
359            return model
360        }
361
362        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
363        redirect(action:search)
364    }
365
366    def delete = {
367        def result = inventoryItemService.delete(params)
368
369        if(!result.error) {
370            flash.message = g.message(code: "default.delete.success", args: ["InventoryItem", params.id])
371            redirect(action:search)
372            return
373        }
374
375        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
376
377        if(result.error.code == "default.not.found") {
378            redirect(action:search)
379            return
380        }
381
382        redirect(action:show, id: params.id)
383    }
384
385    def edit = {
386
387        // In the case of an actionSubmit button, rewrite action name from 'index'.
388        if(params._action_Edit)
389            params.action='edit'
390
391        def result = inventoryItemService.edit(params)
392
393        if(!result.error) {
394            def possibleAlternateItems = inventoryItemService.getPossibleAlternateItems(result.inventoryItemInstance)
395            def suppliers = Supplier.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
396            def manufacturers = Manufacturer.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
397
398            return [ inventoryItemInstance : result.inventoryItemInstance,
399                            possibleAlternateItems: possibleAlternateItems,
400                            suppliers: suppliers,
401                            manufacturers: manufacturers]
402        }
403
404        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
405        redirect(action:search)
406    }
407
408    def update = {
409        def result = inventoryItemService.update(params)
410
411        if(!result.error) {
412            flash.message = g.message(code: "default.update.success", args: ["InventoryItem", params.id])
413            redirect(action:show, id: params.id)
414            return
415        }
416
417        if(result.error.code == "default.not.found") {
418            flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
419            redirect(action:search)
420            return
421        }
422
423        def possibleAlternateItems = inventoryItemService.getPossibleAlternateItems(result.inventoryItemInstance)
424        def suppliers = Supplier.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
425        def manufacturers = Manufacturer.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
426        render(view:'edit', model:[inventoryItemInstance: result.inventoryItemInstance.attach(),
427                                                possibleAlternateItems: possibleAlternateItems,
428                                                suppliers: suppliers,
429                                                manufacturers: manufacturers])
430    }
431
432    def create = {
433        def result = inventoryItemService.create(params)
434        def suppliers = Supplier.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
435        def manufacturers = Manufacturer.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
436
437        if(!result.error)
438            return [inventoryItemInstance: result.inventoryItemInstance,
439                            suppliers: suppliers,
440                            manufacturers: manufacturers]
441
442        //flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
443        redirect(action: search)
444    }
445
446    def save = {
447        def result = inventoryItemService.save(params)
448
449        if(!result.error) {
450            flash.message = g.message(code: "default.create.success", args: ["InventoryItem", result.inventoryItemInstance.id])
451            redirect(action:show, id: result.inventoryItemInstance.id)
452            return
453        }
454
455        def suppliers = Supplier.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
456        def manufacturers = Manufacturer.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
457
458        //flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
459        render(view:'create', model:[inventoryItemInstance: result.inventoryItemInstance,
460                                                    suppliers: suppliers,
461                                                    manufacturers: manufacturers])
462    }
463
464    /**
465    * Handles the use inventory item form submit in the show view.
466    */
467    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
468    def useInventoryItem = {
469
470        params.inventoryMovementType = InventoryMovementType.get(1) // Set type to "Used".
471        def result = inventoryMovementService.move(params)
472
473        if(!result.error) {
474            flash.message = "Inventory Movement for ${result.inventoryMovementInstance.inventoryItem.name.encodeAsHTML()} created."
475            session.inventoryMovementTaskId = null
476            redirect(controller: "taskDetailed",
477                            action: "show",
478                            id: result.taskId,
479                            params: [showTab: "showInventoryTab"])
480            // Success.
481            return
482        }
483
484        // Prepare data for the show view.
485        def p = [:]
486        p.id = result.inventoryMovementInstance.inventoryItem?.id
487        def r = inventoryItemService.show(p)
488
489        // Render show view if data was successfully prepared.
490        if(!r.error) {
491            def model = [ inventoryItemInstance: r.inventoryItemInstance,
492                                    inventoryMovementList: r.inventoryMovementList,
493                                    inventoryMovementListTotal: r.inventoryMovementListTotal,
494                                    inventoryMovementListMax: r.inventoryMovementListMax,
495                                    inventoryItemPurchases: r.inventoryItemPurchases,
496                                    inventoryItemPurchasesTotal: r.inventoryItemPurchasesTotal,
497                                    showTab: r.showTab]
498
499            model.inventoryMovementInstance = result.inventoryMovementInstance // This will pass in the errors.
500
501            render(view: 'show', model: model)
502            return
503        }
504
505        // Could not prepare data for show view so doing the next best thing.
506        flash.errorMessage = g.message(code: r.error.code, args: r.error.args)
507        redirect(action:search)
508
509    } // useInventoryItem
510
511    /**
512    * Clear the use inventory item form in the show view.
513    * Accomplished by clearing the session variable and ajax.
514    */
515    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
516    def clearUseInventoryItem = {
517            session.inventoryMovementTaskId = null
518            render ''
519    }
520
521} // end of class
Note: See TracBrowser for help on using the repository browser.