added redirection to part page on successful scan of lcsc, digikey, and mouser barcodes. added create part button if part does not exist in database

This commit is contained in:
swdee 2026-01-16 13:59:26 +13:00
parent 4325f9e0e6
commit f3cd32cc91
2 changed files with 110 additions and 6 deletions

View file

@ -46,6 +46,8 @@ use App\Services\LabelSystem\BarcodeScanner\BarcodeRedirector;
use App\Services\LabelSystem\BarcodeScanner\BarcodeScanHelper;
use App\Services\LabelSystem\BarcodeScanner\BarcodeSourceType;
use App\Services\LabelSystem\BarcodeScanner\LocalBarcodeScanResult;
use App\Services\LabelSystem\BarcodeScanner\LCSCBarcodeScanResult;
use App\Services\LabelSystem\BarcodeScanner\EIGP114BarcodeScanResult;
use Doctrine\ORM\EntityNotFoundException;
use InvalidArgumentException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
@ -53,6 +55,8 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\MapQueryParameter;
use Symfony\Component\Routing\Attribute\Route;
use App\Services\InfoProviderSystem\PartInfoRetriever;
use App\Services\InfoProviderSystem\ProviderRegistry;
/**
* @see \App\Tests\Controller\ScanControllerTest
@ -60,9 +64,12 @@ use Symfony\Component\Routing\Attribute\Route;
#[Route(path: '/scan')]
class ScanController extends AbstractController
{
public function __construct(protected BarcodeRedirector $barcodeParser, protected BarcodeScanHelper $barcodeNormalizer)
{
}
public function __construct(
protected BarcodeRedirector $barcodeParser,
protected BarcodeScanHelper $barcodeNormalizer,
private readonly ProviderRegistry $providerRegistry,
private readonly PartInfoRetriever $infoRetriever,
) {}
#[Route(path: '', name: 'scan_dialog')]
public function dialog(Request $request, #[MapQueryParameter] ?string $input = null): Response
@ -72,26 +79,113 @@ class ScanController extends AbstractController
$form = $this->createForm(ScanDialogType::class);
$form->handleRequest($request);
$mode = null;
if ($input === null && $form->isSubmitted() && $form->isValid()) {
$input = $form['input']->getData();
$mode = $form['mode']->getData();
}
$infoModeData = null;
$createUrl = null;
if ($input !== null) {
try {
$scan_result = $this->barcodeNormalizer->scanBarcodeContent($input, $mode ?? null);
//Perform a redirect if the info mode is not enabled
if (!$form['info_mode']->getData()) {
try {
// redirect user to part page
return $this->redirect($this->barcodeParser->getRedirectURL($scan_result));
} catch (EntityNotFoundException) {
$this->addFlash('success', 'scan.qr_not_found');
// Fallback: show decoded info like info-mode as part does not exist
$infoModeData = $scan_result->getDecodedForInfoMode();
$locale = $request->getLocale();
// If it's an LCSC scan, offer "create part" link
if ($scan_result instanceof LCSCBarcodeScanResult) {
$lcscCode = $scan_result->getPC();
if (is_string($lcscCode) && $lcscCode !== '') {
// Prefer generating a relative URL; browser will use current host
$createUrl = "/{$locale}/part/from_info_provider/lcsc/{$lcscCode}/create";
}
}
// If EIGP114 (Mouser / Digi-Key), offer "create part" link
if ($scan_result instanceof EIGP114BarcodeScanResult) {
// Use guessed vendor and supplierPartNumber.
$vendor = $scan_result->guessBarcodeVendor();
if ($vendor === 'mouser' && is_string($scan_result->supplierPartNumber)
&& $scan_result->supplierPartNumber !== '') {
try {
$mouserProvider = $this->providerRegistry->getProviderByKey('mouser');
if (!$mouserProvider->isActive()) {
$this->addFlash('warning', 'Mouser provider is disabled / not configured.');
} else {
// Search Mouser using the MPN
$dtos = $this->infoRetriever->searchByKeyword(
keyword: $scan_result->supplierPartNumber,
providers: [$mouserProvider]
);
// If there are results, provider_id is MouserPartNumber (per MouserProvider.php)
$best = $dtos[0] ?? null;
if ($best !== null && is_string($best->provider_id) && $best->provider_id !== '') {
$createUrl = '/'
. rawurlencode($locale)
. '/part/from_info_provider/mouser/'
. rawurlencode($best->provider_id)
. '/create';
} else {
$this->addFlash('warning', 'No Mouser match found for this MPN.');
}
}
} catch (\InvalidArgumentException $e) {
// provider key not found in registry
$this->addFlash('warning', 'Mouser provider is not installed/enabled.');
} catch (\Throwable $e) {
// Dont break scanning UX if provider lookup fails
$this->addFlash('warning', 'Mouser lookup failed: ' . $e->getMessage());
}
}
// Digikey can keep using customerPartNumber if present (it is in their barcode)
if ($vendor === 'digikey') {
try {
$provider = $this->providerRegistry->getProviderByKey('digikey');
if (!$provider->isActive()) {
$this->addFlash('warning', 'Digi-Key provider is disabled / not configured (API key missing).');
} else {
$id = $scan_result->customerPartNumber ?: $scan_result->supplierPartNumber;
if (is_string($id) && $id !== '') {
$createUrl = '/'
. rawurlencode($locale)
. '/part/from_info_provider/digikey/'
. rawurlencode($id)
. '/create';
}
}
} catch (\InvalidArgumentException $e) {
$this->addFlash('warning', 'Digi-Key provider is not installed/enabled');
}
}
}
if ($createUrl === null) {
$this->addFlash('warning', 'scan.qr_not_found');
}
}
} else { //Otherwise retrieve infoModeData
$infoModeData = $scan_result->getDecodedForInfoMode();
}
} catch (InvalidArgumentException) {
$this->addFlash('error', 'scan.format_unknown');
@ -101,6 +195,7 @@ class ScanController extends AbstractController
return $this->render('label_system/scanner/scanner.html.twig', [
'form' => $form,
'infoModeData' => $infoModeData,
'createUrl' => $createUrl,
]);
}