This commit is contained in:
Bernd Bestel 2020-08-17 21:44:28 +02:00
parent 56ab8add27
commit 8d361992d8
No known key found for this signature in database
GPG Key ID: 71BD34C0D4891300
7 changed files with 169 additions and 92 deletions

View File

@ -1810,3 +1810,33 @@ msgstr ""
msgid "Save & return to recipes"
msgstr ""
msgid "Stock value"
msgstr ""
msgid "Average price"
msgstr ""
msgid "Active"
msgstr ""
msgid "Barcodes"
msgstr ""
msgid "Barcode"
msgstr ""
msgid "Create Barcode"
msgstr ""
msgid "Barcode for product"
msgstr ""
msgid "Edit Barcode"
msgstr ""
msgid "Not enough in stock (not included in costs), %s ingredient missing"
msgstr ""
msgid "Based on the prices of the default consume rule which is \"First expiring first, then first in first out\""
msgstr ""

View File

@ -5,44 +5,53 @@ ALTER TABLE stock
ADD qu_factor_purchase_to_stock REAL NOT NULL DEFAULT 1.0;
UPDATE stock
SET qu_factor_purchase_to_stock = (select qu_factor_purchase_to_stock from products where product_id = id);
SET qu_factor_purchase_to_stock = (SELECT qu_factor_purchase_to_stock FROM products WHERE product_id = id);
UPDATE stock_log
SET qu_factor_purchase_to_stock = (select qu_factor_purchase_to_stock from products where product_id = id);
SET qu_factor_purchase_to_stock = (SELECT qu_factor_purchase_to_stock FROM products WHERE product_id = id);
--Price is now going forward to be saved as 1 QU Stock
update stock
SET price = ROUND(price / qu_factor_purchase_to_stock,2);
UPDATE stock
SET price = ROUND(price / qu_factor_purchase_to_stock, 2);
update stock_log
SET price = ROUND(price / qu_factor_purchase_to_stock,2);
UPDATE stock_log
SET price = ROUND(price / qu_factor_purchase_to_stock, 2);
CREATE TABLE product_barcodes (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
product_id INT NOT NULL,
barcode TEXT NOT NULL UNIQUE,
qu_factor_purchase_to_stock REAL NOT NULL DEFAULT 1,
shopping_location_id INTEGER
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
product_id INT NOT NULL,
barcode TEXT NOT NULL UNIQUE,
qu_factor_purchase_to_stock REAL NOT NULL DEFAULT 1,
shopping_location_id INTEGER,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
);
--Convert product table to new barcode table
INSERT INTO product_barcodes (product_id, barcode, qu_factor_purchase_to_stock, shopping_location_id)
WITH split(id, barcode, str, qu_factor_purchase_to_stock, shopping_location_id) AS (
select id as product_id, '', barcode||',' ,qu_factor_purchase_to_stock, shopping_location_id from products
UNION ALL SELECT
id as product_id,
substr(str, 0, instr(str, ',')),
substr(str, instr(str, ',')+1),
qu_factor_purchase_to_stock,
shopping_location_id
FROM split WHERE str!=''
) SELECT id as product_id, barcode, qu_factor_purchase_to_stock, shopping_location_id FROM split WHERE barcode!='';
-- Convert product table to new product_barcodes table
INSERT INTO product_barcodes
(product_id, barcode, qu_factor_purchase_to_stock, shopping_location_id)
WITH barcodes_splitted(id, barcode, str, qu_factor_purchase_to_stock, shopping_location_id) AS (
SELECT id as product_id, '', barcode || ',', qu_factor_purchase_to_stock, shopping_location_id
FROM products
UNION ALL
SELECT
id as product_id,
SUBSTR(str, 0, instr(str, ',')),
SUBSTR(str, instr(str, ',') + 1),
qu_factor_purchase_to_stock,
shopping_location_id
FROM barcodes_splitted
WHERE str != ''
)
SELECT id as product_id, barcode, qu_factor_purchase_to_stock, shopping_location_id
FROM barcodes_splitted
WHERE barcode != '';
PRAGMA legacy_alter_table = ON;
ALTER TABLE products RENAME TO products_old;
--Remove barcode column
--Reorder columns
-- Remove barcode column
-- Reorder columns
CREATE TABLE products (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
name TEXT NOT NULL UNIQUE,
@ -59,7 +68,6 @@ CREATE TABLE products (
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,
@ -67,11 +75,13 @@ CREATE TABLE products (
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);
cumulate_min_stock_amount_of_sub_products TINYINT DEFAULT 0,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
);
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
(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;
@ -84,12 +94,13 @@ SELECT
s.product_id,
SUM(s.amount) AS amount,
ROUND(SUM(s.amount / s.qu_factor_purchase_to_stock),2) as factor_purchase_amount,
ROUND(SUM(IFNULL(s.price, 0) * s.amount),2) AS value,
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 location_id = s.location_id AND open = 1), 0) AS amount_opened
FROM stock s
JOIN products p
ON s.product_id = p.id and p.active = 1
ON s.product_id = p.id
AND p.active = 1
GROUP BY IFNULL(s.location_id, p.location_id), s.product_id;
DROP VIEW stock_current;
@ -98,9 +109,9 @@ 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,
IFNULL(ROUND((SELECT SUM(amount / qu_factor_purchase_to_stock) FROM stock WHERE product_id = pr.parent_product_id),2), 0) as factor_purchase_amount,
IFNULL(ROUND((SELECT SUM(amount / qu_factor_purchase_to_stock) FROM stock WHERE product_id = pr.parent_product_id), 2), 0) as factor_purchase_amount,
SUM(s.amount) * IFNULL(qucr.factor, 1) AS amount_aggregated,
IFNULL(ROUND((SELECT SUM(IFNULL(price,0) * amount) FROM stock WHERE product_id = pr.parent_product_id),2), 0) AS value,
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,
@ -109,9 +120,11 @@ 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
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
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
@ -125,9 +138,9 @@ UNION
SELECT
pr.sub_product_id AS product_id,
SUM(s.amount) AS amount,
ROUND(SUM(s.amount / s.qu_factor_purchase_to_stock),2) as factor_purchase_amount,
SUM(s.amount) AS amount_aggregated,
ROUND(SUM(IFNULL(s.price, 0) * s.amount),2) AS value,
ROUND(SUM(s.amount / s.qu_factor_purchase_to_stock), 2) as factor_purchase_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,
@ -146,7 +159,7 @@ SELECT
p.id as sub_product_id
FROM products p
WHERE p.parent_product_id IS NOT NULL
and p.active = 1
AND p.active = 1
UNION

View File

@ -1,54 +1,88 @@
--Deprecate unused view to instead use products_last_purchased
-- Deprecate unused view to instead use products_last_purchased
DROP VIEW products_current_price;
CREATE VIEW products_last_purchased AS
CREATE VIEW products_last_purchased
AS
select
1 AS id, -- Dummy, LessQL needs an id column
sw.product_id, sw.amount, sw.best_before_date, sw.purchased_date, sw.price, sw.qu_factor_purchase_to_stock, sw.location_id, sw.shopping_location_id
from stock_log sw join
(select
s1.product_id,
max(s1.id) max_stock_id
from stock_log s1
join (
select s.product_id,
max(s.purchased_date) max_purchased_date
from stock_log s
where undone = 0
and transaction_type in ('purchase', 'stock-edit-new', 'inventory-correction')
group by s.product_id) sp2 on s1.product_id = sp2.product_id and s1.purchased_date = sp2.max_purchased_date
where undone = 0
and transaction_type in ('purchase', 'stock-edit-new', 'inventory-correction')
group by s1.product_id) sp3 on sw.product_id = sp3.product_id and sw.id = sp3.max_stock_id;
1 AS id, -- Dummy, LessQL needs an id column
sl.product_id,
sl.amount,
sl.best_before_date,
sl.purchased_date,
sl.price,
sl.qu_factor_purchase_to_stock,
sl.location_id,
sl.shopping_location_id
from stock_log sl
JOIN (
SELECT
s1.product_id,
MAX(s1.id) max_stock_id
FROM stock_log s1
JOIN (
SELECT
s.product_id,
MAX(s.purchased_date) max_purchased_date
FROM stock_log s
WHERE undone = 0
AND transaction_type in ('purchase', 'stock-edit-new', 'inventory-correction')
GROUP BY s.product_id) sp2
ON s1.product_id = sp2.product_id
AND s1.purchased_date = sp2.max_purchased_date
WHERE undone = 0
AND transaction_type in ('purchase', 'stock-edit-new', 'inventory-correction')
GROUP BY s1.product_id) sp3
ON sl.product_id = sp3.product_id
AND sl.id = sp3.max_stock_id;
CREATE VIEW products_average_price AS
select
CREATE VIEW products_average_price
AS
SELECT
1 AS id, -- Dummy, LessQL needs an id column
s.product_id,
round(sum(s.amount * s.price) / sum(s.amount), 2) as price
from stock s group by s.product_id;
FROM stock s
GROUP BY s.product_id;
CREATE VIEW products_oldest_stock_unit_price AS
-- find oldest best_before_date then oldest purchased_date then make sure to return one stock row using max
select
CREATE VIEW products_oldest_stock_unit_price
AS
-- Find oldest best_before_date then oldest purchased_date then make sure to return one stock row using max
SELECT
1 AS id, -- Dummy, LessQL needs an id column
sw.product_id, sw.amount, sw.best_before_date, sw.purchased_date, sw.price, sw.qu_factor_purchase_to_stock, sw.location_id, sw.shopping_location_id
from stock sw join
(select
s1.product_id,
min(s1.id) min_stock_id
from stock s1
join (
select s.product_id,
sp.oldest_date,
min(s.purchased_date) min_purchased_date
from stock s join
(select product_id,
min(best_before_date) as oldest_date
from stock
group by product_id) sp on s.product_id = sp.product_id and s.best_before_date = sp.oldest_date
group by s.product_id, sp.oldest_date) sp2 on s1.product_id = sp2.product_id and s1.best_before_date = sp2.oldest_date and s1.purchased_date = sp2.min_purchased_date
group by s1.product_id) sp3 on sw.product_id = sp3.product_id and sw.id = sp3.min_stock_id;
sw.product_id,
sw.amount,
sw.best_before_date,
sw.purchased_date,
sw.price, sw.qu_factor_purchase_to_stock,
sw.location_id,
sw.shopping_location_id
FROM stock sw
JOIN (
SELECT
s1.product_id,
MIN(s1.id) min_stock_id
FROM stock s1
JOIN (
SELECT
s.product_id,
sp.oldest_date,
MIN(s.purchased_date) min_purchased_date
FROM stock s
JOIN (
SELECT
product_id,
MIN(best_before_date) as oldest_date
FROM stock
GROUP BY product_id) sp
ON s.product_id = sp.product_id
AND s.best_before_date = sp.oldest_date
GROUP BY s.product_id, sp.oldest_date) sp2
ON s1.product_id = sp2.product_id
AND s1.best_before_date = sp2.oldest_date
AND s1.purchased_date = sp2.min_purchased_date
GROUP BY s1.product_id) sp3
ON sw.product_id = sp3.product_id
AND sw.id = sp3.min_stock_id;
DROP VIEW recipes_pos_resolved;
CREATE VIEW recipes_pos_resolved

View File

@ -1,12 +1,12 @@
var stockOverviewTable = $('#stock-overview-table').DataTable({
'order': [[3, 'asc']],
'order': [[4, 'asc']],
'colReorder': false,
'columnDefs': [
{ 'orderable': false, 'targets': 0 },
{ 'searchable': false, "targets": 0 },
{ 'searchable': false, "targets": 0 },
{ 'visible': false, 'targets': 4 },
{ 'visible': false, 'targets': 5 }
{ 'visible': false, 'targets': 5 },
{ 'visible': false, 'targets': 6 }
],
});
$('#stock-overview-table tbody').removeClass("d-none");

View File

@ -1,9 +1,9 @@
@extends('layout.default')
@if($mode == 'edit')
@section('title', $__t('Edit Barcodes'))
@section('title', $__t('Edit Barcode'))
@else
@section('title', $__t('Create Barcodes'))
@section('title', $__t('Create Barcode'))
@endif
@section('viewJsName', 'productbarcodesform')
@ -49,7 +49,7 @@
'additionalCssClasses' => 'input-group-qu',
))
@if(GROCY_FEATURE_FLAG_PRICE_TRACKING)
@if(GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING)
<div class="form-group">
<label for="shopping_location_id_id">{{ $__t('Default store') }}</label>
<select class="form-control" id="shopping_location_id" name="shopping_location_id">

View File

@ -347,7 +347,7 @@
</table>
<h2>
{{ $__t('Barcode Details') }}
{{ $__t('Barcodes') }}
<a class="btn btn-outline-dark show-as-dialog-link" type="button" href="{{ $U('/productbarcodes/new?embedded&product=' . $product->id ) }}">
<i class="fas fa-plus"></i> {{ $__t('Add') }}
</a>
@ -358,8 +358,8 @@
<tr>
<th class="border-right"></th>
<th>{{ $__t('Barcode') }}</th>
<th>{{ $__t('QU Factor Purchase To Stock') }}</th>
<th>{{ $__t('Shopping Location') }}</th>
<th>{{ $__t('Factor purchase to stock quantity unit') }}</th>
<th>{{ $__t('Store') }}</th>
</tr>
</thead>
<tbody class="d-none">

View File

@ -104,7 +104,7 @@
<tr>
<th class="border-right"></th>
<th>{{ $__t('Product') }}</th>
<th>{{ $__t('Product Group') }}</th>
<th>{{ $__t('Product group') }}</th>
<th>{{ $__t('Amount') }}</th>
<th class="@if(!GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING) d-none @endif">{{ $__t('Next best before date') }}</th>
<th class="d-none">Hidden location</th>