Started adding async calls for upgrading to Meteor 3.0. Numerous other fixes.
This commit is contained in:
@@ -5,27 +5,26 @@
|
|||||||
# but you can also edit it by hand.
|
# but you can also edit it by hand.
|
||||||
|
|
||||||
meteor-base@1.5.1 # Packages every Meteor app needs to have
|
meteor-base@1.5.1 # Packages every Meteor app needs to have
|
||||||
mobile-experience@1.1.0 # Packages for a great mobile UX
|
mobile-experience@1.1.1 # Packages for a great mobile UX
|
||||||
mongo@1.16.5 # The database Meteor supports right now
|
mongo@1.16.10 # The database Meteor supports right now
|
||||||
blaze-html-templates@1.0.4 # Compile .html files into Meteor Blaze views
|
blaze-html-templates@2.0.1 # Compile .html files into Meteor Blaze views
|
||||||
reactive-var@1.0.12 # Reactive variable for tracker
|
reactive-var@1.0.12 # Reactive variable for tracker
|
||||||
tracker@1.3.1 # Meteor's client-side reactive programming library
|
tracker@1.3.3 # Meteor's client-side reactive programming library
|
||||||
tomwasd:history-polyfill # Adds IE 8/9 support for HTML5 history.
|
tomwasd:history-polyfill # Adds IE 8/9 support for HTML5 history.
|
||||||
email@2.2.4 # Adds the Meteor/Email package for sending lost password emails
|
email@2.2.6 # Adds the Meteor/Email package for sending lost password emails
|
||||||
|
|
||||||
standard-minifier-css@1.9.0 # CSS minifier run for production mode
|
standard-minifier-css@1.9.2 # CSS minifier run for production mode
|
||||||
standard-minifier-js@2.8.1 # JS minifier run for production mode
|
standard-minifier-js@2.8.1 # JS minifier run for production mode
|
||||||
es5-shim@4.8.0 # ECMAScript 5 compatibility for older browsers.
|
es5-shim@4.8.0 # ECMAScript 5 compatibility for older browsers.
|
||||||
poorvavyas:es6-shim
|
poorvavyas:es6-shim
|
||||||
ecmascript@0.16.6 # Enable ECMAScript2015+ syntax in app code
|
ecmascript@0.16.8 # Enable ECMAScript2015+ syntax in app code
|
||||||
|
|
||||||
#accounts-ui
|
#accounts-ui
|
||||||
#accounts-base
|
#accounts-base
|
||||||
accounts-password@2.3.4
|
accounts-password@2.4.0
|
||||||
useraccounts:core
|
useraccounts:core
|
||||||
useraccounts:unstyled
|
useraccounts:unstyled
|
||||||
useraccounts:flow-routing # Configures email flows. Used for AccountsTemplates class.
|
useraccounts:flow-routing # Configures email flows. Used for AccountsTemplates class.
|
||||||
alanning:roles # Adds roles to the user mix. https://atmospherejs.com/alanning/roles && https://github.com/alanning/meteor-roles/blob/master/examples/flow-router/
|
|
||||||
|
|
||||||
kadira:flow-router
|
kadira:flow-router
|
||||||
arillo:flow-router-helpers # Provides various template helpers such as {{pathFor 'templateName'}}
|
arillo:flow-router-helpers # Provides various template helpers such as {{pathFor 'templateName'}}
|
||||||
@@ -34,14 +33,12 @@ kadira:blaze-layout
|
|||||||
|
|
||||||
#shell-server@0.4.0 # ???
|
#shell-server@0.4.0 # ???
|
||||||
#meteortoys:allthings
|
#meteortoys:allthings
|
||||||
stylus@2.513.13
|
|
||||||
session@1.2.1
|
session@1.2.1
|
||||||
##browser-policy # Adds support for specifying browser level security rules related to content and what's allowed to laod on the page.
|
##browser-policy # Adds support for specifying browser level security rules related to content and what's allowed to laod on the page.
|
||||||
check@1.3.2 # Allows for checking the structure and types of arguments passed to Meteor methods and publications.
|
check@1.4.1 # Allows for checking the structure and types of arguments passed to Meteor methods and publications.
|
||||||
#audit-argument-checks # Used in combination with the Check package for checking the structure and types of arguments passed to Meteor methods and publications. Automatically alerts when a method or publication does not use a check() call.
|
#audit-argument-checks # Used in combination with the Check package for checking the structure and types of arguments passed to Meteor methods and publications. Automatically alerts when a method or publication does not use a check() call.
|
||||||
|
|
||||||
aldeed:simple-schema@1.5.3
|
#aldeed:simple-schema@1.5.3 #Should now be included in collection2 v4+
|
||||||
aldeed:collection2
|
|
||||||
#matb33:collection-hooks # Allows the collections to register handlers that run before or after database interactions.
|
#matb33:collection-hooks # Allows the collections to register handlers that run before or after database interactions.
|
||||||
#zimme:collection-softremovable
|
#zimme:collection-softremovable
|
||||||
|
|
||||||
@@ -60,10 +57,13 @@ juliancwirko:s-alert # Client error/alert handling
|
|||||||
jcbernack:reactive-aggregate # Allows us to create a new client collection (from the server) with the contents being an aggregate of server data. Note that aggregation can only be done on the server currently as mini-mongo does not support it.
|
jcbernack:reactive-aggregate # Allows us to create a new client collection (from the server) with the contents being an aggregate of server data. Note that aggregation can only be done on the server currently as mini-mongo does not support it.
|
||||||
ostrio:logger
|
ostrio:logger
|
||||||
ostrio:loggermongo
|
ostrio:loggermongo
|
||||||
dynamic-import@0.7.2
|
dynamic-import@0.7.3
|
||||||
markdown@1.0.12
|
markdown@2.0.0
|
||||||
wcrisman:jquery-custom-scrollbar
|
wcrisman:jquery-custom-scrollbar
|
||||||
underscore@1.0.12
|
underscore@1.6.1
|
||||||
meteorhacks:aggregate # Allows databaseName.aggragate(pipeline) calls the exact same way you would on the command line in the mongo tool.
|
meteorhacks:aggregate # Allows databaseName.aggragate(pipeline) calls the exact same way you would on the command line in the mongo tool.
|
||||||
#babrahams:constellation # Provides client side debugging when the server is not run in production mode.
|
#babrahams:constellation # Provides client side debugging when the server is not run in production mode.
|
||||||
jquery
|
jquery
|
||||||
|
aldeed:collection2
|
||||||
|
fourseven:scss
|
||||||
|
alanning:roles
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
METEOR@2.11.0
|
METEOR@2.16
|
||||||
|
|||||||
116
.meteor/versions
116
.meteor/versions
@@ -1,90 +1,87 @@
|
|||||||
accounts-base@2.2.7
|
accounts-base@2.2.11
|
||||||
accounts-password@2.3.4
|
accounts-password@2.4.0
|
||||||
alanning:roles@1.3.0
|
alanning:roles@3.6.3
|
||||||
aldeed:collection2@2.10.0
|
aldeed:collection2@4.0.2
|
||||||
aldeed:collection2-core@1.2.0
|
aldeed:simple-schema@1.13.1
|
||||||
aldeed:schema-deny@1.1.0
|
|
||||||
aldeed:schema-index@1.1.1
|
|
||||||
aldeed:simple-schema@1.5.4
|
|
||||||
aldeed:template-extension@4.1.0
|
aldeed:template-extension@4.1.0
|
||||||
allow-deny@1.1.1
|
allow-deny@1.1.1
|
||||||
arillo:flow-router-helpers@0.5.2
|
arillo:flow-router-helpers@0.5.2
|
||||||
autoupdate@1.8.0
|
autoupdate@1.8.0
|
||||||
babel-compiler@7.10.3
|
babel-compiler@7.10.5
|
||||||
babel-runtime@1.5.1
|
babel-runtime@1.5.1
|
||||||
base64@1.0.12
|
base64@1.0.12
|
||||||
binary-heap@1.0.11
|
binary-heap@1.0.11
|
||||||
blaze@2.5.0
|
blaze@2.9.0
|
||||||
blaze-html-templates@1.2.1
|
blaze-html-templates@2.0.1
|
||||||
blaze-tools@1.1.3
|
blaze-tools@1.1.4
|
||||||
boilerplate-generator@1.7.1
|
boilerplate-generator@1.7.2
|
||||||
caching-compiler@1.2.2
|
caching-compiler@1.2.2
|
||||||
caching-html-compiler@1.2.0
|
caching-html-compiler@1.2.2
|
||||||
callback-hook@1.5.0
|
callback-hook@1.5.1
|
||||||
check@1.3.2
|
check@1.4.1
|
||||||
coffeescript@1.0.17
|
coffeescript@1.0.17
|
||||||
ddp@1.4.1
|
ddp@1.4.1
|
||||||
ddp-client@2.6.1
|
ddp-client@2.6.2
|
||||||
ddp-common@1.4.0
|
ddp-common@1.4.1
|
||||||
ddp-rate-limiter@1.1.1
|
ddp-rate-limiter@1.2.1
|
||||||
ddp-server@2.6.0
|
ddp-server@2.7.1
|
||||||
diff-sequence@1.1.2
|
diff-sequence@1.1.2
|
||||||
dynamic-import@0.7.2
|
dynamic-import@0.7.3
|
||||||
ecmascript@0.16.6
|
ecmascript@0.16.8
|
||||||
ecmascript-runtime@0.8.0
|
ecmascript-runtime@0.8.1
|
||||||
ecmascript-runtime-client@0.12.1
|
ecmascript-runtime-client@0.12.1
|
||||||
ecmascript-runtime-server@0.11.0
|
ecmascript-runtime-server@0.11.0
|
||||||
ejson@1.1.3
|
ejson@1.1.3
|
||||||
email@2.2.4
|
email@2.2.6
|
||||||
es5-shim@4.8.0
|
es5-shim@4.8.0
|
||||||
fetch@0.1.3
|
fetch@0.1.4
|
||||||
fortawesome:fontawesome@4.7.0
|
fortawesome:fontawesome@4.7.0
|
||||||
|
fourseven:scss@4.16.0
|
||||||
geojson-utils@1.0.11
|
geojson-utils@1.0.11
|
||||||
hot-code-push@1.0.4
|
hot-code-push@1.0.4
|
||||||
html-tools@1.1.3
|
html-tools@1.1.4
|
||||||
htmljs@1.1.1
|
htmljs@1.2.1
|
||||||
http@1.4.4
|
http@2.0.0
|
||||||
id-map@1.1.1
|
id-map@1.1.1
|
||||||
inter-process-messaging@0.1.1
|
inter-process-messaging@0.1.1
|
||||||
jcbernack:reactive-aggregate@0.7.0
|
jcbernack:reactive-aggregate@1.0.0
|
||||||
jquery@1.11.11
|
jquery@1.11.11
|
||||||
juliancwirko:s-alert@3.2.0
|
juliancwirko:s-alert@3.2.0
|
||||||
kadira:blaze-layout@2.3.0
|
kadira:blaze-layout@2.3.0
|
||||||
kadira:flow-router@2.12.1
|
kadira:flow-router@2.12.1
|
||||||
launch-screen@1.3.0
|
launch-screen@2.0.0
|
||||||
localstorage@1.2.0
|
localstorage@1.2.0
|
||||||
logging@1.3.2
|
logging@1.3.4
|
||||||
markdown@1.0.14
|
markdown@2.0.0
|
||||||
mdg:validation-error@0.2.0
|
meteor@1.11.5
|
||||||
meteor@1.11.1
|
|
||||||
meteor-base@1.5.1
|
meteor-base@1.5.1
|
||||||
meteorhacks:aggregate@1.3.0
|
meteorhacks:aggregate@1.3.0
|
||||||
meteorhacks:collection-utils@1.2.0
|
meteorhacks:collection-utils@1.2.0
|
||||||
minifier-css@1.6.2
|
minifier-css@1.6.4
|
||||||
minifier-js@2.7.5
|
minifier-js@2.8.0
|
||||||
minimongo@1.9.2
|
minimongo@1.9.4
|
||||||
mobile-experience@1.1.0
|
mobile-experience@1.1.1
|
||||||
mobile-status-bar@1.1.0
|
mobile-status-bar@1.1.0
|
||||||
modern-browsers@0.1.9
|
modern-browsers@0.1.10
|
||||||
modules@0.19.0
|
modules@0.20.0
|
||||||
modules-runtime@0.13.1
|
modules-runtime@0.13.1
|
||||||
momentjs:moment@2.29.3
|
momentjs:moment@2.30.1
|
||||||
mongo@1.16.5
|
mongo@1.16.10
|
||||||
mongo-decimal@0.1.3
|
mongo-decimal@0.1.3
|
||||||
mongo-dev-server@1.1.0
|
mongo-dev-server@1.1.0
|
||||||
mongo-id@1.0.8
|
mongo-id@1.0.8
|
||||||
mongo-livedata@1.0.12
|
mongo-livedata@1.0.12
|
||||||
npm-mongo@4.14.0
|
npm-mongo@4.17.2
|
||||||
observe-sequence@1.0.20
|
observe-sequence@1.0.22
|
||||||
ordered-dict@1.1.0
|
ordered-dict@1.1.0
|
||||||
ostrio:logger@2.1.1
|
ostrio:logger@2.1.1
|
||||||
ostrio:loggermongo@2.1.0
|
ostrio:loggermongo@2.1.0
|
||||||
poorvavyas:es6-shim@0.21.1
|
poorvavyas:es6-shim@0.21.1
|
||||||
promise@0.12.2
|
promise@0.12.2
|
||||||
raix:eventemitter@0.1.3
|
raix:eventemitter@1.0.0
|
||||||
random@1.2.1
|
random@1.2.1
|
||||||
rate-limit@1.0.9
|
rate-limit@1.1.1
|
||||||
react-fast-refresh@0.2.6
|
react-fast-refresh@0.2.8
|
||||||
reactive-dict@1.3.1
|
reactive-dict@1.3.1
|
||||||
reactive-var@1.0.12
|
reactive-var@1.0.12
|
||||||
reload@1.3.1
|
reload@1.3.1
|
||||||
@@ -92,25 +89,26 @@ retry@1.1.0
|
|||||||
routepolicy@1.1.1
|
routepolicy@1.1.1
|
||||||
session@1.2.1
|
session@1.2.1
|
||||||
sha@1.0.9
|
sha@1.0.9
|
||||||
socket-stream-client@0.5.0
|
socket-stream-client@0.5.2
|
||||||
spacebars@1.2.0
|
spacebars@1.6.0
|
||||||
spacebars-compiler@1.2.1
|
spacebars-compiler@1.3.2
|
||||||
standard-minifier-css@1.9.0
|
standard-minifier-css@1.9.2
|
||||||
standard-minifier-js@2.8.1
|
standard-minifier-js@2.8.1
|
||||||
stylus@2.513.14
|
templating@1.4.3
|
||||||
templating@1.4.1
|
templating-compiler@1.4.2
|
||||||
templating-compiler@1.4.1
|
templating-runtime@1.6.4
|
||||||
templating-runtime@1.5.0
|
templating-tools@1.2.3
|
||||||
templating-tools@1.2.0
|
|
||||||
tomwasd:history-polyfill@0.0.1
|
tomwasd:history-polyfill@0.0.1
|
||||||
tracker@1.3.1
|
tracker@1.3.3
|
||||||
|
typescript@4.9.5
|
||||||
ui@1.0.13
|
ui@1.0.13
|
||||||
underscore@1.0.12
|
underscore@1.6.1
|
||||||
url@1.3.2
|
url@1.3.2
|
||||||
useraccounts:core@1.16.2
|
useraccounts:core@1.16.2
|
||||||
useraccounts:flow-routing@1.15.0
|
useraccounts:flow-routing@1.15.0
|
||||||
useraccounts:unstyled@1.14.2
|
useraccounts:unstyled@1.14.2
|
||||||
wcrisman:jquery-custom-scrollbar@3.0.0
|
wcrisman:jquery-custom-scrollbar@3.0.0
|
||||||
webapp@1.13.4
|
webapp@1.13.8
|
||||||
webapp-hashing@1.1.1
|
webapp-hashing@1.1.1
|
||||||
zimme:active-route@2.3.2
|
zimme:active-route@2.3.2
|
||||||
|
zodern:types@1.0.13
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
# Current Configuration
|
# Current Configuration
|
||||||
|
|
||||||
|
## NodeJS
|
||||||
|
Use [NVM](https://github.com/coreybutler/nvm-windows) on Windows to set the available versions of NodeJS. By default they are stored in `C:\Users\<user>\AppData\Roaming\nvm`.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
See below for initial setup and updating instructions.
|
See below for initial setup and updating instructions.
|
||||||
|
|
||||||
Currently we have three servers in two locations. Media and FS2 are computers residing on the 18501 property (big barn back top room, and Wynne/Sarah house), and FS1 is a computer residing in SF. All three are accessible via Putty (a windows SSH client - any SSH client will work) via the IP's 192.168.3.101 (Media), 192.168.2.239 (FS1), and 192.168.3.164 (FS2). Note that FS1 is in SF, but is accessible via the LAN because we have a VPN setup between our routers (192.168.3.1, and 192.168.2.1). The VPN makes them look like they are on the same network.
|
Currently we have three servers in two locations. Media and FS2 are computers residing on the 18501 property (big barn back top room, and Wynne/Sarah house), and FS1 is a computer residing in SF. All three are accessible via Putty (a windows SSH client - any SSH client will work) via the IP's 192.168.3.101 (Media), 192.168.2.239 (FS1), and 192.168.3.164 (FS2). Note that FS1 is in SF, but is accessible via the LAN because we have a VPN setup between our routers (192.168.3.1, and 192.168.2.1). The VPN makes them look like they are on the same network.
|
||||||
|
|||||||
@@ -1,9 +1,20 @@
|
|||||||
import {Mongo} from "meteor/mongo";
|
import {Mongo} from "meteor/mongo";
|
||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { check } from 'meteor/check';
|
import { check } from 'meteor/check';
|
||||||
import {SimpleSchema} from 'meteor/aldeed:simple-schema';
|
import 'meteor/aldeed:collection2/static'
|
||||||
|
import SimpleSchema from 'meteor/aldeed:simple-schema';
|
||||||
|
import Products from "./Product";
|
||||||
|
import Measures from "./Measure";
|
||||||
|
|
||||||
Barcodes = new Mongo.Collection('Barcodes');
|
let Barcodes = new Mongo.Collection('Barcodes');
|
||||||
|
|
||||||
|
if(Meteor.isServer) {
|
||||||
|
//Set MongoDB indexes (or remove them) here.
|
||||||
|
try {
|
||||||
|
Barcodes.rawCollection().createIndex({barcodeId: -1}, {unique: true})
|
||||||
|
Barcodes.rawCollection().createIndex({productAndMeasureId: -1}, {unique: true})
|
||||||
|
} catch(e) {console.log("Caught exception while setting indexes in MongoDB"); console.error(e)}
|
||||||
|
}
|
||||||
|
|
||||||
// A simple mapping between a concatenation of the product & measure ID and a unique sequential number for the barcode. This allows us to have a small number to keep our barcodes simple, while maintaining the more traditional MongoDB ID's for the Product and Measure.
|
// A simple mapping between a concatenation of the product & measure ID and a unique sequential number for the barcode. This allows us to have a small number to keep our barcodes simple, while maintaining the more traditional MongoDB ID's for the Product and Measure.
|
||||||
const BarcodesSchema = new SimpleSchema({
|
const BarcodesSchema = new SimpleSchema({
|
||||||
@@ -11,15 +22,15 @@ const BarcodesSchema = new SimpleSchema({
|
|||||||
type: Number,
|
type: Number,
|
||||||
label: "Barcode ID",
|
label: "Barcode ID",
|
||||||
optional: false,
|
optional: false,
|
||||||
index: 1,
|
//index: 1,
|
||||||
unique: true
|
//unique: true
|
||||||
},
|
},
|
||||||
productAndMeasureId: { //Just the two ids jammed together with a single space between them.
|
productAndMeasureId: { //Just the two ids jammed together with a single space between them.
|
||||||
type: String,
|
type: String,
|
||||||
label: "Product And Measure ID",
|
label: "Product And Measure ID",
|
||||||
optional: false,
|
optional: false,
|
||||||
index: 1,
|
//index: 1,
|
||||||
unique: true
|
//unique: true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -29,15 +40,15 @@ if(Meteor.isServer) {
|
|||||||
//});
|
//});
|
||||||
|
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
getBarcodeId: function(productId, measureId) {
|
getBarcodeId: async function(productId, measureId) {
|
||||||
check(productId, String);
|
check(productId, String);
|
||||||
check(measureId, String);
|
check(measureId, String);
|
||||||
|
|
||||||
let hasProduct = Meteor.collections.Products.findOne({_id: productId}, {fields: {}});
|
let hasProduct = await Meteor.collections.Products.findOneAsync({_id: productId}, {fields: {}});
|
||||||
let hasMeasure = Meteor.collections.Measures.findOne({_id: measureId}, {fields: {}});
|
let hasMeasure = await Meteor.collections.Measures.findOneAsync({_id: measureId}, {fields: {}});
|
||||||
|
|
||||||
if(hasProduct && hasMeasure) {
|
if(hasProduct && hasMeasure) {
|
||||||
let existing = Barcodes.findOne({productAndMeasureId: productId + ' ' + measureId});
|
let existing = await Barcodes.findOneAsync({productAndMeasureId: productId + ' ' + measureId});
|
||||||
|
|
||||||
if(existing) {
|
if(existing) {
|
||||||
return existing.barcodeId;
|
return existing.barcodeId;
|
||||||
@@ -48,10 +59,12 @@ if(Meteor.isServer) {
|
|||||||
//Try a thousand times before failing. Should never fail, should also not ever need to try a thousand times (unless we somehow automate label generation to the point where a 1000 processes at once are requesting labels that have never been generated before - highly unlikely).
|
//Try a thousand times before failing. Should never fail, should also not ever need to try a thousand times (unless we somehow automate label generation to the point where a 1000 processes at once are requesting labels that have never been generated before - highly unlikely).
|
||||||
while(c++ < 1000) {
|
while(c++ < 1000) {
|
||||||
//Lookup the most likely next barcode id from the db, then attempt to insert with it. If it fails due to duplication, then increment and repeat.
|
//Lookup the most likely next barcode id from the db, then attempt to insert with it. If it fails due to duplication, then increment and repeat.
|
||||||
let cursor = Products.find({}, {barcodeId: 1}).sort({barcodeId: -1}).limit(1); //Since currently products are never removed, we shouldn't need to detect sequence gaps and fill them in (odds are we will never use more than 10k numbers anyway).
|
//let cursor = Products.find({}, {barcodeId: 1}).sort({barcodeId: -1}).limit(1); //Since currently products are never removed, we shouldn't need to detect sequence gaps and fill them in (odds are we will never use more than 10k numbers anyway).
|
||||||
let barcodeId = cursor.hasNext() ? cursor.next().barcodeId + 1 : 1;
|
//let barcodeId = cursor.hasNext() ? cursor.next().barcodeId + 1 : 1;
|
||||||
|
let product = await Products.findOneAsync({barcodeId: {$exists: true}}, {sort: {barcodeId: -1}})
|
||||||
|
let barcodeId = product ? product.barcodeId : 1;
|
||||||
|
|
||||||
Barcodes.insert({productAndMeasureId: productId + ' ' + measureId, barcodeId}, function(err, id) {
|
await Barcodes.insertAsync({productAndMeasureId: productId + ' ' + measureId, barcodeId}, function(err, id) {
|
||||||
if(err) console.log(err);
|
if(err) console.log(err);
|
||||||
else return barcodeId;
|
else return barcodeId;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { Mongo } from 'meteor/mongo';
|
import { Mongo } from 'meteor/mongo';
|
||||||
import { check } from 'meteor/check';
|
import { check } from 'meteor/check';
|
||||||
import {SimpleSchema} from 'meteor/aldeed:simple-schema';
|
import 'meteor/aldeed:collection2/static'
|
||||||
|
import SimpleSchema from 'meteor/aldeed:simple-schema';
|
||||||
|
import Measures from "./Measure";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notes:
|
* Notes:
|
||||||
@@ -10,12 +12,24 @@ import {SimpleSchema} from 'meteor/aldeed:simple-schema';
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
let Batches = new Mongo.Collection('Batches');
|
let Batches = new Mongo.Collection('Batches');
|
||||||
|
|
||||||
|
if(Meteor.isServer) {
|
||||||
|
//Set MongoDB indexes (or remove them) here.
|
||||||
|
try {
|
||||||
|
Batches.rawCollection().createIndex({date: -1}, {unique: false})
|
||||||
|
Batches.rawCollection().createIndex({measureId: -1}, {unique: false})
|
||||||
|
Batches.rawCollection().createIndex({productId: -1}, {unique: false})
|
||||||
|
Batches.rawCollection().createIndex({cookId: -1}, {unique: false})
|
||||||
|
Batches.rawCollection().createIndex({cannerId: -1}, {unique: false})
|
||||||
|
} catch(e) {console.log("Caught exception while setting indexes in MongoDB"); console.error(e)}
|
||||||
|
}
|
||||||
|
|
||||||
let BatchesSchema = new SimpleSchema({
|
let BatchesSchema = new SimpleSchema({
|
||||||
date: {
|
date: {
|
||||||
type: Number, // A number in the format of YYYYMMDD to allow for searching using greater and less than, and to prevent timezones from messing everything up.
|
type: Number, // A number in the format of YYYYMMDD to allow for searching using greater and less than, and to prevent timezones from messing everything up.
|
||||||
label: "Date",
|
label: "Date",
|
||||||
optional: false,
|
optional: false,
|
||||||
index: 1
|
//index: 1
|
||||||
},
|
},
|
||||||
timestamp: { //This is based off the date with zero for the time and set to GMT (Zulu time).
|
timestamp: { //This is based off the date with zero for the time and set to GMT (Zulu time).
|
||||||
type: Date,
|
type: Date,
|
||||||
@@ -31,21 +45,21 @@ let BatchesSchema = new SimpleSchema({
|
|||||||
type: Number,
|
type: Number,
|
||||||
label: "Amount",
|
label: "Amount",
|
||||||
optional: false,
|
optional: false,
|
||||||
decimal: true
|
//decimal: true
|
||||||
},
|
},
|
||||||
measureId: {
|
measureId: {
|
||||||
type: String,
|
type: String,
|
||||||
label: "Measure Id",
|
label: "Measure Id",
|
||||||
trim: false,
|
trim: false,
|
||||||
regEx: SimpleSchema.RegEx.Id,
|
regEx: SimpleSchema.RegEx.Id,
|
||||||
index: 1
|
//index: 1
|
||||||
},
|
},
|
||||||
productId: {
|
productId: {
|
||||||
type: String,
|
type: String,
|
||||||
label: "Product Id",
|
label: "Product Id",
|
||||||
trim: false,
|
trim: false,
|
||||||
regEx: SimpleSchema.RegEx.Id,
|
regEx: SimpleSchema.RegEx.Id,
|
||||||
index: 1,
|
//index: 1,
|
||||||
optional: false
|
optional: false
|
||||||
},
|
},
|
||||||
cookId: {
|
cookId: {
|
||||||
@@ -53,14 +67,14 @@ let BatchesSchema = new SimpleSchema({
|
|||||||
label: "Cook Worker Id",
|
label: "Cook Worker Id",
|
||||||
trim: false,
|
trim: false,
|
||||||
regEx: SimpleSchema.RegEx.Id,
|
regEx: SimpleSchema.RegEx.Id,
|
||||||
index: 1
|
//index: 1
|
||||||
},
|
},
|
||||||
cannerId: {
|
cannerId: {
|
||||||
type: String,
|
type: String,
|
||||||
label: "Canner Worker Id",
|
label: "Canner Worker Id",
|
||||||
trim: false,
|
trim: false,
|
||||||
regEx: SimpleSchema.RegEx.Id,
|
regEx: SimpleSchema.RegEx.Id,
|
||||||
index: 1,
|
//index: 1,
|
||||||
optional: false
|
optional: false
|
||||||
},
|
},
|
||||||
hasLabels: {
|
hasLabels: {
|
||||||
@@ -134,11 +148,11 @@ if(Meteor.isServer) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
getBatchCount: function(query) {
|
getBatchCount: async function(query) {
|
||||||
//TODO: Validate the query?
|
//TODO: Validate the query?
|
||||||
return Batches.find(query).count();
|
return await Batches.countDocuments(query);
|
||||||
},
|
},
|
||||||
insertBatches: function(batches) { //Insert one or more batches (if one, you can pass just the batch).
|
insertBatches: async function(batches) { //Insert one or more batches (if one, you can pass just the batch).
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
//Force it to be an array if it isn't.
|
//Force it to be an array if it isn't.
|
||||||
if(!Array.isArray(batches)) batches = [batches];
|
if(!Array.isArray(batches)) batches = [batches];
|
||||||
@@ -170,37 +184,37 @@ if(Meteor.isServer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(let batch of batches) {
|
for(let batch of batches) {
|
||||||
Batches.insert(batch, function(err, id) {
|
await Batches.insertAsync(batch, function(err, id) {
|
||||||
if(err) console.log(err);
|
if(err) console.log(err);
|
||||||
}, {bypassCollection2: true});
|
}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
deleteBatch: function(id) { //Does not actually delete the batch, but rather just marks it for deleting by applying a deletion date.
|
deleteBatch: async function(id) { //Does not actually delete the batch, but rather just marks it for deleting by applying a deletion date.
|
||||||
check(id, String);
|
check(id, String);
|
||||||
|
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
let deletedAt = new Date();
|
let deletedAt = new Date();
|
||||||
|
|
||||||
//Batches.remove(id);
|
//Batches.remove(id);
|
||||||
Batches.update(id, {$set: {deletedAt}}, function(err, id) {
|
await Batches.updateAsync(id, {$set: {deletedAt}}, function(err, id) {
|
||||||
if(err) console.log(err);
|
if(err) console.log(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
undeleteBatch: function(id) { //Revokes the previous deletion.
|
undeleteBatch: async function(id) { //Revokes the previous deletion.
|
||||||
check(id, String);
|
check(id, String);
|
||||||
|
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Batches.update(id, {$unset: {deletedAt:""}}, function(err, id) {
|
await Batches.updateAsync(id, {$unset: {deletedAt:""}}, function(err, id) {
|
||||||
if(err) console.log(err);
|
if(err) console.log(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
//editBatchComment: function(id, comment) {
|
//editBatchComment: async function(id, comment) {
|
||||||
// check(id, String);
|
// check(id, String);
|
||||||
// check(comment, String);
|
// check(comment, String);
|
||||||
// //Trim and convert empty comment to undefined.
|
// //Trim and convert empty comment to undefined.
|
||||||
@@ -211,19 +225,19 @@ if(Meteor.isServer) {
|
|||||||
// console.log("Changed comment of " + id + " to: " + comment);
|
// console.log("Changed comment of " + id + " to: " + comment);
|
||||||
//
|
//
|
||||||
// if(comment) {
|
// if(comment) {
|
||||||
// Batches.update(id, {$set: {comment}}, function(error, count) {
|
// await Batches.updateAsync(id, {$set: {comment}}, function(error, count) {
|
||||||
// if(error) throw new Meteor.Error(400, "Unexpected database error: " + error);
|
// if(error) throw new Meteor.Error(400, "Unexpected database error: " + error);
|
||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
// else {
|
// else {
|
||||||
// Batches.update(id, {$unset: {comment: ""}}, function(error, count) {
|
// await Batches.updateAsync(id, {$unset: {comment: ""}}, function(error, count) {
|
||||||
// if(error) throw new Meteor.Error(400, "Unexpected database error: " + error);
|
// if(error) throw new Meteor.Error(400, "Unexpected database error: " + error);
|
||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// else throw new Meteor.Error(403, "Not authorized.");
|
// else throw new Meteor.Error(403, "Not authorized.");
|
||||||
//},
|
//},
|
||||||
updateBatch: function(id, amount, comment) {
|
updateBatch: async function(id, amount, comment) {
|
||||||
check(id, String);
|
check(id, String);
|
||||||
check(amount, Number);
|
check(amount, Number);
|
||||||
check(comment, Match.OneOf(String, undefined));
|
check(comment, Match.OneOf(String, undefined));
|
||||||
@@ -237,13 +251,13 @@ if(Meteor.isServer) {
|
|||||||
//let weekOfYear = timestamp.getWeek().toString();
|
//let weekOfYear = timestamp.getWeek().toString();
|
||||||
|
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Batches.update(id, {$set: {comment, amount}}, function(err, id) {
|
await Batches.updateAsync(id, {$set: {comment, amount}}, function(err, id) {
|
||||||
if(err) console.log(err);
|
if(err) console.log(err);
|
||||||
}, {bypassCollection2: true});
|
}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
setBatchHasLabels: function(id, hasLabels) {
|
setBatchHasLabels: async function(id, hasLabels) {
|
||||||
//console.log(id);
|
//console.log(id);
|
||||||
//console.log(hasLabels);
|
//console.log(hasLabels);
|
||||||
//check(id, Meteor.validators.ObjectID);
|
//check(id, Meteor.validators.ObjectID);
|
||||||
@@ -251,7 +265,7 @@ if(Meteor.isServer) {
|
|||||||
check(hasLabels, Boolean);
|
check(hasLabels, Boolean);
|
||||||
|
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Batches.update(id, {$set: {hasLabels}}, function(err, id) {
|
await Batches.updateAsync(id, {$set: {hasLabels}}, function(err, id) {
|
||||||
if(err) console.log(err);
|
if(err) console.log(err);
|
||||||
}, {bypassCollection2: true});
|
}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { Mongo } from 'meteor/mongo';
|
import { Mongo } from 'meteor/mongo';
|
||||||
import { check } from 'meteor/check';
|
import { check } from 'meteor/check';
|
||||||
import {SimpleSchema} from 'meteor/aldeed:simple-schema';
|
import 'meteor/aldeed:collection2/static'
|
||||||
|
import SimpleSchema from 'meteor/aldeed:simple-schema';
|
||||||
import LabelFormats from '/imports/LabelFormats.js';
|
import LabelFormats from '/imports/LabelFormats.js';
|
||||||
|
|
||||||
|
|
||||||
@@ -36,13 +37,13 @@ if(Meteor.isServer) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
//Returns a JSON containing a denormalized list of products {product_id, measure_id, product_name, measure_name, price, }
|
//Returns a JSON containing a denormalized list of products {product_id, measure_id, product_name, measure_name, price, }
|
||||||
WebApp.connectHandlers.use("/labels/GetBarCodeData", (req, res, next) => {
|
WebApp.connectHandlers.use("/labels/GetBarCodeData", async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
let barcodes = Meteor.collections.Barcodes.find({}, {fields: {_id: 0, barcodeId: 1, productAndMeasureId: 1}});
|
let barcodes = Meteor.collections.Barcodes.find({}, {fields: {_id: 0, barcodeId: 1, productAndMeasureId: 1}});
|
||||||
let measures = Meteor.collections.Measures.find({}, {fields: {_id: 1, name: 1}, sort: {order: 1}}).fetch();
|
let measures = await Meteor.collections.Measures.find({}, {fields: {_id: 1, name: 1}, sort: {order: 1}}).fetchAsync();
|
||||||
//Note: Price data looks like this: {XZ5Z3CM49NDrJNADA /* MeasureID */: {price: 10.5, effectiveDate: ISODate("2017-01-12T13:14:18.876-08:00"), previousPrice: 9}, ...}
|
//Note: Price data looks like this: {XZ5Z3CM49NDrJNADA /* MeasureID */: {price: 10.5, effectiveDate: ISODate("2017-01-12T13:14:18.876-08:00"), previousPrice: 9}, ...}
|
||||||
//Measures is an array of MeasureIDs valid for this product.
|
//Measures is an array of MeasureIDs valid for this product.
|
||||||
let products = Meteor.collections.Products.find({}, {fields: {_id: 1, name: 1, measures: 1, prices: 1}, sort: {order: 1}}).fetch();
|
let products = await Meteor.collections.Products.find({}, {fields: {_id: 1, name: 1, measures: 1, prices: 1}, sort: {order: 1}}).fetchAsync();
|
||||||
let measuresById = {};
|
let measuresById = {};
|
||||||
let barcodesByProductAndMeasureIds = {};
|
let barcodesByProductAndMeasureIds = {};
|
||||||
let result = {};
|
let result = {};
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { LoggerMongo } from 'meteor/ostrio:loggermongo';
|
|||||||
// The logging tool is primarily for managing administrative functions such that administrators can view the app logs and issue commands that might generate administrative logging.
|
// The logging tool is primarily for managing administrative functions such that administrators can view the app logs and issue commands that might generate administrative logging.
|
||||||
|
|
||||||
Meteor.log = new Logger();
|
Meteor.log = new Logger();
|
||||||
Logs = new Mongo.Collection('Logs');
|
let Logs = new Mongo.Collection('Logs');
|
||||||
|
|
||||||
let logMongo = new LoggerMongo(Meteor.log, {
|
let logMongo = new LoggerMongo(Meteor.log, {
|
||||||
collection: Logs
|
collection: Logs
|
||||||
@@ -23,8 +23,8 @@ if(Meteor.isServer) {
|
|||||||
return Logs.find({}, {limit: 10000});
|
return Logs.find({}, {limit: 10000});
|
||||||
});
|
});
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
clearLogs: function() {
|
clearLogs: async function() {
|
||||||
return Logs.remove({}, function(err) {
|
return await Logs.removeAsync({}, function(err) {
|
||||||
if(err) Meteor.log.error(err);
|
if(err) Meteor.log.error(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,26 @@
|
|||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { Mongo } from 'meteor/mongo';
|
import { Mongo } from 'meteor/mongo';
|
||||||
import { check } from 'meteor/check';
|
import { check } from 'meteor/check';
|
||||||
import {SimpleSchema} from 'meteor/aldeed:simple-schema';
|
import 'meteor/aldeed:collection2/static'
|
||||||
|
import SimpleSchema from 'meteor/aldeed:simple-schema';
|
||||||
|
|
||||||
let Measures = new Mongo.Collection('Measures');
|
let Measures = new Mongo.Collection('Measures');
|
||||||
|
|
||||||
|
if(Meteor.isServer) {
|
||||||
|
//Set MongoDB indexes (or remove them) here.
|
||||||
|
try {
|
||||||
|
Measures.rawCollection().createIndex({name: -1}, {unique: true})
|
||||||
|
} catch(e) {console.log("Caught exception while setting indexes in MongoDB"); console.error(e)}
|
||||||
|
}
|
||||||
|
|
||||||
Measures.attachSchema(new SimpleSchema({
|
Measures.attachSchema(new SimpleSchema({
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
label: "Name",
|
label: "Name",
|
||||||
optional: false,
|
optional: false,
|
||||||
trim: true,
|
trim: true,
|
||||||
index: 1,
|
// index: 1, Requires aldeed:schema-index which requires an older version fo aldeed:collection2 (3.5.0 vs 4.0.2) This can be achieved by adding indexes to MongoDB directly.
|
||||||
unique: true
|
//unique: true
|
||||||
},
|
},
|
||||||
postfix: {
|
postfix: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -63,39 +72,39 @@ if(Meteor.isServer) Meteor.publish('measures', function() {
|
|||||||
|
|
||||||
if(Meteor.isServer) {
|
if(Meteor.isServer) {
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
createMeasure: function(name, postfix, order) {
|
createMeasure: async function(name, postfix, order) {
|
||||||
check(name, String);
|
check(name, String);
|
||||||
check(postfix, String);
|
check(postfix, String);
|
||||||
check(order, Number);
|
check(order, Number);
|
||||||
|
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Measures.insert({name, postfix, order, createdAt: new Date()});
|
await Measures.insertAsync({name, postfix, order, createdAt: new Date()});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
deactivateMeasure: function(id) {
|
deactivateMeasure: async function(id) {
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
//Measures.remove(id);
|
//Measures.remove(id);
|
||||||
Measures.update(id, {$set: {deactivated: true}}, {bypassCollection2: true});
|
await Measures.updateAsync(id, {$set: {deactivated: true}}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
reactivateMeasure: function(id) {
|
reactivateMeasure: async function(id) {
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Measures.update(id, {$set: {deactivated: false}}, {bypassCollection2: true});
|
await Measures.updateAsync(id, {$set: {deactivated: false}}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
hideMeasure: function(id) { //One step past deactivated - will only show in the measures list if hidden measures are enabled.
|
hideMeasure: async function(id) { //One step past deactivated - will only show in the measures list if hidden measures are enabled.
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
//Measures.remove(id);
|
//Measures.remove(id);
|
||||||
Measures.update(id, {$set: {hidden: true}}, {bypassCollection2: true});
|
await Measures.updateAsync(id, {$set: {hidden: true}}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
showMeasure: function(id) { //Returns the measure to being simply deactivated. Will again show in lists.
|
showMeasure: async function(id) { //Returns the measure to being simply deactivated. Will again show in lists.
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Measures.update(id, {$set: {hidden: false}}, {bypassCollection2: true});
|
await Measures.updateAsync(id, {$set: {hidden: false}}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
@@ -106,14 +115,14 @@ if(Meteor.isServer) {
|
|||||||
// }
|
// }
|
||||||
// else throw new Meteor.Error(403, "Not authorized.");
|
// else throw new Meteor.Error(403, "Not authorized.");
|
||||||
//},
|
//},
|
||||||
updateMeasure: function(id, name, postfix, order) {
|
updateMeasure: async function(id, name, postfix, order) {
|
||||||
check(id, String);
|
check(id, String);
|
||||||
check(name, String);
|
check(name, String);
|
||||||
check(postfix, String);
|
check(postfix, String);
|
||||||
check(order, Number);
|
check(order, Number);
|
||||||
|
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Measures.update(id, {$set: {name, postfix, order, updatedAt: new Date()}});
|
await Measures.updateAsync(id, {$set: {name, postfix, order, updatedAt: new Date()}});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { Mongo } from 'meteor/mongo';
|
import { Mongo } from 'meteor/mongo';
|
||||||
import { check } from 'meteor/check';
|
import { check } from 'meteor/check';
|
||||||
import {SimpleSchema} from 'meteor/aldeed:simple-schema';
|
import 'meteor/aldeed:collection2/static'
|
||||||
|
import SimpleSchema from 'meteor/aldeed:simple-schema';
|
||||||
|
import Measures from "./Measure";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notes:
|
* Notes:
|
||||||
@@ -16,21 +18,31 @@ import {SimpleSchema} from 'meteor/aldeed:simple-schema';
|
|||||||
|
|
||||||
let Products = new Mongo.Collection('Products');
|
let Products = new Mongo.Collection('Products');
|
||||||
|
|
||||||
|
if(Meteor.isServer) {
|
||||||
|
//Set MongoDB indexes (or remove them) here.
|
||||||
|
try {
|
||||||
|
Products.rawCollection().createIndex({name: -1}, {unique: true})
|
||||||
|
} catch(e) {console.log("Caught exception while setting indexes in MongoDB"); console.error(e)}
|
||||||
|
}
|
||||||
|
|
||||||
const ProductsSchema = new SimpleSchema({
|
const ProductsSchema = new SimpleSchema({
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
label: "Name",
|
label: "Name",
|
||||||
optional: false,
|
optional: false,
|
||||||
trim: true,
|
trim: true,
|
||||||
index: 1,
|
//index: 1,
|
||||||
unique: true
|
//unique: true
|
||||||
},
|
},
|
||||||
tags: { //An array of ProductTag names. Note that we are not using the ProductTag ID's because I want a looser connection (if a ProductTag is deleted, it isn't a big deal if it isn't maintained in the Product records).
|
tags: { //An array of ProductTag names. Note that we are not using the ProductTag ID's because I want a looser connection (if a ProductTag is deleted, it isn't a big deal if it isn't maintained in the Product records).
|
||||||
type: [String],
|
type: Array, //[String],
|
||||||
label: "Tags",
|
label: "Tags",
|
||||||
optional: false,
|
optional: false,
|
||||||
defaultValue: []
|
defaultValue: []
|
||||||
},
|
},
|
||||||
|
'tags.$': {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
measures: { //A JSON array of Measure ID's.
|
measures: { //A JSON array of Measure ID's.
|
||||||
type: Array,
|
type: Array,
|
||||||
label: "Measures",
|
label: "Measures",
|
||||||
@@ -181,7 +193,7 @@ if(Meteor.isServer) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
createProduct: function(name, tags, aliases, measures) {
|
createProduct: async function(name, tags, aliases, measures) {
|
||||||
check(name, String);
|
check(name, String);
|
||||||
if(tags) check(tags, [String]);
|
if(tags) check(tags, [String]);
|
||||||
if(aliases) check(aliases, [String]);
|
if(aliases) check(aliases, [String]);
|
||||||
@@ -192,48 +204,48 @@ if(Meteor.isServer) {
|
|||||||
//let cursor = Products.find({}, {barCodeId: 1}).sort({barCodeId: -1}).limit(1); //Since currently products are never removed, we shouldn't need to detect sequence gaps and fill them in (odds are we will never use more than 10k numbers anyway).
|
//let cursor = Products.find({}, {barCodeId: 1}).sort({barCodeId: -1}).limit(1); //Since currently products are never removed, we shouldn't need to detect sequence gaps and fill them in (odds are we will never use more than 10k numbers anyway).
|
||||||
//let barCodeId = cursor.hasNext() ? cursor.next().barCodeId : 1;
|
//let barCodeId = cursor.hasNext() ? cursor.next().barCodeId : 1;
|
||||||
//
|
//
|
||||||
Products.insert({name, tags, aliases, measures, createdAt: new Date()}, {bypassCollection2: true}, function(err, id) {
|
await Products.insertAsync({name, tags, aliases, measures, createdAt: new Date()}, {bypassCollection2: true}, function(err, id) {
|
||||||
if(err) console.log(err);
|
if(err) console.log(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
convertProduct: function(productId, alternateProductId) {
|
convertProduct: async function(productId, alternateProductId) {
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
check(productId, String);
|
check(productId, String);
|
||||||
check(alternateProductId, String);
|
check(alternateProductId, String);
|
||||||
// Replace all sale references to the given ID with the provided alternate product ID.
|
// Replace all sale references to the given ID with the provided alternate product ID.
|
||||||
Meteor.collections.Sales.update({productId: productId}, {$set: {productId: alternateProductId}}, {multi: true});
|
await Meteor.collections.Sales.updateAsync({productId: productId}, {$set: {productId: alternateProductId}}, {multi: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
deactivateProduct: function(id) {
|
deactivateProduct: async function(id) {
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
//Products.remove(id);
|
//Products.remove(id);
|
||||||
Products.update(id, {$set: {deactivated: true}}, {bypassCollection2: true});
|
await Products.updateAsync(id, {$set: {deactivated: true}}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
reactivateProduct: function(id) {
|
reactivateProduct: async function(id) {
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Products.update(id, {$set: {deactivated: false}}, {bypassCollection2: true});
|
await Products.updateAsync(id, {$set: {deactivated: false}}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
hideProduct: function(id) { //One step past deactivated - will only show in the products list if hidden products are enabled.
|
hideProduct: async function(id) { //One step past deactivated - will only show in the products list if hidden products are enabled.
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
//Products.remove(id);
|
//Products.remove(id);
|
||||||
Products.update(id, {$set: {hidden: true}}, {bypassCollection2: true});
|
await Products.updateAsync(id, {$set: {hidden: true}}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
showProduct: function(id) { //Returns the product to being simply deactivated. Will again show in lists.
|
showProduct: async function(id) { //Returns the product to being simply deactivated. Will again show in lists.
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Products.update(id, {$set: {hidden: false}}, {bypassCollection2: true});
|
await Products.updateAsync(id, {$set: {hidden: false}}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
updateProduct: function(id, name, tags, aliases, measures) {
|
updateProduct: async function(id, name, tags, aliases, measures) {
|
||||||
check(id, String);
|
check(id, String);
|
||||||
check(name, String);
|
check(name, String);
|
||||||
if(tags) check(tags, [String]);
|
if(tags) check(tags, [String]);
|
||||||
@@ -241,22 +253,22 @@ if(Meteor.isServer) {
|
|||||||
if(measures) check(measures, [String]);
|
if(measures) check(measures, [String]);
|
||||||
|
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Products.update(id, {$set: {name: name, tags: tags, aliases: aliases, measures: measures, updatedAt: new Date()}}, {bypassCollection2: true});
|
await Products.updateAsync(id, {$set: {name: name, tags: tags, aliases: aliases, measures: measures, updatedAt: new Date()}}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
clearProductPrice: function(productIds, measureId) {
|
clearProductPrice: async function(productIds, measureId) {
|
||||||
check(productIds, [String]);
|
check(productIds, [String]);
|
||||||
check(measureId, String);
|
check(measureId, String);
|
||||||
|
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
let attr = "prices." + measureId;
|
let attr = "prices." + measureId;
|
||||||
|
|
||||||
Products.update({_id: {$in: productIds}}, {$unset: {[attr]: true}}, {validate: false, bypassCollection2: true});
|
await Products.updateAsync({_id: {$in: productIds}}, {$unset: {[attr]: true}}, {validate: false, bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
setProductPrice: function(productIds, measureId, price, setPrevious, effectiveDate) {
|
setProductPrice: async function(productIds, measureId, price, setPrevious, effectiveDate) {
|
||||||
check(productIds, [String]);
|
check(productIds, [String]);
|
||||||
check(measureId, String);
|
check(measureId, String);
|
||||||
check(price, Number);
|
check(price, Number);
|
||||||
@@ -283,14 +295,14 @@ if(Meteor.isServer) {
|
|||||||
measurePriceData.price = price;
|
measurePriceData.price = price;
|
||||||
|
|
||||||
if(ProductsSchema.newContext().isValid()) {
|
if(ProductsSchema.newContext().isValid()) {
|
||||||
Products.update(product._id, {$set: {prices: prices, updateAt: new Date()}}, {validate: false, bypassCollection2: true});
|
await Products.updateAsync(product._id, {$set: {prices: prices, updateAt: new Date()}}, {validate: false, bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else console.log("Invalid schema for product");
|
else console.log("Invalid schema for product");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
tagProducts: function(productIds, tagId) {
|
tagProducts: async function(productIds, tagId) {
|
||||||
//Tags the products if any products don't have the tag, otherwise removes the tag from all products.
|
//Tags the products if any products don't have the tag, otherwise removes the tag from all products.
|
||||||
check(productIds, [String]);
|
check(productIds, [String]);
|
||||||
check(tagId, String);
|
check(tagId, String);
|
||||||
@@ -299,10 +311,10 @@ if(Meteor.isServer) {
|
|||||||
let productsWithTag = Products.find({_id: {$in: productIds}, tags: {$all: [tagId]}}).count();
|
let productsWithTag = Products.find({_id: {$in: productIds}, tags: {$all: [tagId]}}).count();
|
||||||
|
|
||||||
if(productsWithTag == productIds.length) {
|
if(productsWithTag == productIds.length) {
|
||||||
Products.update({_id: {$in: productIds}}, {$pullAll: {tags: [tagId]}}, {bypassCollection2: true, multi: true});
|
await Products.updateAsync({_id: {$in: productIds}}, {$pullAll: {tags: [tagId]}}, {bypassCollection2: true, multi: true});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Products.update({_id: {$in: productIds}}, {$addToSet: {tags: tagId}}, {bypassCollection2: true, multi: true});
|
await Products.updateAsync({_id: {$in: productIds}}, {$addToSet: {tags: tagId}}, {bypassCollection2: true, multi: true});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { Mongo } from 'meteor/mongo';
|
import { Mongo } from 'meteor/mongo';
|
||||||
import { check } from 'meteor/check'
|
import { check } from 'meteor/check'
|
||||||
import {SimpleSchema} from 'meteor/aldeed:simple-schema';
|
import 'meteor/aldeed:collection2/static'
|
||||||
|
import SimpleSchema from 'meteor/aldeed:simple-schema';
|
||||||
|
import Measures from "./Measure";
|
||||||
|
|
||||||
ProductTags = new Mongo.Collection('ProductTags', {
|
let ProductTags = new Mongo.Collection('ProductTags', {
|
||||||
schema: new SimpleSchema({
|
schema: new SimpleSchema({
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
label: "Name",
|
label: "Name",
|
||||||
optional: false,
|
optional: false,
|
||||||
trim: true,
|
trim: true,
|
||||||
index: 1,
|
//index: 1,
|
||||||
unique: true
|
//unique: true
|
||||||
},
|
},
|
||||||
createdAt: {
|
createdAt: {
|
||||||
type: Date,
|
type: Date,
|
||||||
@@ -26,6 +28,13 @@ ProductTags = new Mongo.Collection('ProductTags', {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(Meteor.isServer) {
|
||||||
|
//Set MongoDB indexes (or remove them) here.
|
||||||
|
try {
|
||||||
|
ProductTags.rawCollection().createIndex({name: -1}, {unique: true})
|
||||||
|
} catch(e) {console.log("Caught exception while setting indexes in MongoDB"); console.error(e)}
|
||||||
|
}
|
||||||
|
|
||||||
//Allows the client to do DB interaction without calling server side methods, while still retaining control over whether the user can make changes.
|
//Allows the client to do DB interaction without calling server side methods, while still retaining control over whether the user can make changes.
|
||||||
ProductTags.allow({
|
ProductTags.allow({
|
||||||
insert: function() {return false;},
|
insert: function() {return false;},
|
||||||
@@ -39,23 +48,23 @@ if(Meteor.isServer) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
insertProductTag: function(productTag) {
|
insertProductTag: async function(productTag) {
|
||||||
check(productTag, String);
|
check(productTag, String);
|
||||||
productTag = {name: productTag, createdAt: new Date()};
|
productTag = {name: productTag, createdAt: new Date()};
|
||||||
|
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
ProductTags.insert(productTag, function(err, id) {
|
await ProductTags.insertAsync(productTag, function(err, id) {
|
||||||
if(err) console.log(err);
|
if(err) console.log(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
deleteProductTag: function(id) {
|
deleteProductTag: async function(id) {
|
||||||
check(id, String);
|
check(id, String);
|
||||||
|
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
//Remove all references to the tag in the products.
|
//Remove all references to the tag in the products.
|
||||||
Meteor.collections.Products.update({tags: {$all: [id]}}, {$pullAll: {tags: [id]}}, {bypassCollection2: true, multi: true});
|
await Meteor.collections.Products.updateAsync({tags: {$all: [id]}}, {$pullAll: {tags: [id]}}, {bypassCollection2: true, multi: true});
|
||||||
// let products = Meteor.collections.Products.find({tags: {$all: [id]}}, {_id: 1, tags: 1}).fetch();
|
// let products = Meteor.collections.Products.find({tags: {$all: [id]}}, {_id: 1, tags: 1}).fetch();
|
||||||
//
|
//
|
||||||
// //Try to remove all tags from products. Log/Ignore any errors.
|
// //Try to remove all tags from products. Log/Ignore any errors.
|
||||||
@@ -73,17 +82,17 @@ if(Meteor.isServer) {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
ProductTags.remove(id);
|
await ProductTags.removeAsync(id);
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
updateProductTag: function(tag) {
|
updateProductTag: async function(tag) {
|
||||||
check(tag, {
|
check(tag, {
|
||||||
_id: String,
|
_id: String,
|
||||||
name: String
|
name: String
|
||||||
});
|
});
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
ProductTags.update(tag._id, {$set: {name: tag.name, updatedAt: new Date()}});
|
await ProductTags.updateAsync(tag._id, {$set: {name: tag.name, updatedAt: new Date()}});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ if(Meteor.isServer) {
|
|||||||
}
|
}
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
result.toArray().then(function(result) {
|
result.toArray().then(async function(result) {
|
||||||
let totalByYear = {};
|
let totalByYear = {};
|
||||||
|
|
||||||
//Create a map of maps: year -> measure id -> sales count.
|
//Create a map of maps: year -> measure id -> sales count.
|
||||||
@@ -80,7 +80,7 @@ if(Meteor.isServer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Create a list of ordered measures. We could use a map, but then getting the ordering correct would be difficult.
|
//Create a list of ordered measures. We could use a map, but then getting the ordering correct would be difficult.
|
||||||
let measures = Meteor.collections.Measures.find({}, {fields: {_id: 1, name: 1}, sort: {order: 1}}).fetch();
|
let measures = await Meteor.collections.Measures.find({}, {fields: {_id: 1, name: 1}, sort: {order: 1}}).fetchAsync();
|
||||||
|
|
||||||
//Collect the years in ascending oder.
|
//Collect the years in ascending oder.
|
||||||
let years = Object.keys(totalByYear).sort(function(a, b) {return parseInt(a) - parseInt(b);});
|
let years = Object.keys(totalByYear).sort(function(a, b) {return parseInt(a) - parseInt(b);});
|
||||||
@@ -130,7 +130,7 @@ if(Meteor.isServer) {
|
|||||||
}
|
}
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
result.toArray().then(function(result) {
|
result.toArray().then(async function(result) {
|
||||||
let productSalesTotalsMapByYear = {};
|
let productSalesTotalsMapByYear = {};
|
||||||
|
|
||||||
//Create a map of maps: year -> product id -> sales totals.
|
//Create a map of maps: year -> product id -> sales totals.
|
||||||
@@ -145,7 +145,7 @@ if(Meteor.isServer) {
|
|||||||
|
|
||||||
//Now create a mapping between the tag id's and tag names for later use.
|
//Now create a mapping between the tag id's and tag names for later use.
|
||||||
let tagIdToTagNameMap = {};
|
let tagIdToTagNameMap = {};
|
||||||
let tags = Meteor.collections.ProductTags.find({}, {fields: {_id: 1, name: 1}}).fetch();
|
let tags = await Meteor.collections.ProductTags.find({}, {fields: {_id: 1, name: 1}}).fetchAsync();
|
||||||
|
|
||||||
for(let tag of tags) {
|
for(let tag of tags) {
|
||||||
tagIdToTagNameMap[tag._id] = tag.name;
|
tagIdToTagNameMap[tag._id] = tag.name;
|
||||||
@@ -153,7 +153,7 @@ if(Meteor.isServer) {
|
|||||||
|
|
||||||
//Now create a map between tag names -> [product ids] so that we can build a table below.
|
//Now create a map between tag names -> [product ids] so that we can build a table below.
|
||||||
let tagProductIdsMap = {};
|
let tagProductIdsMap = {};
|
||||||
let products = Meteor.collections.Products.find({}, {fields: {_id: 1, tags: 1}}).fetch();
|
let products = await Meteor.collections.Products.find({}, {fields: {_id: 1, tags: 1}}).fetchAsync();
|
||||||
|
|
||||||
for(let product of products) {
|
for(let product of products) {
|
||||||
for(let tagId of product.tags) {
|
for(let tagId of product.tags) {
|
||||||
@@ -234,7 +234,7 @@ if(Meteor.isServer) {
|
|||||||
}
|
}
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
result.toArray().then(function(result) {
|
result.toArray().then(async function(result) {
|
||||||
let totalByYear = {};
|
let totalByYear = {};
|
||||||
|
|
||||||
//Create a map of maps: year -> product id -> measure id -> sales count.
|
//Create a map of maps: year -> product id -> measure id -> sales count.
|
||||||
@@ -252,10 +252,10 @@ if(Meteor.isServer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Create a list of ordered measures. We could use a map, but then getting the ordering correct would be difficult.
|
//Create a list of ordered measures. We could use a map, but then getting the ordering correct would be difficult.
|
||||||
let measures = Meteor.collections.Measures.find({}, {fields: {_id: 1, name: 1}, sort: {order: 1}}).fetch();
|
let measures = await Meteor.collections.Measures.find({}, {fields: {_id: 1, name: 1}, sort: {order: 1}}).fetcAsync();
|
||||||
|
|
||||||
//Now create a mapping between the product id's and product names for later use.
|
//Now create a mapping between the product id's and product names for later use.
|
||||||
let products = Meteor.collections.Products.find({}, {fields: {_id: 1, name: 1}, sort: {name: 1}}).fetch();
|
let products = await Meteor.collections.Products.find({}, {fields: {_id: 1, name: 1}, sort: {name: 1}}).fetcAsync();
|
||||||
|
|
||||||
//Collect the years in ascending oder.
|
//Collect the years in ascending oder.
|
||||||
let years = Object.keys(totalByYear).sort(function(a, b) {return parseInt(a) - parseInt(b);});
|
let years = Object.keys(totalByYear).sort(function(a, b) {return parseInt(a) - parseInt(b);});
|
||||||
@@ -367,7 +367,7 @@ if(Meteor.isServer) {
|
|||||||
}
|
}
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
result.toArray().then(function(result) {
|
result.toArray().then(async function(result) {
|
||||||
let totalByYear = {};
|
let totalByYear = {};
|
||||||
|
|
||||||
//Create a map of maps: year -> product id -> measure id -> sales count.
|
//Create a map of maps: year -> product id -> measure id -> sales count.
|
||||||
@@ -385,11 +385,11 @@ if(Meteor.isServer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Create a list of ordered measures. We could use a map, but then getting the ordering correct would be difficult.
|
//Create a list of ordered measures. We could use a map, but then getting the ordering correct would be difficult.
|
||||||
let measures = Meteor.collections.Measures.find({}, {fields: {_id: 1, name: 1}, sort: {order: 1}}).fetch();
|
let measures = await Meteor.collections.Measures.find({}, {fields: {_id: 1, name: 1}, sort: {order: 1}}).fetcAsync();
|
||||||
|
|
||||||
//Now create a mapping between the tag id's and tag names for later use.
|
//Now create a mapping between the tag id's and tag names for later use.
|
||||||
let tagIdToTagNameMap = {};
|
let tagIdToTagNameMap = {};
|
||||||
let tags = Meteor.collections.ProductTags.find({}, {fields: {_id: 1, name: 1}}).fetch();
|
let tags = await Meteor.collections.ProductTags.find({}, {fields: {_id: 1, name: 1}}).fetcAsync();
|
||||||
|
|
||||||
for(let tag of tags) {
|
for(let tag of tags) {
|
||||||
tagIdToTagNameMap[tag._id] = tag.name;
|
tagIdToTagNameMap[tag._id] = tag.name;
|
||||||
@@ -397,7 +397,7 @@ if(Meteor.isServer) {
|
|||||||
|
|
||||||
//Now create a map between tag names -> [product ids] so that we can build a table below.
|
//Now create a map between tag names -> [product ids] so that we can build a table below.
|
||||||
let tagProductIdsMap = {};
|
let tagProductIdsMap = {};
|
||||||
let products = Meteor.collections.Products.find({}, {fields: {_id: 1, tags: 1}}).fetch();
|
let products = await Meteor.collections.Products.find({}, {fields: {_id: 1, tags: 1}}).fetcAsync();
|
||||||
|
|
||||||
for(let product of products) {
|
for(let product of products) {
|
||||||
for(let tagId of product.tags) {
|
for(let tagId of product.tags) {
|
||||||
|
|||||||
@@ -1,11 +1,21 @@
|
|||||||
|
import { Roles } from 'meteor/alanning:roles'
|
||||||
|
|
||||||
if(Meteor.isServer) {
|
if(Meteor.isServer) {
|
||||||
Meteor.publish('roles', function() {
|
Meteor.publish('roles', function() {
|
||||||
|
//console.log("Checking if user is in the manage role: " + Meteor.userId() + " === " + Roles.userIsInRole(this.userId, ['manage']))
|
||||||
if(Roles.userIsInRole(this.userId, ['manage'])) {
|
if(Roles.userIsInRole(this.userId, ['manage'])) {
|
||||||
return Meteor.roles.find({}, {fields: {name: 1}});
|
//Meteor.roles.find({}, {fields: {name: 1}}).fetchAsync().then(roles => {console.log(roles)})
|
||||||
|
//return Meteor.roles.find({}, {fields: {name: 1}});
|
||||||
|
return Meteor.roles.find({});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized to view roles.");
|
else throw new Meteor.Error(403, "Not authorized to view roles.");
|
||||||
});
|
});
|
||||||
|
Meteor.publish("roleAssignments", function() {
|
||||||
|
if(Roles.userIsInRole(this.userId, ['manage'])) {
|
||||||
|
return Meteor.roleAssignment.find({});
|
||||||
|
}
|
||||||
|
else throw new Meteor.Error(403, "Not authorized to view roles.");
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let ROLE_MANAGE = "manage";
|
let ROLE_MANAGE = "manage";
|
||||||
@@ -13,5 +23,12 @@ let ROLE_UPDATE = "update";
|
|||||||
|
|
||||||
Meteor.UserRoles = {ROLE_MANAGE, ROLE_UPDATE};
|
Meteor.UserRoles = {ROLE_MANAGE, ROLE_UPDATE};
|
||||||
|
|
||||||
|
// This is the collection that maps users to roles (v3 of alanning:roles).
|
||||||
|
//Meteor.roleAssignment
|
||||||
|
// This is where you will find the roles defained in MongoDB:
|
||||||
|
//Meteor.roles
|
||||||
|
|
||||||
|
Roles.createRoleAsync(ROLE_MANAGE)
|
||||||
|
Roles.createRoleAsync(ROLE_UPDATE)
|
||||||
|
|
||||||
export default Meteor.roles;
|
export default Meteor.roles;
|
||||||
@@ -1,21 +1,34 @@
|
|||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { Mongo } from 'meteor/mongo';
|
import { Mongo } from 'meteor/mongo';
|
||||||
import { check } from 'meteor/check';
|
import { check } from 'meteor/check';
|
||||||
import {SimpleSchema} from 'meteor/aldeed:simple-schema';
|
import 'meteor/aldeed:collection2/static'
|
||||||
|
import SimpleSchema from 'meteor/aldeed:simple-schema';
|
||||||
import Batches from "./Batch";
|
import Batches from "./Batch";
|
||||||
|
import Measures from "./Measure";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notes:
|
* Notes:
|
||||||
* The Sale object has a date field which stores the date as a number in the format YYYYMMDD. Converting this number into a local date is done with moment(sale.date.toString(), "YYYYMMDD").toDate(), and converting it to a number from a date can be accomplished with ~~(moment(date).format("YYYYMMDD")), where the ~~ is a bitwise not and converts a string to a number quickly and reliably.
|
* The Sale object has a date field which stores the date as a number in the format YYYYMMDD. Converting this number into a local date is done with moment(sale.date.toString(), "YYYYMMDD").toDate(), and converting it to a number from a date can be accomplished with ~~(moment(date).format("YYYYMMDD")), where the ~~ is a bitwise not and converts a string to a number quickly and reliably.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Sales = new Mongo.Collection('Sales');
|
let Sales = new Mongo.Collection('Sales');
|
||||||
|
|
||||||
|
if(Meteor.isServer) {
|
||||||
|
//Set MongoDB indexes (or remove them) here.
|
||||||
|
try {
|
||||||
|
Sales.rawCollection().createIndex({date: -1}, {unique: false})
|
||||||
|
Sales.rawCollection().createIndex({productId: -1}, {unique: false})
|
||||||
|
Sales.rawCollection().createIndex({measureId: -1}, {unique: false})
|
||||||
|
Sales.rawCollection().createIndex({venueId: -1}, {unique: false})
|
||||||
|
} catch(e) {console.log("Caught exception while setting indexes in MongoDB"); console.error(e)}
|
||||||
|
}
|
||||||
|
|
||||||
let SalesSchema = new SimpleSchema({
|
let SalesSchema = new SimpleSchema({
|
||||||
date: {
|
date: {
|
||||||
type: Number, // A number in the format of YYYYMMDD to allow for searching using greater and less than, and to prevent timezones from messing everything up.
|
type: Number, // A number in the format of YYYYMMDD to allow for searching using greater and less than, and to prevent timezones from messing everything up.
|
||||||
label: "Date",
|
label: "Date",
|
||||||
optional: false,
|
optional: false,
|
||||||
index: 1
|
//index: 1
|
||||||
},
|
},
|
||||||
timestamp: {
|
timestamp: {
|
||||||
type: Date,
|
type: Date,
|
||||||
@@ -31,7 +44,7 @@ let SalesSchema = new SimpleSchema({
|
|||||||
type: Number,
|
type: Number,
|
||||||
label: "Amount",
|
label: "Amount",
|
||||||
optional: false,
|
optional: false,
|
||||||
decimal: true
|
//decimal: true
|
||||||
},
|
},
|
||||||
price: {
|
price: {
|
||||||
type: Number,
|
type: Number,
|
||||||
@@ -39,28 +52,29 @@ let SalesSchema = new SimpleSchema({
|
|||||||
optional: false,
|
optional: false,
|
||||||
min: 0,
|
min: 0,
|
||||||
exclusiveMin: true,
|
exclusiveMin: true,
|
||||||
decimal: true
|
//decimal: true
|
||||||
},
|
},
|
||||||
measureId: {
|
measureId: {
|
||||||
type: String,
|
type: String,
|
||||||
label: "Measure Id",
|
label: "Measure Id",
|
||||||
trim: false,
|
trim: false,
|
||||||
regEx: SimpleSchema.RegEx.Id,
|
regEx: SimpleSchema.RegEx.Id,
|
||||||
index: 1
|
//index: 1
|
||||||
},
|
},
|
||||||
productId: {
|
productId: {
|
||||||
type: String,
|
type: String,
|
||||||
label: "Product Id",
|
label: "Product Id",
|
||||||
trim: false,
|
trim: false,
|
||||||
regEx: SimpleSchema.RegEx.Id,
|
regEx: SimpleSchema.RegEx.Id,
|
||||||
index: 1
|
//index: 1
|
||||||
},
|
},
|
||||||
venueId: {
|
venueId: {
|
||||||
type: String,
|
type: String,
|
||||||
label: "Vendor Id",
|
label: "Vendor Id",
|
||||||
trim: false,
|
trim: false,
|
||||||
regEx: SimpleSchema.RegEx.Id,
|
regEx: SimpleSchema.RegEx.Id,
|
||||||
index: 1
|
//index: 1
|
||||||
|
|
||||||
// autoform: {
|
// autoform: {
|
||||||
// type: 'relation',
|
// type: 'relation',
|
||||||
// settings: {
|
// settings: {
|
||||||
@@ -280,11 +294,11 @@ if(Meteor.isServer) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
getSalesCount: function(query) {
|
getSalesCount: async function(query) {
|
||||||
//TODO: Validate the query?
|
//TODO: Validate the query?
|
||||||
return Sales.find(query).count();
|
return await Sales.countDocuments(query);
|
||||||
},
|
},
|
||||||
insertSale: function(sale) {
|
insertSale: async function(sale) {
|
||||||
check(sale, {
|
check(sale, {
|
||||||
date: Number, // TODO: Check that the format is YYYYMMDD
|
date: Number, // TODO: Check that the format is YYYYMMDD
|
||||||
amount: Match.Where(function(x) {
|
amount: Match.Where(function(x) {
|
||||||
@@ -308,21 +322,21 @@ if(Meteor.isServer) {
|
|||||||
sale.weekOfYear = sale.timestamp.getWeek().toString();
|
sale.weekOfYear = sale.timestamp.getWeek().toString();
|
||||||
|
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Sales.insert(sale, function(err, id) {
|
await Sales.insertAsync(sale, function(err, id) {
|
||||||
if(err) console.log(err);
|
if(err) console.log(err);
|
||||||
}, {bypassCollection2: true});
|
}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
deleteSale: function(id) {
|
deleteSale: async function(id) {
|
||||||
check(id, String);
|
check(id, String);
|
||||||
|
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Sales.remove(id);
|
await Sales.removeAsync(id);
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
editSaleComment: function(id, comment) {
|
editSaleComment: async function(id, comment) {
|
||||||
check(id, String);
|
check(id, String);
|
||||||
check(comment, String);
|
check(comment, String);
|
||||||
//Trim and convert empty comment to undefined.
|
//Trim and convert empty comment to undefined.
|
||||||
@@ -333,19 +347,19 @@ if(Meteor.isServer) {
|
|||||||
console.log("Changed comment of " + id + " to: " + comment);
|
console.log("Changed comment of " + id + " to: " + comment);
|
||||||
|
|
||||||
if(comment) {
|
if(comment) {
|
||||||
Sales.update(id, {$set: {comment}}, function(error, count) {
|
await Sales.updateAsync(id, {$set: {comment}}, function(error, count) {
|
||||||
if(error) throw new Meteor.Error(400, "Unexpected database error: " + error);
|
if(error) throw new Meteor.Error(400, "Unexpected database error: " + error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Sales.update(id, {$unset: {comment: ""}}, function(error, count) {
|
await Sales.updateAsync(id, {$unset: {comment: ""}}, function(error, count) {
|
||||||
if(error) throw new Meteor.Error(400, "Unexpected database error: " + error);
|
if(error) throw new Meteor.Error(400, "Unexpected database error: " + error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
updateSale: function(id, date, venueId, price, amount) {
|
updateSale: async function(id, date, venueId, price, amount) {
|
||||||
check(id, String);
|
check(id, String);
|
||||||
check(date, Number); // TODO: Check that the format is YYYYMMDD
|
check(date, Number); // TODO: Check that the format is YYYYMMDD
|
||||||
check(venueId, String);
|
check(venueId, String);
|
||||||
@@ -357,45 +371,45 @@ if(Meteor.isServer) {
|
|||||||
let weekOfYear = timestamp.getWeek().toString();
|
let weekOfYear = timestamp.getWeek().toString();
|
||||||
|
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Sales.update(id, {$set: {date, venueId, price, amount, timestamp, weekOfYear}}, function(err, id) {
|
await Sales.updateAsync(id, {$set: {date, venueId, price, amount, timestamp, weekOfYear}}, function(err, id) {
|
||||||
if(err) console.log(err);
|
if(err) console.log(err);
|
||||||
}, {bypassCollection2: true});
|
}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
countSales: function() {
|
countSales: async function() {
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
return Sales.find({}).count();
|
return await Sales.countDocuments({});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
removeDuplicateSales: function(id, justOne) { // Expects the id of the sale that has duplicates and an optional boolean flag (justOne) indicating whether just one duplicate should be removed, or all of them (default).
|
removeDuplicateSales: async function(id, justOne) { // Expects the id of the sale that has duplicates and an optional boolean flag (justOne) indicating whether just one duplicate should be removed, or all of them (default).
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
// Remove either one or all of the duplicates of the Sale with the given ID.
|
// Remove either one or all of the duplicates of the Sale with the given ID.
|
||||||
if(justOne) {
|
if(justOne) {
|
||||||
let sale = Sales.findOne({isDuplicateOf: id});
|
let sale = await Sales.findOneAsync({isDuplicateOf: id});
|
||||||
|
|
||||||
if(sale) {
|
if(sale) {
|
||||||
Sales.remove({_id: sale._id});
|
await Sales.removeAsync({_id: sale._id});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Sales.remove({isDuplicateOf: id});
|
await Sales.removeAsync({isDuplicateOf: id});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ignoreDuplicateSales: function(id) { // Expects the id of the sale that has duplicates. Will mark this sale and all duplicates to be ignored in future duplicate checks.
|
ignoreDuplicateSales: async function(id) { // Expects the id of the sale that has duplicates. Will mark this sale and all duplicates to be ignored in future duplicate checks.
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
// Mark to ignore duplicates for this Sale (id) and all its duplicates, and clear any duplicate counts and references.
|
// Mark to ignore duplicates for this Sale (id) and all its duplicates, and clear any duplicate counts and references.
|
||||||
//Sales.update({$or: [{_id: id}, {isDuplicateOf: id}]}, {$set: {ignoreDuplicates: true}, $unset: {isDuplicateOf: "", duplicateCount: ""}});
|
//Sales.update({$or: [{_id: id}, {isDuplicateOf: id}]}, {$set: {ignoreDuplicates: true}, $unset: {isDuplicateOf: "", duplicateCount: ""}});
|
||||||
|
|
||||||
// Mark to ignore duplicates for this Sale (id). We will leave the duplicate count and references so that the duplicates will show in a query if we want to revisit those marked as ignored.
|
// Mark to ignore duplicates for this Sale (id). We will leave the duplicate count and references so that the duplicates will show in a query if we want to revisit those marked as ignored.
|
||||||
Sales.update({$or: [{_id: id}, {isDuplicateOf: id}]}, {$set: {ignoreDuplicates: true}});
|
await Sales.updateAsync({$or: [{_id: id}, {isDuplicateOf: id}]}, {$set: {ignoreDuplicates: true}});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
markDuplicateSales: function() {
|
markDuplicateSales: async function() {
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
let sales = Sales.find({}, {sort: {date: 1, venueId: 1, productId: 1, price: 1, amount: 1, measureId: 1, createdAt: 1}}).fetch();
|
let sales = await Sales.find({}, {sort: {date: 1, venueId: 1, productId: 1, price: 1, amount: 1, measureId: 1, createdAt: 1}}).fetchAsync();
|
||||||
|
|
||||||
// Iterate over all the sales looking for sales that have duplicates.
|
// Iterate over all the sales looking for sales that have duplicates.
|
||||||
// Since the sales are sorted by sale date, venueId, productId, price, amount, and measureId which all must be identical to be considered a possible duplicate sale, we only have to check subsequent sales until a non-duplicate is found.
|
// Since the sales are sorted by sale date, venueId, productId, price, amount, and measureId which all must be identical to be considered a possible duplicate sale, we only have to check subsequent sales until a non-duplicate is found.
|
||||||
@@ -405,7 +419,7 @@ if(Meteor.isServer) {
|
|||||||
// If this is marked as a duplicate of another sale, but we got to this point in the loop then the sale it is a duplicate of must have been removed or marked to ignore duplicates.
|
// If this is marked as a duplicate of another sale, but we got to this point in the loop then the sale it is a duplicate of must have been removed or marked to ignore duplicates.
|
||||||
if(sale.isDuplicateOf) {
|
if(sale.isDuplicateOf) {
|
||||||
delete sale.isDuplicateOf;
|
delete sale.isDuplicateOf;
|
||||||
Sales.update(sale._id, {$unset: {isDuplicateOf: ""}}, function(err, id) {
|
await Sales.updateAsync(sale._id, {$unset: {isDuplicateOf: ""}}, function(err, id) {
|
||||||
if(err) console.log(err);
|
if(err) console.log(err);
|
||||||
}, {bypassCollection2: true});
|
}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
@@ -426,7 +440,7 @@ if(Meteor.isServer) {
|
|||||||
if(checkSale && sale.productId === checkSale.productId && sale.venueId === checkSale.venueId && sale.price === checkSale.price && sale.amount === checkSale.amount && sale.measureId === checkSale.measureId) {
|
if(checkSale && sale.productId === checkSale.productId && sale.venueId === checkSale.venueId && sale.price === checkSale.price && sale.amount === checkSale.amount && sale.measureId === checkSale.measureId) {
|
||||||
// Mark the next sale as a duplicate of the currently examined sale.
|
// Mark the next sale as a duplicate of the currently examined sale.
|
||||||
checkSale.isDuplicateOf = sale._id;
|
checkSale.isDuplicateOf = sale._id;
|
||||||
Sales.update(checkSale._id, {$set: {isDuplicateOf: checkSale.isDuplicateOf}}, function(err, id) {
|
await Sales.updateAsync(checkSale._id, {$set: {isDuplicateOf: checkSale.isDuplicateOf}}, function(err, id) {
|
||||||
if(err) console.log(err);
|
if(err) console.log(err);
|
||||||
}, {bypassCollection2: true});
|
}, {bypassCollection2: true});
|
||||||
duplicateCount++;
|
duplicateCount++;
|
||||||
@@ -442,7 +456,7 @@ if(Meteor.isServer) {
|
|||||||
if(sale.duplicateCount !== duplicateCount) {
|
if(sale.duplicateCount !== duplicateCount) {
|
||||||
// Update the sale's duplicate count.
|
// Update the sale's duplicate count.
|
||||||
sale.duplicateCount = duplicateCount;
|
sale.duplicateCount = duplicateCount;
|
||||||
Sales.update(sale._id, {$set: {duplicateCount: sale.duplicateCount}}, function(err, id) {
|
await Sales.updateAsync(sale._id, {$set: {duplicateCount: sale.duplicateCount}}, function(err, id) {
|
||||||
if(err) console.log(err);
|
if(err) console.log(err);
|
||||||
}, {bypassCollection2: true});
|
}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
@@ -450,7 +464,7 @@ if(Meteor.isServer) {
|
|||||||
else if(sale.duplicateCount) {
|
else if(sale.duplicateCount) {
|
||||||
// Remove the duplicate count if it is set.
|
// Remove the duplicate count if it is set.
|
||||||
delete sale.duplicateCount;
|
delete sale.duplicateCount;
|
||||||
Sales.update(sale._id, {$unset: {duplicateCount: ""}}, function(err, id) {
|
await Sales.updateAsync(sale._id, {$unset: {duplicateCount: ""}}, function(err, id) {
|
||||||
if(err) console.log(err);
|
if(err) console.log(err);
|
||||||
}, {bypassCollection2: true});
|
}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,18 @@
|
|||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { Mongo } from 'meteor/mongo';
|
import { Mongo } from 'meteor/mongo';
|
||||||
import { check } from 'meteor/check';
|
import { check } from 'meteor/check';
|
||||||
import {SimpleSchema} from 'meteor/aldeed:simple-schema';
|
import 'meteor/aldeed:collection2/static'
|
||||||
|
import SimpleSchema from 'meteor/aldeed:simple-schema';
|
||||||
|
import Measures from "./Measure";
|
||||||
|
|
||||||
SalesSheets = new Mongo.Collection('SalesSheets');
|
let SalesSheets = new Mongo.Collection('SalesSheets');
|
||||||
|
|
||||||
|
if(Meteor.isServer) {
|
||||||
|
//Set MongoDB indexes (or remove them) here.
|
||||||
|
try {
|
||||||
|
SalesSheets.rawCollection().createIndex({name: -1}, {unique: false})
|
||||||
|
} catch(e) {console.log("Caught exception while setting indexes in MongoDB"); console.error(e)}
|
||||||
|
}
|
||||||
|
|
||||||
const SalesSheetSchema = new SimpleSchema({
|
const SalesSheetSchema = new SimpleSchema({
|
||||||
name: {
|
name: {
|
||||||
@@ -11,8 +20,8 @@ const SalesSheetSchema = new SimpleSchema({
|
|||||||
label: "Name",
|
label: "Name",
|
||||||
optional: false,
|
optional: false,
|
||||||
trim: true,
|
trim: true,
|
||||||
index: 1,
|
//index: 1,
|
||||||
unique: false
|
//unique: false
|
||||||
},
|
},
|
||||||
products: { //An ordered array of product id's included on the sheet.
|
products: { //An ordered array of product id's included on the sheet.
|
||||||
type: Array,
|
type: Array,
|
||||||
@@ -27,7 +36,7 @@ const SalesSheetSchema = new SimpleSchema({
|
|||||||
label: "Name",
|
label: "Name",
|
||||||
optional: false,
|
optional: false,
|
||||||
trim: true,
|
trim: true,
|
||||||
unique: false
|
//unique: false
|
||||||
},
|
},
|
||||||
productId: { //Note: Will be non-existent for headings.
|
productId: { //Note: Will be non-existent for headings.
|
||||||
type: String,
|
type: String,
|
||||||
@@ -37,10 +46,13 @@ const SalesSheetSchema = new SimpleSchema({
|
|||||||
optional: true
|
optional: true
|
||||||
},
|
},
|
||||||
measureIds: { //Note: Will be non-existent for headings.
|
measureIds: { //Note: Will be non-existent for headings.
|
||||||
type: [String],
|
type: Array, //[String],
|
||||||
label: "Measure IDs",
|
label: "Measure IDs",
|
||||||
optional: true
|
optional: true
|
||||||
}
|
},
|
||||||
|
'measureIds.$': {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
//measureIds: {
|
//measureIds: {
|
||||||
// type: Array,
|
// type: Array,
|
||||||
// label: "Measure IDs",
|
// label: "Measure IDs",
|
||||||
@@ -74,11 +86,11 @@ if(Meteor.isServer) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
createSalesSheet: function(name) {
|
createSalesSheet: async function(name) {
|
||||||
check(name, String);
|
check(name, String);
|
||||||
|
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
return SalesSheets.insert({name, products: [], createdAt: new Date()});
|
return await SalesSheets.insertAsync({name, products: [], createdAt: new Date()});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
@@ -98,7 +110,7 @@ if(Meteor.isServer) {
|
|||||||
//updateSalesSheet_updateProduct_removeMeasure: function(id, productId, productName, productMeasures) {
|
//updateSalesSheet_updateProduct_removeMeasure: function(id, productId, productName, productMeasures) {
|
||||||
//
|
//
|
||||||
//},
|
//},
|
||||||
updateSalesSheet: function(id, name, products) {
|
updateSalesSheet: async function(id, name, products) {
|
||||||
check(id, String);
|
check(id, String);
|
||||||
check(name, String);
|
check(name, String);
|
||||||
check(products, [{
|
check(products, [{
|
||||||
@@ -128,7 +140,7 @@ if(Meteor.isServer) {
|
|||||||
//console.log("db.SalesSheet.update({_id: '" + id + "'}, {$set: {name: '" + name + "', updatedAt: " + new Date() + "}, $pull: {$exists: true}, $pushAll: [" + 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.
|
// 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) {
|
await SalesSheets.updateAsync({_id: id}, {$set: {name: name, products: products, updatedAt: new Date()}}, {validate: false}, function(err, count) {
|
||||||
if(err) console.log(err);
|
if(err) console.log(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -146,11 +158,11 @@ if(Meteor.isServer) {
|
|||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
removeSalesSheet: function(id) {
|
removeSalesSheet: async function(id) {
|
||||||
check(id, String);
|
check(id, String);
|
||||||
|
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
SalesSheets.remove(id);
|
await SalesSheets.removeAsync(id);
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,12 +9,13 @@ if(Meteor.isServer) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
"insertUser": function(user) {
|
"insertUser": function(user, roles) {
|
||||||
check(user, {
|
check(user, {
|
||||||
username: String,
|
username: String,
|
||||||
emails: [{address: String, verified: Match.Maybe(Boolean)}],
|
emails: [{address: String, verified: Match.Maybe(Boolean)}],
|
||||||
roles: [String]
|
//roles: [String]
|
||||||
});
|
});
|
||||||
|
check(roles, [String])
|
||||||
|
|
||||||
//Verify the currently logged in user has authority to manage users.
|
//Verify the currently logged in user has authority to manage users.
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_MANAGE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_MANAGE])) {
|
||||||
@@ -33,7 +34,7 @@ if(Meteor.isServer) {
|
|||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized to add users.");
|
else throw new Meteor.Error(403, "Not authorized to add users.");
|
||||||
},
|
},
|
||||||
"updateUser": function(user) {
|
"updateUser": async function(user, roles) {
|
||||||
check(user, {
|
check(user, {
|
||||||
_id: String,
|
_id: String,
|
||||||
username: String,
|
username: String,
|
||||||
@@ -41,15 +42,36 @@ if(Meteor.isServer) {
|
|||||||
address: String,
|
address: String,
|
||||||
verified: Boolean
|
verified: Boolean
|
||||||
}],
|
}],
|
||||||
roles: [String]
|
//roles: [String]
|
||||||
});
|
});
|
||||||
|
check(roles, [String])
|
||||||
|
|
||||||
//Verify the currently logged in user has authority to manage users.
|
//Verify the currently logged in user has authority to manage users.
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_MANAGE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_MANAGE])) {
|
||||||
//Verify the user name isn't already used with a different ID.
|
//Verify the user name isn't already used with a different ID.
|
||||||
if(Meteor.collections.Users.findOne({username: user.username, _id: {$ne: user._id}}) == undefined) {
|
if(Meteor.collections.Users.findOne({username: user.username, _id: {$ne: user._id}}) == undefined) {
|
||||||
//Update the user. Note: I am using direct mongo modification, versus attempting to go through the Accounts and Roles objects. This could cause problems in the future if these packages change their data structures.
|
//Update the user. Note: I am using direct mongo modification, versus attempting to go through the Accounts and Roles objects. This could cause problems in the future if these packages change their data structures.
|
||||||
Meteor.collections.Users.update(user._id, {$set: {username: user.username, emails: user.emails, roles: user.roles}});
|
await Meteor.collections.Users.updateAsync(user._id, {$set: {username: user.username, emails: user.emails/*, roles: user.roles*/}});
|
||||||
|
|
||||||
|
let currentRoles = await Roles.getRolesForUserAsync(user._id)
|
||||||
|
|
||||||
|
//console.log(currentRoles)
|
||||||
|
//console.log(roles)
|
||||||
|
|
||||||
|
//TODO: Figure out which roles to add, and which roles to remove.
|
||||||
|
|
||||||
|
// Add roles not in the database already.
|
||||||
|
//console.log("Adding the user " + user._id + " to the following roles: ")
|
||||||
|
//for(let next of roles) console.log(next)
|
||||||
|
|
||||||
|
let rolesToAdd = roles.filter(x => !currentRoles.includes(x))
|
||||||
|
let rolesToRemove = currentRoles.filter(x => !roles.includes(x))
|
||||||
|
|
||||||
|
console.log('Roles to remove: ' + rolesToRemove)
|
||||||
|
console.log('Roles to add: ' + rolesToAdd)
|
||||||
|
|
||||||
|
if(rolesToAdd.length) Roles.addUsersToRoles([user._id], rolesToAdd)
|
||||||
|
if(rolesToRemove.length) Roles.removeUsersFromRoles([user._id], rolesToRemove)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new Meteor.Error(400, "User name already exists.");
|
throw new Meteor.Error(400, "User name already exists.");
|
||||||
@@ -57,10 +79,10 @@ if(Meteor.isServer) {
|
|||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized to update users.");
|
else throw new Meteor.Error(403, "Not authorized to update users.");
|
||||||
},
|
},
|
||||||
"deleteUser": function(id) {
|
"deleteUser": async function(id) {
|
||||||
check(id, String);
|
check(id, String);
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_MANAGE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_MANAGE])) {
|
||||||
Meteor.collections.Users.remove(id);
|
await Meteor.collections.Users.removeAsync(id);
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized to remove users.");
|
else throw new Meteor.Error(403, "Not authorized to remove users.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,30 @@
|
|||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { Mongo } from 'meteor/mongo';
|
import { Mongo } from 'meteor/mongo';
|
||||||
import { check } from 'meteor/check';
|
import { check } from 'meteor/check';
|
||||||
import {SimpleSchema} from 'meteor/aldeed:simple-schema';
|
import 'meteor/aldeed:collection2/static'
|
||||||
|
import SimpleSchema from 'meteor/aldeed:simple-schema';
|
||||||
|
import Measures from "./Measure";
|
||||||
|
|
||||||
const TYPES = ['Retail', "Farmer's Market", "Restaurant", "Mail"];
|
const TYPES = ['Retail', "Farmer's Market", "Restaurant", "Mail"];
|
||||||
const FREQUENCIES = ['Daily', 'Weekly'];
|
const FREQUENCIES = ['Daily', 'Weekly'];
|
||||||
|
|
||||||
let Venues = new Mongo.Collection('Venues');
|
let Venues = new Mongo.Collection('Venues');
|
||||||
|
|
||||||
|
if(Meteor.isServer) {
|
||||||
|
//Set MongoDB indexes (or remove them) here.
|
||||||
|
try {
|
||||||
|
Venues.rawCollection().createIndex({name: -1}, {unique: true})
|
||||||
|
} catch(e) {console.log("Caught exception while setting indexes in MongoDB"); console.error(e)}
|
||||||
|
}
|
||||||
|
|
||||||
let VenuesSchema = new SimpleSchema({
|
let VenuesSchema = new SimpleSchema({
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
label: "Name",
|
label: "Name",
|
||||||
optional: false,
|
optional: false,
|
||||||
trim: true,
|
trim: true,
|
||||||
index: 1,
|
//index: 1,
|
||||||
unique: true
|
//unique: true
|
||||||
},
|
},
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -70,13 +80,13 @@ if(Meteor.isServer) {
|
|||||||
//});
|
//});
|
||||||
|
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
createVenue: function(name, type, frequency) {
|
createVenue: async function(name, type, frequency) {
|
||||||
check(name, String);
|
check(name, String);
|
||||||
check(type, String);
|
check(type, String);
|
||||||
check(frequency, String);
|
check(frequency, String);
|
||||||
|
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Venues.insert({name, type, frequency, createdAt: new Date()});
|
await Venues.insertAsync({name, type, frequency, createdAt: new Date()});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
@@ -86,40 +96,40 @@ if(Meteor.isServer) {
|
|||||||
// }
|
// }
|
||||||
// else throw new Meteor.Error(403, "Not authorized.");
|
// else throw new Meteor.Error(403, "Not authorized.");
|
||||||
//},
|
//},
|
||||||
updateVenue: function(id, name, type, frequency) {
|
updateVenue: async function(id, name, type, frequency) {
|
||||||
check(id, String);
|
check(id, String);
|
||||||
check(name, String);
|
check(name, String);
|
||||||
check(type, String);
|
check(type, String);
|
||||||
check(frequency, String);
|
check(frequency, String);
|
||||||
|
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Venues.update(id, {$set: {name, type, frequency, updatedAt: new Date()}});
|
await Venues.updateAsync(id, {$set: {name, type, frequency, updatedAt: new Date()}});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
deactivateVenue: function(id) {
|
deactivateVenue: async function(id) {
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
//Venues.remove(id);
|
//Venues.remove(id);
|
||||||
Venues.update(id, {$set: {deactivated: true}}, {bypassCollection2: true});
|
await Venues.updateAsync(id, {$set: {deactivated: true}}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
reactivateVenue: function(id) {
|
reactivateVenue: async function(id) {
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Venues.update(id, {$set: {deactivated: false}}, {bypassCollection2: true});
|
await Venues.updateAsync(id, {$set: {deactivated: false}}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
hideVenue: function(id) { //One step past deactivated - will only show in the venues list if hidden venues are enabled.
|
hideVenue: async function(id) { //One step past deactivated - will only show in the venues list if hidden venues are enabled.
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
//Venues.remove(id);
|
//Venues.remove(id);
|
||||||
Venues.update(id, {$set: {hidden: true}}, {bypassCollection2: true});
|
await Venues.updateAsync(id, {$set: {hidden: true}}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
showVenue: function(id) { //Returns the venue to being simply deactivated. Will again show in lists.
|
showVenue: async function(id) { //Returns the venue to being simply deactivated. Will again show in lists.
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Venues.update(id, {$set: {hidden: false}}, {bypassCollection2: true});
|
await Venues.updateAsync(id, {$set: {hidden: false}}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { Mongo } from 'meteor/mongo';
|
import { Mongo } from 'meteor/mongo';
|
||||||
import { check } from 'meteor/check';
|
import { check } from 'meteor/check';
|
||||||
import {SimpleSchema} from 'meteor/aldeed:simple-schema';
|
import 'meteor/aldeed:collection2/static'
|
||||||
|
import SimpleSchema from 'meteor/aldeed:simple-schema';
|
||||||
|
import Measures from "./Measure";
|
||||||
|
|
||||||
let Workers = new Mongo.Collection('Workers');
|
let Workers = new Mongo.Collection('Workers');
|
||||||
|
|
||||||
|
if(Meteor.isServer) {
|
||||||
|
//Set MongoDB indexes (or remove them) here.
|
||||||
|
try {
|
||||||
|
Workers.rawCollection().createIndex({name: -1}, {unique: true})
|
||||||
|
} catch(e) {console.log("Caught exception while setting indexes in MongoDB"); console.error(e)}
|
||||||
|
}
|
||||||
|
|
||||||
let WORKER_ACTIVITIES = ['sales', 'prep', 'canning', 'farming'];
|
let WORKER_ACTIVITIES = ['sales', 'prep', 'canning', 'farming'];
|
||||||
let workersSchema = new SimpleSchema({
|
let workersSchema = new SimpleSchema({
|
||||||
name: {
|
name: {
|
||||||
@@ -11,15 +21,18 @@ let workersSchema = new SimpleSchema({
|
|||||||
label: "Name",
|
label: "Name",
|
||||||
optional: false,
|
optional: false,
|
||||||
trim: true,
|
trim: true,
|
||||||
index: 1,
|
//index: 1,
|
||||||
unique: true
|
//unique: true
|
||||||
},
|
},
|
||||||
activities: {
|
activities: {
|
||||||
type: [String],
|
type: Array, //[String],
|
||||||
label: "Activities",
|
label: "Activities",
|
||||||
optional: false,
|
optional: false,
|
||||||
trim: true
|
trim: true
|
||||||
},
|
},
|
||||||
|
'activities.$': {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
hourlyRate: {
|
hourlyRate: {
|
||||||
type: SimpleSchema.Integer,
|
type: SimpleSchema.Integer,
|
||||||
label: "HourlyRate",
|
label: "HourlyRate",
|
||||||
@@ -66,13 +79,13 @@ if(Meteor.isServer) Meteor.publish('workers', function() {
|
|||||||
|
|
||||||
if(Meteor.isServer) {
|
if(Meteor.isServer) {
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
createWorker: function(name, activities, hourlyRate) {
|
createWorker: async function(name, activities, hourlyRate) {
|
||||||
check(name, String);
|
check(name, String);
|
||||||
check(activities, [String]);
|
check(activities, [String]);
|
||||||
check(hourlyRate, Number);
|
check(hourlyRate, Number);
|
||||||
|
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Workers.insert({name, activities, hourlyRate, createdAt: new Date()});
|
await Workers.insertAsync({name, activities, hourlyRate, createdAt: new Date()});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
@@ -83,39 +96,39 @@ if(Meteor.isServer) {
|
|||||||
// }
|
// }
|
||||||
// else throw new Meteor.Error(403, "Not authorized.");
|
// else throw new Meteor.Error(403, "Not authorized.");
|
||||||
//},
|
//},
|
||||||
updateWorker: function(id, name, activities, hourlyRate) {
|
updateWorker: async function(id, name, activities, hourlyRate) {
|
||||||
check(id, String);
|
check(id, String);
|
||||||
check(name, String);
|
check(name, String);
|
||||||
check(activities, [String]);
|
check(activities, [String]);
|
||||||
check(hourlyRate, Number);
|
check(hourlyRate, Number);
|
||||||
|
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Workers.update(id, {$set: {name, activities, hourlyRate, updatedAt: new Date()}});
|
await Workers.updateAsync(id, {$set: {name, activities, hourlyRate, updatedAt: new Date()}});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
deactivateWorker: function(id) {
|
deactivateWorker: async function(id) {
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
//Workers.remove(id);
|
//Workers.remove(id);
|
||||||
Workers.update(id, {$set: {deactivated: true}}, {bypassCollection2: true});
|
await Workers.updateAsync(id, {$set: {deactivated: true}}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
reactivateWorker: function(id) {
|
reactivateWorker: async function(id) {
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Workers.update(id, {$set: {deactivated: false}}, {bypassCollection2: true});
|
await Workers.updateAsync(id, {$set: {deactivated: false}}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
hideWorker: function(id) { //One step past deactivated - will only show in the Workers list if hidden Workers are enabled.
|
hideWorker: async function(id) { //One step past deactivated - will only show in the Workers list if hidden Workers are enabled.
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Workers.update(id, {$set: {hidden: true}}, {bypassCollection2: true});
|
await Workers.updateAsync(id, {$set: {hidden: true}}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
},
|
},
|
||||||
showWorker: function(id) { //Returns the measure to being simply deactivated. Will again show in lists.
|
showWorker: async function(id) { //Returns the measure to being simply deactivated. Will again show in lists.
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
Workers.update(id, {$set: {hidden: false}}, {bypassCollection2: true});
|
await Workers.updateAsync(id, {$set: {hidden: false}}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
else throw new Meteor.Error(403, "Not authorized.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,26 +20,28 @@ Meteor.collections = {Measures, Venues, Products, ProductTags, Sales, SalesSheet
|
|||||||
//If this is the server then setup the default admin user if none exist.
|
//If this is the server then setup the default admin user if none exist.
|
||||||
if(Meteor.isServer) {
|
if(Meteor.isServer) {
|
||||||
//Change this to find admin users, create a default admin user if none exists.
|
//Change this to find admin users, create a default admin user if none exists.
|
||||||
if(Users.find({}).count() === 0) {
|
Users.countDocuments({}).then((userCount) => {
|
||||||
try {
|
if(userCount === 0) {
|
||||||
console.log("Creating a default admin user: admin/admin");
|
try {
|
||||||
|
console.log("Creating a default admin user: admin/admin");
|
||||||
|
|
||||||
let id = Accounts.createUser({password: 'admin', username: 'admin'});
|
let id = Accounts.createUser({password: 'admin', username: 'admin'});
|
||||||
//Requires the alanning:roles package.
|
//Requires the alanning:roles package.
|
||||||
Roles.addUsersToRoles(id, [Meteor.UserRoles.ROLE_MANAGE, Meteor.UserRoles.ROLE_UPDATE]);
|
Roles.addUsersToRoles(id, [Meteor.UserRoles.ROLE_MANAGE, Meteor.UserRoles.ROLE_UPDATE]);
|
||||||
}
|
}
|
||||||
catch(err) {
|
catch(err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Meteor.validators = {};
|
|
||||||
Meteor.validators.ObjectID = Match.Where(function(id) {
|
|
||||||
if(id instanceof Mongo.ObjectID) {
|
|
||||||
id = id._str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
check(id, String);
|
Meteor.validators = {};
|
||||||
return /[0-9a-fA-F]{24}/.test(id);
|
Meteor.validators.ObjectID = Match.Where(function(id) {
|
||||||
});
|
if(id instanceof Mongo.ObjectID) {
|
||||||
|
id = id._str;
|
||||||
|
}
|
||||||
|
|
||||||
|
check(id, String);
|
||||||
|
return /[0-9a-fA-F]{24}/.test(id);
|
||||||
|
});
|
||||||
|
})
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
//Look in /libs/startup/both/useraccounts.js for the login/logout/signup routing.
|
//Look in /libs/startup/both/useraccounts.js for the login/logout/signup routing.
|
||||||
|
import { AccountsTemplates } from 'meteor/useraccounts:core';
|
||||||
|
|
||||||
let pri = FlowRouter.group({
|
let pri = FlowRouter.group({
|
||||||
triggersEnter: [AccountsTemplates.ensureSignedIn]
|
triggersEnter: [AccountsTemplates.ensureSignedIn]
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import 'meteor/aldeed:collection2/static'
|
||||||
|
import SimpleSchema from 'meteor/aldeed:simple-schema';
|
||||||
|
|
||||||
let AppVersion = new Mongo.Collection('AppVersion');
|
let AppVersion = new Mongo.Collection('AppVersion');
|
||||||
let AppVersionSchema = new SimpleSchema({
|
let AppVersionSchema = new SimpleSchema({
|
||||||
version: {
|
version: {
|
||||||
@@ -9,16 +12,16 @@ let AppVersionSchema = new SimpleSchema({
|
|||||||
AppVersion.attachSchema(AppVersionSchema);
|
AppVersion.attachSchema(AppVersionSchema);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let appVersions = AppVersion.find({}).fetch();
|
let appVersions = await AppVersion.find({}).fetchAsync();
|
||||||
let appVersion;
|
let appVersion;
|
||||||
|
|
||||||
if(!appVersions || appVersions.length == 0) { //This will happen only when first creating a database.
|
if(!appVersions || appVersions.length == 0) { //This will happen only when first creating a database.
|
||||||
appVersion = {version: 0};
|
appVersion = {version: 0};
|
||||||
appVersion._id = AppVersion.insert(appVersion);
|
appVersion._id = await AppVersion.insertAsync(appVersion);
|
||||||
}
|
}
|
||||||
else if(appVersions.length > 1) { //This should never happen. Remove all but the first app version.
|
else if(appVersions.length > 1) { //This should never happen. Remove all but the first app version.
|
||||||
for(let i = 1; i < appVersions.length; i++) {
|
for(let i = 1; i < appVersions.length; i++) {
|
||||||
AppVersion.remove(appVersions[i]._id);
|
await AppVersion.removeAsync(appVersions[i]._id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ Template.Sales.onCreated(function() {
|
|||||||
Session.set(PREFIX + "sortOption", "date");
|
Session.set(PREFIX + "sortOption", "date");
|
||||||
Session.set(PREFIX + "showOnlyComments", false);
|
Session.set(PREFIX + "showOnlyComments", false);
|
||||||
|
|
||||||
Tracker.autorun(function() {
|
Tracker.autorun(async function() {
|
||||||
let sortOption = Session.get(PREFIX + "sortOption");
|
let sortOption = Session.get(PREFIX + "sortOption");
|
||||||
let sort = sortOption == 'createdAt' ? {createdAt: -1} : {date: -1, createdAt: -1};
|
let sort = sortOption == 'createdAt' ? {createdAt: -1} : {date: -1, createdAt: -1};
|
||||||
let showOnlyComments = Session.get(PREFIX + "showOnlyComments");
|
let showOnlyComments = Session.get(PREFIX + "showOnlyComments");
|
||||||
@@ -34,7 +34,7 @@ Template.Sales.onCreated(function() {
|
|||||||
|
|
||||||
//if(Template.Sales.salesSubscription) Template.Sales.salesSubscription.stop();
|
//if(Template.Sales.salesSubscription) Template.Sales.salesSubscription.stop();
|
||||||
Template.Sales.salesSubscription = Meteor.subscribe("sales", query, sort, QUERY_LIMIT, Session.get(PREFIX + 'skipCount'));
|
Template.Sales.salesSubscription = Meteor.subscribe("sales", query, sort, QUERY_LIMIT, Session.get(PREFIX + 'skipCount'));
|
||||||
Session.set(PREFIX + 'saleCount', Meteor.call('getSalesCount', Session.get(PREFIX + 'searchQuery')));
|
Session.set(PREFIX + 'saleCount', await Meteor.callAsync('getSalesCount', Session.get(PREFIX + 'searchQuery')));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
Template.Sales.onRendered(function() {
|
Template.Sales.onRendered(function() {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import './SalesSheetEditor.html';
|
import './SalesSheetEditor.html';
|
||||||
import swal from 'sweetalert2';
|
import swal from 'sweetalert2';
|
||||||
import dragula from 'dragula';
|
import dragula from 'dragula';
|
||||||
|
import { ReactiveDict } from 'meteor/reactive-dict'
|
||||||
|
|
||||||
let PREFIX = "SalesSheetEditor.";
|
let PREFIX = "SalesSheetEditor.";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
import './SalesSheetForm.html';
|
import './SalesSheetForm.html';
|
||||||
import swal from 'sweetalert2';
|
import swal from 'sweetalert2';
|
||||||
|
import { ReactiveDict } from 'meteor/reactive-dict'
|
||||||
|
|
||||||
let PREFIX = "SalesSheetForm.";
|
let PREFIX = "SalesSheetForm.";
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,8 @@
|
|||||||
<div class="rolesContainer editorDiv"><label>Roles:</label>
|
<div class="rolesContainer editorDiv"><label>Roles:</label>
|
||||||
<div class="roles center" style="font-size: 1.2em">
|
<div class="roles center" style="font-size: 1.2em">
|
||||||
{{#each allRoles}}
|
{{#each allRoles}}
|
||||||
<span class="role {{getRoleState this}} noselect">{{name}}</span>
|
<!-- Roles no longer have a name, they now put the name as the _id in Mongo -->
|
||||||
|
<span class="role {{getRoleState this}} noselect">{{_id}}</span>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ let PREFIX = "UserManagement";
|
|||||||
|
|
||||||
Tracker.autorun(function() {
|
Tracker.autorun(function() {
|
||||||
Meteor.subscribe("users", Session.get(PREFIX + 'searchQuery'));
|
Meteor.subscribe("users", Session.get(PREFIX + 'searchQuery'));
|
||||||
|
Meteor.subscribe("roleAssignments");
|
||||||
Meteor.subscribe("roles");
|
Meteor.subscribe("roles");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -132,6 +133,15 @@ Template.User.helpers({
|
|||||||
let editedUser = Session.get(PREFIX + "editedUser");
|
let editedUser = Session.get(PREFIX + "editedUser");
|
||||||
|
|
||||||
return editedUser == this._id;
|
return editedUser == this._id;
|
||||||
|
},
|
||||||
|
roles: function() {
|
||||||
|
let roles = Meteor.roleAssignment.find({"user._id": this._id}, {"sort": [["role._id", "asc"]]}).fetch();
|
||||||
|
let result = []
|
||||||
|
|
||||||
|
for(let next of roles)
|
||||||
|
result.push(next.role._id)
|
||||||
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -145,7 +155,15 @@ Template.UserEditor.helpers({
|
|||||||
getRoleState: function(role) {
|
getRoleState: function(role) {
|
||||||
let user = Template.parentData(1);
|
let user = Template.parentData(1);
|
||||||
|
|
||||||
return !user.isNew && user.roles.includes(role.name) ? "selected" : "";
|
//Debug code...
|
||||||
|
// console.log("GetRoleState")
|
||||||
|
// console.log(role._id)
|
||||||
|
// console.log(user._id)
|
||||||
|
// console.log(Meteor.roleAssignment.find({"user._id": user._id, "role._id": role._id}).count())
|
||||||
|
//console.log("Role: " + role._id + " === " + Roles.userIsInRole(user._id, [role._id]))
|
||||||
|
|
||||||
|
// Note: Meteor.roleAssignment.countDocuments({...}) returns a Promise and not a count. Cannot use that here.
|
||||||
|
return Roles.userIsInRole(user._id, [role._id]) ? "selected" : ""
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Template.UserEditor.events({
|
Template.UserEditor.events({
|
||||||
@@ -166,10 +184,10 @@ Template.UserEditor.events({
|
|||||||
roles.push($(roleSpans[i]).text());
|
roles.push($(roleSpans[i]).text());
|
||||||
}
|
}
|
||||||
|
|
||||||
user.roles = roles;
|
//user.roles = roles;
|
||||||
|
|
||||||
if(Session.get(PREFIX + 'displayNewUser')) {
|
if(Session.get(PREFIX + 'displayNewUser')) {
|
||||||
Meteor.call('insertUser', user, function(error, result) {
|
Meteor.call('insertUser', user, roles, function(error, result) {
|
||||||
if(error) {
|
if(error) {
|
||||||
sAlert.error(error);
|
sAlert.error(error);
|
||||||
}
|
}
|
||||||
@@ -182,7 +200,7 @@ Template.UserEditor.events({
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
user._id = this._id;
|
user._id = this._id;
|
||||||
Meteor.call("updateUser", user, function(error, result) {
|
Meteor.call("updateUser", user, roles, function(error, result) {
|
||||||
if(error) sAlert.error(error);
|
if(error) sAlert.error(error);
|
||||||
else {
|
else {
|
||||||
sAlert.success("User updated.");
|
sAlert.success("User updated.");
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
// Cleans up all Date objects that don't have a time component. Removes any time component.
|
// Cleans up all Date objects that don't have a time component. Removes any time component.
|
||||||
"cleanDates": function() {
|
"cleanDates": async function() {
|
||||||
|
|
||||||
// Update the sales dates.
|
// Update the sales dates.
|
||||||
|
|
||||||
let sales = Sales.find({}).fetch();
|
let sales = await Sales.find({}).fetchAsync();
|
||||||
|
|
||||||
for(let i = 0; i < sales.length; i++) {
|
for(let i = 0; i < sales.length; i++) {
|
||||||
if(sales[i].date && _.isDate(sales[i].date)) {
|
if(sales[i].date && _.isDate(sales[i].date)) {
|
||||||
@@ -15,7 +15,7 @@ Meteor.methods({
|
|||||||
console.log("Converted " + sales[i].date + " to " + date);
|
console.log("Converted " + sales[i].date + " to " + date);
|
||||||
|
|
||||||
// Save to the database.
|
// Save to the database.
|
||||||
Sales.update(sales[i]._id, {$set: {date}}, function(err, id) {
|
await Sales.updateAsync(sales[i]._id, {$set: {date}}, function(err, id) {
|
||||||
if(err) console.log(err);
|
if(err) console.log(err);
|
||||||
}, {bypassCollection2: true});
|
}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,7 @@ Meteor.methods({
|
|||||||
|
|
||||||
// Update the product price effective dates.
|
// Update the product price effective dates.
|
||||||
|
|
||||||
let products = Products.find({}).fetch();
|
let products = await Products.find({}).fetchAsync();
|
||||||
|
|
||||||
for(let i = 0; i < products.length; i++) {
|
for(let i = 0; i < products.length; i++) {
|
||||||
let product = products[i];
|
let product = products[i];
|
||||||
@@ -48,7 +48,7 @@ Meteor.methods({
|
|||||||
|
|
||||||
// Save the changes.
|
// Save the changes.
|
||||||
if(hasChanges) {
|
if(hasChanges) {
|
||||||
Products.update(product._id, {$set: {prices}}, function(err, id) {
|
await Products.updateAsync(product._id, {$set: {prices}}, function(err, id) {
|
||||||
if(err) console.log(err);
|
if(err) console.log(err);
|
||||||
}, {validate: false, bypassCollection2: true});
|
}, {validate: false, bypassCollection2: true});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
|
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
// Cleans up all Date objects that don't have a time component. Removes any time component.
|
// Cleans up all Date objects that don't have a time component. Removes any time component.
|
||||||
"enhanceSalesDateFields": function() {
|
"enhanceSalesDateFields": async function() {
|
||||||
let sales = Sales.find({}).fetch();
|
let sales = await Sales.find({}).fetchAsync();
|
||||||
|
|
||||||
for(let i = 0; i < sales.length; i++) {
|
for(let i = 0; i < sales.length; i++) {
|
||||||
let dateString = sales[i].date.toString();
|
let dateString = sales[i].date.toString();
|
||||||
@@ -25,7 +25,7 @@ Meteor.methods({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save to the database.
|
// Save to the database.
|
||||||
Sales.update(sales[i]._id, {$set: {"timestamp": timestamp.getTime(), weekOfYear}}, {bypassCollection2: true}, function(err, id) {
|
await Sales.updateAsync(sales[i]._id, {$set: {"timestamp": timestamp.getTime(), weekOfYear}}, {bypassCollection2: true}, function(err, id) {
|
||||||
if(err) console.log(err);
|
if(err) console.log(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
let fs = require('fs');
|
let fs = require('fs');
|
||||||
|
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
"exportMissingSales": function() {
|
"exportMissingSales": async function() {
|
||||||
try {
|
try {
|
||||||
let products = Products.find({}).fetch();
|
let products = await Products.find({}).fetchAsync();
|
||||||
let venues = Venues.find({}).fetch();
|
let venues = await Venues.find({}).fetchAsync();
|
||||||
let measures = Measures.find({}).fetch();
|
let measures = await Measures.find({}).fetchAsync();
|
||||||
let productNameMap = {};
|
let productNameMap = {};
|
||||||
let venueNameMap = {};
|
let venueNameMap = {};
|
||||||
let measureNameMap = {};
|
let measureNameMap = {};
|
||||||
let sales = Sales.find({createdAt: {$gte: moment.utc("2017-01-28", "YYYY-MM-DD").toDate(), $lt: moment.utc("2017-01-29", "YYYY-MM-DD").toDate()}}).fetch();
|
let sales = await Sales.find({createdAt: {$gte: moment.utc("2017-01-28", "YYYY-MM-DD").toDate(), $lt: moment.utc("2017-01-29", "YYYY-MM-DD").toDate()}}).fetchAsync();
|
||||||
let output = "";
|
let output = "";
|
||||||
|
|
||||||
for(let i = 0; i < products.length; i++) {
|
for(let i = 0; i < products.length; i++) {
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
"checkDuplicateSales": function() {
|
"checkDuplicateSales": async function() {
|
||||||
try {
|
try {
|
||||||
let sales = Sales.find({}).fetch();
|
let sales = await Sales.find({}).fetchAsync();
|
||||||
let duplicateCount = 0;
|
let duplicateCount = 0;
|
||||||
|
|
||||||
for(let i = 0; i < sales.length; i++) {
|
for(let i = 0; i < sales.length; i++) {
|
||||||
let next = missingData[i];
|
let next = missingData[i];
|
||||||
let count = Sales.find({date: next.date, measureId: next.measureId, productId: next.productId, venueId: next.venueId, price: next.price, amount: next.amount}).count();
|
let count = await Sales.countDocuments({date: next.date, measureId: next.measureId, productId: next.productId, venueId: next.venueId, price: next.price, amount: next.amount});
|
||||||
|
|
||||||
if(count > 1) {
|
if(count > 1) {
|
||||||
console.log("This sale has a duplicate:");
|
console.log("This sale has a duplicate:");
|
||||||
|
|||||||
110
server/import.js
110
server/import.js
@@ -2,13 +2,13 @@ import readCSV from '/imports/util/csv.js';
|
|||||||
|
|
||||||
//Returns the ID of the created or found object.
|
//Returns the ID of the created or found object.
|
||||||
//This is needed because for some crazy reason upsert only returns the affected document if a document is inserted, otherwise it does not return the ID of the affected document.
|
//This is needed because for some crazy reason upsert only returns the affected document if a document is inserted, otherwise it does not return the ID of the affected document.
|
||||||
function insertOrCreate(collection, selector, object) {
|
async function insertOrCreate(collection, selector, object) {
|
||||||
let id;
|
let id;
|
||||||
|
|
||||||
let findResult = collection.findOne(selector, {fields: {_id: 1}});
|
let findResult = await collection.findOneAsync(selector, {fields: {_id: 1}});
|
||||||
|
|
||||||
if(findResult && findResult._id) id = findResult._id;
|
if(findResult && findResult._id) id = findResult._id;
|
||||||
else id = collection.insert(object);
|
else id = await collection.insertAsync(object);
|
||||||
|
|
||||||
//
|
//
|
||||||
// let result = collection.upsert(selector, {$setOnInsert: object}, {multi: false});
|
// let result = collection.upsert(selector, {$setOnInsert: object}, {multi: false});
|
||||||
@@ -26,7 +26,7 @@ function insertOrCreate(collection, selector, object) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
"importBasics": function() {
|
"importBasics": async function() {
|
||||||
const measures = [
|
const measures = [
|
||||||
{name: "Jar 4oz", postfix: "4oz", order: 0, createdAt: new Date()},
|
{name: "Jar 4oz", postfix: "4oz", order: 0, createdAt: new Date()},
|
||||||
{name: "Jar 8oz", postfix: "8oz", order: 1, createdAt: new Date()},
|
{name: "Jar 8oz", postfix: "8oz", order: 1, createdAt: new Date()},
|
||||||
@@ -55,22 +55,22 @@ Meteor.methods({
|
|||||||
{name: "Website Order", type: "Mail", createdAt: new Date()}
|
{name: "Website Order", type: "Mail", createdAt: new Date()}
|
||||||
];
|
];
|
||||||
|
|
||||||
Measures.remove({});
|
await Measures.removeAsync({});
|
||||||
Venues.remove({});
|
await Venues.removeAsync({});
|
||||||
|
|
||||||
for(let next of measures) {
|
for(let next of measures) {
|
||||||
Measures.insert(next, function(error, _id) {
|
await Measures.insertAsync(next, function(error, _id) {
|
||||||
if(error) console.log("Failed to insert measure: " + JSON.stringify(next) + " ERROR: " + error);
|
if(error) console.log("Failed to insert measure: " + JSON.stringify(next) + " ERROR: " + error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for(let next of venues) {
|
for(let next of venues) {
|
||||||
Venues.insert(next, function(error, _id) {
|
await Venues.insertAsync(next, function(error, _id) {
|
||||||
if(error) console.log("Failed to insert venue: " + JSON.stringify(next) + " ERROR: " + error);
|
if(error) console.log("Failed to insert venue: " + JSON.stringify(next) + " ERROR: " + error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"importItems": function() {
|
"importItems": async function() {
|
||||||
let fileName = "importItems.csv";
|
let fileName = "importItems.csv";
|
||||||
//The mapping of model attributes to CSV columns. The oz sizes are arrays of columns since there are multiple.
|
//The mapping of model attributes to CSV columns. The oz sizes are arrays of columns since there are multiple.
|
||||||
let map = {};
|
let map = {};
|
||||||
@@ -81,31 +81,31 @@ Meteor.methods({
|
|||||||
{
|
{
|
||||||
let result;
|
let result;
|
||||||
|
|
||||||
result = Measures.findOne({name: 'Jar 4oz'}, {fields: {_id: 1}});
|
result = await Measures.findOneAsync({name: 'Jar 4oz'}, {fields: {_id: 1}});
|
||||||
if(result) measureIdMap['4oz'] = result._id;
|
if(result) measureIdMap['4oz'] = result._id;
|
||||||
else {console.log("Error: Couldn't find the _id for Jar 4oz"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Jar 4oz"); hasError = true;}
|
||||||
|
|
||||||
result = Measures.findOne({name: 'Jar 8oz'}, {fields: {_id: 1}});
|
result = await Measures.findOneAsync({name: 'Jar 8oz'}, {fields: {_id: 1}});
|
||||||
if(result) measureIdMap['8oz'] = result._id;
|
if(result) measureIdMap['8oz'] = result._id;
|
||||||
else {console.log("Error: Couldn't find the _id for Jar 8oz"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Jar 8oz"); hasError = true;}
|
||||||
|
|
||||||
result = Measures.findOne({name: 'Jar 12oz'}, {fields: {_id: 1}});
|
result = await Measures.findOneAsync({name: 'Jar 12oz'}, {fields: {_id: 1}});
|
||||||
if(result) measureIdMap['12oz'] = result._id
|
if(result) measureIdMap['12oz'] = result._id
|
||||||
else {console.log("Error: Couldn't find the _id for Jar 12oz"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Jar 12oz"); hasError = true;}
|
||||||
|
|
||||||
result = Measures.findOne({name: 'Jar 16oz'}, {fields: {_id: 1}});
|
result = await Measures.findOneAsync({name: 'Jar 16oz'}, {fields: {_id: 1}});
|
||||||
if(result) measureIdMap['16oz'] = result._id;
|
if(result) measureIdMap['16oz'] = result._id;
|
||||||
else {console.log("Error: Couldn't find the _id for Jar 16oz"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Jar 16oz"); hasError = true;}
|
||||||
|
|
||||||
result = Measures.findOne({name: 'Jar 32oz'}, {fields: {_id: 1}});
|
result = await Measures.findOneAsync({name: 'Jar 32oz'}, {fields: {_id: 1}});
|
||||||
if(result) measureIdMap['32oz'] = result._id;
|
if(result) measureIdMap['32oz'] = result._id;
|
||||||
else {console.log("Error: Couldn't find the _id for Jar 32oz"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Jar 32oz"); hasError = true;}
|
||||||
|
|
||||||
result = Measures.findOne({name: 'Each'}, {fields: {_id: 1}});
|
result = await Measures.findOneAsync({name: 'Each'}, {fields: {_id: 1}});
|
||||||
if(result) measureIdMap['Each'] = result._id;
|
if(result) measureIdMap['Each'] = result._id;
|
||||||
else {console.log("Error: Couldn't find the _id for Each"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Each"); hasError = true;}
|
||||||
|
|
||||||
result = Measures.findOne({name: 'Bags'}, {fields: {_id: 1}});
|
result = await Measures.findOneAsync({name: 'Bags'}, {fields: {_id: 1}});
|
||||||
if(result) measureIdMap['Bags'] = result._id;
|
if(result) measureIdMap['Bags'] = result._id;
|
||||||
else {console.log("Error: Couldn't find the _id for Bags"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Bags"); hasError = true;}
|
||||||
}
|
}
|
||||||
@@ -178,7 +178,7 @@ Meteor.methods({
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Reads a single row of CSV data and adds it to the database.
|
//Reads a single row of CSV data and adds it to the database.
|
||||||
function readRow(row) {
|
async function readRow(row) {
|
||||||
let category = row[map.category].trim();
|
let category = row[map.category].trim();
|
||||||
let subcategory = row[map.subcategory].trim();
|
let subcategory = row[map.subcategory].trim();
|
||||||
let item = row[map.item];
|
let item = row[map.item];
|
||||||
@@ -219,7 +219,7 @@ Meteor.methods({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// categoryId = insertOrCreate(Categories, {name: category}, {name: category, createdAt: new Date()});
|
// categoryId = insertOrCreate(Categories, {name: category}, {name: category, createdAt: new Date()});
|
||||||
categoryId = insertOrCreate(ProductTags, {name: category}, {name: category, createdAt: new Date()});
|
let categoryId = await insertOrCreate(ProductTags, {name: category}, {name: category, createdAt: new Date()});
|
||||||
|
|
||||||
if(categoryId) {
|
if(categoryId) {
|
||||||
// subcategoryId = insertOrCreate(Subcategories, {name: subcategory}, {
|
// subcategoryId = insertOrCreate(Subcategories, {name: subcategory}, {
|
||||||
@@ -227,7 +227,7 @@ Meteor.methods({
|
|||||||
// categoryId: categoryId,
|
// categoryId: categoryId,
|
||||||
// createdAt: new Date()
|
// createdAt: new Date()
|
||||||
// });
|
// });
|
||||||
subcategoryId = insertOrCreate(ProductTags, {name: subcategory}, {name: subcategory, createdAt: new Date()});
|
let subcategoryId = await insertOrCreate(ProductTags, {name: subcategory}, {name: subcategory, createdAt: new Date()});
|
||||||
|
|
||||||
if(subcategoryId) {
|
if(subcategoryId) {
|
||||||
let weightedMeasures = [];
|
let weightedMeasures = [];
|
||||||
@@ -258,7 +258,7 @@ Meteor.methods({
|
|||||||
|
|
||||||
//Here we can just insert since we don't care about the resulting ID.
|
//Here we can just insert since we don't care about the resulting ID.
|
||||||
let obj = {name: item, tags: [categoryId, subcategoryId], measures: measures, createdAt: new Date()};
|
let obj = {name: item, tags: [categoryId, subcategoryId], measures: measures, createdAt: new Date()};
|
||||||
Products.insert(obj, function(error) {
|
await Products.insertAsync(obj, function(error) {
|
||||||
if(error) console.log("Could not insert the Product: " + JSON.stringify(obj) + "\n ERROR: " + error);
|
if(error) console.log("Could not insert the Product: " + JSON.stringify(obj) + "\n ERROR: " + error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -271,7 +271,7 @@ Meteor.methods({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readCSV(fileName, Meteor.bindEnvironment(function(error, data) {
|
readCSV(fileName, Meteor.bindEnvironment(async function(error, data) {
|
||||||
//csv.read(fileName, function(error, csvData) {
|
//csv.read(fileName, function(error, csvData) {
|
||||||
if(error) console.log("Unable to read the importItems.csv file:" + error);
|
if(error) console.log("Unable to read the importItems.csv file:" + error);
|
||||||
else {
|
else {
|
||||||
@@ -282,19 +282,19 @@ Meteor.methods({
|
|||||||
// Items.remove({});
|
// Items.remove({});
|
||||||
// Subcategories.remove({});
|
// Subcategories.remove({});
|
||||||
// Categories.remove({});
|
// Categories.remove({});
|
||||||
Products.remove({});
|
await Products.removeAsync({});
|
||||||
|
|
||||||
// console.log("CSV Column Mapping: " + JSON.stringify(map));
|
// console.log("CSV Column Mapping: " + JSON.stringify(map));
|
||||||
// readRow(data[1]);
|
// readRow(data[1]);
|
||||||
|
|
||||||
for(let i = 1; i < data.length; i++) {
|
for(let i = 1; i < data.length; i++) {
|
||||||
readRow(data[i]);
|
await readRow(data[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"importSales": function() {
|
"importSales": async function() {
|
||||||
let fileName = "importSales.csv";
|
let fileName = "importSales.csv";
|
||||||
//The mapping of model attributes to CSV columns. The oz sizes are arrays of columns since there are multiple.
|
//The mapping of model attributes to CSV columns. The oz sizes are arrays of columns since there are multiple.
|
||||||
let map = {};
|
let map = {};
|
||||||
@@ -543,82 +543,82 @@ Meteor.methods({
|
|||||||
{ //Load the object ids for the measures and venues we will encounter.
|
{ //Load the object ids for the measures and venues we will encounter.
|
||||||
let result;
|
let result;
|
||||||
|
|
||||||
result = Measures.findOne({name: 'Jar 4oz'}, {fields: {_id: 1}});
|
result = await Measures.findOneAsync({name: 'Jar 4oz'}, {fields: {_id: 1}});
|
||||||
if(result) measureIdMap['4oz'] = result._id;
|
if(result) measureIdMap['4oz'] = result._id;
|
||||||
else {console.log("Error: Couldn't find the _id for Jar 4oz"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Jar 4oz"); hasError = true;}
|
||||||
|
|
||||||
result = Measures.findOne({name: 'Jar 8oz'}, {fields: {_id: 1}});
|
result = await Measures.findOneAsync({name: 'Jar 8oz'}, {fields: {_id: 1}});
|
||||||
if(result) measureIdMap['8oz'] = result._id;
|
if(result) measureIdMap['8oz'] = result._id;
|
||||||
else {console.log("Error: Couldn't find the _id for Jar 8oz"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Jar 8oz"); hasError = true;}
|
||||||
|
|
||||||
result = Measures.findOne({name: 'Jar 12oz'}, {fields: {_id: 1}});
|
result = await Measures.findOneAsync({name: 'Jar 12oz'}, {fields: {_id: 1}});
|
||||||
if(result) measureIdMap['12oz'] = result._id
|
if(result) measureIdMap['12oz'] = result._id
|
||||||
else {console.log("Error: Couldn't find the _id for Jar 12oz"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Jar 12oz"); hasError = true;}
|
||||||
|
|
||||||
result = Measures.findOne({name: 'Jar 16oz'}, {fields: {_id: 1}});
|
result = await Measures.findOneAsync({name: 'Jar 16oz'}, {fields: {_id: 1}});
|
||||||
if(result) measureIdMap['16oz'] = result._id;
|
if(result) measureIdMap['16oz'] = result._id;
|
||||||
else {console.log("Error: Couldn't find the _id for Jar 16oz"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Jar 16oz"); hasError = true;}
|
||||||
|
|
||||||
result = Measures.findOne({name: 'Jar 32oz'}, {fields: {_id: 1}});
|
result = await Measures.findOneAsync({name: 'Jar 32oz'}, {fields: {_id: 1}});
|
||||||
if(result) measureIdMap['32oz'] = result._id;
|
if(result) measureIdMap['32oz'] = result._id;
|
||||||
else {console.log("Error: Couldn't find the _id for Jar 32oz"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Jar 32oz"); hasError = true;}
|
||||||
|
|
||||||
result = Measures.findOne({name: 'Each'}, {fields: {_id: 1}});
|
result = await Measures.findOneAsync({name: 'Each'}, {fields: {_id: 1}});
|
||||||
if(result) measureIdMap['Each'] = result._id;
|
if(result) measureIdMap['Each'] = result._id;
|
||||||
else {console.log("Error: Couldn't find the _id for Each"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Each"); hasError = true;}
|
||||||
|
|
||||||
result = Measures.findOne({name: 'Bags'}, {fields: {_id: 1}});
|
result = await Measures.findOneAsync({name: 'Bags'}, {fields: {_id: 1}});
|
||||||
if(result) measureIdMap['Bags'] = result._id;
|
if(result) measureIdMap['Bags'] = result._id;
|
||||||
else {console.log("Error: Couldn't find the _id for Bags"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Bags"); hasError = true;}
|
||||||
|
|
||||||
result = Venues.findOne({name: 'Boonville'}, {fields: {_id: 1}});
|
result = await Venues.findOneAsync({name: 'Boonville'}, {fields: {_id: 1}});
|
||||||
if(result) venueIdMap['bv'] = result._id;
|
if(result) venueIdMap['bv'] = result._id;
|
||||||
else {console.log("Error: Couldn't find the _id for Boonville"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Boonville"); hasError = true;}
|
||||||
|
|
||||||
result = Venues.findOne({name: 'Clement St'}, {fields: {_id: 1}});
|
result = await Venues.findOneAsync({name: 'Clement St'}, {fields: {_id: 1}});
|
||||||
if(result) venueIdMap['sf'] = result._id;
|
if(result) venueIdMap['sf'] = result._id;
|
||||||
else {console.log("Error: Couldn't find the _id for Clement St"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Clement St"); hasError = true;}
|
||||||
|
|
||||||
result = Venues.findOne({name: 'Ukiah'}, {fields: {_id: 1}});
|
result = await Venues.findOneAsync({name: 'Ukiah'}, {fields: {_id: 1}});
|
||||||
if(result) venueIdMap['uk'] = result._id;
|
if(result) venueIdMap['uk'] = result._id;
|
||||||
else {console.log("Error: Couldn't find the _id for Ukiah"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Ukiah"); hasError = true;}
|
||||||
|
|
||||||
result = Venues.findOne({name: 'Mendocino'}, {fields: {_id: 1}});
|
result = await Venues.findOneAsync({name: 'Mendocino'}, {fields: {_id: 1}});
|
||||||
if(result) venueIdMap['men'] = result._id;
|
if(result) venueIdMap['men'] = result._id;
|
||||||
else {console.log("Error: Couldn't find the _id for Mendocino"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Mendocino"); hasError = true;}
|
||||||
|
|
||||||
result = Venues.findOne({name: 'Ft Bragg'}, {fields: {_id: 1}});
|
result = await Venues.findOneAsync({name: 'Ft Bragg'}, {fields: {_id: 1}});
|
||||||
if(result) venueIdMap['fb'] = result._id;
|
if(result) venueIdMap['fb'] = result._id;
|
||||||
else {console.log("Error: Couldn't find the _id for Ft Bragg"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Ft Bragg"); hasError = true;}
|
||||||
|
|
||||||
result = Venues.findOne({name: 'On Farm'}, {fields: {_id: 1}});
|
result = await Venues.findOneAsync({name: 'On Farm'}, {fields: {_id: 1}});
|
||||||
if(result) venueIdMap['of'] = result._id;
|
if(result) venueIdMap['of'] = result._id;
|
||||||
else {console.log("Error: Couldn't find the _id for On Farm"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for On Farm"); hasError = true;}
|
||||||
|
|
||||||
result = Venues.findOne({name: 'Unknown Restaurant'}, {fields: {_id: 1}});
|
result = await Venues.findOneAsync({name: 'Unknown Restaurant'}, {fields: {_id: 1}});
|
||||||
if(result) {venueIdMap['res'] = result._id; venueIdMap['w'] = result._id;}
|
if(result) {venueIdMap['res'] = result._id; venueIdMap['w'] = result._id;}
|
||||||
else {console.log("Error: Couldn't find the _id for Unknown Restaurant"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Unknown Restaurant"); hasError = true;}
|
||||||
|
|
||||||
result = Venues.findOne({name: 'Yorkville Market'}, {fields: {_id: 1}});
|
result = await Venues.findOneAsync({name: 'Yorkville Market'}, {fields: {_id: 1}});
|
||||||
if(result) venueIdMap['ym'] = result._id;
|
if(result) venueIdMap['ym'] = result._id;
|
||||||
else {console.log("Error: Couldn't find the _id for Yorkville Market"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Yorkville Market"); hasError = true;}
|
||||||
|
|
||||||
result = Venues.findOne({name: 'Yorkville Cellars'}, {fields: {_id: 1}});
|
result = await Venues.findOneAsync({name: 'Yorkville Cellars'}, {fields: {_id: 1}});
|
||||||
if(result) venueIdMap['yc'] = result._id;
|
if(result) venueIdMap['yc'] = result._id;
|
||||||
else {console.log("Error: Couldn't find the _id for Yorkville Cellars"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Yorkville Cellars"); hasError = true;}
|
||||||
|
|
||||||
result = Venues.findOne({name: 'Mail Order'}, {fields: {_id: 1}});
|
result = await Venues.findOneAsync({name: 'Mail Order'}, {fields: {_id: 1}});
|
||||||
if(result) venueIdMap['mo'] = result._id;
|
if(result) venueIdMap['mo'] = result._id;
|
||||||
else {console.log("Error: Couldn't find the _id for Mail Order"); hasError = true;}
|
else {console.log("Error: Couldn't find the _id for Mail Order"); hasError = true;}
|
||||||
|
|
||||||
// result = Items.find({}, {fields: {_id: 1, name: 1}, sort: {name: 1}}).fetch();
|
// result = Items.find({}, {fields: {_id: 1, name: 1}, sort: {name: 1}}).fetch();
|
||||||
result = Products.find({}, {fields: {_id: 1, name: 1}, sort: {name: 1}}).fetch();
|
result = await Products.find({}, {fields: {_id: 1, name: 1}, sort: {name: 1}}).fetchAsync();
|
||||||
for(let i = 0; i < result.length; i++) itemIdMap[result[i].name.toLowerCase()] = result[i]._id;
|
for(let i = 0; i < result.length; i++) itemIdMap[result[i].name.toLowerCase()] = result[i]._id;
|
||||||
|
|
||||||
//console.log(JSON.stringify(itemIdMap));
|
//console.log(JSON.stringify(itemIdMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
readCSV(fileName, Meteor.bindEnvironment(function(error, data) {
|
readCSV(fileName, Meteor.bindEnvironment(async function(error, data) {
|
||||||
//csv.read(fileName, function(error, csvData) {
|
//csv.read(fileName, function(error, csvData) {
|
||||||
|
|
||||||
//Data is an array of arrays. data[0] = array of headers. data[1] = first row of data.
|
//Data is an array of arrays. data[0] = array of headers. data[1] = first row of data.
|
||||||
@@ -628,14 +628,14 @@ Meteor.methods({
|
|||||||
collectMetadata(data[0]);
|
collectMetadata(data[0]);
|
||||||
|
|
||||||
//Remove everything first.
|
//Remove everything first.
|
||||||
Sales.remove({"importTag": "1"});
|
await Sales.removeAsync({"importTag": "1"});
|
||||||
|
|
||||||
// console.log("CSV Column Mapping: " + JSON.stringify(map));
|
// console.log("CSV Column Mapping: " + JSON.stringify(map));
|
||||||
// readRow(data[1]);
|
// readRow(data[1]);
|
||||||
|
|
||||||
let undefinedItems = {};
|
let undefinedItems = {};
|
||||||
for(let i = 1; i < data.length; i++) {
|
for(let i = 1; i < data.length; i++) {
|
||||||
readRow(data[i], undefinedItems);
|
await readRow(data[i], undefinedItems);
|
||||||
}
|
}
|
||||||
// let output = "";
|
// let output = "";
|
||||||
// output += "----------------\n";
|
// output += "----------------\n";
|
||||||
@@ -714,7 +714,7 @@ Meteor.methods({
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Reads a single row of CSV data and adds it to the database.
|
//Reads a single row of CSV data and adds it to the database.
|
||||||
function readRow(row, undefinedItems) {
|
async function readRow(row, undefinedItems) {
|
||||||
let date = moment(row[map.date], "M/D/YYYY").toDate();
|
let date = moment(row[map.date], "M/D/YYYY").toDate();
|
||||||
let venue = row[map.venue].toLowerCase();
|
let venue = row[map.venue].toLowerCase();
|
||||||
let item = row[map.item].trim();
|
let item = row[map.item].trim();
|
||||||
@@ -757,7 +757,7 @@ Meteor.methods({
|
|||||||
|
|
||||||
if(price != undefined) price = price['oz32'];
|
if(price != undefined) price = price['oz32'];
|
||||||
if(price == undefined) price = priceMap[year]['oz32'];
|
if(price == undefined) price = priceMap[year]['oz32'];
|
||||||
if(price) insertSale({date: date, amount: oz32, price: price, venueId: venueId, productId: itemId, measureId: measureIdMap['32oz']});
|
if(price) await insertSale({date: date, amount: oz32, price: price, venueId: venueId, productId: itemId, measureId: measureIdMap['32oz']});
|
||||||
else console.log("Could not find a price in the year " + year + " for " + item + " in the size oz32");
|
else console.log("Could not find a price in the year " + year + " for " + item + " in the size oz32");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -766,7 +766,7 @@ Meteor.methods({
|
|||||||
|
|
||||||
if(price != undefined) price = price['oz16'];
|
if(price != undefined) price = price['oz16'];
|
||||||
if(price == undefined) price = priceMap[year]['oz16'];
|
if(price == undefined) price = priceMap[year]['oz16'];
|
||||||
if(price) insertSale({date: date, amount: oz16, price: price, venueId: venueId, productId: itemId, measureId: measureIdMap['16oz']});
|
if(price) await insertSale({date: date, amount: oz16, price: price, venueId: venueId, productId: itemId, measureId: measureIdMap['16oz']});
|
||||||
else console.log("Could not find a price in the year " + year + " for " + item + " in the size oz16");
|
else console.log("Could not find a price in the year " + year + " for " + item + " in the size oz16");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -775,7 +775,7 @@ Meteor.methods({
|
|||||||
|
|
||||||
if(price != undefined) price = price['oz12'];
|
if(price != undefined) price = price['oz12'];
|
||||||
if(price == undefined) price = priceMap[year]['oz12'];
|
if(price == undefined) price = priceMap[year]['oz12'];
|
||||||
if(price) insertSale({date: date, amount: oz12, price: price, venueId: venueId, productId: itemId, measureId: measureIdMap['12oz']});
|
if(price) await insertSale({date: date, amount: oz12, price: price, venueId: venueId, productId: itemId, measureId: measureIdMap['12oz']});
|
||||||
else console.log("Could not find a price in the year " + year + " for " + item + " in the size oz12");
|
else console.log("Could not find a price in the year " + year + " for " + item + " in the size oz12");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -784,7 +784,7 @@ Meteor.methods({
|
|||||||
|
|
||||||
if(price != undefined) price = price['oz8'];
|
if(price != undefined) price = price['oz8'];
|
||||||
if(price == undefined) price = priceMap[year]['oz8'];
|
if(price == undefined) price = priceMap[year]['oz8'];
|
||||||
if(price) insertSale({date: date, amount: oz8, price: price, venueId: venueId, productId: itemId, measureId: measureIdMap['8oz']});
|
if(price) await insertSale({date: date, amount: oz8, price: price, venueId: venueId, productId: itemId, measureId: measureIdMap['8oz']});
|
||||||
else console.log("Could not find a price in the year " + year + " for " + item + " in the size oz8");
|
else console.log("Could not find a price in the year " + year + " for " + item + " in the size oz8");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -793,7 +793,7 @@ Meteor.methods({
|
|||||||
|
|
||||||
if(price != undefined) price = price['oz4'];
|
if(price != undefined) price = price['oz4'];
|
||||||
if(price == undefined) price = priceMap[year]['oz4'];
|
if(price == undefined) price = priceMap[year]['oz4'];
|
||||||
if(price) insertSale({date: date, amount: oz4, price: price, venueId: venueId, productId: itemId, measureId: measureIdMap['4oz']});
|
if(price) await insertSale({date: date, amount: oz4, price: price, venueId: venueId, productId: itemId, measureId: measureIdMap['4oz']});
|
||||||
else console.log("Could not find a price in the year " + year + " for " + item + " in the size oz4");
|
else console.log("Could not find a price in the year " + year + " for " + item + " in the size oz4");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -802,7 +802,7 @@ Meteor.methods({
|
|||||||
|
|
||||||
if(price != undefined) price = price['bags'];
|
if(price != undefined) price = price['bags'];
|
||||||
if(price == undefined) price = priceMap[year]['bags'];
|
if(price == undefined) price = priceMap[year]['bags'];
|
||||||
if(price) insertSale({date: date, amount: bags, price: price, venueId: venueId, productId: itemId, measureId: measureIdMap['Bags']});
|
if(price) await insertSale({date: date, amount: bags, price: price, venueId: venueId, productId: itemId, measureId: measureIdMap['Bags']});
|
||||||
else {
|
else {
|
||||||
console.log("Could not find a price in the year " + year + " for " + item + " in the size bags");
|
console.log("Could not find a price in the year " + year + " for " + item + " in the size bags");
|
||||||
}
|
}
|
||||||
@@ -813,16 +813,16 @@ Meteor.methods({
|
|||||||
|
|
||||||
if(price != undefined) price = price['each'];
|
if(price != undefined) price = price['each'];
|
||||||
if(price == undefined) price = priceMap[year]['each'];
|
if(price == undefined) price = priceMap[year]['each'];
|
||||||
if(price) insertSale({date: date, amount: each, price: price, venueId: venueId, productId: itemId, measureId: measureIdMap['Each']});
|
if(price) await insertSale({date: date, amount: each, price: price, venueId: venueId, productId: itemId, measureId: measureIdMap['Each']});
|
||||||
else console.log("Could not find a price in the year " + year + " for " + item + " in the size each");
|
else console.log("Could not find a price in the year " + year + " for " + item + " in the size each");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function insertSale(sale) {
|
async function insertSale(sale) {
|
||||||
sale.createdAt = new Date();
|
sale.createdAt = new Date();
|
||||||
sale.importTag = "1";
|
sale.importTag = "1";
|
||||||
Sales.insert(sale, function(error) {
|
await Sales.insertAsync(sale, function(error) {
|
||||||
if(error) console.log("Failed to insert the sale: " + JSON.stringify(sale) + "\n ERROR: " + error);
|
if(error) console.log("Failed to insert the sale: " + JSON.stringify(sale) + "\n ERROR: " + error);
|
||||||
}, {bypassCollection2: true});
|
}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
"importMissingSales": function() {
|
"importMissingSales": async function() {
|
||||||
console.log("Importing Missing Sales...");
|
console.log("Importing Missing Sales...");
|
||||||
try {
|
try {
|
||||||
let products = Products.find({}).fetch();
|
let products = await Products.find({}).fetchAsync();
|
||||||
let venues = Venues.find({}).fetch();
|
let venues = await Venues.find({}).fetchAsync();
|
||||||
let measures = Measures.find({}).fetch();
|
let measures = await Measures.find({}).fetchAsync();
|
||||||
let productNameMap = {};
|
let productNameMap = {};
|
||||||
let venueNameMap = {};
|
let venueNameMap = {};
|
||||||
let measureNameMap = {};
|
let measureNameMap = {};
|
||||||
|
|||||||
Reference in New Issue
Block a user