mirror of
https://github.com/grocy/grocy.git
synced 2025-08-18 11:27:03 +00:00
Fix is_aggregated_amount of stock_current did not work anymore
This commit is contained in:
@@ -141,20 +141,3 @@ WHERE pr.parent_product_id != pr.sub_product_id
|
|||||||
GROUP BY pr.sub_product_id
|
GROUP BY pr.sub_product_id
|
||||||
HAVING SUM(s.amount) > 0;
|
HAVING SUM(s.amount) > 0;
|
||||||
|
|
||||||
DROP VIEW products_resolved;
|
|
||||||
CREATE VIEW products_resolved AS
|
|
||||||
SELECT
|
|
||||||
p.parent_product_id parent_product_id,
|
|
||||||
p.id as sub_product_id
|
|
||||||
FROM products p
|
|
||||||
WHERE p.parent_product_id IS NOT NULL
|
|
||||||
AND p.active = 1
|
|
||||||
|
|
||||||
UNION
|
|
||||||
|
|
||||||
SELECT
|
|
||||||
p.id parent_product_id,
|
|
||||||
p.id as sub_product_id
|
|
||||||
FROM products p
|
|
||||||
WHERE p.parent_product_id IS NULL
|
|
||||||
AND p.active = 1;
|
|
||||||
|
@@ -1,29 +1,61 @@
|
|||||||
CREATE INDEX ix_products_performance1 ON products (
|
DROP VIEW stock_missing_products_including_opened;
|
||||||
parent_product_id
|
CREATE VIEW stock_missing_products_including_opened
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX ix_products_performance2 ON products (
|
|
||||||
CASE WHEN parent_product_id IS NULL THEN id ELSE parent_product_id END,
|
|
||||||
active
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX ix_stock_performance1 ON stock (
|
|
||||||
product_id,
|
|
||||||
open,
|
|
||||||
best_before_date,
|
|
||||||
amount
|
|
||||||
);
|
|
||||||
|
|
||||||
DROP VIEW products_resolved;
|
|
||||||
CREATE VIEW products_resolved
|
|
||||||
AS
|
AS
|
||||||
|
|
||||||
|
/* This is basically the same view as stock_missing_products, but the column "amount_missing" includes opened amounts */
|
||||||
|
|
||||||
|
-- Products WITHOUT sub products where the amount of the sub products SHOULD NOT be cumulated
|
||||||
SELECT
|
SELECT
|
||||||
CASE
|
p.id,
|
||||||
WHEN p.parent_product_id IS NULL THEN
|
MAX(p.name) AS name,
|
||||||
p.id
|
p.min_stock_amount - (IFNULL(SUM(s.amount), 0) - IFNULL(SUM(s.amount_opened), 0)) AS amount_missing,
|
||||||
ELSE
|
CASE WHEN IFNULL(SUM(s.amount), 0) > 0 THEN 1 ELSE 0 END AS is_partly_in_stock
|
||||||
p.parent_product_id
|
FROM products_view p
|
||||||
END AS parent_product_id,
|
LEFT JOIN stock_current s
|
||||||
p.id as sub_product_id
|
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) - IFNULL(SUM(s.amount_opened), 0) < p.min_stock_amount
|
||||||
|
|
||||||
|
UNION
|
||||||
|
|
||||||
|
-- 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_aggregated), 0) - IFNULL(SUM(s.amount_opened_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
|
||||||
|
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_sub_products = 1
|
||||||
|
GROUP BY p.id
|
||||||
|
HAVING IFNULL(SUM(s.amount_aggregated), 0) - IFNULL(SUM(s.amount_opened_aggregated), 0) < SUM(sub_p.min_stock_amount)
|
||||||
|
|
||||||
|
UNION
|
||||||
|
|
||||||
|
-- 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 p
|
FROM products p
|
||||||
WHERE p.active = 1;
|
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_sub_products = 0
|
||||||
|
GROUP BY sub_p.id
|
||||||
|
HAVING IFNULL(SUM(s.amount), 0) - IFNULL(SUM(s.amount_opened), 0) < sub_p.min_stock_amount;
|
||||||
|
@@ -1,61 +1,27 @@
|
|||||||
DROP VIEW stock_missing_products_including_opened;
|
DELETE FROM shopping_list
|
||||||
CREATE VIEW stock_missing_products_including_opened
|
WHERE shopping_list_id NOT IN (SELECT id FROM shopping_lists);
|
||||||
AS
|
|
||||||
|
|
||||||
/* This is basically the same view as stock_missing_products, but the column "amount_missing" includes opened amounts */
|
CREATE TRIGGER remove_items_from_deleted_shopping_list AFTER DELETE ON shopping_lists
|
||||||
|
BEGIN
|
||||||
|
DELETE FROM shopping_list WHERE shopping_list_id = OLD.id;
|
||||||
|
END;
|
||||||
|
|
||||||
-- Products WITHOUT sub products where the amount of the sub products SHOULD NOT be cumulated
|
CREATE TRIGGER prevent_infinite_nested_recipes_INS BEFORE INSERT ON recipes_nestings
|
||||||
SELECT
|
BEGIN
|
||||||
p.id,
|
SELECT CASE WHEN((
|
||||||
MAX(p.name) AS name,
|
SELECT 1
|
||||||
p.min_stock_amount - (IFNULL(SUM(s.amount), 0) - IFNULL(SUM(s.amount_opened), 0)) AS amount_missing,
|
FROM recipes_nestings_resolved rnr
|
||||||
CASE WHEN IFNULL(SUM(s.amount), 0) > 0 THEN 1 ELSE 0 END AS is_partly_in_stock
|
WHERE NEW.recipe_id = rnr.includes_recipe_id
|
||||||
FROM products_view p
|
AND NEW.includes_recipe_id = rnr.recipe_id
|
||||||
LEFT JOIN stock_current s
|
) NOTNULL) THEN RAISE(ABORT, "Recursive nested recipe detected") END;
|
||||||
ON p.id = s.product_id
|
END;
|
||||||
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) - IFNULL(SUM(s.amount_opened), 0) < p.min_stock_amount
|
|
||||||
|
|
||||||
UNION
|
CREATE TRIGGER prevent_infinite_nested_recipes_UPD BEFORE UPDATE ON recipes_nestings
|
||||||
|
BEGIN
|
||||||
-- Parent products WITH sub products where the amount of the sub products SHOULD be cumulated
|
SELECT CASE WHEN((
|
||||||
SELECT
|
SELECT 1
|
||||||
p.id,
|
FROM recipes_nestings_resolved rnr
|
||||||
MAX(p.name) AS name,
|
WHERE NEW.recipe_id = rnr.includes_recipe_id
|
||||||
SUM(sub_p.min_stock_amount) - (IFNULL(SUM(s.amount_aggregated), 0) - IFNULL(SUM(s.amount_opened_aggregated), 0)) AS amount_missing,
|
AND NEW.includes_recipe_id = rnr.recipe_id
|
||||||
CASE WHEN IFNULL(SUM(s.amount), 0) > 0 THEN 1 ELSE 0 END AS is_partly_in_stock
|
) NOTNULL) THEN RAISE(ABORT, "Recursive nested recipe detected") END;
|
||||||
FROM products_view p
|
END;
|
||||||
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_sub_products = 1
|
|
||||||
GROUP BY p.id
|
|
||||||
HAVING IFNULL(SUM(s.amount_aggregated), 0) - IFNULL(SUM(s.amount_opened_aggregated), 0) < SUM(sub_p.min_stock_amount)
|
|
||||||
|
|
||||||
UNION
|
|
||||||
|
|
||||||
-- 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 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_sub_products = 0
|
|
||||||
GROUP BY sub_p.id
|
|
||||||
HAVING IFNULL(SUM(s.amount), 0) - IFNULL(SUM(s.amount_opened), 0) < sub_p.min_stock_amount;
|
|
||||||
|
@@ -1,27 +1,46 @@
|
|||||||
DELETE FROM shopping_list
|
DROP VIEW stock_current;
|
||||||
WHERE shopping_list_id NOT IN (SELECT id FROM shopping_lists);
|
CREATE VIEW stock_current
|
||||||
|
AS
|
||||||
|
SELECT
|
||||||
|
pr.parent_product_id AS product_id,
|
||||||
|
IFNULL((SELECT SUM(amount) FROM stock WHERE product_id = pr.parent_product_id), 0) AS amount,
|
||||||
|
SUM(s.amount * IFNULL(qucr.factor, 1.0)) AS amount_aggregated,
|
||||||
|
IFNULL(ROUND((SELECT SUM(IFNULL(price,0) * amount) FROM stock WHERE product_id = pr.parent_product_id), 2), 0) AS value,
|
||||||
|
MIN(s.best_before_date) AS best_before_date,
|
||||||
|
IFNULL((SELECT SUM(amount) FROM stock WHERE product_id = pr.parent_product_id AND open = 1), 0) AS amount_opened,
|
||||||
|
IFNULL((SELECT SUM(amount) FROM stock WHERE product_id IN (SELECT sub_product_id FROM products_resolved WHERE parent_product_id = pr.parent_product_id) AND open = 1), 0) * IFNULL(qucr.factor, 1) AS amount_opened_aggregated,
|
||||||
|
CASE WHEN p_sub.parent_product_id IS NOT NULL THEN 1 ELSE 0 END AS is_aggregated_amount
|
||||||
|
FROM products_resolved pr
|
||||||
|
JOIN stock s
|
||||||
|
ON pr.sub_product_id = s.product_id
|
||||||
|
JOIN products p_parent
|
||||||
|
ON pr.parent_product_id = p_parent.id
|
||||||
|
AND p_parent.active = 1
|
||||||
|
JOIN products p_sub
|
||||||
|
ON pr.sub_product_id = p_sub.id
|
||||||
|
AND p_sub.active = 1
|
||||||
|
LEFT JOIN quantity_unit_conversions_resolved qucr
|
||||||
|
ON pr.sub_product_id = qucr.product_id
|
||||||
|
AND p_sub.qu_id_stock = qucr.from_qu_id
|
||||||
|
AND p_parent.qu_id_stock = qucr.to_qu_id
|
||||||
|
GROUP BY pr.parent_product_id
|
||||||
|
HAVING SUM(s.amount) > 0
|
||||||
|
|
||||||
CREATE TRIGGER remove_items_from_deleted_shopping_list AFTER DELETE ON shopping_lists
|
UNION
|
||||||
BEGIN
|
|
||||||
DELETE FROM shopping_list WHERE shopping_list_id = OLD.id;
|
|
||||||
END;
|
|
||||||
|
|
||||||
CREATE TRIGGER prevent_infinite_nested_recipes_INS BEFORE INSERT ON recipes_nestings
|
-- This is the same as above but sub products not rolled up (no QU conversion and column is_aggregated_amount = 0 here)
|
||||||
BEGIN
|
SELECT
|
||||||
SELECT CASE WHEN((
|
pr.sub_product_id AS product_id,
|
||||||
SELECT 1
|
SUM(s.amount) AS amount,
|
||||||
FROM recipes_nestings_resolved rnr
|
SUM(s.amount) AS amount_aggregated,
|
||||||
WHERE NEW.recipe_id = rnr.includes_recipe_id
|
ROUND(SUM(IFNULL(s.price, 0) * s.amount), 2) AS value,
|
||||||
AND NEW.includes_recipe_id = rnr.recipe_id
|
MIN(s.best_before_date) AS best_before_date,
|
||||||
) NOTNULL) THEN RAISE(ABORT, "Recursive nested recipe detected") END;
|
IFNULL((SELECT SUM(amount) FROM stock WHERE product_id = s.product_id AND open = 1), 0) AS amount_opened,
|
||||||
END;
|
IFNULL((SELECT SUM(amount) FROM stock WHERE product_id = s.product_id AND open = 1), 0) AS amount_opened_aggregated,
|
||||||
|
0 AS is_aggregated_amount
|
||||||
CREATE TRIGGER prevent_infinite_nested_recipes_UPD BEFORE UPDATE ON recipes_nestings
|
FROM products_resolved pr
|
||||||
BEGIN
|
JOIN stock s
|
||||||
SELECT CASE WHEN((
|
ON pr.sub_product_id = s.product_id
|
||||||
SELECT 1
|
WHERE pr.parent_product_id != pr.sub_product_id
|
||||||
FROM recipes_nestings_resolved rnr
|
GROUP BY pr.sub_product_id
|
||||||
WHERE NEW.recipe_id = rnr.includes_recipe_id
|
HAVING SUM(s.amount) > 0;
|
||||||
AND NEW.includes_recipe_id = rnr.recipe_id
|
|
||||||
) NOTNULL) THEN RAISE(ABORT, "Recursive nested recipe detected") END;
|
|
||||||
END;
|
|
||||||
|
@@ -1,46 +1,22 @@
|
|||||||
DROP VIEW stock_current;
|
CREATE VIEW product_price_history
|
||||||
CREATE VIEW stock_current
|
|
||||||
AS
|
AS
|
||||||
SELECT
|
SELECT
|
||||||
pr.parent_product_id AS product_id,
|
sl.product_id AS id, -- Dummy, LessQL needs an id column
|
||||||
IFNULL((SELECT SUM(amount) FROM stock WHERE product_id = pr.parent_product_id), 0) AS amount,
|
sl.product_id,
|
||||||
SUM(s.amount * IFNULL(qucr.factor, 1.0)) AS amount_aggregated,
|
sl.price,
|
||||||
IFNULL(ROUND((SELECT SUM(IFNULL(price,0) * amount) FROM stock WHERE product_id = pr.parent_product_id), 2), 0) AS value,
|
sl.purchased_date,
|
||||||
MIN(s.best_before_date) AS best_before_date,
|
sl.shopping_location_id
|
||||||
IFNULL((SELECT SUM(amount) FROM stock WHERE product_id = pr.parent_product_id AND open = 1), 0) AS amount_opened,
|
FROM stock_log sl
|
||||||
IFNULL((SELECT SUM(amount) FROM stock WHERE product_id IN (SELECT sub_product_id FROM products_resolved WHERE parent_product_id = pr.parent_product_id) AND open = 1), 0) * IFNULL(qucr.factor, 1) AS amount_opened_aggregated,
|
WHERE sl.transaction_type IN ('purchase', 'inventory-correction', 'stock-edit-new')
|
||||||
CASE WHEN p_sub.parent_product_id IS NOT NULL THEN 1 ELSE 0 END AS is_aggregated_amount
|
AND sl.undone = 0
|
||||||
FROM products_resolved pr
|
AND sl.price IS NOT NULL
|
||||||
JOIN stock s
|
AND sl.id NOT IN (
|
||||||
ON pr.sub_product_id = s.product_id
|
-- These are edited purchase and inventory-correction rows
|
||||||
JOIN products p_parent
|
SELECT sl_origin.id
|
||||||
ON pr.parent_product_id = p_parent.id
|
FROM stock_log sl_origin
|
||||||
AND p_parent.active = 1
|
JOIN stock_log sl_edit
|
||||||
JOIN products p_sub
|
ON sl_origin.stock_id = sl_edit.stock_id
|
||||||
ON pr.sub_product_id = p_sub.id
|
AND sl_edit.transaction_type = 'stock-edit-new'
|
||||||
AND p_sub.active = 1
|
AND sl_edit.id > sl_origin.id
|
||||||
LEFT JOIN quantity_unit_conversions_resolved qucr
|
WHERE sl_origin.transaction_type IN ('purchase', 'inventory-correction')
|
||||||
ON pr.sub_product_id = qucr.product_id
|
);
|
||||||
AND p_sub.qu_id_stock = qucr.from_qu_id
|
|
||||||
AND p_parent.qu_id_stock = qucr.to_qu_id
|
|
||||||
GROUP BY pr.parent_product_id
|
|
||||||
HAVING SUM(s.amount) > 0
|
|
||||||
|
|
||||||
UNION
|
|
||||||
|
|
||||||
-- This is the same as above but sub products not rolled up (no QU conversion and column is_aggregated_amount = 0 here)
|
|
||||||
SELECT
|
|
||||||
pr.sub_product_id AS product_id,
|
|
||||||
SUM(s.amount) AS amount,
|
|
||||||
SUM(s.amount) AS amount_aggregated,
|
|
||||||
ROUND(SUM(IFNULL(s.price, 0) * s.amount), 2) AS value,
|
|
||||||
MIN(s.best_before_date) AS best_before_date,
|
|
||||||
IFNULL((SELECT SUM(amount) FROM stock WHERE product_id = s.product_id AND open = 1), 0) AS amount_opened,
|
|
||||||
IFNULL((SELECT SUM(amount) FROM stock WHERE product_id = s.product_id AND open = 1), 0) AS amount_opened_aggregated,
|
|
||||||
0 AS is_aggregated_amount
|
|
||||||
FROM products_resolved pr
|
|
||||||
JOIN stock s
|
|
||||||
ON pr.sub_product_id = s.product_id
|
|
||||||
WHERE pr.parent_product_id != pr.sub_product_id
|
|
||||||
GROUP BY pr.sub_product_id
|
|
||||||
HAVING SUM(s.amount) > 0;
|
|
||||||
|
@@ -1,22 +1,134 @@
|
|||||||
CREATE VIEW product_price_history
|
CREATE TABLE user_permissions
|
||||||
|
(
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
||||||
|
permission_id INTEGER NOT NULL,
|
||||||
|
user_id INTEGER NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE (user_id, permission_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE permission_hierarchy
|
||||||
|
(
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
||||||
|
name TEXT NOT NULL UNIQUE,
|
||||||
|
parent INTEGER NULL -- If the user has the parent permission, the user also has the child permission
|
||||||
|
);
|
||||||
|
|
||||||
|
-- The root/ADMIN permission
|
||||||
|
INSERT INTO permission_hierarchy
|
||||||
|
(name, parent)
|
||||||
|
VALUES
|
||||||
|
('ADMIN', NULL);
|
||||||
|
|
||||||
|
-- User add/edit/read permissions
|
||||||
|
INSERT INTO permission_hierarchy
|
||||||
|
(name, parent)
|
||||||
|
VALUES
|
||||||
|
('USERS', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN'));
|
||||||
|
|
||||||
|
INSERT INTO permission_hierarchy
|
||||||
|
(name, parent)
|
||||||
|
VALUES
|
||||||
|
('USERS_CREATE', (SELECT id FROM permission_hierarchy WHERE name = 'USERS'));
|
||||||
|
|
||||||
|
INSERT INTO permission_hierarchy
|
||||||
|
(name, parent)
|
||||||
|
VALUES
|
||||||
|
('USERS_EDIT', last_insert_rowid());
|
||||||
|
|
||||||
|
INSERT INTO permission_hierarchy
|
||||||
|
(name, parent)
|
||||||
|
VALUES
|
||||||
|
('USERS_READ', last_insert_rowid()),
|
||||||
|
('USERS_EDIT_SELF', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN'));
|
||||||
|
|
||||||
|
-- Base permissions per major feature
|
||||||
|
INSERT INTO permission_hierarchy
|
||||||
|
(name, parent)
|
||||||
|
VALUES
|
||||||
|
('STOCK', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')),
|
||||||
|
('SHOPPINGLIST', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')),
|
||||||
|
('RECIPES', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')),
|
||||||
|
('CHORES', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')),
|
||||||
|
('BATTERIES', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')),
|
||||||
|
('TASKS', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')),
|
||||||
|
('EQUIPMENT', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')),
|
||||||
|
('CALENDAR', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN'));
|
||||||
|
|
||||||
|
-- Sub feature permissions
|
||||||
|
INSERT INTO permission_hierarchy
|
||||||
|
(name, parent)
|
||||||
|
VALUES
|
||||||
|
-- Stock
|
||||||
|
('STOCK_PURCHASE', (SELECT id FROM permission_hierarchy WHERE name = 'STOCK')),
|
||||||
|
('STOCK_CONSUME', (SELECT id FROM permission_hierarchy WHERE name = 'STOCK')),
|
||||||
|
('STOCK_INVENTORY', (SELECT id FROM permission_hierarchy WHERE name = 'STOCK')),
|
||||||
|
('STOCK_TRANSFER', (SELECT id FROM permission_hierarchy WHERE name = 'STOCK')),
|
||||||
|
('STOCK_OPEN', (SELECT id FROM permission_hierarchy WHERE name = 'STOCK')),
|
||||||
|
('STOCK_EDIT', (SELECT id FROM permission_hierarchy WHERE name = 'STOCK')),
|
||||||
|
|
||||||
|
-- Shopping list
|
||||||
|
('SHOPPINGLIST_ITEMS_ADD', (SELECT id FROM permission_hierarchy WHERE name = 'SHOPPINGLIST')),
|
||||||
|
('SHOPPINGLIST_ITEMS_DELETE', (SELECT id FROM permission_hierarchy WHERE name = 'SHOPPINGLIST')),
|
||||||
|
|
||||||
|
-- Recipes
|
||||||
|
('RECIPES_MEALPLAN', (SELECT id FROM permission_hierarchy WHERE name = 'RECIPES')),
|
||||||
|
|
||||||
|
-- Chores
|
||||||
|
('CHORE_TRACK_EXECUTION', (SELECT id FROM permission_hierarchy WHERE name = 'CHORES')),
|
||||||
|
('CHORE_UNDO_EXECUTION', (SELECT id FROM permission_hierarchy WHERE name = 'CHORES')),
|
||||||
|
|
||||||
|
-- Batteries
|
||||||
|
('BATTERIES_TRACK_CHARGE_CYCLE', (SELECT id FROM permission_hierarchy WHERE name = 'BATTERIES')),
|
||||||
|
('BATTERIES_UNDO_CHARGE_CYCLE', (SELECT id FROM permission_hierarchy WHERE name = 'BATTERIES')),
|
||||||
|
|
||||||
|
-- Tasks
|
||||||
|
('TASKS_UNDO_EXECUTION', (SELECT id FROM permission_hierarchy WHERE name = 'TASKS')),
|
||||||
|
('TASKS_MARK_COMPLETED', (SELECT id FROM permission_hierarchy WHERE name = 'TASKS')),
|
||||||
|
|
||||||
|
-- Others
|
||||||
|
('MASTER_DATA_EDIT', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN'));
|
||||||
|
|
||||||
|
-- All existing users get the ADMIN permission
|
||||||
|
INSERT INTO user_permissions
|
||||||
|
(permission_id, user_id)
|
||||||
|
SELECT (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN'), id
|
||||||
|
FROM users;
|
||||||
|
|
||||||
|
CREATE VIEW permission_tree
|
||||||
|
AS
|
||||||
|
WITH RECURSIVE perm AS (
|
||||||
|
SELECT id AS root, id AS child, name, parent
|
||||||
|
FROM permission_hierarchy
|
||||||
|
UNION
|
||||||
|
SELECT perm.root, ph.id, ph.name, ph.id
|
||||||
|
FROM permission_hierarchy ph, perm
|
||||||
|
WHERE ph.parent = perm.child
|
||||||
|
)
|
||||||
|
SELECT root AS id, name AS name
|
||||||
|
FROM perm;
|
||||||
|
|
||||||
|
CREATE VIEW user_permissions_resolved
|
||||||
AS
|
AS
|
||||||
SELECT
|
SELECT
|
||||||
sl.product_id AS id, -- Dummy, LessQL needs an id column
|
u.id AS id, -- Dummy for LessQL
|
||||||
sl.product_id,
|
u.id AS user_id,
|
||||||
sl.price,
|
pt.name AS permission_name
|
||||||
sl.purchased_date,
|
FROM permission_tree pt, users u
|
||||||
sl.shopping_location_id
|
WHERE pt.id IN (SELECT permission_id FROM user_permissions sub_up WHERE sub_up.user_id = u.id);
|
||||||
FROM stock_log sl
|
|
||||||
WHERE sl.transaction_type IN ('purchase', 'inventory-correction', 'stock-edit-new')
|
CREATE VIEW uihelper_user_permissions
|
||||||
AND sl.undone = 0
|
AS
|
||||||
AND sl.price IS NOT NULL
|
SELECT
|
||||||
AND sl.id NOT IN (
|
ph.id AS id,
|
||||||
-- These are edited purchase and inventory-correction rows
|
u.id AS user_id,
|
||||||
SELECT sl_origin.id
|
ph.name AS permission_name,
|
||||||
FROM stock_log sl_origin
|
ph.id AS permission_id,
|
||||||
JOIN stock_log sl_edit
|
(ph.name IN (
|
||||||
ON sl_origin.stock_id = sl_edit.stock_id
|
SELECT pc.permission_name
|
||||||
AND sl_edit.transaction_type = 'stock-edit-new'
|
FROM user_permissions_resolved pc
|
||||||
AND sl_edit.id > sl_origin.id
|
WHERE pc.user_id = u.id
|
||||||
WHERE sl_origin.transaction_type IN ('purchase', 'inventory-correction')
|
)
|
||||||
);
|
) AS has_permission,
|
||||||
|
ph.parent AS parent
|
||||||
|
FROM users u, permission_hierarchy ph;
|
||||||
|
@@ -1,134 +1,16 @@
|
|||||||
CREATE TABLE user_permissions
|
DELETE FROM userfield_values
|
||||||
(
|
WHERE IFNULL(value, '') = '';
|
||||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
|
||||||
permission_id INTEGER NOT NULL,
|
|
||||||
user_id INTEGER NOT NULL,
|
|
||||||
|
|
||||||
UNIQUE (user_id, permission_id)
|
CREATE TRIGGER prevent_empty_userfields_INS AFTER INSERT ON userfield_values
|
||||||
);
|
BEGIN
|
||||||
|
DELETE FROM userfield_values
|
||||||
|
WHERE id = NEW.id
|
||||||
|
AND IFNULL(value, '') = '';
|
||||||
|
END;
|
||||||
|
|
||||||
CREATE TABLE permission_hierarchy
|
CREATE TRIGGER prevent_empty_userfields_UPD AFTER UPDATE ON userfield_values
|
||||||
(
|
BEGIN
|
||||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
DELETE FROM userfield_values
|
||||||
name TEXT NOT NULL UNIQUE,
|
WHERE id = NEW.id
|
||||||
parent INTEGER NULL -- If the user has the parent permission, the user also has the child permission
|
AND IFNULL(value, '') = '';
|
||||||
);
|
END;
|
||||||
|
|
||||||
-- The root/ADMIN permission
|
|
||||||
INSERT INTO permission_hierarchy
|
|
||||||
(name, parent)
|
|
||||||
VALUES
|
|
||||||
('ADMIN', NULL);
|
|
||||||
|
|
||||||
-- User add/edit/read permissions
|
|
||||||
INSERT INTO permission_hierarchy
|
|
||||||
(name, parent)
|
|
||||||
VALUES
|
|
||||||
('USERS', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN'));
|
|
||||||
|
|
||||||
INSERT INTO permission_hierarchy
|
|
||||||
(name, parent)
|
|
||||||
VALUES
|
|
||||||
('USERS_CREATE', (SELECT id FROM permission_hierarchy WHERE name = 'USERS'));
|
|
||||||
|
|
||||||
INSERT INTO permission_hierarchy
|
|
||||||
(name, parent)
|
|
||||||
VALUES
|
|
||||||
('USERS_EDIT', last_insert_rowid());
|
|
||||||
|
|
||||||
INSERT INTO permission_hierarchy
|
|
||||||
(name, parent)
|
|
||||||
VALUES
|
|
||||||
('USERS_READ', last_insert_rowid()),
|
|
||||||
('USERS_EDIT_SELF', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN'));
|
|
||||||
|
|
||||||
-- Base permissions per major feature
|
|
||||||
INSERT INTO permission_hierarchy
|
|
||||||
(name, parent)
|
|
||||||
VALUES
|
|
||||||
('STOCK', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')),
|
|
||||||
('SHOPPINGLIST', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')),
|
|
||||||
('RECIPES', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')),
|
|
||||||
('CHORES', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')),
|
|
||||||
('BATTERIES', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')),
|
|
||||||
('TASKS', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')),
|
|
||||||
('EQUIPMENT', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')),
|
|
||||||
('CALENDAR', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN'));
|
|
||||||
|
|
||||||
-- Sub feature permissions
|
|
||||||
INSERT INTO permission_hierarchy
|
|
||||||
(name, parent)
|
|
||||||
VALUES
|
|
||||||
-- Stock
|
|
||||||
('STOCK_PURCHASE', (SELECT id FROM permission_hierarchy WHERE name = 'STOCK')),
|
|
||||||
('STOCK_CONSUME', (SELECT id FROM permission_hierarchy WHERE name = 'STOCK')),
|
|
||||||
('STOCK_INVENTORY', (SELECT id FROM permission_hierarchy WHERE name = 'STOCK')),
|
|
||||||
('STOCK_TRANSFER', (SELECT id FROM permission_hierarchy WHERE name = 'STOCK')),
|
|
||||||
('STOCK_OPEN', (SELECT id FROM permission_hierarchy WHERE name = 'STOCK')),
|
|
||||||
('STOCK_EDIT', (SELECT id FROM permission_hierarchy WHERE name = 'STOCK')),
|
|
||||||
|
|
||||||
-- Shopping list
|
|
||||||
('SHOPPINGLIST_ITEMS_ADD', (SELECT id FROM permission_hierarchy WHERE name = 'SHOPPINGLIST')),
|
|
||||||
('SHOPPINGLIST_ITEMS_DELETE', (SELECT id FROM permission_hierarchy WHERE name = 'SHOPPINGLIST')),
|
|
||||||
|
|
||||||
-- Recipes
|
|
||||||
('RECIPES_MEALPLAN', (SELECT id FROM permission_hierarchy WHERE name = 'RECIPES')),
|
|
||||||
|
|
||||||
-- Chores
|
|
||||||
('CHORE_TRACK_EXECUTION', (SELECT id FROM permission_hierarchy WHERE name = 'CHORES')),
|
|
||||||
('CHORE_UNDO_EXECUTION', (SELECT id FROM permission_hierarchy WHERE name = 'CHORES')),
|
|
||||||
|
|
||||||
-- Batteries
|
|
||||||
('BATTERIES_TRACK_CHARGE_CYCLE', (SELECT id FROM permission_hierarchy WHERE name = 'BATTERIES')),
|
|
||||||
('BATTERIES_UNDO_CHARGE_CYCLE', (SELECT id FROM permission_hierarchy WHERE name = 'BATTERIES')),
|
|
||||||
|
|
||||||
-- Tasks
|
|
||||||
('TASKS_UNDO_EXECUTION', (SELECT id FROM permission_hierarchy WHERE name = 'TASKS')),
|
|
||||||
('TASKS_MARK_COMPLETED', (SELECT id FROM permission_hierarchy WHERE name = 'TASKS')),
|
|
||||||
|
|
||||||
-- Others
|
|
||||||
('MASTER_DATA_EDIT', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN'));
|
|
||||||
|
|
||||||
-- All existing users get the ADMIN permission
|
|
||||||
INSERT INTO user_permissions
|
|
||||||
(permission_id, user_id)
|
|
||||||
SELECT (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN'), id
|
|
||||||
FROM users;
|
|
||||||
|
|
||||||
CREATE VIEW permission_tree
|
|
||||||
AS
|
|
||||||
WITH RECURSIVE perm AS (
|
|
||||||
SELECT id AS root, id AS child, name, parent
|
|
||||||
FROM permission_hierarchy
|
|
||||||
UNION
|
|
||||||
SELECT perm.root, ph.id, ph.name, ph.id
|
|
||||||
FROM permission_hierarchy ph, perm
|
|
||||||
WHERE ph.parent = perm.child
|
|
||||||
)
|
|
||||||
SELECT root AS id, name AS name
|
|
||||||
FROM perm;
|
|
||||||
|
|
||||||
CREATE VIEW user_permissions_resolved
|
|
||||||
AS
|
|
||||||
SELECT
|
|
||||||
u.id AS id, -- Dummy for LessQL
|
|
||||||
u.id AS user_id,
|
|
||||||
pt.name AS permission_name
|
|
||||||
FROM permission_tree pt, users u
|
|
||||||
WHERE pt.id IN (SELECT permission_id FROM user_permissions sub_up WHERE sub_up.user_id = u.id);
|
|
||||||
|
|
||||||
CREATE VIEW uihelper_user_permissions
|
|
||||||
AS
|
|
||||||
SELECT
|
|
||||||
ph.id AS id,
|
|
||||||
u.id AS user_id,
|
|
||||||
ph.name AS permission_name,
|
|
||||||
ph.id AS permission_id,
|
|
||||||
(ph.name IN (
|
|
||||||
SELECT pc.permission_name
|
|
||||||
FROM user_permissions_resolved pc
|
|
||||||
WHERE pc.user_id = u.id
|
|
||||||
)
|
|
||||||
) AS has_permission,
|
|
||||||
ph.parent AS parent
|
|
||||||
FROM users u, permission_hierarchy ph;
|
|
||||||
|
@@ -1,16 +1,36 @@
|
|||||||
DELETE FROM userfield_values
|
DROP VIEW userfield_values_resolved;
|
||||||
WHERE IFNULL(value, '') = '';
|
CREATE VIEW userfield_values_resolved
|
||||||
|
AS
|
||||||
|
SELECT
|
||||||
|
u.id, -- Dummy, LessQL needs an id column
|
||||||
|
u.entity,
|
||||||
|
u.name,
|
||||||
|
u.caption,
|
||||||
|
u.type,
|
||||||
|
u.show_as_column_in_tables,
|
||||||
|
u.row_created_timestamp,
|
||||||
|
u.config,
|
||||||
|
uv.object_id,
|
||||||
|
uv.value
|
||||||
|
FROM userfields u
|
||||||
|
JOIN userfield_values uv
|
||||||
|
ON u.id = uv.field_id
|
||||||
|
|
||||||
CREATE TRIGGER prevent_empty_userfields_INS AFTER INSERT ON userfield_values
|
UNION
|
||||||
BEGIN
|
|
||||||
DELETE FROM userfield_values
|
|
||||||
WHERE id = NEW.id
|
|
||||||
AND IFNULL(value, '') = '';
|
|
||||||
END;
|
|
||||||
|
|
||||||
CREATE TRIGGER prevent_empty_userfields_UPD AFTER UPDATE ON userfield_values
|
-- Kind of a hack, include userentity userfields also for the table userobjects
|
||||||
BEGIN
|
SELECT
|
||||||
DELETE FROM userfield_values
|
u.id, -- Dummy, LessQL needs an id column,
|
||||||
WHERE id = NEW.id
|
'userobjects',
|
||||||
AND IFNULL(value, '') = '';
|
u.name,
|
||||||
END;
|
u.caption,
|
||||||
|
u.type,
|
||||||
|
u.show_as_column_in_tables,
|
||||||
|
u.row_created_timestamp,
|
||||||
|
u.config,
|
||||||
|
uv.object_id,
|
||||||
|
uv.value
|
||||||
|
FROM userfields u
|
||||||
|
JOIN userfield_values uv
|
||||||
|
ON u.id = uv.field_id
|
||||||
|
WHERE u.entity like 'userentity-%';
|
||||||
|
@@ -1,36 +1,92 @@
|
|||||||
DROP VIEW userfield_values_resolved;
|
CREATE VIEW users_dto
|
||||||
CREATE VIEW userfield_values_resolved
|
|
||||||
AS
|
AS
|
||||||
SELECT
|
SELECT
|
||||||
u.id, -- Dummy, LessQL needs an id column
|
id,
|
||||||
u.entity,
|
username,
|
||||||
u.name,
|
first_name,
|
||||||
u.caption,
|
last_name,
|
||||||
u.type,
|
row_created_timestamp,
|
||||||
u.show_as_column_in_tables,
|
(CASE
|
||||||
u.row_created_timestamp,
|
WHEN IFNULL(first_name, '') = '' AND IFNULL(last_name, '') != '' THEN last_name
|
||||||
u.config,
|
WHEN IFNULL(last_name, '') = '' AND IFNULL(first_name, '') != '' THEN first_name
|
||||||
uv.object_id,
|
WHEN IFNULL(last_name, '') != '' AND IFNULL(first_name, '') != '' THEN first_name || ' ' || last_name
|
||||||
uv.value
|
ELSE username
|
||||||
FROM userfields u
|
END
|
||||||
JOIN userfield_values uv
|
) AS display_name
|
||||||
ON u.id = uv.field_id
|
FROM users;
|
||||||
|
|
||||||
UNION
|
DROP VIEW chores_current;
|
||||||
|
CREATE VIEW chores_current
|
||||||
-- Kind of a hack, include userentity userfields also for the table userobjects
|
AS
|
||||||
SELECT
|
SELECT
|
||||||
u.id, -- Dummy, LessQL needs an id column,
|
x.chore_id AS id, -- Dummy, LessQL needs an id column
|
||||||
'userobjects',
|
x.chore_id,
|
||||||
u.name,
|
x.chore_name,
|
||||||
u.caption,
|
x.last_tracked_time,
|
||||||
u.type,
|
CASE WHEN x.rollover = 1 AND DATETIME('now', 'localtime') > x.next_estimated_execution_time THEN
|
||||||
u.show_as_column_in_tables,
|
DATETIME(STRFTIME('%Y-%m-%d', DATETIME('now', 'localtime')) || ' ' || STRFTIME('%H:%M:%S', x.next_estimated_execution_time))
|
||||||
u.row_created_timestamp,
|
ELSE
|
||||||
u.config,
|
x.next_estimated_execution_time
|
||||||
uv.object_id,
|
END AS next_estimated_execution_time,
|
||||||
uv.value
|
x.track_date_only,
|
||||||
FROM userfields u
|
x.next_execution_assigned_to_user_id
|
||||||
JOIN userfield_values uv
|
FROM (
|
||||||
ON u.id = uv.field_id
|
|
||||||
WHERE u.entity like 'userentity-%';
|
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), DATETIME('now', 'localtime')), '+' || 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), DATETIME('now', 'localtime')), '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), DATETIME('now', 'localtime')), '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), DATETIME('now', 'localtime')), '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), DATETIME('now', 'localtime')), '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), DATETIME('now', 'localtime')), '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), DATETIME('now', 'localtime')), '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), DATETIME('now', 'localtime')), '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
|
||||||
|
)
|
||||||
|
WHEN 'monthly' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '+' || CAST(h.period_interval AS TEXT) || ' month', 'start of month', '+' || CAST(h.period_days - 1 AS TEXT) || ' day')
|
||||||
|
WHEN 'yearly' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '+' || CAST(h.period_interval AS TEXT) || ' years')
|
||||||
|
END AS next_estimated_execution_time,
|
||||||
|
h.track_date_only,
|
||||||
|
h.rollover,
|
||||||
|
h.next_execution_assigned_to_user_id
|
||||||
|
FROM chores h
|
||||||
|
LEFT JOIN chores_log l
|
||||||
|
ON h.id = l.chore_id
|
||||||
|
AND l.undone = 0
|
||||||
|
GROUP BY h.id, h.name, h.period_days
|
||||||
|
|
||||||
|
) x;
|
||||||
|
|
||||||
|
DROP VIEW batteries_current;
|
||||||
|
CREATE VIEW batteries_current
|
||||||
|
AS
|
||||||
|
SELECT
|
||||||
|
b.id, -- Dummy, LessQL needs an id column
|
||||||
|
b.id AS battery_id,
|
||||||
|
MAX(l.tracked_time) AS last_tracked_time,
|
||||||
|
CASE WHEN b.charge_interval_days = 0
|
||||||
|
THEN '2999-12-31 23:59:59'
|
||||||
|
ELSE datetime(MAX(l.tracked_time), '+' || CAST(b.charge_interval_days AS TEXT) || ' day')
|
||||||
|
END AS next_estimated_charge_time
|
||||||
|
FROM batteries b
|
||||||
|
LEFT JOIN battery_charge_cycles l
|
||||||
|
ON b.id = l.battery_id
|
||||||
|
GROUP BY b.id, b.charge_interval_days;
|
||||||
|
@@ -1,92 +1,51 @@
|
|||||||
CREATE VIEW users_dto
|
ALTER TABLE stock_log
|
||||||
|
ADD user_id INTEGER NOT NULL DEFAULT 1;
|
||||||
|
|
||||||
|
CREATE VIEW uihelper_stock_journal
|
||||||
AS
|
AS
|
||||||
SELECT
|
SELECT
|
||||||
id,
|
sl.id,
|
||||||
username,
|
sl.row_created_timestamp,
|
||||||
first_name,
|
sl.correlation_id,
|
||||||
last_name,
|
sl.undone,
|
||||||
row_created_timestamp,
|
sl.undone_timestamp,
|
||||||
(CASE
|
sl.row_created_timestamp,
|
||||||
WHEN IFNULL(first_name, '') = '' AND IFNULL(last_name, '') != '' THEN last_name
|
sl.transaction_type,
|
||||||
WHEN IFNULL(last_name, '') = '' AND IFNULL(first_name, '') != '' THEN first_name
|
sl.spoiled,
|
||||||
WHEN IFNULL(last_name, '') != '' AND IFNULL(first_name, '') != '' THEN first_name || ' ' || last_name
|
sl.amount,
|
||||||
ELSE username
|
sl.location_id,
|
||||||
END
|
l.name AS location_name,
|
||||||
) AS display_name
|
p.name AS product_name,
|
||||||
FROM users;
|
qu.name AS qu_name,
|
||||||
|
qu.name_plural AS qu_name_plural,
|
||||||
|
u.display_name AS user_display_name
|
||||||
|
FROM stock_log sl
|
||||||
|
JOIN users_dto u
|
||||||
|
ON sl.user_id = u.id
|
||||||
|
JOIN products p
|
||||||
|
ON sl.product_id = p.id
|
||||||
|
JOIN locations l
|
||||||
|
ON p.location_id = l.id
|
||||||
|
JOIN quantity_units qu
|
||||||
|
ON p.qu_id_stock = qu.id;
|
||||||
|
|
||||||
DROP VIEW chores_current;
|
CREATE VIEW uihelper_stock_journal_summary
|
||||||
CREATE VIEW chores_current
|
|
||||||
AS
|
AS
|
||||||
SELECT
|
SELECT
|
||||||
x.chore_id AS id, -- Dummy, LessQL needs an id column
|
user_id AS id, -- Dummy, LessQL needs an id column
|
||||||
x.chore_id,
|
user_id, u.display_name AS user_display_name,
|
||||||
x.chore_name,
|
p.name AS product_name,
|
||||||
x.last_tracked_time,
|
product_id,
|
||||||
CASE WHEN x.rollover = 1 AND DATETIME('now', 'localtime') > x.next_estimated_execution_time THEN
|
transaction_type,
|
||||||
DATETIME(STRFTIME('%Y-%m-%d', DATETIME('now', 'localtime')) || ' ' || STRFTIME('%H:%M:%S', x.next_estimated_execution_time))
|
qu.name AS qu_name,
|
||||||
ELSE
|
qu.name_plural AS qu_name_plural,
|
||||||
x.next_estimated_execution_time
|
SUM(amount) AS amount
|
||||||
END AS next_estimated_execution_time,
|
FROM stock_log sl
|
||||||
x.track_date_only,
|
JOIN users_dto u
|
||||||
x.next_execution_assigned_to_user_id
|
on sl.user_id = u.id
|
||||||
FROM (
|
JOIN products p
|
||||||
|
ON sl.product_id = p.id
|
||||||
SELECT
|
JOIN quantity_units qu
|
||||||
h.id AS chore_id,
|
ON p.qu_id_stock = qu.id
|
||||||
h.name AS chore_name,
|
WHERE undone = 0
|
||||||
MAX(l.tracked_time) AS last_tracked_time,
|
GROUP BY user_id, product_id, transaction_type;
|
||||||
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), DATETIME('now', 'localtime')), '+' || 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), DATETIME('now', 'localtime')), '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), DATETIME('now', 'localtime')), '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), DATETIME('now', 'localtime')), '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), DATETIME('now', 'localtime')), '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), DATETIME('now', 'localtime')), '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), DATETIME('now', 'localtime')), '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), DATETIME('now', 'localtime')), '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
|
|
||||||
)
|
|
||||||
WHEN 'monthly' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '+' || CAST(h.period_interval AS TEXT) || ' month', 'start of month', '+' || CAST(h.period_days - 1 AS TEXT) || ' day')
|
|
||||||
WHEN 'yearly' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '+' || CAST(h.period_interval AS TEXT) || ' years')
|
|
||||||
END AS next_estimated_execution_time,
|
|
||||||
h.track_date_only,
|
|
||||||
h.rollover,
|
|
||||||
h.next_execution_assigned_to_user_id
|
|
||||||
FROM chores h
|
|
||||||
LEFT JOIN chores_log l
|
|
||||||
ON h.id = l.chore_id
|
|
||||||
AND l.undone = 0
|
|
||||||
GROUP BY h.id, h.name, h.period_days
|
|
||||||
|
|
||||||
) x;
|
|
||||||
|
|
||||||
DROP VIEW batteries_current;
|
|
||||||
CREATE VIEW batteries_current
|
|
||||||
AS
|
|
||||||
SELECT
|
|
||||||
b.id, -- Dummy, LessQL needs an id column
|
|
||||||
b.id AS battery_id,
|
|
||||||
MAX(l.tracked_time) AS last_tracked_time,
|
|
||||||
CASE WHEN b.charge_interval_days = 0
|
|
||||||
THEN '2999-12-31 23:59:59'
|
|
||||||
ELSE datetime(MAX(l.tracked_time), '+' || CAST(b.charge_interval_days AS TEXT) || ' day')
|
|
||||||
END AS next_estimated_charge_time
|
|
||||||
FROM batteries b
|
|
||||||
LEFT JOIN battery_charge_cycles l
|
|
||||||
ON b.id = l.battery_id
|
|
||||||
GROUP BY b.id, b.charge_interval_days;
|
|
||||||
|
@@ -1,51 +1 @@
|
|||||||
ALTER TABLE stock_log
|
update user_settings set key = "stock_expiring_soon_days" where key = "stock_expring_soon_days";
|
||||||
ADD user_id INTEGER NOT NULL DEFAULT 1;
|
|
||||||
|
|
||||||
CREATE VIEW uihelper_stock_journal
|
|
||||||
AS
|
|
||||||
SELECT
|
|
||||||
sl.id,
|
|
||||||
sl.row_created_timestamp,
|
|
||||||
sl.correlation_id,
|
|
||||||
sl.undone,
|
|
||||||
sl.undone_timestamp,
|
|
||||||
sl.row_created_timestamp,
|
|
||||||
sl.transaction_type,
|
|
||||||
sl.spoiled,
|
|
||||||
sl.amount,
|
|
||||||
sl.location_id,
|
|
||||||
l.name AS location_name,
|
|
||||||
p.name AS product_name,
|
|
||||||
qu.name AS qu_name,
|
|
||||||
qu.name_plural AS qu_name_plural,
|
|
||||||
u.display_name AS user_display_name
|
|
||||||
FROM stock_log sl
|
|
||||||
JOIN users_dto u
|
|
||||||
ON sl.user_id = u.id
|
|
||||||
JOIN products p
|
|
||||||
ON sl.product_id = p.id
|
|
||||||
JOIN locations l
|
|
||||||
ON p.location_id = l.id
|
|
||||||
JOIN quantity_units qu
|
|
||||||
ON p.qu_id_stock = qu.id;
|
|
||||||
|
|
||||||
CREATE VIEW uihelper_stock_journal_summary
|
|
||||||
AS
|
|
||||||
SELECT
|
|
||||||
user_id AS id, -- Dummy, LessQL needs an id column
|
|
||||||
user_id, u.display_name AS user_display_name,
|
|
||||||
p.name AS product_name,
|
|
||||||
product_id,
|
|
||||||
transaction_type,
|
|
||||||
qu.name AS qu_name,
|
|
||||||
qu.name_plural AS qu_name_plural,
|
|
||||||
SUM(amount) AS amount
|
|
||||||
FROM stock_log sl
|
|
||||||
JOIN users_dto u
|
|
||||||
on sl.user_id = u.id
|
|
||||||
JOIN products p
|
|
||||||
ON sl.product_id = p.id
|
|
||||||
JOIN quantity_units qu
|
|
||||||
ON p.qu_id_stock = qu.id
|
|
||||||
WHERE undone = 0
|
|
||||||
GROUP BY user_id, product_id, transaction_type;
|
|
||||||
|
@@ -1 +1,71 @@
|
|||||||
update user_settings set key = "stock_expiring_soon_days" where key = "stock_expring_soon_days";
|
DROP VIEW quantity_unit_conversions_resolved;
|
||||||
|
CREATE VIEW quantity_unit_conversions_resolved
|
||||||
|
AS
|
||||||
|
|
||||||
|
-- First: Product "purchase to stock" conversion factor
|
||||||
|
SELECT
|
||||||
|
p.id AS id, -- Dummy, LessQL needs an id column
|
||||||
|
p.id AS product_id,
|
||||||
|
p.qu_id_purchase AS from_qu_id,
|
||||||
|
qu_from.name AS from_qu_name,
|
||||||
|
p.qu_id_stock AS to_qu_id,
|
||||||
|
qu_to.name AS to_qu_name,
|
||||||
|
p.qu_factor_purchase_to_stock AS factor
|
||||||
|
FROM products p
|
||||||
|
JOIN quantity_units qu_from
|
||||||
|
ON p.qu_id_purchase = qu_from.id
|
||||||
|
JOIN quantity_units qu_to
|
||||||
|
ON p.qu_id_stock = qu_to.id
|
||||||
|
UNION -- Inversed
|
||||||
|
SELECT
|
||||||
|
p.id AS id, -- Dummy, LessQL needs an id column
|
||||||
|
p.id AS product_id,
|
||||||
|
p.qu_id_stock AS from_qu_id,
|
||||||
|
qu_to.name AS from_qu_name,
|
||||||
|
p.qu_id_purchase AS to_qu_id,
|
||||||
|
qu_from.name AS to_qu_name,
|
||||||
|
1 / p.qu_factor_purchase_to_stock AS factor
|
||||||
|
FROM products p
|
||||||
|
JOIN quantity_units qu_from
|
||||||
|
ON p.qu_id_purchase = qu_from.id
|
||||||
|
JOIN quantity_units qu_to
|
||||||
|
ON p.qu_id_stock = qu_to.id
|
||||||
|
|
||||||
|
UNION
|
||||||
|
|
||||||
|
-- Second: Product specific overrides
|
||||||
|
SELECT
|
||||||
|
p.id AS id, -- Dummy, LessQL needs an id column
|
||||||
|
p.id AS product_id,
|
||||||
|
quc.from_qu_id AS from_qu_id,
|
||||||
|
qu_from.name AS from_qu_name,
|
||||||
|
quc.to_qu_id AS to_qu_id,
|
||||||
|
qu_to.name AS to_qu_name,
|
||||||
|
quc.factor AS factor
|
||||||
|
FROM products p
|
||||||
|
JOIN quantity_unit_conversions quc
|
||||||
|
ON p.id = quc.product_id
|
||||||
|
JOIN quantity_units qu_from
|
||||||
|
ON quc.from_qu_id = qu_from.id
|
||||||
|
JOIN quantity_units qu_to
|
||||||
|
ON quc.to_qu_id = qu_to.id
|
||||||
|
|
||||||
|
UNION
|
||||||
|
|
||||||
|
-- Third: Default quantity unit conversion factors
|
||||||
|
SELECT
|
||||||
|
p.id AS id, -- Dummy, LessQL needs an id column
|
||||||
|
p.id AS product_id,
|
||||||
|
p.qu_id_stock AS from_qu_id,
|
||||||
|
qu_from.name AS from_qu_name,
|
||||||
|
quc.to_qu_id AS to_qu_id,
|
||||||
|
qu_to.name AS to_qu_name,
|
||||||
|
quc.factor AS factor
|
||||||
|
FROM products p
|
||||||
|
JOIN quantity_unit_conversions quc
|
||||||
|
ON p.qu_id_stock = quc.from_qu_id
|
||||||
|
AND quc.product_id IS NULL
|
||||||
|
JOIN quantity_units qu_from
|
||||||
|
ON quc.from_qu_id = qu_from.id
|
||||||
|
JOIN quantity_units qu_to
|
||||||
|
ON quc.to_qu_id = qu_to.id;
|
||||||
|
@@ -1,71 +0,0 @@
|
|||||||
DROP VIEW quantity_unit_conversions_resolved;
|
|
||||||
CREATE VIEW quantity_unit_conversions_resolved
|
|
||||||
AS
|
|
||||||
|
|
||||||
-- First: Product "purchase to stock" conversion factor
|
|
||||||
SELECT
|
|
||||||
p.id AS id, -- Dummy, LessQL needs an id column
|
|
||||||
p.id AS product_id,
|
|
||||||
p.qu_id_purchase AS from_qu_id,
|
|
||||||
qu_from.name AS from_qu_name,
|
|
||||||
p.qu_id_stock AS to_qu_id,
|
|
||||||
qu_to.name AS to_qu_name,
|
|
||||||
p.qu_factor_purchase_to_stock AS factor
|
|
||||||
FROM products p
|
|
||||||
JOIN quantity_units qu_from
|
|
||||||
ON p.qu_id_purchase = qu_from.id
|
|
||||||
JOIN quantity_units qu_to
|
|
||||||
ON p.qu_id_stock = qu_to.id
|
|
||||||
UNION -- Inversed
|
|
||||||
SELECT
|
|
||||||
p.id AS id, -- Dummy, LessQL needs an id column
|
|
||||||
p.id AS product_id,
|
|
||||||
p.qu_id_stock AS from_qu_id,
|
|
||||||
qu_to.name AS from_qu_name,
|
|
||||||
p.qu_id_purchase AS to_qu_id,
|
|
||||||
qu_from.name AS to_qu_name,
|
|
||||||
1 / p.qu_factor_purchase_to_stock AS factor
|
|
||||||
FROM products p
|
|
||||||
JOIN quantity_units qu_from
|
|
||||||
ON p.qu_id_purchase = qu_from.id
|
|
||||||
JOIN quantity_units qu_to
|
|
||||||
ON p.qu_id_stock = qu_to.id
|
|
||||||
|
|
||||||
UNION
|
|
||||||
|
|
||||||
-- Second: Product specific overrides
|
|
||||||
SELECT
|
|
||||||
p.id AS id, -- Dummy, LessQL needs an id column
|
|
||||||
p.id AS product_id,
|
|
||||||
quc.from_qu_id AS from_qu_id,
|
|
||||||
qu_from.name AS from_qu_name,
|
|
||||||
quc.to_qu_id AS to_qu_id,
|
|
||||||
qu_to.name AS to_qu_name,
|
|
||||||
quc.factor AS factor
|
|
||||||
FROM products p
|
|
||||||
JOIN quantity_unit_conversions quc
|
|
||||||
ON p.id = quc.product_id
|
|
||||||
JOIN quantity_units qu_from
|
|
||||||
ON quc.from_qu_id = qu_from.id
|
|
||||||
JOIN quantity_units qu_to
|
|
||||||
ON quc.to_qu_id = qu_to.id
|
|
||||||
|
|
||||||
UNION
|
|
||||||
|
|
||||||
-- Third: Default quantity unit conversion factors
|
|
||||||
SELECT
|
|
||||||
p.id AS id, -- Dummy, LessQL needs an id column
|
|
||||||
p.id AS product_id,
|
|
||||||
p.qu_id_stock AS from_qu_id,
|
|
||||||
qu_from.name AS from_qu_name,
|
|
||||||
quc.to_qu_id AS to_qu_id,
|
|
||||||
qu_to.name AS to_qu_name,
|
|
||||||
quc.factor AS factor
|
|
||||||
FROM products p
|
|
||||||
JOIN quantity_unit_conversions quc
|
|
||||||
ON p.qu_id_stock = quc.from_qu_id
|
|
||||||
AND quc.product_id IS NULL
|
|
||||||
JOIN quantity_units qu_from
|
|
||||||
ON quc.from_qu_id = qu_from.id
|
|
||||||
JOIN quantity_units qu_to
|
|
||||||
ON quc.to_qu_id = qu_to.id;
|
|
Reference in New Issue
Block a user