Added graphs and charts; Updated a lot of the collections for security and consistency; Updated all of the page to fix bugs and propagate fixes to all templates; Added the d3 library for graphing; Added a real ui for Measures and Venues.

This commit is contained in:
Wynne Crisman
2017-02-03 09:20:29 -08:00
parent 55337521f6
commit 184ce1133f
38 changed files with 2564 additions and 641 deletions

View File

@@ -628,7 +628,7 @@ Meteor.methods({
collectMetadata(data[0]);
//Remove everything first.
Sales.remove({});
Sales.remove({"importTag": "1"});
// console.log("CSV Column Mapping: " + JSON.stringify(map));
// readRow(data[1]);
@@ -821,9 +821,192 @@ Meteor.methods({
function insertSale(sale) {
sale.createdAt = new Date();
sale.importTag = "1";
Sales.insert(sale, function(error) {
if(error) console.log("Failed to insert the sale: " + JSON.stringify(sale) + "\n ERROR: " + error);
});
}, {bypassCollection2: true});
}
},
"importSales2": function() {
let fileName = "importSales2.csv";
//The mapping of model attributes to CSV columns. The oz sizes are arrays of columns since there are multiple.
let map = {};
//The id's in the db for the letious jar sizes.
let measureIdMap = {};
let venueIdMap = {};
let itemIdMap = {};
let hasError = false;
{ //Load the object ids for the measures and venues we will encounter.
let result;
result = Measures.findOne({name: 'Pounds'}, {fields: {_id: 1}});
if(result) measureIdMap['lbs'] = result._id;
else {console.log("Error: Couldn't find the _id for Lbs"); hasError = true;}
result = Measures.findOne({name: 'Each'}, {fields: {_id: 1}});
if(result) measureIdMap['each'] = result._id;
else {console.log("Error: Couldn't find the _id for Each"); hasError = true;}
result = Measures.findOne({name: 'Dozen Large'}, {fields: {_id: 1}});
if(result) measureIdMap['dozen, large'] = result._id;
else {console.log("Error: Couldn't find the _id for Dozen, Large"); hasError = true;}
result = Venues.findOne({name: 'Boonville'}, {fields: {_id: 1}});
if(result) venueIdMap['bv'] = result._id;
else {console.log("Error: Couldn't find the _id for Boonville"); hasError = true;}
result = Venues.findOne({name: 'Clement St'}, {fields: {_id: 1}});
if(result) venueIdMap['sf'] = result._id;
else {console.log("Error: Couldn't find the _id for Clement St"); hasError = true;}
result = Venues.findOne({name: 'Ukiah'}, {fields: {_id: 1}});
if(result) venueIdMap['uk'] = result._id;
else {console.log("Error: Couldn't find the _id for Ukiah"); hasError = true;}
result = Venues.findOne({name: 'Mendocino'}, {fields: {_id: 1}});
if(result) venueIdMap['men'] = result._id;
else {console.log("Error: Couldn't find the _id for Mendocino"); hasError = true;}
result = Venues.findOne({name: 'Ft Bragg'}, {fields: {_id: 1}});
if(result) venueIdMap['fb'] = result._id;
else {console.log("Error: Couldn't find the _id for Ft Bragg"); hasError = true;}
result = Venues.findOne({name: 'On Farm'}, {fields: {_id: 1}});
if(result) venueIdMap['of'] = result._id;
else {console.log("Error: Couldn't find the _id for On Farm"); hasError = true;}
result = Venues.findOne({name: 'Unknown Restaurant'}, {fields: {_id: 1}});
if(result) {venueIdMap['res'] = result._id; venueIdMap['w'] = result._id;}
else {console.log("Error: Couldn't find the _id for Unknown Restaurant"); hasError = true;}
result = Venues.findOne({name: 'Yorkville Market'}, {fields: {_id: 1}});
if(result) venueIdMap['ym'] = result._id;
else {console.log("Error: Couldn't find the _id for Yorkville Market"); hasError = true;}
result = Venues.findOne({name: 'Yorkville Cellars'}, {fields: {_id: 1}});
if(result) venueIdMap['yc'] = result._id;
else {console.log("Error: Couldn't find the _id for Yorkville Cellars"); hasError = true;}
result = Venues.findOne({name: 'Mail Order'}, {fields: {_id: 1}});
if(result) venueIdMap['mo'] = result._id;
else {console.log("Error: Couldn't find the _id for Mail Order"); hasError = true;}
result = Products.find({}, {fields: {_id: 1, name: 1}, sort: {name: 1}}).fetch();
for(let i = 0; i < result.length; i++) itemIdMap[result[i].name.toLowerCase()] = result[i]._id;
}
readCSV(fileName, Meteor.bindEnvironment(function(error, data) {
//Data is an array of arrays. data[0] = array of headers. data[1] = first row of data.
if(error) console.log("Unable to read the importSales.csv file:" + error);
else {
//Collect the mapping data.
collectMetadata(data[0]);
//Remove everything first.
Sales.remove({"importTag": "2"});
let undefinedItems = {};
for(let i = 1; i < data.length; i++) {
readRow(data[i], undefinedItems);
}
}
}));
//Collect the metadata from the first row of the CSV data - make a mapping.
function collectMetadata(row) {
let DATE = 'date';
let VENUE = 'vendor';
let ITEM = 'item';
let LBS = 'lbs';
let EACH = 'each';
let DOZ = 'dozen, large';
let TOTAL = 'total';
//Iterate over the columns to create a mapping.
for(let i = 0; i < row.length; i++) {
let next = row[i];
if(next && next != '') {
switch(next.toLowerCase()) {
case DATE:
map.date = i;
break;
case VENUE:
map.venue = i;
break;
case ITEM:
map.item = i;
break;
case LBS:
map.lbs = i;
break;
case EACH:
map.each = i;
break;
case DOZ:
map.doz = i;
break;
case TOTAL:
map.total = i;
break;
}
}
}
}
//Reads a single row of CSV data and adds it to the database.
function readRow(row, undefinedItems) {
let date = moment(row[map.date], "M/D/YYYY").toDate();
let venue = row[map.venue] ? row[map.venue].toLowerCase() : undefined;
let item = row[map.item] ? row[map.item].trim() : undefined;
item = item ? item.toLowerCase() : undefined;
let lbs = row[map.lbs] == undefined ? 0 : Number(row[map.lbs]);
let each = row[map.each] == undefined ? 0 : Number(row[map.each]);
let doz = row[map.doz] == undefined ? 0 : Number(row[map.doz]);
let total = row[map.total] == undefined ? 0 : Number(row[map.total]);
let venueId = venueIdMap[venue];
let itemId = itemIdMap[item];
let year = date.getFullYear();
if(venueId == undefined) {
console.log("Found an undefined venue: " + venue);
console.log(row);
}
else if(itemId == undefined) {
console.log("Error: Could not find the item: '" + item + "'");
}
else if(total == undefined || total <= 0) {
console.log("Error: Invalid total '" + total + "' for the item: '" + item + "'");
}
else if(!(lbs > 0 || each > 0 || doz > 0)) {
console.log("Error: Invalid measures for the item: '" + item + "'");
}
else {
//Split it into multiple sales entries, one for each measure that has a positive value.
if(lbs > 0) {
let price = total / lbs;
insertSale({date: date, amount: lbs, price: price, venueId: venueId, productId: itemId, measureId: measureIdMap['lbs']});
}
if(each > 0) {
let price = total / each;
insertSale({date: date, amount: each, price: price, venueId: venueId, productId: itemId, measureId: measureIdMap['each']});
}
if(doz > 0) {
let price = total / doz;
insertSale({date: date, amount: doz, price: price, venueId: venueId, productId: itemId, measureId: measureIdMap['dozen, large']});
}
}
}
function insertSale(sale) {
sale.createdAt = new Date();
sale.importTag = "2";
Sales.insert(sale, function(error) {
if(error) console.log("Failed to insert the sale: " + JSON.stringify(sale) + "\n ERROR: " + error);
}, {bypassCollection2: true});
}
}
});