diff --git a/controllers/StockController.php b/controllers/StockController.php
index 7436d02d..e06a07ca 100644
--- a/controllers/StockController.php
+++ b/controllers/StockController.php
@@ -49,9 +49,7 @@ class StockController extends BaseController
'locations' => $this->Database->locations()->orderBy('name'),
'currentStockDetail' => $this->Database->stock()->orderBy('product_id'),
'currentStockLocations' => $this->StockService->GetCurrentStockLocations(),
- 'missingProducts' => $this->StockService->GetMissingProducts(),
'nextXDays' => $nextXDays,
- 'productGroups' => $this->Database->product_groups()->orderBy('name'),
'userfields' => $this->UserfieldsService->GetFields('products'),
'userfieldValues' => $this->UserfieldsService->GetAllValues('products')
]);
diff --git a/localization/strings.pot b/localization/strings.pot
index 408f8b77..2d9f91eb 100644
--- a/localization/strings.pot
+++ b/localization/strings.pot
@@ -1615,3 +1615,6 @@ msgstr ""
msgid "Keep screen on while displaying a \"fullscreen-card\""
msgstr ""
+
+msgid "A purchased date is required"
+msgstr ""
diff --git a/public/js/grocy.js b/public/js/grocy.js
index 7ee410ad..cb080592 100644
--- a/public/js/grocy.js
+++ b/public/js/grocy.js
@@ -614,10 +614,10 @@ $(document).on("click", ".show-as-dialog-link", function(e)
backdrop: true,
closeButton: false,
buttons: {
- ok: {
- label: __t('OK'),
- className: 'btn-success responsive-button',
- callback: function()
+ cancel: {
+ label: __t('Cancel'),
+ className: 'btn-secondary responsive-button',
+ callback: function ()
{
bootbox.hideAll();
}
diff --git a/public/viewjs/consume.js b/public/viewjs/consume.js
index 18d9f808..9faf4cca 100644
--- a/public/viewjs/consume.js
+++ b/public/viewjs/consume.js
@@ -1,24 +1,4 @@
-$(document).ready(function() {
-
- if (GetUriParam("embedded") !== undefined)
- {
- var locationId = GetUriParam('locationId');
-
- if (typeof locationId === 'undefined')
- {
- Grocy.Components.ProductPicker.GetPicker().trigger('change');
- Grocy.Components.ProductPicker.GetInputElement().focus();
- } else {
-
- $("#location_id").val(locationId);
- $("#location_id").trigger('change');
- $("#use_specific_stock_entry").click();
- $("#use_specific_stock_entry").trigger('change');
- }
- }
-});
-
-$('#save-consume-button').on('click', function(e)
+$('#save-consume-button').on('click', function(e)
{
e.preventDefault();
@@ -497,3 +477,21 @@ function UndoStockTransaction(transactionId)
}
);
};
+
+if (GetUriParam("embedded") !== undefined)
+{
+ var locationId = GetUriParam('locationId');
+
+ if (typeof locationId === 'undefined')
+ {
+ Grocy.Components.ProductPicker.GetPicker().trigger('change');
+ Grocy.Components.ProductPicker.GetInputElement().focus();
+ }
+ else
+ {
+ $("#location_id").val(locationId);
+ $("#location_id").trigger('change');
+ $("#use_specific_stock_entry").click();
+ $("#use_specific_stock_entry").trigger('change');
+ }
+}
diff --git a/public/viewjs/stockdetail.js b/public/viewjs/stockdetail.js
index 2ee665c2..0772bd4a 100644
--- a/public/viewjs/stockdetail.js
+++ b/public/viewjs/stockdetail.js
@@ -7,45 +7,19 @@
});
$('#stock-detail-table tbody').removeClass("d-none");
-function bootBoxModal(message) {
- bootbox.dialog({
- message: message,
- size: 'large',
- backdrop: true,
- closeButton: false,
- buttons: {
- cancel: {
- label: __t('Cancel'),
- className: 'btn-secondary responsive-button',
- callback: function()
- {
- bootbox.hideAll();
- }
- }
- }
- });
-}
+$.fn.dataTable.ext.search.push(function(settings, data, dataIndex)
+{
+ var productId = Grocy.Components.ProductPicker.GetValue();
+ if ((isNaN(productId) || productId == "" || productId == data[1]))
+ {
+ return true;
+ }
+
+ return false;
+});
-
-$.fn.dataTable.ext.search.push(
- function( settings, data, dataIndex ) {
- var productId = Grocy.Components.ProductPicker.GetValue();
-
- if ( ( isNaN( productId ) ||
- productId == "" ||
- //assume productId is in the first column
- productId == data[1] ) )
- {
- return true;
- }
- return false;
- }
-);
-
-$(document).ready(function() {
- Grocy.Components.ProductPicker.GetPicker().trigger('change');
-} );
+Grocy.Components.ProductPicker.GetPicker().trigger('change');
Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
{
@@ -114,29 +88,17 @@ $(document).on('click', '.product-open-button', function(e)
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');
+ var specificStockEntryId = $(e.currentTarget).attr('data-stock-id');
+ var stockRowId = $(e.currentTarget).attr('data-stockrow-id');
var button = $(e.currentTarget);
-
- Grocy.Api.Post('stock/products/' + productId + '/open', { 'amount': 1 },
+
+ Grocy.Api.Post('stock/products/' + productId + '/open', { 'amount': 1, 'stock_entry_id': specificStockEntryId },
function(bookingResponse)
{
- Grocy.Api.Get('stock/products/' + productId,
- function(result)
- {
- if (result.stock_amount == result.stock_amount_opened)
- {
- button.addClass("disabled");
- }
-
- Grocy.FrontendHelpers.EndUiBusy();
- toastr.success(__t('Marked %1$s of %2$s as opened', 1 + " " + productQuName, productName) + '
' + __t("Undo") + '');
- RefreshProductRow(productId);
- },
- function(xhr)
- {
- Grocy.FrontendHelpers.EndUiBusy();
- console.error(xhr);
- }
- );
+ button.addClass("disabled");
+ Grocy.FrontendHelpers.EndUiBusy();
+ toastr.success(__t('Marked %1$s of %2$s as opened', 1 + " " + productQuName, productName) + '
' + __t("Undo") + '');
+ RefreshStockDetailRow(stockRowId);
},
function(xhr)
{
@@ -152,91 +114,40 @@ $(document).on("click", ".stock-name-cell", function(e)
$("#stockdetail-productcard-modal").modal("show");
});
-$(document).on("click", ".product-purchase-button", function(e)
-{
- e.preventDefault();
-
- var productId = $(e.currentTarget).attr("data-product-id");
-
- bootBoxModal('');
-});
-
-$(document).on("click", ".product-transfer-button", function(e)
-{
-
- e.preventDefault();
-
- var productId = $(e.currentTarget).attr("data-product-id");
- var locationId = $(e.currentTarget).attr('data-location-id');
- var specificStockEntryId = $(e.currentTarget).attr('data-stock-id');
- bootBoxModal('');
-
-});
-
-$(document).on("click", ".product-consume-custom-amount-button", function(e)
-{
- e.preventDefault();
-
- var productId = $(e.currentTarget).attr("data-product-id");
- var locationId = $(e.currentTarget).attr('data-location-id');
- var specificStockEntryId = $(e.currentTarget).attr('data-stock-id');
-
- bootBoxModal('');
-
-});
-
-$(document).on("click", ".product-inventory-button", function(e)
-{
- e.preventDefault();
-
- var productId = $(e.currentTarget).attr("data-product-id");
-
- bootBoxModal('');
-});
-
-$(document).on("click", ".product-stockedit-button", function(e)
-{
- e.preventDefault();
-
- var productId = $(e.currentTarget).attr("data-product-id");
- var stockRowId = $(e.currentTarget).attr("data-id");
-
- bootBoxModal('');
-});
-
-$(document).on("click", ".product-add-to-shopping-list-button", function(e)
-{
- e.preventDefault();
-
- var productId = $(e.currentTarget).attr("data-product-id");
-
- bootBoxModal('');
-});
-
function RefreshStockDetailRow(stockRowId)
{
Grocy.Api.Get("stock/" + stockRowId + "/entry",
function(result)
{
var stockRow = $('#stock-' + stockRowId + '-row');
- var now = moment();
-
- stockRow.removeClass("table-warning");
- stockRow.removeClass("table-danger");
- stockRow.removeClass("table-info");
- stockRow.removeClass("d-none");
- stockRow.removeAttr("style");
-
+
if (result == null || result.amount == 0)
{
stockRow.fadeOut(500, function()
{
- //$(this).tooltip("hide");
$(this).addClass("d-none");
});
}
else
{
+ var expiringThreshold = moment().add(Grocy.UserSettings.stock_expring_soon_days, "days");
+ var now = moment();
+ var bestBeforeDate = moment(result.best_before_date);
+
+ stockRow.removeClass("table-warning");
+ stockRow.removeClass("table-danger");
+ stockRow.removeClass("table-info");
+ stockRow.removeClass("d-none");
+ stockRow.removeAttr("style");
+ if (now.isAfter(bestBeforeDate))
+ {
+ stockRow.addClass("table-danger");
+ }
+ else if (bestBeforeDate.isBefore(expiringThreshold))
+ {
+ stockRow.addClass("table-warning");
+ }
+
$('#stock-' + stockRowId + '-amount').parent().effect('highlight', { }, 500);
$('#stock-' + stockRowId + '-amount').fadeOut(500, function ()
{
@@ -248,6 +159,7 @@ function RefreshStockDetailRow(stockRowId)
{
$(this).text(result.best_before_date).fadeIn(500);
});
+ $('#stock-' + stockRowId + '-best-before-date-timeago').attr('datetime', result.best_before_date + ' 23:59:59');
var locationName = "";
Grocy.Api.Get("objects/locations/" + result.location_id,
@@ -258,7 +170,8 @@ function RefreshStockDetailRow(stockRowId)
function(xhr)
{
console.error(xhr);
- });
+ }
+ );
$('#stock-' + stockRowId + '-location').parent().effect('highlight', { }, 500);
$('#stock-' + stockRowId + '-location').fadeOut(500, function()
{
@@ -276,8 +189,24 @@ function RefreshStockDetailRow(stockRowId)
{
$(this).text(result.purchased_date).fadeIn(500);
});
+ $('#stock-' + stockRowId + '-purchased-date-timeago').attr('datetime', result.purchased_date + ' 23:59:59');
+
+ $('#stock-' + stockRowId + '-opened-amount').parent().effect('highlight', {}, 500);
+ $('#stock-' + stockRowId + '-opened-amount').fadeOut(500, function ()
+ {
+ if (result.open == 1)
+ {
+ $(this).text(__t('Opened')).fadeIn(500);
+ }
+ else
+ {
+ $(this).text("").fadeIn(500);
+ $(".product-open-button[data-stockrow-id='" + stockRowId + "']").removeClass("disabled");
+ }
+ });
}
+ // Needs to be delayed because of the animation above the date-text would be wrong if fired immediately...
setTimeout(function()
{
RefreshContextualTimeago();
@@ -316,3 +245,9 @@ function UndoStockBookingEntry(bookingId, stockRowId)
}
);
};
+
+$(document).on("click", ".product-name-cell", function(e)
+{
+ Grocy.Components.ProductCard.Refresh($(e.currentTarget).attr("data-product-id"));
+ $("#productcard-modal").modal("show");
+});
diff --git a/public/viewjs/stockedit.js b/public/viewjs/stockedit.js
index ca02abb2..109d092a 100644
--- a/public/viewjs/stockedit.js
+++ b/public/viewjs/stockedit.js
@@ -1,57 +1,4 @@
-$(document).ready(function() {
- var stockRowId = GetUriParam('stockRowId');
- Grocy.Api.Get("stock/" + stockRowId + "/entry",
- function(stockEntry)
- {
- Grocy.Components.LocationPicker.SetId(stockEntry.location_id);
- $('#amount').val(stockEntry.amount);
- $('#price').val(stockEntry.price);
- Grocy.Components.DateTimePicker.SetValue(stockEntry.best_before_date);
-
- Grocy.Api.Get('stock/products/' + stockEntry.product_id,
- function(productDetails)
- {
- $('#amount_qu_unit').text(productDetails.quantity_unit_stock.name);
-
- if (productDetails.product.allow_partial_units_in_stock == 1)
- {
- $("#amount").attr("min", "0.01");
- $("#amount").attr("step", "0.01");
- $("#amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %1$s', 0.01.toLocaleString()));
- }
- else
- {
- $("#amount").attr("min", "1");
- $("#amount").attr("step", "1");
- $("#amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %1$s', '1'));
- }
-
- if (productDetails.product.enable_tare_weight_handling == 1)
- {
- $("#amount").attr("min", productDetails.product.tare_weight);
- $("#amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %1$s', parseFloat(productDetails.product.tare_weight).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: 2 })));
- $("#tare-weight-handling-info").removeClass("d-none");
- }
- else
- {
- $("#tare-weight-handling-info").addClass("d-none");
- }
-
- },
- function(xhr)
- {
- console.error(xhr);
- }
- );
- },
- function(xhr)
- {
- console.error(xhr);
- }
- );
-} );
-
-$('#save-stockedit-button').on('click', function(e)
+$('#save-stockedit-button').on('click', function(e)
{
e.preventDefault();
@@ -76,8 +23,6 @@ $('#save-stockedit-button').on('click', function(e)
}
jsonData.price = price;
- var bookingResponse = null;
-
var stockRowId = GetUriParam('stockRowId');
jsonData.id = stockRowId;
@@ -135,3 +80,54 @@ if (Grocy.Components.DateTimePicker)
Grocy.FrontendHelpers.ValidateForm('stockedit-form');
});
}
+
+var stockRowId = GetUriParam('stockRowId');
+Grocy.Api.Get("stock/" + stockRowId + "/entry",
+ function (stockEntry)
+ {
+ Grocy.Components.LocationPicker.SetId(stockEntry.location_id);
+ $('#amount').val(stockEntry.amount);
+ $('#price').val(stockEntry.price);
+ Grocy.Components.DateTimePicker.SetValue(stockEntry.best_before_date);
+
+ Grocy.Api.Get('stock/products/' + stockEntry.product_id,
+ function (productDetails)
+ {
+ $('#amount_qu_unit').text(productDetails.quantity_unit_stock.name);
+
+ if (productDetails.product.allow_partial_units_in_stock == 1)
+ {
+ $("#amount").attr("min", "0.01");
+ $("#amount").attr("step", "0.01");
+ $("#amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %1$s', 0.01.toLocaleString()));
+ }
+ else
+ {
+ $("#amount").attr("min", "1");
+ $("#amount").attr("step", "1");
+ $("#amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %1$s', '1'));
+ }
+
+ if (productDetails.product.enable_tare_weight_handling == 1)
+ {
+ $("#amount").attr("min", productDetails.product.tare_weight);
+ $("#amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %1$s', parseFloat(productDetails.product.tare_weight).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: 2 })));
+ $("#tare-weight-handling-info").removeClass("d-none");
+ }
+ else
+ {
+ $("#tare-weight-handling-info").addClass("d-none");
+ }
+
+ },
+ function (xhr)
+ {
+ console.error(xhr);
+ }
+ );
+ },
+ function (xhr)
+ {
+ console.error(xhr);
+ }
+);
diff --git a/public/viewjs/stockoverview.js b/public/viewjs/stockoverview.js
index 4047f197..c3d26bba 100644
--- a/public/viewjs/stockoverview.js
+++ b/public/viewjs/stockoverview.js
@@ -196,126 +196,6 @@ function RefreshStatistics()
}
RefreshStatistics();
-$(document).on("click", ".product-purchase-button", function(e)
-{
- e.preventDefault();
-
- var productId = $(e.currentTarget).attr("data-product-id");
-
- bootbox.dialog({
- message: '',
- size: 'large',
- backdrop: true,
- closeButton: false,
- buttons: {
- cancel: {
- label: __t('Cancel'),
- className: 'btn-secondary responsive-button',
- callback: function()
- {
- bootbox.hideAll();
- }
- }
- }
- });
-});
-
-$(document).on("click", ".product-transfer-button", function(e)
-{
- e.preventDefault();
-
- var productId = $(e.currentTarget).attr("data-product-id");
-
- bootbox.dialog({
- message: '',
- size: 'large',
- backdrop: true,
- closeButton: false,
- buttons: {
- cancel: {
- label: __t('Cancel'),
- className: 'btn-secondary responsive-button',
- callback: function()
- {
- bootbox.hideAll();
- }
- }
- }
- });
-});
-
-$(document).on("click", ".product-consume-custom-amount-button", function(e)
-{
- e.preventDefault();
-
- var productId = $(e.currentTarget).attr("data-product-id");
-
- bootbox.dialog({
- message: '',
- size: 'large',
- backdrop: true,
- closeButton: false,
- buttons: {
- cancel: {
- label: __t('Cancel'),
- className: 'btn-secondary responsive-button',
- callback: function()
- {
- bootbox.hideAll();
- }
- }
- }
- });
-});
-
-$(document).on("click", ".product-inventory-button", function(e)
-{
- e.preventDefault();
-
- var productId = $(e.currentTarget).attr("data-product-id");
-
- bootbox.dialog({
- message: '',
- size: 'large',
- backdrop: true,
- closeButton: false,
- buttons: {
- cancel: {
- label: __t('Cancel'),
- className: 'btn-secondary responsive-button',
- callback: function()
- {
- bootbox.hideAll();
- }
- }
- }
- });
-});
-
-$(document).on("click", ".product-add-to-shopping-list-button", function(e)
-{
- e.preventDefault();
-
- var productId = $(e.currentTarget).attr("data-product-id");
-
- bootbox.dialog({
- message: '',
- size: 'large',
- backdrop: true,
- closeButton: false,
- buttons: {
- cancel: {
- label: __t('Cancel'),
- className: 'btn-secondary responsive-button',
- callback: function()
- {
- bootbox.hideAll();
- }
- }
- }
- });
-});
-
function RefreshProductRow(productId)
{
productId = productId.toString();
@@ -398,7 +278,7 @@ function RefreshProductRow(productId)
{
$(this).text(result.next_best_before_date).fadeIn(500);
});
- $('#product-' + productId + '-next-best-before-date-timeago').attr('datetime', result.next_best_before_date);
+ $('#product-' + productId + '-next-best-before-date-timeago').attr('datetime', result.next_best_before_date + ' 23:59:59');
if (result.stock_amount_opened > 0)
{
diff --git a/public/viewjs/transfer.js b/public/viewjs/transfer.js
index 88d2d111..1918befa 100644
--- a/public/viewjs/transfer.js
+++ b/public/viewjs/transfer.js
@@ -1,23 +1,4 @@
-$(document).ready(function() {
- if (GetUriParam("embedded") !== undefined)
- {
- var locationId = GetUriParam('locationId');
-
- if (typeof locationId === 'undefined')
- {
- Grocy.Components.ProductPicker.GetPicker().trigger('change');
- Grocy.Components.ProductPicker.GetInputElement().focus();
- } else {
-
- $("#location_id_from").val(locationId);
- $("#location_id_from").trigger('change');
- $("#use_specific_stock_entry").click();
- $("#use_specific_stock_entry").trigger('change');
- }
- }
-});
-
-$('#save-transfer-button').on('click', function(e)
+$('#save-transfer-button').on('click', function(e)
{
e.preventDefault();
@@ -440,3 +421,22 @@ function UndoStockTransaction(transactionId)
}
);
};
+
+if (GetUriParam("embedded") !== undefined)
+{
+ var locationId = GetUriParam('locationId');
+
+ if (typeof locationId === 'undefined')
+ {
+ Grocy.Components.ProductPicker.GetPicker().trigger('change');
+ Grocy.Components.ProductPicker.GetInputElement().focus();
+ }
+ else
+ {
+
+ $("#location_id_from").val(locationId);
+ $("#location_id_from").trigger('change');
+ $("#use_specific_stock_entry").click();
+ $("#use_specific_stock_entry").trigger('change');
+ }
+}
diff --git a/views/stockdetail.blade.php b/views/stockdetail.blade.php
index 53b6a146..1b11535b 100644
--- a/views/stockdetail.blade.php
+++ b/views/stockdetail.blade.php
@@ -9,21 +9,16 @@
@endpush
-@push('pageStyles')
-
-@endpush
-
@section('content')