Ignore:
Timestamp:
Mar 16, 2010, 12:00:04 PM (15 years ago)
Author:
gav
Message:

Add CostCode and InventoryItemPurchase domain classes with import features.
Includes some fixes to inventory imports, where manufacturer and supplier were crossed.

Location:
trunk/grails-app/services
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/services/CreateDataService.groovy

    r433 r441  
    6262        createBaseAddressTypes()
    6363        createBaseContactTypes()
     64        createBaseInventoryItemPurchaseTypes()
    6465
    6566        // Tasks
     
    113114        createDemoManufacturers()
    114115        createDemoProductionReference()
     116        createDemoCostCodes()
    115117
    116118        // Tasks
     
    612614    }
    613615
     616    def createBaseInventoryItemPurchaseTypes() {
     617
     618        // InventoryItemPurchaseType
     619        def inventoryItemPurchaseTypeInstance
     620
     621        // InventoryItemPurchaseType #1
     622        inventoryItemPurchaseTypeInstance = new InventoryItemPurchaseType(name: "Order Placed",
     623                                                                                description: "Order has been placed.")
     624        saveAndTest(inventoryItemPurchaseTypeInstance)
     625
     626        // InventoryItemPurchaseType #2
     627        inventoryItemPurchaseTypeInstance = new InventoryItemPurchaseType(name: "Received B/order To Come",
     628                                                                                description: "Order has been partially received.")
     629        saveAndTest(inventoryItemPurchaseTypeInstance)
     630        // InventoryItemPurchaseType #3
     631        inventoryItemPurchaseTypeInstance = new InventoryItemPurchaseType(name: "Received Complete",
     632                                                                                description: "Order has been partially received.")
     633        saveAndTest(inventoryItemPurchaseTypeInstance)
     634
     635        // InventoryItemPurchaseType #4
     636        inventoryItemPurchaseTypeInstance = new InventoryItemPurchaseType(name: "Invoice Approved",
     637                                                                                description: "Invoice approved for payment.")
     638        saveAndTest(inventoryItemPurchaseTypeInstance)
     639    }
     640
    614641    def createDemoSuppliers() {
    615642
     
    656683        productionReferenceInstance = new ProductionReference(name: "Tuesday Production")
    657684        saveAndTest(productionReferenceInstance)
     685    }
     686
     687    def createDemoCostCodes() {
     688
     689        // CostCode
     690        def costCodeInstance
     691
     692        // CostCode #1
     693        costCodeInstance = new CostCode(name: "RM Reelstand")
     694        saveAndTest(costCodeInstance)
     695
     696        // CostCode #2
     697        costCodeInstance = new CostCode(name: "CAPEX Reelstand")
     698        saveAndTest(costCodeInstance)
    658699    }
    659700
  • trunk/grails-app/services/InventoryCsvService.groovy

    r436 r441  
    1111
    1212    boolean transactional = false
     13
     14    def dateUtilService
    1315
    1416    def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()
     
    4749            if (multiPartFile.getSize() > fileMaxSize)
    4850                return fail(code: "default.file.over.max.size", args: [fileMaxSize/kByteMultiplier, "kB"])
    49 
    50             //TODO: delete
    51             def columnValue = ''
    52             def columnIndex = 0
    53             def numberOfColumns = 0
    5451
    5552            def line = []
     
    105102            def tempAlternateItems = []
    106103
    107             def column = ''
    108 
    109104            def nextLine = {
    110105                    line = reader.readNext()
    111106                    lineNumber ++
    112107                    log.info "Processing line: " + lineNumber
    113             }
    114 
    115             def nextColumn = {
    116 
    117                 if( columnIndex < numberOfColumns ) {
    118                         column = line[columnIndex].trim()
    119                 }
    120                 else {
    121                     log.info "No more columns on line: " + lineNumber
    122                     return false
    123                 }
    124 
    125                 columnIndex++
    126                 // Success.
    127                 return column
    128108            }
    129109
     
    280260                        // Manufacturer Type.
    281261                        if(tempPreferredManufacturerItemAndType.size == 2) {
    282                             tempPreferredManufacturerType = WordUtils.capitalizeFully(tempPreferredManufacturerItemAndType[1])
     262                            tempPreferredManufacturerType = WordUtils.capitalize(tempPreferredManufacturerItemAndType[1])
    283263                            manufacturerTypeInstance = ManufacturerType.findByName(tempPreferredManufacturerType)
    284264                        }
     
    291271
    292272                        preferredManufacturerInstance = new Manufacturer(name: tempPreferredManufacturerItem,
    293                                                                                                             supplierType: manufacturerTypeInstance)
     273                                                                                                            manufacturerType: manufacturerTypeInstance)
    294274                        if(!preferredManufacturerInstance.save()) {
    295275                            log.error "Failed to create preferred manufacturer on line: " + lineNumber
     
    302282
    303283                // Alternate Manufacturers.
    304                 tempAlternateManufacturers = parseInputList(inventoryParams.manufacturers)
    305                 inventoryParams.manufacturers = []
     284                tempAlternateManufacturers = parseInputList(inventoryParams.alternateManufacturers)
     285                inventoryParams.alternateManufacturers = []
    306286
    307287                for(tempManufacturer in tempAlternateManufacturers) {
     
    309289                    tempManufacturerItem = WordUtils.capitalizeFully(tempManufacturerItemAndType[0])
    310290
    311                     manufacturerInstance = Manufacturer.findByName(tempManufacturerItem)
    312                     if(!manufacturerInstance) {
     291                    alternateManufacturerInstance = Manufacturer.findByName(tempManufacturerItem)
     292                    if(!alternateManufacturerInstance) {
    313293
    314294                        // ManufacturerType.
    315295                        if(tempManufacturerItemAndType.size == 2) {
    316                             tempManufacturerType = WordUtils.capitalizeFully(tempManufacturerItemAndType[1])
     296                            tempManufacturerType = WordUtils.capitalize(tempManufacturerItemAndType[1])
    317297                            manufacturerTypeInstance = ManufacturerType.findByName(tempManufacturerType)
    318298                        }
     
    324304                        }
    325305
    326                         manufacturerInstance = new Manufacturer(name: tempManufacturerItem,
     306                        alternateManufacturerInstance = new Manufacturer(name: tempManufacturerItem,
    327307                                                                                                manufacturerType: manufacturerTypeInstance)
    328                         if(!manufacturerInstance.save()) {
     308                        if(!alternateManufacturerInstance.save()) {
    329309                            log.error "Failed to create manufacturers on line: " + lineNumber
    330310                            return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
     
    332312                    }
    333313
    334                     inventoryParams.manufacturers.add(manufacturerInstance)
     314                    inventoryParams.alternateManufacturers.add(alternateManufacturerInstance)
    335315                }
    336316
     
    345325                        // SupplierType.
    346326                        if(tempPreferredSupplierItemAndType.size == 2) {
    347                             tempPreferredSupplierType = WordUtils.capitalizeFully(tempPreferredSupplierItemAndType[1])
     327                            tempPreferredSupplierType = WordUtils.capitalize(tempPreferredSupplierItemAndType[1])
    348328                            supplierTypeInstance = SupplierType.findByName(tempPreferredSupplierType)
    349329                        }
     
    379359                        // SupplierType.
    380360                        if(tempSupplierItemAndType.size == 2) {
    381                             tempSupplierType = WordUtils.capitalizeFully(tempSupplierItemAndType[1])
     361                            tempSupplierType = WordUtils.capitalize(tempSupplierItemAndType[1])
    382362                            supplierTypeInstance = SupplierType.findByName(tempSupplierType)
    383363                        }
     
    397377                    }
    398378
    399                     inventoryParams.suppliers.add(alternateSupplierInstance)
     379                    inventoryParams.alternateSuppliers.add(alternateSupplierInstance)
    400380                }
    401381
     
    475455                // Save inventoryItem.
    476456                if(inventoryItemInstance.hasErrors() || !inventoryItemInstance.save()) {
    477                     log.error "Failed to create item on line: " + column + "(" + lineNumber + ")"
     457                    log.error "Failed to create item on line: " + lineNumber
    478458                    log.debug inventoryItemInstance.errors
    479459                    return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
     
    641621        writer.close()
    642622        return sw.toString()
    643     } // end buildInventory
     623    } // end buildInventory()
     624
     625    /**
     626    * Import inventoryItemPurchases creating items as required.
     627    */
     628    def importInventoryItemPurchases(request) {
     629        InventoryItemPurchase.withTransaction { status ->
     630            def result = [:]
     631
     632            def kByteMultiplier = 1000
     633            def fileMaxSize = 800 * kByteMultiplier
     634            def logFileLink = g.link(controller: "appCore", action: "appLog") {"log"}
     635
     636            def multiPartFile = request.getFile('file')
     637
     638            InputStreamReader sr = new InputStreamReader(multiPartFile.inputStream)
     639            CSVReader reader = new CSVReader(sr)
     640
     641            def fail = { Map m ->
     642                status.setRollbackOnly()
     643                reader.close()
     644                result.error = [ code: m.code, args: m.args ]
     645                return result
     646            }
     647
     648            if(!multiPartFile || multiPartFile.isEmpty())
     649                return fail(code: "default.file.not.supplied")
     650
     651            if (multiPartFile.getSize() > fileMaxSize)
     652                return fail(code: "default.file.over.max.size", args: [fileMaxSize/kByteMultiplier, "kB"])
     653
     654            def line = []
     655            def lineNumber = 0
     656            def maxNumberOfColumns = 10
     657            def inventoryItemPurchaseParams = [:]
     658            def inventoryItemPurchaseProperties = ["inventoryItem", "purchaseOrderNumber", "quantity",
     659                                                                                "inventoryItemPurchaseType",
     660                                                                                "costCode", "enteredBy", "dateEntered",
     661                                                                                "orderValueAmount", "orderValueCurrency", "invoiceNumber"]
     662
     663            def personInstance
     664            def costCodeInstance
     665            def inventoryItemInstance
     666            def inventoryItemPurchaseInstance
     667            def inventoryItemPurchaseTypeInstance
     668
     669            def nextLine = {
     670                    line = reader.readNext()
     671                    lineNumber ++
     672                    log.info "Processing line: " + lineNumber
     673            }
     674
     675            def parseInputDate = {
     676                if( (it == null) || (it.trim() == '') ) {
     677                    log.error "Failed to find any date on line: " + lineNumber
     678                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
     679                }
     680
     681                def d = it.split("/").collect{it.trim()}
     682                if(d.size() != 3) {
     683                    log.error "Failed to find full date on line: " + lineNumber
     684                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
     685                }
     686                dateUtilService.makeDate(d[0], d[1], d[2])
     687            }
     688
     689            // Get first line.
     690            nextLine()
     691
     692            // Check for header line 1.
     693            if(line != purchasesTemplateHeaderLine1) {
     694                log.error "Failed to find header line 1. "
     695                log.error "Required: " + purchasesTemplateHeaderLine1.toString()
     696                log.error "Supplied: " + line.toString()
     697                return fail(code: "default.file.no.header")
     698            }
     699
     700            log.info "Header line found."
     701
     702            // Prepare the first body line.
     703            nextLine()
     704
     705            // Primary loop.
     706            while(line) {
     707
     708                if(line.size() > maxNumberOfColumns) {
     709                    log.error "Too many columns on line: " + lineNumber
     710                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
     711                }
     712
     713                // Ignore comment lines.
     714                if(line.toString().toLowerCase().contains("comment")) {
     715                    log.info "Comment line found."
     716                    nextLine()
     717                    continue
     718                }
     719
     720                // Ignore example lines.
     721                if(line.toString().toLowerCase().contains("example")) {
     722                    log.info "Example line found."
     723                    nextLine()
     724                    continue
     725                }
     726
     727                // Parse the line into the params map.
     728                inventoryItemPurchaseParams = [:]
     729                line.eachWithIndex { it, j ->
     730                    inventoryItemPurchaseParams."${inventoryItemPurchaseProperties[j]}" = it.trim()
     731                }
     732
     733                // Debug
     734                log.debug " Supplied params: "
     735                log.debug inventoryItemPurchaseParams
     736
     737                // Ignore blank lines.
     738                if(inventoryItemPurchaseParams.inventoryItem == '') {
     739                    log.info "No inventory item name found."
     740                    nextLine()
     741                    continue
     742                }
     743
     744                // Inventory Item.
     745                inventoryItemPurchaseParams.inventoryItem = WordUtils.capitalize(inventoryItemPurchaseParams.inventoryItem)
     746                inventoryItemInstance = InventoryItem.findByName(inventoryItemPurchaseParams.inventoryItem)
     747                if(!inventoryItemInstance) {
     748                    log.error "Inventory item not found on line: " + lineNumber
     749                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
     750                }
     751                inventoryItemPurchaseParams.inventoryItem = inventoryItemInstance
     752
     753                // Quantity.
     754                if(inventoryItemPurchaseParams.quantity.isInteger())
     755                    inventoryItemPurchaseParams.quantity = inventoryItemPurchaseParams.quantity.toInteger()
     756                else {
     757                    log.error "Quantity is not a valid number on line: " + lineNumber
     758                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
     759                }
     760
     761                // InventoryItemPurchaseType.
     762                inventoryItemPurchaseParams.inventoryItemPurchaseType = WordUtils.capitalizeFully(inventoryItemPurchaseParams.inventoryItemPurchaseType)
     763                inventoryItemPurchaseTypeInstance = InventoryItemPurchaseType.findByName(inventoryItemPurchaseParams.inventoryItemPurchaseType)
     764                if(!inventoryItemPurchaseTypeInstance) {
     765                    log.error "Inventory item purchase type not found on line: " + lineNumber
     766                    log.debug inventoryItemPurchaseParams.inventoryItemPurchaseType
     767                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
     768                }
     769                inventoryItemPurchaseParams.inventoryItemPurchaseType = inventoryItemPurchaseTypeInstance
     770
     771                // CostCode.
     772                if(inventoryItemPurchaseParams.costCode != '') {
     773                    inventoryItemPurchaseParams.costCode = WordUtils.capitalizeFully(inventoryItemPurchaseParams.costCode)
     774                    costCodeInstance = CostCode.findByName(inventoryItemPurchaseParams.costCode)
     775                    if(!costCodeInstance) {
     776                        costCodeInstance = new CostCode(name: inventoryItemPurchaseParams.costCode)
     777                        if(!costCodeInstance.save()) {
     778                            log.error "Failed to create cost code on line: " + lineNumber
     779                            return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
     780                        }
     781                    }
     782                    inventoryItemPurchaseParams.costCode = costCodeInstance
     783                }
     784
     785                // Entered By.
     786                inventoryItemPurchaseParams.enteredBy = inventoryItemPurchaseParams.enteredBy.toLowerCase()
     787                personInstance = Person.findByLoginName(inventoryItemPurchaseParams.enteredBy)
     788                if(!personInstance) {
     789                    log.error "Entered by person not found on line: " + lineNumber
     790                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
     791                }
     792                inventoryItemPurchaseParams.enteredBy = personInstance
     793
     794                // Date Entered.
     795                inventoryItemPurchaseParams.dateEntered = parseInputDate(inventoryItemPurchaseParams.dateEntered)
     796
     797                // Debug
     798                log.debug "InventoryItemPurchaseParams: "
     799                log.debug inventoryItemPurchaseParams
     800
     801                // Save inventoryItem.
     802                log.info "Creating new purchase."
     803                inventoryItemPurchaseInstance = new InventoryItemPurchase(inventoryItemPurchaseParams)
     804
     805                if(inventoryItemPurchaseInstance.hasErrors() || !inventoryItemPurchaseInstance.save()) {
     806                    log.error "Failed to create item on line: " + lineNumber
     807                    log.debug inventoryItemPurchaseInstance.errors
     808                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
     809                }
     810
     811                if(lineNumber % 100 == 0)
     812                    cleanUpGorm()
     813
     814                if(!result.error) nextLine()
     815            } //while(line)
     816
     817            // Success.
     818            log.info "End of file."
     819            reader.close()
     820            return result
     821
     822
     823         } //end withTransaction
     824    } // end importInventoryItemPurchases()
    644825
    645826    private getTemplateHeaderLine1() {
     
    648829            "Average Delivery Time", "Average Delivery Period", "Supplier's Part Number", "Preferred Supplier", "Alternate Suppliers",
    649830            "Manufacturer's Part Number", "Preferred Manufacturer", "Alternate Manufacturers", "Alternate Item", "Spare For"]
     831    }
     832
     833    private getPurchasesTemplateHeaderLine1() {
     834            ["Inventory Item*", "Purchase Order Number", "Quantity*", "Purchase Type*", "Cost Code*", "Entered By*",
     835            "Date Entered*", "Order Value", "Currency", "Invoice Number"]
    650836    }
    651837
  • trunk/grails-app/services/InventoryItemService.groovy

    r425 r441  
    2828    def show(params) {
    2929        def result = [:]
     30
    3031        def fail = { Map m ->
    3132            result.error = [ code: m.code, args: ["InventoryItem", params.id] ]
     
    3738        if(!result.inventoryItemInstance)
    3839            return fail(code:"default.not.found")
     40
     41        def p = [:]
     42
     43        if(params.paginate == "purchases") {
     44            params.showTab = "showPurchasingTab"
     45            p.max = Math.min(params.max?.toInteger() ?: 10, 100)
     46            p.offset = params.offset?.toInteger() ?: 0
     47            p.sort = params.sort ?: null
     48            p.order = params.order ?: null
     49        }
     50        else {
     51            p.max = 10
     52            p.offset = 0
     53        }
     54
     55        result.inventoryItemPurchasesTotal = InventoryItemPurchase.countByInventoryItem(result.inventoryItemInstance)
     56
     57        result.inventoryItemPurchases = InventoryItemPurchase.withCriteria {
     58                eq("inventoryItem", result.inventoryItemInstance)
     59                maxResults(p.max)
     60                firstResult(p.offset)
     61                // Sorting:
     62                // Default is to sort by order number then id.
     63                // When a sortable column is clicked then we sort by that.
     64                // If the sortable column clicked is order number then we add id as the second sort.
     65                if(p.sort && p.order) {
     66                    order(p.sort, p.order)
     67                    if(p.sort == "purchaseOrderNumber") order('id', 'asc')
     68                }
     69                else {
     70                    order('purchaseOrderNumber', 'desc')
     71                    order('id', 'asc')
     72                }
     73            }
    3974
    4075        result.showTab = [:]
     
    4681                result.showTab.movement =  new String("true")
    4782                break
     83            case "showPurchasingTab":
     84                result.showTab.purchasing =  new String("true")
     85                break
    4886            default:
    4987                result.showTab.inventory = new String("true")
    5088        }
    5189
    52         def p = [:]
    5390        p.max = result.inventoryMovementListMax = 10
     91        p.offset = 0
    5492        p.order = "desc"
    5593        p.sort = "id"
    5694        result.inventoryMovementList = InventoryMovement.findAllByInventoryItem(result.inventoryItemInstance, p)
    5795        result.inventoryMovementListTotal = InventoryMovement.countByInventoryItem(result.inventoryItemInstance)
     96
    5897
    5998        // Success.
Note: See TracChangeset for help on using the changeset viewer.