diff --git a/src/Form/LabelSystem/ScanDialogType.php b/src/Form/LabelSystem/ScanDialogType.php index 13ff8e6f..9199c31d 100644 --- a/src/Form/LabelSystem/ScanDialogType.php +++ b/src/Form/LabelSystem/ScanDialogType.php @@ -75,7 +75,8 @@ class ScanDialogType extends AbstractType BarcodeSourceType::INTERNAL => 'scan_dialog.mode.internal', BarcodeSourceType::IPN => 'scan_dialog.mode.ipn', BarcodeSourceType::USER_DEFINED => 'scan_dialog.mode.user', - BarcodeSourceType::EIGP114 => 'scan_dialog.mode.eigp' + BarcodeSourceType::EIGP114 => 'scan_dialog.mode.eigp', + BarcodeSourceType::GTIN => 'scan_dialog.mode.gtin', }, ]); diff --git a/src/Services/LabelSystem/BarcodeScanner/BarcodeRedirector.php b/src/Services/LabelSystem/BarcodeScanner/BarcodeRedirector.php index d5ddc1de..1a3c29c2 100644 --- a/src/Services/LabelSystem/BarcodeScanner/BarcodeRedirector.php +++ b/src/Services/LabelSystem/BarcodeScanner/BarcodeRedirector.php @@ -77,6 +77,10 @@ final class BarcodeRedirector return $this->getURLVendorBarcode($barcodeScan); } + if ($barcodeScan instanceof GTINBarcodeScanResult) { + return $this->getURLGTINBarcode($barcodeScan); + } + throw new InvalidArgumentException('Unknown $barcodeScan type: '.get_class($barcodeScan)); } @@ -111,6 +115,16 @@ final class BarcodeRedirector return $this->urlGenerator->generate('app_part_show', ['id' => $part->getID()]); } + private function getURLGTINBarcode(GTINBarcodeScanResult $barcodeScan): string + { + $part = $this->em->getRepository(Part::class)->findOneBy(['gtin' => $barcodeScan->gtin]); + if (!$part instanceof Part) { + throw new EntityNotFoundException(); + } + + return $this->urlGenerator->generate('app_part_show', ['id' => $part->getID()]); + } + /** * Gets a part from a scan of a Vendor Barcode by filtering for parts * with the same Info Provider Id or, if that fails, by looking for parts with a diff --git a/src/Services/LabelSystem/BarcodeScanner/BarcodeScanHelper.php b/src/Services/LabelSystem/BarcodeScanner/BarcodeScanHelper.php index e5930b36..520c9f3b 100644 --- a/src/Services/LabelSystem/BarcodeScanner/BarcodeScanHelper.php +++ b/src/Services/LabelSystem/BarcodeScanner/BarcodeScanHelper.php @@ -92,6 +92,9 @@ final class BarcodeScanHelper if ($type === BarcodeSourceType::EIGP114) { return $this->parseEIGP114Barcode($input); } + if ($type === BarcodeSourceType::GTIN) { + return $this->parseGTINBarcode($input); + } //Null means auto and we try the different formats $result = $this->parseInternalBarcode($input); @@ -117,9 +120,19 @@ final class BarcodeScanHelper return $result; } + //If the result is a valid GTIN barcode, we can parse it directly + if (GTINBarcodeScanResult::isValidGTIN($input)) { + return $this->parseGTINBarcode($input); + } + throw new InvalidArgumentException('Unknown barcode'); } + private function parseGTINBarcode(string $input): GTINBarcodeScanResult + { + return new GTINBarcodeScanResult($input); + } + private function parseEIGP114Barcode(string $input): EIGP114BarcodeScanResult { return EIGP114BarcodeScanResult::parseFormat06Code($input); diff --git a/src/Services/LabelSystem/BarcodeScanner/BarcodeSourceType.php b/src/Services/LabelSystem/BarcodeScanner/BarcodeSourceType.php index 40f707de..43643d12 100644 --- a/src/Services/LabelSystem/BarcodeScanner/BarcodeSourceType.php +++ b/src/Services/LabelSystem/BarcodeScanner/BarcodeSourceType.php @@ -42,4 +42,9 @@ enum BarcodeSourceType * EIGP114 formatted barcodes like used by digikey, mouser, etc. */ case EIGP114; -} \ No newline at end of file + + /** + * GTIN /EAN barcodes, which are used on most products in the world. These are checked with the GTIN field of a part. + */ + case GTIN; +} diff --git a/src/Services/LabelSystem/BarcodeScanner/GTINBarcodeScanResult.php b/src/Services/LabelSystem/BarcodeScanner/GTINBarcodeScanResult.php new file mode 100644 index 00000000..389bfdcc --- /dev/null +++ b/src/Services/LabelSystem/BarcodeScanner/GTINBarcodeScanResult.php @@ -0,0 +1,64 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Services\LabelSystem\BarcodeScanner; + +use GtinValidation\GtinValidator; + +readonly class GTINBarcodeScanResult implements BarcodeScanResultInterface +{ + + private GtinValidator $validator; + + public function __construct( + public string $gtin, + ) { + $this->validator = new GtinValidator($this->gtin); + } + + public function getDecodedForInfoMode(): array + { + $obj = $this->validator->getGtinObject(); + return [ + 'GTIN' => $this->gtin, + 'GTIN type' => $obj->getType(), + 'Valid' => $this->validator->isValid() ? 'Yes' : 'No', + 'Reference Number' => $obj->getReferenceNumber(), + 'Check Digit' => $obj->getCheckDigit(), + ]; + } + + /** + * Checks if the given input is a valid GTIN. This is used to determine whether a scanned barcode should be interpreted as a GTIN or not. + * @param string $input + * @return bool + */ + public static function isValidGTIN(string $input): bool + { + try { + return (new GtinValidator($input))->isValid(); + } catch (\Exception $e) { + return false; + } + } +} diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf index 8953982d..b2a577b0 100644 --- a/translations/messages.en.xlf +++ b/translations/messages.en.xlf @@ -12419,5 +12419,11 @@ Buerklin-API Authentication server: GTIN + + + scan_dialog.mode.gtin + GTIN / EAN + +