diff --git a/changelog/60_UNRELEASED_2020-xx-xx.md b/changelog/60_UNRELEASED_2020-xx-xx.md
index 444a222f..558701b1 100644
--- a/changelog/60_UNRELEASED_2020-xx-xx.md
+++ b/changelog/60_UNRELEASED_2020-xx-xx.md
@@ -40,6 +40,7 @@
- Products which are overdue are highlighted in grey (there is also a new filter button on the stock overview page for them)
- Products which are expired (new option) are highlighted in red
- When creating a quantity unit conversion it's now possible to automatically create the inverse conversion (thanks @kriddles)
+- The product option "Allow partial units in stock" was removed, partial amounts are now possible by default for all products
- On purchase there is now a warning shown, when the due date of the purchased product is earlier than the next due date in stock (enabled by default, can be disabled by a new stock setting (top right corner settings menu))
- The amount to be used for the "quick consume/open buttons" on the stock overview page can now be configured per product (new product option "Quick consume amount", defaults to 1)
- Products can now be duplicated (new button on the products list page, all fields will be preset from the copied product, except the name)
@@ -127,6 +128,8 @@
- Table states (visible columns, sorting, column order and so on) are now saved server side (in user settings) means that this stays the same when using different browsers
- Dialogs are now used everywhere where appropriate instead of jumping between pages (for exampel when adding/editing shopping list items)
- Added a "Clear filter"-button on all pages (with filters) to quickly reset applied filters
+- Prefilled number inputs now use sensible decimal places (max. the configured decimals while hiding trailing zeros where appropriate, means if you never use partial amounts for a product, you'll never see decimals for it)
+- Improved / more precise validation messages for number inputs
- The data path (previously fixed to the `data` folder) is now configurable, making it possible to run multiple grocy instances from the same directory (with different `config.php` files / different database, etc.) (thanks @fgrsnau)
- Via an environment variable `GROCY_DATAPATH` (higher priority)
- Via an FastCGI parameter `GROCY_DATAPATH` (lower priority)
diff --git a/grocy.openapi.json b/grocy.openapi.json
index f3792f1a..680c4f24 100644
--- a/grocy.openapi.json
+++ b/grocy.openapi.json
@@ -3957,9 +3957,6 @@
"picture_file_name": {
"type": "string"
},
- "allow_partial_units_in_stock": {
- "type": "boolean"
- },
"row_created_timestamp": {
"type": "string",
"format": "date-time"
@@ -3987,7 +3984,6 @@
"product_group_id": "1",
"picture_file_name": "cookies.jpg",
"default_best_before_days_after_open": "0",
- "allow_partial_units_in_stock": "0",
"enable_tare_weight_handling": "0",
"tare_weight": "0.0",
"not_check_stock_fulfillment_for_recipes": "0",
@@ -4284,7 +4280,6 @@
"product_group_id": "1",
"picture_file_name": "cookies.jpg",
"default_best_before_days_after_open": "0",
- "allow_partial_units_in_stock": "0",
"enable_tare_weight_handling": "0",
"tare_weight": "0.0",
"not_check_stock_fulfillment_for_recipes": "0",
diff --git a/localization/strings.pot b/localization/strings.pot
index 2e1b4411..8252a03a 100644
--- a/localization/strings.pot
+++ b/localization/strings.pot
@@ -405,12 +405,6 @@ msgstr ""
msgid "A location is required"
msgstr ""
-msgid "The amount cannot be lower than %s"
-msgstr ""
-
-msgid "This cannot be negative"
-msgstr ""
-
msgid "A quantity unit is required"
msgstr ""
@@ -563,9 +557,6 @@ msgstr ""
msgid "Price"
msgstr ""
-msgid "The price cannot be lower than %s"
-msgstr ""
-
msgid "Unit"
msgstr ""
@@ -597,9 +588,6 @@ msgstr[1] ""
msgid "in singular form"
msgstr ""
-msgid "This cannot be lower than %s"
-msgstr ""
-
msgid "Quantity unit"
msgstr ""
@@ -844,9 +832,6 @@ msgstr ""
msgid "Charge cycle successfully undone"
msgstr ""
-msgid "This cannot be negative and must be an integral number"
-msgstr ""
-
msgid "Disable stock fulfillment checking for this ingredient"
msgstr ""
@@ -1125,9 +1110,6 @@ msgid_plural "Not enough in stock, %s ingredients missing"
msgstr[0] ""
msgstr[1] ""
-msgid "The amount cannot be lower than %1$s or equal %2$s"
-msgstr ""
-
msgid "Not enough in stock, but already on the shopping list"
msgstr ""
@@ -1223,7 +1205,7 @@ msgstr ""
msgid "all locations"
msgstr ""
-msgid "Here you can print a page per location with the current stock, maybe to hang it there and note the consumed things on it."
+msgid "Here you can print a page per location with the current stock, maybe to hang it there and note the consumed things on it"
msgstr ""
msgid "this location"
@@ -1265,9 +1247,6 @@ msgstr ""
msgid "Quantity unit to"
msgstr ""
-msgid "This cannot be lower than %1$s and must be a valid number with max. %2$s decimal places"
-msgstr ""
-
msgid "This cannot be equal to %s"
msgstr ""
@@ -1981,3 +1960,18 @@ msgstr ""
msgid "Add overdue/expired products"
msgstr ""
+
+msgid "Products with tare weight enabled are currently not supported for transfer"
+msgstr ""
+
+msgid "This cannot be lower than %1$s or equal %2$s and needs to be a valid number with max. %3$s decimal places"
+msgstr ""
+
+msgid "This must be between %1$s and %2$s, cannot equal %3$s and needs to be a valid number with max. %4$s decimal places"
+msgstr ""
+
+msgid "This cannot be lower than %1$s and needs to be a valid number with max. %2$s decimal places"
+msgstr ""
+
+msgid "This must between %1$s and %2$s and needs to be a valid number with max. %3$s decimal places"
+msgstr ""
diff --git a/migrations/0103.sql b/migrations/0103.sql
index 62291bbf..4b6c7fe9 100644
--- a/migrations/0103.sql
+++ b/migrations/0103.sql
@@ -61,7 +61,6 @@ CREATE TABLE products (
default_best_before_days_after_freezing INTEGER NOT NULL DEFAULT 0,
default_best_before_days_after_thawing INTEGER NOT NULL DEFAULT 0,
picture_file_name TEXT,
- allow_partial_units_in_stock TINYINT NOT NULL DEFAULT 0,
enable_tare_weight_handling TINYINT NOT NULL DEFAULT 0,
tare_weight REAL NOT NULL DEFAULT 0,
not_check_stock_fulfillment_for_recipes TINYINT DEFAULT 0,
@@ -74,8 +73,8 @@ CREATE TABLE products (
);
INSERT INTO products
- (id, name, description, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, min_stock_amount, default_best_before_days, row_created_timestamp, product_group_id, picture_file_name, default_best_before_days_after_open, allow_partial_units_in_stock, enable_tare_weight_handling, tare_weight, not_check_stock_fulfillment_for_recipes, parent_product_id, calories, cumulate_min_stock_amount_of_sub_products, default_best_before_days_after_freezing, default_best_before_days_after_thawing, shopping_location_id)
-SELECT id, name, description, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, min_stock_amount,default_best_before_days, row_created_timestamp, product_group_id, picture_file_name, default_best_before_days_after_open, allow_partial_units_in_stock, enable_tare_weight_handling, tare_weight, not_check_stock_fulfillment_for_recipes, parent_product_id, calories, cumulate_min_stock_amount_of_sub_products, default_best_before_days_after_freezing, default_best_before_days_after_thawing, shopping_location_id
+ (id, name, description, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, min_stock_amount, default_best_before_days, row_created_timestamp, product_group_id, picture_file_name, default_best_before_days_after_open, enable_tare_weight_handling, tare_weight, not_check_stock_fulfillment_for_recipes, parent_product_id, calories, cumulate_min_stock_amount_of_sub_products, default_best_before_days_after_freezing, default_best_before_days_after_thawing, shopping_location_id)
+SELECT id, name, description, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, min_stock_amount,default_best_before_days, row_created_timestamp, product_group_id, picture_file_name, default_best_before_days_after_open, enable_tare_weight_handling, tare_weight, not_check_stock_fulfillment_for_recipes, parent_product_id, calories, cumulate_min_stock_amount_of_sub_products, default_best_before_days_after_freezing, default_best_before_days_after_thawing, shopping_location_id
FROM products_old;
DROP TABLE products_old;
diff --git a/public/css/grocy.css b/public/css/grocy.css
index e57a3f71..4b6ff326 100755
--- a/public/css/grocy.css
+++ b/public/css/grocy.css
@@ -290,10 +290,18 @@ a:not([href]) {
/* Hide the form validation feedback icons introduced in Bootstrap 4.2.0 - a colored border is enough */
.form-control.is-invalid,
+.custom-control.is-invalid,
.was-validated .form-control:invalid,
+.was-validated .custom-control:invalid,
.form-control.is-valid,
-.was-validated .form-control:valid {
- background-size: 0 0;
+.custom-control.is-valid,
+.was-validated .form-control:valid,
+.was-validated .custom-control:valid {
+ background-image: none;
+}
+.was-validated .custom-select:valid,
+.was-validated .custom-select:invalid {
+ background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px;
}
/* There is a little too much padding on form inputs */
diff --git a/public/js/grocy.js b/public/js/grocy.js
index f36dafcb..70a4d593 100644
--- a/public/js/grocy.js
+++ b/public/js/grocy.js
@@ -548,32 +548,38 @@ function RefreshLocaleNumberDisplay(rootSelector = "#page-content")
{
$(rootSelector + " .locale-number.locale-number-currency").each(function()
{
- if (isNaN(parseFloat($(this).text())))
+ var text = $(this).text();
+ if (isNaN(text) || text.isEmpty())
{
return;
}
- $(this).text(parseFloat($(this).text()).toLocaleString(undefined, { style: "currency", currency: Grocy.Currency, minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_prices }));
+ var value = parseFloat(text);
+ $(this).text(value.toLocaleString(undefined, { style: "currency", currency: Grocy.Currency, minimumFractionDigits: Grocy.UserSettings.stock_decimal_places_prices, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_prices }));
});
$(rootSelector + " .locale-number.locale-number-quantity-amount").each(function()
{
- if (isNaN(parseFloat($(this).text())))
+ var text = $(this).text();
+ if (isNaN(text) || text.isEmpty())
{
return;
}
- $(this).text(parseFloat($(this).text()).toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }));
+ var value = parseFloat(text);
+ $(this).text(value.toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }));
});
$(rootSelector + " .locale-number.locale-number-generic").each(function()
{
- if (isNaN(parseFloat($(this).text())))
+ var text = $(this).text();
+ if (isNaN(text) || text.isEmpty())
{
return;
}
- $(this).text(parseFloat($(this).text()).toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 2 }));
+ var value = parseFloat(text);
+ $(this).text(value.toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 2 }));
});
}
RefreshLocaleNumberDisplay();
@@ -583,18 +589,18 @@ function RefreshLocaleNumberInput(rootSelector = "#page-content")
$(rootSelector + " .locale-number-input.locale-number-currency").each(function()
{
var value = $(this).val();
- if (isNaN(value))
+ if (isNaN(value) || value.toString().isEmpty())
{
return;
}
- $(this).val(parseFloat(value).toLocaleString("en", { minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_prices, useGrouping: false }));
+ $(this).val(parseFloat(value).toLocaleString("en", { minimumFractionDigits: Grocy.UserSettings.stock_decimal_places_prices, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_prices, useGrouping: false }));
});
$(rootSelector + " .locale-number-input.locale-number-quantity-amount").each(function()
{
var value = $(this).val();
- if (isNaN(value))
+ if (isNaN(value) || value.toString().isEmpty())
{
return;
}
@@ -605,7 +611,7 @@ function RefreshLocaleNumberInput(rootSelector = "#page-content")
$(rootSelector + " .locale-number-input.locale-number-generic").each(function()
{
var value = $(this).val();
- if (isNaN(value))
+ if (isNaN(value) || value.toString().isEmpty())
{
return;
}
diff --git a/public/viewjs/choreform.js b/public/viewjs/choreform.js
index ec054827..3d3f0a05 100644
--- a/public/viewjs/choreform.js
+++ b/public/viewjs/choreform.js
@@ -133,8 +133,7 @@ $('.input-group-chore-period-type').on('change', function(e)
{
$("label[for='period_days']").text(__t("Period days"));
$("#period_days").attr("min", "0");
- $("#period_days").attr("max", "9999");
- $("#period_days").parent().find(".invalid-feedback").text(__t('This cannot be negative'));
+ $("#period_days").attr("max", "999999");
$('#chore-period-type-info').attr("data-original-title", __t('This means the next execution of this chore is scheduled %s days after the last execution', periodDays.toString()));
}
else if (periodType === 'daily')
@@ -154,7 +153,6 @@ $('.input-group-chore-period-type').on('change', function(e)
$("label[for='period_days']").text(__t("Day of month"));
$("#period_days").attr("min", "1");
$("#period_days").attr("max", "31");
- $("#period_days").parent().find(".invalid-feedback").text(__t('The amount must be between %1$s and %2$s', "1", "31"));
$('#chore-period-interval-info').attr("data-original-title", __t('This means the next execution of this chore should only be scheduled every %s months', periodInterval.toString()));
}
else if (periodType === 'yearly')
diff --git a/public/viewjs/components/barcodescanner.js b/public/viewjs/components/barcodescanner.js
index af033325..b0116651 100644
--- a/public/viewjs/components/barcodescanner.js
+++ b/public/viewjs/components/barcodescanner.js
@@ -252,7 +252,7 @@ $(document).on("click", "#barcodescanner-start-button", async function(e)
});
// Add camera select to existing dialog
- dialog.find('.bootbox-body').append('
');
+ dialog.find('.bootbox-body').append('
');
var cameraSelect = document.querySelector('.cameraSelect');
var cameras = await Quagga.CameraAccess.enumerateVideoDevices();
diff --git a/public/viewjs/components/numberpicker.js b/public/viewjs/components/numberpicker.js
index bd7afd33..59c0097b 100644
--- a/public/viewjs/components/numberpicker.js
+++ b/public/viewjs/components/numberpicker.js
@@ -25,3 +25,48 @@ $(".numberpicker").on("keyup", function()
$(this)[0].setCustomValidity("");
}
});
+
+$(".numberpicker").each(function()
+{
+ new MutationObserver(function(mutations)
+ {
+ mutations.forEach(function(mutation)
+ {
+ if (mutation.type == "attributes" && (mutation.attributeName == "min" || mutation.attributeName == "max" || mutation.attributeName == "data-not-equal"))
+ {
+ var element = $(mutation.target);
+ var min = element.attr("min");
+ var max = element.attr("max");
+ var decimals = element.attr("data-decimals");
+
+ if (element.hasAttr("data-not-equal"))
+ {
+ var notEqual = element.attr("data-not-equal");
+
+ if (max.isEmpty() || max.startsWith("999999"))
+ {
+ element.parent().find(".invalid-feedback").text(__t("This cannot be lower than %1$s or equal %2$s and needs to be a valid number with max. %3$s decimal places", parseFloat(min).toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: decimals }), parseFloat(notEqual).toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: decimals }), decimals));
+ }
+ else
+ {
+ element.parent().find(".invalid-feedback").text(__t("This must be between %1$s and %2$s, cannot equal %3$s and needs to be a valid number with max. %4$s decimal places", parseFloat(min).toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: decimals }), parseFloat(max).toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: decimals }), parseFloat(notEqual).toLocaleString(undefined, { minimumFractionDigits: decimals, maximumFractionDigits: decimals }), decimals));
+ }
+
+ return;
+ }
+
+ if (max.isEmpty() || max.startsWith("999999"))
+ {
+ element.parent().find(".invalid-feedback").text(__t("This cannot be lower than %1$s and needs to be a valid number with max. %2$s decimal places", parseFloat(min).toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: decimals }), decimals));
+ }
+ else
+ {
+ element.parent().find(".invalid-feedback").text(__t("This must between %1$s and %2$s and needs to be a valid number with max. %3$s decimal places", parseFloat(min).toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: decimals }), parseFloat(max).toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: decimals }), decimals));
+ }
+ }
+ });
+ }).observe(this, {
+ attributes: true
+ });
+});
+$(".numberpicker").attr("min", $(".numberpicker").attr("min")); // Dummy change to trigger MutationObserver above once
diff --git a/public/viewjs/consume.js b/public/viewjs/consume.js
index 414458f8..256c77f1 100644
--- a/public/viewjs/consume.js
+++ b/public/viewjs/consume.js
@@ -92,10 +92,8 @@
Grocy.Components.ProductPicker.FinishFlow();
Grocy.Components.ProductAmountPicker.Reset();
- $("#display_amount").attr("min", "1");
+ $("#display_amount").attr("min", "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
$("#display_amount").attr("max", "999999");
- $("#display_amount").attr("step", "1");
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %s', '1'));
$('#display_amount').val(parseFloat(Grocy.UserSettings.stock_default_consume_amount));
RefreshLocaleNumberInput();
$(".input-group-productamountpicker").trigger("change");
@@ -336,28 +334,15 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
}
);
- if (productDetails.product.allow_partial_units_in_stock == 1)
- {
- $("#display_amount").attr("min", "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#display_amount").attr("step", "." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount must be between %1$s and %2$s', "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1", parseFloat(productDetails.stock_amount).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts })));
- }
- else
- {
- $("#display_amount").attr("min", "1");
- $("#display_amount").attr("step", "1");
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount must be between %1$s and %2$s', "1", parseFloat(productDetails.stock_amount).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts })));
- }
-
if (productDetails.product.enable_tare_weight_handling == 1)
{
$("#display_amount").attr("min", productDetails.product.tare_weight);
$('#display_amount').attr('max', parseFloat(productDetails.stock_amount) + parseFloat(productDetails.product.tare_weight));
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount must be between %1$s and %2$s', parseFloat(productDetails.product.tare_weight).toLocaleString(), (parseFloat(productDetails.stock_amount) + parseFloat(productDetails.product.tare_weight)).toLocaleString()));
$("#tare-weight-handling-info").removeClass("d-none");
}
else
{
+ $("#display_amount").attr("min", "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
$("#tare-weight-handling-info").addClass("d-none");
}
@@ -455,10 +440,6 @@ $("#specific_stock_entry").on("change", function(e)
{
$("#display_amount").parent().find(".invalid-feedback").text(__t('There are no units available at this location'));
}
- else
- {
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount must be between %1$s and %2$s', "1", sumValue));
- }
},
function(xhr)
{
@@ -468,7 +449,6 @@ $("#specific_stock_entry").on("change", function(e)
}
else
{
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount must be between %1$s and %2$s', "1", $('option:selected', this).attr('amount')));
$("#display_amount").attr("max", $('option:selected', this).attr('amount'));
}
});
@@ -578,30 +558,18 @@ function RefreshForm()
{
$("#consume-exact-amount-group").addClass("d-none");
}
+
if (productDetails.product.enable_tare_weight_handling == 1 && !$('#consume-exact-amount').is(':checked'))
{
$("#display_amount").attr("min", productDetails.product.tare_weight);
$('#display_amount').attr('max', sumValue + parseFloat(productDetails.product.tare_weight));
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount must be between %1$s and %2$s', parseFloat(productDetails.product.tare_weight).toLocaleString(), (parseFloat(productDetails.stock_amount) + parseFloat(productDetails.product.tare_weight)).toLocaleString()));
$("#tare-weight-handling-info").removeClass("d-none");
}
else
{
$("#tare-weight-handling-info").addClass("d-none");
- if (productDetails.product.allow_partial_units_in_stock == 1)
- {
- $("#display_amount").attr("min", "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#display_amount").attr("step", "." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount must be between %1$s and %2$s', "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1", parseFloat(productDetails.stock_amount).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts })));
- }
- else
- {
- $("#display_amount").attr("min", "1");
- $("#display_amount").attr("step", "1");
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount must be between %1$s and %2$s', "1", parseFloat(productDetails.stock_amount).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts })));
- }
-
+ $("#display_amount").attr("min", "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
$('#display_amount').attr('max', sumValue);
if (sumValue == 0)
diff --git a/public/viewjs/inventory.js b/public/viewjs/inventory.js
index 452b3d66..2250f79c 100644
--- a/public/viewjs/inventory.js
+++ b/public/viewjs/inventory.js
@@ -83,8 +83,6 @@
$('#inventory-change-info').addClass('d-none');
$("#tare-weight-handling-info").addClass("d-none");
$("#display_amount").attr("min", "0");
- $("#display_amount").attr("step", "1");
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %s', '0'));
$('#display_amount').val('');
$(".input-group-productamountpicker").trigger("change");
$('#price').val('');
@@ -138,27 +136,14 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
$('#display_amount').attr("data-stock-amount", productDetails.stock_amount)
$('#display_amount').attr('data-not-equal', productDetails.stock_amount * $("#qu_id option:selected").attr("data-qu-factor"));
- if (productDetails.product.allow_partial_units_in_stock == 1)
- {
- $("#display_amount").attr("min", "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#display_amount").attr("step", "." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %1$s or equal %2$s', "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1", productDetails.stock_amount.toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts })));
- }
- else
- {
- $("#display_amount").attr("min", "0");
- $("#display_amount").attr("step", "1");
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %1$s or equal %2$s', '0', productDetails.stock_amount.toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts })));
- }
-
if (productDetails.product.enable_tare_weight_handling == 1)
{
$("#display_amount").attr("min", productDetails.product.tare_weight);
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %1$s or equal %2$s', parseFloat(productDetails.product.tare_weight).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }), (parseFloat(productDetails.stock_amount) + parseFloat(productDetails.product.tare_weight)).toLocaleString()));
$("#tare-weight-handling-info").removeClass("d-none");
}
else
{
+ $("#display_amount").attr("min", "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
$("#tare-weight-handling-info").addClass("d-none");
}
@@ -243,7 +228,6 @@ $('#inventory-form input').keydown(function(event)
$('#qu_id').on('change', function(e)
{
$('#display_amount').attr('data-not-equal', parseFloat($('#display_amount').attr('data-stock-amount')) * parseFloat($("#qu_id option:selected").attr("data-qu-factor")));
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %1$s or equal %2$s', "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1", parseFloat($('#display_amount').attr('data-not-equal')).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts })));
Grocy.FrontendHelpers.ValidateForm('inventory-form');
});
diff --git a/public/viewjs/productbarcodeform.js b/public/viewjs/productbarcodeform.js
index 917df311..b7cb0feb 100644
--- a/public/viewjs/productbarcodeform.js
+++ b/public/viewjs/productbarcodeform.js
@@ -81,3 +81,4 @@ if (Grocy.EditMode == "edit")
Grocy.FrontendHelpers.ValidateForm('barcode-form');
$('#barcode').focus();
+RefreshLocaleNumberInput();
diff --git a/public/viewjs/productform.js b/public/viewjs/productform.js
index b2213110..e845791b 100644
--- a/public/viewjs/productform.js
+++ b/public/viewjs/productform.js
@@ -247,34 +247,6 @@ $("#enable_tare_weight_handling").on("click", function()
Grocy.FrontendHelpers.ValidateForm("product-form");
});
-$("#allow_partial_units_in_stock").on("click", function()
-{
- if (this.checked)
- {
- $("#min_stock_amount").attr("min", "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts)));
- $("#min_stock_amount").attr("step", "." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#qu_factor_purchase_to_stock").attr("min", "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#qu_factor_purchase_to_stock").attr("step", "." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#qu_factor_purchase_to_stock").parent().find(".invalid-feedback").text(__t('This cannot be lower than %1$s and must be a valid number with max. %2$s decimal places', "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1", Grocy.UserSettings.stock_decimal_places_amounts));
- $("#quick_consume_amount").attr("min", "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#quick_consume_amount").attr("step", "." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#quick_consume_amount").parent().find(".invalid-feedback").text(__t('This cannot be lower than %1$s and must be a valid number with max. %2$s decimal places', "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1", Grocy.UserSettings.stock_decimal_places_amounts));
- }
- else
- {
- $("#min_stock_amount").attr("min", "0");
- $("#min_stock_amount").attr("step", "1");
- $("#qu_factor_purchase_to_stock").attr("min", "1");
- $("#qu_factor_purchase_to_stock").attr("step", "1");
- $("#qu_factor_purchase_to_stock").parent().find(".invalid-feedback").text(__t('This cannot be lower than %1$s and must be a valid number with max. %2$s decimal places', '1', '0'));
- $("#quick_consume_amount").attr("min", "1");
- $("#quick_consume_amount").attr("step", "1");
- $("#quick_consume_amount").parent().find(".invalid-feedback").text(__t('This cannot be lower than %1$s and must be a valid number with max. %2$s decimal places', '1', '0'));
- }
-
- Grocy.FrontendHelpers.ValidateForm("product-form");
-});
-
$("#product-picture").on("change", function(e)
{
$("#product-picture-label").removeClass("d-none");
@@ -346,10 +318,6 @@ $('#name').focus();
$('.input-group-qu').trigger('change');
Grocy.FrontendHelpers.ValidateForm('product-form');
-// Click twice to trigger on-click but not change the actual checked state
-$("#allow_partial_units_in_stock").click();
-$("#allow_partial_units_in_stock").click();
-
$(document).on('click', '.qu-conversion-delete-button', function(e)
{
var objectId = $(e.currentTarget).attr('data-qu-conversion-id');
@@ -479,10 +447,6 @@ if (Grocy.EditMode == "create" && GetUriParam("copy-of") != undefined)
$("#qu_id_stock").val(sourceProduct.qu_id_stock);
$("#qu_id_purchase").val(sourceProduct.qu_id_purchase);
$("#qu_factor_purchase_to_stock").val(sourceProduct.qu_factor_purchase_to_stock);
- if (BoolVal(sourceProduct.allow_partial_units_in_stock))
- {
- $("#allow_partial_units_in_stock").prop("checked", true);
- }
if (BoolVal(sourceProduct.enable_tare_weight_handling))
{
$("#enable_tare_weight_handling").prop("checked", true);
diff --git a/public/viewjs/purchase.js b/public/viewjs/purchase.js
index 7c969246..882cfffb 100644
--- a/public/viewjs/purchase.js
+++ b/public/viewjs/purchase.js
@@ -108,9 +108,7 @@ $('#save-purchase-button').on('click', function(e)
}
Grocy.Components.ProductAmountPicker.Reset();
- $("#display_amount").attr("min", "1");
- $("#display_amount").attr("step", "1");
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %s', '1'));
+ $("#display_amount").attr("min", "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
$('#display_amount').val(parseFloat(Grocy.UserSettings.stock_default_purchase_amount));
$(".input-group-productamountpicker").trigger("change");
$('#price').val('');
@@ -220,29 +218,15 @@ if (Grocy.Components.ProductPicker !== undefined)
refreshPriceHint();
- if (productDetails.product.allow_partial_units_in_stock == 1)
- {
- $("#display_amount").attr("min", "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#display_amount").attr("step", "." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %s', "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1"));
- }
- else
- {
- $("#display_amount").attr("min", "1");
- $("#display_amount").attr("step", "1");
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %s', '1'));
- }
-
if (productDetails.product.enable_tare_weight_handling == 1)
{
var minAmount = parseFloat(productDetails.product.tare_weight) / $("#qu_id option:selected").attr("data-qu-factor") + parseFloat(productDetails.stock_amount);
$("#display_amount").attr("min", minAmount);
- $("#display_amount").attr("step", "." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %s', minAmount.toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts })));
$("#tare-weight-handling-info").removeClass("d-none");
}
else
{
+ $("#display_amount").attr("min", "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
$("#tare-weight-handling-info").addClass("d-none");
}
diff --git a/public/viewjs/recipeposform.js b/public/viewjs/recipeposform.js
index 299e0848..0d564a61 100644
--- a/public/viewjs/recipeposform.js
+++ b/public/viewjs/recipeposform.js
@@ -62,19 +62,6 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
Grocy.Components.ProductAmountPicker.Reload(productDetails.product.id, productDetails.quantity_unit_stock.id);
}
- if (productDetails.product.allow_partial_units_in_stock == 1)
- {
- $("#display_amount").attr("min", "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#display_amount").attr("step", "." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %s', "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1"));
- }
- else
- {
- $("#display_amount").attr("min", "1");
- $("#display_amount").attr("step", "1");
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %s', '1'));
- }
-
if (Grocy.Mode == "create")
{
$("#not_check_stock_fulfillment").prop("checked", productDetails.product.not_check_stock_fulfillment_for_recipes == 1);
@@ -154,17 +141,13 @@ $("#only_check_single_unit_in_stock").on("click", function()
if (this.checked)
{
$("#display_amount").attr("min", "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#display_amount").attr("step", "." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#display_amount").parent().find(".invalid-feedback").text(__t("This cannot be negative"));
Grocy.Components.ProductAmountPicker.AllowAnyQu(true);
Grocy.FrontendHelpers.ValidateForm("recipe-pos-form");
}
else
{
$("#display_amount").attr("min", "0");
- $("#display_amount").attr("step", "1");
Grocy.Components.ProductPicker.GetPicker().trigger("change"); // Selects the default quantity unit of the selected product
- $("#display_amount").parent().find(".invalid-feedback").text(__t("This cannot be negative and must be an integral number"));
Grocy.Components.ProductAmountPicker.AllowAnyQuEnabled = false;
Grocy.FrontendHelpers.ValidateForm("recipe-pos-form");
}
diff --git a/public/viewjs/shoppinglistitemform.js b/public/viewjs/shoppinglistitemform.js
index 4ac4f663..76daeac9 100644
--- a/public/viewjs/shoppinglistitemform.js
+++ b/public/viewjs/shoppinglistitemform.js
@@ -216,5 +216,3 @@ if (GetUriParam("amount") !== undefined)
$(".input-group-productamountpicker").trigger("change");
Grocy.FrontendHelpers.ValidateForm('shoppinglist-form');
}
-
-$("#display_amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %s', "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1"));
diff --git a/public/viewjs/stockentryform.js b/public/viewjs/stockentryform.js
index 96181f50..75dc2e04 100644
--- a/public/viewjs/stockentryform.js
+++ b/public/viewjs/stockentryform.js
@@ -96,19 +96,6 @@ Grocy.Api.Get('stock/products/' + Grocy.EditObjectProductId,
function(productDetails)
{
$('#amount_qu_unit').text(productDetails.quantity_unit_stock.name);
-
- if (productDetails.product.allow_partial_units_in_stock == 1)
- {
- $("#amount").attr("min", "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#amount").attr("step", "." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %1$s', "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1"));
- }
- 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'));
- }
},
function(xhr)
{
diff --git a/public/viewjs/stockoverview.js b/public/viewjs/stockoverview.js
index c05b7708..bf00262a 100755
--- a/public/viewjs/stockoverview.js
+++ b/public/viewjs/stockoverview.js
@@ -1,6 +1,5 @@
var stockOverviewTable = $('#stock-overview-table').DataTable({
'order': [[4, 'asc']],
- 'colReorder': false,
'columnDefs': [
{ 'orderable': false, 'targets': 0 },
{ 'searchable': false, "targets": 0 },
diff --git a/public/viewjs/transfer.js b/public/viewjs/transfer.js
index 19606d47..db2ea93a 100644
--- a/public/viewjs/transfer.js
+++ b/public/viewjs/transfer.js
@@ -89,10 +89,8 @@
Grocy.Components.ProductAmountPicker.Reset();
$("#location_id_from").find("option").remove().end().append("");
- $("#display_amount").attr("min", "1");
+ $("#display_amount").attr("min", "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
$("#display_amount").attr("max", "999999");
- $("#display_amount").attr("step", "1");
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %s', '1'));
$('#display_amount').val(parseFloat(Grocy.UserSettings.stock_default_transfer_amount));
RefreshLocaleNumberInput();
$(".input-group-productamountpicker").trigger("change");
@@ -144,7 +142,7 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
if (productDetails.product.enable_tare_weight_handling == 1)
{
- Grocy.Components.ProductPicker.GetPicker().parent().find(".invalid-feedback").text(__t('Products with Tare weight enabled are currently not supported for Transfer. Please select another product.'));
+ Grocy.Components.ProductPicker.GetPicker().parent().find(".invalid-feedback").text(__t('Products with tare weight enabled are currently not supported for transfer'));
Grocy.Components.ProductPicker.Clear();
return;
}
@@ -189,19 +187,6 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
}
);
- if (productDetails.product.allow_partial_units_in_stock == 1)
- {
- $("#display_amount").attr("min", "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#display_amount").attr("step", "." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount must be between %1$s and %2$s', "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1"));
- }
- else
- {
- $("#display_amount").attr("min", "1");
- $("#display_amount").attr("step", "1");
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount must be between %1$s and %2$s', "1", parseFloat(productDetails.stock_amount).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: 4 })));
- }
-
if (productDetails.product.enable_tare_weight_handling == 1)
{
$("#display_amount").attr("min", productDetails.product.tare_weight);
@@ -209,6 +194,7 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
}
else
{
+ $("#display_amount").attr("min", "0." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
$("#tare-weight-handling-info").addClass("d-none");
}
@@ -293,10 +279,6 @@ $("#location_id_from").on('change', function(e)
{
$("#display_amount").parent().find(".invalid-feedback").text(__t('There are no units available at this location'));
}
- else
- {
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount must be between %1$s and %2$s', "1", sumValue));
- }
},
function(xhr)
{
@@ -369,10 +351,6 @@ $("#specific_stock_entry").on("change", function(e)
{
$("#display_amount").parent().find(".invalid-feedback").text(__t('There are no units available at this location'));
}
- else
- {
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount must be between %1$s and %2$s', "1", sumValue));
- }
},
function(xhr)
{
@@ -382,7 +360,6 @@ $("#specific_stock_entry").on("change", function(e)
}
else
{
- $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount must be between %1$s and %2$s', "1", $('option:selected', this).attr('amount')));
$("#display_amount").attr("max", $('option:selected', this).attr('amount'));
}
});
diff --git a/views/barcodescannertesting.blade.php b/views/barcodescannertesting.blade.php
index bf9903d6..b03b7d34 100644
--- a/views/barcodescannertesting.blade.php
+++ b/views/barcodescannertesting.blade.php
@@ -55,7 +55,7 @@
{{ $__t('Miss') }}: 0
- {{ $__t('Battery') }}
-
@foreach($batteries as $battery)
diff --git a/views/batteriesoverview.blade.php b/views/batteriesoverview.blade.php
index 67924e29..2a05ae9f 100644
--- a/views/batteriesoverview.blade.php
+++ b/views/batteriesoverview.blade.php
@@ -71,7 +71,7 @@