source: trunk/grails-app/services/InventoryCsvService.groovy @ 720

Last change on this file since 720 was 720, checked in by gav, 9 years ago

Domain change: as per ticket #96 - Remove unused fields from InventoryItem?.
Removed InventoryItem?.alternateItems.

File size: 31.5 KB
Line 
1import grails.util.GrailsUtil
2import au.com.bytecode.opencsv.CSVWriter
3import au.com.bytecode.opencsv.CSVReader
4import org.apache.commons.lang.WordUtils
5
6/**
7 * Provides some csv import/export methods.
8 * Requires the opencsv jar to be available which is included in the grails-export plugin.
9 */
10class InventoryCsvService {
11
12    boolean transactional = false
13
14    def dateUtilService
15
16    def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()
17
18    def sessionFactory
19    def propertyInstanceMap = org.codehaus.groovy.grails.plugins.DomainClassGrailsPlugin.PROPERTY_INSTANCE_MAP
20
21    /**
22    * Import inventory creating items as required.
23    * @param request The http request to run getFile against.
24    * Get file should return a csv format file containing the inventory as per template.
25    */
26    def importInventory(request) {
27        InventoryItem.withTransaction { status ->
28            def result = [:]
29
30            def kByteMultiplier = 1000
31            def fileMaxSize = 800 * kByteMultiplier
32            def logFileLink = g.link(controller: "appCore", action: "appLog") {"log"}
33
34            def multiPartFile = request.getFile('file')
35
36            InputStreamReader sr = new InputStreamReader(multiPartFile.inputStream)
37            CSVReader reader = new CSVReader(sr)
38
39            def fail = { Map m ->
40                status.setRollbackOnly()
41                reader.close()
42                result.error = [ code: m.code, args: m.args ]
43                return result
44            }
45
46            if(!multiPartFile || multiPartFile.isEmpty())
47                return fail(code: "default.file.not.supplied")
48
49            if (multiPartFile.getSize() > fileMaxSize)
50                return fail(code: "default.file.over.max.size", args: [fileMaxSize/kByteMultiplier, "kB"])
51
52            def line = []
53            def lineNumber = 0
54            def maxNumberOfColumns = 20
55            def inventoryParams = [:]
56            def inventoryProperties = ["name", "description", "comment", "unitsInStock", "reorderPoint", "reorderQuantity",
57                                                        "unitOfMeasure", "estimatedUnitPriceAmount", "estimatedUnitPriceCurrency",
58                                                        "enableReorderListing", "inventoryLocation", "inventoryStore", "site",
59                                                        "inventoryGroup", "inventoryType",
60                                                        "suppliersPartNumber", "preferredSupplier", "alternateSuppliers",
61                                                        "spareFor"]
62
63            def siteInstance
64            def alternateSupplierInstance
65            def preferredSupplierInstance
66            def supplierTypeInstance
67            def supplierTypeUnknown = SupplierType.get(1)
68            def spareForInstance
69            def inventoryTypeInstance
70            def unitOfMeasureInstance
71            def inventoryGroupInstance
72            def inventoryItemInstance
73            def inventoryStoreInstance
74            def inventoryLocationInstance
75
76            def tempPreferredSupplierItemAndType = ''
77            def tempPreferredSupplierItem = ''
78            def tempPreferredSupplierType = ''
79
80            def tempAlternateSuppliers = []
81            def tempSupplierItem = ''
82            def tempSupplierType = ''
83            def tempSupplierItemAndType = []
84
85            def tempSpareFor = []
86
87            def nextLine = {
88                    line = reader.readNext()
89                    lineNumber ++
90                    log.info "Processing line: " + lineNumber
91            }
92
93            def parseInputList = {
94                if( (it == null) || (it.trim() == '') ) return []
95                return it.split(";").collect{it.trim()}
96            }
97
98            def parseItemAndType = {
99                return it.split("@").collect{it.trim()}
100            }
101
102            // Get first line.
103            nextLine()
104
105            // Check for header line 1.
106            if(line != templateHeaderLine1) {
107                log.error "Failed to find header line 1. "
108                log.error "Required: " + templateHeaderLine1.toString()
109                log.error "Supplied: " + line.toString()
110                return fail(code: "default.file.no.header")
111            }
112
113            log.info "Header line found."
114
115            // Prepare the first body line.
116            nextLine()
117
118            // Primary loop.
119            while(line) {
120
121                if(line.size() > maxNumberOfColumns) {
122                    log.error "Too many columns on line: " + lineNumber
123                    return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
124                }
125
126                // Ignore comment lines.
127                if(line.toString().toLowerCase().contains("comment")) {
128                    log.info "Comment line found."
129                    nextLine()
130                    continue
131                }
132
133                // Ignore example lines.
134                if(line.toString().toLowerCase().contains("example")) {
135                    log.info "Example line found."
136                    nextLine()
137                    continue
138                }
139
140                // Parse the line into the params map.
141                inventoryParams = [:]
142                line.eachWithIndex { it, j ->
143                    inventoryParams."${inventoryProperties[j]}" = it.trim()
144                }
145
146                // Debug
147                log.debug " Supplied params: "
148                log.debug inventoryParams
149
150                // Ignore blank lines.
151                if(inventoryParams.name == '') {
152                    log.info "No name found."
153                    nextLine()
154                    continue
155                }
156
157                /** Prepare the params and create supporting items as required. */
158
159                // Site
160                inventoryParams.site = WordUtils.capitalize(inventoryParams.site)
161                siteInstance = Site.findByName(inventoryParams.site)
162                if(!siteInstance) {
163                    siteInstance = new Site(name: inventoryParams.site)
164                    if(!siteInstance.save()) {
165                        log.error "Failed to create site on line: " + lineNumber
166                        return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
167                    }
168                }
169
170                // InventoryStore
171                inventoryParams.inventoryStore = WordUtils.capitalizeFully(inventoryParams.inventoryStore)
172                inventoryStoreInstance = InventoryStore.findByName(inventoryParams.inventoryStore)
173                if(!inventoryStoreInstance) {
174                    inventoryStoreInstance = new InventoryStore(name: inventoryParams.inventoryStore,
175                                                                                                site: siteInstance)
176                    if(!inventoryStoreInstance.save()) {
177                        log.error "Failed to create inventory store on line: " + lineNumber
178                        return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
179                    }
180                }
181
182                // InventoryLocation
183                inventoryParams.inventoryLocation = WordUtils.capitalize(inventoryParams.inventoryLocation)
184                inventoryLocationInstance = InventoryLocation.findByName(inventoryParams.inventoryLocation)
185                if(!inventoryLocationInstance) {
186                    inventoryLocationInstance = new InventoryLocation(name: inventoryParams.inventoryLocation,
187                                                                                                        inventoryStore: inventoryStoreInstance)
188                    if(!inventoryLocationInstance.save()) {
189                        log.error "Failed to create inventory location on line: " + lineNumber
190                        return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
191                    }
192                }
193
194                // InventoryGroup
195                inventoryParams.inventoryLocation = WordUtils.capitalizeFully(inventoryParams.inventoryLocation)
196                inventoryGroupInstance = InventoryGroup.findByName(inventoryParams.inventoryGroup)
197                if(!inventoryGroupInstance) {
198                    inventoryGroupInstance = new InventoryGroup(name: inventoryParams.inventoryGroup)
199                    if(!inventoryGroupInstance.save()) {
200                        log.error "Failed to create inventory group on line: " + lineNumber
201                        return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
202                    }
203                }
204
205                // InventoryType
206                inventoryParams.inventoryType = WordUtils.capitalizeFully(inventoryParams.inventoryType)
207                inventoryTypeInstance = InventoryType.findByName(inventoryParams.inventoryType)
208                if(!inventoryTypeInstance) {
209                    inventoryTypeInstance = new InventoryType(name: inventoryParams.inventoryType)
210                    if(!inventoryTypeInstance.save()) {
211                        log.error "Failed to create inventory type on line: " + lineNumber
212                        return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
213                    }
214                }
215
216                // UnitOfMeasure.
217                unitOfMeasureInstance = UnitOfMeasure.findByName(inventoryParams.unitOfMeasure)
218                if(!unitOfMeasureInstance) {
219                    unitOfMeasureInstance = new UnitOfMeasure(name: inventoryParams.unitOfMeasure)
220                    if(!unitOfMeasureInstance.save()) {
221                        log.error "Failed to create unit of measure on line: " + lineNumber
222                        return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
223                    }
224                }
225
226                // Preferred Supplier
227                if(inventoryParams.preferredSupplier) {
228                    tempPreferredSupplierItemAndType = parseItemAndType(inventoryParams.preferredSupplier)
229                    tempPreferredSupplierItem = WordUtils.capitalize(tempPreferredSupplierItemAndType[0])
230
231                    preferredSupplierInstance = Supplier.findByName(tempPreferredSupplierItem)
232                    if(!preferredSupplierInstance) {
233
234                        // SupplierType.
235                        if(tempPreferredSupplierItemAndType.size == 2) {
236                            tempPreferredSupplierType = WordUtils.capitalize(tempPreferredSupplierItemAndType[1])
237                            supplierTypeInstance = SupplierType.findByName(tempPreferredSupplierType)
238                        }
239                        else
240                            supplierTypeInstance = supplierTypeUnknown
241                        if(!supplierTypeInstance) {
242                            log.error "Failed to find preferred supplier type on line: " + lineNumber
243                            return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
244                        }
245
246                        preferredSupplierInstance = new Supplier(name: tempPreferredSupplierItem,
247                                                                                            supplierType: supplierTypeInstance)
248                        if(!preferredSupplierInstance.save()) {
249                            log.error "Failed to create preferred supplier on line: " + lineNumber
250                            return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
251                        }
252                    }
253                }
254                else
255                    preferredSupplierInstance = null
256
257                // Alternate Suppliers.
258                tempAlternateSuppliers = parseInputList(inventoryParams.alternateSuppliers)
259                inventoryParams.alternateSuppliers = []
260
261                for(tempSupplier in tempAlternateSuppliers) {
262                    tempSupplierItemAndType = parseItemAndType(tempSupplier)
263                    tempSupplierItem = WordUtils.capitalizeFully(tempSupplierItemAndType[0])
264
265                    alternateSupplierInstance = Supplier.findByName(tempSupplierItem)
266                    if(!alternateSupplierInstance) {
267
268                        // SupplierType.
269                        if(tempSupplierItemAndType.size == 2) {
270                            tempSupplierType = WordUtils.capitalize(tempSupplierItemAndType[1])
271                            supplierTypeInstance = SupplierType.findByName(tempSupplierType)
272                        }
273                        else
274                            supplierTypeInstance = supplierTypeUnknown
275                        if(!supplierTypeInstance) {
276                            log.error "Failed to find alternate supplier type on line: " + lineNumber
277                            return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
278                        }
279
280                        alternateSupplierInstance = new Supplier(name: tempSupplierItem,
281                                                                            supplierType: supplierTypeInstance)
282                        if(!alternateSupplierInstance.save()) {
283                            log.error "Failed to create alternate suppliers on line: " + lineNumber
284                            return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
285                        }
286                    }
287
288                    inventoryParams.alternateSuppliers.add(alternateSupplierInstance)
289                }
290
291                // spareFor.
292                tempSpareFor = parseInputList(inventoryParams.spareFor)
293                inventoryParams.spareFor = []
294
295                for(asset in tempSpareFor) {
296
297                    asset = WordUtils.capitalize(asset)
298
299                    spareForInstance = Asset.findByName(asset)
300                    if(!spareForInstance) {
301                        log.error "Failed to find 'Spare For' asset on line: " + lineNumber
302                        return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
303                    }
304
305                    inventoryParams.spareFor.add(spareForInstance)
306                }
307
308                // Assign the retrieved or created instances to params.
309                inventoryParams.inventoryLocation = inventoryLocationInstance
310                inventoryParams.inventoryGroup = inventoryGroupInstance
311                inventoryParams.inventoryType = inventoryTypeInstance
312                inventoryParams.unitOfMeasure = unitOfMeasureInstance
313                inventoryParams.preferredSupplier = preferredSupplierInstance
314
315                // Name.
316                // Checked above for blank string.
317                inventoryParams.name = WordUtils.capitalize(inventoryParams.name)
318
319                // Description.
320                if(inventoryParams.description != '')
321                    inventoryParams.description = inventoryParams.description[0].toUpperCase() + inventoryParams.description[1..-1]
322
323                // Debug
324                log.debug "InventoryParams: "
325                log.debug inventoryParams
326
327                // Create new or update.
328                inventoryItemInstance = InventoryItem.findByName(inventoryParams.name)
329                if(inventoryItemInstance) {
330                    log.info "Updating existing item: " + inventoryItemInstance
331                    inventoryItemInstance.properties = inventoryParams
332                }
333                else {
334                    log.info "Creating new item: " + inventoryParams.name
335                    inventoryItemInstance = new InventoryItem(inventoryParams)
336                }
337
338                // Save inventoryItem.
339                if(inventoryItemInstance.hasErrors() || !inventoryItemInstance.save()) {
340                    log.error "Failed to create item on line: " + lineNumber
341                    log.debug inventoryItemInstance.errors
342                    return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
343                }
344
345                if(lineNumber % 100 == 0)
346                    cleanUpGorm()
347
348                if(!result.error) nextLine()
349            } //while(line)
350
351            // Success.
352            log.info "End of file."
353            reader.close()
354            return result
355
356        } //end withTransaction
357    } // end importInventory()
358
359    /**
360    * Build an inventory template csv file.
361    * This template can then be populated for import.
362    * @returns The template as a String in csv format.
363    */
364    def buildInventoryTemplate() {
365
366        StringWriter sw = new StringWriter()
367        CSVWriter writer = new CSVWriter(sw)
368
369        writeTemplateLines(writer)
370
371        writer.close()
372        return sw.toString()
373    }
374
375    private writeTemplateLines(writer) {
376        writer.writeNext(templateHeaderLine1 as String[])
377        writer.writeNext()
378        writer.writeNext("Comment: The header line is required.")
379        writer.writeNext("Comment: Required columns are marked with a (*) in the header line.")
380        writer.writeNext("Comment: Lists of items in a column must be separated by a semicolon (;), not a comma.")
381        writer.writeNext("Comment: The at symbol (@) is reserved for indicating supplier types.")
382        writer.writeNext("Comment: Identical and existing names will be considered as the same item.")
383        writer.writeNext("Comment: Lines containing 'comment' will be ignored.")
384        writer.writeNext("Comment: Lines containing 'example' will be ignored.")
385        writer.writeNext("Comment: This file must be saved as a CSV file before import.")
386        writer.writeNext()
387    }
388
389    /**
390    * Build an inventory example/test file.
391    * This test file can be imported to test the import and export methods.
392    * @returns The test file as a String in csv format.
393    */
394    def buildInventoryExample() {
395
396        StringWriter sw = new StringWriter()
397        CSVWriter writer = new CSVWriter(sw)
398
399        writeTemplateLines(writer)
400
401        // Requires creation of some of the base/group/type data.
402        writer.writeNext(["Split19", "19mm split pin", "Very usefull item.",
403                                        "1024", "0", "1",
404                                        "each", "5", "NZD",
405                                        "false", "BR4",
406                                        "Store #99", "Inventory Depot",
407                                        "Mechanical Stock",
408                                        "Consumable",
409                                        "123", "Multi Supplier@Local",
410                                        "Multi Distributors1@OEM; Multi Distributors2@Local",
411                                        "2204E-2RS", ""
412                                        ] as String[])
413
414        // Using existing base data.
415        writer.writeNext(["2204E-2RS", "Double Row Self Align Ball Bearing 2204E-2RS - Sealed - 20/47x18", "",
416                                        "4", "1", "9",
417                                        "each", "16.35", "USD",
418                                        "TRUE", "BR4",
419                                        "Store #99", "Inventory Depot",
420                                        "Mechanical Stock",
421                                        "Consumable",
422                                        "456KL", "Multi Supplier",
423                                        "Multi Distributors1; Multi Distributors2",
424                                        "", ""
425                                        ] as String[])
426
427        writer.close()
428        return sw.toString()
429    }
430
431    /**
432    * Build complete inventory for export.
433    * @param inventoryItemList The list of inventory items to build.
434    * @returns The inventory as a String in csv format.
435    */
436    def buildInventory(List inventoryItemList) {
437
438        def sw = new StringWriter()
439        def writer = new CSVWriter(sw)
440
441        writeTemplateLines(writer)
442
443        //Rows
444        def row
445
446        inventoryItemList.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }.each() { inventoryItem ->
447            row = []
448            row.add(inventoryItem.name)
449            row.add(inventoryItem.description)
450            row.add(inventoryItem.comment)
451            row.add(inventoryItem.unitsInStock)
452            row.add(inventoryItem.reorderPoint)
453            row.add(inventoryItem.reorderQuantity)
454            row.add(inventoryItem.unitOfMeasure)
455            row.add(inventoryItem.estimatedUnitPriceAmount)
456            row.add(inventoryItem.estimatedUnitPriceCurrency)
457            row.add(inventoryItem.enableReorderListing)
458            row.add(inventoryItem.inventoryLocation)
459            row.add(inventoryItem.inventoryLocation.inventoryStore)
460            row.add(inventoryItem.inventoryLocation.inventoryStore.site)
461            row.add(inventoryItem.inventoryGroup)
462            row.add(inventoryItem.inventoryType)
463            row.add(inventoryItem.suppliersPartNumber)
464
465            if(inventoryItem.preferredSupplier)
466                row.add( inventoryItem.preferredSupplier.name + "@" + inventoryItem.preferredSupplier.supplierType )
467            else
468                row.add('')
469
470            row.add( inventoryItem.alternateSuppliers.sort { p1, p2 ->
471                p1.name.compareToIgnoreCase(p2.name)
472            }.collect { it.name + "@" + it.supplierType }.join(';') )
473
474            row.add(inventoryItem.spareFor.sort { p1, p2 ->
475                p1.name.compareToIgnoreCase(p2.name)
476            }.collect { it.name }.join(';'))
477
478            writer.writeNext(row as String[])
479        }
480
481        writer.close()
482        return sw.toString()
483    } // end buildInventory()
484
485    /**
486    * Import inventoryItemPurchases creating items as required.
487    */
488    def importInventoryItemPurchases(request) {
489        InventoryItemPurchase.withTransaction { status ->
490            def result = [:]
491
492            def kByteMultiplier = 1000
493            def fileMaxSize = 800 * kByteMultiplier
494            def logFileLink = g.link(controller: "appCore", action: "appLog") {"log"}
495
496            def multiPartFile = request.getFile('file')
497
498            InputStreamReader sr = new InputStreamReader(multiPartFile.inputStream)
499            CSVReader reader = new CSVReader(sr)
500
501            def fail = { Map m ->
502                status.setRollbackOnly()
503                reader.close()
504                result.error = [ code: m.code, args: m.args ]
505                return result
506            }
507
508            if(!multiPartFile || multiPartFile.isEmpty())
509                return fail(code: "default.file.not.supplied")
510
511            if (multiPartFile.getSize() > fileMaxSize)
512                return fail(code: "default.file.over.max.size", args: [fileMaxSize/kByteMultiplier, "kB"])
513
514            def line = []
515            def lineNumber = 0
516            def maxNumberOfColumns = 10
517            def inventoryItemPurchaseParams = [:]
518            def inventoryItemPurchaseProperties = ["inventoryItem", "purchaseOrderNumber", "quantity",
519                                                                                "inventoryItemPurchaseType",
520                                                                                "costCode", "enteredBy", "dateEntered",
521                                                                                "orderValueAmount", "orderValueCurrency", "invoiceNumber"]
522
523            def personInstance
524            def costCodeInstance
525            def inventoryItemInstance
526            def inventoryItemPurchaseInstance
527            def inventoryItemPurchaseTypeInstance
528
529            def nextLine = {
530                    line = reader.readNext()
531                    lineNumber ++
532                    log.info "Processing line: " + lineNumber
533            }
534
535            def parseInputDate = {
536                if( (it == null) || (it.trim() == '') ) {
537                    log.error "Failed to find any date on line: " + lineNumber
538                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
539                }
540
541                def d = it.split("/").collect{it.trim()}
542                if(d.size() != 3) {
543                    log.error "Failed to find full date on line: " + lineNumber
544                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
545                }
546                dateUtilService.makeDate(d[0], d[1], d[2])
547            }
548
549            // Get first line.
550            nextLine()
551
552            // Check for header line 1.
553            if(line != purchasesTemplateHeaderLine1) {
554                log.error "Failed to find header line 1. "
555                log.error "Required: " + purchasesTemplateHeaderLine1.toString()
556                log.error "Supplied: " + line.toString()
557                return fail(code: "default.file.no.header")
558            }
559
560            log.info "Header line found."
561
562            // Prepare the first body line.
563            nextLine()
564
565            // Primary loop.
566            while(line) {
567
568                if(line.size() > maxNumberOfColumns) {
569                    log.error "Too many columns on line: " + lineNumber
570                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
571                }
572
573                // Ignore comment lines.
574                if(line.toString().toLowerCase().contains("comment")) {
575                    log.info "Comment line found."
576                    nextLine()
577                    continue
578                }
579
580                // Ignore example lines.
581                if(line.toString().toLowerCase().contains("example")) {
582                    log.info "Example line found."
583                    nextLine()
584                    continue
585                }
586
587                // Parse the line into the params map.
588                inventoryItemPurchaseParams = [:]
589                line.eachWithIndex { it, j ->
590                    inventoryItemPurchaseParams."${inventoryItemPurchaseProperties[j]}" = it.trim()
591                }
592
593                // Debug
594                log.debug " Supplied params: "
595                log.debug inventoryItemPurchaseParams
596
597                // Ignore blank lines.
598                if(inventoryItemPurchaseParams.inventoryItem == '') {
599                    log.info "No inventory item name found."
600                    nextLine()
601                    continue
602                }
603
604                // Inventory Item.
605                inventoryItemPurchaseParams.inventoryItem = WordUtils.capitalize(inventoryItemPurchaseParams.inventoryItem)
606                inventoryItemInstance = InventoryItem.findByName(inventoryItemPurchaseParams.inventoryItem)
607                if(!inventoryItemInstance) {
608                    log.error "Inventory item not found on line: " + lineNumber
609                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
610                }
611                inventoryItemPurchaseParams.inventoryItem = inventoryItemInstance
612
613                // Quantity.
614                if(inventoryItemPurchaseParams.quantity.isInteger())
615                    inventoryItemPurchaseParams.quantity = inventoryItemPurchaseParams.quantity.toInteger()
616                else {
617                    log.error "Quantity is not a valid number on line: " + lineNumber
618                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
619                }
620
621                // InventoryItemPurchaseType.
622                inventoryItemPurchaseParams.inventoryItemPurchaseType = WordUtils.capitalizeFully(inventoryItemPurchaseParams.inventoryItemPurchaseType)
623                inventoryItemPurchaseTypeInstance = InventoryItemPurchaseType.findByName(inventoryItemPurchaseParams.inventoryItemPurchaseType)
624                if(!inventoryItemPurchaseTypeInstance) {
625                    log.error "Inventory item purchase type not found on line: " + lineNumber
626                    log.debug inventoryItemPurchaseParams.inventoryItemPurchaseType
627                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
628                }
629                inventoryItemPurchaseParams.inventoryItemPurchaseType = inventoryItemPurchaseTypeInstance
630
631                // CostCode.
632                if(inventoryItemPurchaseParams.costCode != '') {
633                    inventoryItemPurchaseParams.costCode = WordUtils.capitalizeFully(inventoryItemPurchaseParams.costCode)
634                    costCodeInstance = CostCode.findByName(inventoryItemPurchaseParams.costCode)
635                    if(!costCodeInstance) {
636                        costCodeInstance = new CostCode(name: inventoryItemPurchaseParams.costCode)
637                        if(!costCodeInstance.save()) {
638                            log.error "Failed to create cost code on line: " + lineNumber
639                            return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
640                        }
641                    }
642                    inventoryItemPurchaseParams.costCode = costCodeInstance
643                }
644
645                // Entered By.
646                inventoryItemPurchaseParams.enteredBy = inventoryItemPurchaseParams.enteredBy.toLowerCase()
647                personInstance = Person.findByLoginName(inventoryItemPurchaseParams.enteredBy)
648                if(!personInstance) {
649                    log.error "Entered by person not found on line: " + lineNumber
650                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
651                }
652                inventoryItemPurchaseParams.enteredBy = personInstance
653
654                // Date Entered.
655                inventoryItemPurchaseParams.dateEntered = parseInputDate(inventoryItemPurchaseParams.dateEntered)
656
657                // Debug
658                log.debug "InventoryItemPurchaseParams: "
659                log.debug inventoryItemPurchaseParams
660
661                // Save inventoryItem.
662                log.info "Creating new purchase."
663                inventoryItemPurchaseInstance = new InventoryItemPurchase(inventoryItemPurchaseParams)
664
665                if(inventoryItemPurchaseInstance.hasErrors() || !inventoryItemPurchaseInstance.save()) {
666                    log.error "Failed to create item on line: " + lineNumber
667                    log.debug inventoryItemPurchaseInstance.errors
668                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
669                }
670
671                if(lineNumber % 100 == 0)
672                    cleanUpGorm()
673
674                if(!result.error) nextLine()
675            } //while(line)
676
677            // Success.
678            log.info "End of file."
679            reader.close()
680            return result
681
682
683         } //end withTransaction
684    } // end importInventoryItemPurchases()
685
686    private getTemplateHeaderLine1() {
687            ["Name*", "Description", "Comment", "Units In Stock", "Reorder Point*", "Reorder Quantity", "Unit Of Measure*",
688            "Estimated Unit Price", "Currency", "Enable Reorder", "Location*", "Store*", "Site*", "Group*", "Type*",
689            "Supplier's Part Number", "Preferred Supplier", "Alternate Suppliers",
690            "Alternate Item", "Spare For"]
691    }
692
693    private getPurchasesTemplateHeaderLine1() {
694            ["Inventory Item*", "Purchase Order Number*", "Quantity*", "Purchase Type*", "Cost Code*", "Entered By*",
695            "Date Entered*", "Order Value", "Currency", "Invoice Number"]
696    }
697
698    /**
699    * This cleans up the hibernate session and a grails map.
700    * For more info see: http://naleid.com/blog/2009/10/01/batch-import-performance-with-grails-and-mysql/
701    * The hibernate session flush is normal for hibernate.
702    * The map is apparently used by grails for domain object validation errors.
703    * A starting point for clean up is every 100 objects.
704    */
705    def cleanUpGorm() {
706        def session = sessionFactory.currentSession
707        session.flush()
708        session.clear()
709        propertyInstanceMap.get().clear()
710    }
711
712} // end class
Note: See TracBrowser for help on using the repository browser.