mirror of
https://github.com/grocy/grocy.git
synced 2025-08-16 18:54:35 +00:00
Finalized frontend external barcode lookup implementation (references #158)
This commit is contained in:
@@ -129,11 +129,11 @@ Example: Button "**P** Add as new product" can be "pressed" by using the `P` key
|
||||
|
||||
Products can be directly added to the database via looking them up against external services by a barcode.
|
||||
|
||||
This can be done in-place using the product picker workflow "External barcode lookup (via plugin)" (the workflow dialog is displayed when entering something unknown in any product input field).
|
||||
This can be done in-place using the product picker workflow "External barcode lookup" (the workflow dialog is displayed when entering something unknown in any product input field).
|
||||
|
||||
A plugin for [Open Food Facts](https://world.openfoodfacts.org/) is included and used by default (see the `data/config.php` option `STOCK_BARCODE_LOOKUP_PLUGIN`).
|
||||
|
||||
See that plugin or the reference implementation in `data/plugins/DemoBarcodeLookupPlugin.php` if you want to build a plugin.
|
||||
See that plugin or `plugins/DemoBarcodeLookupPlugin.php` for a commented example implementation if you want to build a plugin.
|
||||
|
||||
### Database migrations
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
- Implemented using [QuaggaJS](https://github.com/serratus/quaggaJS) - camera stream processing happens totally offline / client-side
|
||||
- Please note due to browser security restrictions, this only works when serving Grocy via a secure connection (`https://`)
|
||||
- There is also a `config.php` setting `DISABLE_BROWSER_BARCODE_CAMERA_SCANNING` to disable this, if you don't need it at all (defaults to `false`)
|
||||
- I you have problems that barcodes are not recognized properly, there is a little "barcode scanner testing page" at [/barcodescannertesting](https://demo.grocy.info/barcodescannertesting)
|
||||
- If you have problems that barcodes are not recognized properly, there is a little "barcode scanner testing page" at [/barcodescannertesting](https://demo.grocy.info/barcodescannertesting)
|
||||
- => Quick video demo: https://www.youtube.com/watch?v=Y5YH6IJFnfc
|
||||
|
||||
### Stock improvements/fixes
|
||||
|
@@ -10,7 +10,7 @@
|
||||
|
||||
### Stock
|
||||
|
||||
- Added a new product picker workflow "External barcode lookup (via plugin)"
|
||||
- Added a new product picker workflow "External barcode lookup"
|
||||
- This executes the configured barcode lookup plugin with the given barcode
|
||||
- If the lookup was successful, the product edit page of the created product is displayed, where the product setup can be completed (if required)
|
||||
- After that, the transaction is continued with that product as usual
|
||||
|
@@ -64,8 +64,9 @@ Setting('BASE_PATH', '');
|
||||
Setting('BASE_URL', '/');
|
||||
|
||||
// The plugin to use for external barcode lookups,
|
||||
// must be the filename (folder /data/plugins) without the .php extension,
|
||||
// see /data/plugins/DemoBarcodeLookupPlugin.php for an example implementation
|
||||
// must be the filename (folder "/plugins" for built-in plugins or "/data/plugins" for user plugins) without the .php extension,
|
||||
// see /plugins/DemoBarcodeLookupPlugin.php for a commented example implementation
|
||||
// Leave empty to disable external barcode lookups
|
||||
Setting('STOCK_BARCODE_LOOKUP_PLUGIN', 'OpenFoodFactsBarcodeLookupPlugin');
|
||||
|
||||
// If, however, your webserver does not support URL rewriting, set this to true
|
||||
|
@@ -29,7 +29,7 @@ class BaseController
|
||||
}
|
||||
|
||||
protected $AppContainer;
|
||||
private $View;
|
||||
protected $View;
|
||||
|
||||
protected function getApiKeyService()
|
||||
{
|
||||
|
@@ -4,6 +4,7 @@ namespace Grocy\Controllers;
|
||||
|
||||
use Grocy\Helpers\Grocycode;
|
||||
use Grocy\Services\RecipesService;
|
||||
use DI\Container;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
@@ -11,6 +12,24 @@ class StockController extends BaseController
|
||||
{
|
||||
use GrocycodeTrait;
|
||||
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
|
||||
try
|
||||
{
|
||||
$externalBarcodeLookupPluginName = $this->getStockService()->GetExternalBarcodeLookupPluginName();
|
||||
}
|
||||
catch (\Exception)
|
||||
{
|
||||
$externalBarcodeLookupPluginName = '';
|
||||
}
|
||||
finally
|
||||
{
|
||||
$this->View->set('ExternalBarcodeLookupPluginName', $externalBarcodeLookupPluginName);
|
||||
}
|
||||
}
|
||||
|
||||
public function Consume(Request $request, Response $response, array $args)
|
||||
{
|
||||
return $this->renderPage($response, 'consume', [
|
||||
|
1
data/plugins/.gitignore
vendored
1
data/plugins/.gitignore
vendored
@@ -1,3 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
||||
!DemoBarcodeLookupPlugin.php
|
||||
|
@@ -4,14 +4,19 @@ namespace Grocy\Helpers;
|
||||
|
||||
abstract class BaseBarcodeLookupPlugin
|
||||
{
|
||||
final public function __construct($locations, $quantityUnits)
|
||||
// That's a "self-referencing constant" and forces the child class to define it
|
||||
public const PLUGIN_NAME = self::PLUGIN_NAME;
|
||||
|
||||
final public function __construct($locations, $quantityUnits, $userSettings)
|
||||
{
|
||||
$this->Locations = $locations;
|
||||
$this->QuantityUnits = $quantityUnits;
|
||||
$this->UserSettings = $userSettings;
|
||||
}
|
||||
|
||||
protected $Locations;
|
||||
protected $QuantityUnits;
|
||||
protected $UserSettings;
|
||||
|
||||
final public function Lookup($barcode)
|
||||
{
|
||||
@@ -40,8 +45,8 @@ abstract class BaseBarcodeLookupPlugin
|
||||
'location_id',
|
||||
'qu_id_purchase',
|
||||
'qu_id_stock',
|
||||
'qu_factor_purchase_to_stock',
|
||||
'barcode'
|
||||
'__qu_factor_purchase_to_stock',
|
||||
'__barcode'
|
||||
];
|
||||
|
||||
foreach ($minimunNeededProperties as $prop)
|
||||
@@ -58,25 +63,25 @@ abstract class BaseBarcodeLookupPlugin
|
||||
$locationId = $pluginOutput['location_id'];
|
||||
if (FindObjectInArrayByPropertyValue($this->Locations, 'id', $locationId) === null)
|
||||
{
|
||||
throw new \Exception("Location $locationId is not a valid location id");
|
||||
throw new \Exception("Provided location_id ($locationId) is not a valid location id");
|
||||
}
|
||||
|
||||
$quIdPurchase = $pluginOutput['qu_id_purchase'];
|
||||
if (FindObjectInArrayByPropertyValue($this->QuantityUnits, 'id', $quIdPurchase) === null)
|
||||
{
|
||||
throw new \Exception("Location $quIdPurchase is not a valid quantity unit id");
|
||||
throw new \Exception("Provided qu_id_purchase ($quIdPurchase) is not a valid quantity unit id");
|
||||
}
|
||||
|
||||
$quIdStock = $pluginOutput['qu_id_stock'];
|
||||
if (FindObjectInArrayByPropertyValue($this->QuantityUnits, 'id', $quIdStock) === null)
|
||||
{
|
||||
throw new \Exception("Location $quIdStock is not a valid quantity unit id");
|
||||
throw new \Exception("Provided qu_id_stock ($quIdStock) is not a valid quantity unit id");
|
||||
}
|
||||
|
||||
$quFactor = $pluginOutput['qu_factor_purchase_to_stock'];
|
||||
$quFactor = $pluginOutput['__qu_factor_purchase_to_stock'];
|
||||
if (empty($quFactor) || !is_numeric($quFactor))
|
||||
{
|
||||
throw new \Exception('Quantity unit factor is empty or not a number');
|
||||
throw new \Exception('Provided __qu_factor_purchase_to_stock is empty or not a number');
|
||||
}
|
||||
|
||||
return $pluginOutput;
|
||||
|
@@ -2424,7 +2424,7 @@ msgid_plural "This means %1$s labels will be printed"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "External barcode lookup (via plugin)"
|
||||
msgid "External barcode lookup"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while executing the barcode lookup plugin"
|
||||
|
10
migrations/0240.php
Normal file
10
migrations/0240.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
// This is executed inside DatabaseMigrationService class/context
|
||||
|
||||
// This is now a built-in plugin
|
||||
$filePath = GROCY_DATAPATH . '/plugins/DemoBarcodeLookupPlugin.php';
|
||||
if (file_exists($filePath))
|
||||
{
|
||||
unlink($filePath);
|
||||
}
|
@@ -17,7 +17,7 @@ class DemoBarcodeLookupPlugin extends BaseBarcodeLookupPlugin
|
||||
|
||||
Call the API function at /api/stock/barcodes/external-lookup/{barcode}
|
||||
|
||||
Or use the product picker workflow "External barcode lookup (via plugin)"
|
||||
Or use the product picker workflow "External barcode lookup"
|
||||
|
||||
When you also add ?add=true as a query parameter to the API call,
|
||||
on a successful lookup the product is added to the database and in the output
|
||||
@@ -29,6 +29,7 @@ class DemoBarcodeLookupPlugin extends BaseBarcodeLookupPlugin
|
||||
|
||||
$this->Locations contains all locations
|
||||
$this->QuantityUnits contains all quantity units
|
||||
$this->UserSettings contains all user settings
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -41,12 +42,14 @@ class DemoBarcodeLookupPlugin extends BaseBarcodeLookupPlugin
|
||||
$location = FindObjectInArrayByPropertyValue($this->Locations, 'name', 'Fridge');
|
||||
*/
|
||||
|
||||
// Provide a name
|
||||
public const PLUGIN_NAME = 'Demo';
|
||||
|
||||
/*
|
||||
This class must implement the protected abstract function ExecuteLookup($barcode),
|
||||
which is called with the barcode that needs to be looked up and must return an
|
||||
associative array of the product model or null, when nothing was found for the barcode
|
||||
|
||||
The returned array must be a valid product object (see the "products" database table for all available properties/columns):
|
||||
associative array of the product model (see the "products" database table for all available properties/columns)
|
||||
or null when nothing was found for the barcode:
|
||||
[
|
||||
// Required properties:
|
||||
'name' => '',
|
||||
@@ -54,12 +57,12 @@ class DemoBarcodeLookupPlugin extends BaseBarcodeLookupPlugin
|
||||
'qu_id_purchase' => 1, // A valid id of a quantity unit object, check against $this->QuantityUnits
|
||||
'qu_id_stock' => 1, // A valid id of a quantity unit object, check against $this->QuantityUnits
|
||||
|
||||
// These are virtual properties (not part of the product object, will be automatically handled as needed)
|
||||
'qu_factor_purchase_to_stock' => 1, // Normally 1 when quantity unit stock and purchase is the same
|
||||
'barcode' => $barcode // The barcode of the product, maybe just pass through $barcode or manipulate it if necessary
|
||||
// Required virtual properties (not part of the product object, will be automatically handled as needed):
|
||||
'__qu_factor_purchase_to_stock' => 1, // Normally 1 when quantity unit stock and purchase is the same
|
||||
'__barcode' => $barcode // The barcode of the product, maybe just pass through $barcode or manipulate it if necessary
|
||||
|
||||
// Optional virtual properties
|
||||
'image_url' => '' // When provided, the corresponding image will be downloaded and set as the product picture
|
||||
// Optional virtual properties (not part of the product object, will be automatically handled as needed):
|
||||
'__image_url' => '' // When provided, the corresponding image will be downloaded and set as the product picture
|
||||
]
|
||||
*/
|
||||
protected function ExecuteLookup($barcode)
|
||||
@@ -76,13 +79,27 @@ class DemoBarcodeLookupPlugin extends BaseBarcodeLookupPlugin
|
||||
}
|
||||
else
|
||||
{
|
||||
// Take the preset user setting or otherwise simply the first existing location
|
||||
$locationId = $this->Locations[0]->id;
|
||||
if ($this->UserSettings['product_presets_location_id'] != -1)
|
||||
{
|
||||
$locationId = $this->UserSettings['product_presets_location_id'];
|
||||
}
|
||||
|
||||
// Take the preset user setting or otherwise simply the first existing quantity unit
|
||||
$quId = $this->QuantityUnits[0]->id;
|
||||
if ($this->UserSettings['product_presets_qu_id'] != -1)
|
||||
{
|
||||
$quId = $this->UserSettings['product_presets_qu_id'];
|
||||
}
|
||||
|
||||
return [
|
||||
'name' => 'LookedUpProduct_' . RandomString(5),
|
||||
'location_id' => $this->Locations[0]->id, // Take the first location as a default
|
||||
'qu_id_purchase' => $this->QuantityUnits[0]->id, // Take the first QU as a default
|
||||
'qu_id_stock' => $this->QuantityUnits[0]->id, // Take the first QU as a default
|
||||
'qu_factor_purchase_to_stock' => 1,
|
||||
'barcode' => $barcode
|
||||
'location_id' => $locationId,
|
||||
'qu_id_purchase' => $quId,
|
||||
'qu_id_stock' => $quId,
|
||||
'__qu_factor_purchase_to_stock' => 1,
|
||||
'__barcode' => $barcode
|
||||
];
|
||||
}
|
||||
}
|
@@ -10,10 +10,12 @@ use GuzzleHttp\Client;
|
||||
|
||||
class OpenFoodFactsBarcodeLookupPlugin extends BaseBarcodeLookupPlugin
|
||||
{
|
||||
public const PLUGIN_NAME = 'Open Food Facts';
|
||||
|
||||
protected function ExecuteLookup($barcode)
|
||||
{
|
||||
$webClient = new Client(['http_errors' => false]);
|
||||
$response = $webClient->request('GET', "https://world.openfoodfacts.net/api/v2/product/$barcode?fields=product_name,image_url");
|
||||
$response = $webClient->request('GET', "https://world.openfoodfacts.net/api/v2/product/$barcode?fields=product_name,image_url", ['headers' => ['User-Agent' => 'GrocyOpenFoodFactsBarcodeLookupPlugin/1.0 (https://grocy.info)']]);
|
||||
$statusCode = $response->getStatusCode();
|
||||
|
||||
// Guzzle throws exceptions for connection errors, so nothing to do on that here
|
||||
@@ -32,14 +34,28 @@ class OpenFoodFactsBarcodeLookupPlugin extends BaseBarcodeLookupPlugin
|
||||
$imageUrl = $data->product->image_url;
|
||||
}
|
||||
|
||||
// Take the preset user setting or otherwise simply the first existing location
|
||||
$locationId = $this->Locations[0]->id;
|
||||
if ($this->UserSettings['product_presets_location_id'] != -1)
|
||||
{
|
||||
$locationId = $this->UserSettings['product_presets_location_id'];
|
||||
}
|
||||
|
||||
// Take the preset user setting or otherwise simply the first existing quantity unit
|
||||
$quId = $this->QuantityUnits[0]->id;
|
||||
if ($this->UserSettings['product_presets_qu_id'] != -1)
|
||||
{
|
||||
$quId = $this->UserSettings['product_presets_qu_id'];
|
||||
}
|
||||
|
||||
return [
|
||||
'name' => $data->product->product_name,
|
||||
'location_id' => $this->Locations[0]->id,
|
||||
'qu_id_purchase' => $this->QuantityUnits[0]->id,
|
||||
'qu_id_stock' => $this->QuantityUnits[0]->id,
|
||||
'qu_factor_purchase_to_stock' => 1,
|
||||
'barcode' => $barcode,
|
||||
'image_url' => $imageUrl
|
||||
'location_id' => $locationId,
|
||||
'qu_id_purchase' => $quId,
|
||||
'qu_id_stock' => $quId,
|
||||
'__qu_factor_purchase_to_stock' => 1,
|
||||
'__barcode' => $barcode,
|
||||
'__image_url' => $imageUrl
|
||||
];
|
||||
}
|
||||
}
|
@@ -250,9 +250,13 @@ $('#product_id_text_input').on('blur', function(e)
|
||||
Grocy.Components.ProductPicker.PopupOpen = false;
|
||||
window.location.href = U('/product/new?flow=InplaceNewProductWithBarcode&barcode=' + encodeURIComponent(input) + '&returnto=' + encodeURIComponent(Grocy.CurrentUrlRelative + "?flow=InplaceAddBarcodeToExistingProduct&barcode=" + input + "&" + embedded) + "&" + embedded);
|
||||
}
|
||||
},
|
||||
barcodepluginlookup: {
|
||||
label: '<strong>E</strong> ' + __t('External barcode lookup (via plugin)'),
|
||||
}
|
||||
};
|
||||
|
||||
if (Grocy.ExternalBarcodeLookupPluginName)
|
||||
{
|
||||
buttons.barcodepluginlookup = {
|
||||
label: '<strong>E</strong> ' + __t('External barcode lookup') + ' <span class="badge badge-pill badge-light">' + Grocy.ExternalBarcodeLookupPluginName + '</span>',
|
||||
className: 'btn-dark add-new-product-plugin-dialog-button responsive-button ' + addProductWorkflowsAdditionalCssClasses,
|
||||
callback: function()
|
||||
{
|
||||
@@ -279,8 +283,8 @@ $('#product_id_text_input').on('blur', function(e)
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (!Grocy.FeatureFlags.GROCY_FEATURE_FLAG_DISABLE_BROWSER_BARCODE_CAMERA_SCANNING)
|
||||
{
|
||||
@@ -332,7 +336,8 @@ $('#product_id_text_input').on('blur', function(e)
|
||||
size: 'large',
|
||||
backdrop: true,
|
||||
closeButton: false,
|
||||
buttons: buttons
|
||||
buttons: buttons,
|
||||
className: "wider"
|
||||
}).on('keypress', function(e)
|
||||
{
|
||||
if (e.key === 'B' || e.key === 'b')
|
||||
|
@@ -71,4 +71,9 @@ class BaseService
|
||||
{
|
||||
return FilesService::getInstance();
|
||||
}
|
||||
|
||||
protected function getApplicationService()
|
||||
{
|
||||
return ApplicationService::getInstance();
|
||||
}
|
||||
}
|
||||
|
@@ -220,6 +220,9 @@ class DemoDataGeneratorService extends BaseService
|
||||
INSERT INTO userfield_values (field_id, object_id, value) VALUES (1, 2, '{$this->__t_sql('Example field value...')}');
|
||||
INSERT INTO userfield_values (field_id, object_id, value) VALUES (2, 2, '{$this->__t_sql('Example field value...')}');
|
||||
|
||||
INSERT INTO user_settings(user_id, key, value) VALUES (1, 'product_presets_location_id', '3'); -- Pantry
|
||||
INSERT INTO user_settings(user_id, key, value) VALUES (1, 'product_presets_qu_id', '3'); -- Pack
|
||||
|
||||
INSERT INTO migrations (migration) VALUES (-1);
|
||||
";
|
||||
$this->getDatabaseService()->ExecuteDbStatement($sql);
|
||||
|
@@ -592,9 +592,15 @@ class StockService extends BaseService
|
||||
return $transactionId;
|
||||
}
|
||||
|
||||
public function GetExternalBarcodeLookupPluginName()
|
||||
{
|
||||
$plugin = $this->LoadExternalBarcodeLookupPlugin();
|
||||
return $plugin::PLUGIN_NAME;
|
||||
}
|
||||
|
||||
public function ExternalBarcodeLookup($barcode, $addFoundProduct)
|
||||
{
|
||||
$plugin = $this->LoadBarcodeLookupPlugin();
|
||||
$plugin = $this->LoadExternalBarcodeLookupPlugin();
|
||||
$pluginOutput = $plugin->Lookup($barcode);
|
||||
|
||||
if ($pluginOutput !== null)
|
||||
@@ -602,21 +608,24 @@ class StockService extends BaseService
|
||||
// Lookup was successful
|
||||
if ($addFoundProduct === true)
|
||||
{
|
||||
if ($this->getDatabase()->products()->where('name = :1', $pluginOutput['name'])->fetch() !== null)
|
||||
{
|
||||
throw new \Exception('Product "' . $pluginOutput['name'] . '" already exists');
|
||||
}
|
||||
|
||||
// Add product to database and include new product id in output
|
||||
$productData = $pluginOutput;
|
||||
unset($productData['barcode'], $productData['qu_factor_purchase_to_stock'], $productData['image_url']); // Virtual lookup plugin properties
|
||||
unset($productData['__barcode'], $productData['__qu_factor_purchase_to_stock'], $productData['__image_url']); // Virtual lookup plugin properties
|
||||
|
||||
// Download and save image if provided
|
||||
if (isset($pluginOutput['image_url']) && !empty($pluginOutput['image_url']))
|
||||
if (isset($pluginOutput['__image_url']) && !empty($pluginOutput['__image_url']))
|
||||
{
|
||||
try
|
||||
{
|
||||
$webClient = new Client();
|
||||
$response = $webClient->request('GET', $pluginOutput['image_url']);
|
||||
$fileName = $pluginOutput['barcode'] . '.' . pathinfo($pluginOutput['image_url'], PATHINFO_EXTENSION);
|
||||
$fileHandle = fopen($this->getFilesService()->GetFilePath('productpictures', $fileName), 'wb');
|
||||
fwrite($fileHandle, $response->getBody());
|
||||
fclose($fileHandle);
|
||||
$response = $webClient->request('GET', $pluginOutput['__image_url'], ['headers' => ['User-Agent' => 'Grocy/' . $this->getApplicationService()->GetInstalledVersion()->Version . ' (https://grocy.info)']]);
|
||||
$fileName = $pluginOutput['__barcode'] . '.' . pathinfo($pluginOutput['__image_url'], PATHINFO_EXTENSION);
|
||||
file_put_contents($this->getFilesService()->GetFilePath('productpictures', $fileName), $response->getBody());
|
||||
$productData['picture_file_name'] = $fileName;
|
||||
}
|
||||
catch (\Exception)
|
||||
@@ -630,7 +639,7 @@ class StockService extends BaseService
|
||||
|
||||
$this->getDatabase()->product_barcodes()->createRow([
|
||||
'product_id' => $newProductRow->id,
|
||||
'barcode' => $pluginOutput['barcode']
|
||||
'barcode' => $pluginOutput['__barcode']
|
||||
])->save();
|
||||
|
||||
if ($pluginOutput['qu_id_stock'] != $pluginOutput['qu_id_purchase'])
|
||||
@@ -639,7 +648,7 @@ class StockService extends BaseService
|
||||
'product_id' => $newProductRow->id,
|
||||
'from_qu_id' => $pluginOutput['qu_id_purchase'],
|
||||
'to_qu_id' => $pluginOutput['qu_id_stock'],
|
||||
'factor' => $pluginOutput['qu_factor_purchase_to_stock'],
|
||||
'factor' => $pluginOutput['__qu_factor_purchase_to_stock'],
|
||||
])->save();
|
||||
}
|
||||
|
||||
@@ -1730,7 +1739,7 @@ class StockService extends BaseService
|
||||
}
|
||||
}
|
||||
|
||||
private function LoadBarcodeLookupPlugin()
|
||||
private function LoadExternalBarcodeLookupPlugin()
|
||||
{
|
||||
$pluginName = defined('GROCY_STOCK_BARCODE_LOOKUP_PLUGIN') ? GROCY_STOCK_BARCODE_LOOKUP_PLUGIN : '';
|
||||
if (empty($pluginName))
|
||||
@@ -1738,11 +1747,18 @@ class StockService extends BaseService
|
||||
throw new \Exception('No barcode lookup plugin defined');
|
||||
}
|
||||
|
||||
$path = GROCY_DATAPATH . "/plugins/$pluginName.php";
|
||||
if (file_exists($path))
|
||||
// User plugins take precedence
|
||||
$standardPluginPath = __DIR__ . "/../plugins/$pluginName.php";
|
||||
$userPluginPath = GROCY_DATAPATH . "/plugins/$pluginName.php";
|
||||
if (file_exists($userPluginPath))
|
||||
{
|
||||
require_once $path;
|
||||
return new $pluginName($this->getDatabase()->locations()->where('active = 1')->fetchAll(), $this->getDatabase()->quantity_units()->fetchAll());
|
||||
require_once $userPluginPath;
|
||||
return new $pluginName($this->getDatabase()->locations()->where('active = 1')->fetchAll(), $this->getDatabase()->quantity_units()->where('active = 1')->fetchAll(), $this->getUsersService()->GetUserSettings(GROCY_USER_ID));
|
||||
}
|
||||
elseif (file_exists($standardPluginPath))
|
||||
{
|
||||
require_once $standardPluginPath;
|
||||
return new $pluginName($this->getDatabase()->locations()->where('active = 1')->fetchAll(), $this->getDatabase()->quantity_units()->where('active = 1')->fetchAll(), $this->getUsersService()->GetUserSettings(GROCY_USER_ID));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -4,6 +4,11 @@
|
||||
@push('componentScripts')
|
||||
<script src="{{ $U('/viewjs/components/productpicker.js', true) }}?v={{ $version }}"></script>
|
||||
@endpush
|
||||
@push('componentScripts')
|
||||
<script>
|
||||
Grocy.ExternalBarcodeLookupPluginName = "{{ $ExternalBarcodeLookupPluginName }}";
|
||||
</script>
|
||||
@endpush
|
||||
@endonce
|
||||
|
||||
@php if(empty($disallowAddProductWorkflows)) { $disallowAddProductWorkflows = false; } @endphp
|
||||
|
Reference in New Issue
Block a user