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;
}
$object = $this->getDatabase()->{$args['entity']}
($args['objectId']);
$object = $this->getDatabase()->{$args['entity']}($args['objectId']);
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)
{
$objects = $this->getDatabase()->{$args['entity']}
();
$objects = $this->getDatabase()->{$args['entity']}();
$allUserfields = $this->getUserfieldsService()->GetAllValues($args['entity']);
foreach ($objects as $object)
@ -184,13 +182,11 @@ class GenericEntityApiController extends BaseApiController
{
try
{
return $this->FilteredApiResponse($response, $this->getDatabase()->{$args['entity']}
()->where('name LIKE ?', '%' . $args['searchString'] . '%'), $request->getQueryParams());
return $this->FilteredApiResponse($response, $this->getDatabase()->{$args['entity']}(), $request->getQueryParams());
}
catch (\PDOException $ex)
{
throw new HttpBadRequestException($request, $ex->getMessage(), $ex);
//return $this->GenericErrorResponse($response, 'The given entity has no field "name"', $ex);
}
}
else

View File

@ -108,13 +108,6 @@ class StockApiController extends BaseApiController
$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;
if (array_key_exists('transaction_type', $requestBody) && !empty($requestBody['transactiontype']))
@ -122,7 +115,7 @@ class StockApiController extends BaseApiController
$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));
}
catch (\Exception $ex)
@ -372,7 +365,7 @@ class StockApiController extends BaseApiController
$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));
}
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)
{
try

View File

@ -30,7 +30,9 @@ class StockController extends BaseController
'products' => $this->getDatabase()->products()->where('active = 1')->orderBy('name'),
'barcodes' => $productBarcodes,
'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')
{
return $this->renderPage($response, 'productbarcodesform', [
return $this->renderPage($response, 'productbarcodeform', [
'mode' => 'create',
'barcodes' => $this->getDatabase()->product_barcodes()->orderBy('barcode'),
'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
{
return $this->renderPage($response, 'productbarcodesform', [
return $this->renderPage($response, 'productbarcodeform', [
'mode' => 'edit',
'barcode' => $this->getDatabase()->product_barcodes($args['productBarcodeId']),
'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": {
"post": {
"summary": "Adds all missing products for the given recipe to the shopping list",
@ -3940,8 +3889,9 @@
"id": "1",
"product_id": "13",
"barcode": "01321230213",
"qu_factor_purchase_to_stock": "10.0",
"shopping_location_id": "2"
"qu_id": "1",
"shopping_location_id": "2",
"amount": "10"
}
],
"last_purchased": null,
@ -4004,12 +3954,15 @@
"barcode": {
"type": "string"
},
"qu_factor_purchase_to_stock": {
"type": "number",
"format": "number"
"qu_id": {
"type": "integer"
},
"shopping_location_id": {
"type": "integer"
},
"amount": {
"type": "number",
"format": "number"
}
}
},

View File

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

View File

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

View File

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

View File

@ -15,7 +15,6 @@ SELECT
p.name AS product_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,
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_plural FROM quantity_units WHERE quantity_units.id = p.qu_id_purchase) AS qu_purchase_unit_name_plural,
sc.is_aggregated_amount,
@ -26,7 +25,7 @@ FROM (
FROM stock_current
WHERE best_before_date IS NOT NULL
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
WHERE id NOT IN (SELECT product_id FROM stock_current)
) sc
@ -50,7 +49,6 @@ SELECT
p.name AS product_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,
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_plural FROM quantity_units WHERE quantity_units.id = p.qu_id_purchase) AS qu_purchase_unit_name_plural,
sc.is_aggregated_amount,

View File

@ -4,7 +4,6 @@ AS
SELECT
pr.parent_product_id AS product_id,
IFNULL((SELECT SUM(amount) FROM stock WHERE product_id = pr.parent_product_id), 0) AS amount,
IFNULL(ROUND((SELECT SUM(amount / qu_factor_purchase_to_stock) FROM stock WHERE product_id = pr.parent_product_id), 2), 0) as factor_purchase_amount,
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,
MIN(s.best_before_date) AS best_before_date,
@ -33,7 +32,6 @@ UNION
SELECT
pr.sub_product_id AS product_id,
SUM(s.amount) AS amount,
ROUND(SUM(s.amount / s.qu_factor_purchase_to_stock), 2) as factor_purchase_amount,
SUM(s.amount) AS amount_aggregated,
ROUND(SUM(IFNULL(s.price, 0) * s.amount), 2) AS value,
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 {
display: inline-block;
cursor: pointer;
line-height: 0.5;
}
.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);
conversionsForProduct.forEach(conversion =>
{
var factor = conversion.factor;
var factor = parseFloat(conversion.factor);
if (conversion.to_qu_id == destinationQuId)
{
factor = 1;
@ -39,6 +39,15 @@ Grocy.Components.ProductAmountPicker.Reload = function(productId, destinationQuI
$("#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");
}

View File

@ -6,23 +6,12 @@ Grocy.Components.ProductCard.Refresh = function(productId)
function(productDetails)
{
var stockAmount = productDetails.stock_amount || '0';
var stockFactorPurchaseAmount = productDetails.stock_factor_purchase_amount || '0';
var stockValue = productDetails.stock_value || '0';
var stockAmountOpened = productDetails.stock_amount_opened || '0';
$('#productcard-product-name').text(productDetails.product.name);
$('#productcard-product-description').html(productDetails.product.description);
$('#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));
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-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');
@ -95,14 +84,7 @@ Grocy.Components.ProductCard.Refresh = function(productId)
if (productDetails.last_price !== null)
{
if (productDetails.last_qu_factor_purchase_to_stock > 1)
{
$('#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);
}
$('#productcard-product-last-price').text(Number.parseFloat(productDetails.last_price).toLocaleString() + ' ' + Grocy.Currency + ' per ' + productDetails.quantity_unit_stock.name);
}
else
{

View File

@ -48,7 +48,6 @@
var jsonDataBarcode = {};
jsonDataBarcode.barcode = addBarcode;
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,
function(result)

View File

@ -45,7 +45,6 @@
var jsonDataBarcode = {};
jsonDataBarcode.barcode = addBarcode;
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;
Grocy.Api.Post('objects/product_barcodes', jsonDataBarcode,

View File

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

View File

@ -180,11 +180,6 @@ var calendar = $("#calendar").fullCalendar({
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);
var productOrderMissingButtonDisabledClasses = "disabled";
@ -210,7 +205,7 @@ var calendar = $("#calendar").fullCalendar({
var costsAndCaloriesPerServing = ""
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
{

View File

@ -3,6 +3,9 @@
e.preventDefault();
var jsonData = $('#barcode-form').serializeJSON();
jsonData.amount = jsonData.display_amount;
delete jsonData.display_amount;
Grocy.FrontendHelpers.BeginUiBusy("barcode-form");
if (Grocy.EditMode === 'create')
@ -36,12 +39,17 @@
window.parent.postMessage(WindowMessageBag("CloseAllModals"), U("/product/" + GetUriParam("product")));
});
$('#barcode').on('change', function(e)
$('#barcode').on('keyup', function(e)
{
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');
});
@ -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');
$('#barcode').focus();

View File

@ -8,6 +8,12 @@
Grocy.Api.UploadFile($("#product-picture")[0].files[0], 'productpictures', jsonData.picture_file_name,
(result) =>
{
if (Grocy.ProductEditFormRedirectUri == "reload")
{
window.location.reload();
return
}
var returnTo = GetUriParam('returnto');
if (GetUriParam("closeAfterCreation") !== undefined)
{
@ -32,6 +38,12 @@
}
else
{
if (Grocy.ProductEditFormRedirectUri == "reload")
{
window.location.reload();
return
}
var returnTo = GetUriParam('returnto');
if (GetUriParam("closeAfterCreation") !== undefined)
{
@ -145,9 +157,6 @@ $('.input-group-qu').on('change', function(e)
$('#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());
Grocy.FrontendHelpers.ValidateForm('product-form');
@ -301,14 +310,14 @@ if (Grocy.EditMode === 'create')
var quConversionsTable = $('#qu-conversions-table').DataTable({
'order': [[1, 'asc']],
"orderFixed": [[3, 'asc']],
"orderFixed": [[4, 'asc']],
'columnDefs': [
{ 'orderable': false, 'targets': 0 },
{ 'searchable': false, "targets": 0 },
{ 'visible': false, 'targets': 3 }
{ 'visible': false, 'targets': 4 }
],
'rowGroup': {
dataSrc: 3
dataSrc: 4
}
});
$('#qu-conversions-table tbody').removeClass("d-none");

View File

@ -3,7 +3,6 @@
e.preventDefault();
var jsonForm = $('#purchase-form').serializeJSON();
jsonForm.qu_factor_purchase_to_stock = $("#qu_id option:selected").attr("data-qu-factor");
Grocy.FrontendHelpers.BeginUiBusy("purchase-form");
@ -16,14 +15,14 @@
if (!Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING)
{
jsonData.price = 0;
} else
}
else
{
// price is saved as 1 QU to stock
var price = parseFloat(jsonForm.price / jsonForm.qu_factor_purchase_to_stock).toFixed(Grocy.UserSettings.stock_decimal_places_prices);
var price = parseFloat(jsonForm.price * $("#qu_id option:selected").attr("data-qu-factor")).toFixed(Grocy.UserSettings.stock_decimal_places_prices);
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;
}
@ -50,7 +49,6 @@
{
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,
function(result)
@ -66,7 +64,6 @@
var jsonDataBarcode = {};
jsonDataBarcode.barcode = addBarcode;
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;
Grocy.Api.Post('objects/product_barcodes', jsonDataBarcode,
@ -122,6 +119,12 @@
}
Grocy.Components.ProductPicker.GetInputElement().focus();
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');
}
},
@ -155,67 +158,17 @@ if (Grocy.Components.ProductPicker !== undefined)
{
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,
function(productDetails)
{
Grocy.Components.ProductAmountPicker.Reload(productDetails.product.id, productDetails.quantity_unit_stock.id);
Grocy.Components.ProductAmountPicker.SetQuantityUnit(productDetails.quantity_unit_purchase.id);
var qu_factor_purchase_to_stock = 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 (barcode_shopping_location_id != null)
{
Grocy.Components.ShoppingLocationPicker.SetId(barcode_shopping_location_id);
}
else if (productDetails.last_shopping_location_id != null)
if (productDetails.last_shopping_location_id != null)
{
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);
}
$('#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 priceTypeUnitPriceLabel = $("[for=" + priceTypeUnitPrice.attr("id") + "]");
priceTypeUnitPriceLabel.text(productDetails.quantity_unit_purchase.name + " price");
priceTypeUnitPriceLabel.text($("#qu_id option:selected").text() + " " + __t("price"));
refreshPriceHint();
@ -253,7 +206,7 @@ if (Grocy.Components.ProductPicker !== undefined)
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("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 })));
@ -304,6 +257,40 @@ if (Grocy.Components.ProductPicker !== undefined)
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)
{
@ -409,12 +396,7 @@ if (GetUriParam("flow") === "shoppinglistitemtostock")
function refreshPriceHint()
{
if ($('#amount').val() == 0)
{
$('#price-hint').text("");
return;
}
if ($('#price').val() == 0)
if ($('#amount').val() == 0 || $('#price').val() == 0)
{
$('#price-hint').text("");
return;
@ -422,29 +404,14 @@ function refreshPriceHint()
if ($("input[name='price-type']:checked").val() == "total-price")
{
var price = $('#price').val() / $("#qu_id option:selected").attr("data-qu-factor") / $('#amount').val();
var quprice = $('#price').val() / $('#amount').val();
var price = parseFloat($('#price').val() * $("#qu_id option:selected").attr("data-qu-factor")).toFixed(Grocy.UserSettings.stock_decimal_places_prices);
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 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")));
}
$('#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
{
if ($("#qu_id option:selected").attr("data-qu-factor") > 1)
{
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("");
}
$('#price-hint').text("");
}
};
@ -520,3 +487,10 @@ $("#scan-mode-button").on("click", function(e)
$("#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)
{
$('#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');
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');
}
}
@ -196,3 +196,8 @@ Grocy.Components.UserfieldsForm.Load();
$('.input-group-qu').trigger('change');
$('#from_qu_id').focus();
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 + '-qu-factor-purchase-to-stock').text(result.qu_factor_purchase_to_stock);
$('#stock-' + stockRowId + '-purchased-date').text(result.purchased_date);
$('#stock-' + stockRowId + '-purchased-date-timeago').attr('datetime', result.purchased_date + ' 23:59:59');

View File

@ -27,7 +27,6 @@
jsonData.location_id = 1;
}
jsonData.price = price;
jsonData.qu_factor_purchase_to_stock = jsonForm.qu_factor_purchase_to_stock;
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 + '-amount').text(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 + '-next-best-before-date').text(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 = {};
jsonDataBarcode.barcode = addBarcode;
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,
function(result)

View File

@ -203,7 +203,6 @@ $app->group('/api', function (RouteCollectorProxy $group) {
$group->get('/stock/transactions/{transactionId}', '\Grocy\Controllers\StockApiController:StockTransactions');
$group->post('/stock/transactions/{transactionId}/undo', '\Grocy\Controllers\StockApiController:UndoTransaction');
$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/summary', '\Grocy\Controllers\StockApiController:JournalSummary');
}

View File

@ -185,80 +185,80 @@ class DemoDataGeneratorService extends BaseService
$stockTransactionId = uniqid();
$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('-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('-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('-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('-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('-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('-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('-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('-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('-50 days')), $this->RandomPrice(), 1.0, 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('-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('-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('-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('-50 days')), $this->RandomPrice(), 10, 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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-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('-50 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddMissingProductsToShoppingList();
$stockService->OpenProduct(3, 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))
{
@ -88,11 +88,6 @@ class StockService extends BaseService
$productDetails = (object) $this->GetProductDetails($productId);
if ($quFactorPurchaseToStock == null)
{
$quFactorPurchaseToStock = $productDetails->product->qu_factor_purchase_to_stock;
}
// Tare weight handling
// 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
@ -144,7 +139,6 @@ class StockService extends BaseService
'location_id' => $locationId,
'transaction_id' => $transactionId,
'shopping_location_id' => $shoppingLocationId,
'qu_factor_purchase_to_stock' => $quFactorPurchaseToStock,
'user_id' => GROCY_USER_ID
]);
$logRow->save();
@ -160,7 +154,6 @@ class StockService extends BaseService
'price' => $price,
'location_id' => $locationId,
'shopping_location_id' => $shoppingLocationId,
'qu_factor_purchase_to_stock' => $quFactorPurchaseToStock
]);
$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();
@ -364,7 +357,6 @@ class StockService extends BaseService
'opened_date' => $stockRow->opened_date,
'location_id' => $stockRow->location_id,
'shopping_location_id' => $stockRow->shopping_location_id,
'qu_factor_purchase_to_stock' => $stockRow->qu_factor_purchase_to_stock,
'correlation_id' => $correlationId,
'transaction_id' => $transactionId,
'stock_row_id' => $stockRow->id,
@ -391,7 +383,6 @@ class StockService extends BaseService
'shopping_location_id' => $shoppingLocationId,
'opened_date' => $openedDate,
'open' => $open,
'qu_factor_purchase_to_stock' => $quFactorPurchaseToStock,
'purchased_date' => $purchasedDate
]);
@ -406,7 +397,6 @@ class StockService extends BaseService
'opened_date' => $stockRow->opened_date,
'location_id' => $locationId,
'shopping_location_id' => $shoppingLocationId,
'qu_factor_purchase_to_stock' => $stockRow->qu_factor_purchase_to_stock,
'correlation_id' => $correlationId,
'transaction_id' => $transactionId,
'stock_row_id' => $stockRow->id,
@ -528,7 +518,6 @@ class StockService extends BaseService
{
$stockCurrentRow = new \stdClass();
$stockCurrentRow->amount = 0;
$stockCurrentRow->factor_purchase_amount = 0;
$stockCurrentRow->value = 0;
$stockCurrentRow->amount_opened = 0;
$stockCurrentRow->amount_aggregated = 0;
@ -539,7 +528,6 @@ class StockService extends BaseService
$productLastPurchased = $this->getDatabase()->products_last_purchased()->where('product_id', $productId)->fetch();
$lastPurchasedDate = null;
$lastPrice = null;
$lastQuFactorPurchaseToStock = null;
$lastShoppingLocation = null;
$avgPrice = null;
$oldestPrice = null;
@ -547,7 +535,6 @@ class StockService extends BaseService
{
$lastPurchasedDate = $productLastPurchased->purchased_date;
$lastPrice = $productLastPurchased->price;
$lastQuFactorPurchaseToStock = $productLastPurchased->qu_factor_purchase_to_stock;
$lastShoppingLocation = $productLastPurchased->shopping_location_id;
$avgPriceRow = $this->getDatabase()->products_average_price()->where('product_id', $productId)->fetch();
if ($avgPriceRow)
@ -587,7 +574,6 @@ class StockService extends BaseService
'last_purchased' => $lastPurchasedDate,
'last_used' => $productLastUsed,
'stock_amount' => $stockCurrentRow->amount,
'stock_factor_purchase_amount' => $stockCurrentRow->factor_purchase_amount,
'stock_value' => $stockCurrentRow->value,
'stock_amount_opened' => $stockCurrentRow->amount_opened,
'stock_amount_aggregated' => $stockCurrentRow->amount_aggregated,
@ -595,7 +581,6 @@ class StockService extends BaseService
'quantity_unit_purchase' => $quPurchase,
'quantity_unit_stock' => $quStock,
'last_price' => $lastPrice,
'last_qu_factor_purchase_to_stock' => $lastQuFactorPurchaseToStock,
'avg_price' => $avgPrice,
'oldest_price' => $oldestPrice,
'last_shopping_location_id' => $lastShoppingLocation,
@ -728,7 +713,7 @@ class StockService extends BaseService
$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)
{
@ -964,7 +949,8 @@ class StockService extends BaseService
$correlationId = uniqid();
if ($amount >= $stockEntry->amount)
{ // Take the whole stock entry
{
// Take the whole stock entry
$logRowForLocationFrom = $this->getDatabase()->stock_log()->createRow([
'product_id' => $stockEntry->product_id,
'amount' => $stockEntry->amount * -1,
@ -973,7 +959,6 @@ class StockService extends BaseService
'stock_id' => $stockEntry->stock_id,
'transaction_type' => self::TRANSACTION_TYPE_TRANSFER_FROM,
'price' => $stockEntry->price,
'qu_factor_purchase_to_stock' => $stockEntry->qu_factor_purchase_to_stock,
'opened_date' => $stockEntry->opened_date,
'location_id' => $stockEntry->location_id,
'correlation_id' => $correlationId,
@ -990,7 +975,6 @@ class StockService extends BaseService
'stock_id' => $stockEntry->stock_id,
'transaction_type' => self::TRANSACTION_TYPE_TRANSFER_TO,
'price' => $stockEntry->price,
'qu_factor_purchase_to_stock' => $stockEntry->qu_factor_purchase_to_stock,
'opened_date' => $stockEntry->opened_date,
'location_id' => $locationIdTo,
'correlation_id' => $correlationId,
@ -1018,7 +1002,6 @@ class StockService extends BaseService
'stock_id' => $stockEntry->stock_id,
'transaction_type' => self::TRANSACTION_TYPE_TRANSFER_FROM,
'price' => $stockEntry->price,
'qu_factor_purchase_to_stock' => $stockEntry->qu_factor_purchase_to_stock,
'opened_date' => $stockEntry->opened_date,
'location_id' => $stockEntry->location_id,
'correlation_id' => $correlationId,
@ -1035,7 +1018,6 @@ class StockService extends BaseService
'stock_id' => $stockEntry->stock_id,
'transaction_type' => self::TRANSACTION_TYPE_TRANSFER_TO,
'price' => $stockEntry->price,
'qu_factor_purchase_to_stock' => $stockEntry->qu_factor_purchase_to_stock,
'opened_date' => $stockEntry->opened_date,
'location_id' => $locationIdTo,
'correlation_id' => $correlationId,
@ -1056,7 +1038,6 @@ class StockService extends BaseService
'best_before_date' => $newBestBeforeDate,
'purchased_date' => $stockEntry->purchased_date,
'stock_id' => $stockEntry->stock_id,
'qu_factor_purchase_to_stock' => $stockEntry->qu_factor_purchase_to_stock,
'price' => $stockEntry->price,
'location_id' => $locationIdTo,
'open' => $stockEntry->open,
@ -1237,7 +1218,6 @@ class StockService extends BaseService
'best_before_date' => $logRow->best_before_date,
'purchased_date' => $logRow->purchased_date,
'price' => $logRow->price,
'qu_factor_purchase_to_stock' => $logRow->qu_factor_purchase_to_stock,
'location_id' => $logRow->location_id,
'open' => $open,
'opened_date' => $openedDate

View File

@ -37,14 +37,14 @@
data-status-filter="overdue"
class="error-message status-filter-message responsive-button"></div>
<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"
href="#table-filter-row"
role="button">
<i class="fas fa-filter"></i>
</a>
<a id="clear-filter-button"
class="btn btn-sm btn-outline-info mt-2"
class="btn btn-sm btn-outline-info mt-1"
href="#">
{{ $__t('Clear filter') }}
</a>

View File

@ -42,14 +42,14 @@
class="normal-message user-filter-message responsive-button"></div>
@endif
<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"
href="#table-filter-row"
role="button">
<i class="fas fa-filter"></i>
</a>
<a id="clear-filter-button"
class="btn btn-sm btn-outline-info mt-2"
class="btn btn-sm btn-outline-info mt-1"
href="#">
{{ $__t('Clear filter') }}
</a>

View File

@ -15,6 +15,7 @@
@php if(empty($additionalHtmlContextHelp)) { $additionalHtmlContextHelp = ''; } @endphp
@php if(!isset($isRequired)) { $isRequired = true; } @endphp
@php if(!isset($noNameAttribute)) { $noNameAttribute = false; } @endphp
@php if(empty($contextInfoId)) { $additionalHtmlContextHelp = ''; } @endphp
<div id="group-{{ $id }}"
class="form-group {{ $additionalGroupCssClasses }}">
@ -22,7 +23,12 @@
{{ $__t($label) }}&nbsp;
<span id="{{ $hintId }}"
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">
<input {!!
$additionalAttributes

View File

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

View File

@ -42,8 +42,6 @@
<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>
<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"
class="small font-italic locale-number locale-number-quantity-amount"></span><br>
<strong>{{ $__t('Stock value') }}:</strong> <span id="productcard-product-stock-value"

View File

@ -6,9 +6,14 @@
@section('title', $__t('Create Barcode'))
@endif
@section('viewJsName', 'productbarcodesform')
@section('viewJsName', 'productbarcodeform')
@section('content')
<script>
Grocy.QuantityUnits = {!! json_encode($quantityUnits) !!};
Grocy.QuantityUnitConversionsResolved = {!! json_encode($quantityUnitConversionsResolved) !!};
</script>
<div class="row">
<div class="col">
<div class="title-related-links">
@ -27,11 +32,13 @@
<script>
Grocy.EditMode = '{{ $mode }}';
Grocy.EditObjectProduct = {!! json_encode($product) !!};
</script>
@if($mode == 'edit')
<script>
Grocy.EditObjectId = {{ $barcode->id }};
Grocy.EditObject = {!! json_encode($barcode) !!};
</script>
@endif
@ -56,21 +63,15 @@
</div>
</div>
@php if($mode == 'edit') { $value = $barcode->qu_factor_purchase_to_stock; } else { $value = 1; } @endphp
@include('components.numberpicker', 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'],
@php if($mode == 'edit') { $value = $barcode->amount; } else { $value = ''; } @endphp
@include('components.productamountpicker', array(
'value' => $value,
'isRequired' => true,
'invalidFeedback' => $__t('The amount cannot be lower than %s', '1'),
'additionalCssClasses' => 'input-group-qu',
'isRequired' => false
))
@if(GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING)
<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"
id="shopping_location_id"
name="shopping_location_id">
@ -78,7 +79,7 @@
@foreach($shoppinglocations as $store)
<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
</select>
</div>

View File

@ -298,7 +298,7 @@
'value' => $value,
'invalidFeedback' => $__t('This cannot be lower than %s', '0'),
'additionalAttributes' => $additionalAttributes,
'hintId' => 'tare_weight_qu_info'
'contextInfoId' => 'tare_weight_qu_info'
))
@php $additionalAttributes = '' @endphp
@ -380,82 +380,6 @@
<div class="col-lg-6 col-xs-12 @if($mode == 'create') d-none @endif">
<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="title-related-links">
<h4>
@ -485,10 +409,11 @@
<tr>
<th class="border-right"></th>
<th>{{ $__t('Barcode') }}</th>
<th>{{ $__t('Factor purchase to stock quantity unit') }}</th>
@if(GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING)
<th>{{ $__t('Store') }}</th>
@endif
<th>{{ $__t('Quantity unit') }}</th>
<th>{{ $__t('Amount') }}</th>
</tr>
</thead>
<tbody class="d-none">
@ -513,9 +438,6 @@
<td>
{{ $barcode->barcode }}
</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)
<td id="barcode-shopping-location">
@if (FindObjectInArrayByPropertyValue($shoppinglocations, 'id', $barcode->shopping_location_id) !== null)
@ -523,6 +445,96 @@
@endif
</td>
@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>
@endif
@endforeach

View File

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

View File

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

View File

@ -51,7 +51,6 @@
<div class="form-group">
<label for="from_qu_id">{{ $__t('Quantity unit from') }}</label>
<select required
disabled
class="form-control input-group-qu"
id="from_qu_id"
name="from_qu_id">
@ -89,7 +88,7 @@
'min' => '0.' . str_repeat('0', $userSettings['stock_decimal_places_amounts'] - 1) . '1',
'decimals' => $userSettings['stock_decimal_places_amounts'],
'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"
class="form-text text-info d-none"></p>',
'additionalCssClasses' => 'input-group-qu'
@ -100,11 +99,7 @@
<input type="hidden"
name="create_inverse:skip"
value="0">
<input @if($mode=='create'
&&
$product==null)
checked
@endif
<input checked
class="form-check-input custom-control-input"
type="checkbox"
id="create_inverse"
@ -112,9 +107,9 @@
value="1">
<label class="form-check-label custom-control-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>
<span id="qu-conversion-inverse-info"
class="form-text text-info d-none"></span>
</div>
@include('components.userfieldsform', array(

View File

@ -77,7 +77,7 @@
</div>
@else
<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"
data-toggle="collapse"
data-target="#table-filter-row">
@ -95,7 +95,7 @@
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>
<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"
href="{{ $U('/shoppinglistitem/new?embedded&list=' . $selectedShoppingListId) }}">
{{ $__t('Add item') }}

View File

@ -48,7 +48,6 @@
<th>{{ $__t('Store') }}</th>
<th>{{ $__t('Price') }}</th>
@endif
<th>{{ $__t('Factor purchase to stock quantity unit') }}</th>
<th>{{ $__t('Purchased date') }}</th>
@include('components.userfields_thead', array(
@ -214,9 +213,6 @@
{{ $stockEntry->price }}
</td>
@endif
<td id="stock-{{ $stockEntry->id }}-qu-factor-purchase-to-stock">
{{ $stockEntry->qu_factor_purchase_to_stock }}
</td>
<td>
<span id="stock-{{ $stockEntry->id }}-purchased-date">{{ $stockEntry->purchased_date }}</span>
<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>'
))
@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)
@php
if (empty($stockEntry->price))
@ -134,10 +122,15 @@
'additionalGroupCssClasses' => 'date-only-datetimepicker'
))
<div class="checkbox">
<label for="open">
<input @if($stockEntry->open == 1) checked @endif type="checkbox" id="open" name="open"> {{ $__t('Opened') }}
</label>
<div class="form-group">
<div class="custom-control custom-checkbox">
<input type="hidden"
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>
<button id="save-stockentry-button"

View File

@ -62,14 +62,14 @@
data-status-filter="belowminstockamount"
class="normal-message status-filter-message responsive-button"></div>
<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"
href="#table-filter-row"
role="button">
<i class="fas fa-filter"></i>
</a>
<a id="clear-filter-button"
class="btn btn-sm btn-outline-info mt-2"
class="btn btn-sm btn-outline-info mt-1"
href="#">
{{ $__t('Clear filter') }}
</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>
<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>
@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)
<span class="pl-1 text-secondary">
<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"
class="error-message status-filter-message responsive-button"></div>
<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"
href="#table-filter-row"
role="button">
<i class="fas fa-filter"></i>
</a>
<a id="clear-filter-button"
class="btn btn-sm btn-outline-info mt-2"
class="btn btn-sm btn-outline-info mt-1"
href="#">
{{ $__t('Clear filter') }}
</a>