Test/review/rework (and hopefully finalized) new price handling

This commit is contained in:
Bernd Bestel 2020-11-10 18:11:33 +01:00
parent 33a6a28208
commit 68eeb07e5f
No known key found for this signature in database
GPG Key ID: 71BD34C0D4891300
44 changed files with 461 additions and 495 deletions

View File

@ -116,8 +116,7 @@ class GenericEntityApiController extends BaseApiController
$userfields = null; $userfields = null;
} }
$object = $this->getDatabase()->{$args['entity']} $object = $this->getDatabase()->{$args['entity']}($args['objectId']);
($args['objectId']);
if ($object == null) if ($object == null)
{ {
@ -136,8 +135,7 @@ class GenericEntityApiController extends BaseApiController
public function GetObjects(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args) public function GetObjects(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
{ {
$objects = $this->getDatabase()->{$args['entity']} $objects = $this->getDatabase()->{$args['entity']}();
();
$allUserfields = $this->getUserfieldsService()->GetAllValues($args['entity']); $allUserfields = $this->getUserfieldsService()->GetAllValues($args['entity']);
foreach ($objects as $object) foreach ($objects as $object)
@ -184,13 +182,11 @@ class GenericEntityApiController extends BaseApiController
{ {
try try
{ {
return $this->FilteredApiResponse($response, $this->getDatabase()->{$args['entity']} return $this->FilteredApiResponse($response, $this->getDatabase()->{$args['entity']}(), $request->getQueryParams());
()->where('name LIKE ?', '%' . $args['searchString'] . '%'), $request->getQueryParams());
} }
catch (\PDOException $ex) catch (\PDOException $ex)
{ {
throw new HttpBadRequestException($request, $ex->getMessage(), $ex); throw new HttpBadRequestException($request, $ex->getMessage(), $ex);
//return $this->GenericErrorResponse($response, 'The given entity has no field "name"', $ex);
} }
} }
else else

View File

@ -108,13 +108,6 @@ class StockApiController extends BaseApiController
$shoppingLocationId = $requestBody['shopping_location_id']; $shoppingLocationId = $requestBody['shopping_location_id'];
} }
$quFactorPurchaseToStock = null;
if (array_key_exists('qu_factor_purchase_to_stock', $requestBody) && is_numeric($requestBody['qu_factor_purchase_to_stock']))
{
$quFactorPurchaseToStock = $requestBody['qu_factor_purchase_to_stock'];
}
$transactionType = StockService::TRANSACTION_TYPE_PURCHASE; $transactionType = StockService::TRANSACTION_TYPE_PURCHASE;
if (array_key_exists('transaction_type', $requestBody) && !empty($requestBody['transactiontype'])) if (array_key_exists('transaction_type', $requestBody) && !empty($requestBody['transactiontype']))
@ -122,7 +115,7 @@ class StockApiController extends BaseApiController
$transactionType = $requestBody['transactiontype']; $transactionType = $requestBody['transactiontype'];
} }
$bookingId = $this->getStockService()->AddProduct($args['productId'], $requestBody['amount'], $bestBeforeDate, $transactionType, $purchasedDate, $price, $quFactorPurchaseToStock, $locationId, $shoppingLocationId); $bookingId = $this->getStockService()->AddProduct($args['productId'], $requestBody['amount'], $bestBeforeDate, $transactionType, $purchasedDate, $price, $locationId, $shoppingLocationId);
return $this->ApiResponse($response, $this->getDatabase()->stock_log($bookingId)); return $this->ApiResponse($response, $this->getDatabase()->stock_log($bookingId));
} }
catch (\Exception $ex) catch (\Exception $ex)
@ -372,7 +365,7 @@ class StockApiController extends BaseApiController
$shoppingLocationId = $requestBody['shopping_location_id']; $shoppingLocationId = $requestBody['shopping_location_id'];
} }
$bookingId = $this->getStockService()->EditStockEntry($args['entryId'], $requestBody['amount'], $bestBeforeDate, $locationId, $shoppingLocationId, $price, $requestBody['open'], $requestBody['purchased_date'], $requestBody['qu_factor_purchase_to_stock']); $bookingId = $this->getStockService()->EditStockEntry($args['entryId'], $requestBody['amount'], $bestBeforeDate, $locationId, $shoppingLocationId, $price, $requestBody['open'], $requestBody['purchased_date']);
return $this->ApiResponse($response, $this->getDatabase()->stock_log($bookingId)); return $this->ApiResponse($response, $this->getDatabase()->stock_log($bookingId));
} }
catch (\Exception $ex) catch (\Exception $ex)
@ -524,18 +517,6 @@ class StockApiController extends BaseApiController
} }
} }
public function ProductBarcodeDetails(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
{
try
{
return $this->ApiResponse($response, $this->getDatabase()->product_barcodes()->where('barcode = :1', $args['barcode'])->fetch());
}
catch (\Exception $ex)
{
return $this->GenericErrorResponse($response, $ex->getMessage());
}
}
public function ProductDetails(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args) public function ProductDetails(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
{ {
try try

View File

@ -30,7 +30,9 @@ class StockController extends BaseController
'products' => $this->getDatabase()->products()->where('active = 1')->orderBy('name'), 'products' => $this->getDatabase()->products()->where('active = 1')->orderBy('name'),
'barcodes' => $productBarcodes, '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'),
'quantityUnits' => $this->getDatabase()->quantity_units()->orderBy('name'),
'quantityUnitConversionsResolved' => $this->getDatabase()->quantity_unit_conversions_resolved()
]); ]);
} }
@ -107,20 +109,24 @@ class StockController extends BaseController
if ($args['productBarcodeId'] == 'new') if ($args['productBarcodeId'] == 'new')
{ {
return $this->renderPage($response, 'productbarcodesform', [ return $this->renderPage($response, 'productbarcodeform', [
'mode' => 'create', 'mode' => 'create',
'barcodes' => $this->getDatabase()->product_barcodes()->orderBy('barcode'), 'barcodes' => $this->getDatabase()->product_barcodes()->orderBy('barcode'),
'product' => $product, 'product' => $product,
'shoppinglocations' => $this->getDatabase()->shopping_locations()->orderBy('name') 'shoppinglocations' => $this->getDatabase()->shopping_locations()->orderBy('name'),
'quantityUnits' => $this->getDatabase()->quantity_units()->orderBy('name'),
'quantityUnitConversionsResolved' => $this->getDatabase()->quantity_unit_conversions_resolved()
]); ]);
} }
else else
{ {
return $this->renderPage($response, 'productbarcodesform', [ return $this->renderPage($response, 'productbarcodeform', [
'mode' => 'edit', 'mode' => 'edit',
'barcode' => $this->getDatabase()->product_barcodes($args['productBarcodeId']), 'barcode' => $this->getDatabase()->product_barcodes($args['productBarcodeId']),
'product' => $product, 'product' => $product,
'shoppinglocations' => $this->getDatabase()->shopping_locations()->orderBy('name') 'shoppinglocations' => $this->getDatabase()->shopping_locations()->orderBy('name'),
'quantityUnits' => $this->getDatabase()->quantity_units()->orderBy('name'),
'quantityUnitConversionsResolved' => $this->getDatabase()->quantity_unit_conversions_resolved()
]); ]);
} }
} }

View File

@ -2755,57 +2755,6 @@
} }
} }
}, },
"/productbarcodedetails/{barcode}": {
"get": {
"summary": "Executes a product barcode details lookoup via the configured plugin with the given barcode",
"tags": [
"Product"
],
"parameters": [
{
"in": "path",
"name": "barcode",
"required": true,
"description": "The barcode to lookup up",
"schema": {
"type": "string"
}
},
{
"in": "query",
"name": "add",
"required": false,
"description": "When true, the product is added to the database on a successful lookup and the new product id is in included in the response",
"schema": {
"type": "boolean",
"default": false
}
}
],
"responses": {
"200": {
"description": "An ProductBarcodeDetails object or null, when nothing was found for the given barcode",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductBarcodeDetailsResponse"
}
}
}
},
"400": {
"description": "The operation was not successful (possible errors are: Plugin error)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GenericErrorResponse"
}
}
}
}
}
}
},
"/recipes/{recipeId}/add-not-fulfilled-products-to-shoppinglist": { "/recipes/{recipeId}/add-not-fulfilled-products-to-shoppinglist": {
"post": { "post": {
"summary": "Adds all missing products for the given recipe to the shopping list", "summary": "Adds all missing products for the given recipe to the shopping list",
@ -3940,8 +3889,9 @@
"id": "1", "id": "1",
"product_id": "13", "product_id": "13",
"barcode": "01321230213", "barcode": "01321230213",
"qu_factor_purchase_to_stock": "10.0", "qu_id": "1",
"shopping_location_id": "2" "shopping_location_id": "2",
"amount": "10"
} }
], ],
"last_purchased": null, "last_purchased": null,
@ -4004,12 +3954,15 @@
"barcode": { "barcode": {
"type": "string" "type": "string"
}, },
"qu_factor_purchase_to_stock": { "qu_id": {
"type": "number", "type": "integer"
"format": "number"
}, },
"shopping_location_id": { "shopping_location_id": {
"type": "integer" "type": "integer"
},
"amount": {
"type": "number",
"format": "number"
} }
} }
}, },

View File

@ -41,3 +41,9 @@ msgstr "Select list (multiple items can be selected)"
msgid "link" msgid "link"
msgstr "Link" msgstr "Link"
msgid "file"
msgstr "File"
msgid "image"
msgstr "Image"

View File

@ -1942,3 +1942,15 @@ msgstr ""
msgid "Save & return to quantity units" msgid "Save & return to quantity units"
msgstr "" msgstr ""
msgid "price"
msgstr ""
msgid "means %1$s per %2$s and %3$s per %4$s"
msgstr ""
msgid "New stock amount"
msgstr ""
msgid "Price per stock unit"
msgstr ""

View File

@ -2,39 +2,28 @@
DELETE from stock_log DELETE from stock_log
WHERE product_id NOT IN (SELECT id from products); WHERE product_id NOT IN (SELECT id from products);
ALTER TABLE stock_log -- Price is based on 1 QU stock
ADD qu_factor_purchase_to_stock REAL NOT NULL DEFAULT 1.0;
ALTER TABLE stock
ADD qu_factor_purchase_to_stock REAL NOT NULL DEFAULT 1.0;
UPDATE stock UPDATE stock
SET qu_factor_purchase_to_stock = (SELECT qu_factor_purchase_to_stock FROM products WHERE product_id = id); SET price = ROUND(price / (SELECT qu_factor_purchase_to_stock FROM products WHERE id = product_id), 2);
UPDATE stock_log UPDATE stock_log
SET qu_factor_purchase_to_stock = (SELECT qu_factor_purchase_to_stock FROM products WHERE product_id = id); SET price = ROUND(price / (SELECT qu_factor_purchase_to_stock FROM products WHERE id = product_id), 2);
--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_log
SET price = ROUND(price / qu_factor_purchase_to_stock, 2);
CREATE TABLE product_barcodes ( CREATE TABLE product_barcodes (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
product_id INT NOT NULL, product_id INT NOT NULL,
barcode TEXT NOT NULL UNIQUE, barcode TEXT NOT NULL UNIQUE,
qu_factor_purchase_to_stock REAL NOT NULL DEFAULT 1, qu_id INT,
amount REAL,
shopping_location_id INTEGER, shopping_location_id INTEGER,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime')) row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
); );
-- Convert product table to new product_barcodes table -- Convert product table to new product_barcodes table
INSERT INTO product_barcodes INSERT INTO product_barcodes
(product_id, barcode, qu_factor_purchase_to_stock, shopping_location_id) (product_id, barcode, shopping_location_id)
WITH barcodes_splitted(id, barcode, str, qu_factor_purchase_to_stock, shopping_location_id) AS ( WITH barcodes_splitted(id, barcode, str, shopping_location_id) AS (
SELECT id as product_id, '', barcode || ',', qu_factor_purchase_to_stock, shopping_location_id SELECT id as product_id, '', barcode || ',', shopping_location_id
FROM products FROM products
UNION ALL UNION ALL
@ -42,12 +31,11 @@ WITH barcodes_splitted(id, barcode, str, qu_factor_purchase_to_stock, shopping_l
id as product_id, id as product_id,
SUBSTR(str, 0, instr(str, ',')), SUBSTR(str, 0, instr(str, ',')),
SUBSTR(str, instr(str, ',') + 1), SUBSTR(str, instr(str, ',') + 1),
qu_factor_purchase_to_stock,
shopping_location_id shopping_location_id
FROM barcodes_splitted FROM barcodes_splitted
WHERE str != '' WHERE str != ''
) )
SELECT id as product_id, barcode, qu_factor_purchase_to_stock, shopping_location_id SELECT id as product_id, barcode, shopping_location_id
FROM barcodes_splitted FROM barcodes_splitted
WHERE barcode != ''; WHERE barcode != '';
@ -97,7 +85,6 @@ SELECT
IFNULL(s.location_id, p.location_id) AS location_id, IFNULL(s.location_id, p.location_id) AS location_id,
s.product_id, s.product_id,
SUM(s.amount) AS amount, 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, 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 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
@ -113,7 +100,6 @@ AS
SELECT SELECT
pr.parent_product_id AS product_id, pr.parent_product_id AS product_id,
IFNULL((SELECT SUM(amount) FROM stock WHERE product_id = pr.parent_product_id), 0) AS amount, 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,
SUM(s.amount) * IFNULL(qucr.factor, 1) AS amount_aggregated, 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, MIN(s.best_before_date) AS best_before_date,
@ -142,7 +128,6 @@ UNION
SELECT SELECT
pr.sub_product_id AS product_id, pr.sub_product_id AS product_id,
SUM(s.amount) AS amount, 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, SUM(s.amount) AS amount_aggregated,
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, MIN(s.best_before_date) AS best_before_date,

View File

@ -10,7 +10,6 @@ select
sl.best_before_date, sl.best_before_date,
sl.purchased_date, sl.purchased_date,
sl.price, sl.price,
sl.qu_factor_purchase_to_stock,
sl.location_id, sl.location_id,
sl.shopping_location_id sl.shopping_location_id
FROM stock_log sl FROM stock_log sl
@ -53,7 +52,7 @@ SELECT
sw.amount, sw.amount,
sw.best_before_date, sw.best_before_date,
sw.purchased_date, sw.purchased_date,
sw.price, sw.qu_factor_purchase_to_stock, sw.price,
sw.location_id, sw.location_id,
sw.shopping_location_id sw.shopping_location_id
FROM stock sw FROM stock sw

View File

@ -15,7 +15,6 @@ SELECT
p.name AS product_name, p.name AS product_name,
(SELECT name FROM product_groups WHERE product_groups.id = product_group_id) AS product_group_name, (SELECT name FROM product_groups WHERE product_groups.id = product_group_id) AS product_group_name,
EXISTS(SELECT * FROM shopping_list WHERE shopping_list.product_id = sc.product_id) AS on_shopping_list, EXISTS(SELECT * FROM shopping_list WHERE shopping_list.product_id = sc.product_id) AS on_shopping_list,
sc.factor_purchase_amount AS factor_purchase_amount,
(SELECT name FROM quantity_units WHERE quantity_units.id = p.qu_id_purchase) AS qu_purchase_unit_name, (SELECT name FROM quantity_units WHERE quantity_units.id = p.qu_id_purchase) AS qu_purchase_unit_name,
(SELECT name_plural FROM quantity_units WHERE quantity_units.id = p.qu_id_purchase) AS qu_purchase_unit_name_plural, (SELECT name_plural FROM quantity_units WHERE quantity_units.id = p.qu_id_purchase) AS qu_purchase_unit_name_plural,
sc.is_aggregated_amount, sc.is_aggregated_amount,
@ -26,7 +25,7 @@ FROM (
FROM stock_current FROM stock_current
WHERE best_before_date IS NOT NULL WHERE best_before_date IS NOT NULL
UNION UNION
SELECT id, 0, 0, 0, 0, null, 0, 0, 0 SELECT id, 0, 0, 0, null, 0, 0, 0
FROM stock_missing_products_including_opened FROM stock_missing_products_including_opened
WHERE id NOT IN (SELECT product_id FROM stock_current) WHERE id NOT IN (SELECT product_id FROM stock_current)
) sc ) sc
@ -50,7 +49,6 @@ SELECT
p.name AS product_name, p.name AS product_name,
(SELECT name FROM product_groups WHERE product_groups.id = product_group_id) AS product_group_name, (SELECT name FROM product_groups WHERE product_groups.id = product_group_id) AS product_group_name,
EXISTS(SELECT * FROM shopping_list WHERE shopping_list.product_id = sc.product_id) AS on_shopping_list, EXISTS(SELECT * FROM shopping_list WHERE shopping_list.product_id = sc.product_id) AS on_shopping_list,
sc.factor_purchase_amount AS factor_purchase_amount,
(SELECT name FROM quantity_units WHERE quantity_units.id = p.qu_id_purchase) AS qu_purchase_unit_name, (SELECT name FROM quantity_units WHERE quantity_units.id = p.qu_id_purchase) AS qu_purchase_unit_name,
(SELECT name_plural FROM quantity_units WHERE quantity_units.id = p.qu_id_purchase) AS qu_purchase_unit_name_plural, (SELECT name_plural FROM quantity_units WHERE quantity_units.id = p.qu_id_purchase) AS qu_purchase_unit_name_plural,
sc.is_aggregated_amount, sc.is_aggregated_amount,

View File

@ -4,7 +4,6 @@ AS
SELECT SELECT
pr.parent_product_id AS product_id, pr.parent_product_id AS product_id,
IFNULL((SELECT SUM(amount) FROM stock WHERE product_id = pr.parent_product_id), 0) AS amount, 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,
SUM(s.amount * IFNULL(qucr.factor, 1.0)) AS amount_aggregated, 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, 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, MIN(s.best_before_date) AS best_before_date,
@ -33,7 +32,6 @@ UNION
SELECT SELECT
pr.sub_product_id AS product_id, pr.sub_product_id AS product_id,
SUM(s.amount) AS amount, 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, SUM(s.amount) AS amount_aggregated,
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, MIN(s.best_before_date) AS best_before_date,

71
migrations/0117.sql Normal file
View File

@ -0,0 +1,71 @@
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;

View File

@ -486,6 +486,7 @@ canvas.drawingBuffer {
.user-filter-message { .user-filter-message {
display: inline-block; display: inline-block;
cursor: pointer; cursor: pointer;
line-height: 0.5;
} }
.related-links .btn { .related-links .btn {

View File

@ -11,7 +11,7 @@ Grocy.Components.ProductAmountPicker.Reload = function(productId, destinationQuI
$("#qu_id").attr("data-destination-qu-name", FindObjectInArrayByPropertyValue(Grocy.QuantityUnits, 'id', destinationQuId).name); $("#qu_id").attr("data-destination-qu-name", FindObjectInArrayByPropertyValue(Grocy.QuantityUnits, 'id', destinationQuId).name);
conversionsForProduct.forEach(conversion => conversionsForProduct.forEach(conversion =>
{ {
var factor = conversion.factor; var factor = parseFloat(conversion.factor);
if (conversion.to_qu_id == destinationQuId) if (conversion.to_qu_id == destinationQuId)
{ {
factor = 1; factor = 1;
@ -39,6 +39,15 @@ Grocy.Components.ProductAmountPicker.Reload = function(productId, destinationQuI
$("#qu_id").val($("#qu_id option:first").val()); $("#qu_id").val($("#qu_id option:first").val());
} }
if ($('#qu_id option').length == 1)
{
$("#qu_id").attr("disabled", "");
}
else
{
$("#qu_id").removeAttr("disabled");
}
$(".input-group-productamountpicker").trigger("change"); $(".input-group-productamountpicker").trigger("change");
} }

View File

@ -6,23 +6,12 @@ Grocy.Components.ProductCard.Refresh = function(productId)
function(productDetails) function(productDetails)
{ {
var stockAmount = productDetails.stock_amount || '0'; var stockAmount = productDetails.stock_amount || '0';
var stockFactorPurchaseAmount = productDetails.stock_factor_purchase_amount || '0';
var stockValue = productDetails.stock_value || '0'; var stockValue = productDetails.stock_value || '0';
var stockAmountOpened = productDetails.stock_amount_opened || '0'; var stockAmountOpened = productDetails.stock_amount_opened || '0';
$('#productcard-product-name').text(productDetails.product.name); $('#productcard-product-name').text(productDetails.product.name);
$('#productcard-product-description').html(productDetails.product.description); $('#productcard-product-description').html(productDetails.product.description);
$('#productcard-product-stock-amount').text(stockAmount); $('#productcard-product-stock-amount').text(stockAmount);
$('#productcard-product-stock-qu-name').text(__n(stockAmount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural)); $('#productcard-product-stock-qu-name').text(__n(stockAmount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural));
if (productDetails.last_qu_factor_purchase_to_stock > 1)
{
$('#productcard-product-stock-factor-purchase-amount').text('(' + stockFactorPurchaseAmount);
$('#productcard-product-stock-factor-purchase-qu-name').text(__n(stockFactorPurchaseAmount, productDetails.quantity_unit_purchase.name, productDetails.quantity_unit_purchase.name_plural) + ')');
}
else
{
$('#productcard-product-stock-factor-purchase-amount').text('');
$('#productcard-product-stock-factor-purchase-qu-name').text('');
}
$('#productcard-product-stock-value').text(stockValue + ' ' + Grocy.Currency); $('#productcard-product-stock-value').text(stockValue + ' ' + Grocy.Currency);
$('#productcard-product-last-purchased').text((productDetails.last_purchased || '2999-12-31').substring(0, 10)); $('#productcard-product-last-purchased').text((productDetails.last_purchased || '2999-12-31').substring(0, 10));
$('#productcard-product-last-purchased-timeago').attr("datetime", productDetails.last_purchased || '2999-12-31'); $('#productcard-product-last-purchased-timeago').attr("datetime", productDetails.last_purchased || '2999-12-31');
@ -95,14 +84,7 @@ Grocy.Components.ProductCard.Refresh = function(productId)
if (productDetails.last_price !== null) if (productDetails.last_price !== null)
{ {
if (productDetails.last_qu_factor_purchase_to_stock > 1) $('#productcard-product-last-price').text(Number.parseFloat(productDetails.last_price).toLocaleString() + ' ' + Grocy.Currency + ' per ' + productDetails.quantity_unit_stock.name);
{
$('#productcard-product-last-price').text(Number.parseFloat(productDetails.last_price * productDetails.last_qu_factor_purchase_to_stock).toLocaleString() + ' ' + Grocy.Currency + ' per 1 ' + productDetails.quantity_unit_purchase.name + ' of ' + productDetails.last_qu_factor_purchase_to_stock + ' ' + productDetails.quantity_unit_stock.name_plural);
}
else
{
$('#productcard-product-last-price').text(Number.parseFloat(productDetails.last_price).toLocaleString() + ' ' + Grocy.Currency + ' per ' + productDetails.quantity_unit_purchase.name);
}
} }
else else
{ {

View File

@ -48,7 +48,6 @@
var jsonDataBarcode = {}; var jsonDataBarcode = {};
jsonDataBarcode.barcode = addBarcode; jsonDataBarcode.barcode = addBarcode;
jsonDataBarcode.product_id = jsonForm.product_id; jsonDataBarcode.product_id = jsonForm.product_id;
jsonDataBarcode.qu_factor_purchase_to_stock = productDetails.product.qu_factor_purchase_to_stock;
Grocy.Api.Post('objects/product_barcodes', jsonDataBarcode, Grocy.Api.Post('objects/product_barcodes', jsonDataBarcode,
function(result) function(result)

View File

@ -45,7 +45,6 @@
var jsonDataBarcode = {}; var jsonDataBarcode = {};
jsonDataBarcode.barcode = addBarcode; jsonDataBarcode.barcode = addBarcode;
jsonDataBarcode.product_id = jsonForm.product_id; jsonDataBarcode.product_id = jsonForm.product_id;
jsonDataBarcode.qu_factor_purchase_to_stock = productDetails.product.qu_factor_purchase_to_stock;
jsonDataBarcode.shopping_location_id = jsonForm.shopping_location_id; jsonDataBarcode.shopping_location_id = jsonForm.shopping_location_id;
Grocy.Api.Post('objects/product_barcodes', jsonDataBarcode, Grocy.Api.Post('objects/product_barcodes', jsonDataBarcode,

View File

@ -79,5 +79,5 @@ $('#location-form input').keydown(function(event)
}); });
Grocy.Components.UserfieldsForm.Load(); Grocy.Components.UserfieldsForm.Load();
$('#name').focus();
Grocy.FrontendHelpers.ValidateForm('location-form'); Grocy.FrontendHelpers.ValidateForm('location-form');
$('#name').focus();

View File

@ -180,11 +180,6 @@ var calendar = $("#calendar").fullCalendar({
productDetails.last_price = 0; productDetails.last_price = 0;
} }
if (productDetails.last_qu_factor_purchase_to_stock === null)
{
productDetails.last_qu_factor_purchase_to_stock = 1;
}
element.attr("data-product-details", event.productDetails); element.attr("data-product-details", event.productDetails);
var productOrderMissingButtonDisabledClasses = "disabled"; var productOrderMissingButtonDisabledClasses = "disabled";
@ -210,7 +205,7 @@ var calendar = $("#calendar").fullCalendar({
var costsAndCaloriesPerServing = "" var costsAndCaloriesPerServing = ""
if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING) if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING)
{ {
costsAndCaloriesPerServing = '<h5 class="small text-truncate"><span class="locale-number locale-number-currency">' + productDetails.last_price / productDetails.last_qu_factor_purchase_to_stock * mealPlanEntry.product_amount + '</span> / <span class="locale-number locale-number-generic">' + productDetails.product.calories * mealPlanEntry.product_amount + '</span> kcal ' + '<h5>'; costsAndCaloriesPerServing = '<h5 class="small text-truncate"><span class="locale-number locale-number-currency">' + productDetails.last_price * mealPlanEntry.product_amount + '</span> / <span class="locale-number locale-number-generic">' + productDetails.product.calories * mealPlanEntry.product_amount + '</span> kcal ' + '<h5>';
} }
else else
{ {

View File

@ -3,6 +3,9 @@
e.preventDefault(); e.preventDefault();
var jsonData = $('#barcode-form').serializeJSON(); var jsonData = $('#barcode-form').serializeJSON();
jsonData.amount = jsonData.display_amount;
delete jsonData.display_amount;
Grocy.FrontendHelpers.BeginUiBusy("barcode-form"); Grocy.FrontendHelpers.BeginUiBusy("barcode-form");
if (Grocy.EditMode === 'create') if (Grocy.EditMode === 'create')
@ -36,12 +39,17 @@
window.parent.postMessage(WindowMessageBag("CloseAllModals"), U("/product/" + GetUriParam("product"))); window.parent.postMessage(WindowMessageBag("CloseAllModals"), U("/product/" + GetUriParam("product")));
}); });
$('#barcode').on('change', function(e) $('#barcode').on('keyup', function(e)
{ {
Grocy.FrontendHelpers.ValidateForm('barcode-form'); Grocy.FrontendHelpers.ValidateForm('barcode-form');
}); });
$('#qu_factor_purchase_to_stock').on('change', function(e) $('#qu_id').on('change', function(e)
{
Grocy.FrontendHelpers.ValidateForm('barcode-form');
});
$('#display_amount').on('keyup', function(e)
{ {
Grocy.FrontendHelpers.ValidateForm('barcode-form'); Grocy.FrontendHelpers.ValidateForm('barcode-form');
}); });
@ -62,4 +70,13 @@ $('#barcode-form input').keydown(function(event)
} }
} }
}); });
Grocy.Components.ProductAmountPicker.Reload(Grocy.EditObjectProduct.id, Grocy.EditObjectProduct.qu_id_purchase);
if (Grocy.EditMode == "edit")
{
$("#display_amount").val(Grocy.EditObject.amount);
Grocy.Components.ProductAmountPicker.SetQuantityUnit(Grocy.EditObject.qu_id);
}
Grocy.FrontendHelpers.ValidateForm('barcode-form'); Grocy.FrontendHelpers.ValidateForm('barcode-form');
$('#barcode').focus();

View File

@ -8,6 +8,12 @@
Grocy.Api.UploadFile($("#product-picture")[0].files[0], 'productpictures', jsonData.picture_file_name, Grocy.Api.UploadFile($("#product-picture")[0].files[0], 'productpictures', jsonData.picture_file_name,
(result) => (result) =>
{ {
if (Grocy.ProductEditFormRedirectUri == "reload")
{
window.location.reload();
return
}
var returnTo = GetUriParam('returnto'); var returnTo = GetUriParam('returnto');
if (GetUriParam("closeAfterCreation") !== undefined) if (GetUriParam("closeAfterCreation") !== undefined)
{ {
@ -32,6 +38,12 @@
} }
else else
{ {
if (Grocy.ProductEditFormRedirectUri == "reload")
{
window.location.reload();
return
}
var returnTo = GetUriParam('returnto'); var returnTo = GetUriParam('returnto');
if (GetUriParam("closeAfterCreation") !== undefined) if (GetUriParam("closeAfterCreation") !== undefined)
{ {
@ -145,9 +157,6 @@ $('.input-group-qu').on('change', function(e)
$('#qu-conversion-info').addClass('d-none'); $('#qu-conversion-info').addClass('d-none');
} }
$("#qu-conversion-headline-info").text(__t('1 %s is the same as...', $("#qu_id_stock option:selected").text()));
quConversionsTable.column(4).search("from_qu_id xx" + $("#qu_id_stock").val().toString() + "xx").draw();
$("#tare_weight_qu_info").text($("#qu_id_stock option:selected").text()); $("#tare_weight_qu_info").text($("#qu_id_stock option:selected").text());
Grocy.FrontendHelpers.ValidateForm('product-form'); Grocy.FrontendHelpers.ValidateForm('product-form');
@ -301,14 +310,14 @@ if (Grocy.EditMode === 'create')
var quConversionsTable = $('#qu-conversions-table').DataTable({ var quConversionsTable = $('#qu-conversions-table').DataTable({
'order': [[1, 'asc']], 'order': [[1, 'asc']],
"orderFixed": [[3, 'asc']], "orderFixed": [[4, 'asc']],
'columnDefs': [ 'columnDefs': [
{ 'orderable': false, 'targets': 0 }, { 'orderable': false, 'targets': 0 },
{ 'searchable': false, "targets": 0 }, { 'searchable': false, "targets": 0 },
{ 'visible': false, 'targets': 3 } { 'visible': false, 'targets': 4 }
], ],
'rowGroup': { 'rowGroup': {
dataSrc: 3 dataSrc: 4
} }
}); });
$('#qu-conversions-table tbody').removeClass("d-none"); $('#qu-conversions-table tbody').removeClass("d-none");

View File

@ -3,7 +3,6 @@
e.preventDefault(); e.preventDefault();
var jsonForm = $('#purchase-form').serializeJSON(); var jsonForm = $('#purchase-form').serializeJSON();
jsonForm.qu_factor_purchase_to_stock = $("#qu_id option:selected").attr("data-qu-factor");
Grocy.FrontendHelpers.BeginUiBusy("purchase-form"); Grocy.FrontendHelpers.BeginUiBusy("purchase-form");
@ -16,14 +15,14 @@
if (!Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING) if (!Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING)
{ {
jsonData.price = 0; jsonData.price = 0;
} else }
else
{ {
// price is saved as 1 QU to stock var price = parseFloat(jsonForm.price * $("#qu_id option:selected").attr("data-qu-factor")).toFixed(Grocy.UserSettings.stock_decimal_places_prices);
var price = parseFloat(jsonForm.price / jsonForm.qu_factor_purchase_to_stock).toFixed(Grocy.UserSettings.stock_decimal_places_prices);
if ($("input[name='price-type']:checked").val() == "total-price") if ($("input[name='price-type']:checked").val() == "total-price")
{ {
price = parseFloat(price / jsonForm.amount).toFixed(Grocy.UserSettings.stock_decimal_places_prices); price = parseFloat(price / jsonForm.display_amount).toFixed(Grocy.UserSettings.stock_decimal_places_prices);
} }
jsonData.price = price; jsonData.price = price;
} }
@ -50,7 +49,6 @@
{ {
jsonData.location_id = Grocy.Components.LocationPicker.GetValue(); jsonData.location_id = Grocy.Components.LocationPicker.GetValue();
} }
jsonData.qu_factor_purchase_to_stock = jsonForm.qu_factor_purchase_to_stock;
Grocy.Api.Post('stock/products/' + jsonForm.product_id + '/add', jsonData, Grocy.Api.Post('stock/products/' + jsonForm.product_id + '/add', jsonData,
function(result) function(result)
@ -66,7 +64,6 @@
var jsonDataBarcode = {}; var jsonDataBarcode = {};
jsonDataBarcode.barcode = addBarcode; jsonDataBarcode.barcode = addBarcode;
jsonDataBarcode.product_id = jsonForm.product_id; jsonDataBarcode.product_id = jsonForm.product_id;
jsonDataBarcode.qu_factor_purchase_to_stock = jsonForm.qu_factor_purchase_to_stock;
jsonDataBarcode.shopping_location_id = jsonForm.shopping_location_id; jsonDataBarcode.shopping_location_id = jsonForm.shopping_location_id;
Grocy.Api.Post('objects/product_barcodes', jsonDataBarcode, Grocy.Api.Post('objects/product_barcodes', jsonDataBarcode,
@ -122,6 +119,12 @@
} }
Grocy.Components.ProductPicker.GetInputElement().focus(); Grocy.Components.ProductPicker.GetInputElement().focus();
Grocy.Components.ProductCard.Refresh(jsonForm.product_id); Grocy.Components.ProductCard.Refresh(jsonForm.product_id);
$('#price-hint').text("");
var priceTypeUnitPrice = $("#price-type-unit-price");
var priceTypeUnitPriceLabel = $("[for=" + priceTypeUnitPrice.attr("id") + "]");
priceTypeUnitPriceLabel.text(__t("Unit price"));
Grocy.FrontendHelpers.ValidateForm('purchase-form'); Grocy.FrontendHelpers.ValidateForm('purchase-form');
} }
}, },
@ -155,67 +158,17 @@ if (Grocy.Components.ProductPicker !== undefined)
{ {
Grocy.Components.ProductCard.Refresh(productId); Grocy.Components.ProductCard.Refresh(productId);
if (document.getElementById("product_id").getAttribute("barcode") != "null")
{
Grocy.Api.Get('productbarcodedetails/' + document.getElementById("product_id").getAttribute("barcode"),
function(resultBarcode)
{
if (resultBarcode != null)
{
$('#product_id').attr("barcode-qu-factor-purchase-to-stock", resultBarcode.qu_factor_purchase_to_stock);
$('#product_id').attr("barcode-shopping-location-id", resultBarcode.shopping_location_id);
}
else
{
$('#product_id').attr("barcode-qu-factor-purchase-to-stock", "null");
$('#product_id').attr("barcode-shopping-location-id", "null");
}
},
function(xhr)
{
console.error(xhr);
}
);
}
else
{
$('#product_id').attr("barcode-qu-factor-purchase-to-stock", "null");
$('#product_id').attr("barcode-shopping-location-id", "null");
}
Grocy.Api.Get('stock/products/' + productId, Grocy.Api.Get('stock/products/' + productId,
function(productDetails) function(productDetails)
{ {
Grocy.Components.ProductAmountPicker.Reload(productDetails.product.id, productDetails.quantity_unit_stock.id); Grocy.Components.ProductAmountPicker.Reload(productDetails.product.id, productDetails.quantity_unit_stock.id);
Grocy.Components.ProductAmountPicker.SetQuantityUnit(productDetails.quantity_unit_purchase.id); Grocy.Components.ProductAmountPicker.SetQuantityUnit(productDetails.quantity_unit_purchase.id);
var qu_factor_purchase_to_stock = null;
var barcode_shopping_location_id = null; var barcode_shopping_location_id = null;
if (document.getElementById("product_id").getAttribute("barcode") != "null" && document.getElementById("product_id").getAttribute("barcode-qu-factor-purchase-to-stock") != "null")
{
qu_factor_purchase_to_stock = document.getElementById("product_id").getAttribute("barcode-qu-factor-purchase-to-stock");
barcode_shopping_location_id = document.getElementById("product_id").getAttribute("barcode-shopping-location-id");
}
else
{
if (productDetails.last_qu_factor_purchase_to_stock != null)
{
qu_factor_purchase_to_stock = productDetails.last_qu_factor_purchase_to_stock;
}
else
{
qu_factor_purchase_to_stock = productDetails.product.qu_factor_purchase_to_stock;
}
}
if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING) if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING)
{ {
if (barcode_shopping_location_id != null) if (productDetails.last_shopping_location_id != null)
{
Grocy.Components.ShoppingLocationPicker.SetId(barcode_shopping_location_id);
}
else if (productDetails.last_shopping_location_id != null)
{ {
Grocy.Components.ShoppingLocationPicker.SetId(productDetails.last_shopping_location_id); Grocy.Components.ShoppingLocationPicker.SetId(productDetails.last_shopping_location_id);
} }
@ -230,11 +183,11 @@ if (Grocy.Components.ProductPicker !== undefined)
Grocy.Components.LocationPicker.SetId(productDetails.location.id); Grocy.Components.LocationPicker.SetId(productDetails.location.id);
} }
$('#price').val(parseFloat(productDetails.last_price * qu_factor_purchase_to_stock).toLocaleString({ minimumFractionDigits: 2, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_prices })); $('#price').val(parseFloat(productDetails.last_price / $("#qu_id option:selected").attr("data-qu-factor")).toLocaleString({ minimumFractionDigits: 2, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_prices }));
var priceTypeUnitPrice = $("#price-type-unit-price"); var priceTypeUnitPrice = $("#price-type-unit-price");
var priceTypeUnitPriceLabel = $("[for=" + priceTypeUnitPrice.attr("id") + "]"); var priceTypeUnitPriceLabel = $("[for=" + priceTypeUnitPrice.attr("id") + "]");
priceTypeUnitPriceLabel.text(productDetails.quantity_unit_purchase.name + " price"); priceTypeUnitPriceLabel.text($("#qu_id option:selected").text() + " " + __t("price"));
refreshPriceHint(); refreshPriceHint();
@ -253,7 +206,7 @@ if (Grocy.Components.ProductPicker !== undefined)
if (productDetails.product.enable_tare_weight_handling == 1) if (productDetails.product.enable_tare_weight_handling == 1)
{ {
var minAmount = parseFloat(productDetails.product.tare_weight) / qu_factor_purchase_to_stock + parseFloat(productDetails.stock_amount); var minAmount = parseFloat(productDetails.product.tare_weight) / $("#qu_id option:selected").attr("data-qu-factor") + parseFloat(productDetails.stock_amount);
$("#display_amount").attr("min", minAmount); $("#display_amount").attr("min", minAmount);
$("#display_amount").attr("step", "." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1"); $("#display_amount").attr("step", "." + "0".repeat(parseInt(Grocy.UserSettings.stock_decimal_places_amounts) - 1) + "1");
$("#display_amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %s', minAmount.toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }))); $("#display_amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %s', minAmount.toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts })));
@ -304,6 +257,40 @@ if (Grocy.Components.ProductPicker !== undefined)
Grocy.UISound.Error(); Grocy.UISound.Error();
} }
} }
if (document.getElementById("product_id").getAttribute("barcode") != "null")
{
Grocy.Api.Get('objects/product_barcodes/search/?query[]=barcode=' + document.getElementById("product_id").getAttribute("barcode"),
function(barcodeResult)
{
if (barcodeResult != null)
{
var barcode = barcodeResult[0];
if (barcode.amount != null)
{
$("#display_amount").val(barcode.amount);
}
if (barcode.qu_id != null)
{
Grocy.Components.ProductAmountPicker.SetQuantityUnit(barcode.qu_id);
}
if (barcode.shopping_location_id != null)
{
Grocy.Components.ShoppingLocationPicker.SetId(barcode.shopping_location_id);
}
Grocy.FrontendHelpers.ValidateForm('purchase-form');
}
},
function(xhr)
{
console.error(xhr);
}
);
}
}, },
function(xhr) function(xhr)
{ {
@ -409,12 +396,7 @@ if (GetUriParam("flow") === "shoppinglistitemtostock")
function refreshPriceHint() function refreshPriceHint()
{ {
if ($('#amount').val() == 0) if ($('#amount').val() == 0 || $('#price').val() == 0)
{
$('#price-hint').text("");
return;
}
if ($('#price').val() == 0)
{ {
$('#price-hint').text(""); $('#price-hint').text("");
return; return;
@ -422,29 +404,14 @@ function refreshPriceHint()
if ($("input[name='price-type']:checked").val() == "total-price") if ($("input[name='price-type']:checked").val() == "total-price")
{ {
var price = $('#price').val() / $("#qu_id option:selected").attr("data-qu-factor") / $('#amount').val(); var price = parseFloat($('#price').val() * $("#qu_id option:selected").attr("data-qu-factor")).toFixed(Grocy.UserSettings.stock_decimal_places_prices);
var quprice = $('#price').val() / $('#amount').val(); price = parseFloat(price / $('#display_amount').val()).toFixed(Grocy.UserSettings.stock_decimal_places_prices);
if ($("#qu_id option:selected").attr("data-qu-factor") > 1) $('#price-hint').text(__t('means %1$s per %2$s', price.toLocaleString({ minimumFractionDigits: 2, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_prices }), $("#qu_id").attr("data-destination-qu-name")));
{
$('#price-hint').text(__t('means %1$s per %2$s and %3$s per %4$s', price.toLocaleString({ minimumFractionDigits: 2, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_prices }), $("#qu_id").attr("data-destination-qu-name"), quprice.toLocaleString({ minimumFractionDigits: 2, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_prices }), document.getElementById("amount_qu_unit").getAttribute("quantity-unit-purchase-name")));
}
else
{
$('#price-hint').text(__t('means %1$s per %2$s', price.toLocaleString({ minimumFractionDigits: 2, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_prices }), $("#qu_id").attr("data-destination-qu-name")));
}
} }
else else
{ {
if ($("#qu_id option:selected").attr("data-qu-factor") > 1) $('#price-hint').text("");
{
var price = $('#price').val() / $("#qu_id option:selected").attr("data-qu-factor");
$('#price-hint').text(__t('means %1$s per %2$s', price.toLocaleString({ minimumFractionDigits: 2, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_prices }), $("#qu_id").attr("data-destination-qu-name")));
}
else
{
$('#price-hint').text("");
}
} }
}; };
@ -520,3 +487,10 @@ $("#scan-mode-button").on("click", function(e)
$("#scan-mode-status").text(__t("off")); $("#scan-mode-status").text(__t("off"));
} }
}); });
$('#qu_id').on('change', function(e)
{
var priceTypeUnitPrice = $("#price-type-unit-price");
var priceTypeUnitPriceLabel = $("[for=" + priceTypeUnitPrice.attr("id") + "]");
priceTypeUnitPriceLabel.text($("#qu_id option:selected").text() + " " + __t("price"));
});

View File

@ -174,12 +174,12 @@ $('.input-group-qu').on('change', function(e)
if (fromQuId && toQuId) if (fromQuId && toQuId)
{ {
$('#qu-conversion-info').text(__t('This means 1 %1$s is the same as %2$s %3$s', $("#from_qu_id option:selected").text(), (1 * factor).toString(), __n((1 * factor).toString(), $("#to_qu_id option:selected").text(), $("#to_qu_id option:selected").data("plural-form")))); $('#qu-conversion-info').text(__t('This means 1 %1$s is the same as %2$s %3$s', $("#from_qu_id option:selected").text(), parseFloat((1 * factor)).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }), __n((1 * factor).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }), $("#to_qu_id option:selected").text(), $("#to_qu_id option:selected").data("plural-form"))));
$('#qu-conversion-info').removeClass('d-none'); $('#qu-conversion-info').removeClass('d-none');
if (Grocy.EditMode === 'create') if (Grocy.EditMode === 'create')
{ {
$('#qu-conversion-inverse-info').text('(' + __t('This means 1 %1$s is the same as %2$s %3$s', $("#to_qu_id option:selected").text(), (1 / factor).toString(), __n((1 / factor).toString(), $("#from_qu_id option:selected").text(), $("#from_qu_id option:selected").data("plural-form"))) + ')'); $('#qu-conversion-inverse-info').text(__t('This means 1 %1$s is the same as %2$s %3$s', $("#to_qu_id option:selected").text(), parseFloat((1 / factor)).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }), __n((1 / factor).toString(), $("#from_qu_id option:selected").text(), $("#from_qu_id option:selected").data("plural-form"))));
$('#qu-conversion-inverse-info').removeClass('d-none'); $('#qu-conversion-inverse-info').removeClass('d-none');
} }
} }
@ -196,3 +196,8 @@ Grocy.Components.UserfieldsForm.Load();
$('.input-group-qu').trigger('change'); $('.input-group-qu').trigger('change');
$('#from_qu_id').focus(); $('#from_qu_id').focus();
Grocy.FrontendHelpers.ValidateForm('quconversion-form'); Grocy.FrontendHelpers.ValidateForm('quconversion-form');
if (GetUriParam("qu-unit") !== undefined)
{
$("#from_qu_id").attr("disabled", "");
}

View File

@ -177,7 +177,6 @@ function RefreshStockEntryRow(stockRowId)
); );
$('#stock-' + stockRowId + '-price').text(result.price); $('#stock-' + stockRowId + '-price').text(result.price);
$('#stock-' + stockRowId + '-qu-factor-purchase-to-stock').text(result.qu_factor_purchase_to_stock);
$('#stock-' + stockRowId + '-purchased-date').text(result.purchased_date); $('#stock-' + stockRowId + '-purchased-date').text(result.purchased_date);
$('#stock-' + stockRowId + '-purchased-date-timeago').attr('datetime', result.purchased_date + ' 23:59:59'); $('#stock-' + stockRowId + '-purchased-date-timeago').attr('datetime', result.purchased_date + ' 23:59:59');

View File

@ -27,7 +27,6 @@
jsonData.location_id = 1; jsonData.location_id = 1;
} }
jsonData.price = price; jsonData.price = price;
jsonData.qu_factor_purchase_to_stock = jsonForm.qu_factor_purchase_to_stock;
jsonData.open = $("#open").is(":checked"); jsonData.open = $("#open").is(":checked");

View File

@ -291,7 +291,6 @@ function RefreshProductRow(productId)
$('#product-' + productId + '-qu-name').text(__n(result.stock_amount, result.quantity_unit_stock.name, result.quantity_unit_stock.name_plural)); $('#product-' + productId + '-qu-name').text(__n(result.stock_amount, result.quantity_unit_stock.name, result.quantity_unit_stock.name_plural));
$('#product-' + productId + '-amount').text(result.stock_amount); $('#product-' + productId + '-amount').text(result.stock_amount);
$('#product-' + productId + '-consume-all-button').attr('data-consume-amount', result.stock_amount); $('#product-' + productId + '-consume-all-button').attr('data-consume-amount', result.stock_amount);
$('#product-' + productId + '-factor-purchase-amount').text(__t('( %s', result.stock_factor_purchase_amount));
$('#product-' + productId + '-value').text(result.stock_value); $('#product-' + productId + '-value').text(result.stock_value);
$('#product-' + productId + '-next-best-before-date').text(result.next_best_before_date); $('#product-' + productId + '-next-best-before-date').text(result.next_best_before_date);
$('#product-' + productId + '-next-best-before-date-timeago').attr('datetime', result.next_best_before_date); $('#product-' + productId + '-next-best-before-date-timeago').attr('datetime', result.next_best_before_date);

View File

@ -33,7 +33,6 @@
var jsonDataBarcode = {}; var jsonDataBarcode = {};
jsonDataBarcode.barcode = addBarcode; jsonDataBarcode.barcode = addBarcode;
jsonDataBarcode.product_id = jsonForm.product_id; jsonDataBarcode.product_id = jsonForm.product_id;
jsonDataBarcode.qu_factor_purchase_to_stock = productDetails.product.qu_factor_purchase_to_stock;
Grocy.Api.Post('objects/product_barcodes', jsonDataBarcode, Grocy.Api.Post('objects/product_barcodes', jsonDataBarcode,
function(result) function(result)

View File

@ -203,7 +203,6 @@ $app->group('/api', function (RouteCollectorProxy $group) {
$group->get('/stock/transactions/{transactionId}', '\Grocy\Controllers\StockApiController:StockTransactions'); $group->get('/stock/transactions/{transactionId}', '\Grocy\Controllers\StockApiController:StockTransactions');
$group->post('/stock/transactions/{transactionId}/undo', '\Grocy\Controllers\StockApiController:UndoTransaction'); $group->post('/stock/transactions/{transactionId}/undo', '\Grocy\Controllers\StockApiController:UndoTransaction');
$group->get('/stock/barcodes/external-lookup/{barcode}', '\Grocy\Controllers\StockApiController:ExternalBarcodeLookup'); $group->get('/stock/barcodes/external-lookup/{barcode}', '\Grocy\Controllers\StockApiController:ExternalBarcodeLookup');
$group->get('/productbarcodedetails/{barcode}', '\Grocy\Controllers\StockApiController:ProductBarcodeDetails');
$group->get('/stock/journal', '\Grocy\Controllers\StockApiController:Journal'); $group->get('/stock/journal', '\Grocy\Controllers\StockApiController:Journal');
$group->get('/stock/journal/summary', '\Grocy\Controllers\StockApiController:JournalSummary'); $group->get('/stock/journal/summary', '\Grocy\Controllers\StockApiController:JournalSummary');
} }

View File

@ -185,80 +185,80 @@ class DemoDataGeneratorService extends BaseService
$stockTransactionId = uniqid(); $stockTransactionId = uniqid();
$stockService = new StockService(); $stockService = new StockService();
$stockService->AddProduct(3, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(3, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(3, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(3, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(3, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(3, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(3, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(3, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(3, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(3, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(4, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(4, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(4, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(4, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(4, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(4, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(4, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(4, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(4, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(4, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(5, 1, date('Y-m-d', strtotime('+20 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), 10, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(5, 1, date('Y-m-d', strtotime('+20 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(5, 1, date('Y-m-d', strtotime('+20 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), 10, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(5, 1, date('Y-m-d', strtotime('+20 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(5, 1, date('Y-m-d', strtotime('+20 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), 10, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(5, 1, date('Y-m-d', strtotime('+20 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(5, 1, date('Y-m-d', strtotime('+20 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), 10, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(5, 1, date('Y-m-d', strtotime('+20 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(5, 1, date('Y-m-d', strtotime('+20 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), 10, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(5, 1, date('Y-m-d', strtotime('+20 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(6, 1, date('Y-m-d', strtotime('+600 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(6, 1, date('Y-m-d', strtotime('+600 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(6, 1, date('Y-m-d', strtotime('+600 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(6, 1, date('Y-m-d', strtotime('+600 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(6, 1, date('Y-m-d', strtotime('+600 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(6, 1, date('Y-m-d', strtotime('+600 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(6, 1, date('Y-m-d', strtotime('+600 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(6, 1, date('Y-m-d', strtotime('+600 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(6, 1, date('Y-m-d', strtotime('+600 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(6, 1, date('Y-m-d', strtotime('+600 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(7, 1, date('Y-m-d', strtotime('+800 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(7, 1, date('Y-m-d', strtotime('+800 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(7, 1, date('Y-m-d', strtotime('+800 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(7, 1, date('Y-m-d', strtotime('+800 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(7, 1, date('Y-m-d', strtotime('+800 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(7, 1, date('Y-m-d', strtotime('+800 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(7, 1, date('Y-m-d', strtotime('+800 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(7, 1, date('Y-m-d', strtotime('+800 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(7, 1, date('Y-m-d', strtotime('+800 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(7, 1, date('Y-m-d', strtotime('+800 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(8, 1, date('Y-m-d', strtotime('+900 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(8, 1, date('Y-m-d', strtotime('+900 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(8, 1, date('Y-m-d', strtotime('+900 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(8, 1, date('Y-m-d', strtotime('+900 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(8, 1, date('Y-m-d', strtotime('+900 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(8, 1, date('Y-m-d', strtotime('+900 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(8, 1, date('Y-m-d', strtotime('+900 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(8, 1, date('Y-m-d', strtotime('+900 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(8, 1, date('Y-m-d', strtotime('+900 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(8, 1, date('Y-m-d', strtotime('+900 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(9, 1, date('Y-m-d', strtotime('+14 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(9, 1, date('Y-m-d', strtotime('+14 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(9, 1, date('Y-m-d', strtotime('+14 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(9, 1, date('Y-m-d', strtotime('+14 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(9, 1, date('Y-m-d', strtotime('+14 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(9, 1, date('Y-m-d', strtotime('+14 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(9, 1, date('Y-m-d', strtotime('+14 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(9, 1, date('Y-m-d', strtotime('+14 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(9, 1, date('Y-m-d', strtotime('+14 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(9, 1, date('Y-m-d', strtotime('+14 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(10, 1, date('Y-m-d', strtotime('+21 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(10, 1, date('Y-m-d', strtotime('+21 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(10, 1, date('Y-m-d', strtotime('+21 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(10, 1, date('Y-m-d', strtotime('+21 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(10, 1, date('Y-m-d', strtotime('+21 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(10, 1, date('Y-m-d', strtotime('+21 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(10, 1, date('Y-m-d', strtotime('+21 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(10, 1, date('Y-m-d', strtotime('+21 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(10, 1, date('Y-m-d', strtotime('+21 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(10, 1, date('Y-m-d', strtotime('+21 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(11, 1, date('Y-m-d', strtotime('+10 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(11, 1, date('Y-m-d', strtotime('+10 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(11, 1, date('Y-m-d', strtotime('+10 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(11, 1, date('Y-m-d', strtotime('+10 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(11, 1, date('Y-m-d', strtotime('+10 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(11, 1, date('Y-m-d', strtotime('+10 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(11, 1, date('Y-m-d', strtotime('+10 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(11, 1, date('Y-m-d', strtotime('+10 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(11, 1, date('Y-m-d', strtotime('+10 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(11, 1, date('Y-m-d', strtotime('+10 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(12, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(12, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(12, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(12, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(12, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(12, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(12, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(12, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(12, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(12, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(13, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(13, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(13, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(13, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(13, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(13, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(13, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(13, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(13, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(13, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(14, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(14, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(14, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(14, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(14, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(14, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(14, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(14, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(14, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(14, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(15, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(15, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(15, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(15, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(15, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(15, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(15, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(15, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(15, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(15, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(21, 1500, date('Y-m-d', strtotime('+200 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(21, 1500, date('Y-m-d', strtotime('+200 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(21, 2500, date('Y-m-d', strtotime('+200 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(21, 2500, date('Y-m-d', strtotime('+200 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(22, 1, date('Y-m-d', strtotime('+200 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(22, 1, date('Y-m-d', strtotime('+200 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(22, 1, date('Y-m-d', strtotime('+200 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(22, 1, date('Y-m-d', strtotime('+200 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(23, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(23, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(23, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(23, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(24, 2, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(24, 2, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(25, 2, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(25, 2, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(2, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), 1.0, null, $this->NextSupermarketId(), $stockTransactionId); $stockService->AddProduct(2, 1, date('Y-m-d', strtotime('+180 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddMissingProductsToShoppingList(); $stockService->AddMissingProductsToShoppingList();
$stockService->OpenProduct(3, 1); $stockService->OpenProduct(3, 1);
$stockService->OpenProduct(6, 1); $stockService->OpenProduct(6, 1);

View File

@ -79,7 +79,7 @@ class StockService extends BaseService
} }
} }
public function AddProduct(int $productId, float $amount, $bestBeforeDate, $transactionType, $purchasedDate, $price, $quFactorPurchaseToStock = null, $locationId = null, $shoppingLocationId = null, &$transactionId = null) public function AddProduct(int $productId, float $amount, $bestBeforeDate, $transactionType, $purchasedDate, $price, $locationId = null, $shoppingLocationId = null, &$transactionId = null)
{ {
if (!$this->ProductExists($productId)) if (!$this->ProductExists($productId))
{ {
@ -88,11 +88,6 @@ class StockService extends BaseService
$productDetails = (object) $this->GetProductDetails($productId); $productDetails = (object) $this->GetProductDetails($productId);
if ($quFactorPurchaseToStock == null)
{
$quFactorPurchaseToStock = $productDetails->product->qu_factor_purchase_to_stock;
}
// Tare weight handling // Tare weight handling
// The given amount is the new total amount including the container weight (gross) // The given amount is the new total amount including the container weight (gross)
// The amount to be posted needs to be the given amount - stock amount - tare weight // The amount to be posted needs to be the given amount - stock amount - tare weight
@ -144,7 +139,6 @@ class StockService extends BaseService
'location_id' => $locationId, 'location_id' => $locationId,
'transaction_id' => $transactionId, 'transaction_id' => $transactionId,
'shopping_location_id' => $shoppingLocationId, 'shopping_location_id' => $shoppingLocationId,
'qu_factor_purchase_to_stock' => $quFactorPurchaseToStock,
'user_id' => GROCY_USER_ID 'user_id' => GROCY_USER_ID
]); ]);
$logRow->save(); $logRow->save();
@ -160,7 +154,6 @@ class StockService extends BaseService
'price' => $price, 'price' => $price,
'location_id' => $locationId, 'location_id' => $locationId,
'shopping_location_id' => $shoppingLocationId, 'shopping_location_id' => $shoppingLocationId,
'qu_factor_purchase_to_stock' => $quFactorPurchaseToStock
]); ]);
$stockRow->save(); $stockRow->save();
@ -342,7 +335,7 @@ class StockService extends BaseService
} }
} }
public function EditStockEntry(int $stockRowId, float $amount, $bestBeforeDate, $locationId, $shoppingLocationId, $price, $open, $purchasedDate, $quFactorPurchaseToStock) public function EditStockEntry(int $stockRowId, float $amount, $bestBeforeDate, $locationId, $shoppingLocationId, $price, $open, $purchasedDate)
{ {
$stockRow = $this->getDatabase()->stock()->where('id = :1', $stockRowId)->fetch(); $stockRow = $this->getDatabase()->stock()->where('id = :1', $stockRowId)->fetch();
@ -364,7 +357,6 @@ class StockService extends BaseService
'opened_date' => $stockRow->opened_date, 'opened_date' => $stockRow->opened_date,
'location_id' => $stockRow->location_id, 'location_id' => $stockRow->location_id,
'shopping_location_id' => $stockRow->shopping_location_id, 'shopping_location_id' => $stockRow->shopping_location_id,
'qu_factor_purchase_to_stock' => $stockRow->qu_factor_purchase_to_stock,
'correlation_id' => $correlationId, 'correlation_id' => $correlationId,
'transaction_id' => $transactionId, 'transaction_id' => $transactionId,
'stock_row_id' => $stockRow->id, 'stock_row_id' => $stockRow->id,
@ -391,7 +383,6 @@ class StockService extends BaseService
'shopping_location_id' => $shoppingLocationId, 'shopping_location_id' => $shoppingLocationId,
'opened_date' => $openedDate, 'opened_date' => $openedDate,
'open' => $open, 'open' => $open,
'qu_factor_purchase_to_stock' => $quFactorPurchaseToStock,
'purchased_date' => $purchasedDate 'purchased_date' => $purchasedDate
]); ]);
@ -406,7 +397,6 @@ class StockService extends BaseService
'opened_date' => $stockRow->opened_date, 'opened_date' => $stockRow->opened_date,
'location_id' => $locationId, 'location_id' => $locationId,
'shopping_location_id' => $shoppingLocationId, 'shopping_location_id' => $shoppingLocationId,
'qu_factor_purchase_to_stock' => $stockRow->qu_factor_purchase_to_stock,
'correlation_id' => $correlationId, 'correlation_id' => $correlationId,
'transaction_id' => $transactionId, 'transaction_id' => $transactionId,
'stock_row_id' => $stockRow->id, 'stock_row_id' => $stockRow->id,
@ -528,7 +518,6 @@ class StockService extends BaseService
{ {
$stockCurrentRow = new \stdClass(); $stockCurrentRow = new \stdClass();
$stockCurrentRow->amount = 0; $stockCurrentRow->amount = 0;
$stockCurrentRow->factor_purchase_amount = 0;
$stockCurrentRow->value = 0; $stockCurrentRow->value = 0;
$stockCurrentRow->amount_opened = 0; $stockCurrentRow->amount_opened = 0;
$stockCurrentRow->amount_aggregated = 0; $stockCurrentRow->amount_aggregated = 0;
@ -539,7 +528,6 @@ class StockService extends BaseService
$productLastPurchased = $this->getDatabase()->products_last_purchased()->where('product_id', $productId)->fetch(); $productLastPurchased = $this->getDatabase()->products_last_purchased()->where('product_id', $productId)->fetch();
$lastPurchasedDate = null; $lastPurchasedDate = null;
$lastPrice = null; $lastPrice = null;
$lastQuFactorPurchaseToStock = null;
$lastShoppingLocation = null; $lastShoppingLocation = null;
$avgPrice = null; $avgPrice = null;
$oldestPrice = null; $oldestPrice = null;
@ -547,7 +535,6 @@ class StockService extends BaseService
{ {
$lastPurchasedDate = $productLastPurchased->purchased_date; $lastPurchasedDate = $productLastPurchased->purchased_date;
$lastPrice = $productLastPurchased->price; $lastPrice = $productLastPurchased->price;
$lastQuFactorPurchaseToStock = $productLastPurchased->qu_factor_purchase_to_stock;
$lastShoppingLocation = $productLastPurchased->shopping_location_id; $lastShoppingLocation = $productLastPurchased->shopping_location_id;
$avgPriceRow = $this->getDatabase()->products_average_price()->where('product_id', $productId)->fetch(); $avgPriceRow = $this->getDatabase()->products_average_price()->where('product_id', $productId)->fetch();
if ($avgPriceRow) if ($avgPriceRow)
@ -587,7 +574,6 @@ class StockService extends BaseService
'last_purchased' => $lastPurchasedDate, 'last_purchased' => $lastPurchasedDate,
'last_used' => $productLastUsed, 'last_used' => $productLastUsed,
'stock_amount' => $stockCurrentRow->amount, 'stock_amount' => $stockCurrentRow->amount,
'stock_factor_purchase_amount' => $stockCurrentRow->factor_purchase_amount,
'stock_value' => $stockCurrentRow->value, 'stock_value' => $stockCurrentRow->value,
'stock_amount_opened' => $stockCurrentRow->amount_opened, 'stock_amount_opened' => $stockCurrentRow->amount_opened,
'stock_amount_aggregated' => $stockCurrentRow->amount_aggregated, 'stock_amount_aggregated' => $stockCurrentRow->amount_aggregated,
@ -595,7 +581,6 @@ class StockService extends BaseService
'quantity_unit_purchase' => $quPurchase, 'quantity_unit_purchase' => $quPurchase,
'quantity_unit_stock' => $quStock, 'quantity_unit_stock' => $quStock,
'last_price' => $lastPrice, 'last_price' => $lastPrice,
'last_qu_factor_purchase_to_stock' => $lastQuFactorPurchaseToStock,
'avg_price' => $avgPrice, 'avg_price' => $avgPrice,
'oldest_price' => $oldestPrice, 'oldest_price' => $oldestPrice,
'last_shopping_location_id' => $lastShoppingLocation, 'last_shopping_location_id' => $lastShoppingLocation,
@ -728,7 +713,7 @@ class StockService extends BaseService
$bookingAmount = $newAmount; $bookingAmount = $newAmount;
} }
return $this->AddProduct($productId, $bookingAmount, $bestBeforeDate, self::TRANSACTION_TYPE_INVENTORY_CORRECTION, $purchasedDate, $price, null, $locationId, $shoppingLocationId); return $this->AddProduct($productId, $bookingAmount, $bestBeforeDate, self::TRANSACTION_TYPE_INVENTORY_CORRECTION, $purchasedDate, $price, $locationId, $shoppingLocationId);
} }
elseif ($newAmount < $productDetails->stock_amount + $containerWeight) elseif ($newAmount < $productDetails->stock_amount + $containerWeight)
{ {
@ -964,7 +949,8 @@ class StockService extends BaseService
$correlationId = uniqid(); $correlationId = uniqid();
if ($amount >= $stockEntry->amount) if ($amount >= $stockEntry->amount)
{ // Take the whole stock entry {
// Take the whole stock entry
$logRowForLocationFrom = $this->getDatabase()->stock_log()->createRow([ $logRowForLocationFrom = $this->getDatabase()->stock_log()->createRow([
'product_id' => $stockEntry->product_id, 'product_id' => $stockEntry->product_id,
'amount' => $stockEntry->amount * -1, 'amount' => $stockEntry->amount * -1,
@ -973,7 +959,6 @@ class StockService extends BaseService
'stock_id' => $stockEntry->stock_id, 'stock_id' => $stockEntry->stock_id,
'transaction_type' => self::TRANSACTION_TYPE_TRANSFER_FROM, 'transaction_type' => self::TRANSACTION_TYPE_TRANSFER_FROM,
'price' => $stockEntry->price, 'price' => $stockEntry->price,
'qu_factor_purchase_to_stock' => $stockEntry->qu_factor_purchase_to_stock,
'opened_date' => $stockEntry->opened_date, 'opened_date' => $stockEntry->opened_date,
'location_id' => $stockEntry->location_id, 'location_id' => $stockEntry->location_id,
'correlation_id' => $correlationId, 'correlation_id' => $correlationId,
@ -990,7 +975,6 @@ class StockService extends BaseService
'stock_id' => $stockEntry->stock_id, 'stock_id' => $stockEntry->stock_id,
'transaction_type' => self::TRANSACTION_TYPE_TRANSFER_TO, 'transaction_type' => self::TRANSACTION_TYPE_TRANSFER_TO,
'price' => $stockEntry->price, 'price' => $stockEntry->price,
'qu_factor_purchase_to_stock' => $stockEntry->qu_factor_purchase_to_stock,
'opened_date' => $stockEntry->opened_date, 'opened_date' => $stockEntry->opened_date,
'location_id' => $locationIdTo, 'location_id' => $locationIdTo,
'correlation_id' => $correlationId, 'correlation_id' => $correlationId,
@ -1018,7 +1002,6 @@ class StockService extends BaseService
'stock_id' => $stockEntry->stock_id, 'stock_id' => $stockEntry->stock_id,
'transaction_type' => self::TRANSACTION_TYPE_TRANSFER_FROM, 'transaction_type' => self::TRANSACTION_TYPE_TRANSFER_FROM,
'price' => $stockEntry->price, 'price' => $stockEntry->price,
'qu_factor_purchase_to_stock' => $stockEntry->qu_factor_purchase_to_stock,
'opened_date' => $stockEntry->opened_date, 'opened_date' => $stockEntry->opened_date,
'location_id' => $stockEntry->location_id, 'location_id' => $stockEntry->location_id,
'correlation_id' => $correlationId, 'correlation_id' => $correlationId,
@ -1035,7 +1018,6 @@ class StockService extends BaseService
'stock_id' => $stockEntry->stock_id, 'stock_id' => $stockEntry->stock_id,
'transaction_type' => self::TRANSACTION_TYPE_TRANSFER_TO, 'transaction_type' => self::TRANSACTION_TYPE_TRANSFER_TO,
'price' => $stockEntry->price, 'price' => $stockEntry->price,
'qu_factor_purchase_to_stock' => $stockEntry->qu_factor_purchase_to_stock,
'opened_date' => $stockEntry->opened_date, 'opened_date' => $stockEntry->opened_date,
'location_id' => $locationIdTo, 'location_id' => $locationIdTo,
'correlation_id' => $correlationId, 'correlation_id' => $correlationId,
@ -1056,7 +1038,6 @@ class StockService extends BaseService
'best_before_date' => $newBestBeforeDate, 'best_before_date' => $newBestBeforeDate,
'purchased_date' => $stockEntry->purchased_date, 'purchased_date' => $stockEntry->purchased_date,
'stock_id' => $stockEntry->stock_id, 'stock_id' => $stockEntry->stock_id,
'qu_factor_purchase_to_stock' => $stockEntry->qu_factor_purchase_to_stock,
'price' => $stockEntry->price, 'price' => $stockEntry->price,
'location_id' => $locationIdTo, 'location_id' => $locationIdTo,
'open' => $stockEntry->open, 'open' => $stockEntry->open,
@ -1237,7 +1218,6 @@ class StockService extends BaseService
'best_before_date' => $logRow->best_before_date, 'best_before_date' => $logRow->best_before_date,
'purchased_date' => $logRow->purchased_date, 'purchased_date' => $logRow->purchased_date,
'price' => $logRow->price, 'price' => $logRow->price,
'qu_factor_purchase_to_stock' => $logRow->qu_factor_purchase_to_stock,
'location_id' => $logRow->location_id, 'location_id' => $logRow->location_id,
'open' => $open, 'open' => $open,
'opened_date' => $openedDate 'opened_date' => $openedDate

View File

@ -37,14 +37,14 @@
data-status-filter="overdue" data-status-filter="overdue"
class="error-message status-filter-message responsive-button"></div> class="error-message status-filter-message responsive-button"></div>
<div class="float-right"> <div class="float-right">
<a class="btn btn-sm btn-outline-info d-md-none mt-2" <a class="btn btn-sm btn-outline-info d-md-none mt-1"
data-toggle="collapse" data-toggle="collapse"
href="#table-filter-row" href="#table-filter-row"
role="button"> role="button">
<i class="fas fa-filter"></i> <i class="fas fa-filter"></i>
</a> </a>
<a id="clear-filter-button" <a id="clear-filter-button"
class="btn btn-sm btn-outline-info mt-2" class="btn btn-sm btn-outline-info mt-1"
href="#"> href="#">
{{ $__t('Clear filter') }} {{ $__t('Clear filter') }}
</a> </a>

View File

@ -42,14 +42,14 @@
class="normal-message user-filter-message responsive-button"></div> class="normal-message user-filter-message responsive-button"></div>
@endif @endif
<div class="float-right"> <div class="float-right">
<a class="btn btn-sm btn-outline-info d-md-none mt-2" <a class="btn btn-sm btn-outline-info d-md-none mt-1"
data-toggle="collapse" data-toggle="collapse"
href="#table-filter-row" href="#table-filter-row"
role="button"> role="button">
<i class="fas fa-filter"></i> <i class="fas fa-filter"></i>
</a> </a>
<a id="clear-filter-button" <a id="clear-filter-button"
class="btn btn-sm btn-outline-info mt-2" class="btn btn-sm btn-outline-info mt-1"
href="#"> href="#">
{{ $__t('Clear filter') }} {{ $__t('Clear filter') }}
</a> </a>

View File

@ -15,6 +15,7 @@
@php if(empty($additionalHtmlContextHelp)) { $additionalHtmlContextHelp = ''; } @endphp @php if(empty($additionalHtmlContextHelp)) { $additionalHtmlContextHelp = ''; } @endphp
@php if(!isset($isRequired)) { $isRequired = true; } @endphp @php if(!isset($isRequired)) { $isRequired = true; } @endphp
@php if(!isset($noNameAttribute)) { $noNameAttribute = false; } @endphp @php if(!isset($noNameAttribute)) { $noNameAttribute = false; } @endphp
@php if(empty($contextInfoId)) { $additionalHtmlContextHelp = ''; } @endphp
<div id="group-{{ $id }}" <div id="group-{{ $id }}"
class="form-group {{ $additionalGroupCssClasses }}"> class="form-group {{ $additionalGroupCssClasses }}">
@ -22,7 +23,12 @@
{{ $__t($label) }}&nbsp; {{ $__t($label) }}&nbsp;
<span id="{{ $hintId }}" <span id="{{ $hintId }}"
data-toggle="tooltip" data-toggle="tooltip"
title="{{ $hint }}"></span>{!! $additionalHtmlContextHelp !!}</label> title="{{ $hint }}"></span>{!! $additionalHtmlContextHelp !!}
@if(!empty($contextInfoId))
<span id="{{ $contextInfoId }}"
class="small text-muted"></span>
@endif
</label>
<div class="input-group"> <div class="input-group">
<input {!! <input {!!
$additionalAttributes $additionalAttributes

View File

@ -7,6 +7,7 @@
@php if(empty($additionalHtmlElements)) { $additionalHtmlElements = ''; } @endphp @php if(empty($additionalHtmlElements)) { $additionalHtmlElements = ''; } @endphp
@php if(empty($label)) { $label = 'Amount'; } @endphp @php if(empty($label)) { $label = 'Amount'; } @endphp
@php if(empty($initialQuId)) { $initialQuId = '-1'; } @endphp @php if(empty($initialQuId)) { $initialQuId = '-1'; } @endphp
@php if(!isset($isRequired)) { $isRequired = true; } @endphp
<div class="form-group row {{ $additionalGroupCssClasses }}"> <div class="form-group row {{ $additionalGroupCssClasses }}">
<div class="col"> <div class="col">
@ -29,7 +30,9 @@
<div class="col-sm-7 col-xs-12"> <div class="col-sm-7 col-xs-12">
<label for="qu_id">{{ $__t('Quantity unit') }}</label> <label for="qu_id">{{ $__t('Quantity unit') }}</label>
<select required <select @if($isRequired)
required
@endif
class="form-control input-group-productamountpicker" class="form-control input-group-productamountpicker"
id="qu_id" id="qu_id"
name="qu_id" name="qu_id"

View File

@ -42,8 +42,6 @@
<strong>{{ $__t('Stock amount') }}:</strong> <span id="productcard-product-stock-amount" <strong>{{ $__t('Stock amount') }}:</strong> <span id="productcard-product-stock-amount"
class="locale-number locale-number-quantity-amount"></span> <span id="productcard-product-stock-qu-name"></span> class="locale-number locale-number-quantity-amount"></span> <span id="productcard-product-stock-qu-name"></span>
<span id="productcard-product-stock-factor-purchase-amount"
class="locale-number locale-number-quantity-amount"></span> <span id="productcard-product-stock-factor-purchase-qu-name"></span>
<span id="productcard-product-stock-opened-amount" <span id="productcard-product-stock-opened-amount"
class="small font-italic locale-number locale-number-quantity-amount"></span><br> class="small font-italic locale-number locale-number-quantity-amount"></span><br>
<strong>{{ $__t('Stock value') }}:</strong> <span id="productcard-product-stock-value" <strong>{{ $__t('Stock value') }}:</strong> <span id="productcard-product-stock-value"

View File

@ -6,9 +6,14 @@
@section('title', $__t('Create Barcode')) @section('title', $__t('Create Barcode'))
@endif @endif
@section('viewJsName', 'productbarcodesform') @section('viewJsName', 'productbarcodeform')
@section('content') @section('content')
<script>
Grocy.QuantityUnits = {!! json_encode($quantityUnits) !!};
Grocy.QuantityUnitConversionsResolved = {!! json_encode($quantityUnitConversionsResolved) !!};
</script>
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<div class="title-related-links"> <div class="title-related-links">
@ -27,11 +32,13 @@
<script> <script>
Grocy.EditMode = '{{ $mode }}'; Grocy.EditMode = '{{ $mode }}';
Grocy.EditObjectProduct = {!! json_encode($product) !!};
</script> </script>
@if($mode == 'edit') @if($mode == 'edit')
<script> <script>
Grocy.EditObjectId = {{ $barcode->id }}; Grocy.EditObjectId = {{ $barcode->id }};
Grocy.EditObject = {!! json_encode($barcode) !!};
</script> </script>
@endif @endif
@ -56,21 +63,15 @@
</div> </div>
</div> </div>
@php if($mode == 'edit') { $value = $barcode->qu_factor_purchase_to_stock; } else { $value = 1; } @endphp @php if($mode == 'edit') { $value = $barcode->amount; } else { $value = ''; } @endphp
@include('components.numberpicker', array( @include('components.productamountpicker', array(
'id' => 'qu_factor_purchase_to_stock',
'label' => 'Factor purchase to stock quantity unit',
'min' => '0.' . str_repeat('0', $userSettings['stock_decimal_places_amounts'] - 1) . '1',
'decimals' => $userSettings['stock_decimal_places_amounts'],
'value' => $value, 'value' => $value,
'isRequired' => true, 'isRequired' => false
'invalidFeedback' => $__t('The amount cannot be lower than %s', '1'),
'additionalCssClasses' => 'input-group-qu',
)) ))
@if(GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING) @if(GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING)
<div class="form-group"> <div class="form-group">
<label for="shopping_location_id_id">{{ $__t('Default store') }}</label> <label for="shopping_location_id_id">{{ $__t('Store') }}</label>
<select class="form-control" <select class="form-control"
id="shopping_location_id" id="shopping_location_id"
name="shopping_location_id"> name="shopping_location_id">
@ -78,7 +79,7 @@
@foreach($shoppinglocations as $store) @foreach($shoppinglocations as $store)
<option @if($mode=='edit' <option @if($mode=='edit'
&& &&
$store->id == $product->shopping_location_id) selected="selected" @endif value="{{ $store->id }}">{{ $store->name }}</option> $store->id == $barcode->shopping_location_id) selected="selected" @endif value="{{ $store->id }}">{{ $store->name }}</option>
@endforeach @endforeach
</select> </select>
</div> </div>

View File

@ -298,7 +298,7 @@
'value' => $value, 'value' => $value,
'invalidFeedback' => $__t('This cannot be lower than %s', '0'), 'invalidFeedback' => $__t('This cannot be lower than %s', '0'),
'additionalAttributes' => $additionalAttributes, 'additionalAttributes' => $additionalAttributes,
'hintId' => 'tare_weight_qu_info' 'contextInfoId' => 'tare_weight_qu_info'
)) ))
@php $additionalAttributes = '' @endphp @php $additionalAttributes = '' @endphp
@ -380,82 +380,6 @@
<div class="col-lg-6 col-xs-12 @if($mode == 'create') d-none @endif"> <div class="col-lg-6 col-xs-12 @if($mode == 'create') d-none @endif">
<div class="row"> <div class="row">
<div class="col">
<div class="title-related-links">
<h4>
{{ $__t('QU conversions') }}
</h4>
<button class="btn btn-outline-dark d-md-none mt-2 float-right order-1 order-md-3"
type="button"
data-toggle="collapse"
data-target="#related-links">
<i class="fas fa-ellipsis-v"></i>
</button>
<div class="related-links collapse d-md-flex order-2 width-xs-sm-100"
id="related-links">
<a class="btn btn-outline-primary btn-sm m-1 mt-md-0 mb-md-0 float-right show-as-dialog-link"
href="{{ $U('/quantityunitconversion/new?embedded&product=' . $product->id ) }}">
{{ $__t('Add') }}
</a>
</div>
</div>
<h5 id="qu-conversion-headline-info"
class="text-muted font-italic"></h5>
<table id="qu-conversions-table"
class="table table-sm table-striped nowrap w-100">
<thead>
<tr>
<th class="border-right"></th>
<th>{{ $__t('Factor') }}</th>
<th>{{ $__t('Unit') }}</th>
<th class="d-none">Hidden group</th>
<th class="d-none">Hidden from_qu_id</th>
</tr>
</thead>
<tbody class="d-none">
@if($mode == "edit")
@foreach($quConversions as $quConversion)
@if($quConversion->product_id == $product->id || $quConversion->product_id == null)
<tr>
<td class="fit-content border-right">
<a class="btn btn-sm btn-info show-as-dialog-link @if($quConversion->product_id == null) disabled @endif"
href="{{ $U('/quantityunitconversion/' . $quConversion->id . '?embedded&product=' . $product->id ) }}">
<i class="fas fa-edit"></i>
</a>
<a class="btn btn-sm btn-danger qu-conversion-delete-button @if($quConversion->product_id == null) disabled @endif"
href="#"
data-qu-conversion-id="{{ $quConversion->id }}">
<i class="fas fa-trash"></i>
</a>
</td>
<td>
<span class="locale-number locale-number-quantity-amount">{{ $quConversion->factor }}</span>
</td>
<td>
{{ FindObjectInArrayByPropertyValue($quantityunits, 'id', $quConversion->to_qu_id)->name }}
</td>
<td class="d-none">
@if($quConversion->product_id != null)
{{ $__t('Product overrides') }}
@else
{{ $__t('Default conversions') }}
@endif
</td>
<td class="d-none">
from_qu_id xx{{ $quConversion->from_qu_id }}xx
</td>
</tr>
@endif
@endforeach
@endif
</tbody>
</table>
</div>
</div>
<div class="row mt-5">
<div class="col"> <div class="col">
<div class="title-related-links"> <div class="title-related-links">
<h4> <h4>
@ -485,10 +409,11 @@
<tr> <tr>
<th class="border-right"></th> <th class="border-right"></th>
<th>{{ $__t('Barcode') }}</th> <th>{{ $__t('Barcode') }}</th>
<th>{{ $__t('Factor purchase to stock quantity unit') }}</th>
@if(GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING) @if(GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING)
<th>{{ $__t('Store') }}</th> <th>{{ $__t('Store') }}</th>
@endif @endif
<th>{{ $__t('Quantity unit') }}</th>
<th>{{ $__t('Amount') }}</th>
</tr> </tr>
</thead> </thead>
<tbody class="d-none"> <tbody class="d-none">
@ -513,9 +438,6 @@
<td> <td>
{{ $barcode->barcode }} {{ $barcode->barcode }}
</td> </td>
<td>
<span class="locale-number locale-number-quantity-amount">{{ $barcode->qu_factor_purchase_to_stock }}</span>
</td>
@if(GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING) @if(GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING)
<td id="barcode-shopping-location"> <td id="barcode-shopping-location">
@if (FindObjectInArrayByPropertyValue($shoppinglocations, 'id', $barcode->shopping_location_id) !== null) @if (FindObjectInArrayByPropertyValue($shoppinglocations, 'id', $barcode->shopping_location_id) !== null)
@ -523,6 +445,96 @@
@endif @endif
</td> </td>
@endif @endif
<td>
@if(!empty($barcode->qu_id))
<span class="locale-number locale-number-quantity-amount">{{ FindObjectInArrayByPropertyValue($quantityunits, 'id', $barcode->qu_id)->name }}</span>
@endif
</td>
<td>
@if(!empty($barcode->amount))
{{ $barcode->amount }}
@endif
</td>
</tr>
@endif
@endforeach
@endif
</tbody>
</table>
</div>
</div>
<div class="row mt-5">
<div class="col">
<div class="title-related-links">
<h4>
{{ $__t('QU conversions') }}
</h4>
<button class="btn btn-outline-dark d-md-none mt-2 float-right order-1 order-md-3"
type="button"
data-toggle="collapse"
data-target="#related-links">
<i class="fas fa-ellipsis-v"></i>
</button>
<div class="related-links collapse d-md-flex order-2 width-xs-sm-100"
id="related-links">
<a class="btn btn-outline-primary btn-sm m-1 mt-md-0 mb-md-0 float-right show-as-dialog-link"
href="{{ $U('/quantityunitconversion/new?embedded&product=' . $product->id ) }}">
{{ $__t('Add') }}
</a>
</div>
</div>
<h5 id="qu-conversion-headline-info"
class="text-muted font-italic"></h5>
<table id="qu-conversions-table"
class="table table-sm table-striped nowrap w-100">
<thead>
<tr>
<th class="border-right"></th>
<th>{{ $__t('Quantity unit from') }}</th>
<th>{{ $__t('Quantity unit to') }}</th>
<th>{{ $__t('Factor') }}</th>
<th class="d-none">Hidden group</th>
<th></th>
</tr>
</thead>
<tbody class="d-none">
@if($mode == "edit")
@foreach($quConversions as $quConversion)
@if($quConversion->product_id == $product->id || $quConversion->product_id == null && ($quConversion->product_id != null || $quConversion->from_qu_id == $product->qu_id_purchase || $quConversion->from_qu_id == $product->qu_id_stock || $quConversion->to_qu_id == $product->qu_id_purchase || $quConversion->to_qu_id == $product->qu_id_stock))
<tr>
<td class="fit-content border-right">
<a class="btn btn-sm btn-info show-as-dialog-link @if($quConversion->product_id == null) disabled @endif"
href="{{ $U('/quantityunitconversion/' . $quConversion->id . '?embedded&product=' . $product->id ) }}">
<i class="fas fa-edit"></i>
</a>
<a class="btn btn-sm btn-danger qu-conversion-delete-button @if($quConversion->product_id == null) disabled @endif"
href="#"
data-qu-conversion-id="{{ $quConversion->id }}">
<i class="fas fa-trash"></i>
</a>
</td>
<td>
{{ FindObjectInArrayByPropertyValue($quantityunits, 'id', $quConversion->from_qu_id)->name }}
</td>
<td>
{{ FindObjectInArrayByPropertyValue($quantityunits, 'id', $quConversion->to_qu_id)->name }}
</td>
<td>
<span class="locale-number locale-number-quantity-amount">{{ $quConversion->factor }}</span>
</td>
<td class="d-none">
@if($quConversion->product_id != null)
{{ $__t('Product overrides') }}
@else
{{ $__t('Default conversions') }}
@endif
</td>
<td class="font-italic">
{{ $__t('This means 1 %1$s is the same as %2$s %3$s', FindObjectInArrayByPropertyValue($quantityunits, 'id', $quConversion->from_qu_id)->name, $quConversion->factor, FindObjectInArrayByPropertyValue($quantityunits, 'id', $quConversion->to_qu_id)->name) }}
</td>
</tr> </tr>
@endif @endif
@endforeach @endforeach

View File

@ -94,7 +94,6 @@
<th>{{ $__t('Min. stock amount') }}</th> <th>{{ $__t('Min. stock amount') }}</th>
<th>{{ $__t('QU purchase') }}</th> <th>{{ $__t('QU purchase') }}</th>
<th>{{ $__t('QU stock') }}</th> <th>{{ $__t('QU stock') }}</th>
<th>{{ $__t('QU factor') }}</th>
<th>{{ $__t('Product group') }}</th> <th>{{ $__t('Product group') }}</th>
@include('components.userfields_thead', array( @include('components.userfields_thead', array(
@ -133,9 +132,6 @@
<td> <td>
{{ FindObjectInArrayByPropertyValue($quantityunits, 'id', $product->qu_id_stock)->name }} {{ FindObjectInArrayByPropertyValue($quantityunits, 'id', $product->qu_id_stock)->name }}
</td> </td>
<td>
<span class="locale-number locale-number-quantity-amount">{{ $product->qu_factor_purchase_to_stock }}</span>
</td>
<td> <td>
@if(!empty($product->product_group_id)) {{ FindObjectInArrayByPropertyValue($productGroups, 'id', $product->product_group_id)->name }} @endif @if(!empty($product->product_group_id)) {{ FindObjectInArrayByPropertyValue($productGroups, 'id', $product->product_group_id)->name }} @endif
</td> </td>

View File

@ -103,7 +103,7 @@
'min' => '0.' . str_repeat('0', $userSettings['stock_decimal_places_prices'] - 1) . '1', 'min' => '0.' . str_repeat('0', $userSettings['stock_decimal_places_prices'] - 1) . '1',
'decimals' => $userSettings['stock_decimal_places_prices'], 'decimals' => $userSettings['stock_decimal_places_prices'],
'value' => '', 'value' => '',
'hintId' => 'price-hint', 'contextInfoId' => 'price-hint',
'invalidFeedback' => $__t('The price cannot be lower than %s', '0'), 'invalidFeedback' => $__t('The price cannot be lower than %s', '0'),
'isRequired' => false, 'isRequired' => false,
'additionalGroupCssClasses' => 'mb-1' 'additionalGroupCssClasses' => 'mb-1'
@ -117,7 +117,7 @@
value="unit-price" value="unit-price"
checked> checked>
<label class="form-check-label" <label class="form-check-label"
for="price-type-unit-price">{{ $__t('Price') }}</label> for="price-type-unit-price">{{ $__t('Unit price') }}</label>
</div> </div>
<div class="form-check form-check-inline mb-3"> <div class="form-check form-check-inline mb-3">
<input class="form-check-input" <input class="form-check-input"

View File

@ -51,7 +51,6 @@
<div class="form-group"> <div class="form-group">
<label for="from_qu_id">{{ $__t('Quantity unit from') }}</label> <label for="from_qu_id">{{ $__t('Quantity unit from') }}</label>
<select required <select required
disabled
class="form-control input-group-qu" class="form-control input-group-qu"
id="from_qu_id" id="from_qu_id"
name="from_qu_id"> name="from_qu_id">
@ -89,7 +88,7 @@
'min' => '0.' . str_repeat('0', $userSettings['stock_decimal_places_amounts'] - 1) . '1', 'min' => '0.' . str_repeat('0', $userSettings['stock_decimal_places_amounts'] - 1) . '1',
'decimals' => $userSettings['stock_decimal_places_amounts'], 'decimals' => $userSettings['stock_decimal_places_amounts'],
'value' => $value, 'value' => $value,
'invalidFeedback' => $__t('This cannot be lower than %1$s and must be a valid number with max. %2$s decimal places', '0', '3'), 'invalidFeedback' => $__t('This cannot be lower than %1$s and must be a valid number with max. %2$s decimal places', '0', $userSettings['stock_decimal_places_amounts']),
'additionalHtmlElements' => '<p id="qu-conversion-info" 'additionalHtmlElements' => '<p id="qu-conversion-info"
class="form-text text-info d-none"></p>', class="form-text text-info d-none"></p>',
'additionalCssClasses' => 'input-group-qu' 'additionalCssClasses' => 'input-group-qu'
@ -100,11 +99,7 @@
<input type="hidden" <input type="hidden"
name="create_inverse:skip" name="create_inverse:skip"
value="0"> value="0">
<input @if($mode=='create' <input checked
&&
$product==null)
checked
@endif
class="form-check-input custom-control-input" class="form-check-input custom-control-input"
type="checkbox" type="checkbox"
id="create_inverse" id="create_inverse"
@ -112,9 +107,9 @@
value="1"> value="1">
<label class="form-check-label custom-control-label" <label class="form-check-label custom-control-label"
for="create_inverse">{{ $__t('Create inverse QU conversion') }}</label> for="create_inverse">{{ $__t('Create inverse QU conversion') }}</label>
<span id="qu-conversion-inverse-info"
class="form-text text-info d-none"></span>
</div> </div>
<span id="qu-conversion-inverse-info"
class="form-text text-info d-none"></span>
</div> </div>
@include('components.userfieldsform', array( @include('components.userfieldsform', array(

View File

@ -77,7 +77,7 @@
</div> </div>
@else @else
<div class="float-right"> <div class="float-right">
<button class="btn btn-outline-dark d-md-none mt-2 order-1 order-md-3" <button class="btn btn-outline-dark d-md-none mt-1 order-1 order-md-3"
type="button" type="button"
data-toggle="collapse" data-toggle="collapse"
data-target="#table-filter-row"> data-target="#table-filter-row">
@ -95,7 +95,7 @@
data-status-filter="belowminstockamount" data-status-filter="belowminstockamount"
class="collapse d-md-inline-block normal-message status-filter-message responsive-button @if(!GROCY_FEATURE_FLAG_STOCK) d-none @endif"><span class="d-block d-md-none">{{count($missingProducts)}} <i class="fas fa-exclamation-circle"></i></span><span class="d-none d-md-block">{{ $__n(count($missingProducts), '%s product is below defined min. stock amount', '%s products are below defined min. stock amount') }}</span></div> class="collapse d-md-inline-block normal-message status-filter-message responsive-button @if(!GROCY_FEATURE_FLAG_STOCK) d-none @endif"><span class="d-block d-md-none">{{count($missingProducts)}} <i class="fas fa-exclamation-circle"></i></span><span class="d-none d-md-block">{{ $__n(count($missingProducts), '%s product is below defined min. stock amount', '%s products are below defined min. stock amount') }}</span></div>
<div id="related-links" <div id="related-links"
class="float-right mt-2 collapse d-md-block"> class="float-right mt-1 collapse d-md-block">
<a class="btn btn-primary responsive-button btn-sm mb-1 show-as-dialog-link" <a class="btn btn-primary responsive-button btn-sm mb-1 show-as-dialog-link"
href="{{ $U('/shoppinglistitem/new?embedded&list=' . $selectedShoppingListId) }}"> href="{{ $U('/shoppinglistitem/new?embedded&list=' . $selectedShoppingListId) }}">
{{ $__t('Add item') }} {{ $__t('Add item') }}

View File

@ -48,7 +48,6 @@
<th>{{ $__t('Store') }}</th> <th>{{ $__t('Store') }}</th>
<th>{{ $__t('Price') }}</th> <th>{{ $__t('Price') }}</th>
@endif @endif
<th>{{ $__t('Factor purchase to stock quantity unit') }}</th>
<th>{{ $__t('Purchased date') }}</th> <th>{{ $__t('Purchased date') }}</th>
@include('components.userfields_thead', array( @include('components.userfields_thead', array(
@ -214,9 +213,6 @@
{{ $stockEntry->price }} {{ $stockEntry->price }}
</td> </td>
@endif @endif
<td id="stock-{{ $stockEntry->id }}-qu-factor-purchase-to-stock">
{{ $stockEntry->qu_factor_purchase_to_stock }}
</td>
<td> <td>
<span id="stock-{{ $stockEntry->id }}-purchased-date">{{ $stockEntry->purchased_date }}</span> <span id="stock-{{ $stockEntry->id }}-purchased-date">{{ $stockEntry->purchased_date }}</span>
<time id="stock-{{ $stockEntry->id }}-purchased-date-timeago" <time id="stock-{{ $stockEntry->id }}-purchased-date-timeago"

View File

@ -64,18 +64,6 @@
class="text-small text-info font-italic d-none">' . $__t('Tare weight handling enabled - please weigh the whole container, the amount to be posted will be automatically calculcated') . '</div>' class="text-small text-info font-italic d-none">' . $__t('Tare weight handling enabled - please weigh the whole container, the amount to be posted will be automatically calculcated') . '</div>'
)) ))
@include('components.numberpicker', array(
'id' => 'qu_factor_purchase_to_stock',
'label' => 'Factor purchase to stock quantity unit',
'value' => $stockEntry->qu_factor_purchase_to_stock,
'min' => '0.' . str_repeat('0', $userSettings['stock_decimal_places_amounts'] - 1) . '1',
'decimals' => $userSettings['stock_decimal_places_amounts'],
'invalidFeedback' => $__t('The amount cannot be lower than %s', '1'),
'additionalCssClasses' => 'input-group-qu',
'additionalHtmlElements' => '<p id="qu-conversion-info"
class="form-text text-muted small d-none"></p>'
))
@if(GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING) @if(GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING)
@php @php
if (empty($stockEntry->price)) if (empty($stockEntry->price))
@ -134,10 +122,15 @@
'additionalGroupCssClasses' => 'date-only-datetimepicker' 'additionalGroupCssClasses' => 'date-only-datetimepicker'
)) ))
<div class="checkbox"> <div class="form-group">
<label for="open"> <div class="custom-control custom-checkbox">
<input @if($stockEntry->open == 1) checked @endif type="checkbox" id="open" name="open"> {{ $__t('Opened') }} <input type="hidden"
</label> name="open"
value="1">
<input @if($stockEntry->open == 1) checked @endif class="form-check-input custom-control-input" type="checkbox" id="open" name="open" value="1">
<label class="form-check-label custom-control-label"
for="open">{{ $__t('Opened') }}</label>
</div>
</div> </div>
<button id="save-stockentry-button" <button id="save-stockentry-button"

View File

@ -62,14 +62,14 @@
data-status-filter="belowminstockamount" data-status-filter="belowminstockamount"
class="normal-message status-filter-message responsive-button"></div> class="normal-message status-filter-message responsive-button"></div>
<div class="float-right"> <div class="float-right">
<a class="btn btn-sm btn-outline-info d-md-none mt-2" <a class="btn btn-sm btn-outline-info d-md-none mt-1"
data-toggle="collapse" data-toggle="collapse"
href="#table-filter-row" href="#table-filter-row"
role="button"> role="button">
<i class="fas fa-filter"></i> <i class="fas fa-filter"></i>
</a> </a>
<a id="clear-filter-button" <a id="clear-filter-button"
class="btn btn-sm btn-outline-info mt-2" class="btn btn-sm btn-outline-info mt-1"
href="#"> href="#">
{{ $__t('Clear filter') }} {{ $__t('Clear filter') }}
</a> </a>
@ -308,10 +308,6 @@
class="locale-number locale-number-quantity-amount">{{ $currentStockEntry->amount }}</span> <span id="product-{{ $currentStockEntry->product_id }}-qu-name">{{ $__n($currentStockEntry->amount, $currentStockEntry->qu_unit_name, $currentStockEntry->qu_unit_name_plural) }}</span> class="locale-number locale-number-quantity-amount">{{ $currentStockEntry->amount }}</span> <span id="product-{{ $currentStockEntry->product_id }}-qu-name">{{ $__n($currentStockEntry->amount, $currentStockEntry->qu_unit_name, $currentStockEntry->qu_unit_name_plural) }}</span>
<span id="product-{{ $currentStockEntry->product_id }}-opened-amount" <span id="product-{{ $currentStockEntry->product_id }}-opened-amount"
class="small font-italic">@if($currentStockEntry->amount_opened > 0){{ $__t('%s opened', $currentStockEntry->amount_opened) }}@endif</span> class="small font-italic">@if($currentStockEntry->amount_opened > 0){{ $__t('%s opened', $currentStockEntry->amount_opened) }}@endif</span>
@if($currentStockEntry->amount != $currentStockEntry->factor_purchase_amount)
<span id="product-{{ $currentStockEntry->product_id }}-factor-purchase-amount"
class="locale-number locale-number-quantity-amount">({{ $currentStockEntry->factor_purchase_amount }}</span> <span id="product-{{ $currentStockEntry->product_id }}-qu-purchase-name">{{ $__n($currentStockEntry->factor_purchase_amount, $currentStockEntry->qu_purchase_unit_name,$currentStockEntry->qu_purchase_unit_name_plural) }})</span>
@endif
@if($currentStockEntry->is_aggregated_amount == 1) @if($currentStockEntry->is_aggregated_amount == 1)
<span class="pl-1 text-secondary"> <span class="pl-1 text-secondary">
<i class="fas fa-custom-sigma-sign"></i> <span id="product-{{ $currentStockEntry->product_id }}-amount-aggregated" <i class="fas fa-custom-sigma-sign"></i> <span id="product-{{ $currentStockEntry->product_id }}-amount-aggregated"

View File

@ -44,14 +44,14 @@
data-status-filter="overdue" data-status-filter="overdue"
class="error-message status-filter-message responsive-button"></div> class="error-message status-filter-message responsive-button"></div>
<div class="float-right"> <div class="float-right">
<a class="btn btn-sm btn-outline-info d-md-none mt-2" <a class="btn btn-sm btn-outline-info d-md-none mt-1"
data-toggle="collapse" data-toggle="collapse"
href="#table-filter-row" href="#table-filter-row"
role="button"> role="button">
<i class="fas fa-filter"></i> <i class="fas fa-filter"></i>
</a> </a>
<a id="clear-filter-button" <a id="clear-filter-button"
class="btn btn-sm btn-outline-info mt-2" class="btn btn-sm btn-outline-info mt-1"
href="#"> href="#">
{{ $__t('Clear filter') }} {{ $__t('Clear filter') }}
</a> </a>