import './Sales.html'; import '/imports/util/selectize/selectize.js' import ResizeSensor from '/imports/util/resize/ResizeSensor.js'; let QUERY_LIMIT = 20; let PREFIX = "Sales."; Meteor.subscribe("products"); Tracker.autorun(function() { Meteor.subscribe("sales", Session.get(PREFIX + 'searchQuery'), QUERY_LIMIT, Session.get(PREFIX + 'skipCount')); Session.set(PREFIX + 'saleCount', Meteor.call('getSalesCount', Session.get(PREFIX + 'searchQuery'))); }); Template.Sales.helpers({ sales: function() { return Meteor.collections.Sales.find({}, {sort: {date: -1, createdAt: -1}}); }, disablePrev: function() { return (Session.get(PREFIX + 'skipCount') || 0) == 0; }, disableNext: function() { return Session.get(PREFIX + 'saleCount') - (Session.get(PREFIX + 'skipCount') || 0) - QUERY_LIMIT <= 0; } }); Template.Sales.events({ 'click .prevButton': function(event, template) { if(!$(event.target).hasClass('disabled')) Session.set(PREFIX + 'skipCount', Math.max(0, (Session.get(PREFIX + 'skipCount') || 0) - QUERY_LIMIT)); }, 'click .nextButton': function(event, template) { if(!$(event.target).hasClass('disabled')) Session.set(PREFIX + 'skipCount', (Session.get(PREFIX + 'skipCount') || 0) + QUERY_LIMIT); } }); Template.Sale.onCreated(function() { }); Template.Sale.helpers({ measureName: function(id) { return Meteor.collections.Measures.findOne({_id: id}, {fields: {name: 1}}).name; }, venueName: function(id) { return Meteor.collections.Venues.findOne({_id: id}, {fields: {name: 1}}).name; }, productName: function(id) { return Meteor.collections.Products.findOne({_id: id}, {fields: {name: 1}}).name; }, formatDate: function(date) { return moment(date).format("MM/DD/YYYY (w)"); }, formatPrice: function(price) { return price.toLocaleString("en-US", {style: 'currency', currency: 'USD', minimumFractionDigits: 2}); }, formatTotalPrice: function(price, amount) { return (price * amount).toLocaleString("en-US", {style: 'currency', currency: 'USD', minimumFractionDigits: 2}); }, showTotalPrice: function(amount) { return amount > 1; } }); Template.Sale.events({ "click .saleRemove": function(event, template) { let _this = this; bootbox.confirm({ message: "Delete the sale?", buttons: {confirm: {label: "Yes", className: 'btn-success'}, cancel: {label: "No", className: "btn-danger"}}, callback: function(result) { if(result) { // Meteor.collections.Sales.remove(_this._id); Meteor.call('deleteSale', _this._id); } } }); } }); Template.SaleSearch.helpers({ searchValue: function() { let searchFields = Session.get(PREFIX + 'searchFields'); return (searchFields && searchFields[this.columnName]) ? searchFields[this.columnName] : ''; } }); Template.SaleSearch.events({ "keyup .searchInput": _.throttle(function(event, template) { let searchQuery = Session.get(PREFIX + 'searchQuery') || {}; let searchFields = Session.get(PREFIX + 'searchFields') || {}; let searchValue = template.$('.searchInput').val(); if(searchValue) { if(this.number) searchValue = parseFloat(searchValue); if(this.collection) { let ids = Meteor.collections[this.collection].find({[this.collectionQueryColumnName]: {$regex: searchValue, $options: 'i'}}, {fields: {[this.collectionResultColumnName]: 1}}).fetch(); //Convert the ids to an array of ids instead of an array of objects containing an id. for(let i = 0; i < ids.length; i++) {ids[i] = ids[i]._id;} searchQuery[this.columnName] = {$in: ids}; searchFields[this.columnName] = searchValue; } else { searchFields[this.columnName] = searchQuery[this.columnName] = searchValue; } } else { //Remove columns from the search query whose values are empty so we don't bother the database with them. delete searchQuery[this.columnName]; delete searchFields[this.columnName]; } Session.set(PREFIX + 'searchQuery', searchQuery); Session.set(PREFIX + 'searchFields', searchFields); }, 500) }); Template.InsertSale.onCreated(function() { // $('#insertSale').validator(); // $('#insertSale').data('bs.validator'); // this.products = new ReactiveVar([]); this.selectedDate = new ReactiveVar(); this.selectedProduct = new ReactiveVar(); this.selectedVenue = new ReactiveVar(); }); Template.InsertSale.onRendered(function() { this.$('.insertSaleForm').validator(); // this.$('[name="product"]'). // this.autorun(function() { // this.$('[name="product"]').buildCombo(Meteor.collections.Products.find({}).fetch(), {textAttr: 'name', listClass: 'comboList'}); // }); //TODO: Highlight deactivated products in combo //TODO: Default the price for each size product based on the date. this.$('[name="product"]').buildCombo({cursor: Meteor.collections.Products.find({$or: [{hidden: false}, {hidden: {$exists:false}}]}), selection: this.selectedProduct, textAttr: 'name', listClass: 'comboList', getClasses: function(data) { return (data && data.deactivated) ? "deactivated" : ""; }}); this.$('[name="venue"]').buildCombo({cursor: Meteor.collections.Venues.find({}), selection: this.selectedVenue, textAttr: 'name', listClass: 'comboList'}); // this.autorun(function(){ // this.products.set(Meteor.collections.Products.find({})); // }.bind(this)); }); Template.InsertSale.events({ 'change input[name="product"]': function(event, template) { let selectedId = template.$('input[name="product"]').val(); let selected = Meteor.collections.Products.findOne(selectedId); template.selectedProduct.set(selected); }, 'change input[name="date"]': function(event, template) { template.selectedDate.set(moment(event.target.value, "YYYY-MM-DD").toDate()); }, 'click input[type="submit"]': function(event, template) { event.preventDefault(); template.$('.insertSaleForm').data('bs.validator').validate(function(isValid) { if(isValid) { let sales = []; let sale = { date: moment(template.find("[name='date']").value, "YYYY-MM-DD").toDate(), productId: template.selectedProduct.get()._id, venueId: template.selectedVenue.get()._id }; let insertSaleMeasures = template.$(".insertSaleMeasure"); for(let next = 0; next < insertSaleMeasures.length; next++) { let nextMeasure = $(insertSaleMeasures[next]); let measureId = nextMeasure.find(".measureId").val(); let price = parseFloat(nextMeasure.find(".price").val()).toFixed(2); let amount = parseFloat(nextMeasure.find(".amount").val()).toFixed(2); if(amount > 0) { let nextSale = _.clone(sale); nextSale.measureId = measureId; nextSale.price = price; nextSale.amount = amount; sales.push(nextSale); } } for(let index = 0; index < sales.length; index++) { let next = sales[index]; //console.log("Inserting: " + JSON.stringify(next)); Meteor.call('insertSale', next, function(error) { if(error) sAlert.error("Failed to insert the sale!\n" + error); else sAlert.success("Sale Created"); }); } } }); } }); Template.InsertSale.helpers({ products: function() { return [{label: "Hermies", value: 1}, {label: "Ralfe", value: 2}, {label: "Bob", value: 3}]; }, productMeasures: function() { let product = Template.instance().selectedProduct.get(); let result = product ? product.measures : []; for(let i = 0; i < result.length; i++) { result[i] = Meteor.collections.Measures.findOne(result[i]); } // if(product) console.log("Found " + result.length + " measures for the product " + product.name); // else console.log("No product!"); return result; }, venues: function() { return Meteor.collections.Venues.find({}); } }); Template.InsertSaleMeasure.onCreated(function() { let _this = this; this.price = new ReactiveVar(0); this.amount = new ReactiveVar(0); Tracker.autorun(function() { let date = _this.parentTemplate().selectedDate.get(); let prices = _this.parentTemplate().selectedProduct.get().prices; let priceData; let price = 0; if(prices) priceData = prices[_this.data._id]; //If this product has pricing data for the given measure, then either use the price, or the previousPrice (if there is one and the effectiveDate is after the sale date). if(priceData) { if(priceData.effectiveDate && date && moment(priceData.effectiveDate).isAfter(date)) price = priceData.previousPrice; else price = priceData.price } _this.price.set(price); }); }); Template.InsertSaleMeasure.events({ 'change .price': function(event, template) { template.price.set(parseFloat($(event.target).val())); }, 'change .amount': function(event, template) { template.amount.set(parseFloat($(event.target).val())); } }); Template.InsertSaleMeasure.helpers({ price: function() { return Template.instance().price.get().toFixed(2); }, total: function() { let template = Template.instance(); return (template.price.get() * template.amount.get()).toFixed(2); }, amount: function() { return Template.instance().amount.get(); } });