Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add POReceiveBarcodeHandler to support barcode/po-receive/ endpoint #421

Merged
merged 7 commits into from
Oct 19, 2023

Conversation

30350n
Copy link
Contributor

@30350n 30350n commented Sep 11, 2023

This adds the barcode handler for scanning received parts, implementing the new api endpoint from inventree #5509.

There's 3 different places in which the barcode action gets added:

  1. Purchase Order List (purchase order has to be detected from barcode)
  2. Purchase Order Detail
  3. Stock Location (purchase order has to be detected from barcode), for quickly scanning multiple items into a specific location

@30350n
Copy link
Contributor Author

30350n commented Sep 11, 2023

Oh also, probably doesn't exactly belong here, but why did the minSDKVersion get bumped to Android 10 exactly? ^^
I pulled from master before committing and pulled my hair out for half an hour because the App wouldn't install anymore, before realizing it was my phones version...

Copy link
Member

@SchrodingersGat SchrodingersGat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@30350n this is really well implemented, very nicely done! Will compile and test myself in the next couple of days

lib/barcode/handler.dart Show resolved Hide resolved
lib/l10n/de_DE/app_de_DE.arb Outdated Show resolved Hide resolved
@30350n 30350n force-pushed the api_barcode_po_receive branch from 2c26b28 to 8243299 Compare September 14, 2023 22:23
@30350n
Copy link
Contributor Author

30350n commented Sep 14, 2023

@30350n this is really well implemented, very nicely done! Will compile and test myself in the next couple of days

Thanks a lot! I've been using it a bunch the last days, scanning through a box of old digikey parts and it's been working great for me! (Currently working on mouser and lcsc support for my part importer, so I can go through the rest of that box aswell ^^)
You can really scan in parts rather quickly, especially if you've set up a default location for the part category the part is in or are using the "Scan Received Parts into Location" feature.

I really like how the barcode scanner also just keeps being open, only annoying thing is that, atleast for me it still turns my phones screen of after 30s (in the camera app, it stays on forever I think, not sure if that's possible to implement here aswell).

@SchrodingersGat
Copy link
Member

I really like how the barcode scanner also just keeps being open, only annoying thing is that, atleast for me it still turns my phones screen of after 30s (in the camera app, it stays on forever I think, not sure if that's possible to implement here aswell).

Worth looking into. I am sure there is a way to keep the screen on.

@SchrodingersGat
Copy link
Member

As the app can be pointing to an older version of the server (which does not support this functionality) you will need to hide the scanning actions if the server API version is below a minimum version (as specified in your other PR).

Check out api.dart where we have functions such as "supportsFeatureX()". Please implement something similar, to hide your new barcode actions if the server is not new enough to support them :)

@30350n 30350n force-pushed the api_barcode_po_receive branch from 0708ce4 to 6146ddc Compare September 15, 2023 15:38
@30350n
Copy link
Contributor Author

30350n commented Sep 15, 2023

Done! Bumped the API version to 135 in #5509 and added checks for it here :)

Copy link
Member

@SchrodingersGat SchrodingersGat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@30350n the app side of the equation is working really well :) just one small change to the barcode overlay

lib/barcode/barcode.dart Show resolved Hide resolved
Copy link
Member

@SchrodingersGat SchrodingersGat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! Once the changes are made to the InvenTree code I'll merge this in :)

The "quantity" field is not an integer, and can cause the app to crash if not handled correctly
@SchrodingersGat
Copy link
Member

@30350n I had to make a slight tweak here, was crashing due to incompatible field types (int? vs double?)

@30350n
Copy link
Contributor Author

30350n commented Oct 18, 2023

Ah yeah, thanks! I still think of quantity as an int somehow 😅

@SchrodingersGat SchrodingersGat merged commit 67fd6a5 into inventree:master Oct 19, 2023
1 check passed
@HannesMorre
Copy link

@30350n I saw this issue in the release notes and was really excited to try it out, but unfortunately cannot get it to work on my setup. Can you tell me the steps to execute to get this working?

@30350n
Copy link
Contributor Author

30350n commented Jan 5, 2024

Sorry for the late answer. To make this work, you basically just need a placed purchase order containing various supplier parts. Then use the Scan Received Parts feature in the app to scan the barcodes of the parts you received.

Can you describe how/why you "cannot get it to work on your setup"?

@HannesMorre
Copy link

Where do I find the Scan Received Parts option?
Do I need the latest Inventree server version for this to work?

@30350n
Copy link
Contributor Author

30350n commented Jan 16, 2024

It's in a few different places.

You can use the Barcode Action from the Purchase Order Section, but then you'll have to specify the Location manually for each part you scan.

If you don't want to do this, you can navigate to the Stock Location first (by scanning a barcode for example) and then use the Scan Received Parts Barcode Action from there. That way the parts will be automatically added to that stock location.

If the App fails to match a purchase order from the barcode (there's been some recent improvements here which aren't released yet afaik), then you can also use the Scan Received Parts Barcode Action from a specific purchase order (i.e. from the PurchaseOrderDetail screen). In that case you'll have to specify the location again though.

Do I need the latest Inventree server version for this to work?

Afaik you need 0.13 atleast.

@HannesMorre
Copy link

@30350n This is still not working for me. When I try to scan the 2d matrix on the digikey label, I get the "No match for barcode" notification. What am I doing wrong and how can I fix it?
all plugins are enabled
image
and the digikey supplier id is correct
image
Also the po number is the same as on the package.

@SchrodingersGat
Copy link
Member

@HannesMorre are you certain that the InvenTree SKU matches the Digikey part number exactly?

@30350n
Copy link
Contributor Author

30350n commented Sep 14, 2024

It would also make this much easier if you could provide a picture of the barcode you are trying to scan, as well as a screenshot of the Part page of the part you are trying to scan.

@HannesMorre
Copy link

Here is the package:
IMG_2661

The purchase order with that specific part on inventree:
image

The supplier integration plugin with correct supplier id:
image

This is the data scanned with the built-in scanner of the mobile device we are using:
[)>06PBH2AAPC-4-ND1PBH2AAPC-430PBH2AAPC-4-NDKPOR24-004131K8858870510K1070259609D1T11K14LTWQ511ZPICK12Z109903213Z99999920Z000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

I just found out that when we use the camera of the mobile device, this functionality works, but when we use the built-in scanner, it does not work. Could you please investigate why the scanner is not working? If you need more info for this, please let me know.

@SchrodingersGat
Copy link
Member

I just found out that when we use the camera of the mobile device, this functionality works, but when we use the built-in scanner, it does not work. Could you please investigate why the scanner is not working? If you need more info for this, please let me know.

Ok so this is a critical piece of information.

  • What do you mean by "built in scanner"
  • Are you running the InvenTree app on a dedicated barcode scanner running android?
  • Or are you scanning using the web interface?

@HannesMorre
Copy link

We have 2 devices to scan all kinds of barcodes:

  • PointMobile PM85: This one has a built in scanner, I don't know how else to describe it.
  • A tablet with a ProGlove connected to it. We use this one all the time for all scans we do in our warehouse without any problems. Also all qr codes generated from Inventree can be scanned correctly, but the POR receiving does not work.

We are scanning using the Inventree app on these android devices.

@30350n
Copy link
Contributor Author

30350n commented Sep 16, 2024

@SchrodingersGat this feels kinda like some kind of space padding issue that occurs when using the wedge scanning mode.

My guess is the barcode_data probably has a trailing \n when using wedge scanning.

Nvm, seems like past me already accounted for that.

Could it be some non whitespace character?

@HannesMorre Easiest way for us to debug this further would be if you'd change your log_level to DEBUG in your inventree config file, then try to receive a barcode with the wedge/hardware scanning mode and look for BarcodePOReceive: scanned barcode - in the logs.

Repeat this while scanning with the camera (which should be working if I understand correctly) and share both log sections here.

@HannesMorre
Copy link

I scanned with the hardware/wedge scanner first and then with the camera. These are the logs:

inventree-server  | [2024-09-16 16:03:57 +0200] [149] [DEBUG] POST /api/barcode/po-receive/
inventree-server  | BarcodePOReceive: scanned barcode - '[)>06PBH2AAPC-4-ND1PBH2AAPC-430PBH2AAPC-4-NDKPOR24-004131K8858870510K1070259609D1T11K14LTWQ511ZPICK12Z109903213Z99999920Z000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
inventree-server  | Checking plugin registry hash
inventree-server  | Checking plugin registry hash
inventree-server  | Bad Request: /api/barcode/po-receive/
inventree-server  | 172.16.224.30 - - [16/Sep/2024:16:03:57 +0200] "POST /api/barcode/po-receive/ HTTP/1.0" 400 342 "-" "Dart/3.1 (dart:io)"
inventree-server  | [2024-09-16 16:03:57 +0200] [149] [DEBUG] Closing connection.
inventree-server  | [2024-09-16 16:03:59 +0200] [146] [DEBUG] GET /api/order/po/337/
inventree-server  | 172.16.224.30 - - [16/Sep/2024:16:03:59 +0200] "GET /api/order/po/337/?supplier_detail=true HTTP/1.0" 200 802 "-" "Dart/3.1 (dart:io)"
inventree-server  | [2024-09-16 16:03:59 +0200] [146] [DEBUG] Closing connection.
inventree-server  | [2024-09-16 16:03:59 +0200] [148] [DEBUG] GET /api/order/po-line/
inventree-server  | 172.16.224.30 - - [16/Sep/2024:16:03:59 +0200] "GET /api/order/po-line/?part_detail=true&order=337 HTTP/1.0" 200 49175 "-" "Dart/3.1 (dart:io)"
inventree-server  | [2024-09-16 16:03:59 +0200] [148] [DEBUG] Closing connection.
inventree-server  | [2024-09-16 16:03:59 +0200] [149] [DEBUG] GET /api/order/po/attachment/
inventree-server  | 172.16.224.30 - - [16/Sep/2024:16:03:59 +0200] "GET /api/order/po/attachment/?order=337&limit=1 HTTP/1.0" 200 52 "-" "Dart/3.1 (dart:io)"
inventree-server  | [2024-09-16 16:03:59 +0200] [149] [DEBUG] Closing connection.
inventree-server  | [2024-09-16 16:04:00 +0200] [148] [DEBUG] GET /api/notifications/
inventree-server  | 172.16.224.30 - - [16/Sep/2024:16:04:00 +0200] "GET /api/notifications/?read=false&limit=1 HTTP/1.0" 200 52 "-" "Dart/3.1 (dart:io)"
inventree-server  | [2024-09-16 16:04:00 +0200] [148] [DEBUG] Closing connection.
inventree-server  | [2024-09-16 16:04:05 +0200] [146] [DEBUG] GET /api/notifications/
inventree-server  | 172.16.224.30 - - [16/Sep/2024:16:04:05 +0200] "GET /api/notifications/?read=false&limit=1 HTTP/1.0" 200 52 "-" "Dart/3.1 (dart:io)"
inventree-server  | [2024-09-16 16:04:05 +0200] [146] [DEBUG] Closing connection.
inventree-server  | [2024-09-16 16:04:10 +0200] [149] [DEBUG] GET /api/notifications/
inventree-server  | 172.16.224.30 - - [16/Sep/2024:16:04:10 +0200] "GET /api/notifications/?read=false&limit=1 HTTP/1.0" 200 52 "-" "Dart/3.1 (dart:io)"
inventree-server  | [2024-09-16 16:04:10 +0200] [149] [DEBUG] Closing connection.
inventree-server  | [2024-09-16 16:04:11 +0200] [149] [DEBUG] POST /api/barcode/po-receive/
inventree-server  | BarcodePOReceive: scanned barcode - '[)>�06�PBH2AAPC-4-ND�1PBH2AAPC-4�30PBH2AAPC-4-ND�KPOR24-00413�1K88588705�10K107025960�9D�1T�11K1�4LTW�Q5�11ZPICK�12Z1099032�13Z999999�20Z000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000��'
inventree-server  | Checking plugin registry hash
inventree-server  | Checking plugin registry hash
inventree-server  | 172.16.224.30 - - [16/Sep/2024:16:04:11 +0200] "POST /api/barcode/po-receive/ HTTP/1.0" 200 547 "-" "Dart/3.1 (dart:io)"
inventree-server  | [2024-09-16 16:04:11 +0200] [149] [DEBUG] Closing connection.
inventree-server  | [2024-09-16 16:04:11 +0200] [148] [DEBUG] OPTIONS /api/order/po/337/receive/
inventree-server  | --- Logging error ---
inventree-server  | Traceback (most recent call last):
inventree-server  |   File "/usr/local/lib/python3.11/logging/__init__.py", line 1110, in emit
inventree-server  |     msg = self.format(record)
inventree-server  |           ^^^^^^^^^^^^^^^^^^^
inventree-server  |   File "/usr/local/lib/python3.11/logging/__init__.py", line 953, in format
inventree-server  |     return fmt.format(record)
inventree-server  |            ^^^^^^^^^^^^^^^^^^
inventree-server  |   File "/usr/local/lib/python3.11/logging/__init__.py", line 687, in format
inventree-server  |     record.message = record.getMessage()
inventree-server  |                      ^^^^^^^^^^^^^^^^^^^
inventree-server  |   File "/usr/local/lib/python3.11/logging/__init__.py", line 377, in getMessage
inventree-server  |     msg = msg % self.args
inventree-server  |           ~~~~^~~~~~~~~~~
inventree-server  | TypeError: not all arguments converted during string formatting
inventree-server  | Call stack:
inventree-server  |   File "/usr/local/lib/python3.11/threading.py", line 1002, in _bootstrap
inventree-server  |     self._bootstrap_inner()
inventree-server  |   File "/usr/local/lib/python3.11/threading.py", line 1045, in _bootstrap_inner
inventree-server  |     self.run()
inventree-server  |   File "/usr/local/lib/python3.11/threading.py", line 982, in run
inventree-server  |     self._target(*self._args, **self._kwargs)
inventree-server  |   File "/usr/local/lib/python3.11/concurrent/futures/thread.py", line 83, in _worker
inventree-server  |     work_item.run()
inventree-server  |   File "/usr/local/lib/python3.11/concurrent/futures/thread.py", line 58, in run
inventree-server  |     result = self.fn(*self.args, **self.kwargs)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/gunicorn/workers/gthread.py", line 282, in handle
inventree-server  |     keepalive = self.handle_request(req, conn)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/gunicorn/workers/gthread.py", line 334, in handle_request
inventree-server  |     respiter = self.wsgi(environ, resp.start_response)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/wsgi.py", line 124, in __call__
inventree-server  |     response = self.get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/base.py", line 140, in get_response
inventree-server  |     response = self._middleware_chain(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
inventree-server  |     response = get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/utils/deprecation.py", line 134, in __call__
inventree-server  |     response = response or self.get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
inventree-server  |     response = get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/utils/deprecation.py", line 134, in __call__
inventree-server  |     response = response or self.get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
inventree-server  |     response = get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/utils/deprecation.py", line 134, in __call__
inventree-server  |     response = response or self.get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
inventree-server  |     response = get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/utils/deprecation.py", line 134, in __call__
inventree-server  |     response = response or self.get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
inventree-server  |     response = get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/utils/deprecation.py", line 134, in __call__
inventree-server  |     response = response or self.get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
inventree-server  |     response = get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/corsheaders/middleware.py", line 56, in __call__
inventree-server  |     result = self.get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
inventree-server  |     response = get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/whitenoise/middleware.py", line 124, in __call__
inventree-server  |     return self.get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
inventree-server  |     response = get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/utils/deprecation.py", line 134, in __call__
inventree-server  |     response = response or self.get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
inventree-server  |     response = get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/utils/deprecation.py", line 134, in __call__
inventree-server  |     response = response or self.get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
inventree-server  |     response = get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/utils/deprecation.py", line 134, in __call__
inventree-server  |     response = response or self.get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
inventree-server  |     response = get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django_otp/middleware.py", line 35, in __call__
inventree-server  |     return self.get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
inventree-server  |     response = get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/utils/deprecation.py", line 134, in __call__
inventree-server  |     response = response or self.get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
inventree-server  |     response = get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/allauth/account/middleware.py", line 29, in middleware
inventree-server  |     response = get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
inventree-server  |     response = get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/utils/deprecation.py", line 134, in __call__
inventree-server  |     response = response or self.get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
inventree-server  |     response = get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/utils/deprecation.py", line 134, in __call__
inventree-server  |     response = response or self.get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
inventree-server  |     response = get_response(request)
inventree-server  |   File "/home/inventree/src/backend/InvenTree/InvenTree/middleware.py", line 73, in __call__
inventree-server  |     response = self.get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
inventree-server  |     response = get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/utils/deprecation.py", line 134, in __call__
inventree-server  |     response = response or self.get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
inventree-server  |     response = get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/maintenance_mode/middleware.py", line 11, in __call__
inventree-server  |     response = self.get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
inventree-server  |     response = get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/error_report/middleware.py", line 22, in __call__
inventree-server  |     return self.get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
inventree-server  |     response = get_response(request)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
inventree-server  |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/views/decorators/csrf.py", line 56, in wrapper_view
inventree-server  |     return view_func(*args, **kwargs)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/django/views/generic/base.py", line 104, in view
inventree-server  |     return self.dispatch(request, *args, **kwargs)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/rest_framework/views.py", line 506, in dispatch
inventree-server  |     response = handler(request, *args, **kwargs)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/rest_framework/views.py", line 520, in options
inventree-server  |     data = self.metadata_class().determine_metadata(request, self)
inventree-server  |   File "/home/inventree/src/backend/InvenTree/InvenTree/metadata.py", line 37, in determine_metadata
inventree-server  |     metadata = super().determine_metadata(request, view)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/rest_framework/metadata.py", line 67, in determine_metadata
inventree-server  |     actions = self.determine_actions(request, view)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/rest_framework/metadata.py", line 93, in determine_actions
inventree-server  |     actions[method] = self.get_serializer_info(serializer)
inventree-server  |   File "/home/inventree/src/backend/InvenTree/InvenTree/metadata.py", line 122, in get_serializer_info
inventree-server  |     serializer_info = super().get_serializer_info(serializer)
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/rest_framework/metadata.py", line 108, in get_serializer_info
inventree-server  |     return OrderedDict([
inventree-server  |   File "/root/.local/lib/python3.11/site-packages/rest_framework/metadata.py", line 109, in <listcomp>
inventree-server  |     (field_name, self.get_field_info(field))
inventree-server  |   File "/home/inventree/src/backend/InvenTree/InvenTree/metadata.py", line 270, in get_field_info
inventree-server  |     logger.debug(
inventree-server  | Message: 'Could not extract model for:'
inventree-server  | Arguments: ('Items', '->', PurchaseOrderLineItemReceiveSerializer(many=True):
inventree-server  |     line_item = PrimaryKeyRelatedField(allow_null=False, label='Line Item', queryset=<QuerySet [<PurchaseOrderLineItem: 1000 x 595-SN65HVD231DR from Mouser Electronics (for PO0021 - Mouser Electronics)>, <PurchaseOrderLineItem: 1000 x 595-TPS610986DSET from Mouser Electronics (for PO0018 - Mouser Electronics)>, <PurchaseOrderLineItem: 750 x 691322110003 from Würth Elektronik België BV (for PO0024 - Würth Elektronik België BV)>, <PurchaseOrderLineItem: 2000 x 667-ECA-1HM330I from Mouser Electronics (for PO0004 - Mouser Electronics)>, <PurchaseOrderLineItem: 500 x 480-AG9912M from Mouser Electronics (for PO0005 - Mouser Electronics)>, <PurchaseOrderLineItem: 3000 x 78-SISA14DN-T1-GE3 from Mouser Electronics (for PO0008 - Mouser Electronics)>, <PurchaseOrderLineItem: 2850 x 875105645005 from Würth Elektronik België BV (for PO0007 - Würth Elektronik België BV)>, <PurchaseOrderLineItem: 2000 x 430181038816 from Würth Elektronik België BV (for PO0006 - Würth Elektronik België BV)>, <PurchaseOrderLineItem: 750 x 691361100003 from Würth Elektronik België BV (for PO0024 - Würth Elektronik België BV)>, <PurchaseOrderLineItem: 1000 x ZXMS6004DN8-13DITR-ND from Digi-Key (for PO0026 - Digi-Key)>, <PurchaseOrderLineItem: 110 x EG1941-ND from Digi-Key (for PO0029 - Digi-Key)>, <PurchaseOrderLineItem: 2500 x 691243110006 from Würth Elektronik België BV (for PO0027 - Würth Elektronik België BV)>, <PurchaseOrderLineItem: 500 x 5020021 from Ansmann (for POR24-00329 - Ansmann)>, <PurchaseOrderLineItem: 750 x Raspberry Pi3 Model B V1.2 from Raspberry Pi Ltd (for PO0011 - Raspberry Pi Ltd)>, <PurchaseOrderLineItem: 750 x Raspberry Pi3 Model B V1.2 from Raspberry Pi Ltd (for PO0011 - Raspberry Pi Ltd)>, <PurchaseOrderLineItem: 250 x 587-5883-6-ND from Digi-Key (for PO0010 - Digi-Key)>, <PurchaseOrderLineItem: 250 x 712-2450BM15A0002001EDKR-ND from Digi-Key (for PO0010 - Digi-Key)>, <PurchaseOrderLineItem: 250 x SER4088TR-ND from Digi-Key (for PO0010 - Digi-Key)>, <PurchaseOrderLineItem: 1000 x 870-IS25LP128FJBLETR from Mouser Electronics (for PO0028 - Mouser Electronics)>, <PurchaseOrderLineItem: 1000 x 870-ISS4M8BLL-104NLI from Mouser Electronics (for PO0028 - Mouser Electronics)>, '...(remaining elements truncated)...']>, required=True)
inventree-server  |     location = PrimaryKeyRelatedField(allow_null=True, help_text='Select destination location for received items', label='Location', queryset=<TreeQuerySet [<StockLocation: Assemblics - Assemblics>, <StockLocation: Hoofdgebouw - Hoofdgebouw>, <StockLocation: Hoofdgebouw/Bureau Hardware - Bureau Hardware>, <StockLocation: Hoofdgebouw/Bureau Hardware/ASS doos - >, <StockLocation: Hoofdgebouw/Bureau Hardware/AVR Varia - AVR Varia>, <StockLocation: Hoofdgebouw/Bureau Hardware/BMS doos - BMS doos>, <StockLocation: Hoofdgebouw/Bureau Hardware/CANIO doos - CANIO doos>, <StockLocation: Hoofdgebouw/Bureau Hardware/Cellular hat doos - Cellular hat doos>, <StockLocation: Hoofdgebouw/Bureau Hardware/ETHDRV doos - ETHDRV doos>, <StockLocation: Hoofdgebouw/Bureau Hardware/Guard 2 doos - Guard 2 doos>, <StockLocation: Hoofdgebouw/Bureau Hardware/IR array doos - IR array doos>, <StockLocation: Hoofdgebouw/Bureau Hardware/LEDSTRIP doos - LEDSTRIP doos>, <StockLocation: Hoofdgebouw/Bureau Hardware/LIFELINE doos - LIFELINE doos>, <StockLocation: Hoofdgebouw/Bureau Hardware/LST doos - LST doos>, <StockLocation: Hoofdgebouw/Bureau Hardware/MDZ Varia 1 - MDZ Varia 1>, <StockLocation: Hoofdgebouw/Bureau Hardware/MDZ Varia 2 - MDZ Varia 2>, <StockLocation: Hoofdgebouw/Bureau Hardware/N-CANIO doos - N-CANIO doos>, <StockLocation: Hoofdgebouw/Bureau Hardware/NODE V2 doos - NODE V2 doos>, <StockLocation: Hoofdgebouw/Bureau Hardware/RMT03 doos - RMT03 doos>, <StockLocation: Hoofdgebouw/Bureau Hardware/SDP VARIA - SDP VARIA>, '...(remaining elements truncated)...']>, required=False)
inventree-server  |     quantity = DecimalField(decimal_places=5, max_digits=15, min_value=0, required=True)
inventree-server  |     batch_code = CharField(allow_blank=True, default='', help_text='Enter batch code for incoming stock items', label='Batch Code', required=False)
inventree-server  |     serial_numbers = CharField(allow_blank=True, default='', help_text='Enter serial numbers for incoming stock items', label='Serial Numbers', required=False)
inventree-server  |     status = ChoiceField(choices=[(10, 'OK'), (50, 'Attention needed'), (55, 'Damaged'), (60, 'Destroyed'), (65, 'Rejected'), (70, 'Lost'), (75, 'Quarantined'), (85, 'Returned')], default=10, label='Status')
inventree-server  |     barcode = CharField(allow_blank=True, allow_null=True, default='', help_text='Scanned barcode', label='Barcode', required=False))
inventree-server  | 172.16.224.30 - - [16/Sep/2024:16:04:11 +0200] "OPTIONS /api/order/po/337/receive/ HTTP/1.0" 200 2550 "-" "Dart/3.1 (dart:io)"
inventree-server  | [2024-09-16 16:04:11 +0200] [148] [DEBUG] Closing connection.
inventree-server  | [2024-09-16 16:04:11 +0200] [148] [DEBUG] GET /api/order/po-line/833/
inventree-server  | 172.16.224.30 - - [16/Sep/2024:16:04:11 +0200] "GET /api/order/po-line/833/ HTTP/1.0" 200 298 "-" "Dart/3.1 (dart:io)"
inventree-server  | [2024-09-16 16:04:11 +0200] [148] [DEBUG] Closing connection.

@30350n
Copy link
Contributor Author

30350n commented Sep 17, 2024

Okay, thanks for that.

# this doesn't work
inventree-server  | BarcodePOReceive: scanned barcode - '[)>06PBH2AAPC-4-ND1PBH2AAPC-430PBH2AAPC-4-NDKPOR24-004131K8858870510K1070259609D1T11K14LTWQ511ZPICK12Z109903213Z99999920Z000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
# this does
inventree-server  | BarcodePOReceive: scanned barcode - '[)>�06�PBH2AAPC-4-ND�1PBH2AAPC-4�30PBH2AAPC-4-ND�KPOR24-00413�1K88588705�10K107025960�9D�1T�11K1�4LTW�Q5�11ZPICK�12Z1099032�13Z999999�20Z000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000��'

So the issue here seems to be that when using the wedge scanner the barcode data is missing the unicode seperation characters (\u001e and \u001d). Thus the barcode data cannot be passed.

@HannesMorre You've previously stated this:

This is the data scanned with the built-in scanner of the mobile device we are using:

[)>06PBH2AAPC-4-ND1PBH2AAPC-430PBH2AAPC-4- NDKPOR24-004131K8858870510K1070259609D1T11K14LTWQ511ZPICK12Z109903213Z99999920Z000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

and here those are also not included actually. Could this be an issue with the wedge scanner you are using? Maybe there's a setting enabled that supresses special characters or something like that?

You could test this by using a third party barcode scanning app (I'm using this one for example, available on F-Droid) with the wedge scanner to scan the barcode.
(The app I'm using displays the seperation characters as spaces, but correctly copies them to the clipboard).

@SchrodingersGat I could also imagine it being an issue with the keyboard handling code here, particularily the very first early return check.

@HannesMorre
Copy link

Both barcode scanners are set to process the data as "keyboard event" and "key stroke". Could this be the cause of the problem? We also use these scanners with other apps where the keyboard event/key stroke setting is required.

@30350n
Copy link
Contributor Author

30350n commented Sep 19, 2024

No, that's how these wedge scanners generally work. The problem is that they might or might not have a problem with handling unicode characters. That's why I'm asking you to test with a 3rd party barcode scanning app, that way we'd be able to tell if it's the scanner itself causing the problem, or the keyboard handling code in the inventree-app.

If you are looking for possible scanner settings that'd be affecting this: Do they maybe have a charset/encoding setting? If so, make sure it's set to "unicode"/"utf-8".

@SchrodingersGat
Copy link
Member

It would appear that the "keyboard listener" approach under flutter (at least on android) does not send through the special control characters are not recorded!

I have a USB zebra scanner I am testing with. Scanning the barcode above, into a text editor on the PC, the correct control characters (0x1D, 0x1E) are inserted. However in the app, these characters are missing!

Currently looking into why this is happening, and how to potentially fix.. No promising leads so far

@30350n
Copy link
Contributor Author

30350n commented Sep 19, 2024

Okay, thanks for confirming that!

I don't have any hardware scanners so it's hard for me to mess with this, looking at the code though, I noticed that the RawKeyboard API has been deprecated, so it might be worth checking if using the HardwareKeyboard one fixes it. No guarantees though I guess.

@HannesMorre
Copy link

So if I understand correctly it could be a bug in the mobile app? When I can find the time I will download a third party scanner app to test the scanned data.

@SchrodingersGat
Copy link
Member

@HannesMorre please do, any additional information would be helpful. For reference I was using the Zebra DS2208 scanner.

@SchrodingersGat
Copy link
Member

@30350n I'll checkout HardwareKeyboard when I get a chance...

@HannesMorre
Copy link

Another remark on this:

When we assign a customer P/N to certain parts on Mouser, only this part is included in the data matrix and not the Mouser SKU:
Data: [)>06KPOR24-0041614K008PPRO-000242-00Q20011K0810211594LCN1VLittelfuse
Label:
IMG_2682

Are there changes needed in code to fix this or do we need to change our way of working for this? (e.g. not assigning customer P/N on Mouser) Important note on this is that the customer P/N are assigned automatically by using the supplier panel plugin

@30350n
Copy link
Contributor Author

30350n commented Sep 20, 2024

When we assign a customer P/N to certain parts on Mouser, only this part is included in the data matrix and not the Mouser SKU.

Yeah, that is kinda annoying and will probably not work with the current implementation. They do the same thing with custom order numbers, which I accounted for, but I never used custom part numbers myself, so I missed that one.

@HannesMorre
Copy link

Will this be implemented in any future update?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants