mirror of
https://github.com/grocy/grocy.git
synced 2025-04-29 17:45:39 +00:00
Make it possible to round up shopping list and recipe ingredient amounts (closes #902, closes #2644)
This commit is contained in:
parent
e3965ed82c
commit
1946ff870e
@ -41,12 +41,17 @@
|
|||||||
|
|
||||||
### Shopping list
|
### Shopping list
|
||||||
|
|
||||||
- xxx
|
- Added a new shopping list setting (top right corner settings menu) "Round up quantity amounts to the nearest whole number"
|
||||||
|
- When enabled, all quantity amounts on the shopping list are always displayed rounded up to the nearest whole number
|
||||||
|
- Defaults to disabled, so no changed behavior when not configured
|
||||||
|
|
||||||
### Recipes
|
### Recipes
|
||||||
|
|
||||||
- Consuming a recipe is now also possible when not all needed ingredients are currently in stock (the in stock amount, if any, of the corresponding ingredient will be consumed in that case)
|
- Consuming a recipe is now also possible when not all needed ingredients are currently in stock (the in stock amount, if any, of the corresponding ingredient will be consumed in that case)
|
||||||
- For in stock ingredients, the amount actually in stock is now displayed next to the hint "Enough in stock"
|
- For in stock ingredients, the amount actually in stock is now displayed next to the hint "Enough in stock"
|
||||||
|
- Added a new recipe ingredient option "Round up quantity amounts to the nearest whole number"
|
||||||
|
- When enabled, resulting quantity amounts (after scaling according the desired serving amount) are always rounded up to the nearest whole number
|
||||||
|
- Defaults to disabled, so no changed behavior when not configured
|
||||||
- Optimized that when adding missing recipe ingredients with the option "Only check if any amount is in stock" enabled to the shopping list and when no corresponding unit conversion exists, the amount/unit is now taken "as is" (as defined in the recipe ingredient) into the created shopping list item
|
- Optimized that when adding missing recipe ingredients with the option "Only check if any amount is in stock" enabled to the shopping list and when no corresponding unit conversion exists, the amount/unit is now taken "as is" (as defined in the recipe ingredient) into the created shopping list item
|
||||||
- When no price information is available for at least one ingredient, a red exclamation mark is now displayed next to the recipe total cost information
|
- When no price information is available for at least one ingredient, a red exclamation mark is now displayed next to the recipe total cost information
|
||||||
- Fixed that calories/costs of recipe ingredients were wrong when the ingredient option "Only check if any amount is in stock" was set and the on the ingredient used quantity unit was different from the product's QU stock
|
- Fixed that calories/costs of recipe ingredients were wrong when the ingredient option "Only check if any amount is in stock" was set and the on the ingredient used quantity unit was different from the product's QU stock
|
||||||
|
@ -199,6 +199,7 @@ DefaultUserSetting('show_warning_on_purchase_when_due_date_is_earlier_than_next'
|
|||||||
// Shopping list settings
|
// Shopping list settings
|
||||||
DefaultUserSetting('shopping_list_to_stock_workflow_auto_submit_when_prefilled', false); // Automatically do the booking using the last price and the amount of the shopping list item, if the product has "Default due days" set
|
DefaultUserSetting('shopping_list_to_stock_workflow_auto_submit_when_prefilled', false); // Automatically do the booking using the last price and the amount of the shopping list item, if the product has "Default due days" set
|
||||||
DefaultUserSetting('shopping_list_show_calendar', false); // When enabled, a small (month view) calendar will be shown on the shopping list page
|
DefaultUserSetting('shopping_list_show_calendar', false); // When enabled, a small (month view) calendar will be shown on the shopping list page
|
||||||
|
DefaultUserSetting('shopping_list_round_up', false); // When enabled, all quantity amounts on the shopping list are always displayed rounded up to the nearest whole number
|
||||||
DefaultUserSetting('shopping_list_auto_add_below_min_stock_amount', false); // If products should be automatically added to the shopping list when they are below their min. stock amount
|
DefaultUserSetting('shopping_list_auto_add_below_min_stock_amount', false); // If products should be automatically added to the shopping list when they are below their min. stock amount
|
||||||
DefaultUserSetting('shopping_list_auto_add_below_min_stock_amount_list_id', 1); // When the above setting is enabled, the id of the shopping list to which the products will be added
|
DefaultUserSetting('shopping_list_auto_add_below_min_stock_amount_list_id', 1); // When the above setting is enabled, the id of the shopping list to which the products will be added
|
||||||
|
|
||||||
|
@ -2470,3 +2470,6 @@ msgstr ""
|
|||||||
|
|
||||||
msgid "Unspecified"
|
msgid "Unspecified"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Round up quantity amounts to the nearest whole number"
|
||||||
|
msgstr ""
|
||||||
|
141
migrations/0249.sql
Normal file
141
migrations/0249.sql
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
ALTER TABLE recipes_pos
|
||||||
|
ADD round_up TINYINT NOT NULL DEFAULT 0 CHECK(round_up IN (0, 1));
|
||||||
|
|
||||||
|
DROP VIEW recipes_pos_resolved;
|
||||||
|
CREATE VIEW recipes_pos_resolved
|
||||||
|
AS
|
||||||
|
|
||||||
|
-- Multiplication by 1.0 to force conversion to float (REAL)
|
||||||
|
|
||||||
|
-- Resolved amount (here used multiple times):
|
||||||
|
-- CASE WHEN rnr.recipe_id = rnr.includes_recipe_id THEN rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) ELSE rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) * ((rnr.includes_servings*1.0) / (rnrr.base_servings*1.0)) END
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
r.id AS recipe_id,
|
||||||
|
rp.id AS recipe_pos_id,
|
||||||
|
rp.product_id AS product_id,
|
||||||
|
CASE WHEN rp.round_up = 1 THEN CEIL(CASE WHEN rnr.recipe_id = rnr.includes_recipe_id THEN rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) ELSE rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) * ((rnr.includes_servings*1.0) / (rnrr.base_servings*1.0)) END) ELSE CASE WHEN rnr.recipe_id = rnr.includes_recipe_id THEN rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) ELSE rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) * ((rnr.includes_servings*1.0) / (rnrr.base_servings*1.0)) END END AS recipe_amount,
|
||||||
|
IFNULL(sc.amount_aggregated, 0) AS stock_amount,
|
||||||
|
CASE WHEN IFNULL(sc.amount_aggregated, 0) >= CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN 0.00000001 ELSE CASE WHEN rp.round_up = 1 THEN CEIL(CASE WHEN rnr.recipe_id = rnr.includes_recipe_id THEN rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) ELSE rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) * ((rnr.includes_servings*1.0) / (rnrr.base_servings*1.0)) END) ELSE CASE WHEN rnr.recipe_id = rnr.includes_recipe_id THEN rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) ELSE rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) * ((rnr.includes_servings*1.0) / (rnrr.base_servings*1.0)) END END END THEN 1 ELSE 0 END AS need_fulfilled,
|
||||||
|
CASE WHEN IFNULL(sc.amount_aggregated, 0) - CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN 0.00000001 ELSE CASE WHEN rp.round_up = 1 THEN CEIL(CASE WHEN rnr.recipe_id = rnr.includes_recipe_id THEN rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) ELSE rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) * ((rnr.includes_servings*1.0) / (rnrr.base_servings*1.0)) END) ELSE CASE WHEN rnr.recipe_id = rnr.includes_recipe_id THEN rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) ELSE rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) * ((rnr.includes_servings*1.0) / (rnrr.base_servings*1.0)) END END END < 0 THEN ABS(IFNULL(sc.amount_aggregated, 0) - (CASE WHEN rp.round_up = 1 THEN CEIL(CASE WHEN rnr.recipe_id = rnr.includes_recipe_id THEN rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) ELSE rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) * ((rnr.includes_servings*1.0) / (rnrr.base_servings*1.0)) END) ELSE CASE WHEN rnr.recipe_id = rnr.includes_recipe_id THEN rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) ELSE rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) * ((rnr.includes_servings*1.0) / (rnrr.base_servings*1.0)) END END)) ELSE 0 END AS missing_amount,
|
||||||
|
IFNULL(sl.amount, 0) AS amount_on_shopping_list,
|
||||||
|
CASE WHEN ROUND(IFNULL(sc.amount_aggregated, 0) + CASE WHEN r.not_check_shoppinglist = 1 THEN 0 ELSE IFNULL(sl.amount, 0) END, 2) >= ROUND(CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN 0.00000001 ELSE CASE WHEN rp.round_up = 1 THEN CEIL(CASE WHEN rnr.recipe_id = rnr.includes_recipe_id THEN rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) ELSE rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) * ((rnr.includes_servings*1.0) / (rnrr.base_servings*1.0)) END) ELSE CASE WHEN rnr.recipe_id = rnr.includes_recipe_id THEN rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) ELSE rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) * ((rnr.includes_servings*1.0) / (rnrr.base_servings*1.0)) END END END, 2) THEN 1 ELSE 0 END AS need_fulfilled_with_shopping_list,
|
||||||
|
rp.qu_id,
|
||||||
|
(r.desired_servings*1.0 / r.base_servings*1.0) * CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN IFNULL(qucr.factor, 1.0) ELSE 1 END * (rnr.includes_servings*1.0 / CASE WHEN rnr.recipe_id != rnr.includes_recipe_id THEN rnrr.base_servings*1.0 ELSE 1 END) * rp.amount * IFNULL(pcp.price, 0) * rp.price_factor * CASE WHEN rp.product_id != p_effective.id THEN IFNULL(qucr.factor, 1.0) ELSE 1.0 END AS costs,
|
||||||
|
CASE WHEN rnr.recipe_id = rnr.includes_recipe_id THEN 0 ELSE 1 END AS is_nested_recipe_pos,
|
||||||
|
rp.ingredient_group,
|
||||||
|
pg.name as product_group,
|
||||||
|
rp.id, -- Just a dummy id column
|
||||||
|
r.type as recipe_type,
|
||||||
|
rnr.includes_recipe_id as child_recipe_id,
|
||||||
|
rp.note,
|
||||||
|
rp.variable_amount AS recipe_variable_amount,
|
||||||
|
rp.only_check_single_unit_in_stock,
|
||||||
|
rp.amount * CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN IFNULL(qucr.factor, 1.0) ELSE 1 END / 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) * IFNULL(p_effective.calories, 0) * CASE WHEN rp.product_id != p_effective.id THEN IFNULL(qucr.factor, 1.0) ELSE 1.0 END AS calories,
|
||||||
|
p.active AS product_active,
|
||||||
|
CASE pvs.current_due_status
|
||||||
|
WHEN 'ok' THEN 0
|
||||||
|
WHEN 'due_soon' THEN 1
|
||||||
|
WHEN 'overdue' THEN 10
|
||||||
|
WHEN 'expired' THEN 20
|
||||||
|
END AS due_score,
|
||||||
|
IFNULL(pcs.product_id_effective, rp.product_id) AS product_id_effective,
|
||||||
|
p.name AS product_name
|
||||||
|
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
|
||||||
|
JOIN products_volatile_status pvs
|
||||||
|
ON rp.product_id = pvs.product_id
|
||||||
|
LEFT JOIN product_groups pg
|
||||||
|
ON p.product_group_id = pg.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_substitutions pcs
|
||||||
|
ON rp.product_id = pcs.parent_product_id
|
||||||
|
LEFT JOIN products_current_price pcp
|
||||||
|
ON IFNULL(pcs.product_id_effective, rp.product_id) = pcp.product_id
|
||||||
|
LEFT JOIN products p_effective
|
||||||
|
ON IFNULL(pcs.product_id_effective, rp.product_id) = p_effective.id
|
||||||
|
LEFT JOIN cache__quantity_unit_conversions_resolved qucr
|
||||||
|
ON IFNULL(pcs.product_id_effective, rp.product_id) = qucr.product_id
|
||||||
|
AND CASE WHEN rp.product_id != p_effective.id THEN p.qu_id_stock ELSE rp.qu_id END = qucr.from_qu_id
|
||||||
|
AND IFNULL(p_effective.qu_id_stock, p.qu_id_stock) = qucr.to_qu_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,
|
||||||
|
CASE WHEN rp.round_up = 1 THEN CEIL(CASE WHEN rnr.recipe_id = rnr.includes_recipe_id THEN rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) ELSE rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) * ((rnr.includes_servings*1.0) / (rnrr.base_servings*1.0)) END) ELSE CASE WHEN rnr.recipe_id = rnr.includes_recipe_id THEN rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) ELSE rp.amount * ((r.desired_servings*1.0) / (r.base_servings*1.0)) * ((rnr.includes_servings*1.0) / (rnrr.base_servings*1.0)) END END AS recipe_amount,
|
||||||
|
IFNULL(sc.amount_aggregated, 0) AS stock_amount,
|
||||||
|
1 AS need_fulfilled,
|
||||||
|
0 AS missing_amount,
|
||||||
|
IFNULL(sl.amount, 0) AS amount_on_shopping_list,
|
||||||
|
1 AS need_fulfilled_with_shopping_list,
|
||||||
|
rp.qu_id,
|
||||||
|
(r.desired_servings*1.0 / r.base_servings*1.0) * CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN IFNULL(qucr.factor, 1.0) ELSE 1 END * (rnr.includes_servings*1.0 / CASE WHEN rnr.recipe_id != rnr.includes_recipe_id THEN rnrr.base_servings*1.0 ELSE 1 END) * rp.amount * IFNULL(pcp.price, 0) * rp.price_factor * CASE WHEN rp.product_id != p_effective.id THEN IFNULL(qucr.factor, 1.0) ELSE 1.0 END AS costs,
|
||||||
|
CASE WHEN rnr.recipe_id = rnr.includes_recipe_id THEN 0 ELSE 1 END AS is_nested_recipe_pos,
|
||||||
|
rp.ingredient_group,
|
||||||
|
pg.name as product_group,
|
||||||
|
rp.id, -- Just a dummy id column
|
||||||
|
r.type as recipe_type,
|
||||||
|
rnr.includes_recipe_id as child_recipe_id,
|
||||||
|
rp.note,
|
||||||
|
rp.variable_amount AS recipe_variable_amount,
|
||||||
|
rp.only_check_single_unit_in_stock,
|
||||||
|
rp.amount * CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN IFNULL(qucr.factor, 1.0) ELSE 1 END / 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) * IFNULL(p_effective.calories, 0) * CASE WHEN rp.product_id != p_effective.id THEN IFNULL(qucr.factor, 1.0) ELSE 1.0 END AS calories,
|
||||||
|
p.active AS product_active,
|
||||||
|
CASE pvs.current_due_status
|
||||||
|
WHEN 'ok' THEN 0
|
||||||
|
WHEN 'due_soon' THEN 1
|
||||||
|
WHEN 'overdue' THEN 10
|
||||||
|
WHEN 'expired' THEN 20
|
||||||
|
END AS due_score,
|
||||||
|
IFNULL(pcs.product_id_effective, rp.product_id) AS product_id_effective,
|
||||||
|
p.name AS product_name
|
||||||
|
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
|
||||||
|
JOIN products_volatile_status pvs
|
||||||
|
ON rp.product_id = pvs.product_id
|
||||||
|
LEFT JOIN product_groups pg
|
||||||
|
ON p.product_group_id = pg.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_substitutions pcs
|
||||||
|
ON rp.product_id = pcs.parent_product_id
|
||||||
|
LEFT JOIN products_current_price pcp
|
||||||
|
ON IFNULL(pcs.product_id_effective, rp.product_id) = pcp.product_id
|
||||||
|
LEFT JOIN products p_effective
|
||||||
|
ON IFNULL(pcs.product_id_effective, rp.product_id) = p_effective.id
|
||||||
|
LEFT JOIN cache__quantity_unit_conversions_resolved qucr
|
||||||
|
ON IFNULL(pcs.product_id_effective, rp.product_id) = qucr.product_id
|
||||||
|
AND CASE WHEN rp.product_id != p_effective.id THEN p.qu_id_stock ELSE rp.qu_id END = qucr.from_qu_id
|
||||||
|
AND IFNULL(p_effective.qu_id_stock, p.qu_id_stock) = qucr.to_qu_id
|
||||||
|
WHERE rp.not_check_stock_fulfillment = 1;
|
@ -219,7 +219,7 @@ $(document).on('click', '.recipe-shopping-list', function(e)
|
|||||||
Grocy.Api.Post('recipes/' + objectId + '/add-not-fulfilled-products-to-shoppinglist', { "excludedProductIds": excludedProductIds },
|
Grocy.Api.Post('recipes/' + objectId + '/add-not-fulfilled-products-to-shoppinglist', { "excludedProductIds": excludedProductIds },
|
||||||
function(result)
|
function(result)
|
||||||
{
|
{
|
||||||
window.location.href = U('/recipes');
|
window.location.reload();
|
||||||
},
|
},
|
||||||
function(xhr)
|
function(xhr)
|
||||||
{
|
{
|
||||||
|
@ -8,6 +8,11 @@ if (BoolVal(Grocy.UserSettings.shopping_list_show_calendar))
|
|||||||
$("#shopping_list_show_calendar").prop("checked", true);
|
$("#shopping_list_show_calendar").prop("checked", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (BoolVal(Grocy.UserSettings.shopping_list_round_up))
|
||||||
|
{
|
||||||
|
$("#shopping_list_round_up").prop("checked", true);
|
||||||
|
}
|
||||||
|
|
||||||
if (BoolVal(Grocy.UserSettings.shopping_list_auto_add_below_min_stock_amount))
|
if (BoolVal(Grocy.UserSettings.shopping_list_auto_add_below_min_stock_amount))
|
||||||
{
|
{
|
||||||
$("#shopping_list_auto_add_below_min_stock_amount").prop("checked", true);
|
$("#shopping_list_auto_add_below_min_stock_amount").prop("checked", true);
|
||||||
|
@ -103,6 +103,14 @@ class DatabaseService
|
|||||||
return $usersService->GetUserSetting(GROCY_USER_ID, $value);
|
return $usersService->GetUserSetting(GROCY_USER_ID, $value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Unfortunately not included by default
|
||||||
|
// https://www.sqlite.org/lang_mathfunc.html#ceil
|
||||||
|
$pdo->sqliteCreateFunction('ceil', function ($value)
|
||||||
|
{
|
||||||
|
return ceil($value);
|
||||||
|
});
|
||||||
|
|
||||||
self::$DbConnectionRaw = $pdo;
|
self::$DbConnectionRaw = $pdo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,6 +80,14 @@
|
|||||||
id="variable_amount"
|
id="variable_amount"
|
||||||
name="variable_amount"
|
name="variable_amount"
|
||||||
value="@if($mode == 'edit'){{ $recipePos->variable_amount }}@endif">
|
value="@if($mode == 'edit'){{ $recipePos->variable_amount }}@endif">
|
||||||
|
|
||||||
|
<div class="custom-control custom-checkbox">
|
||||||
|
<input @if($mode=='edit'
|
||||||
|
&&
|
||||||
|
$recipePos->round_up == 1) checked @endif class="form-check-input custom-control-input" type="checkbox" id="round_up" name="round_up" value="1">
|
||||||
|
<label class="form-check-label custom-control-label"
|
||||||
|
for="round_up">{{ $__t('Round up quantity amounts to the nearest whole number') }}</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group @if(!GROCY_FEATURE_FLAG_STOCK) d-none @endif">
|
<div class="form-group @if(!GROCY_FEATURE_FLAG_STOCK) d-none @endif">
|
||||||
|
@ -254,6 +254,11 @@
|
|||||||
$listItem->amount = $listItem->amount * $productQuConversion->factor;
|
$listItem->amount = $listItem->amount * $productQuConversion->factor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(boolval($userSettings['shopping_list_round_up']))
|
||||||
|
{
|
||||||
|
$listItem->amount = ceil($listItem->amount);
|
||||||
|
}
|
||||||
@endphp
|
@endphp
|
||||||
@endif
|
@endif
|
||||||
<td>
|
<td>
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-6 col-12">
|
<div class="col-lg-6 col-12">
|
||||||
<h4 class="mt-2">{{ $__t('Shopping list') }}</h4>
|
<h4 class="mt-2">{{ $__t('Shopping list') }}</h4>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="custom-control custom-checkbox">
|
<div class="custom-control custom-checkbox">
|
||||||
<input type="checkbox"
|
<input type="checkbox"
|
||||||
@ -25,7 +26,22 @@
|
|||||||
{{ $__t('Show a month-view calendar') }}
|
{{ $__t('Show a month-view calendar') }}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="custom-control custom-checkbox">
|
||||||
|
<input type="checkbox"
|
||||||
|
class="form-check-input custom-control-input user-setting-control"
|
||||||
|
id="shopping_list_round_up"
|
||||||
|
data-setting-key="shopping_list_round_up">
|
||||||
|
<label class="form-check-label custom-control-label"
|
||||||
|
for="shopping_list_round_up">
|
||||||
|
{{ $__t('Round up quantity amounts to the nearest whole number') }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
<div class="custom-control custom-checkbox">
|
<div class="custom-control custom-checkbox">
|
||||||
<input type="checkbox"
|
<input type="checkbox"
|
||||||
class="form-check-input custom-control-input user-setting-control"
|
class="form-check-input custom-control-input user-setting-control"
|
||||||
@ -48,7 +64,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<h4 class="mt-2">{{ $__t('Shopping list to stock workflow') }}</h4>
|
<h4 class="mt-2">{{ $__t('Shopping list to stock workflow') }}</h4>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="custom-control custom-checkbox">
|
<div class="custom-control custom-checkbox">
|
||||||
<input type="checkbox"
|
<input type="checkbox"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user