Files
PetitTeton/importItems.js

221 lines
6.7 KiB
JavaScript

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)});
// };