Allow to scan IPN barcodes using the built in barcode scanner

This improves issue #373
This commit is contained in:
Jan Böhmer 2023-11-12 00:36:13 +01:00
parent 3953e36921
commit 5cfccab671
9 changed files with 1480 additions and 1397 deletions

View file

@ -71,11 +71,12 @@ class ScanController extends AbstractController
if ($input === null && $form->isSubmitted() && $form->isValid()) {
$input = $form['input']->getData();
$mode = $form['mode']->getData();
}
if ($input !== null) {
try {
$scan_result = $this->barcodeNormalizer->scanBarcodeContent($input);
$scan_result = $this->barcodeNormalizer->scanBarcodeContent($input, $mode ?? null);
try {
return $this->redirect($this->barcodeParser->getRedirectURL($scan_result));
} catch (EntityNotFoundException) {

View file

@ -83,6 +83,7 @@ class PartFixtures extends Fixture implements DependentFixtureInterface
$part->setManufacturer($manager->find(Manufacturer::class, 1));
$part->setTags('test, Test, Part2');
$part->setMass(100.2);
$part->setIpn('IPN123');
$part->setNeedsReview(true);
$part->setManufacturingStatus(ManufacturingStatus::ACTIVE);
$manager->persist($part);

View file

@ -41,7 +41,9 @@ declare(strict_types=1);
namespace App\Form\LabelSystem;
use App\Services\LabelSystem\Barcodes\BarcodeSourceType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\EnumType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
@ -59,6 +61,20 @@ class ScanDialogType extends AbstractType
],
]);
$builder->add('mode', EnumType::class, [
'label' => 'scan_dialog.mode',
'expanded' => true,
'class' => BarcodeSourceType::class,
'required' => false,
'placeholder' => 'scan_dialog.mode.auto',
'choice_label' => fn (?BarcodeSourceType $enum) => match($enum) {
null => 'scan_dialog.mode.auto',
BarcodeSourceType::INTERNAL => 'scan_dialog.mode.internal',
BarcodeSourceType::IPN => 'scan_dialog.mode.ipn',
},
]);
$builder->add('submit', SubmitType::class, [
'label' => 'scan_dialog.submit',
]);

View file

@ -42,6 +42,8 @@ declare(strict_types=1);
namespace App\Services\LabelSystem\Barcodes;
use App\Entity\LabelSystem\LabelSupportedElement;
use App\Entity\Parts\Part;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
/**
@ -61,6 +63,10 @@ final class BarcodeScanHelper
'location' => LabelSupportedElement::STORELOCATION,
];
public function __construct(private readonly EntityManagerInterface $entityManager)
{
}
/**
* Parse the given barcode content and return the target type and ID.
* If the barcode could not be parsed, an exception is thrown.
@ -76,6 +82,9 @@ final class BarcodeScanHelper
if ($type === BarcodeSourceType::INTERNAL) {
return $this->parseInternalBarcode($input) ?? throw new InvalidArgumentException('Could not parse barcode');
}
if ($type === BarcodeSourceType::IPN) {
return $this->parseIPNBarcode($input) ?? throw new InvalidArgumentException('Could not parse barcode');
}
//Null means auto and we try the different formats
$result = $this->parseInternalBarcode($input);
@ -83,9 +92,35 @@ final class BarcodeScanHelper
if ($result !== null) {
return $result;
}
//Try to parse as IPN barcode
$result = $this->parseIPNBarcode($input);
if ($result !== null) {
return $result;
}
throw new InvalidArgumentException('Unknown barcode format');
}
private function parseIPNBarcode(string $input): ?BarcodeScanResult
{
$part_repo = $this->entityManager->getRepository(Part::class);
//Find only the first result
$results = $part_repo->findBy(['ipn' => $input], limit: 1);
if (count($results) === 0) {
return null;
}
//We found a part, so use it to create the result
$part = $results[0];
return new BarcodeScanResult(
target_type: LabelSupportedElement::PART,
target_id: $part->getID(),
source_type: BarcodeSourceType::IPN
);
}
/**
* This function tries to interpret the given barcode content as an internal barcode.
* If the barcode could not be parsed at all, null is returned. If the barcode is a valid format, but could

View file

@ -30,4 +30,6 @@ enum BarcodeSourceType
{
/** This Barcode was generated using Part-DB internal recommended barcode generator */
case INTERNAL;
/** This barcode is containing an internal part number (IPN) */
case IPN;
}