diff --git a/README.md b/README.md index dd3eace5..19ecaf3c 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,9 @@ Example: Button "**P** Add as new product" can be "pressed" by using the `P` key ### Barcode lookup via external services 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`. ### Database migrations diff --git a/changelog/47_2.4.0_2019-05-10.md b/changelog/47_2.4.0_2019-05-10.md index e0cd68b6..25f2b189 100644 --- a/changelog/47_2.4.0_2019-05-10.md +++ b/changelog/47_2.4.0_2019-05-10.md @@ -29,6 +29,6 @@ - Also applies to quantity units, n-plural forms can be entered on the quantity unit edit page - It's not required to install the PHP gettext extension, on both, server and client, managed implementations of gettext are used ([oscarotero/Gettext](https://github.com/oscarotero/Gettext) & [oscarotero/gettext-translator](https://github.com/oscarotero/gettext-translator)) - Some other small fixes and improvements - - The "Add as barcode to existing product" productpicker workflow failed to add the barcode to the given product + - The "Add as barcode to existing product" product picker workflow failed to add the barcode to the given product - Recipes can now be filter by stock availability - Added a feature flag (`config.php` setting) to also be able to hide all stock related UI elements and routes diff --git a/changelog/62_3.1.0_2021-07-16.md b/changelog/62_3.1.0_2021-07-16.md index 0ac29c3d..77f2ebcb 100644 --- a/changelog/62_3.1.0_2021-07-16.md +++ b/changelog/62_3.1.0_2021-07-16.md @@ -64,7 +64,7 @@ - Fixed the form validation on the shopping list item page (thanks @Forceu) - Fixed that when adding products to the shopping list from the stock overview page, the used quantity unit was always the products default purchase QU (and not the selected one) - Fixed that the displayed last unit/total price was wrong when the used quantity unit was not the products stock QU -- Fixed that the "Add as barcode to existing product" productpicker workflow did not work +- Fixed that the "Add as barcode to existing product" product picker workflow did not work ### Recipe improvements/fixes - Recipe printing improvements (thanks @Ape) diff --git a/changelog/65_3.1.3_2021-11-14.md b/changelog/65_3.1.3_2021-11-14.md index 21aefc23..06703e5e 100644 --- a/changelog/65_3.1.3_2021-11-14.md +++ b/changelog/65_3.1.3_2021-11-14.md @@ -5,7 +5,7 @@ - When adding (purchase) a product with "Default due days after freezing" set directly to a freezer location, the due date is now prefilled by that (instead of the normal "Default due days") (thanks @grahamc for the initial work on this) - Chores can now be merged (new item in the context-/more-menu on the chores list page) - Fixed that "Label per unit" stock entry labels (on purchase) weren't unique per unit -- Fixed that the "Add as new product" productpicker workflow, started from the shopping list item form, always selected the default shopping list after finishing the flow +- Fixed that the "Add as new product" product picker workflow, started from the shopping list item form, always selected the default shopping list after finishing the flow - Fixed that when undoing a product opened transaction and when the product has "Default due days after opened" set, the original due date wasn't restored - Fixed that "Track date only"-chores were shown as overdue on the due day on the chores overview page - Fixed that dropdown filters for tables maybe did not work after reordering columns diff --git a/changelog/74_UNRELEASED_xxxx-xx-xx.md b/changelog/74_UNRELEASED_xxxx-xx-xx.md index fb77119b..92739fea 100644 --- a/changelog/74_UNRELEASED_xxxx-xx-xx.md +++ b/changelog/74_UNRELEASED_xxxx-xx-xx.md @@ -10,6 +10,10 @@ ### 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 status filter "n products are overdue" on the stock overview page also counted/included stock entries due today or tomorrow diff --git a/controllers/StockApiController.php b/controllers/StockApiController.php index 0def9cd0..27fd5b26 100644 --- a/controllers/StockApiController.php +++ b/controllers/StockApiController.php @@ -442,7 +442,6 @@ class StockApiController extends BaseApiController try { $addFoundProduct = false; - if (isset($request->getQueryParams()['add']) && ($request->getQueryParams()['add'] === 'true' || $request->getQueryParams()['add'] === 1)) { $addFoundProduct = true; diff --git a/data/plugins/DemoBarcodeLookupPlugin.php b/data/plugins/DemoBarcodeLookupPlugin.php index 7321cc85..56eda3c2 100644 --- a/data/plugins/DemoBarcodeLookupPlugin.php +++ b/data/plugins/DemoBarcodeLookupPlugin.php @@ -3,7 +3,7 @@ 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 { @@ -14,8 +14,11 @@ class DemoBarcodeLookupPlugin extends BaseBarcodeLookupPlugin /* To try it: + 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, 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) @@ -55,12 +58,14 @@ class DemoBarcodeLookupPlugin extends BaseBarcodeLookupPlugin */ protected function ExecuteLookup($barcode) { - if ($barcode === 'x') - { // Demonstration when nothing is found + if ($barcode === 'nothing') + { + // Demonstration when nothing is found return null; } - elseif ($barcode === 'e') - { // Demonstration when an error occurred + elseif ($barcode === 'error') + { + // Demonstration when an error occurred throw new \Exception('This is the error message from the plugin...'); } else diff --git a/helpers/BaseBarcodeLookupPlugin.php b/helpers/BaseBarcodeLookupPlugin.php index 87a10a8e..1978cfeb 100644 --- a/helpers/BaseBarcodeLookupPlugin.php +++ b/helpers/BaseBarcodeLookupPlugin.php @@ -29,7 +29,8 @@ abstract class BaseBarcodeLookupPlugin } 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'); } @@ -53,7 +54,7 @@ abstract class BaseBarcodeLookupPlugin // $pluginOutput contains all needed properties here - // Check referenced entity ids are valid + // Check if referenced entity ids are valid $locationId = $pluginOutput['location_id']; if (FindObjectInArrayByPropertyValue($this->Locations, 'id', $locationId) === null) { diff --git a/localization/strings.pot b/localization/strings.pot index c6fe92a1..92804df8 100644 --- a/localization/strings.pot +++ b/localization/strings.pot @@ -2423,3 +2423,12 @@ msgid "This means 1 label will be printed" msgid_plural "This means %1$s labels will be printed" msgstr[0] "" 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 "" diff --git a/public/viewjs/components/productpicker.js b/public/viewjs/components/productpicker.js index 5bc95d20..f6371792 100644 --- a/public/viewjs/components/productpicker.js +++ b/public/viewjs/components/productpicker.js @@ -249,6 +249,32 @@ $('#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: 'E ' + __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(); } + if (e.key === 'e' || e.key === 'E') + { + $('.add-new-product-plugin-dialog-button').not(".d-none").click(); + } }); } else diff --git a/services/StockService.php b/services/StockService.php index 1e77f4b9..86c0b4f5 100644 --- a/services/StockService.php +++ b/services/StockService.php @@ -1702,14 +1702,12 @@ class StockService extends BaseService private function LoadBarcodeLookupPlugin() { $pluginName = defined('GROCY_STOCK_BARCODE_LOOKUP_PLUGIN') ? GROCY_STOCK_BARCODE_LOOKUP_PLUGIN : ''; - if (empty($pluginName)) { throw new \Exception('No barcode lookup plugin defined'); } $path = GROCY_DATAPATH . "/plugins/$pluginName.php"; - if (file_exists($path)) { require_once $path;