diff --git a/changelog/66_UNRELEASED_xxxx-xx-xx.md b/changelog/66_UNRELEASED_xxxx-xx-xx.md index fe2e3eb6..bbd323e7 100644 --- a/changelog/66_UNRELEASED_xxxx-xx-xx.md +++ b/changelog/66_UNRELEASED_xxxx-xx-xx.md @@ -1,3 +1,4 @@ +- Stock entry labels get now also printed on inventory (only when adding products, same option "Stock entry label" like on the purchase page) - Optimized relative time display (also fixed a phrasing problem for some languages, e.g. Hungarian) (thanks @Tallyrald) - When using LDAP authentication, the configured `LDAP_UID_ATTR` is now used to compare if the user already exists instead of the username entered on the login page (that prevents creating multiple users if you entere the username in different notations) (thanks @FloSet) - Fixed that stock entry labels on purchase were printed, even when "No label" was selected (was only a problem when running label printer WebHooks server side) diff --git a/controllers/StockApiController.php b/controllers/StockApiController.php index 013b1032..e216f32f 100644 --- a/controllers/StockApiController.php +++ b/controllers/StockApiController.php @@ -495,7 +495,13 @@ class StockApiController extends BaseApiController $shoppingLocationId = $requestBody['shopping_location_id']; } - $transactionId = $this->getStockService()->InventoryProduct($args['productId'], $requestBody['new_amount'], $bestBeforeDate, $locationId, $price, $shoppingLocationId, $purchasedDate); + $stockLabelType = 0; + if (array_key_exists('stock_label_type', $requestBody) && is_numeric($requestBody['stock_label_type'])) + { + $stockLabelType = intval($requestBody['stock_label_type']); + } + + $transactionId = $this->getStockService()->InventoryProduct($args['productId'], $requestBody['new_amount'], $bestBeforeDate, $locationId, $price, $shoppingLocationId, $purchasedDate, $stockLabelType); $args['transactionId'] = $transactionId; return $this->StockTransactions($request, $response, $args); } diff --git a/grocy.openapi.json b/grocy.openapi.json index 0c86be19..6a6a8c26 100644 --- a/grocy.openapi.json +++ b/grocy.openapi.json @@ -2180,6 +2180,11 @@ "type": "number", "format": "number", "description": "If omitted, the last price of the product is used (only applies to added products)" + }, + "stock_label_type": { + "type": "number", + "format": "integer", + "description": "`1` = No label, `2` = Single label, `3` = Label per unit (only applies to added products)" } } } diff --git a/public/viewjs/inventory.js b/public/viewjs/inventory.js index a2509295..38e7a6da 100644 --- a/public/viewjs/inventory.js +++ b/public/viewjs/inventory.js @@ -22,6 +22,7 @@ var jsonData = {}; jsonData.new_amount = jsonForm.amount; jsonData.best_before_date = Grocy.Components.DateTimePicker.GetValue(); + jsonData.stock_label_type = jsonForm.stock_label_type; if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING) { jsonData.shopping_location_id = Grocy.Components.ShoppingLocationPicker.GetValue(); @@ -67,6 +68,49 @@ ); } + if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_LABEL_PRINTER && parseFloat($("#display_amount").attr("data-estimated-booking-amount")) > 0) + { + if (Grocy.Webhooks.labelprinter !== undefined) + { + if (jsonForm.stock_label_type == 1) // Single label + { + var webhookData = {}; + webhookData.product = productDetails.product.name; + webhookData.grocycode = 'grcy:p:' + jsonForm.product_id + ":" + result[0].stock_id; + if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING) + { + webhookData.due_date = __t('DD') + ': ' + result[0].best_before_date; + } + + Grocy.FrontendHelpers.RunWebhook(Grocy.Webhooks.labelprinter, webhookData); + } + else if (jsonForm.stock_label_type == 2) // Label per unit + { + Grocy.Api.Get('stock/transactions/' + result[0].transaction_id, + function(stockEntries) + { + stockEntries.forEach(stockEntry => + { + var webhookData = {}; + webhookData.product = productDetails.product.name; + webhookData.grocycode = 'grcy:p:' + jsonForm.product_id + ":" + stockEntry.stock_id; + if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING) + { + webhookData.due_date = __t('DD') + ': ' + result[0].best_before_date; + } + + Grocy.FrontendHelpers.RunWebhook(Grocy.Webhooks.labelprinter, webhookData); + }); + }, + function(xhr) + { + console.error(xhr); + } + ); + } + } + } + Grocy.Api.Get('stock/products/' + jsonForm.product_id, function(result) { @@ -100,6 +144,12 @@ } Grocy.Components.ProductPicker.GetInputElement().focus(); Grocy.Components.ProductCard.Refresh(jsonForm.product_id); + + if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_LABEL_PRINTER) + { + $("#stock_label_type").val(0); + } + Grocy.FrontendHelpers.ValidateForm('inventory-form'); } }, @@ -182,6 +232,11 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e) } } + if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_LABEL_PRINTER) + { + $("#stock_label_type").val(productDetails.product.default_stock_label_type); + } + if (document.getElementById("product_id").getAttribute("barcode") != "null") { Grocy.Api.Get('objects/product_barcodes?query[]=barcode=' + document.getElementById("product_id").getAttribute("barcode"), @@ -303,7 +358,7 @@ Grocy.Components.DateTimePicker.GetInputElement().on('keypress', function(e) $('#display_amount').on('keyup', function(e) { var productId = Grocy.Components.ProductPicker.GetValue(); - var newAmount = parseInt($('#amount').val()); + var newAmount = parseFloat($('#amount').val()); if (productId) { @@ -318,7 +373,9 @@ $('#display_amount').on('keyup', function(e) containerWeight = parseFloat(productDetails.product.tare_weight); } - var estimatedBookingAmount = Math.abs(newAmount - productStockAmount - containerWeight); + var estimatedBookingAmount = (newAmount - productStockAmount - containerWeight).toFixed(Grocy.UserSettings.stock_decimal_places_amounts); + $("#display_amount").attr("data-estimated-booking-amount", estimatedBookingAmount); + estimatedBookingAmount = Math.abs(estimatedBookingAmount); $('#inventory-change-info').removeClass('d-none'); if (productDetails.product.enable_tare_weight_handling == 1 && newAmount < containerWeight) diff --git a/services/StockService.php b/services/StockService.php index 99348050..bfc74aed 100644 --- a/services/StockService.php +++ b/services/StockService.php @@ -855,7 +855,7 @@ class StockService extends BaseService return $this->getDatabase()->stock()->where('id', $entryId)->fetch(); } - public function InventoryProduct(int $productId, float $newAmount, $bestBeforeDate, $locationId = null, $price = null, $shoppingLocationId = null, $purchasedDate = null) + public function InventoryProduct(int $productId, float $newAmount, $bestBeforeDate, $locationId = null, $price = null, $shoppingLocationId = null, $purchasedDate = null, $stockLabelType = 0) { if (!$this->ProductExists($productId)) { @@ -902,7 +902,7 @@ class StockService extends BaseService $bookingAmount = $newAmount; } - return $this->AddProduct($productId, $bookingAmount, $bestBeforeDate, self::TRANSACTION_TYPE_INVENTORY_CORRECTION, $purchasedDate, $price, $locationId, $shoppingLocationId); + return $this->AddProduct($productId, $bookingAmount, $bestBeforeDate, self::TRANSACTION_TYPE_INVENTORY_CORRECTION, $purchasedDate, $price, $locationId, $shoppingLocationId, $unusedTransactionId, $stockLabelType); } elseif ($newAmount < $productDetails->stock_amount + $containerWeight) { diff --git a/views/inventory.blade.php b/views/inventory.blade.php index 82d1ba38..f9cf8d9f 100644 --- a/views/inventory.blade.php +++ b/views/inventory.blade.php @@ -112,6 +112,26 @@ )) @endif + @if(GROCY_FEATURE_FLAG_LABEL_PRINTER) +