mirror of
https://github.com/grocy/grocy.git
synced 2025-08-18 03:25:50 +00:00
Implemented a way to use the external barcode lookup plugin also from within the frontend as a product picker workflow
This commit is contained in:
@@ -123,7 +123,9 @@ Example: Button "**P** Add as new product" can be "pressed" by using the `P` key
|
|||||||
### Barcode lookup via external services
|
### Barcode lookup via external services
|
||||||
|
|
||||||
Products can be directly added to the database via looking them up against external services by a barcode.
|
Products can be directly added to the database via looking them up against external services by a barcode.
|
||||||
This is currently only possible through the REST API.
|
|
||||||
|
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).
|
||||||
|
|
||||||
There is no plugin included for any service, see the reference implementation in `data/plugins/DemoBarcodeLookupPlugin.php`.
|
There is no plugin included for any service, see the reference implementation in `data/plugins/DemoBarcodeLookupPlugin.php`.
|
||||||
|
|
||||||
### Database migrations
|
### Database migrations
|
||||||
|
@@ -10,6 +10,10 @@
|
|||||||
|
|
||||||
### Stock
|
### Stock
|
||||||
|
|
||||||
|
- Added a new product picker workflow "External barcode lookup (via plugin)"
|
||||||
|
- 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 purchase transaction is continued with that product
|
||||||
- Fixed that the location dropdown on the consume page contained the same location multiple times if there are currently stock entries at multiple locations of the corresponding product
|
- Fixed that the location dropdown on the consume page contained the same location multiple times if there are currently stock entries at multiple locations of the corresponding product
|
||||||
- Fixed that the status filter "n products are overdue" on the stock overview page also counted/included stock entries due today or tomorrow
|
- Fixed that the status filter "n products are overdue" on the stock overview page also counted/included stock entries due today or tomorrow
|
||||||
|
|
||||||
|
@@ -442,7 +442,6 @@ class StockApiController extends BaseApiController
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
$addFoundProduct = false;
|
$addFoundProduct = false;
|
||||||
|
|
||||||
if (isset($request->getQueryParams()['add']) && ($request->getQueryParams()['add'] === 'true' || $request->getQueryParams()['add'] === 1))
|
if (isset($request->getQueryParams()['add']) && ($request->getQueryParams()['add'] === 'true' || $request->getQueryParams()['add'] === 1))
|
||||||
{
|
{
|
||||||
$addFoundProduct = true;
|
$addFoundProduct = true;
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
use Grocy\Helpers\BaseBarcodeLookupPlugin;
|
use Grocy\Helpers\BaseBarcodeLookupPlugin;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This class must extend BaseBarcodeLookupPlugin (in namespace \Grocy\Helpers)
|
This class must extend BaseBarcodeLookupPlugin (in namespace Grocy\Helpers)
|
||||||
*/
|
*/
|
||||||
class DemoBarcodeLookupPlugin extends BaseBarcodeLookupPlugin
|
class DemoBarcodeLookupPlugin extends BaseBarcodeLookupPlugin
|
||||||
{
|
{
|
||||||
@@ -14,8 +14,11 @@ class DemoBarcodeLookupPlugin extends BaseBarcodeLookupPlugin
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
To try it:
|
To try it:
|
||||||
|
|
||||||
Call the API function at /api/stock/barcodes/external-lookup/{barcode}
|
Call the API function at /api/stock/barcodes/external-lookup/{barcode}
|
||||||
|
|
||||||
|
Or use the product picker workflow "External barcode lookup (via plugin)"
|
||||||
|
|
||||||
When you also add ?add=true as a query parameter to the API call,
|
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
|
on a successful lookup the product is added to the database and in the output
|
||||||
the new product id is included (automatically, nothing to do here in the plugin)
|
the new product id is included (automatically, nothing to do here in the plugin)
|
||||||
@@ -55,12 +58,14 @@ class DemoBarcodeLookupPlugin extends BaseBarcodeLookupPlugin
|
|||||||
*/
|
*/
|
||||||
protected function ExecuteLookup($barcode)
|
protected function ExecuteLookup($barcode)
|
||||||
{
|
{
|
||||||
if ($barcode === 'x')
|
if ($barcode === 'nothing')
|
||||||
{ // Demonstration when nothing is found
|
{
|
||||||
|
// Demonstration when nothing is found
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
elseif ($barcode === 'e')
|
elseif ($barcode === 'error')
|
||||||
{ // Demonstration when an error occurred
|
{
|
||||||
|
// Demonstration when an error occurred
|
||||||
throw new \Exception('This is the error message from the plugin...');
|
throw new \Exception('This is the error message from the plugin...');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@@ -29,7 +29,8 @@ abstract class BaseBarcodeLookupPlugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!IsAssociativeArray($pluginOutput))
|
if (!IsAssociativeArray($pluginOutput))
|
||||||
{ // $pluginOutput is at least an indexed array here
|
{
|
||||||
|
// $pluginOutput is at least an indexed array here
|
||||||
throw new \Exception('Plugin output must be an associative array');
|
throw new \Exception('Plugin output must be an associative array');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@ abstract class BaseBarcodeLookupPlugin
|
|||||||
|
|
||||||
// $pluginOutput contains all needed properties here
|
// $pluginOutput contains all needed properties here
|
||||||
|
|
||||||
// Check referenced entity ids are valid
|
// Check if referenced entity ids are valid
|
||||||
$locationId = $pluginOutput['location_id'];
|
$locationId = $pluginOutput['location_id'];
|
||||||
if (FindObjectInArrayByPropertyValue($this->Locations, 'id', $locationId) === null)
|
if (FindObjectInArrayByPropertyValue($this->Locations, 'id', $locationId) === null)
|
||||||
{
|
{
|
||||||
|
@@ -2423,3 +2423,12 @@ msgid "This means 1 label will be printed"
|
|||||||
msgid_plural "This means %1$s labels will be printed"
|
msgid_plural "This means %1$s labels will be printed"
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
|
||||||
|
msgid "External barcode lookup (via plugin)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Error while executing the barcode lookup plugin"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Nothing was found for the given barcode"
|
||||||
|
msgstr ""
|
||||||
|
@@ -249,6 +249,32 @@ $('#product_id_text_input').on('blur', function(e)
|
|||||||
Grocy.Components.ProductPicker.PopupOpen = false;
|
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);
|
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)'),
|
||||||
|
className: 'btn-dark add-new-product-plugin-dialog-button responsive-button ' + addProductWorkflowsAdditionalCssClasses,
|
||||||
|
callback: function()
|
||||||
|
{
|
||||||
|
Grocy.Components.ProductPicker.PopupOpen = false;
|
||||||
|
|
||||||
|
Grocy.Api.Get("stock/barcodes/external-lookup/" + encodeURIComponent(input) + "?add=true",
|
||||||
|
function(pluginResponse)
|
||||||
|
{
|
||||||
|
if (pluginResponse == null)
|
||||||
|
{
|
||||||
|
toastr.warning(__t("Nothing was found for the given barcode"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
window.location.href = U("/product/" + pluginResponse.id + "?flow=InplaceNewProductByPlugin&returnto=" + encodeURIComponent(Grocy.CurrentUrlRelative + "?flow=InplaceNewProductWithName&" + embedded) + "&" + embedded);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
function(xhr)
|
||||||
|
{
|
||||||
|
Grocy.FrontendHelpers.ShowGenericError("Error while executing the barcode lookup plugin", xhr.response);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -321,6 +347,10 @@ $('#product_id_text_input').on('blur', function(e)
|
|||||||
{
|
{
|
||||||
$('.retry-camera-scanning-button').not(".d-none").click();
|
$('.retry-camera-scanning-button').not(".d-none").click();
|
||||||
}
|
}
|
||||||
|
if (e.key === 'e' || e.key === 'E')
|
||||||
|
{
|
||||||
|
$('.add-new-product-plugin-dialog-button').not(".d-none").click();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@@ -1702,14 +1702,12 @@ class StockService extends BaseService
|
|||||||
private function LoadBarcodeLookupPlugin()
|
private function LoadBarcodeLookupPlugin()
|
||||||
{
|
{
|
||||||
$pluginName = defined('GROCY_STOCK_BARCODE_LOOKUP_PLUGIN') ? GROCY_STOCK_BARCODE_LOOKUP_PLUGIN : '';
|
$pluginName = defined('GROCY_STOCK_BARCODE_LOOKUP_PLUGIN') ? GROCY_STOCK_BARCODE_LOOKUP_PLUGIN : '';
|
||||||
|
|
||||||
if (empty($pluginName))
|
if (empty($pluginName))
|
||||||
{
|
{
|
||||||
throw new \Exception('No barcode lookup plugin defined');
|
throw new \Exception('No barcode lookup plugin defined');
|
||||||
}
|
}
|
||||||
|
|
||||||
$path = GROCY_DATAPATH . "/plugins/$pluginName.php";
|
$path = GROCY_DATAPATH . "/plugins/$pluginName.php";
|
||||||
|
|
||||||
if (file_exists($path))
|
if (file_exists($path))
|
||||||
{
|
{
|
||||||
require_once $path;
|
require_once $path;
|
||||||
|
Reference in New Issue
Block a user