var fs = require("fs"); var csv = require('./csv.js'); var Promise = require('bluebird'); var fileName = "./importItems.csv"; // module.exports = function(models, softErrors) { // return new Promise(function(resolve, reject) { var models = require("./models"); var softErrors = []; var p = new Promise(function(resolve, reject) { //var sequelize = models.sequelize; //The CSV data as an array of rows (each row is an array). var data; //The mapping of model attributes to CSV columns. The oz sizes are arrays of columns since there are multiple. var map = {}; //The id's in the db for the various jar sizes. var measureIdMap = {}; //The id of the 'each' measure. var eachId = -1; //A default price for all items. var DEFAULT_PRICE = 11.0; //Collect the metadata from the first row of the CSV data - make a mapping. function collectMetadata() { var CATEGORY = 'category'; var SUBCATEGORY = 'subcategory'; var ITEM = 'item'; var OZ32 = '32 oz'; var OZ16 = '16 oz'; var OZ12 = '12 oz'; var OZ8 = '8 oz'; var OZ4 = '4 oz'; //Data is an array of arrays. data[0] = array of headers. data[1] = first row of data. //Iterate over the columns to create a mapping. for(var i = 0; i < data[0].length; i++) { var next = data[0][i]; if(next && next != '') { switch(next.toLowerCase()) { case CATEGORY: map.category = i; break; case SUBCATEGORY: map.subcategory = i; break; case ITEM: map.item = i; break; case OZ32: if(!map.oz32) map.oz32 = []; map.oz32.push(i); break; case OZ16: if(!map.oz16) map.oz16 = []; map.oz16.push(i); break; case OZ12: if(!map.oz12) map.oz12 = []; map.oz12.push(i); break; case OZ8: if(!map.oz8) map.oz8 = []; map.oz8.push(i); break; case OZ4: if(!map.oz4) map.oz4 = []; map.oz4.push(i); break; } } } } //Reads a single row of CSV data and adds it to the database. function readRow(rowIndex) { if(!data) { console.log("WTF?"); //process.exit(1); reject(new Error("Data is null?!?")); return; } else if(!data[rowIndex]) { softErrors.push("Empty line? - Found while reading items."); readRow(rowIndex + 1); return; } var category = data[rowIndex][map.category]; var subcategory = data[rowIndex][map.subcategory]; var item = data[rowIndex][map.item]; var oz32 = 0; var oz16 = 0; var oz12 = 0; var oz8 = 0; var oz4 = 0; for(var o = 0; o < map.oz32.length; o++) { oz32 += Math.max(data[rowIndex][map.oz32[o]], 0); } for(var o = 0; o < map.oz16.length; o++) { oz16 += Math.max(data[rowIndex][map.oz16[o]], 0); } for(var o = 0; o < map.oz12.length; o++) { oz12 += Math.max(data[rowIndex][map.oz12[o]], 0); } for(var o = 0; o < map.oz8.length; o++) { oz8 += Math.max(data[rowIndex][map.oz8[o]], 0); } for(var o = 0; o < map.oz4.length; o++) { oz4 += Math.max(data[rowIndex][map.oz4[o]], 0); } //If the category doesn't yet exist then add it, otherwise get the ID. models.Category.findOrCreate({where: {name: category}, defaults: {name: category}}).then(function(result) { var categoryId = result[0].id; //Note: result[1] is a boolean indicating whether the object had to be created. //If the subcategory doesn't yet exist then add it, otherwise get the ID. models.Subcategory.findOrCreate({ where: {name: subcategory}, defaults: {name: subcategory, categoryId: categoryId} }).then(function(result) { var subcategoryId = result[0].id; var weightedMeasures = []; var measures = []; if(oz32 > 0) weightedMeasures.push({name: '32 oz', count: oz32}); if(oz16 > 0) weightedMeasures.push({name: '16 oz', count: oz16}); if(oz12 > 0) weightedMeasures.push({name: '12 oz', count: oz12}); if(oz8 > 0) weightedMeasures.push({name: '8 oz', count: oz8}); if(oz4 > 0) weightedMeasures.push({name: '4 oz', count: oz4}); if(weightedMeasures.length == 0) { measures.push(eachId); } else { //Place the measure that had the most jars at the front of the list. weightedMeasures.sort(function(a, b) { return a.count >= b.count ? 1 : -1; }); //Build the array of measure id's. for(var i = 0; i < weightedMeasures.length; i++) { measures.push(measureIdMap[weightedMeasures[i].name]); } } //Ensure the item doesn't yet exist - display an error if it does, otherwise add it. models.Item.findOrCreate({ where: {name: item}, defaults: {name: item, subcategoryId: subcategoryId, measures: measures} }).then(function(result) { if(!result[1]) { console.log("The item named '" + item + "' already exists in the database."); } //Recursively read rows until there are no more rows to read. if(rowIndex + 1 < data.length) readRow(rowIndex + 1); else resolve(); }); }) }); } if(fs.existsSync(fileName)) { csv.read(fileName, function(error, csvData) { if(error) console.log(error); else { data = csvData; //Collect the mapping data. collectMetadata(); //Read or create the required models to make this all work: Promise.each([ models.Measure.findOrCreate({where: {name: 'Jar 32oz'}, defaults: {name: 'Jar 32oz', postfix: '32oz'}}), models.Measure.findOrCreate({where: {name: 'Jar 16oz'}, defaults: {name: 'Jar 16oz', postfix: '16oz'}}), models.Measure.findOrCreate({where: {name: 'Jar 12oz'}, defaults: {name: 'Jar 12oz', postfix: '12oz'}}), models.Measure.findOrCreate({where: {name: 'Jar 8oz'}, defaults: {name: 'Jar 8oz', postfix: '8oz'}}), models.Measure.findOrCreate({where: {name: 'Jar 4oz'}, defaults: {name: 'Jar 4oz', postfix: '4oz'}}), models.Measure.findOrCreate({where: {name: 'Each'}, defaults: {name: 'Each', postfix: ''}}) ], function(value, index, length) { switch(index) { case 0: measureIdMap['32 oz'] = value[0].id; break; case 1: measureIdMap['16 oz'] = value[0].id; break; case 2: measureIdMap['12 oz'] = value[0].id; break; case 3: measureIdMap['8 oz'] = value[0].id; break; case 4: measureIdMap['4 oz'] = value[0].id; break; case 5: eachId = value[0].id; break; } }).then(function() { //Read the first row. readRow(1); }); } }); } else { console.log("Cannot find " + fileName); } }); p.then(function() {console.log("Import Complete!")}).error(function(error) {console.log("Ran into an error: \n" + error)}); // };