diff --git a/.meteor/packages b/.meteor/packages
index 425d535..da820fd 100644
--- a/.meteor/packages
+++ b/.meteor/packages
@@ -6,19 +6,19 @@
meteor-base@1.4.0 # Packages every Meteor app needs to have
mobile-experience@1.0.5 # Packages for a great mobile UX
-mongo@1.6.0 # The database Meteor supports right now
+mongo@1.6.2 # The database Meteor supports right now
blaze-html-templates@1.0.4 # Compile .html files into Meteor Blaze views
reactive-var@1.0.11 # Reactive variable for tracker
-reactive-dict@1.2.1 # ???
+reactive-dict@1.3.0 # ???
tracker@1.2.0 # Meteor's client-side reactive programming library
tomwasd:history-polyfill # Adds IE 8/9 support for HTML5 history.
email@1.2.3 # Adds the Meteor/Email package for sending lost password emails
-standard-minifier-css@1.5.2 # CSS minifier run for production mode
-standard-minifier-js@2.4.0 # JS minifier run for production mode
+standard-minifier-css@1.5.3 # CSS minifier run for production mode
+standard-minifier-js@2.4.1 # JS minifier run for production mode
es5-shim@4.8.0 # ECMAScript 5 compatibility for older browsers.
poorvavyas:es6-shim
-ecmascript@0.12.3 # Enable ECMAScript2015+ syntax in app code
+ecmascript@0.12.4 # Enable ECMAScript2015+ syntax in app code
#accounts-ui
#accounts-base
@@ -61,8 +61,8 @@ 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.
ostrio:logger
ostrio:loggermongo
-dynamic-import@0.5.0
+dynamic-import@0.5.1
markdown@1.0.12
wcrisman:jquery-custom-scrollbar
-underscore
+underscore@1.0.10
meteorhacks:aggregate # Allows databaseName.aggragate(pipeline) calls the exact same way you would on the command line in the mongo tool.
diff --git a/.meteor/release b/.meteor/release
index 2299ae7..97064e1 100644
--- a/.meteor/release
+++ b/.meteor/release
@@ -1 +1 @@
-METEOR@1.8.0.1
+METEOR@1.8.1
diff --git a/.meteor/versions b/.meteor/versions
index 7a0cb6a..424b559 100644
--- a/.meteor/versions
+++ b/.meteor/versions
@@ -1,4 +1,4 @@
-accounts-base@1.4.3
+accounts-base@1.4.4
accounts-password@1.5.1
alanning:roles@1.2.16
aldeed:collection2@2.10.0
@@ -9,10 +9,10 @@ aldeed:simple-schema@1.5.4
aldeed:template-extension@4.1.0
allow-deny@1.1.0
arillo:flow-router-helpers@0.5.2
-autoupdate@1.5.0
-babel-compiler@7.2.4
+autoupdate@1.6.0
+babel-compiler@7.3.4
babel-runtime@1.3.0
-base64@1.0.11
+base64@1.0.12
binary-heap@1.0.11
blaze@2.3.3
blaze-html-templates@1.1.2
@@ -27,18 +27,18 @@ ddp@1.4.0
ddp-client@2.3.3
ddp-common@1.4.0
ddp-rate-limiter@1.0.7
-ddp-server@2.2.0
+ddp-server@2.3.0
deps@1.0.12
diff-sequence@1.1.1
dynamic-import@0.5.1
-ecmascript@0.12.4
+ecmascript@0.12.7
ecmascript-runtime@0.7.0
ecmascript-runtime-client@0.8.0
ecmascript-runtime-server@0.7.1
ejson@1.1.0
email@1.2.3
es5-shim@4.8.0
-fetch@0.1.0
+fetch@0.1.1
fortawesome:fontawesome@4.7.0
geojson-utils@1.0.10
hot-code-push@1.0.4
@@ -58,7 +58,7 @@ localstorage@1.2.0
logging@1.1.20
markdown@1.0.12
mdg:validation-error@0.2.0
-meteor@1.9.2
+meteor@1.9.3
meteor-base@1.4.0
meteorhacks:aggregate@1.3.0
meteorhacks:collection-utils@1.2.0
@@ -79,37 +79,37 @@ meteortoys:sub@4.0.0
meteortoys:throttle@4.0.0
meteortoys:toggle@4.0.0
meteortoys:toykit@4.0.2
-minifier-css@1.4.1
-minifier-js@2.4.0
+minifier-css@1.4.2
+minifier-js@2.4.1
minimongo@1.4.5
mizzao:bootboxjs@4.4.0
mobile-experience@1.0.5
mobile-status-bar@1.0.14
-modern-browsers@0.1.3
+modern-browsers@0.1.4
modules@0.13.0
modules-runtime@0.10.3
-momentjs:moment@2.23.0
-mongo@1.6.0
-mongo-decimal@0.1.0
+momentjs:moment@2.24.0
+mongo@1.6.3
+mongo-decimal@0.1.1
mongo-dev-server@1.1.0
mongo-id@1.0.7
mongo-livedata@1.0.12
msavin:jetsetter@4.0.0
msavin:mongol@4.0.1
npm-bcrypt@0.9.3
-npm-mongo@3.1.1
+npm-mongo@3.1.2
observe-sequence@1.0.16
ordered-dict@1.1.0
-ostrio:logger@2.0.7
-ostrio:loggermongo@2.0.4
+ostrio:logger@2.0.8
+ostrio:loggermongo@2.0.5
poorvavyas:es6-shim@0.21.1
promise@0.11.2
raix:eventemitter@0.1.3
random@1.1.0
rate-limit@1.0.9
-reactive-dict@1.2.1
+reactive-dict@1.3.0
reactive-var@1.0.11
-reload@1.2.0
+reload@1.3.0
retry@1.1.0
routepolicy@1.1.0
service-configuration@1.0.11
@@ -121,8 +121,8 @@ softwarerero:accounts-t9n@1.3.11
spacebars@1.0.15
spacebars-compiler@1.1.3
srp@1.0.12
-standard-minifier-css@1.5.2
-standard-minifier-js@2.4.0
+standard-minifier-css@1.5.3
+standard-minifier-js@2.4.1
stylus@2.513.14
templating@1.3.2
templating-compiler@1.3.3
@@ -137,6 +137,6 @@ useraccounts:core@1.14.2
useraccounts:flow-routing@1.14.2
useraccounts:unstyled@1.14.2
wcrisman:jquery-custom-scrollbar@3.0.0
-webapp@1.7.2
+webapp@1.7.4
webapp-hashing@1.0.9
zimme:active-route@2.3.2
diff --git a/client/main.styl b/client/main.styl
index e027125..375ca43 100644
--- a/client/main.styl
+++ b/client/main.styl
@@ -187,4 +187,5 @@ body
@import "../imports/ui/Workers.import.styl"
@import "../imports/ui/Graphs.import.styl"
@import "../imports/ui/Reports.import.styl"
+@import "../imports/ui/Label.import.styl"
@import "../imports/ui/TestList.import.styl"
\ No newline at end of file
diff --git a/imports/api/Measure.js b/imports/api/Measure.js
index 847f104..c4c57de 100644
--- a/imports/api/Measure.js
+++ b/imports/api/Measure.js
@@ -3,7 +3,7 @@ import { Mongo } from 'meteor/mongo';
import { check } from 'meteor/check';
import {SimpleSchema} from 'meteor/aldeed:simple-schema';
-Measures = new Mongo.Collection('Measures');
+let Measures = new Mongo.Collection('Measures');
Measures.attachSchema(new SimpleSchema({
name: {
type: String,
diff --git a/imports/api/Reports.js b/imports/api/Reports.js
index 93f222b..3ff9c25 100644
--- a/imports/api/Reports.js
+++ b/imports/api/Reports.js
@@ -2,17 +2,18 @@ import { Meteor } from 'meteor/meteor';
if(Meteor.isServer) {
WebApp.connectHandlers.use("/reports/AnnualTotals", (req, res, next) => {
+ const separator = ";";
try {
let result = Meteor.collections.Sales.aggregate([{$group: {_id: {$substr: ['$date', 0, 4]}, total: {$sum: {$multiply: ["$price", "$amount"]}}}}]);
result.toArray().then(function(result) {
res.writeHead(200, {'Content-Type': 'text/csv'});
- res.write("Year,Sales Total\n");
+ res.write("Year" + separator + "Sales Total ($)\n");
for(let i = 0; i < result.length; i++) {
res.write(result[i]._id);
- res.write(",");
+ res.write(separator);
res.write("" + result[i].total);
res.write("\n");
}
@@ -25,13 +26,14 @@ if(Meteor.isServer) {
}
});
WebApp.connectHandlers.use("/reports/MonthlyTotals", (req, res, next) => {
+ const separator = ";";
try {
let result = Meteor.collections.Sales.aggregate([{$group: {_id: {$substr: ['$date', 0, 6]}, total: {$sum: {$multiply: ["$price", "$amount"]}}}}]);
result.toArray().then(function(result) {
res.writeHead(200, {'Content-Type': 'text/csv'});
- res.write("Date,Sales Total\n");
+ res.write("Date" + separator + "Sales Total ($)\n");
result.sort(function(a, b) {
return parseInt(a._id) - parseInt(b._id);
@@ -39,7 +41,7 @@ if(Meteor.isServer) {
for(let i = 0; i < result.length; i++) {
res.write(result[i]._id.substr(4, 2) + "/" + result[i]._id.substr(0, 4));
- res.write(",");
+ res.write(separator);
res.write("" + result[i].total);
res.write("\n");
}
@@ -51,7 +53,72 @@ if(Meteor.isServer) {
res.end();
}
});
+ WebApp.connectHandlers.use("/reports/AnnualSaleCountsByMeasure", (req, res, next) => {
+ const separator = ";";
+ try {
+ let result = Meteor.collections.Sales.aggregate([{
+ $group: {
+ _id: {$concat: [{$substr: ['$date', 0, 4]}, "-", "$measureId"]},
+ measureId: {$first: "$measureId"},
+ year: {$first: {$substr: ['$date', 0, 4]}},
+ count: {$sum: "$amount"},
+ total: {$sum: {$multiply: ["$price", "$amount"]}}
+ }
+ }]);
+
+ result.toArray().then(function(result) {
+ let totalByYear = {};
+
+ //Create a map of maps: year -> measure id -> sales count.
+ for(let next of result) {
+ //Get the map of totals by product for the year.
+ let totalByMeasure = totalByYear[next.year];
+ //Create the map if necessary.
+ if(totalByMeasure === undefined) totalByMeasure = totalByYear[next.year] = {};
+
+ totalByMeasure[next.measureId] = {count: next.count, total: next.total};
+ }
+
+ //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();
+
+ //Collect the years in ascending oder.
+ let years = Object.keys(totalByYear).sort(function(a, b) {return parseInt(a) - parseInt(b);});
+
+ res.writeHead(200, {'Content-Type': 'text/csv'});
+
+ res.write("Year" + separator + "Measure" + separator + "Sales Count" + separator + "Sales Total ($)\n");
+
+ result.sort(function(a, b) {
+ return parseInt(a._id) - parseInt(b._id);
+ });
+
+ for(let year of years) {
+ for(let measure of measures) {
+ let totals = totalByYear[year][measure._id];
+
+ if(totals) {
+ res.write(year);
+ res.write(separator);
+ res.write(measure.name);
+ res.write(separator);
+ res.write("" + totals.count);
+ res.write(separator);
+ res.write("" + totals.total);
+ res.write("\n");
+ }
+ }
+ }
+
+ res.end();
+ });
+ } catch(err) {
+ console.log(err);
+ res.end();
+ }
+ });
WebApp.connectHandlers.use("/reports/TagTotals", (req, res, next) => {
+ const separator = ";";
try {
//Aggregate all the sales by product id & year, then later create a map between products and tags to create tag totals.
let result = Meteor.collections.Sales.aggregate([{
@@ -111,7 +178,7 @@ if(Meteor.isServer) {
//Iterate over the years and add them to the headers.
for(let year of years) {
- res.write("," + year);
+ res.write(separator + year);
}
res.write('\n');
@@ -135,7 +202,7 @@ if(Meteor.isServer) {
if(productAnnualTotal) annualTotal += productAnnualTotal;
}
- res.write("," + annualTotal);
+ res.write(separator + annualTotal);
}
res.write('\n');
@@ -201,7 +268,7 @@ if(Meteor.isServer) {
//Iterate over the years and add them to the headers.
for(let year of years) {
- res.write(separator + year + " Count" + separator + year + " Total");
+ res.write(separator + year + " Count" + separator + year + " Total ($)");
}
res.write('\n');
diff --git a/imports/startup/client/routes.js b/imports/startup/client/routes.js
index f566fca..f187434 100644
--- a/imports/startup/client/routes.js
+++ b/imports/startup/client/routes.js
@@ -116,6 +116,13 @@ pri.route('/graphTest', {
BlazeLayout.render('Body', {content: 'GraphTest'});
}
});
+pri.route('/labels', {
+ name: 'Labels',
+ action: function(params, queryParams) {
+ require("/imports/ui/Label.js");
+ BlazeLayout.render('Body', {content: 'LabelMaker'});
+ }
+});
pri.route('/testList', {
name: 'TestList',
action: function(params, queryParams) {
diff --git a/imports/ui/Label.html b/imports/ui/Label.html
new file mode 100644
index 0000000..e056112
--- /dev/null
+++ b/imports/ui/Label.html
@@ -0,0 +1,31 @@
+
+
+
+