2018-07-08 15:16:24 +02:00
var stockOverviewTable = $ ( '#stock-overview-table' ) . DataTable ( {
2018-05-12 16:15:28 +02:00
'order' : [ [ 3 , 'asc' ] ] ,
'columnDefs' : [
2019-01-05 16:27:26 +01:00
{ 'orderable' : false , 'targets' : 0 } ,
2020-01-03 14:18:56 +01:00
{ 'searchable' : false , "targets" : 0 } ,
2019-01-05 16:27:26 +01:00
{ 'visible' : false , 'targets' : 4 } ,
{ 'visible' : false , 'targets' : 5 } ,
{ 'visible' : false , 'targets' : 6 }
2018-05-12 16:15:28 +02:00
] ,
2018-07-08 15:16:24 +02:00
} ) ;
2019-01-05 14:27:40 +01:00
$ ( '#stock-overview-table tbody' ) . removeClass ( "d-none" ) ;
2019-03-04 17:43:12 +01:00
stockOverviewTable . columns . adjust ( ) . draw ( ) ;
2018-07-08 15:16:24 +02:00
2018-07-08 16:54:37 +02:00
$ ( "#location-filter" ) . on ( "change" , function ( )
2018-07-08 15:16:24 +02:00
{
2018-07-08 16:54:37 +02:00
var value = $ ( this ) . val ( ) ;
if ( value === "all" )
2018-07-08 15:16:24 +02:00
{
2018-07-08 16:54:37 +02:00
value = "" ;
}
2019-01-19 00:37:21 -07:00
2018-07-08 16:54:37 +02:00
stockOverviewTable . column ( 4 ) . search ( value ) . draw ( ) ;
} ) ;
2018-07-08 15:16:24 +02:00
2018-10-06 18:19:31 +02:00
$ ( "#product-group-filter" ) . on ( "change" , function ( )
{
var value = $ ( this ) . val ( ) ;
if ( value === "all" )
{
value = "" ;
}
2019-01-19 00:37:21 -07:00
2018-10-06 18:19:31 +02:00
stockOverviewTable . column ( 6 ) . search ( value ) . draw ( ) ;
} ) ;
2018-09-24 19:13:53 +02:00
$ ( "#status-filter" ) . on ( "change" , function ( )
{
var value = $ ( this ) . val ( ) ;
if ( value === "all" )
{
value = "" ;
}
// Transfer CSS classes of selected element to dropdown element (for background)
$ ( this ) . attr ( "class" , $ ( "#" + $ ( this ) . attr ( "id" ) + " option[value='" + value + "']" ) . attr ( "class" ) + " form-control" ) ;
2019-01-19 00:37:21 -07:00
2018-09-24 19:13:53 +02:00
stockOverviewTable . column ( 5 ) . search ( value ) . draw ( ) ;
} ) ;
$ ( ".status-filter-button" ) . on ( "click" , function ( )
{
var value = $ ( this ) . data ( "status-filter" ) ;
$ ( "#status-filter" ) . val ( value ) ;
$ ( "#status-filter" ) . trigger ( "change" ) ;
} ) ;
2019-10-15 19:59:14 +02:00
$ ( "#search" ) . on ( "keyup" , Delay ( function ( )
2018-07-08 16:54:37 +02:00
{
var value = $ ( this ) . val ( ) ;
if ( value === "all" )
{
value = "" ;
}
2019-01-19 00:37:21 -07:00
2018-07-08 16:54:37 +02:00
stockOverviewTable . search ( value ) . draw ( ) ;
2019-10-15 19:59:14 +02:00
} , 200 ) ) ;
2018-05-12 16:15:28 +02:00
$ ( document ) . on ( 'click' , '.product-consume-button' , function ( e )
{
2018-09-24 09:30:26 +02:00
e . preventDefault ( ) ;
2018-09-25 16:24:43 +02:00
// Remove the focus from the current button
// to prevent that the tooltip stays until clicked anywhere else
document . activeElement . blur ( ) ;
2018-11-24 19:40:50 +01:00
Grocy . FrontendHelpers . BeginUiBusy ( ) ;
2019-01-19 00:37:21 -07:00
2018-05-12 16:15:28 +02:00
var productId = $ ( e . currentTarget ) . attr ( 'data-product-id' ) ;
2018-05-13 08:42:45 +02:00
var consumeAmount = $ ( e . currentTarget ) . attr ( 'data-consume-amount' ) ;
2019-07-06 18:15:53 +02:00
var wasSpoiled = $ ( e . currentTarget ) . hasClass ( "product-consume-button-spoiled" ) ;
2018-05-12 16:15:28 +02:00
2019-07-06 18:15:53 +02:00
Grocy . Api . Post ( 'stock/products/' + productId + '/consume' , { 'amount' : consumeAmount , 'spoiled' : wasSpoiled } ,
2019-09-20 13:37:53 +02:00
function ( bookingResponse )
2018-05-12 16:15:28 +02:00
{
2019-01-19 14:51:51 +01:00
Grocy . Api . Get ( 'stock/products/' + productId ,
2018-08-07 20:11:08 +02:00
function ( result )
2018-05-13 08:42:45 +02:00
{
2019-12-19 12:48:36 -06:00
var toastMessage = _ _t ( 'Removed %1$s of %2$s from stock' , consumeAmount . toString ( ) + " " + _ _n ( consumeAmount , result . quantity _unit _stock . name , result . quantity _unit _stock . name _plural ) , result . product . name ) + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoStockTransaction(\'' + bookingResponse . transaction _id + '\')"><i class="fas fa-undo"></i> ' + _ _t ( "Undo" ) + '</a>' ;
2019-07-06 18:15:53 +02:00
if ( wasSpoiled )
{
toastMessage += " (" + _ _t ( "Spoiled" ) + ")" ;
}
2018-11-24 19:40:50 +01:00
Grocy . FrontendHelpers . EndUiBusy ( ) ;
2019-07-06 18:15:53 +02:00
toastr . success ( toastMessage ) ;
2018-08-07 20:11:08 +02:00
RefreshStatistics ( ) ;
2019-09-20 13:37:53 +02:00
RefreshProductRow ( productId ) ;
2018-08-07 20:11:08 +02:00
} ,
function ( xhr )
{
2018-11-24 19:40:50 +01:00
Grocy . FrontendHelpers . EndUiBusy ( ) ;
2018-08-07 20:11:08 +02:00
console . error ( xhr ) ;
}
) ;
2018-05-12 16:15:28 +02:00
} ,
function ( xhr )
{
2018-11-24 19:40:50 +01:00
Grocy . FrontendHelpers . EndUiBusy ( ) ;
2018-05-12 16:15:28 +02:00
console . error ( xhr ) ;
}
) ;
} ) ;
2018-08-04 14:25:32 +02:00
2018-11-17 19:39:37 +01:00
$ ( document ) . on ( 'click' , '.product-open-button' , function ( e )
{
e . preventDefault ( ) ;
// Remove the focus from the current button
// to prevent that the tooltip stays until clicked anywhere else
document . activeElement . blur ( ) ;
2018-11-24 19:40:50 +01:00
Grocy . FrontendHelpers . BeginUiBusy ( ) ;
2019-01-19 00:37:21 -07:00
2018-11-17 19:39:37 +01:00
var productId = $ ( e . currentTarget ) . attr ( 'data-product-id' ) ;
var productName = $ ( e . currentTarget ) . attr ( 'data-product-name' ) ;
var productQuName = $ ( e . currentTarget ) . attr ( 'data-product-qu-name' ) ;
2018-11-18 13:35:21 +01:00
var button = $ ( e . currentTarget ) ;
2018-11-17 19:39:37 +01:00
2019-01-19 14:51:51 +01:00
Grocy . Api . Post ( 'stock/products/' + productId + '/open' , { 'amount' : 1 } ,
2019-09-20 13:37:53 +02:00
function ( bookingResponse )
2018-11-17 19:39:37 +01:00
{
2019-01-19 14:51:51 +01:00
Grocy . Api . Get ( 'stock/products/' + productId ,
2018-11-17 19:39:37 +01:00
function ( result )
{
2018-11-18 13:35:21 +01:00
if ( result . stock _amount == result . stock _amount _opened )
{
button . addClass ( "disabled" ) ;
}
2018-11-24 19:40:50 +01:00
Grocy . FrontendHelpers . EndUiBusy ( ) ;
2019-12-19 12:48:36 -06:00
toastr . success ( _ _t ( 'Marked %1$s of %2$s as opened' , 1 + " " + productQuName , productName ) + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoStockTransaction(\'' + bookingResponse . transaction _id + '\')"><i class="fas fa-undo"></i> ' + _ _t ( "Undo" ) + '</a>' ) ;
2018-11-17 19:39:37 +01:00
RefreshStatistics ( ) ;
2019-09-20 13:37:53 +02:00
RefreshProductRow ( productId ) ;
2018-11-17 19:39:37 +01:00
} ,
function ( xhr )
{
2018-11-24 19:40:50 +01:00
Grocy . FrontendHelpers . EndUiBusy ( ) ;
2018-11-17 19:39:37 +01:00
console . error ( xhr ) ;
}
) ;
} ,
function ( xhr )
{
2018-11-24 19:40:50 +01:00
Grocy . FrontendHelpers . EndUiBusy ( ) ;
2018-11-17 19:39:37 +01:00
console . error ( xhr ) ;
}
) ;
} ) ;
2018-10-01 20:20:50 +02:00
$ ( document ) . on ( "click" , ".product-name-cell" , function ( e )
2018-09-30 23:22:17 +02:00
{
2018-10-22 19:28:59 +02:00
Grocy . Components . ProductCard . Refresh ( $ ( e . currentTarget ) . attr ( "data-product-id" ) ) ;
$ ( "#stockoverview-productcard-modal" ) . modal ( "show" ) ;
2018-09-30 23:22:17 +02:00
} ) ;
2018-08-04 14:25:32 +02:00
function RefreshStatistics ( )
{
2019-01-19 00:37:21 -07:00
Grocy . Api . Get ( 'stock' ,
2018-08-04 14:25:32 +02:00
function ( result )
{
var amountSum = 0 ;
result . forEach ( element => {
amountSum += parseInt ( element . amount ) ;
} ) ;
2019-05-02 20:20:18 +02:00
$ ( "#info-current-stock" ) . text ( _ _n ( result . length , '%s Product' , '%s Products' ) + ", " + _ _n ( amountSum , '%s Unit' , '%s Units' ) ) ;
2018-08-04 14:25:32 +02:00
} ,
function ( xhr )
{
console . error ( xhr ) ;
}
) ;
var nextXDays = $ ( "#info-expiring-products" ) . data ( "next-x-days" ) ;
2019-01-19 00:37:21 -07:00
Grocy . Api . Get ( 'stock/volatile?expiring_days=' + nextXDays ,
2018-08-04 14:25:32 +02:00
function ( result )
{
2019-05-02 20:20:18 +02:00
$ ( "#info-expiring-products" ) . text ( _ _n ( result . expiring _products . length , '%s product expires' , '%s products expiring' ) + ' ' + _ _n ( nextXDays , 'within the next day' , 'within the next %s days' ) ) ;
$ ( "#info-expired-products" ) . text ( _ _n ( result . expired _products . length , '%s product is already expired' , '%s products are already expired' ) ) ;
$ ( "#info-missing-products" ) . text ( _ _n ( result . missing _products . length , '%s product is below defined min. stock amount' , '%s products are below defined min. stock amount' ) ) ;
2018-08-04 14:25:32 +02:00
} ,
function ( xhr )
{
console . error ( xhr ) ;
}
) ;
}
RefreshStatistics ( ) ;
2019-09-20 13:37:53 +02:00
function RefreshProductRow ( productId )
{
productId = productId . toString ( ) ;
Grocy . Api . Get ( 'stock/products/' + productId ,
function ( result )
{
2019-09-27 08:30:08 +02:00
// Also refresh the parent product, if any
if ( result . product . parent _product _id !== null && ! result . product . parent _product _id . toString ( ) . isEmpty ( ) )
{
RefreshProductRow ( result . product . parent _product _id ) ;
}
2019-09-20 13:37:53 +02:00
var productRow = $ ( '#product-' + productId + '-row' ) ;
2019-09-27 08:12:37 +02:00
var expiringThreshold = moment ( ) . add ( $ ( "#info-expiring-products" ) . data ( "next-x-days" ) , "days" ) ;
2019-09-20 13:37:53 +02:00
var now = moment ( ) ;
var nextBestBeforeDate = moment ( result . next _best _before _date ) ;
productRow . removeClass ( "table-warning" ) ;
productRow . removeClass ( "table-danger" ) ;
2019-09-26 13:55:42 +02:00
productRow . removeClass ( "table-info" ) ;
productRow . removeClass ( "d-none" ) ;
productRow . removeAttr ( "style" ) ;
2019-09-20 13:37:53 +02:00
if ( now . isAfter ( nextBestBeforeDate ) )
{
productRow . addClass ( "table-danger" ) ;
}
2019-09-27 08:12:37 +02:00
else if ( nextBestBeforeDate . isBefore ( expiringThreshold ) )
2019-09-20 13:37:53 +02:00
{
productRow . addClass ( "table-warning" ) ;
}
2019-09-26 13:55:42 +02:00
if ( result . stock _amount == 0 && result . product . min _stock _amount == 0 )
2019-09-20 13:37:53 +02:00
{
$ ( '#product-' + productId + '-row' ) . fadeOut ( 500 , function ( )
{
$ ( this ) . tooltip ( "hide" ) ;
2019-09-26 13:55:42 +02:00
$ ( this ) . addClass ( "d-none" ) ;
2019-09-20 13:37:53 +02:00
} ) ;
}
else
{
$ ( '#product-' + productId + '-qu-name' ) . text ( _ _n ( result . stock _amount , result . quantity _unit _stock . name , result . quantity _unit _stock . name _plural ) ) ;
$ ( '#product-' + productId + '-amount' ) . parent ( ) . effect ( 'highlight' , { } , 500 ) ;
$ ( '#product-' + productId + '-amount' ) . fadeOut ( 500 , function ( )
{
$ ( this ) . text ( result . stock _amount ) . fadeIn ( 500 ) ;
} ) ;
$ ( '#product-' + productId + '-consume-all-button' ) . attr ( 'data-consume-amount' , result . stock _amount ) ;
$ ( '#product-' + productId + '-next-best-before-date' ) . parent ( ) . effect ( 'highlight' , { } , 500 ) ;
$ ( '#product-' + productId + '-next-best-before-date' ) . fadeOut ( 500 , function ( )
{
$ ( this ) . text ( result . next _best _before _date ) . fadeIn ( 500 ) ;
} ) ;
$ ( '#product-' + productId + '-next-best-before-date-timeago' ) . attr ( 'datetime' , result . next _best _before _date ) ;
var openedAmount = result . stock _amount _opened || 0 ;
$ ( '#product-' + productId + '-opened-amount' ) . parent ( ) . effect ( 'highlight' , { } , 500 ) ;
$ ( '#product-' + productId + '-opened-amount' ) . fadeOut ( 500 , function ( )
{
if ( openedAmount > 0 )
{
$ ( this ) . text ( _ _t ( '%s opened' , openedAmount ) ) . fadeIn ( 500 ) ;
}
else
{
$ ( this ) . text ( "" ) . fadeIn ( 500 ) ;
}
} ) ;
2019-09-26 13:55:42 +02:00
if ( result . stock _amount == 0 && result . product . min _stock _amount > 0 )
{
productRow . addClass ( "table-info" ) ;
}
2019-09-20 13:37:53 +02:00
}
$ ( '#product-' + productId + '-next-best-before-date' ) . parent ( ) . effect ( 'highlight' , { } , 500 ) ;
$ ( '#product-' + productId + '-next-best-before-date' ) . fadeOut ( 500 , function ( )
{
$ ( this ) . text ( result . next _best _before _date ) . fadeIn ( 500 ) ;
} ) ;
2020-01-21 17:30:09 +01:00
$ ( '#product-' + productId + '-next-best-before-date-timeago' ) . attr ( 'datetime' , result . next _best _before _date + ' 23:59:59' ) ;
2019-09-20 13:37:53 +02:00
if ( result . stock _amount _opened > 0 )
{
$ ( '#product-' + productId + '-opened-amount' ) . parent ( ) . effect ( 'highlight' , { } , 500 ) ;
$ ( '#product-' + productId + '-opened-amount' ) . fadeOut ( 500 , function ( )
{
$ ( this ) . text ( _ _t ( '%s opened' , result . stock _amount _opened ) ) . fadeIn ( 500 ) ;
} ) ;
}
else
{
$ ( '#product-' + productId + '-opened-amount' ) . text ( "" ) ;
}
2019-09-27 08:30:08 +02:00
if ( parseInt ( result . is _aggregated _amount ) === 1 )
{
$ ( '#product-' + productId + '-amount-aggregated' ) . fadeOut ( 500 , function ( )
{
$ ( this ) . text ( result . stock _amount _aggregated ) . fadeIn ( 500 ) ;
} ) ;
if ( result . stock _amount _opened _aggregated > 0 )
{
$ ( '#product-' + productId + '-opened-amount-aggregated' ) . parent ( ) . effect ( 'highlight' , { } , 500 ) ;
$ ( '#product-' + productId + '-opened-amount-aggregated' ) . fadeOut ( 500 , function ( )
{
$ ( this ) . text ( _ _t ( '%s opened' , result . stock _amount _opened _aggregated ) ) . fadeIn ( 500 ) ;
} ) ;
}
else
{
$ ( '#product-' + productId + '-opened-amount-aggregated' ) . text ( "" ) ;
}
}
2019-09-20 13:37:53 +02:00
// Needs to be delayed because of the animation above the date-text would be wrong if fired immediately...
setTimeout ( function ( )
{
RefreshContextualTimeago ( ) ;
2019-09-27 08:30:08 +02:00
RefreshLocaleNumberDisplay ( ) ;
2019-09-20 13:37:53 +02:00
} , 600 ) ;
} ,
function ( xhr )
{
Grocy . FrontendHelpers . EndUiBusy ( ) ;
console . error ( xhr ) ;
}
) ;
}
$ ( window ) . on ( "message" , function ( e )
{
var data = e . originalEvent . data ;
if ( data . Message === "ProductChanged" )
{
RefreshProductRow ( data . Payload ) ;
RefreshStatistics ( ) ;
}
} ) ;