diff --git a/controllers/StockController.php b/controllers/StockController.php index 6e3a33a1..d42d9a36 100644 --- a/controllers/StockController.php +++ b/controllers/StockController.php @@ -172,6 +172,34 @@ class StockController extends BaseController } } + public function ProductGrocycodeImage(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args) + { + $product = $this->getDatabase()->products($args['productId']); + + $gc = new Grocycode(Grocycode::PRODUCT, $product->id); + $png = (new DatamatrixFactory())->setCode((string) $gc)->getDatamatrixPngData(); + + $isDownload = $request->getQueryParam('download', false); + + if ($isDownload) + { + $response = $response->withHeader('Content-Type', 'application/octet-stream') + ->withHeader('Content-Disposition', 'attachment; filename=grocycode.png') + ->withHeader('Content-Length', strlen($png)) + ->withHeader('Cache-Control', 'no-cache') + ->withHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT'); + } + else + { + $response = $response->withHeader('Content-Type', 'image/png') + ->withHeader('Content-Length', strlen($png)) + ->withHeader('Cache-Control', 'no-cache') + ->withHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT'); + } + $response->getBody()->write($png); + return $response; + } + public function ProductGroupEditForm(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args) { if ($args['productGroupId'] == 'new') @@ -436,11 +464,24 @@ class StockController extends BaseController $gc = new Grocycode(Grocycode::PRODUCT, $stockEntry->product_id, [$stockEntry->stock_id]); $png = (new DatamatrixFactory())->setCode((string) $gc)->getDatamatrixPngData(); - $response = $response->withHeader('Content-Type', 'image/png') + $isDownload = $request->getQueryParam('download', false); + + if ($isDownload) + { + $response = $response->withHeader('Content-Type', 'application/octet-stream') + ->withHeader('Content-Disposition', 'attachment; filename=grocycode.png') ->withHeader('Content-Length', strlen($png)) ->withHeader('Cache-Control', 'no-cache') ->withHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT'); - $response->getBody()->write($png); + } + else + { + $response = $response->withHeader('Content-Type', 'image/png') + ->withHeader('Content-Length', strlen($png)) + ->withHeader('Cache-Control', 'no-cache') + ->withHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT'); + $response->getBody()->write($png); + } return $response; } diff --git a/localization/de/strings.po b/localization/de/strings.po index 66135bc1..048556dd 100644 --- a/localization/de/strings.po +++ b/localization/de/strings.po @@ -2374,3 +2374,18 @@ msgstr "Druckoptionen" msgid "A product or a note is required" msgstr "Ein Produkt oder eine Notiz ist erforderlich" + +msgid "Grocycode" +msgstr "Grocycode" + +msgid "Download" +msgstr "Herunterladen" + +msgid "Download stock entry grocycode" +msgstr "Bestandseingrags-Grocycode herunterladen" + +msgid "Download product grocycode" +msgstr "Produkt-Grocycode herunterladen" + +msgid "Grocycode is a unique referer to this product in your grocy instance. Print it onto a label and scan it like any other barcode!" +msgstr "Grocycode ist eine eindeutige Referenz zu diesem Produkt in dieser Grocy-Instanz. Ausgedruckt kann es wie jeder andere Barcode gescannt werden!" \ No newline at end of file diff --git a/localization/strings.pot b/localization/strings.pot index 6ce941ba..b32ec66d 100644 --- a/localization/strings.pot +++ b/localization/strings.pot @@ -2077,3 +2077,26 @@ msgstr "" msgid "A product or a note is required" msgstr "" + +msgid "Grocycode" +msgstr "" + +msgid "Download" +msgstr "" + +msgid "Download stock entry grocycode" +msgstr "" + +msgid "Download product grocycode" +msgstr "" + +msgid "" +"If enabled, the min. stock amount of sub products will be accumulated into this product, means the sub product will never be \"\n" +"\t\t\t\t\t\t\tmissing\",\n" +"\t\t\t\t\t\t\tonly\n" +"\t\t\t\t\t\t\tthis\n" +"\t\t\t\t\t\t\tproduct" +msgstr "" + +msgid "Grocycode is a unique referer to this product in your grocy instance. Print it onto a label and scan it like any other barcode!" +msgstr "" diff --git a/public/viewjs/components/productcard.js b/public/viewjs/components/productcard.js index f9bf3215..aaa00669 100644 --- a/public/viewjs/components/productcard.js +++ b/public/viewjs/components/productcard.js @@ -23,6 +23,10 @@ Grocy.Components.ProductCard.Refresh = function(productId) } $('#productcard-product-spoil-rate').text((parseFloat(productDetails.spoil_rate_percent) / 100).toLocaleString(undefined, { style: "percent" })); + // grocycode + $("#productcard-product-grocycode-image").attr("src", U('/product/' + productDetails.product.id + '/grocycode')); + $("#productcard-product-grocycode-image-link").attr("href", U('/product/' + productDetails.product.id + '/grocycode?download=true')); + if (productDetails.is_aggregated_amount == 1) { $('#productcard-product-stock-amount-aggregated').text(productDetails.stock_amount_aggregated); diff --git a/routes.php b/routes.php index 8b5dcc23..5a146491 100644 --- a/routes.php +++ b/routes.php @@ -5,8 +5,7 @@ use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use Slim\Routing\RouteCollectorProxy; -$app->group('', function (RouteCollectorProxy $group) -{ +$app->group('', function (RouteCollectorProxy $group) { // System routes $group->get('/', '\Grocy\Controllers\SystemController:Root')->setName('root'); $group->get('/about', '\Grocy\Controllers\SystemController:About'); @@ -41,6 +40,7 @@ $app->group('', function (RouteCollectorProxy $group) $group->get('/quantityunitconversion/{quConversionId}', '\Grocy\Controllers\StockController:QuantityUnitConversionEditForm'); $group->get('/productgroups', '\Grocy\Controllers\StockController:ProductGroupsList'); $group->get('/productgroup/{productGroupId}', '\Grocy\Controllers\StockController:ProductGroupEditForm'); + $group->get('/product/{productId}/grocycode', '\Grocy\Controllers\StockController:ProductGrocycodeImage'); // Stock handling routes if (GROCY_FEATURE_FLAG_STOCK) @@ -140,8 +140,7 @@ $app->group('', function (RouteCollectorProxy $group) $group->get('/manageapikeys/new', '\Grocy\Controllers\OpenApiController:CreateNewApiKey'); }); -$app->group('/api', function (RouteCollectorProxy $group) -{ +$app->group('/api', function (RouteCollectorProxy $group) { // OpenAPI $group->get('/openapi/specification', '\Grocy\Controllers\OpenApiController:DocumentationSpec'); @@ -247,7 +246,6 @@ $app->group('/api', function (RouteCollectorProxy $group) })->add(JsonMiddleware::class); // Handle CORS preflight OPTIONS requests -$app->options('/api/{routes:.+}', function (Request $request, Response $response): Response -{ +$app->options('/api/{routes:.+}', function (Request $request, Response $response): Response { return $response->withStatus(204); }); diff --git a/views/components/productcard.blade.php b/views/components/productcard.blade.php index f159af70..7da09ef9 100644 --- a/views/components/productcard.blade.php +++ b/views/components/productcard.blade.php @@ -55,6 +55,11 @@ @if (GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING){{ $__t('Average price') }}:
@endif @if (GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING){{ $__t('Average shelf life') }}:
@endif {{ $__t('Spoil rate') }}: +

{{ $__t('Grocycode') }}:

{{ $__t('Download') }}

{{ $__t('No price history available') }} @endif - + \ No newline at end of file diff --git a/views/productform.blade.php b/views/productform.blade.php index 144ed05e..7670b324 100644 --- a/views/productform.blade.php +++ b/views/productform.blade.php @@ -25,7 +25,11 @@ @if($mode == 'edit') @if(!empty($product->picture_file_name)) @@ -145,7 +149,12 @@ for="cumulate_min_stock_amount_of_sub_products">{{ $__t('Accumulate sub products min. stock amount') }}   + title="{{ $__t('If enabled, the min. stock amount of sub products will be accumulated into this product, means the sub product will never be " + missing", + only + this + product') + }}"> @@ -426,7 +435,24 @@

-
+ +
+
+ +
+
+ +
-@stop +@stop \ No newline at end of file diff --git a/views/stockentries.blade.php b/views/stockentries.blade.php index a3b4da15..0ea08182 100644 --- a/views/stockentries.blade.php +++ b/views/stockentries.blade.php @@ -185,6 +185,11 @@ href="#"> {{ $__t('Product overview') }} + + {{ $__t('Download stock entry grocycode') }} + @@ -279,4 +284,4 @@
-@stop +@stop \ No newline at end of file diff --git a/views/stockoverview.blade.php b/views/stockoverview.blade.php index 2cb2394b..3d8bf983 100755 --- a/views/stockoverview.blade.php +++ b/views/stockoverview.blade.php @@ -277,6 +277,11 @@ href="#"> {{ $__t('Product overview') }} + + {{ $__t('Download product grocycode') }} + @if($currentStockEntry->product_group_name !== null){{ $currentStockEntry->product_group_name }}@endif - amount }}> + amount }}> {{ $currentStockEntry->amount }} {{ $__n($currentStockEntry->amount, $currentStockEntry->qu_unit_name, $currentStockEntry->qu_unit_name_plural) }} -@stop +@stop \ No newline at end of file