Make it possible to change a products stock QU after it was once added to stock (closes #1326)

This commit is contained in:
Bernd Bestel 2022-03-13 17:09:07 +01:00
parent 7532626123
commit 7ea9984fd3
No known key found for this signature in database
GPG Key ID: 71BD34C0D4891300
6 changed files with 61 additions and 31 deletions

View File

@ -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

View File

@ -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'),

View File

@ -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 ""

55
migrations/0175.sql Normal file
View File

@ -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;

View File

@ -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"));

View File

@ -331,20 +331,12 @@
<div class="form-group">
<label for="qu_id_stock">{{ $__t('Quantity unit stock') }}</label>
<i class="fas fa-question-circle text-muted"
data-toggle="tooltip"
data-trigger="hover click"
title="{{ $__t('Quantity unit stock cannot be changed after first purchase') }}"></i>
<select required
class="custom-control custom-select input-group-qu"
id="qu_id_stock"
name="qu_id_stock"
@if($mode=='edit'
)
disabled
@endif>
name="qu_id_stock">
<option></option>
@foreach($quantityunits as $quantityunit)
@foreach($quantityunitsStock as $quantityunit)
<option @if($mode=='edit'
&&
$quantityunit->id == $product->qu_id_stock) selected="selected" @endif value="{{ $quantityunit->id }}" data-plural-form="{{ $quantityunit->name_plural }}">{{ $quantityunit->name }}</option>