diff --git a/changelog/67_UNRELEASED_xxxx-xx-xx.md b/changelog/67_UNRELEASED_xxxx-xx-xx.md index cec3c101..0decbf03 100644 --- a/changelog/67_UNRELEASED_xxxx-xx-xx.md +++ b/changelog/67_UNRELEASED_xxxx-xx-xx.md @@ -8,7 +8,8 @@ ### Stock -- xxx +- It's now possible to change a products stock QU, even after it was once added to stock + - When the product was once added to stock, there needs to exist a corresponding unit conversion for the new QU ### Shopping list diff --git a/controllers/StockController.php b/controllers/StockController.php index 7de604fe..c1f9b901 100644 --- a/controllers/StockController.php +++ b/controllers/StockController.php @@ -160,6 +160,7 @@ class StockController extends BaseController 'locations' => $this->getDatabase()->locations()->orderBy('name'), 'barcodes' => $this->getDatabase()->product_barcodes()->orderBy('barcode'), 'quantityunits' => $this->getDatabase()->quantity_units()->orderBy('name', 'COLLATE NOCASE'), + 'quantityunitsStock' => $this->getDatabase()->quantity_units()->orderBy('name', 'COLLATE NOCASE'), 'shoppinglocations' => $this->getDatabase()->shopping_locations()->orderBy('name', 'COLLATE NOCASE'), 'productgroups' => $this->getDatabase()->product_groups()->orderBy('name', 'COLLATE NOCASE'), 'userfields' => $this->getUserfieldsService()->GetFields('products'), @@ -177,6 +178,7 @@ class StockController extends BaseController 'locations' => $this->getDatabase()->locations()->orderBy('name', 'COLLATE NOCASE'), 'barcodes' => $this->getDatabase()->product_barcodes()->orderBy('barcode'), 'quantityunits' => $this->getDatabase()->quantity_units()->orderBy('name', 'COLLATE NOCASE'), + 'quantityunitsStock' => $this->getDatabase()->quantity_units()->where('id IN (SELECT to_qu_id FROM quantity_unit_conversions_resolved WHERE product_id = :1) OR NOT EXISTS(SELECT 1 FROM stock_log WHERE product_id = :1)', $product->id)->orderBy('name', 'COLLATE NOCASE'), 'shoppinglocations' => $this->getDatabase()->shopping_locations()->orderBy('name', 'COLLATE NOCASE'), 'productgroups' => $this->getDatabase()->product_groups()->orderBy('name', 'COLLATE NOCASE'), 'userfields' => $this->getUserfieldsService()->GetFields('products'), diff --git a/localization/strings.pot b/localization/strings.pot index f90e7b8e..e1d4938d 100644 --- a/localization/strings.pot +++ b/localization/strings.pot @@ -1682,9 +1682,6 @@ msgstr "" msgid "Based on the prices of the default consume rule (Opened first, then first due first, then first in first out) for in-stock ingredients and on the last price for missing ones" msgstr "" -msgid "Quantity unit stock cannot be changed after first purchase" -msgstr "" - msgid "Clear filter" msgstr "" diff --git a/migrations/0175.sql b/migrations/0175.sql new file mode 100644 index 00000000..4e7486d7 --- /dev/null +++ b/migrations/0175.sql @@ -0,0 +1,55 @@ +DROP TRIGGER prevent_qu_stock_change_after_first_purchase; + +CREATE TRIGGER cascade_change_qu_id_stock AFTER UPDATE ON products WHEN NEW.qu_id_stock != OLD.qu_id_stock +BEGIN + -- All amounts anywhere are related to the products stock QU, + -- so apply the appropriate unit conversion to all amounts everywhere on change + -- (and enforce that such a conversion need to exist when the product was once added to stock) + + SELECT CASE WHEN(( + SELECT 1 + FROM quantity_unit_conversions_resolved + WHERE product_id = NEW.id + AND from_qu_id = OLD.qu_id_stock + AND to_qu_id = NEW.qu_id_stock + AND source NOT LIKE '1%' + ) ISNULL) + AND + (( + SELECT 1 + FROM stock_log + WHERE product_id = NEW.id + AND NEW.qu_id_stock != OLD.qu_id_stock + ) NOTNULL) THEN RAISE(ABORT, "qu_id_stock can only be changed when a corresponding QU conversion (old QU => new QU) exists when the product was once added to stock") END; + + UPDATE chores + SET product_amount = product_amount * IFNULL((SELECT factor FROM quantity_unit_conversions_resolved WHERE product_id = NEW.id AND from_qu_id = OLD.qu_id_stock AND to_qu_id = NEW.qu_id_stock AND source NOT LIKE '1%'), 1.0) + WHERE product_id = NEW.id; + + UPDATE meal_plan + SET product_amount = product_amount * IFNULL((SELECT factor FROM quantity_unit_conversions_resolved WHERE product_id = NEW.id AND from_qu_id = OLD.qu_id_stock AND to_qu_id = NEW.qu_id_stock AND source NOT LIKE '1%'), 1.0) + WHERE type = 'product' + AND product_id = NEW.id; + + UPDATE product_barcodes + SET amount = amount * IFNULL((SELECT factor FROM quantity_unit_conversions_resolved WHERE product_id = NEW.id AND from_qu_id = OLD.qu_id_stock AND to_qu_id = NEW.qu_id_stock AND source NOT LIKE '1%'), 1.0) + WHERE product_id = NEW.id + AND amount IS NOT NULL; + + UPDATE recipes_pos + SET amount = amount * IFNULL((SELECT factor FROM quantity_unit_conversions_resolved WHERE product_id = NEW.id AND from_qu_id = OLD.qu_id_stock AND to_qu_id = NEW.qu_id_stock AND source NOT LIKE '1%'), 1.0) + WHERE product_id = NEW.id; + + UPDATE shopping_list + SET amount = amount * IFNULL((SELECT factor FROM quantity_unit_conversions_resolved WHERE product_id = NEW.id AND from_qu_id = OLD.qu_id_stock AND to_qu_id = NEW.qu_id_stock AND source NOT LIKE '1%'), 1.0) + WHERE product_id = NEW.id + AND product_id IS NOT NULL; + + UPDATE stock + SET amount = amount * IFNULL((SELECT factor FROM quantity_unit_conversions_resolved WHERE product_id = NEW.id AND from_qu_id = OLD.qu_id_stock AND to_qu_id = NEW.qu_id_stock AND source NOT LIKE '1%'), 1.0) + WHERE product_id = NEW.id; + + UPDATE stock_log + SET amount = amount * IFNULL((SELECT factor FROM quantity_unit_conversions_resolved WHERE product_id = NEW.id AND from_qu_id = OLD.qu_id_stock AND to_qu_id = NEW.qu_id_stock AND source NOT LIKE '1%'), 1.0) + WHERE product_id = NEW.id; +END; diff --git a/public/viewjs/productform.js b/public/viewjs/productform.js index 17a70688..cf77917e 100644 --- a/public/viewjs/productform.js +++ b/public/viewjs/productform.js @@ -140,23 +140,6 @@ $('.save-product-button').on('click', function(e) ); }); -if (Grocy.EditMode == "edit") -{ - Grocy.Api.Get('objects/stock_log?limit=1&query[]=product_id=' + Grocy.EditObjectId, - function(productJournalEntries) - { - if (productJournalEntries.length == 0) - { - $('#qu_id_stock').removeAttr("disabled"); - } - }, - function(xhr) - { - console.error(xhr); - } - ); -} - if (GetUriParam("flow") == "InplaceNewProductWithName") { $('#name').val(GetUriParam("name")); diff --git a/views/productform.blade.php b/views/productform.blade.php index a86662b8..27f5e3c3 100644 --- a/views/productform.blade.php +++ b/views/productform.blade.php @@ -331,20 +331,12 @@