mirror of
https://github.com/grocy/grocy.git
synced 2025-08-20 04:12:59 +00:00
Squashed commit
Optimized new chore start date handling (references #1612) Change yearly chore schedule to be on the same day each year (closes #817) Use the last price for out of stock ingredients (closes #779) Make it optionally possible to show the recipes list full-width (closes #1772)
This commit is contained in:
@@ -10,6 +10,27 @@ UPDATE chores
|
||||
SET start_date = DATETIME('now', 'localtime')
|
||||
WHERE start_date IS NULL;
|
||||
|
||||
CREATE TRIGGER default_start_date_when_empty_INS AFTER INSERT ON chores
|
||||
BEGIN
|
||||
UPDATE chores
|
||||
SET start_date = DATETIME('now', 'localtime')
|
||||
WHERE id = NEW.id
|
||||
AND IFNULL(start_date, '') = '';
|
||||
END;
|
||||
|
||||
CREATE TRIGGER default_start_date_when_empty_UPD AFTER UPDATE ON chores
|
||||
BEGIN
|
||||
UPDATE chores
|
||||
SET start_date = DATETIME('now', 'localtime')
|
||||
WHERE id = NEW.id
|
||||
AND IFNULL(start_date, '') = '';
|
||||
END;
|
||||
|
||||
UPDATE chores
|
||||
SET period_type = 'daily',
|
||||
period_interval = IFNULL(period_interval, 1) * 365
|
||||
WHERE period_type = 'yearly';
|
||||
|
||||
DROP VIEW chores_current;
|
||||
CREATE VIEW chores_current
|
||||
AS
|
||||
@@ -39,33 +60,37 @@ SELECT
|
||||
h.id AS chore_id,
|
||||
h.name AS chore_name,
|
||||
MAX(l.tracked_time) AS last_tracked_time,
|
||||
CASE h.period_type
|
||||
WHEN 'manually' THEN '2999-12-31 23:59:59'
|
||||
WHEN 'dynamic-regular' THEN DATETIME(MAX(l.tracked_time), '+' || CAST(h.period_days AS TEXT) || ' day')
|
||||
WHEN 'daily' THEN DATETIME(IFNULL(MAX(l.tracked_time), h.start_date), '+' || CAST(h.period_interval AS TEXT) || ' day')
|
||||
WHEN 'weekly' THEN (
|
||||
SELECT next
|
||||
FROM (
|
||||
SELECT 'sunday' AS day, DATETIME(COALESCE((SELECT tracked_time FROM chores_log WHERE chore_id = h.id ORDER BY tracked_time DESC LIMIT 1), h.start_date), '1 days', '+' || CAST((h.period_interval - 1) * 7 AS TEXT) || ' days', 'weekday 0') AS next
|
||||
UNION
|
||||
SELECT 'monday' AS day, DATETIME(COALESCE((SELECT tracked_time FROM chores_log WHERE chore_id = h.id ORDER BY tracked_time DESC LIMIT 1), h.start_date), '1 days', '+' || CAST((h.period_interval - 1) * 7 AS TEXT) || ' days', 'weekday 1') AS next
|
||||
UNION
|
||||
SELECT 'tuesday' AS day, DATETIME(COALESCE((SELECT tracked_time FROM chores_log WHERE chore_id = h.id ORDER BY tracked_time DESC LIMIT 1), h.start_date), '1 days', '+' || CAST((h.period_interval - 1) * 7 AS TEXT) || ' days', 'weekday 2') AS next
|
||||
UNION
|
||||
SELECT 'wednesday' AS day, DATETIME(COALESCE((SELECT tracked_time FROM chores_log WHERE chore_id = h.id ORDER BY tracked_time DESC LIMIT 1), h.start_date), '1 days', '+' || CAST((h.period_interval - 1) * 7 AS TEXT) || ' days', 'weekday 3') AS next
|
||||
UNION
|
||||
SELECT 'thursday' AS day, DATETIME(COALESCE((SELECT tracked_time FROM chores_log WHERE chore_id = h.id ORDER BY tracked_time DESC LIMIT 1), h.start_date), '1 days', '+' || CAST((h.period_interval - 1) * 7 AS TEXT) || ' days', 'weekday 4') AS next
|
||||
UNION
|
||||
SELECT 'friday' AS day, DATETIME(COALESCE((SELECT tracked_time FROM chores_log WHERE chore_id = h.id ORDER BY tracked_time DESC LIMIT 1), h.start_date), '1 days', '+' || CAST((h.period_interval - 1) * 7 AS TEXT) || ' days', 'weekday 5') AS next
|
||||
UNION
|
||||
SELECT 'saturday' AS day, DATETIME(COALESCE((SELECT tracked_time FROM chores_log WHERE chore_id = h.id ORDER BY tracked_time DESC LIMIT 1), h.start_date), '1 days', '+' || CAST((h.period_interval - 1) * 7 AS TEXT) || ' days', 'weekday 6') AS next
|
||||
CASE WHEN MAX(l.tracked_time) IS NULL THEN
|
||||
h.start_date
|
||||
ELSE
|
||||
CASE h.period_type
|
||||
WHEN 'manually' THEN '2999-12-31 23:59:59'
|
||||
WHEN 'dynamic-regular' THEN DATETIME(MAX(l.tracked_time), '+' || CAST(h.period_days AS TEXT) || ' day')
|
||||
WHEN 'daily' THEN DATETIME(MAX(l.tracked_time), '+' || CAST(h.period_interval AS TEXT) || ' day')
|
||||
WHEN 'weekly' THEN (
|
||||
SELECT next
|
||||
FROM (
|
||||
SELECT 'sunday' AS day, DATETIME((SELECT tracked_time FROM chores_log WHERE chore_id = h.id ORDER BY tracked_time DESC LIMIT 1), '1 days', '+' || CAST((h.period_interval - 1) * 7 AS TEXT) || ' days', 'weekday 0') AS next
|
||||
UNION
|
||||
SELECT 'monday' AS day, DATETIME((SELECT tracked_time FROM chores_log WHERE chore_id = h.id ORDER BY tracked_time DESC LIMIT 1), '1 days', '+' || CAST((h.period_interval - 1) * 7 AS TEXT) || ' days', 'weekday 1') AS next
|
||||
UNION
|
||||
SELECT 'tuesday' AS day, DATETIME((SELECT tracked_time FROM chores_log WHERE chore_id = h.id ORDER BY tracked_time DESC LIMIT 1), '1 days', '+' || CAST((h.period_interval - 1) * 7 AS TEXT) || ' days', 'weekday 2') AS next
|
||||
UNION
|
||||
SELECT 'wednesday' AS day, DATETIME((SELECT tracked_time FROM chores_log WHERE chore_id = h.id ORDER BY tracked_time DESC LIMIT 1), '1 days', '+' || CAST((h.period_interval - 1) * 7 AS TEXT) || ' days', 'weekday 3') AS next
|
||||
UNION
|
||||
SELECT 'thursday' AS day, DATETIME((SELECT tracked_time FROM chores_log WHERE chore_id = h.id ORDER BY tracked_time DESC LIMIT 1), '1 days', '+' || CAST((h.period_interval - 1) * 7 AS TEXT) || ' days', 'weekday 4') AS next
|
||||
UNION
|
||||
SELECT 'friday' AS day, DATETIME((SELECT tracked_time FROM chores_log WHERE chore_id = h.id ORDER BY tracked_time DESC LIMIT 1), '1 days', '+' || CAST((h.period_interval - 1) * 7 AS TEXT) || ' days', 'weekday 5') AS next
|
||||
UNION
|
||||
SELECT 'saturday' AS day, DATETIME((SELECT tracked_time FROM chores_log WHERE chore_id = h.id ORDER BY tracked_time DESC LIMIT 1), '1 days', '+' || CAST((h.period_interval - 1) * 7 AS TEXT) || ' days', 'weekday 6') AS next
|
||||
)
|
||||
WHERE INSTR(period_config, day) > 0
|
||||
ORDER BY next
|
||||
LIMIT 1
|
||||
)
|
||||
WHERE INSTR(period_config, day) > 0
|
||||
ORDER BY next
|
||||
LIMIT 1
|
||||
)
|
||||
WHEN 'monthly' THEN DATETIME(IFNULL(MAX(l.tracked_time), h.start_date), 'start of month', '+' || CAST(h.period_interval AS TEXT) || ' month', '+' || CAST(h.period_days - 1 AS TEXT) || ' day')
|
||||
WHEN 'yearly' THEN DATETIME(IFNULL(MAX(l.tracked_time), h.start_date), '+' || CAST(h.period_interval AS TEXT) || ' years')
|
||||
WHEN 'monthly' THEN DATETIME(MAX(l.tracked_time), 'start of month', '+' || CAST(h.period_interval AS TEXT) || ' month', '+' || CAST(h.period_days - 1 AS TEXT) || ' day')
|
||||
WHEN 'yearly' THEN DATETIME(SUBSTR(CAST(DATETIME(MAX(l.tracked_time), '+' || CAST(h.period_interval AS TEXT) || ' years') AS TEXT), 1, 4) || SUBSTR(CAST(h.start_date AS TEXT), 5, 6) || SUBSTR(CAST(DATETIME(MAX(l.tracked_time), '+' || CAST(h.period_interval AS TEXT) || ' years') AS TEXT), -9))
|
||||
END
|
||||
END AS next_estimated_execution_time,
|
||||
h.track_date_only,
|
||||
h.rollover,
|
||||
|
111
migrations/0165.sql
Normal file
111
migrations/0165.sql
Normal file
@@ -0,0 +1,111 @@
|
||||
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,
|
||||
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 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 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 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 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 < 0 THEN ABS(IFNULL(sc.amount_aggregated, 0) - (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 0 END AS missing_amount,
|
||||
IFNULL(sl.amount, 0) * p.qu_factor_purchase_to_stock 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 * p.qu_factor_purchase_to_stock), 2) >= ROUND(CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN 0.00000001 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, 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) * (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(pop.price, IFNULL(plp.price, 0)) * rp.price_factor * CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN IFNULL(qucr.factor, 1) ELSE 1 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 / 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.calories, 0) * CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN IFNULL(qucr.factor, 1) ELSE 1 END AS calories,
|
||||
p.active AS product_active
|
||||
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 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_oldest_stock_unit_price pop
|
||||
ON rp.product_id = pop.product_id
|
||||
LEFT JOIN products_last_purchased plp
|
||||
ON rp.product_id = plp.product_id
|
||||
LEFT JOIN quantity_unit_conversions_resolved qucr
|
||||
ON rp.product_id = qucr.product_id
|
||||
AND rp.qu_id = qucr.from_qu_id
|
||||
AND 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 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 AS recipe_amount,
|
||||
IFNULL(sc.amount_aggregated, 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,
|
||||
(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) * rp.amount * IFNULL(pop.price, IFNULL(plp.price, 0)) * rp.price_factor * CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN IFNULL(qucr.factor, 1) ELSE 1 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 / 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.calories, 0) * CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN IFNULL(qucr.factor, 1) ELSE 1 END AS calories,
|
||||
p.active AS product_active
|
||||
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 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_oldest_stock_unit_price pop
|
||||
ON rp.product_id = pop.product_id
|
||||
LEFT JOIN products_last_purchased plp
|
||||
ON rp.product_id = plp.product_id
|
||||
LEFT JOIN quantity_unit_conversions_resolved qucr
|
||||
ON rp.product_id = qucr.product_id
|
||||
AND rp.qu_id = qucr.from_qu_id
|
||||
AND p.qu_id_stock = qucr.to_qu_id
|
||||
WHERE rp.not_check_stock_fulfillment = 1;
|
Reference in New Issue
Block a user