Started adding async calls for upgrading to Meteor 3.0. Numerous other fixes.

This commit is contained in:
2025-07-02 11:18:09 -07:00
parent e1216741d6
commit 2e99ad007c
32 changed files with 549 additions and 373 deletions

View File

@@ -1,21 +1,34 @@
import { Meteor } from 'meteor/meteor';
import { Mongo } from 'meteor/mongo';
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 Measures from "./Measure";
/**
* 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.
*/
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({
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.
label: "Date",
optional: false,
index: 1
//index: 1
},
timestamp: {
type: Date,
@@ -31,7 +44,7 @@ let SalesSchema = new SimpleSchema({
type: Number,
label: "Amount",
optional: false,
decimal: true
//decimal: true
},
price: {
type: Number,
@@ -39,28 +52,29 @@ let SalesSchema = new SimpleSchema({
optional: false,
min: 0,
exclusiveMin: true,
decimal: true
//decimal: true
},
measureId: {
type: String,
label: "Measure Id",
trim: false,
regEx: SimpleSchema.RegEx.Id,
index: 1
//index: 1
},
productId: {
type: String,
label: "Product Id",
trim: false,
regEx: SimpleSchema.RegEx.Id,
index: 1
//index: 1
},
venueId: {
type: String,
label: "Vendor Id",
trim: false,
regEx: SimpleSchema.RegEx.Id,
index: 1
//index: 1
// autoform: {
// type: 'relation',
// settings: {
@@ -280,11 +294,11 @@ if(Meteor.isServer) {
});
Meteor.methods({
getSalesCount: function(query) {
getSalesCount: async function(query) {
//TODO: Validate the query?
return Sales.find(query).count();
return await Sales.countDocuments(query);
},
insertSale: function(sale) {
insertSale: async function(sale) {
check(sale, {
date: Number, // TODO: Check that the format is YYYYMMDD
amount: Match.Where(function(x) {
@@ -308,21 +322,21 @@ if(Meteor.isServer) {
sale.weekOfYear = sale.timestamp.getWeek().toString();
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);
}, {bypassCollection2: true});
}
else throw new Meteor.Error(403, "Not authorized.");
},
deleteSale: function(id) {
deleteSale: async function(id) {
check(id, String);
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
Sales.remove(id);
await Sales.removeAsync(id);
}
else throw new Meteor.Error(403, "Not authorized.");
},
editSaleComment: function(id, comment) {
editSaleComment: async function(id, comment) {
check(id, String);
check(comment, String);
//Trim and convert empty comment to undefined.
@@ -333,19 +347,19 @@ if(Meteor.isServer) {
console.log("Changed comment of " + id + " to: " + 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);
});
}
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);
});
}
}
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(date, Number); // TODO: Check that the format is YYYYMMDD
check(venueId, String);
@@ -357,45 +371,45 @@ if(Meteor.isServer) {
let weekOfYear = timestamp.getWeek().toString();
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);
}, {bypassCollection2: true});
}
else throw new Meteor.Error(403, "Not authorized.");
},
countSales: function() {
countSales: async function() {
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.");
},
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])) {
// Remove either one or all of the duplicates of the Sale with the given ID.
if(justOne) {
let sale = Sales.findOne({isDuplicateOf: id});
let sale = await Sales.findOneAsync({isDuplicateOf: id});
if(sale) {
Sales.remove({_id: sale._id});
await Sales.removeAsync({_id: sale._id});
}
}
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])) {
// 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: ""}});
// 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])) {
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.
// 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(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);
}, {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) {
// Mark the next sale as a duplicate of the currently examined sale.
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);
}, {bypassCollection2: true});
duplicateCount++;
@@ -442,7 +456,7 @@ if(Meteor.isServer) {
if(sale.duplicateCount !== duplicateCount) {
// Update the sale's duplicate count.
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);
}, {bypassCollection2: true});
}
@@ -450,7 +464,7 @@ if(Meteor.isServer) {
else if(sale.duplicateCount) {
// Remove the duplicate count if it is set.
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);
}, {bypassCollection2: true});
}