From 828ab8eba08630fc5df7f430cc06e360a2120182 Mon Sep 17 00:00:00 2001 From: Bernd Bestel Date: Thu, 26 Sep 2019 10:36:49 +0200 Subject: [PATCH 01/14] Allow accumulating min. stock amounts on parent product level (closes #384) --- changelog/53_UNRELEASED_2019-xx-xx.md | 1 + localization/strings.pot | 6 ++ migrations/0092.sql | 131 ++++++++++++++++++++++++++ views/productform.blade.php | 13 ++- 4 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 migrations/0092.sql diff --git a/changelog/53_UNRELEASED_2019-xx-xx.md b/changelog/53_UNRELEASED_2019-xx-xx.md index fc4244eb..887af78a 100644 --- a/changelog/53_UNRELEASED_2019-xx-xx.md +++ b/changelog/53_UNRELEASED_2019-xx-xx.md @@ -1,4 +1,5 @@ - Fixed that barcode lookups now compare the whole barcode, not parts of it (e. g. when you have two products with the barcodes "$1" and "$10" and scan "$1" maybe the product of "$10" was found till now) +- It's now possible to accumulate min. stock amounts on parent product level (new option per product, means the sub product will never be "missing" then, only the parent product) - It's now possible to display a recipe directly from the meal plan (new "eye button") (thanks @kriddles) - Improved the responsiveness of the meal plan and calendar page by automatically switching to a day calendar view on smaller screens (thanks for the idea @kriddles) - The calendar now also contains all planned recipes from the meal plan on the corresponding day diff --git a/localization/strings.pot b/localization/strings.pot index 136583c5..de8b4179 100644 --- a/localization/strings.pot +++ b/localization/strings.pot @@ -1519,3 +1519,9 @@ msgstr "" msgid "Display recipe" msgstr "" + +msgid "Accumulate sub products min. stock amount" +msgstr "" + +msgid "If enabled, the min. stock amount of sub products will be accumulated into this product, means the sub product will never be \"missing\", only this product" +msgstr "" diff --git a/migrations/0092.sql b/migrations/0092.sql new file mode 100644 index 00000000..f4cf3f57 --- /dev/null +++ b/migrations/0092.sql @@ -0,0 +1,131 @@ +ALTER TABLE products +ADD cumulate_min_stock_amount_of_subproducts TINYINT DEFAULT 0; + +CREATE VIEW products_view +AS +SELECT *, CASE WHEN (SELECT 1 FROM products WHERE parent_product_id = p.id) NOTNULL THEN 1 ELSE 0 END AS has_sub_products +FROM products p; + +DROP VIEW stock_missing_products; +CREATE VIEW stock_missing_products +AS + +-- Products which are not sub products and not with "cumulate_min_stock_amount_of_subproducts" +SELECT + p.id, + MAX(p.name) AS name, + p.min_stock_amount - IFNULL(SUM(s.amount), 0) AS amount_missing, + CASE WHEN IFNULL(SUM(s.amount), 0) > 0 THEN 1 ELSE 0 END AS is_partly_in_stock +FROM products_view p +LEFT JOIN stock_current s + ON p.id = s.product_id +WHERE p.min_stock_amount != 0 + AND p.cumulate_min_stock_amount_of_subproducts = 0 + AND p.parent_product_id IS NULL +GROUP BY p.id +HAVING IFNULL(SUM(s.amount), 0) < p.min_stock_amount + +UNION + +-- Products which have sub products and with "cumulate_min_stock_amount_of_subproducts" +SELECT + p.id, + MAX(p.name) AS name, + SUM(sub_p.min_stock_amount) - IFNULL(SUM(s.amount), 0) AS amount_missing, + CASE WHEN IFNULL(SUM(s.amount), 0) > 0 THEN 1 ELSE 0 END AS is_partly_in_stock +FROM products_view p +JOIN products_resolved pr + ON p.id = pr.parent_product_id +JOIN products sub_p + ON pr.sub_product_id = sub_p.id +LEFT JOIN stock_current s + ON pr.sub_product_id = s.product_id +WHERE sub_p.min_stock_amount != 0 + AND p.cumulate_min_stock_amount_of_subproducts = 1 + AND p.has_sub_products IS NOT NULL +GROUP BY p.id +HAVING IFNULL(SUM(s.amount), 0) < SUM(sub_p.min_stock_amount) + +UNION + +-- Sub products where the parent product has not "cumulate_min_stock_amount_of_subproducts" +SELECT + sub_p.id, + MAX(sub_p.name) AS name, + SUM(sub_p.min_stock_amount) - IFNULL(SUM(s.amount), 0) AS amount_missing, + CASE WHEN IFNULL(SUM(s.amount), 0) > 0 THEN 1 ELSE 0 END AS is_partly_in_stock +FROM products_view p +JOIN products_resolved pr + ON p.id = pr.parent_product_id +JOIN products sub_p + ON pr.sub_product_id = sub_p.id +LEFT JOIN stock_current s + ON pr.sub_product_id = s.product_id +WHERE sub_p.min_stock_amount != 0 + AND p.cumulate_min_stock_amount_of_subproducts = 0 + AND sub_p.parent_product_id IS NOT NULL +GROUP BY sub_p.id +HAVING IFNULL(SUM(s.amount), 0) < sub_p.min_stock_amount; + +DROP VIEW stock_missing_products_including_opened; +CREATE VIEW stock_missing_products_including_opened +AS + +/* This is basically the same view as stock_missing_products, but the column amount_missing includes opened amounts */ + +-- Products which are not sub products and not with "cumulate_min_stock_amount_of_subproducts" +SELECT + p.id, + MAX(p.name) AS name, + p.min_stock_amount - (IFNULL(SUM(s.amount), 0) - IFNULL(SUM(s.amount_opened), 0)) AS amount_missing, + CASE WHEN IFNULL(SUM(s.amount), 0) > 0 THEN 1 ELSE 0 END AS is_partly_in_stock +FROM products_view p +LEFT JOIN stock_current s + ON p.id = s.product_id +WHERE p.min_stock_amount != 0 + AND p.cumulate_min_stock_amount_of_subproducts = 0 + AND p.parent_product_id IS NULL +GROUP BY p.id +HAVING IFNULL(SUM(s.amount), 0) < p.min_stock_amount + +UNION + +-- Products which have sub products and with "cumulate_min_stock_amount_of_subproducts" +SELECT + p.id, + MAX(p.name) AS name, + SUM(sub_p.min_stock_amount) - (IFNULL(SUM(s.amount), 0) - IFNULL(SUM(s.amount_opened), 0)) AS amount_missing, + CASE WHEN IFNULL(SUM(s.amount), 0) > 0 THEN 1 ELSE 0 END AS is_partly_in_stock +FROM products_view p +JOIN products_resolved pr + ON p.id = pr.parent_product_id +JOIN products sub_p + ON pr.sub_product_id = sub_p.id +LEFT JOIN stock_current s + ON pr.sub_product_id = s.product_id +WHERE sub_p.min_stock_amount != 0 + AND p.cumulate_min_stock_amount_of_subproducts = 1 + AND p.has_sub_products IS NOT NULL +GROUP BY p.id +HAVING IFNULL(SUM(s.amount), 0) < SUM(sub_p.min_stock_amount) + +UNION + +-- Sub products where the parent product has not "cumulate_min_stock_amount_of_subproducts" +SELECT + sub_p.id, + MAX(sub_p.name) AS name, + SUM(sub_p.min_stock_amount) - (IFNULL(SUM(s.amount), 0) - IFNULL(SUM(s.amount_opened), 0)) AS amount_missing, + CASE WHEN IFNULL(SUM(s.amount), 0) > 0 THEN 1 ELSE 0 END AS is_partly_in_stock +FROM products_view p +JOIN products_resolved pr + ON p.id = pr.parent_product_id +JOIN products sub_p + ON pr.sub_product_id = sub_p.id +LEFT JOIN stock_current s + ON pr.sub_product_id = s.product_id +WHERE sub_p.min_stock_amount != 0 + AND p.cumulate_min_stock_amount_of_subproducts = 0 + AND sub_p.parent_product_id IS NOT NULL +GROUP BY sub_p.id +HAVING IFNULL(SUM(s.amount), 0) < sub_p.min_stock_amount; diff --git a/views/productform.blade.php b/views/productform.blade.php index f6ccda39..cac44599 100644 --- a/views/productform.blade.php +++ b/views/productform.blade.php @@ -94,9 +94,20 @@ 'label' => 'Minimum stock amount', 'min' => 0, 'value' => $value, - 'invalidFeedback' => $__t('The amount cannot be lower than %s', '0') + 'invalidFeedback' => $__t('The amount cannot be lower than %s', '0'), + 'additionalGroupCssClasses' => 'mb-1' )) +
+
+ + cumulate_min_stock_amount_of_subproducts == 1) checked @endif class="form-check-input" type="checkbox" id="cumulate_min_stock_amount_of_subproducts" name="cumulate_min_stock_amount_of_subproducts" value="1"> + +
+
+ @php if($mode == 'edit') { $value = $product->default_best_before_days; } else { $value = 0; } @endphp @include('components.numberpicker', array( 'id' => 'default_best_before_days', From c5927a10f3a682cfa917ff845e4c3191dc471e85 Mon Sep 17 00:00:00 2001 From: DeeeeLAN Date: Thu, 26 Sep 2019 02:42:30 -0700 Subject: [PATCH 02/14] fixed recipe ingredient layout issue in safari (#387) * fixed barcode button on iOS and made nicer on the desktop * fixed indentation * fixed indentation * fixed recipe ingredient layout issue in safari --- public/css/grocy.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/public/css/grocy.css b/public/css/grocy.css index ef7412de..81a0520e 100644 --- a/public/css/grocy.css +++ b/public/css/grocy.css @@ -317,3 +317,8 @@ canvas.drawingBuffer { left: 0; top: 0; } + +/* Third party component customizations - Bootstrap list-group */ +.list-group { + flex-shrink: 0; +} From 02f30d141e8e9c01aa95fca439a537dd798a2549 Mon Sep 17 00:00:00 2001 From: Bernd Bestel Date: Thu, 26 Sep 2019 12:43:00 +0200 Subject: [PATCH 03/14] Reviewed/optimized last changes (references #384) --- migrations/0092.sql | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/migrations/0092.sql b/migrations/0092.sql index f4cf3f57..aa3b8215 100644 --- a/migrations/0092.sql +++ b/migrations/0092.sql @@ -1,39 +1,33 @@ ALTER TABLE products ADD cumulate_min_stock_amount_of_subproducts TINYINT DEFAULT 0; -CREATE VIEW products_view -AS -SELECT *, CASE WHEN (SELECT 1 FROM products WHERE parent_product_id = p.id) NOTNULL THEN 1 ELSE 0 END AS has_sub_products -FROM products p; - DROP VIEW stock_missing_products; CREATE VIEW stock_missing_products AS --- Products which are not sub products and not with "cumulate_min_stock_amount_of_subproducts" +-- Parent products where the amount of the sub products SHOULD NOT be cumulated SELECT p.id, MAX(p.name) AS name, p.min_stock_amount - IFNULL(SUM(s.amount), 0) AS amount_missing, CASE WHEN IFNULL(SUM(s.amount), 0) > 0 THEN 1 ELSE 0 END AS is_partly_in_stock -FROM products_view p +FROM products p LEFT JOIN stock_current s ON p.id = s.product_id WHERE p.min_stock_amount != 0 AND p.cumulate_min_stock_amount_of_subproducts = 0 - AND p.parent_product_id IS NULL GROUP BY p.id HAVING IFNULL(SUM(s.amount), 0) < p.min_stock_amount UNION --- Products which have sub products and with "cumulate_min_stock_amount_of_subproducts" +-- Parent products where the amount of the sub products SHOULD be cumulated SELECT p.id, MAX(p.name) AS name, SUM(sub_p.min_stock_amount) - IFNULL(SUM(s.amount), 0) AS amount_missing, CASE WHEN IFNULL(SUM(s.amount), 0) > 0 THEN 1 ELSE 0 END AS is_partly_in_stock -FROM products_view p +FROM products p JOIN products_resolved pr ON p.id = pr.parent_product_id JOIN products sub_p @@ -42,19 +36,18 @@ LEFT JOIN stock_current s ON pr.sub_product_id = s.product_id WHERE sub_p.min_stock_amount != 0 AND p.cumulate_min_stock_amount_of_subproducts = 1 - AND p.has_sub_products IS NOT NULL GROUP BY p.id HAVING IFNULL(SUM(s.amount), 0) < SUM(sub_p.min_stock_amount) UNION --- Sub products where the parent product has not "cumulate_min_stock_amount_of_subproducts" +-- Sub products where the amount SHOULD NOT be cumulated into the parent product SELECT sub_p.id, MAX(sub_p.name) AS name, SUM(sub_p.min_stock_amount) - IFNULL(SUM(s.amount), 0) AS amount_missing, CASE WHEN IFNULL(SUM(s.amount), 0) > 0 THEN 1 ELSE 0 END AS is_partly_in_stock -FROM products_view p +FROM products p JOIN products_resolved pr ON p.id = pr.parent_product_id JOIN products sub_p @@ -63,7 +56,6 @@ LEFT JOIN stock_current s ON pr.sub_product_id = s.product_id WHERE sub_p.min_stock_amount != 0 AND p.cumulate_min_stock_amount_of_subproducts = 0 - AND sub_p.parent_product_id IS NOT NULL GROUP BY sub_p.id HAVING IFNULL(SUM(s.amount), 0) < sub_p.min_stock_amount; @@ -71,32 +63,31 @@ DROP VIEW stock_missing_products_including_opened; CREATE VIEW stock_missing_products_including_opened AS -/* This is basically the same view as stock_missing_products, but the column amount_missing includes opened amounts */ +/* This is basically the same view as stock_missing_products, but the column "amount_missing" includes opened amounts */ --- Products which are not sub products and not with "cumulate_min_stock_amount_of_subproducts" +-- Parent products where the amount of the sub products SHOULD NOT be cumulated SELECT p.id, MAX(p.name) AS name, p.min_stock_amount - (IFNULL(SUM(s.amount), 0) - IFNULL(SUM(s.amount_opened), 0)) AS amount_missing, CASE WHEN IFNULL(SUM(s.amount), 0) > 0 THEN 1 ELSE 0 END AS is_partly_in_stock -FROM products_view p +FROM products p LEFT JOIN stock_current s ON p.id = s.product_id WHERE p.min_stock_amount != 0 AND p.cumulate_min_stock_amount_of_subproducts = 0 - AND p.parent_product_id IS NULL GROUP BY p.id HAVING IFNULL(SUM(s.amount), 0) < p.min_stock_amount UNION --- Products which have sub products and with "cumulate_min_stock_amount_of_subproducts" +-- Parent products where the amount of the sub products SHOULD be cumulated SELECT p.id, MAX(p.name) AS name, SUM(sub_p.min_stock_amount) - (IFNULL(SUM(s.amount), 0) - IFNULL(SUM(s.amount_opened), 0)) AS amount_missing, CASE WHEN IFNULL(SUM(s.amount), 0) > 0 THEN 1 ELSE 0 END AS is_partly_in_stock -FROM products_view p +FROM products p JOIN products_resolved pr ON p.id = pr.parent_product_id JOIN products sub_p @@ -105,19 +96,18 @@ LEFT JOIN stock_current s ON pr.sub_product_id = s.product_id WHERE sub_p.min_stock_amount != 0 AND p.cumulate_min_stock_amount_of_subproducts = 1 - AND p.has_sub_products IS NOT NULL GROUP BY p.id HAVING IFNULL(SUM(s.amount), 0) < SUM(sub_p.min_stock_amount) UNION --- Sub products where the parent product has not "cumulate_min_stock_amount_of_subproducts" +-- Sub products where the amount SHOULD NOT be cumulated into the parent product SELECT sub_p.id, MAX(sub_p.name) AS name, SUM(sub_p.min_stock_amount) - (IFNULL(SUM(s.amount), 0) - IFNULL(SUM(s.amount_opened), 0)) AS amount_missing, CASE WHEN IFNULL(SUM(s.amount), 0) > 0 THEN 1 ELSE 0 END AS is_partly_in_stock -FROM products_view p +FROM products p JOIN products_resolved pr ON p.id = pr.parent_product_id JOIN products sub_p @@ -126,6 +116,5 @@ LEFT JOIN stock_current s ON pr.sub_product_id = s.product_id WHERE sub_p.min_stock_amount != 0 AND p.cumulate_min_stock_amount_of_subproducts = 0 - AND sub_p.parent_product_id IS NOT NULL GROUP BY sub_p.id HAVING IFNULL(SUM(s.amount), 0) < sub_p.min_stock_amount; From 2809cc1454760c78d7fdeca74d5d509cbc7c60aa Mon Sep 17 00:00:00 2001 From: Bernd Bestel Date: Thu, 26 Sep 2019 12:45:35 +0200 Subject: [PATCH 04/14] Typo... --- migrations/0092.sql | 14 +++++++------- views/productform.blade.php | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/migrations/0092.sql b/migrations/0092.sql index aa3b8215..825d71d8 100644 --- a/migrations/0092.sql +++ b/migrations/0092.sql @@ -1,5 +1,5 @@ ALTER TABLE products -ADD cumulate_min_stock_amount_of_subproducts TINYINT DEFAULT 0; +ADD cumulate_min_stock_amount_of_sub_products TINYINT DEFAULT 0; DROP VIEW stock_missing_products; CREATE VIEW stock_missing_products @@ -15,7 +15,7 @@ FROM products p LEFT JOIN stock_current s ON p.id = s.product_id WHERE p.min_stock_amount != 0 - AND p.cumulate_min_stock_amount_of_subproducts = 0 + AND p.cumulate_min_stock_amount_of_sub_products = 0 GROUP BY p.id HAVING IFNULL(SUM(s.amount), 0) < p.min_stock_amount @@ -35,7 +35,7 @@ JOIN products sub_p LEFT JOIN stock_current s ON pr.sub_product_id = s.product_id WHERE sub_p.min_stock_amount != 0 - AND p.cumulate_min_stock_amount_of_subproducts = 1 + AND p.cumulate_min_stock_amount_of_sub_products = 1 GROUP BY p.id HAVING IFNULL(SUM(s.amount), 0) < SUM(sub_p.min_stock_amount) @@ -55,7 +55,7 @@ JOIN products sub_p LEFT JOIN stock_current s ON pr.sub_product_id = s.product_id WHERE sub_p.min_stock_amount != 0 - AND p.cumulate_min_stock_amount_of_subproducts = 0 + AND p.cumulate_min_stock_amount_of_sub_products = 0 GROUP BY sub_p.id HAVING IFNULL(SUM(s.amount), 0) < sub_p.min_stock_amount; @@ -75,7 +75,7 @@ FROM products p LEFT JOIN stock_current s ON p.id = s.product_id WHERE p.min_stock_amount != 0 - AND p.cumulate_min_stock_amount_of_subproducts = 0 + AND p.cumulate_min_stock_amount_of_sub_products = 0 GROUP BY p.id HAVING IFNULL(SUM(s.amount), 0) < p.min_stock_amount @@ -95,7 +95,7 @@ JOIN products sub_p LEFT JOIN stock_current s ON pr.sub_product_id = s.product_id WHERE sub_p.min_stock_amount != 0 - AND p.cumulate_min_stock_amount_of_subproducts = 1 + AND p.cumulate_min_stock_amount_of_sub_products = 1 GROUP BY p.id HAVING IFNULL(SUM(s.amount), 0) < SUM(sub_p.min_stock_amount) @@ -115,6 +115,6 @@ JOIN products sub_p LEFT JOIN stock_current s ON pr.sub_product_id = s.product_id WHERE sub_p.min_stock_amount != 0 - AND p.cumulate_min_stock_amount_of_subproducts = 0 + AND p.cumulate_min_stock_amount_of_sub_products = 0 GROUP BY sub_p.id HAVING IFNULL(SUM(s.amount), 0) < sub_p.min_stock_amount; diff --git a/views/productform.blade.php b/views/productform.blade.php index cac44599..ff3dc97c 100644 --- a/views/productform.blade.php +++ b/views/productform.blade.php @@ -100,9 +100,9 @@
- - cumulate_min_stock_amount_of_subproducts == 1) checked @endif class="form-check-input" type="checkbox" id="cumulate_min_stock_amount_of_subproducts" name="cumulate_min_stock_amount_of_subproducts" value="1"> -
From 45d3c25b2134a7663eb5d04d161a1855484248b9 Mon Sep 17 00:00:00 2001 From: Bernd Bestel Date: Thu, 26 Sep 2019 13:13:49 +0200 Subject: [PATCH 05/14] Again optimizations for #384 --- migrations/0092.sql | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/migrations/0092.sql b/migrations/0092.sql index 825d71d8..6e76866b 100644 --- a/migrations/0092.sql +++ b/migrations/0092.sql @@ -1,33 +1,40 @@ ALTER TABLE products ADD cumulate_min_stock_amount_of_sub_products TINYINT DEFAULT 0; +CREATE VIEW products_view +AS +SELECT *, CASE WHEN (SELECT 1 FROM products WHERE parent_product_id = p.id) NOTNULL THEN 1 ELSE 0 END AS has_sub_products +FROM products p; + DROP VIEW stock_missing_products; CREATE VIEW stock_missing_products AS --- Parent products where the amount of the sub products SHOULD NOT be cumulated +-- Products WITHOUT sub products where the amount of the sub products SHOULD NOT be cumulated SELECT p.id, MAX(p.name) AS name, p.min_stock_amount - IFNULL(SUM(s.amount), 0) AS amount_missing, CASE WHEN IFNULL(SUM(s.amount), 0) > 0 THEN 1 ELSE 0 END AS is_partly_in_stock -FROM products p +FROM products_view p LEFT JOIN stock_current s ON p.id = s.product_id WHERE p.min_stock_amount != 0 AND p.cumulate_min_stock_amount_of_sub_products = 0 + AND p.has_sub_products = 0 + AND p.parent_product_id IS NULL GROUP BY p.id HAVING IFNULL(SUM(s.amount), 0) < p.min_stock_amount UNION --- Parent products where the amount of the sub products SHOULD be cumulated +-- Parent products WITH sub products where the amount of the sub products SHOULD be cumulated SELECT p.id, MAX(p.name) AS name, SUM(sub_p.min_stock_amount) - IFNULL(SUM(s.amount), 0) AS amount_missing, CASE WHEN IFNULL(SUM(s.amount), 0) > 0 THEN 1 ELSE 0 END AS is_partly_in_stock -FROM products p +FROM products_view p JOIN products_resolved pr ON p.id = pr.parent_product_id JOIN products sub_p @@ -65,29 +72,31 @@ AS /* This is basically the same view as stock_missing_products, but the column "amount_missing" includes opened amounts */ --- Parent products where the amount of the sub products SHOULD NOT be cumulated +-- Products WITHOUT sub products where the amount of the sub products SHOULD NOT be cumulated SELECT p.id, MAX(p.name) AS name, p.min_stock_amount - (IFNULL(SUM(s.amount), 0) - IFNULL(SUM(s.amount_opened), 0)) AS amount_missing, CASE WHEN IFNULL(SUM(s.amount), 0) > 0 THEN 1 ELSE 0 END AS is_partly_in_stock -FROM products p +FROM products_view p LEFT JOIN stock_current s ON p.id = s.product_id WHERE p.min_stock_amount != 0 AND p.cumulate_min_stock_amount_of_sub_products = 0 + AND p.has_sub_products = 0 + AND p.parent_product_id IS NULL GROUP BY p.id HAVING IFNULL(SUM(s.amount), 0) < p.min_stock_amount UNION --- Parent products where the amount of the sub products SHOULD be cumulated +-- Parent products WITH sub products where the amount of the sub products SHOULD be cumulated SELECT p.id, MAX(p.name) AS name, SUM(sub_p.min_stock_amount) - (IFNULL(SUM(s.amount), 0) - IFNULL(SUM(s.amount_opened), 0)) AS amount_missing, CASE WHEN IFNULL(SUM(s.amount), 0) > 0 THEN 1 ELSE 0 END AS is_partly_in_stock -FROM products p +FROM products_view p JOIN products_resolved pr ON p.id = pr.parent_product_id JOIN products sub_p From a2b6d9ae39d616387fc2b966d0196e19241e9f1d Mon Sep 17 00:00:00 2001 From: Bernd Bestel Date: Thu, 26 Sep 2019 13:14:24 +0200 Subject: [PATCH 06/14] Various small UI refinements --- public/viewjs/equipment.js | 1 + public/viewjs/mealplan.js | 13 +++++++++++++ views/equipment.blade.php | 10 +++++----- views/productform.blade.php | 2 +- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/public/viewjs/equipment.js b/public/viewjs/equipment.js index 7d376510..f9198cf9 100644 --- a/public/viewjs/equipment.js +++ b/public/viewjs/equipment.js @@ -131,4 +131,5 @@ $("#selectedEquipmentDescriptionToggleFullscreenButton").on('click', function(e) $("#selectedEquipmentDescriptionCard").toggleClass("fullscreen"); $("#selectedEquipmentDescriptionCard .card-header").toggleClass("fixed-top"); $("#selectedEquipmentDescriptionCard .card-body").toggleClass("mt-5"); + $("body").toggleClass("fullscreen-card"); }); diff --git a/public/viewjs/mealplan.js b/public/viewjs/mealplan.js index 240d502c..09210559 100644 --- a/public/viewjs/mealplan.js +++ b/public/viewjs/mealplan.js @@ -116,6 +116,7 @@ var calendar = $("#calendar").fullCalendar({ { RefreshLocaleNumberDisplay(); LoadImagesLazy(); + $('[data-toggle="tooltip"]').tooltip(); if (GetUriParam("week") !== undefined) { @@ -213,6 +214,10 @@ $(document).on("keyodwn", "#servings", function(e) $(document).on('click', '.recipe-order-missing-button', function(e) { + // Remove the focus from the current button + // to prevent that the tooltip stays until clicked anywhere else + document.activeElement.blur(); + var objectName = $(e.currentTarget).attr('data-recipe-name'); var objectId = $(e.currentTarget).attr('data-recipe-id'); var button = $(this); @@ -262,6 +267,10 @@ $(document).on('click', '.recipe-order-missing-button', function(e) $(document).on('click', '.recipe-consume-button', function(e) { + // Remove the focus from the current button + // to prevent that the tooltip stays until clicked anywhere else + document.activeElement.blur(); + var objectName = $(e.currentTarget).attr('data-recipe-name'); var objectId = $(e.currentTarget).attr('data-recipe-id'); @@ -304,6 +313,10 @@ $(document).on('click', '.recipe-consume-button', function(e) $(document).on("click", ".recipe-popup-button", function(e) { + // Remove the focus from the current button + // to prevent that the tooltip stays until clicked anywhere else + document.activeElement.blur(); + var objectId = $(e.currentTarget).attr('data-recipe-id'); bootbox.dialog({ diff --git a/views/equipment.blade.php b/views/equipment.blade.php index 4667288b..cca752f8 100644 --- a/views/equipment.blade.php +++ b/views/equipment.blade.php @@ -61,10 +61,10 @@
-

{{ $__t('The selected equipment has no instruction manual') }}

+

{{ $__t('The selected equipment has no instruction manual') }}

@@ -81,10 +81,10 @@ -
+
enable_tare_weight_handling == 1) checked @endif class="form-check-input" type="checkbox" id="enable_tare_weight_handling" name="enable_tare_weight_handling" value="1"> From b8f9d09afc9e23c08abb0ebac17512e31f33f605 Mon Sep 17 00:00:00 2001 From: Bernd Bestel Date: Thu, 26 Sep 2019 13:55:42 +0200 Subject: [PATCH 07/14] Don't remove products from stock overview on consuming all and the product has a min. stock amount & show it again on undo --- public/js/grocy.js | 13 +++++++++++++ public/viewjs/stockoverview.js | 12 ++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/public/js/grocy.js b/public/js/grocy.js index 8d3e725e..a74f2502 100644 --- a/public/js/grocy.js +++ b/public/js/grocy.js @@ -298,8 +298,21 @@ RefreshContextualTimeago = function() $("time.timeago").each(function() { var element = $(this); + + if (!element.hasAttr("datetime")) + { + element.text("") + return + } + var timestamp = element.attr("datetime"); + if (timestamp.isEmpty()) + { + element.text("") + return + } + var isNever = timestamp && timestamp.substring(0, 10) == "2999-12-31"; var isToday = timestamp && timestamp.substring(0, 10) == moment().format("YYYY-MM-DD"); var isDateWithoutTime = element.hasClass("timeago-date-only"); diff --git a/public/viewjs/stockoverview.js b/public/viewjs/stockoverview.js index ac5d0788..d66f73c1 100644 --- a/public/viewjs/stockoverview.js +++ b/public/viewjs/stockoverview.js @@ -319,6 +319,9 @@ function RefreshProductRow(productId) productRow.removeClass("table-warning"); productRow.removeClass("table-danger"); + productRow.removeClass("table-info"); + productRow.removeClass("d-none"); + productRow.removeAttr("style"); if (now.isAfter(nextBestBeforeDate)) { productRow.addClass("table-danger"); @@ -328,12 +331,12 @@ function RefreshProductRow(productId) productRow.addClass("table-warning"); } - if (result.stock_amount <= 0) + if (result.stock_amount == 0 && result.product.min_stock_amount == 0) { $('#product-' + productId + '-row').fadeOut(500, function() { $(this).tooltip("hide"); - $(this).remove(); + $(this).addClass("d-none"); }); } else @@ -366,6 +369,11 @@ function RefreshProductRow(productId) $(this).text("").fadeIn(500); } }); + + if (result.stock_amount == 0 && result.product.min_stock_amount > 0) + { + productRow.addClass("table-info"); + } } $('#product-' + productId + '-next-best-before-date').parent().effect('highlight', {}, 500); From b39866bda2f0c03b98b5e836065de29a046f4a4e Mon Sep 17 00:00:00 2001 From: Bernd Bestel Date: Thu, 26 Sep 2019 13:59:41 +0200 Subject: [PATCH 08/14] Immediately refresh the QU conversion hint on key presses on the product edit page --- public/viewjs/productform.js | 1 + 1 file changed, 1 insertion(+) diff --git a/public/viewjs/productform.js b/public/viewjs/productform.js index 3df99660..eb81f018 100644 --- a/public/viewjs/productform.js +++ b/public/viewjs/productform.js @@ -222,6 +222,7 @@ $('.input-group-qu').on('change', function(e) $('#product-form input').keyup(function(event) { Grocy.FrontendHelpers.ValidateForm('product-form'); + $(".input-group-qu").trigger("change"); if (document.getElementById('product-form').checkValidity() === false) //There is at least one validation error { From 41e93d2c5079de645eaf35d366cd77af0e8607f8 Mon Sep 17 00:00:00 2001 From: Bernd Bestel Date: Thu, 26 Sep 2019 14:13:30 +0200 Subject: [PATCH 09/14] Little night mode improvements --- public/css/grocy_night_mode.css | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/public/css/grocy_night_mode.css b/public/css/grocy_night_mode.css index 89d7091d..801f9901 100644 --- a/public/css/grocy_night_mode.css +++ b/public/css/grocy_night_mode.css @@ -4,7 +4,8 @@ .night-mode .table-info, .night-mode .table-info > td, -.night-mode .table-info > th { +.night-mode .table-info > th, +.night-mode .alert-info { background-color: #07373f; color: #6c757d; } @@ -54,14 +55,17 @@ border-color: #0d3a18; } -.night-mode .btn-light { +.night-mode .btn-light, +.night-mode .input-group-text, +.night-mode .note-editor.note-frame .note-statusbar, +.night-mode .img-thumbnail { color: #c1c1c1; background-color: #292b2a; border-color: #292b2a; } .night-mode .form-control { - color: #495057; + color: #ced4da; background-color: #333131; border: 1px solid #ced4da; } @@ -100,7 +104,7 @@ } .night-mode .form-control:focus { - color: #495057; + color: #ced4da; background-color: #333131; border-color: #80bdff; } From 7369603d7844e897d2b14fd42b40d62f754748f0 Mon Sep 17 00:00:00 2001 From: Bernd Bestel Date: Thu, 26 Sep 2019 14:55:31 +0200 Subject: [PATCH 10/14] Added missing localization string --- localization/strings.pot | 3 +++ 1 file changed, 3 insertions(+) diff --git a/localization/strings.pot b/localization/strings.pot index de8b4179..89cc8cfe 100644 --- a/localization/strings.pot +++ b/localization/strings.pot @@ -1525,3 +1525,6 @@ msgstr "" msgid "If enabled, the min. stock amount of sub products will be accumulated into this product, means the sub product will never be \"missing\", only this product" msgstr "" + +msgid "Are you sure to remove this conversion?" +msgstr "" From 21503c26d2f1eb44377056ac8035e0f91892d4fa Mon Sep 17 00:00:00 2001 From: Bernd Bestel Date: Thu, 26 Sep 2019 15:25:30 +0200 Subject: [PATCH 11/14] Use properly formatted numbers "everywhere" (partly references #389) --- public/js/grocy.js | 21 ++++++++++++++++++--- public/viewjs/mealplan.js | 4 ++-- views/barcodescannertesting.blade.php | 4 ++-- views/components/batterycard.blade.php | 2 +- views/components/chorecard.blade.php | 2 +- views/components/productcard.blade.php | 4 ++-- views/locationcontentsheet.blade.php | 2 +- views/productform.blade.php | 2 +- views/products.blade.php | 4 ++-- views/recipeform.blade.php | 2 +- views/recipes.blade.php | 8 ++++---- views/shoppinglist.blade.php | 2 +- views/stockjournal.blade.php | 2 +- views/stockoverview.blade.php | 4 ++-- 14 files changed, 39 insertions(+), 24 deletions(-) diff --git a/public/js/grocy.js b/public/js/grocy.js index a74f2502..637e5503 100644 --- a/public/js/grocy.js +++ b/public/js/grocy.js @@ -528,18 +528,33 @@ $("#about-dialog-link").on("click", function() function RefreshLocaleNumberDisplay() { - $(".locale-number-format[data-format='currency']").each(function() + $(".locale-number.locale-number-currency").each(function() { + if (isNaN(parseFloat($(this).text()))) + { + return; + } + $(this).text(parseFloat($(this).text()).toLocaleString(undefined, { style: "currency", currency: Grocy.Currency })); }); - $(".locale-number-format[data-format='quantity-amount']").each(function() + $(".locale-number.locale-number-quantity-amount").each(function() { + if (isNaN(parseFloat($(this).text()))) + { + return; + } + $(this).text(parseFloat($(this).text()).toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 3 })); }); - $(".locale-number-format[data-format='generic']").each(function () + $(".locale-number.locale-number-generic").each(function () { + if (isNaN(parseFloat($(this).text()))) + { + return; + } + $(this).text(parseFloat($(this).text()).toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 2 })); }); } diff --git a/public/viewjs/mealplan.js b/public/viewjs/mealplan.js index 09210559..9c987d07 100644 --- a/public/viewjs/mealplan.js +++ b/public/viewjs/mealplan.js @@ -54,7 +54,7 @@ var calendar = $("#calendar").fullCalendar({ weekRecipeOrderMissingButtonHtml = '' weekRecipeConsumeButtonHtml = '' } - $(".fc-header-toolbar .fc-center").html("

" + __t("Week costs") + ': ' + weekCosts.toString() + " " + weekRecipeOrderMissingButtonHtml + weekRecipeConsumeButtonHtml + "

"); + $(".fc-header-toolbar .fc-center").html("

" + __t("Week costs") + ': ' + weekCosts.toString() + " " + weekRecipeOrderMissingButtonHtml + weekRecipeConsumeButtonHtml + "

"); }, "eventRender": function(event, element) { @@ -98,7 +98,7 @@ var calendar = $("#calendar").fullCalendar({
' + recipe.name + '
\
' + __n(mealPlanEntry.servings, "%s serving", "%s servings") + '
\
' + fulfillmentIconHtml + " " + fulfillmentInfoHtml + '
\ -
' + resolvedRecipe.costs + ' ' + __t('per serving') + '
\ +
' + resolvedRecipe.costs + ' ' + __t('per serving') + '
\
\ \ \ diff --git a/views/barcodescannertesting.blade.php b/views/barcodescannertesting.blade.php index 60f72a5f..c68d0c1a 100644 --- a/views/barcodescannertesting.blade.php +++ b/views/barcodescannertesting.blade.php @@ -30,8 +30,8 @@
- {{ $__t('Hit') }}: 0 // - {{ $__t('Miss') }}: 0 + {{ $__t('Hit') }}: 0 // + {{ $__t('Miss') }}: 0
diff --git a/views/components/batterycard.blade.php b/views/components/batterycard.blade.php index 80b71b63..91f2a1c0 100644 --- a/views/components/batterycard.blade.php +++ b/views/components/batterycard.blade.php @@ -12,7 +12,7 @@

{{ $__t('Used in') }}:
- {{ $__t('Charge cycles count') }}:
+ {{ $__t('Charge cycles count') }}:
{{ $__t('Last charged') }}:
diff --git a/views/components/chorecard.blade.php b/views/components/chorecard.blade.php index b89f59db..fdb1ce8d 100644 --- a/views/components/chorecard.blade.php +++ b/views/components/chorecard.blade.php @@ -11,7 +11,7 @@

- {{ $__t('Tracked count') }}:
+ {{ $__t('Tracked count') }}:
{{ $__t('Last tracked') }}:
{{ $__t('Last done by') }}:
diff --git a/views/components/productcard.blade.php b/views/components/productcard.blade.php index 0a5474cf..aba5b267 100644 --- a/views/components/productcard.blade.php +++ b/views/components/productcard.blade.php @@ -18,8 +18,8 @@
- {{ $__t('Stock amount') . ' / ' . $__t('Quantity unit') }}: -
+ {{ $__t('Stock amount') . ' / ' . $__t('Quantity unit') }}: +
@if(GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING){{ $__t('Location') }}:
@endif {{ $__t('Last purchased') }}:
{{ $__t('Last used') }}:
diff --git a/views/locationcontentsheet.blade.php b/views/locationcontentsheet.blade.php index 84d247ba..a1f67915 100644 --- a/views/locationcontentsheet.blade.php +++ b/views/locationcontentsheet.blade.php @@ -69,7 +69,7 @@ {{ FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name }} - {{ $currentStockEntry->amount }} {{ $__n($currentStockEntry->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name_plural) }} + {{ $currentStockEntry->amount }} {{ $__n($currentStockEntry->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name_plural) }} @if($currentStockEntry->amount_opened > 0){{ $__t('%s opened', $currentStockEntry->amount_opened) }}@endif diff --git a/views/productform.blade.php b/views/productform.blade.php index 222b999f..bedeb439 100644 --- a/views/productform.blade.php +++ b/views/productform.blade.php @@ -278,7 +278,7 @@ - {{ $quConversion->factor }} + {{ $quConversion->factor }} {{ FindObjectInArrayByPropertyValue($quantityunits, 'id', $quConversion->to_qu_id)->name }} diff --git a/views/products.blade.php b/views/products.blade.php index 74e22829..10f6823f 100644 --- a/views/products.blade.php +++ b/views/products.blade.php @@ -77,7 +77,7 @@ {{ FindObjectInArrayByPropertyValue($locations, 'id', $product->location_id)->name }} - {{ $product->min_stock_amount }} + {{ $product->min_stock_amount }} {{ FindObjectInArrayByPropertyValue($quantityunits, 'id', $product->qu_id_purchase)->name }} @@ -86,7 +86,7 @@ {{ FindObjectInArrayByPropertyValue($quantityunits, 'id', $product->qu_id_stock)->name }} - {{ $product->qu_factor_purchase_to_stock }} + {{ $product->qu_factor_purchase_to_stock }} @if(!empty($product->product_group_id)) {{ FindObjectInArrayByPropertyValue($productGroups, 'id', $product->product_group_id)->name }} @endif diff --git a/views/recipeform.blade.php b/views/recipeform.blade.php index 9b1d2f14..a1246f18 100644 --- a/views/recipeform.blade.php +++ b/views/recipeform.blade.php @@ -142,7 +142,7 @@ @if(!empty($recipePosition->variable_amount)) {{ $recipePosition->variable_amount }} @else - @if($recipePosition->amount == round($recipePosition->amount)){{ round($recipePosition->amount) }}@else{{ $recipePosition->amount }}@endif + @if($recipePosition->amount == round($recipePosition->amount)){{ round($recipePosition->amount) }}@else{{ $recipePosition->amount }}@endif @endif {{ $__n($recipePosition->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', $recipePosition->qu_id)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', $recipePosition->qu_id)->name_plural) }} diff --git a/views/recipes.blade.php b/views/recipes.blade.php index 82fede08..dc34377a 100644 --- a/views/recipes.blade.php +++ b/views/recipes.blade.php @@ -165,7 +165,7 @@

-

{{ $selectedRecipeTotalCalories }}

+

{{ $selectedRecipeTotalCalories }}

@endif @@ -175,7 +175,7 @@ {{ $__t('Based on the prices of the last purchase per product') }}

-

{{ $selectedRecipeTotalCosts }}

+

{{ $selectedRecipeTotalCosts }}

@endif @@ -217,7 +217,7 @@ @if(!empty($selectedRecipePosition->recipe_variable_amount)) {{ $selectedRecipePosition->recipe_variable_amount }} @else - @if($selectedRecipePosition->recipe_amount == round($selectedRecipePosition->recipe_amount, 2)){{ round($selectedRecipePosition->recipe_amount, 2) }}@else{{ $selectedRecipePosition->recipe_amount }}@endif + @if($selectedRecipePosition->recipe_amount == round($selectedRecipePosition->recipe_amount, 2)){{ round($selectedRecipePosition->recipe_amount, 2) }}@else{{ $selectedRecipePosition->recipe_amount }}@endif @endif {{ $__n($selectedRecipePosition->recipe_amount, FindObjectInArrayByPropertyValue($quantityUnits, 'id', $selectedRecipePosition->qu_id)->name, FindObjectInArrayByPropertyValue($quantityUnits, 'id', $selectedRecipePosition->qu_id)->name_plural) }} {{ FindObjectInArrayByPropertyValue($products, 'id', $selectedRecipePosition->product_id)->name }} @if($selectedRecipePosition->need_fulfilled == 1)@elseif($selectedRecipePosition->need_fulfilled_with_shopping_list == 1)@else@endif @@ -268,7 +268,7 @@ @if(!empty($selectedRecipePosition->recipe_variable_amount)) {{ $selectedRecipePosition->recipe_variable_amount }} @else - @if($selectedRecipePosition->recipe_amount == round($selectedRecipePosition->recipe_amount, 2)){{ round($selectedRecipePosition->recipe_amount, 2) }}@else{{ $selectedRecipePosition->recipe_amount }}@endif + @if($selectedRecipePosition->recipe_amount == round($selectedRecipePosition->recipe_amount, 2)){{ round($selectedRecipePosition->recipe_amount, 2) }}@else{{ $selectedRecipePosition->recipe_amount }}@endif @endif {{ $__n($selectedRecipePosition->recipe_amount, FindObjectInArrayByPropertyValue($quantityUnits, 'id', $selectedRecipePosition->qu_id)->name, FindObjectInArrayByPropertyValue($quantityUnits, 'id', $selectedRecipePosition->qu_id)->name_plural) }} {{ FindObjectInArrayByPropertyValue($products, 'id', $selectedRecipePosition->product_id)->name }} @if($selectedRecipePosition->need_fulfilled == 1)@elseif($selectedRecipePosition->need_fulfilled_with_shopping_list == 1)@else@endif diff --git a/views/shoppinglist.blade.php b/views/shoppinglist.blade.php index d2483710..edf97320 100644 --- a/views/shoppinglist.blade.php +++ b/views/shoppinglist.blade.php @@ -120,7 +120,7 @@ @if(!empty($listItem->product_id)) {{ FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->name }}
@endif{!! nl2br($listItem->note) !!} - {{ $listItem->amount }} @if(!empty($listItem->product_id)){{ $__n($listItem->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->qu_id_purchase)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->qu_id_purchase)->name_plural) }}@endif + {{ $listItem->amount }} @if(!empty($listItem->product_id)){{ $__n($listItem->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->qu_id_purchase)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->qu_id_purchase)->name_plural) }}@endif @if(!empty(FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->product_group_id)) {{ FindObjectInArrayByPropertyValue($productGroups, 'id', FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->product_group_id)->name }} @else {{ $__t('Ungrouped') }} @endif diff --git a/views/stockjournal.blade.php b/views/stockjournal.blade.php index a95acf75..5704a90d 100644 --- a/views/stockjournal.blade.php +++ b/views/stockjournal.blade.php @@ -56,7 +56,7 @@ @endif - {{ $stockLogEntry->amount }} {{ $__n($stockLogEntry->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $stockLogEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $stockLogEntry->product_id)->qu_id_stock)->name_plural) }} + {{ $stockLogEntry->amount }} {{ $__n($stockLogEntry->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $stockLogEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $stockLogEntry->product_id)->qu_id_stock)->name_plural) }} {{ $stockLogEntry->row_created_timestamp }} diff --git a/views/stockoverview.blade.php b/views/stockoverview.blade.php index 1ef2b19f..5abc1ac2 100644 --- a/views/stockoverview.blade.php +++ b/views/stockoverview.blade.php @@ -174,11 +174,11 @@ {{ FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name }} - {{ $currentStockEntry->amount }} {{ $__n($currentStockEntry->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name_plural) }} + {{ $currentStockEntry->amount }} {{ $__n($currentStockEntry->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name_plural) }} @if($currentStockEntry->amount_opened > 0){{ $__t('%s opened', $currentStockEntry->amount_opened) }}@endif @if($currentStockEntry->is_aggregated_amount == 1) - {{ $currentStockEntry->amount_aggregated }} {{ $__n($currentStockEntry->amount_aggregated, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name_plural) }} + {{ $currentStockEntry->amount_aggregated }} {{ $__n($currentStockEntry->amount_aggregated, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name_plural) }} @if($currentStockEntry->amount_opened_aggregated > 0){{ $__t('%s opened', $currentStockEntry->amount_opened_aggregated) }}@endif @endif From cf3217ada4856f49f9e5f4881a301cc5bab1b5e6 Mon Sep 17 00:00:00 2001 From: Bernd Bestel Date: Thu, 26 Sep 2019 16:42:59 +0200 Subject: [PATCH 12/14] Fixed expired products count on stock overview page (fixes #392) --- changelog/53_UNRELEASED_2019-xx-xx.md | 20 +++++++++++++++----- controllers/StockController.php | 2 +- services/StockService.php | 16 ++++++++-------- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/changelog/53_UNRELEASED_2019-xx-xx.md b/changelog/53_UNRELEASED_2019-xx-xx.md index 887af78a..868e93fa 100644 --- a/changelog/53_UNRELEASED_2019-xx-xx.md +++ b/changelog/53_UNRELEASED_2019-xx-xx.md @@ -1,13 +1,23 @@ -- Fixed that barcode lookups now compare the whole barcode, not parts of it (e. g. when you have two products with the barcodes "$1" and "$10" and scan "$1" maybe the product of "$10" was found till now) +### Stock improvements/fixes +- Fixed that barcode lookups now compare the whole barcode, not parts of it (e. g. when you have two products with the barcodes `$1` and `$10` and scan `$1` maybe the product of `$10` was found till now) +- Fixed that the "X products are already expired" count on the stock overview page was wrong - It's now possible to accumulate min. stock amounts on parent product level (new option per product, means the sub product will never be "missing" then, only the parent product) +- When adding a product to the shopping list from the new context/more menu from the stock overview page and if the product is already on the shopping list, the amount of that entry will be updated acccordingly instead of adding a new (double) shopping list item + +### Recipe improvements/fixes +- Fixed a problem regarding quantity unit conversion handling for recipe ingredients of products with no unit relations, but only a different purchase/stock quantity unit - It's now possible to display a recipe directly from the meal plan (new "eye button") (thanks @kriddles) - Improved the responsiveness of the meal plan and calendar page by automatically switching to a day calendar view on smaller screens (thanks for the idea @kriddles) + +### Calendar improvements - The calendar now also contains all planned recipes from the meal plan on the corresponding day -- When adding a product to the shopping list from the new context/more menu from the stock overview page and if the product is already on the shopping list, the amount of that entry will be updated acccordingly instead of adding a new (double) shopping list item +- Improved that dates in the iCal calendar export now include the server timezone + +### General & other improvements/fixes - Fixed that the browser barcode scanner button was not clickable on iOS Safari (thanks @DeeeeLAN) -- Fixed a problem regarding quantity unit conversion handling for recipe ingredients of products with no unit relations, but only a different purchase/stock quantity unit -- Improved that dates in the iCal calendar export now includes the server timezone - It's now also possible to set the meal plan page as the default/entry page (`config.php` setting `ENTRY_PAGE`) (thanks @lwis) +- Some UI detail-refinements + +### API improvements/fixes - The API Endpoint `GET /files/{group}/{fileName}` now also returns a `Cache-Control` header (defaults fixed to 30 days) to further increase page load times - Fixed that the API endpoint `/stock/shoppinglist/add-product` failed when a product should be added which was not already on the shopping list (thanks @Forceu) -- Some style/CSS detail-refinements diff --git a/controllers/StockController.php b/controllers/StockController.php index 64dd3fc6..ec946ae0 100644 --- a/controllers/StockController.php +++ b/controllers/StockController.php @@ -28,7 +28,7 @@ class StockController extends BaseController 'products' => $this->Database->products()->orderBy('name'), 'quantityunits' => $this->Database->quantity_units()->orderBy('name'), 'locations' => $this->Database->locations()->orderBy('name'), - 'currentStock' => $this->StockService->GetCurrentStock(), + 'currentStock' => $this->StockService->GetCurrentStock(true), 'currentStockLocations' => $this->StockService->GetCurrentStockLocations(), 'missingProducts' => $this->StockService->GetMissingProducts(), 'nextXDays' => $nextXDays, diff --git a/services/StockService.php b/services/StockService.php index 67a01e14..48276380 100644 --- a/services/StockService.php +++ b/services/StockService.php @@ -11,15 +11,15 @@ class StockService extends BaseService public function GetCurrentStock($includeNotInStockButMissingProducts = false) { - $missingProductsView = 'stock_missing_products_including_opened'; - if (!GROCY_FEATURE_SETTING_STOCK_COUNT_OPENED_PRODUCTS_AGAINST_MINIMUM_STOCK_AMOUNT) - { - $missingProductsView = 'stock_missing_products'; - } - - $sql = 'SELECT * FROM stock_current UNION SELECT id, 0, 0, null, 0, 0, 0 FROM ' . $missingProductsView . ' WHERE id NOT IN (SELECT product_id FROM stock_current)'; + $sql = 'SELECT * FROM stock_current'; if ($includeNotInStockButMissingProducts) { + $missingProductsView = 'stock_missing_products_including_opened'; + if (!GROCY_FEATURE_SETTING_STOCK_COUNT_OPENED_PRODUCTS_AGAINST_MINIMUM_STOCK_AMOUNT) + { + $missingProductsView = 'stock_missing_products'; + } + $sql = 'SELECT * FROM stock_current WHERE best_before_date IS NOT NULL UNION SELECT id, 0, 0, null, 0, 0, 0 FROM ' . $missingProductsView . ' WHERE id NOT IN (SELECT product_id FROM stock_current)'; } @@ -69,7 +69,7 @@ class StockService extends BaseService public function GetExpiringProducts(int $days = 5, bool $excludeExpired = false) { - $currentStock = $this->GetCurrentStock(true); + $currentStock = $this->GetCurrentStock(false); $currentStock = FindAllObjectsInArrayByPropertyValue($currentStock, 'best_before_date', date('Y-m-d 23:59:59', strtotime("+$days days")), '<'); if ($excludeExpired) From cf2e6f10399677759143df2fd54fe2663a2a83b3 Mon Sep 17 00:00:00 2001 From: Bernd Bestel Date: Thu, 26 Sep 2019 17:20:25 +0200 Subject: [PATCH 13/14] Added a sub feature flag to disable chore assignments when not needed --- changelog/53_UNRELEASED_2019-xx-xx.md | 3 +++ config-dist.php | 1 + public/viewjs/choreform.js | 6 +++++- public/viewjs/choretracking.js | 2 +- views/choreform.blade.php | 5 +++++ views/choresjournal.blade.php | 4 ++++ views/choresoverview.blade.php | 14 +++++++++++++- views/choretracking.blade.php | 4 ++++ views/components/chorecard.blade.php | 2 ++ 9 files changed, 38 insertions(+), 3 deletions(-) diff --git a/changelog/53_UNRELEASED_2019-xx-xx.md b/changelog/53_UNRELEASED_2019-xx-xx.md index 868e93fa..989ccdb1 100644 --- a/changelog/53_UNRELEASED_2019-xx-xx.md +++ b/changelog/53_UNRELEASED_2019-xx-xx.md @@ -9,6 +9,9 @@ - It's now possible to display a recipe directly from the meal plan (new "eye button") (thanks @kriddles) - Improved the responsiveness of the meal plan and calendar page by automatically switching to a day calendar view on smaller screens (thanks for the idea @kriddles) +### Chores improvements +- There is now a new sub feature flag `FEATURE_FLAG_CHORES_ASSIGNMENTS` to disable chore assignments if you don't need them (defaults to `true`, so no changed behavior when not configured) + ### Calendar improvements - The calendar now also contains all planned recipes from the meal plan on the corresponding day - Improved that dates in the iCal calendar export now include the server timezone diff --git a/config-dist.php b/config-dist.php index 53817a24..c83286bb 100644 --- a/config-dist.php +++ b/config-dist.php @@ -124,6 +124,7 @@ Setting('FEATURE_FLAG_STOCK_PRICE_TRACKING', true); Setting('FEATURE_FLAG_STOCK_LOCATION_TRACKING', true); Setting('FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING', true); Setting('FEATURE_FLAG_STOCK_PRODUCT_OPENED_TRACKING', true); +Setting('FEATURE_FLAG_CHORES_ASSIGNMENTS', true); # Feature settings diff --git a/public/viewjs/choreform.js b/public/viewjs/choreform.js index 730a2bcd..1bd77713 100644 --- a/public/viewjs/choreform.js +++ b/public/viewjs/choreform.js @@ -3,7 +3,11 @@ e.preventDefault(); var jsonData = $('#chore-form').serializeJSON({ checkboxUncheckedValue: "0" }); - jsonData.assignment_config = $("#assignment_config").val().join(","); + if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_CHORES_ASSIGNMENTS) + { + jsonData.assignment_config = $("#assignment_config").val().join(","); + } + Grocy.FrontendHelpers.BeginUiBusy("chore-form"); if (Grocy.EditMode === 'create') diff --git a/public/viewjs/choretracking.js b/public/viewjs/choretracking.js index 6218008b..05b60fa9 100644 --- a/public/viewjs/choretracking.js +++ b/public/viewjs/choretracking.js @@ -8,7 +8,7 @@ Grocy.Api.Get('chores/' + jsonForm.chore_id, function (choreDetails) { - Grocy.Api.Post('chores/' + jsonForm.chore_id + '/execute', { 'tracked_time': Grocy.Components.DateTimePicker.GetValue(), 'done_by': Grocy.Components.UserPicker.GetValue() }, + Grocy.Api.Post('chores/' + jsonForm.chore_id + '/execute', { 'tracked_time': Grocy.Components.DateTimePicker.GetValue(), 'done_by': $("#user_id").val() }, function(result) { Grocy.FrontendHelpers.EndUiBusy("choretracking-form"); diff --git a/views/choreform.blade.php b/views/choreform.blade.php index e965d1eb..0287b65e 100644 --- a/views/choreform.blade.php +++ b/views/choreform.blade.php @@ -86,6 +86,7 @@ + @if(GROCY_FEATURE_FLAG_CHORES_ASSIGNMENTS)
{{ $__t('This assignment type requires that at least one is assigned') }}
+ @else + + + @endif
diff --git a/views/choresjournal.blade.php b/views/choresjournal.blade.php index 96cab621..e686a797 100644 --- a/views/choresjournal.blade.php +++ b/views/choresjournal.blade.php @@ -35,7 +35,9 @@ {{ $__t('Chore') }} {{ $__t('Tracked time') }} + @if(GROCY_FEATURE_FLAG_CHORES_ASSIGNMENTS) {{ $__t('Done by') }} + @endif @@ -58,6 +60,7 @@ {{ $choreLogEntry->tracked_time }} + @if(GROCY_FEATURE_FLAG_CHORES_ASSIGNMENTS) @if ($choreLogEntry->done_by_user_id !== null && !empty($choreLogEntry->done_by_user_id)) {{ GetUserDisplayName(FindObjectInArrayByPropertyValue($users, 'id', $choreLogEntry->done_by_user_id)) }} @@ -65,6 +68,7 @@ {{ $__t('Unknown') }} @endif + @endif @endforeach diff --git a/views/choresoverview.blade.php b/views/choresoverview.blade.php index d6e6b721..abfdc843 100644 --- a/views/choresoverview.blade.php +++ b/views/choresoverview.blade.php @@ -18,7 +18,9 @@

+ @if(GROCY_FEATURE_FLAG_CHORES_ASSIGNMENTS)

+ @endif
@@ -35,15 +37,17 @@ + @if(GROCY_FEATURE_FLAG_CHORES_ASSIGNMENTS)
+ @endif
@@ -55,9 +59,13 @@ {{ $__t('Chore') }} {{ $__t('Next estimated tracking') }} {{ $__t('Last tracked') }} + @if(GROCY_FEATURE_FLAG_CHORES_ASSIGNMENTS) {{ $__t('Assigned to') }} + @endif Hidden status + @if(GROCY_FEATURE_FLAG_CHORES_ASSIGNMENTS) Hidden assigned to user id + @endif @include('components.userfields_thead', array( 'userfields' => $userfields @@ -106,6 +114,7 @@ {{ $curentChoreEntry->last_tracked_time }} + @if(GROCY_FEATURE_FLAG_CHORES_ASSIGNMENTS) @if(!empty($curentChoreEntry->next_execution_assigned_to_user_id)) @@ -115,14 +124,17 @@ @endif + @endif @if(FindObjectInArrayByPropertyValue($chores, 'id', $curentChoreEntry->chore_id)->period_type !== \Grocy\Services\ChoresService::CHORE_PERIOD_TYPE_MANUALLY && $curentChoreEntry->next_estimated_execution_time < date('Y-m-d H:i:s')) overdue @elseif(FindObjectInArrayByPropertyValue($chores, 'id', $curentChoreEntry->chore_id)->period_type !== \Grocy\Services\ChoresService::CHORE_PERIOD_TYPE_MANUALLY && $curentChoreEntry->next_estimated_execution_time < date('Y-m-d H:i:s', strtotime("+$nextXDays days"))) duesoon @endif + @if(GROCY_FEATURE_FLAG_CHORES_ASSIGNMENTS) @if(!empty($curentChoreEntry->next_execution_assigned_to_user_id)) xx{{ $curentChoreEntry->next_execution_assigned_to_user_id }}xx @endif + @endif @include('components.userfields_tbody', array( 'userfields' => $userfields, diff --git a/views/choretracking.blade.php b/views/choretracking.blade.php index 48cce595..53f578f7 100644 --- a/views/choretracking.blade.php +++ b/views/choretracking.blade.php @@ -32,12 +32,16 @@ 'invalidFeedback' => $__t('This can only be before now') )) + @if(GROCY_FEATURE_FLAG_CHORES_ASSIGNMENTS) @include('components.userpicker', array( 'label' => 'Done by', 'users' => $users, 'nextInputSelector' => '#user_id', 'prefillByUserId' => GROCY_USER_ID )) + @else + + @endif diff --git a/views/components/chorecard.blade.php b/views/components/chorecard.blade.php index fdb1ce8d..6a04def9 100644 --- a/views/components/chorecard.blade.php +++ b/views/components/chorecard.blade.php @@ -13,6 +13,8 @@

{{ $__t('Tracked count') }}:
{{ $__t('Last tracked') }}:
+ @if(GROCY_FEATURE_FLAG_CHORES_ASSIGNMENTS) {{ $__t('Last done by') }}: + @endif
From 654d00dd67add6ab9d4a0738f6b6cfab22a096bb Mon Sep 17 00:00:00 2001 From: Bernd Bestel Date: Thu, 26 Sep 2019 20:56:19 +0200 Subject: [PATCH 14/14] Again corrections for #384) --- migrations/0092.sql | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/migrations/0092.sql b/migrations/0092.sql index 6e76866b..84c39cab 100644 --- a/migrations/0092.sql +++ b/migrations/0092.sql @@ -32,7 +32,7 @@ UNION SELECT p.id, MAX(p.name) AS name, - SUM(sub_p.min_stock_amount) - IFNULL(SUM(s.amount), 0) AS amount_missing, + SUM(sub_p.min_stock_amount) - IFNULL(SUM(s.amount_aggregated), 0) AS amount_missing, CASE WHEN IFNULL(SUM(s.amount), 0) > 0 THEN 1 ELSE 0 END AS is_partly_in_stock FROM products_view p JOIN products_resolved pr @@ -44,7 +44,7 @@ LEFT JOIN stock_current s WHERE sub_p.min_stock_amount != 0 AND p.cumulate_min_stock_amount_of_sub_products = 1 GROUP BY p.id -HAVING IFNULL(SUM(s.amount), 0) < SUM(sub_p.min_stock_amount) +HAVING IFNULL(SUM(s.amount_aggregated), 0) < SUM(sub_p.min_stock_amount) UNION @@ -94,7 +94,7 @@ UNION SELECT p.id, MAX(p.name) AS name, - SUM(sub_p.min_stock_amount) - (IFNULL(SUM(s.amount), 0) - IFNULL(SUM(s.amount_opened), 0)) AS amount_missing, + SUM(sub_p.min_stock_amount) - (IFNULL(SUM(s.amount_aggregated), 0) - IFNULL(SUM(s.amount_opened), 0)) AS amount_missing, CASE WHEN IFNULL(SUM(s.amount), 0) > 0 THEN 1 ELSE 0 END AS is_partly_in_stock FROM products_view p JOIN products_resolved pr @@ -106,7 +106,7 @@ LEFT JOIN stock_current s WHERE sub_p.min_stock_amount != 0 AND p.cumulate_min_stock_amount_of_sub_products = 1 GROUP BY p.id -HAVING IFNULL(SUM(s.amount), 0) < SUM(sub_p.min_stock_amount) +HAVING IFNULL(SUM(s.amount_aggregated), 0) < SUM(sub_p.min_stock_amount) UNION