remove column product barcode and use product_barcodes

This commit is contained in:
Kurt Riddlesperger 2020-04-30 16:53:01 -05:00
parent e5c0c85ab8
commit 502622da69
14 changed files with 87 additions and 93 deletions

View File

@ -50,8 +50,12 @@ class StockController extends BaseController
public function Purchase(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args) public function Purchase(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
{ {
$sql = 'select group_concat(barcode) barcodes, product_id from product_barcodes group by product_id';
$productBarcodes = $this->getDatabaseService()->ExecuteDbQuery($sql)->fetchAll(\PDO::FETCH_OBJ);
return $this->renderPage($response, 'purchase', [ return $this->renderPage($response, 'purchase', [
'products' => $this->getDatabase()->products()->orderBy('name'), 'products' => $this->getDatabase()->products()->orderBy('name'),
'barcodes' => $productBarcodes,
'shoppinglocations' => $this->getDatabase()->shopping_locations()->orderBy('name'), 'shoppinglocations' => $this->getDatabase()->shopping_locations()->orderBy('name'),
'locations' => $this->getDatabase()->locations()->orderBy('name') 'locations' => $this->getDatabase()->locations()->orderBy('name')
]); ]);
@ -59,8 +63,12 @@ class StockController extends BaseController
public function Consume(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args) public function Consume(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
{ {
$sql = 'select group_concat(barcode) barcodes, product_id from product_barcodes group by product_id';
$productBarcodes = $this->getDatabaseService()->ExecuteDbQuery($sql)->fetchAll(\PDO::FETCH_OBJ);
return $this->renderPage($response, 'consume', [ return $this->renderPage($response, 'consume', [
'products' => $this->getDatabase()->products()->orderBy('name'), 'products' => $this->getDatabase()->products()->orderBy('name'),
'barcodes' => $productBarcodes,
'recipes' => $this->getDatabase()->recipes()->orderBy('name'), 'recipes' => $this->getDatabase()->recipes()->orderBy('name'),
'locations' => $this->getDatabase()->locations()->orderBy('name') 'locations' => $this->getDatabase()->locations()->orderBy('name')
]); ]);
@ -68,8 +76,12 @@ class StockController extends BaseController
public function Transfer(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args) public function Transfer(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
{ {
$sql = 'select group_concat(barcode) barcodes, product_id from product_barcodes group by product_id';
$productBarcodes = $this->getDatabaseService()->ExecuteDbQuery($sql)->fetchAll(\PDO::FETCH_OBJ);
return $this->renderPage($response, 'transfer', [ return $this->renderPage($response, 'transfer', [
'products' => $this->getDatabase()->products()->orderBy('name'), 'products' => $this->getDatabase()->products()->orderBy('name'),
'barcodes' => $productBarcodes,
'recipes' => $this->getDatabase()->recipes()->orderBy('name'), 'recipes' => $this->getDatabase()->recipes()->orderBy('name'),
'locations' => $this->getDatabase()->locations()->orderBy('name') 'locations' => $this->getDatabase()->locations()->orderBy('name')
]); ]);
@ -77,8 +89,12 @@ class StockController extends BaseController
public function Inventory(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args) public function Inventory(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
{ {
$sql = 'select group_concat(barcode) barcodes, product_id from product_barcodes group by product_id';
$productBarcodes = $this->getDatabaseService()->ExecuteDbQuery($sql)->fetchAll(\PDO::FETCH_OBJ);
return $this->renderPage($response, 'inventory', [ return $this->renderPage($response, 'inventory', [
'products' => $this->getDatabase()->products()->orderBy('name'), 'products' => $this->getDatabase()->products()->orderBy('name'),
'barcodes' => $productBarcodes,
'shoppinglocations' => $this->getDatabase()->shopping_locations()->orderBy('name'), 'shoppinglocations' => $this->getDatabase()->shopping_locations()->orderBy('name'),
'locations' => $this->getDatabase()->locations()->orderBy('name') 'locations' => $this->getDatabase()->locations()->orderBy('name')
]); ]);

View File

@ -3451,6 +3451,7 @@
"type": "string", "type": "string",
"enum": [ "enum": [
"products", "products",
"product_barcodes",
"chores", "chores",
"batteries", "batteries",
"locations", "locations",
@ -3800,6 +3801,9 @@
"product": { "product": {
"$ref": "#/components/schemas/Product" "$ref": "#/components/schemas/Product"
}, },
"product_barcodes": {
"$ref": "#/components/schemas/ProductBarcodeDetailsResponse"
},
"quantity_unit_purchase": { "quantity_unit_purchase": {
"$ref": "#/components/schemas/QuantityUnit" "$ref": "#/components/schemas/QuantityUnit"
}, },
@ -3873,6 +3877,15 @@
"not_check_stock_fulfillment_for_recipes": "0", "not_check_stock_fulfillment_for_recipes": "0",
"last_shopping_location_id": null "last_shopping_location_id": null
}, },
"product_barcodes": [
{
"id": "1",
"product_id": "13",
"barcode": "01321230213",
"qu_factor_purchase_to_stock": "10.0",
"shopping_location_id": "2"
}
],
"last_purchased": null, "last_purchased": null,
"last_used": null, "last_used": null,
"stock_amount": "2", "stock_amount": "2",

View File

@ -25,6 +25,43 @@ qu_factor_purchase_to_stock REAL NOT NULL DEFAULT 1,
shopping_location_id INTEGER shopping_location_id INTEGER
); );
ALTER TABLE products RENAME TO products_old;
--Remove barcode column
--Reorder columns
CREATE TABLE products (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
name TEXT NOT NULL UNIQUE,
description TEXT,
product_group_id INTEGER,
location_id INTEGER NOT NULL,
shopping_location_id INTEGER,
qu_id_purchase INTEGER NOT NULL,
qu_id_stock INTEGER NOT NULL,
qu_factor_purchase_to_stock REAL NOT NULL,
min_stock_amount INTEGER NOT NULL DEFAULT 0,
default_best_before_days INTEGER NOT NULL DEFAULT 0,
default_best_before_days_after_open INTEGER NOT NULL DEFAULT 0,
default_best_before_days_after_freezing INTEGER NOT NULL DEFAULT 0,
default_best_before_days_after_thawing INTEGER NOT NULL DEFAULT 0,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime')),
picture_file_name TEXT,
allow_partial_units_in_stock TINYINT NOT NULL DEFAULT 0,
enable_tare_weight_handling TINYINT NOT NULL DEFAULT 0,
tare_weight REAL NOT NULL DEFAULT 0,
not_check_stock_fulfillment_for_recipes TINYINT DEFAULT 0,
parent_product_id INT,
calories INTEGER,
cumulate_min_stock_amount_of_sub_products TINYINT DEFAULT 0);
INSERT INTO products
(id,name,description,location_id,qu_id_purchase,qu_id_stock,qu_factor_purchase_to_stock,min_stock_amount,default_best_before_days,row_created_timestamp,product_group_id,picture_file_name,default_best_before_days_after_open,allow_partial_units_in_stock,enable_tare_weight_handling,tare_weight,not_check_stock_fulfillment_for_recipes,parent_product_id,calories,cumulate_min_stock_amount_of_sub_products,default_best_before_days_after_freezing,default_best_before_days_after_thawing,shopping_location_id)
SELECT id,name,description,location_id,qu_id_purchase,qu_id_stock,qu_factor_purchase_to_stock,min_stock_amount,default_best_before_days,row_created_timestamp,product_group_id,picture_file_name,default_best_before_days_after_open,allow_partial_units_in_stock,enable_tare_weight_handling,tare_weight,not_check_stock_fulfillment_for_recipes,parent_product_id,calories,cumulate_min_stock_amount_of_sub_products,default_best_before_days_after_freezing,default_best_before_days_after_thawing,shopping_location_id
FROM products_old;
DROP TABLE products_old;
DROP VIEW stock_current_location_content; DROP VIEW stock_current_location_content;
CREATE VIEW stock_current_location_content CREATE VIEW stock_current_location_content
AS AS

View File

@ -44,27 +44,6 @@
var addBarcode = GetUriParam('addbarcodetoselection'); var addBarcode = GetUriParam('addbarcodetoselection');
if (addBarcode !== undefined) if (addBarcode !== undefined)
{ {
var existingBarcodes = productDetails.product.barcode || '';
if (existingBarcodes.length === 0)
{
productDetails.product.barcode = addBarcode;
}
else
{
productDetails.product.barcode += ',' + addBarcode;
}
Grocy.Api.Put('objects/products/' + productDetails.product.id, productDetails.product,
function(result)
{
$("#flow-info-addbarcodetoselection").addClass("d-none");
$('#barcode-lookup-disabled-hint').addClass('d-none');
},
function(xhr)
{
console.error(xhr);
}
);
var jsonDataBarcode = {}; var jsonDataBarcode = {};
jsonDataBarcode.barcode = addBarcode; jsonDataBarcode.barcode = addBarcode;
jsonDataBarcode.product_id = jsonForm.product_id; jsonDataBarcode.product_id = jsonForm.product_id;
@ -73,11 +52,13 @@
Grocy.Api.Post('objects/product_barcodes', jsonDataBarcode, Grocy.Api.Post('objects/product_barcodes', jsonDataBarcode,
function(result) function(result)
{ {
$("#flow-info-addbarcodetoselection").addClass("d-none");
$('#barcode-lookup-disabled-hint').addClass('d-none');
window.history.replaceState({ }, document.title, U("/consume")); window.history.replaceState({ }, document.title, U("/consume"));
}, },
function(xhr) function(xhr)
{ {
Grocy.FrontendHelpers.EndUiBusy("barcode-form"); Grocy.FrontendHelpers.EndUiBusy("consume-form");
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response); Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response);
} }
); );

View File

@ -37,27 +37,6 @@
var addBarcode = GetUriParam('addbarcodetoselection'); var addBarcode = GetUriParam('addbarcodetoselection');
if (addBarcode !== undefined) if (addBarcode !== undefined)
{ {
var existingBarcodes = productDetails.product.barcode || '';
if (existingBarcodes.length === 0)
{
productDetails.product.barcode = addBarcode;
}
else
{
productDetails.product.barcode += ',' + addBarcode;
}
Grocy.Api.Put('objects/products/' + productDetails.product.id, productDetails.product,
function(result)
{
$("#flow-info-addbarcodetoselection").addClass("d-none");
$('#barcode-lookup-disabled-hint').addClass('d-none');
},
function(xhr)
{
console.error(xhr);
}
);
var jsonDataBarcode = {}; var jsonDataBarcode = {};
jsonDataBarcode.barcode = addBarcode; jsonDataBarcode.barcode = addBarcode;
jsonDataBarcode.product_id = jsonForm.product_id; jsonDataBarcode.product_id = jsonForm.product_id;
@ -67,11 +46,13 @@
Grocy.Api.Post('objects/product_barcodes', jsonDataBarcode, Grocy.Api.Post('objects/product_barcodes', jsonDataBarcode,
function(result) function(result)
{ {
$("#flow-info-addbarcodetoselection").addClass("d-none");
$('#barcode-lookup-disabled-hint').addClass('d-none');
window.history.replaceState({ }, document.title, U("/inventory")); window.history.replaceState({ }, document.title, U("/inventory"));
}, },
function(xhr) function(xhr)
{ {
Grocy.FrontendHelpers.EndUiBusy("barcode-form"); Grocy.FrontendHelpers.EndUiBusy("inventory-form");
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response); Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response);
} }
); );

View File

@ -51,29 +51,6 @@
var addBarcode = GetUriParam('addbarcodetoselection'); var addBarcode = GetUriParam('addbarcodetoselection');
if (addBarcode !== undefined) if (addBarcode !== undefined)
{ {
var existingBarcodes = productDetails.product.barcode || '';
if (existingBarcodes.length === 0)
{
productDetails.product.barcode = addBarcode;
}
else
{
productDetails.product.barcode += ',' + addBarcode;
}
Grocy.Api.Put('objects/products/' + productDetails.product.id, productDetails.product,
function(result)
{
$("#flow-info-addbarcodetoselection").addClass("d-none");
$('#barcode-lookup-disabled-hint').addClass('d-none');
},
function(xhr)
{
Grocy.FrontendHelpers.EndUiBusy("purchase-form");
console.error(xhr);
}
);
var jsonDataBarcode = {}; var jsonDataBarcode = {};
jsonDataBarcode.barcode = addBarcode; jsonDataBarcode.barcode = addBarcode;
jsonDataBarcode.product_id = jsonForm.product_id; jsonDataBarcode.product_id = jsonForm.product_id;
@ -83,11 +60,13 @@
Grocy.Api.Post('objects/product_barcodes', jsonDataBarcode, Grocy.Api.Post('objects/product_barcodes', jsonDataBarcode,
function(result) function(result)
{ {
$("#flow-info-addbarcodetoselection").addClass("d-none");
$('#barcode-lookup-disabled-hint').addClass('d-none');
window.history.replaceState({ }, document.title, U("/purchase")); window.history.replaceState({ }, document.title, U("/purchase"));
}, },
function(xhr) function(xhr)
{ {
Grocy.FrontendHelpers.EndUiBusy("barcode-form"); Grocy.FrontendHelpers.EndUiBusy("purchase-form");
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response); Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response);
} }
); );

View File

@ -30,27 +30,6 @@
if (addBarcode !== undefined) if (addBarcode !== undefined)
{ {
var existingBarcodes = productDetails.product.barcode || '';
if (existingBarcodes.length === 0)
{
productDetails.product.barcode = addBarcode;
}
else
{
productDetails.product.barcode += ',' + addBarcode;
}
Grocy.Api.Put('objects/products/' + productDetails.product.id, productDetails.product,
function(result)
{
$("#flow-info-addbarcodetoselection").addClass("d-none");
$('#barcode-lookup-disabled-hint').addClass('d-none');
},
function(xhr)
{
console.error(xhr);
}
);
var jsonDataBarcode = {}; var jsonDataBarcode = {};
jsonDataBarcode.barcode = addBarcode; jsonDataBarcode.barcode = addBarcode;
jsonDataBarcode.product_id = jsonForm.product_id; jsonDataBarcode.product_id = jsonForm.product_id;
@ -59,11 +38,13 @@
Grocy.Api.Post('objects/product_barcodes', jsonDataBarcode, Grocy.Api.Post('objects/product_barcodes', jsonDataBarcode,
function(result) function(result)
{ {
$("#flow-info-addbarcodetoselection").addClass("d-none");
$('#barcode-lookup-disabled-hint').addClass('d-none');
window.history.replaceState({ }, document.title, U("/transfer")); window.history.replaceState({ }, document.title, U("/transfer"));
}, },
function(xhr) function(xhr)
{ {
Grocy.FrontendHelpers.EndUiBusy("barcode-form"); Grocy.FrontendHelpers.EndUiBusy("transfer-form");
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response); Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response);
} }
); );

View File

@ -96,7 +96,7 @@ class DemoDataGeneratorService extends BaseService
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, product_group_id, calories) VALUES ('{$this->__t_sql('Milk')}', 2, 10, 10, 1, 6, 1); --23 INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, product_group_id, calories) VALUES ('{$this->__t_sql('Milk')}', 2, 10, 10, 1, 6, 1); --23
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, product_group_id, parent_product_id) VALUES ('{$this->__t_sql('Milk Chocolate')}', 4, 3, 3, 1, 1, 2); --24 INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, product_group_id, parent_product_id) VALUES ('{$this->__t_sql('Milk Chocolate')}', 4, 3, 3, 1, 1, 2); --24
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, product_group_id, parent_product_id) VALUES ('{$this->__t_sql('Dark Chocolate')}', 4, 3, 3, 1, 1, 2); --25 INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, product_group_id, parent_product_id) VALUES ('{$this->__t_sql('Dark Chocolate')}', 4, 3, 3, 1, 1, 2); --25
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, product_group_id, barcode) VALUES ('{$this->__t_sql('Waffle rolls')}', 4, 3, 3, 1, 1, '22111289'); --26 INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, product_group_id) VALUES ('{$this->__t_sql('Waffle rolls')}', 4, 3, 3, 1, 1); --26
UPDATE products SET calories = 123 WHERE IFNULL(calories, 0) = 0; UPDATE products SET calories = 123 WHERE IFNULL(calories, 0) = 0;
/* Prevent invalid quantity unit assignments */ /* Prevent invalid quantity unit assignments */

View File

@ -69,7 +69,7 @@ class StockService extends BaseService
public function GetProductIdFromBarcode(string $barcode) public function GetProductIdFromBarcode(string $barcode)
{ {
$potentialProduct = $this->getDatabase()->products()->where("',' || barcode || ',' LIKE '%,' || :1 || ',%' AND IFNULL(barcode, '') != ''", $barcode)->limit(1)->fetch(); $potentialProduct = $this->getDatabase()->product_barcodes()->where("barcode = :1", $barcode)->fetch();
if ($potentialProduct === null) if ($potentialProduct === null)
{ {
@ -114,6 +114,7 @@ class StockService extends BaseService
} }
$product = $this->getDatabase()->products($productId); $product = $this->getDatabase()->products($productId);
$productBarcodes = $this->getDatabase()->product_barcodes()->where('product_id', $productId)->fetchAll();
$productLastPurchased = $this->getDatabase()->products_last_purchased()->where('product_id', $productId)->fetch(); $productLastPurchased = $this->getDatabase()->products_last_purchased()->where('product_id', $productId)->fetch();
$productLastUsed = $this->getDatabase()->stock_log()->where('product_id', $productId)->where('transaction_type', self::TRANSACTION_TYPE_CONSUME)->where('undone', 0)->max('used_date'); $productLastUsed = $this->getDatabase()->stock_log()->where('product_id', $productId)->where('transaction_type', self::TRANSACTION_TYPE_CONSUME)->where('undone', 0)->max('used_date');
$nextBestBeforeDate = $this->getDatabase()->stock()->where('product_id', $productId)->min('best_before_date'); $nextBestBeforeDate = $this->getDatabase()->stock()->where('product_id', $productId)->min('best_before_date');
@ -138,6 +139,7 @@ class StockService extends BaseService
return array( return array(
'product' => $product, 'product' => $product,
'product_barcodes' => $productBarcodes,
'last_purchased' => $productLastPurchased->purchased_date, 'last_purchased' => $productLastPurchased->purchased_date,
'last_used' => $productLastUsed, 'last_used' => $productLastUsed,
'stock_amount' => $stockCurrentRow->amount, 'stock_amount' => $stockCurrentRow->amount,

View File

@ -21,7 +21,7 @@
<select class="form-control product-combobox barcodescanner-input" id="product_id" name="product_id" @if($isRequired) required @endif @if($disabled) disabled @endif data-target="@productpicker"> <select class="form-control product-combobox barcodescanner-input" id="product_id" name="product_id" @if($isRequired) required @endif @if($disabled) disabled @endif data-target="@productpicker">
<option value=""></option> <option value=""></option>
@foreach($products as $product) @foreach($products as $product)
<option data-additional-searchdata="{{ $product->barcode }}@if(!empty($product->barcode)),@endif" value="{{ $product->id }}">{{ $product->name }}</option> <option data-additional-searchdata="{{ FindObjectInArrayByPropertyValue($barcodes, 'product_id', $product->id)->barcodes }}," value="{{ $product->id }}">{{ $product->name }}</option>
@endforeach @endforeach
</select> </select>
<div class="invalid-feedback">{{ $__t('You have to select a product') }}</div> <div class="invalid-feedback">{{ $__t('You have to select a product') }}</div>

View File

@ -30,6 +30,7 @@
@include('components.productpicker', array( @include('components.productpicker', array(
'products' => $products, 'products' => $products,
'barcodes' => $barcodes,
'nextInputSelector' => '#amount', 'nextInputSelector' => '#amount',
'disallowAddProductWorkflows' => true 'disallowAddProductWorkflows' => true
)) ))

View File

@ -13,6 +13,7 @@
@include('components.productpicker', array( @include('components.productpicker', array(
'products' => $products, 'products' => $products,
'barcodes' => $barcodes,
'nextInputSelector' => '#new_amount' 'nextInputSelector' => '#new_amount'
)) ))

View File

@ -30,6 +30,7 @@
@include('components.productpicker', array( @include('components.productpicker', array(
'products' => $products, 'products' => $products,
'barcodes' => $barcodes,
'nextInputSelector' => '#amount' 'nextInputSelector' => '#amount'
)) ))

View File

@ -14,6 +14,7 @@
@include('components.productpicker', array( @include('components.productpicker', array(
'products' => $products, 'products' => $products,
'barcodes' => $barcodes,
'nextInputSelector' => '#location_id_from', 'nextInputSelector' => '#location_id_from',
'disallowAddProductWorkflows' => true 'disallowAddProductWorkflows' => true
)) ))