Added a Sales Sheet page along with other changes.

This commit is contained in:
Wynne Crisman
2017-05-09 13:51:26 -07:00
parent 184ce1133f
commit e1b0b19589
39 changed files with 3581 additions and 5610 deletions

View File

@@ -53,6 +53,11 @@ let SalesSchema = new SimpleSchema({
// }
// }
},
comment: {
type: String,
trim: false,
optional: true
},
createdAt: {
type: Date,
label: "Created On",
@@ -62,7 +67,7 @@ let SalesSchema = new SimpleSchema({
Sales.attachSchema(SalesSchema);
if(Meteor.isServer) {
Meteor.publish('sales', function(query, limit = 100, skipCount) {
Meteor.publish('sales', function(query, sort, limit = 100, skipCount) {
let dbQuery = [];
if(query) {
@@ -90,7 +95,7 @@ if(Meteor.isServer) {
if(!_.isNumber(skipCount) || skipCount < 0) skipCount = 0;
dbQuery = dbQuery.length > 0 ? {$and: dbQuery} : {};
return Meteor.collections.Sales.find(dbQuery, {limit: limit, sort: {date: -1, createdAt: -1}, skip: skipCount});
return Meteor.collections.Sales.find(dbQuery, {limit: limit, sort, skip: skipCount});
});
// time: expects either undefined, 'weekly', or 'monthly'
// options: expects either undefined, 'markets', or 'types'
@@ -179,6 +184,21 @@ if(Meteor.isServer) {
return Sales.find(query).count();
},
insertSale: function(sale) {
check(sale, {
date: Date,
amount: Match.Where(function(x) {
check(x, Number);
return x > 0;
}),
price: Match.Where(function(x) {
check(x, Number);
return x > 0;
}),
measureId: String,
productId: String,
venueId: String,
comment: Match.Optional(String)
});
//TODO: Check the structure of sale. Use: check(sale, {name: String, ...});
sale.createdAt = new Date();
@@ -193,9 +213,45 @@ if(Meteor.isServer) {
check(id, String);
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
Sales.remove(id, {bypassCollection2: true});
Sales.remove(id);
}
else throw new Meteor.Error(403, "Not authorized.");
},
editSaleComment: function(id, comment) {
check(id, String);
check(comment, String);
//Trim and convert empty comment to undefined.
comment = comment ? comment.trim() : undefined;
comment = comment && comment.length > 0 ? comment : undefined;
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
console.log("Changed comment of " + id + " to: " + comment);
if(comment) {
Sales.update(id, {$set: {comment}}, function(error, count) {
if(error) throw new Meteor.Error(400, "Unexpected database error: " + error);
});
}
else {
Sales.update(id, {$unset: {comment: ""}}, function(error, count) {
if(error) throw new Meteor.Error(400, "Unexpected database error: " + error);
});
}
}
else throw new Meteor.Error(403, "Not authorized.");
},
updateSale: function(id, date, venueId, price, amount) {
check(id, String);
check(date, Date);
check(venueId, String);
check(price, Number);
check(amount, Number);
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
Sales.update(id, {$set: {date, venueId, price, amount}}, function(err, id) {
if(err) console.log(err);
}, {bypassCollection2: true});
}
}
});
}

160
imports/api/SalesSheet.js Normal file
View File

@@ -0,0 +1,160 @@
import { Meteor } from 'meteor/meteor';
import { Mongo } from 'meteor/mongo';
import { check } from 'meteor/check';
import {SimpleSchema} from 'meteor/aldeed:simple-schema';
SalesSheets = new Mongo.Collection('SalesSheets');
const SalesSheetSchema = new SimpleSchema({
name: {
type: String,
label: "Name",
optional: false,
trim: true,
index: 1,
unique: false
},
products: { //An ordered array of product id's included on the sheet.
type: Array,
label: "products",
optional: false,
defaultValue: []
},
'products.$': {
type: new SimpleSchema({
name: {
type: String,
label: "Name",
optional: false,
trim: true,
unique: false
},
productId: { //Note: Will be non-existent for headings.
type: String,
label: "Product ID",
trim: false,
regEx: SimpleSchema.RegEx.Id,
optional: true
},
measureIds: { //Note: Will be non-existent for headings.
type: [String],
label: "Measure IDs",
optional: true
}
//measureIds: {
// type: Array,
// label: "Measure IDs",
// optional: true
//},
//'measureIds.$': {
// type: String,
// label: "Measure ID",
// trim: false,
// regEx: SimpleSchema.RegEx.Id,
// optional: false
//}
})
},
createdAt: {
type: Date,
label: "Created On",
optional: false
},
updatedAt: {
type: Date,
label: "Updated On",
optional: true
}
});
SalesSheets.attachSchema(SalesSheetSchema);
if(Meteor.isServer) {
Meteor.publish('salesSheets', function() {
return SalesSheets.find({});
});
Meteor.methods({
createSalesSheet: function(name) {
check(name, String);
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
return SalesSheets.insert({name, products: [], createdAt: new Date()});
}
else throw new Meteor.Error(403, "Not authorized.");
},
// This gets ridiculous. What would be required, along with a ton of code to micro manage each change.
//updateSalesSheet_addProduct: function(id, productId, productName, productMeasures) {
//
//},
//updateSalesSheet_removeProduct: function(id, productId) {
//
//},
//updateSalesSheet_updateProduct: function(id, productId, productName) {
//
//},
//updateSalesSheet_updateProduct_addMeasure: function(id, productId, productName, productMeasures) {
//
//},
//updateSalesSheet_updateProduct_removeMeasure: function(id, productId, productName, productMeasures) {
//
//},
updateSalesSheet: function(id, name, products) {
check(id, String);
check(name, String);
check(products, [{
productId: Match.Maybe(String),
name: String,
measureIds: Match.Maybe([String])
}]);
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
try {
// Generates some queries for testing.
//console.log("db.SalesSheet.update({_id: " + id + "}, {{name: " + name + ", products: " + products + ", updatedAt: " + new Date() + "}})");
//let productList = "";
//let firstProduct = true;
//for(next of products) {
// if(firstProduct) firstProduct = false;
// else productList += ',';
// productList += '{id:"' + next.id + '",name:"' + next.name + '",measureIds:[';
// let firstMeasure = true;
// for(measureId of next.measureIds) {
// if(firstMeasure) firstMeasure = false;
// else productList += ',';
// productList += '"' + measureId + '"';
// }
// productList += ']}';
//}
//console.log("db.SalesSheet.update({_id: '" + id + "'}, {$set: {name: '" + name + "', updatedAt: " + new Date() + "}, $pull: {$exists: true}, $pushAll: [" + productList + "]})");
// Forces the object to be re-written, versus piecemeal updated.
SalesSheets.update({_id: id}, {$set: {name: name, products: products, updatedAt: new Date()}}, {validate: false}, function(err, count) {
if(err) console.log(err);
});
// Attempts to remove all products and re-add them. Note: Does not work!
//SalesSheet.update({_id: id}, {$set: {name: name, updatedAt: new Date()}, $pull: {products: {$exists: true}}}, {bypassCollection2: true}, function(err, count) {
// if(err) console.log(err);
//});
//SalesSheet.update({_id: id}, {$push: {products: {$each: [products]}}}, {bypassCollection2: true}, function(err, count) {
// if(err) console.log(err);
//});
}
catch(err) {
console.log(err);
}
}
else throw new Meteor.Error(403, "Not authorized.");
},
removeSalesSheet: function(id) {
check(id, String);
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
SalesSheets.remove(id);
}
else throw new Meteor.Error(403, "Not authorized.");
}
});
}
export default SalesSheets;

View File

@@ -46,16 +46,16 @@ if(Meteor.isServer) Meteor.publish('venues', function() {
return Venues.find({});
});
// //Requires: meteor add matb33:collection-hooks
if(Meteor.isServer) {
Venues.before.insert(function(userId, doc) {
// check(userId, String);
doc.createdAt = new Date();
});
Venues.before.update(function(userId, doc, fieldNames, modifier, options) {
modifier.$set = modifier.$set || {}; //Make sure there is an object.
modifier.$set.updatedAt = new Date();
});
// //Requires: meteor add matb33:collection-hooks
//Venues.before.insert(function(userId, doc) {
// // check(userId, String);
// doc.createdAt = new Date();
//});
//Venues.before.update(function(userId, doc, fieldNames, modifier, options) {
// modifier.$set = modifier.$set || {}; //Make sure there is an object.
// modifier.$set.updatedAt = new Date();
//});
Meteor.methods({
createVenue: function(name, type) {

View File

@@ -1,14 +1,16 @@
//import Categories from "./Category.js";
//import Subcategories from "./Subcategory.js";
import Measures from "./Measure.js";
import Venues from "./Venue.js";
import Products from "./Product.js";
import ProductTags from "./ProductTag.js";
import Sales from "./Sale.js";
import SalesSheets from "./SalesSheet.js";
import Users from "./User.js";
import UserRoles from "./Roles.js";
Meteor.collections = {Measures, Venues, Products, ProductTags, Sales, Users, UserRoles};
//Save the collections in the Meteor.collections property for easy access without name conflicts.
Meteor.collections = {Measures, Venues, Products, ProductTags, Sales, SalesSheets, Users, UserRoles};
//If this is the server then setup the default admin user if none exist.
if(Meteor.isServer) {
//Change this to find admin users, create a default admin user if none exists.
if(Users.find({}).count() == 0) {