diff --git a/changelog/50_2.4.3_2019-xx-xx.md b/changelog/50_2.4.3_2019-xx-xx.md index ec8a8d11..63b8bf3f 100644 --- a/changelog/50_2.4.3_2019-xx-xx.md +++ b/changelog/50_2.4.3_2019-xx-xx.md @@ -2,6 +2,7 @@ - Fixed that "Track date only" chores were always tracked today, regardless of the given date - Fixed that the "week costs" were wrong after removing a meal plan entry - Fixed wrong recipes costs calculation with nested recipes when the base recipe servings are > 1 (also affected the meal plan when adding such a recipe there) +- Fixed consuming recipes did not consume ingredients of the nested recipes - Improved recipes API - added new endpoints to get stock fulfillment information (thanks @Aerex) - Improved date display for products that never expires (instead of "2999-12-31" now just "Never" will be shown) - Improved date display for dates of today and no time (instead of the hours since midnight now just "Today" will be shown) @@ -9,4 +10,5 @@ - Items can now be switched between lists (there is a shopping list dropdown on the item edit page) - Items can now be marked as "done" (new check mark button per item, when clicked, the item will be displayed greyed out, when clicked again the item will be displayed normally again) - Improved that products can now also be consumed as spoiled from the stock overview page (option in the more/context menu per line) +- Added a "consume this recipe"-button to the meal plan (and also a button to consume all recipes for a whole week) - Added a new `config.php` setting `DISABLE_AUTH` to be able to disable authentication / the login screen diff --git a/localization/strings.pot b/localization/strings.pot index bdcfe217..13c81bc9 100644 --- a/localization/strings.pot +++ b/localization/strings.pot @@ -1280,3 +1280,6 @@ msgstr "" msgid "Consume %1$s of %2$s as spoiled" msgstr "" + +msgid "Not all ingredients of recipe \"%s\" are in stock, nothing removed" +msgstr "" diff --git a/migrations/0076.sql b/migrations/0076.sql new file mode 100644 index 00000000..c2b6b9e0 --- /dev/null +++ b/migrations/0076.sql @@ -0,0 +1,87 @@ +DROP VIEW recipes_pos_resolved; +CREATE VIEW recipes_pos_resolved +AS + +-- Multiplication by 1.0 to force conversion to float (REAL) + +SELECT + r.id AS recipe_id, + rp.id AS recipe_pos_id, + rp.product_id AS product_id, + rp.amount * (r.desired_servings*1.0 / r.base_servings*1.0) * (rnr.includes_servings*1.0 / CASE WHEN rnr.recipe_id != rnr.includes_recipe_id THEN rnrr.base_servings*1.0 ELSE 1 END) AS recipe_amount, + IFNULL(sc.amount, 0) AS stock_amount, + CASE WHEN IFNULL(sc.amount, 0) >= CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN 1 ELSE rp.amount * (r.desired_servings*1.0 / r.base_servings*1.0) * (rnr.includes_servings*1.0 / CASE WHEN rnr.recipe_id != rnr.includes_recipe_id THEN rnrr.base_servings*1.0 ELSE 1 END) END THEN 1 ELSE 0 END AS need_fulfilled, + CASE WHEN IFNULL(sc.amount, 0) - CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN 1 ELSE rp.amount * (r.desired_servings*1.0 / r.base_servings*1.0) * (rnr.includes_servings*1.0 / CASE WHEN rnr.recipe_id != rnr.includes_recipe_id THEN rnrr.base_servings*1.0 ELSE 1 END) END < 0 THEN ABS(IFNULL(sc.amount, 0) - (CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN 1 ELSE rp.amount * (r.desired_servings*1.0 / r.base_servings*1.0) * (rnr.includes_servings*1.0 / CASE WHEN rnr.recipe_id != rnr.includes_recipe_id THEN rnrr.base_servings*1.0 ELSE 1 END) END)) ELSE 0 END AS missing_amount, + IFNULL(sl.amount, 0) * p.qu_factor_purchase_to_stock AS amount_on_shopping_list, + CASE WHEN IFNULL(sc.amount, 0) + (CASE WHEN r.not_check_shoppinglist = 1 THEN 0 ELSE IFNULL(sl.amount, 0) END * p.qu_factor_purchase_to_stock) >= CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN 1 ELSE rp.amount * (r.desired_servings*1.0 / r.base_servings*1.0) * (rnr.includes_servings*1.0 / CASE WHEN rnr.recipe_id != rnr.includes_recipe_id THEN rnrr.base_servings*1.0 ELSE 1 END) END THEN 1 ELSE 0 END AS need_fulfilled_with_shopping_list, + rp.qu_id, + (CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN 1 ELSE rp.amount * (r.desired_servings*1.0 / r.base_servings*1.0) * (rnr.includes_servings*1.0 / CASE WHEN rnr.recipe_id != rnr.includes_recipe_id THEN rnrr.base_servings*1.0 ELSE 1 END) END / p.qu_factor_purchase_to_stock) * pcp.last_price AS costs, + CASE WHEN rnr.recipe_id = rnr.includes_recipe_id THEN 0 ELSE 1 END AS is_nested_recipe_pos, + rp.ingredient_group, + rp.id, -- Just a dummy id column + rnr.includes_recipe_id as child_recipe_id, + rp.note, + rp.variable_amount AS recipe_variable_amount, + rp.only_check_single_unit_in_stock +FROM recipes r +JOIN recipes_nestings_resolved rnr + ON r.id = rnr.recipe_id +JOIN recipes rnrr + ON rnr.includes_recipe_id = rnrr.id +JOIN recipes_pos rp + ON rnr.includes_recipe_id = rp.recipe_id +JOIN products p + ON rp.product_id = p.id +LEFT JOIN ( + SELECT product_id, SUM(amount) AS amount + FROM shopping_list + GROUP BY product_id) sl + ON rp.product_id = sl.product_id +LEFT JOIN stock_current sc + ON rp.product_id = sc.product_id +LEFT JOIN products_current_price pcp + ON rp.product_id = pcp.product_id +WHERE rp.not_check_stock_fulfillment = 0 + +UNION + +-- Just add all recipe positions which should not be checked against stock with fulfilled need + +SELECT + r.id AS recipe_id, + rp.id AS recipe_pos_id, + rp.product_id AS product_id, + rp.amount * (r.desired_servings*1.0 / r.base_servings*1.0) * (rnr.includes_servings*1.0 / CASE WHEN rnr.recipe_id != rnr.includes_recipe_id THEN rnrr.base_servings*1.0 ELSE 1 END) AS recipe_amount, + IFNULL(sc.amount, 0) AS stock_amount, + 1 AS need_fulfilled, + 0 AS missing_amount, + IFNULL(sl.amount, 0) * p.qu_factor_purchase_to_stock AS amount_on_shopping_list, + 1 AS need_fulfilled_with_shopping_list, + rp.qu_id, + (CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN 1 ELSE rp.amount * (r.desired_servings*1.0 / r.base_servings*1.0) * (rnr.includes_servings*1.0 / CASE WHEN rnr.recipe_id != rnr.includes_recipe_id THEN rnrr.base_servings*1.0 ELSE 1 END) END / p.qu_factor_purchase_to_stock) * pcp.last_price AS costs, + CASE WHEN rnr.recipe_id = rnr.includes_recipe_id THEN 0 ELSE 1 END AS is_nested_recipe_pos, + rp.ingredient_group, + rp.id, -- Just a dummy id column + rnr.includes_recipe_id as child_recipe_id, + rp.note, + rp.variable_amount AS recipe_variable_amount, + rp.only_check_single_unit_in_stock +FROM recipes r +JOIN recipes_nestings_resolved rnr + ON r.id = rnr.recipe_id +JOIN recipes rnrr + ON rnr.includes_recipe_id = rnrr.id +JOIN recipes_pos rp + ON rnr.includes_recipe_id = rp.recipe_id +JOIN products p + ON rp.product_id = p.id +LEFT JOIN ( + SELECT product_id, SUM(amount) AS amount + FROM shopping_list + GROUP BY product_id) sl + ON rp.product_id = sl.product_id +LEFT JOIN stock_current sc + ON rp.product_id = sc.product_id +LEFT JOIN products_current_price pcp + ON rp.product_id = pcp.product_id +WHERE rp.not_check_stock_fulfillment = 1; diff --git a/public/viewjs/mealplan.js b/public/viewjs/mealplan.js index 0170af49..9a35d182 100644 --- a/public/viewjs/mealplan.js +++ b/public/viewjs/mealplan.js @@ -29,6 +29,7 @@ var calendar = $("#calendar").fullCalendar({ var weekCosts = 0; var weekRecipeOrderMissingButtonHtml = ""; + var weekRecipeConsumeButtonHtml = ""; if (weekRecipe !== null) { weekCosts = FindObjectInArrayByPropertyValue(recipesResolved, "recipe_id", weekRecipe.id).costs; @@ -38,9 +39,15 @@ var calendar = $("#calendar").fullCalendar({ { weekRecipeOrderMissingButtonDisabledClasses = "disabled"; } + var weekRecipeConsumeButtonDisabledClasses = ""; + if (FindObjectInArrayByPropertyValue(recipesResolved, "recipe_id", weekRecipe.id).need_fulfilled == 0) + { + weekRecipeConsumeButtonDisabledClasses = "disabled"; + } weekRecipeOrderMissingButtonHtml = '' + weekRecipeConsumeButtonHtml = '' } - $(".fc-header-toolbar .fc-center").html("