2017-01-15 11:33:37 -08:00
import './Production.html' ;
2019-10-07 15:51:50 -07:00
let QUERY _LIMIT = 100 ;
let QUERY _LIMIT _INCREMENT = 100 ;
let PREFIX = "Production." ;
Tracker . autorun ( function ( ) {
//Meteor.subscribe("batches");
Meteor . subscribe ( "workers" ) ;
Meteor . subscribe ( "products" ) ;
Meteor . subscribe ( "measures" ) ;
} ) ;
Template . Production . onCreated ( function ( ) {
Session . set ( PREFIX + "displayNew" , false ) ; //Whether the new dialog is inlined in the table and visible.
Session . set ( PREFIX + "sortOption" , 'date' ) ; //Allows us to sort the results of the batch query by batch attribute.
Session . set ( PREFIX + 'skipCount' , 0 ) ; //Allows us to page through the results of the batch query. Currently not used.
Session . set ( PREFIX + 'batchCount' , 0 ) ; //A count of all batches in the system (that fit our current query). Useful for paging and dynamic loading.
Session . set ( PREFIX + "queryLimit" , QUERY _LIMIT ) ;
Session . set ( PREFIX + "showDeleted" , false ) ;
Session . set ( PREFIX + "editedId" , undefined ) ;
Tracker . autorun ( function ( ) {
let sortOption = Session . get ( PREFIX + "sortOption" ) ;
let sort = sortOption == 'createdAt' ? { createdAt : - 1 } : { date : - 1 , createdAt : - 1 } ;
//let showOnlyComments = Session.get(PREFIX + "showOnlyComments"); //Not needed here. Shows how to limit the query to only records with certain features.
let query = _ . clone ( Session . get ( PREFIX + 'searchQuery' ) ) ;
//if(showOnlyComments) {
// if(!query) query = {};
// query.comment = {$exists: true};
//}
if ( ! Session . get ( PREFIX + "showDeleted" ) ) {
if ( ! query ) query = { } ;
query . deletedAt = { $exists : false } ;
}
Template . Production . batchesSubscription = Meteor . subscribe ( "batches" , query , sort , QUERY _LIMIT , Session . get ( PREFIX + 'skipCount' ) ) ;
Session . set ( PREFIX + 'batchCount' , Meteor . call ( 'getBatchCount' , Session . get ( PREFIX + 'searchQuery' ) ) ) ;
} ) ;
} ) ;
Template . Production . onDestroyed ( function ( ) {
if ( Template . Production . batchSubscription ) {
Template . Production . batchSubscription . stop ( ) ;
}
} ) ;
Template . Production . onRendered ( function ( ) {
$ ( ".tableContainer" ) . mCustomScrollbar ( {
scrollButtons : { enable : true } ,
theme : "light-thick" ,
scrollbarPosition : "outside" ,
scrollEasing : "linear"
} ) ;
} ) ;
Template . Production . helpers ( {
displayNew : function ( ) {
return Session . get ( PREFIX + "displayNew" ) ;
} ,
batches : function ( ) {
let sortOption = Session . get ( PREFIX + "sortOption" ) ;
return Meteor . collections . Batches . find ( { } , { sort : ( sortOption == 'createdAt' ? { createdAt : - 1 } : { date : - 1 , createdAt : - 1 } ) } ) ;
} ,
disableLoadMore : function ( ) {
return Session . get ( PREFIX + 'batchCount' ) - ( Session . get ( PREFIX + 'skipCount' ) || 0 ) - Session . get ( PREFIX + "queryLimit" ) <= 0 ;
} ,
showDeletedSelected : function ( ) {
return ( Session . get ( PREFIX + "showDeleted" ) ) ? "selected" : "" ;
}
} ) ;
Template . Production . events ( {
'click .loadMoreLink' : function ( event , template ) {
event . preventDefault ( ) ;
Session . set ( PREFIX + 'queryLimit' , Session . get ( PREFIX + "queryLimit" ) + QUERY _LIMIT _INCREMENT ) ;
} ,
'click .newButton' : function ( event , template ) {
if ( template . $ ( '.newButton' ) . hasClass ( 'active' ) ) {
Session . set ( PREFIX + 'displayNew' , false ) ;
}
else {
Session . set ( PREFIX + 'displayNew' , true ) ;
Session . set ( PREFIX + "editedId" , undefined ) ; //Clear the edited product so that only one editor is open at a time.
}
template . $ ( '.newButton' ) . toggleClass ( 'active' ) ;
} ,
'click .showDeletedButton' : function ( event , template ) {
Session . set ( PREFIX + "showDeleted" , ! Session . get ( PREFIX + "showDeleted" ) ) ; //Toggle the display of deleted production.
}
} ) ;
Template . Batch . onCreated ( function ( ) {
} ) ;
Template . Batch . onRendered ( function ( ) {
} ) ;
Template . Batch . helpers ( {
hasLabelsClass : function ( ) {
return this . hasLabels === true ? "hasLabels" : "noLabels" ;
} ,
name : function ( ) {
let product = Meteor . collections . Products . findOne ( { _id : this . productId } ) ;
let measure = Meteor . collections . Measures . findOne ( { _id : this . measureId } ) ;
return product . name + " (" + measure . name + ")" ;
} ,
date : function ( ) {
return moment ( this . date , "YYYYMMDD" ) . format ( "MM/DD/YYYY" ) ;
} ,
cook : function ( ) {
let worker = Meteor . collections . Workers . findOne ( { _id : this . cookId } ) ;
return worker . name ;
} ,
canner : function ( ) {
let worker = Meteor . collections . Workers . findOne ( { _id : this . cannerId } ) ;
return worker . name ;
} ,
editing : function ( ) {
let editedId = Session . get ( PREFIX + "editedId" ) ;
return editedId && editedId . toString ( ) === this . _id . toString ( ) ;
} ,
getRowClass : function ( ) {
return this . deletedAt ? "deleted" : "" ;
} ,
isDeleted : function ( ) {
return this . deletedAt ;
2020-01-16 09:31:12 -08:00
} ,
jdate : function ( ) {
return moment ( this . date , "YYYYMMDD" ) . format ( "YYDDDD" ) ;
2019-10-07 15:51:50 -07:00
}
} ) ;
Template . Batch . events ( {
"click .hasLabels" : function ( event , template ) {
Meteor . call ( 'setBatchHasLabels' , this . _id , ! ( this . hasLabels === true ) , function ( error , result ) {
if ( error ) sAlert . error ( error ) ;
} ) ;
} ,
"click .actionEdit" : function ( event , template ) {
Session . set ( PREFIX + "editedId" , this . _id ) ;
Session . set ( PREFIX + 'displayNew' , false ) ; //Ensure the new editor is closed.
template . parentTemplate ( ) . $ ( '.newButton' ) . removeClass ( 'active' ) ;
} ,
"click .actionDelete" : function ( event , template ) {
Meteor . call ( 'deleteBatch' , this . _id , function ( error , result ) {
if ( error ) sAlert . error ( error ) ;
else sAlert . success ( "Production Batch Deleted" ) ;
} ) ;
} ,
'click .actionUndelete' : function ( event , template ) {
Meteor . call ( 'undeleteBatch' , this . _id , function ( error , result ) {
if ( error ) sAlert . error ( error ) ;
else sAlert . success ( "Production Batch No Longer Deleted" ) ;
} ) ;
}
} ) ;
Template . BatchEditor . onCreated ( function ( ) {
} ) ;
Template . BatchEditor . onRendered ( function ( ) {
2020-01-16 09:31:12 -08:00
//Not working????
//this.$('.editorForm').validator();
2019-10-07 15:51:50 -07:00
} ) ;
Template . BatchEditor . helpers ( {
name : function ( ) {
let product = Meteor . collections . Products . findOne ( { _id : this . productId } ) ;
let measure = Meteor . collections . Measures . findOne ( { _id : this . measureId } ) ;
return ( product ? product . name : "" ) + " (" + ( measure ? measure . name : "" ) + ")" ;
} ,
date : function ( ) {
return moment ( this . date , "YYYYMMDD" ) . format ( "MM/DD/YYYY" ) ;
} ,
cook : function ( ) {
let worker = Meteor . collections . Workers . findOne ( { _id : this . cookId } ) ;
return worker . name ;
} ,
canner : function ( ) {
let worker = Meteor . collections . Workers . findOne ( { _id : this . cannerId } ) ;
return worker . name ;
}
} ) ;
Template . BatchEditor . events ( {
'click .editorCancel' : function ( event , template ) {
Session . set ( PREFIX + "editedId" , undefined ) ;
} ,
2020-01-16 09:31:12 -08:00
'click .editorApply' : function ( event , template ) {
//template.$('.editorForm').data('bs.validator').validate(function(isValid) {
// if(isValid) {
let id = template . data . _id ;
let amount = parseInt ( template . $ ( 'input.amount' ) . val ( ) ) ;
let comment = template . $ ( '#batchEditorComment' ) . val ( ) ;
2019-10-07 15:51:50 -07:00
2020-01-16 09:31:12 -08:00
console . log ( id + " " + amount + " " + comment ) ;
if ( Number . isInteger ( amount ) && amount > 0 ) {
Meteor . call ( 'updateBatch' , id , amount , comment , function ( error ) {
if ( error ) sAlert . error ( "Failed to update the batch!\n" + error ) ;
else {
sAlert . success ( "Production batch updated." ) ;
Session . set ( PREFIX + "editedId" , undefined ) ;
}
} ) ;
}
else {
sAlert . error ( "Amount must be a number greater than zero." ) ;
}
// }
//});
2019-10-07 15:51:50 -07:00
}
} ) ;
Template . BatchNew . onCreated ( function ( ) {
this . selectedProduct = new ReactiveVar ( ) ;
this . selectedCook = new ReactiveVar ( ) ;
this . selectedCanner = new ReactiveVar ( ) ;
} ) ;
Template . BatchNew . onRendered ( function ( ) {
this . $ ( '.insertForm' ) . validator ( ) ;
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="cook"]' ) . buildCombo ( { cursor : Meteor . collections . Workers . find ( { } ) , selection : this . selectedCook , textAttr : 'name' , listClass : 'comboList' } ) ;
this . $ ( '[name="canner"]' ) . buildCombo ( { cursor : Meteor . collections . Workers . find ( { } ) , selection : this . selectedCanner , textAttr : 'name' , listClass : 'comboList' } ) ;
this . $ ( 'input[name="product"]' ) . focus ( ) ;
} ) ;
Template . BatchNew . helpers ( {
//products: function() {
// return Meteor.collections.Products.find({});
//},
//productSelected: function() {
// let product = this;
// let batch = Template.parentData();
//
// return batch.productId === product._id ? "selected" : "";
//},
productMeasures : function ( ) {
//Show only the list allowed by the product
let product = Template . instance ( ) . selectedProduct . get ( ) ;
if ( product ) {
let measures = Meteor . collections . Measures . find ( { } ) . fetch ( ) ;
let measuresById = { } ;
let allowedMeasureIds = product . measures ;
let allowedMeasures = [ ] ;
//Create a hashmap of measures by their id.
for ( let measure of measures ) measuresById [ measure . _id . toString ( ) ] = measure ;
//Create a list of measures allowed for the product.
for ( let measureId of allowedMeasureIds ) {
allowedMeasures . push ( measuresById [ measureId . toString ( ) ] ) ;
}
return allowedMeasures ;
}
else return [ ] ;
} ,
today : ( ) => {
return moment ( ) . format ( "YYYY-MM-DD" ) ;
}
} ) ;
Template . BatchNew . events ( {
'change input[name="date"]' : function ( event , template ) {
template . selectedDate . set ( moment ( event . target . value , "YYYY-MM-DD" ) . toDate ( ) ) ;
} ,
'click .editorCancel' : function ( event , template ) {
Session . set ( PREFIX + "editedId" , undefined ) ;
} ,
'click .editorApply' : function ( event , template ) {
event . preventDefault ( ) ;
template . $ ( '.insertForm' ) . data ( 'bs.validator' ) . validate ( function ( isValid ) {
if ( isValid ) {
let batches = [ ] ;
let insertMeasure = template . $ ( ".insertMeasure" ) ;
let batch = {
date : ~ ~ ( moment ( template . find ( "[name='date']" ) . value , "YYYY-MM-DD" ) . format ( "YYYYMMDD" ) ) , // Note: ~~ performs a bitwise not which is a fast method of converting a string to a number.
productId : template . selectedProduct . get ( ) . _id ,
cookId : template . selectedCook . get ( ) . _id ,
cannerId : template . selectedCanner . get ( ) . _id ,
comment : template . $ ( '.comment' ) . val ( )
} ;
//Iterate over the measures for the batch (based on the product chosen) and amounts.
for ( let next = 0 ; next < insertMeasure . length ; next ++ ) {
let nextMeasure = $ ( insertMeasure [ next ] ) ;
let measureId = nextMeasure . find ( ".measureId" ) . val ( ) ;
let amount = parseFloat ( nextMeasure . find ( ".amount" ) . val ( ) ) ;
if ( amount > 0 ) {
let next = _ . clone ( batch ) ;
next . measureId = measureId ;
next . amount = amount ;
batches . push ( next ) ;
}
}
Meteor . call ( 'insertBatches' , batches , function ( error ) {
if ( error ) sAlert . error ( "Failed to insert the batch!\n" + error ) ;
else {
let productCombo = template . $ ( "input[name='product']" ) ;
let measureFields = template . $ ( ".amount" ) ;
sAlert . success ( "Production batches created." ) ;
//Clear the measure quantity fields so the user can enter another sale without the quantities already set.
measureFields . val ( 0 ) ;
//Set the focus to the product field of the form.
//productCombo.focus();
//Clear the product since it is highly unlikely the same product will be added twice for the same date.
productCombo . val ( "" ) ;
Session . set ( PREFIX + "displayNew" , false ) ;
}
} ) ;
}
} ) ;
}
} ) ;
Template . InsertBatchMeasure . onCreated ( function ( ) {
let _this = this ;
this . amount = new ReactiveVar ( 0 ) ;
} ) ;
Template . InsertBatchMeasure . onRendered ( function ( ) {
} ) ;
Template . InsertBatchMeasure . helpers ( {
amount : function ( ) {
return Template . instance ( ) . amount . get ( ) ;
}
} ) ;
Template . InsertBatchMeasure . events ( {
'change .amount' : function ( event , template ) {
template . amount . set ( parseFloat ( $ ( event . target ) . val ( ) ) ) ;
} ,
'focus input[name="amount"]' : function ( event , template ) {
//See http://stackoverflow.com/questions/3150275/jquery-input-select-all-on-focus
//Handle selecting the text in the field on receipt of focus.
let $this = $ ( this )
. one ( 'mouseup.mouseupSelect' , function ( ) {
$this . select ( ) ;
return false ;
} )
. one ( 'mousedown' , function ( ) {
// compensate for untriggered 'mouseup' caused by focus via tab
$this . off ( 'mouseup.mouseupSelect' ) ;
} )
. select ( ) ;
}
} ) ;
Template . BatchSearch . onCreated ( function ( ) {
} ) ;
Template . BatchSearch . onRendered ( function ( ) {
} ) ;
Template . BatchSearch . helpers ( {
searchValue : function ( ) {
let searchFields = Session . get ( PREFIX + 'searchFields' ) ;
return ( searchFields && searchFields [ this . columnName ] ) ? searchFields [ this . columnName ] : '' ;
}
} ) ;
Template . BatchSearch . events ( {
"keyup .searchInput" : _ . throttle ( function ( event , template ) {
let searchQuery = Session . get ( PREFIX + 'searchQuery' ) || { } ;
let searchFields = Session . get ( PREFIX + 'searchFields' ) || { } ;
let searchValue = template . $ ( event . target ) . val ( ) ;
if ( searchValue ) {
if ( this . number ) searchValue = parseFloat ( searchValue ) ;
// A collection name will be provided if there is a related table of data that will contain the text provided and will map to an ID that is then searched for in the current table of data.
// For example we are displaying a table of Sales which has the ID of a Product. The Product table has a Name field and the search box searches for Product Names. The ID's of the Products found should be used to filter the Sales by Product ID.
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 ) ;
Session . set ( PREFIX + 'skipCount' , 0 ) ; //Reset the paging of the results.
Session . set ( PREFIX + "queryLimit" , QUERY _LIMIT ) ; //Reset the query limit in case we loaded more
} , 500 )
} ) ;
Template . BatchDateRangeSearch . helpers ( {
startDate : function ( ) {
let searchFields = Session . get ( PREFIX + 'searchFields' ) ;
let searchValue = ( searchFields && searchFields [ this . columnName ] ) ? searchFields [ this . columnName ] : { } ;
return searchValue . start ? moment ( searchValue . start . toString ( ) , "YYYYMMDD" ) . format ( "MM/DD/YYYY" ) : "" ;
} ,
endDate : function ( ) {
let searchFields = Session . get ( PREFIX + 'searchFields' ) ;
let searchValue = ( searchFields && searchFields [ this . columnName ] ) ? searchFields [ this . columnName ] : { } ;
return searchValue . end ? moment ( searchValue . end . toString ( ) , "YYYYMMDD" ) . format ( "MM/DD/YYYY" ) : "" ;
}
} ) ;
Template . BatchDateRangeSearch . events ( {
"change .searchDateStartInput" : function ( event , template ) { Template . DateRangeSearch . dateChanged ( true , event , template ) } ,
"keyup .searchDateStartInput" : _ . throttle ( function ( event , template ) { Template . DateRangeSearch . dateChanged ( true , event , template ) } , 500 ) ,
"change .searchDateEndInput" : function ( event , template ) { Template . DateRangeSearch . dateChanged ( false , event , template ) } ,
"keyup .searchDateEndInput" : _ . throttle ( function ( event , template ) { Template . DateRangeSearch . dateChanged ( false , event , template ) } , 500 )
} ) ;
Template . BatchDateRangeSearch . dateChanged = function ( isStart , event , template ) {
let searchQuery = Session . get ( PREFIX + 'searchQuery' ) || { } ;
let searchFields = Session . get ( PREFIX + 'searchFields' ) || { } ;
let searchValue = template . $ ( event . target ) . val ( ) ;
let columnName = template . data . columnName ;
if ( searchValue ) {
let search = searchQuery [ columnName ] ;
// Create a search object and attach it to the searchFields and searchQuery objects if needed.
if ( ! search ) {
search = { type : 'dateRange' } ;
searchFields [ columnName ] = searchQuery [ columnName ] = search ;
}
// Use moment to parse date and convert it to YYYYMMDD for searching the database.
searchValue = ~ ~ ( moment ( searchValue , searchValue . includes ( "-" ) ? "YYYY-MM-DD" : "MM/DD/YYYY" ) . format ( "YYYYMMDD" ) ) ; // Note: ~~ performs a bitwise not which is a fast method of converting a string to a number.
// Save the search ending date.
isStart ? search . start = searchValue : search . end = searchValue ;
}
else {
if ( searchQuery [ columnName ] ) {
// Remove columns from the search query whose values are empty so we don't bother the database with them.
if ( isStart ) {
delete searchQuery [ columnName ] . start ;
delete searchFields [ columnName ] . start ;
}
else {
delete searchQuery [ columnName ] . end ;
delete searchFields [ columnName ] . end ;
}
}
}
Session . set ( PREFIX + 'searchQuery' , searchQuery ) ;
Session . set ( PREFIX + 'searchFields' , searchFields ) ;
Session . set ( PREFIX + 'skipCount' , 0 ) ; //Reset the paging of the results.
Session . set ( PREFIX + "queryLimit" , QUERY _LIMIT ) ; //Reset the query limit in case we loaded more
} ;