fix scanning of part-db barcodes to redirect to storage location or part lots. made scan result messages conditional for parts or other non-part barcodes

This commit is contained in:
swdee 2026-01-17 19:51:40 +13:00
parent 052780c865
commit 3b1ea8275f
3 changed files with 90 additions and 52 deletions

View file

@ -321,36 +321,44 @@ class ScanController extends AbstractController
$decoded = $scan->getDecodedForInfoMode(); $decoded = $scan->getDecodedForInfoMode();
// Resolve part (or null) // Determine if this barcode resolves to *anything* (part, lot->part, storelocation)
$part = $this->barcodeParser->resolvePartOrNull($scan);
$redirectUrl = null; $redirectUrl = null;
if ($part !== null) { $targetFound = false;
// Redirector knows how to route parts, lots, and storelocations.
try {
$redirectUrl = $this->barcodeParser->getRedirectURL($scan); $redirectUrl = $this->barcodeParser->getRedirectURL($scan);
$targetFound = true;
} catch (EntityNotFoundException) {
$targetFound = false;
} }
// Build template vars // Only resolve Part for part-like targets. Storelocation scans should remain null here.
$part = null;
$partName = null; $partName = null;
$partUrl = null; $partUrl = null;
$locations = []; $locations = [];
$createUrl = null;
if ($part !== null) { if ($targetFound) {
$partName = $part->getName(); $part = $this->barcodeParser->resolvePartOrNull($scan);
$partUrl = $this->generateUrl('app_part_show', ['id' => $part->getID()]);
$locations = $this->buildLocationsForPart($part); if ($part instanceof Part) {
} else { $partName = $part->getName();
$partUrl = $this->generateUrl('app_part_show', ['id' => $part->getID()]);
$locations = $this->buildLocationsForPart($part);
}
}
// Create link only when NOT found (vendor codes)
$createUrl = null;
if (!$targetFound) {
$createUrl = $this->buildCreateUrlForScanResult($scan, $locale); $createUrl = $this->buildCreateUrlForScanResult($scan, $locale);
} }
// Render one fragment that shows: // Render fragment (use openUrl for universal "Open" link)
// - decoded info (optional if you kept it)
// - part info + locations when found
// - create link when not found
$html = $this->renderView('label_system/scanner/augmented_result.html.twig', [ $html = $this->renderView('label_system/scanner/augmented_result.html.twig', [
'decoded' => $decoded, 'decoded' => $decoded,
'found' => ($part !== null), 'found' => $targetFound,
'openUrl' => $redirectUrl,
'partName' => $partName, 'partName' => $partName,
'partUrl' => $partUrl, 'partUrl' => $partUrl,
'locations' => $locations, 'locations' => $locations,
@ -359,7 +367,7 @@ class ScanController extends AbstractController
return new JsonResponse([ return new JsonResponse([
'ok' => true, 'ok' => true,
'found' => ($part !== null), 'found' => $targetFound,
'redirectUrl' => $redirectUrl, // client redirects only when infoMode=false 'redirectUrl' => $redirectUrl, // client redirects only when infoMode=false
'html' => $html, 'html' => $html,
'infoMode' => $infoMode, 'infoMode' => $infoMode,

View file

@ -2,7 +2,14 @@
<hr> <hr>
<div class="d-flex align-items-center mb-2"> <div class="d-flex align-items-center mb-2">
<h4 class="mb-0 me-2">{% trans %}label_scanner.part_info.title{% endtrans %}</h4> <h4 class="mb-0 me-2">
{% if found and partName %}
{% trans %}label_scanner.part_info.title{% endtrans %}
{% else %}
{% trans %}label_scanner.scan_result.title{% endtrans %}
{% endif %}
</h4>
{% if createUrl %} {% if createUrl %}
<a class="btn btn-primary ms-2 mb-2" <a class="btn btn-primary ms-2 mb-2"
@ -15,42 +22,53 @@
</div> </div>
{% if found %} {% if found %}
<div class="alert alert-success mb-2"> <div class="alert alert-success mb-2 d-flex align-items-center justify-content-between">
{{ partName }} <div>
{% if partUrl %} {% if partName %}
— <a href="{{ partUrl }}" target="_blank">{% trans %}open{% endtrans %}</a> {{ partName }}
{% endif %} {% else %}
</div> {% trans %}label_scanner.target_found{% endtrans %}
{% endif %}
</div>
{% if locations is not empty %} {% if openUrl %}
<table class="table table-sm mb-2 w-auto"> <a href="{{ openUrl }}" target="_blank" class="btn btn-sm btn-outline-success">
<thead> {% trans %}open{% endtrans %}
<tr> </a>
<th scope="col">{% trans %}part_lots.storage_location{% endtrans %}</th> {% endif %}
<th scope="col" class="text-end" style="width: 6rem;"> </div>
{% trans %}part_lots.amount{% endtrans %}
</th> {% if partName %}
</tr> {% if locations is not empty %}
</thead> <table class="table table-sm mb-2 w-auto">
<tbody> <thead>
{% for loc in locations %}
<tr> <tr>
<td> <th scope="col">{% trans %}part_lots.storage_location{% endtrans %}</th>
<ul class="structural_link d-inline"> <th scope="col" class="text-end" style="width: 6rem;">
{% for crumb in loc.breadcrumb %} {% trans %}part_lots.amount{% endtrans %}
<li><a href="{{ crumb.url }}" target="_blank">{{ crumb.name }}</a></li> </th>
{% endfor %}
</ul>
</td>
<td class="text-end" style="width: 6rem;">
{% if loc.qty is not null %}<strong>{{ loc.qty }}</strong>{% else %}<span class="text-muted">—</span>{% endif %}
</td>
</tr> </tr>
{% endfor %} </thead>
</tbody> <tbody>
</table> {% for loc in locations %}
{% else %} <tr>
<div class="text-muted mb-2">{% trans %}label_scanner.no_locations{% endtrans %}</div> <td>
<ul class="structural_link d-inline">
{% for crumb in loc.breadcrumb %}
<li><a href="{{ crumb.url }}" target="_blank">{{ crumb.name }}</a></li>
{% endfor %}
</ul>
</td>
<td class="text-end" style="width: 6rem;">
{% if loc.qty is not null %}<strong>{{ loc.qty }}</strong>{% else %}<span class="text-muted">—</span>{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<div class="text-muted mb-2">{% trans %}label_scanner.no_locations{% endtrans %}</div>
{% endif %}
{% endif %} {% endif %}
{% else %} {% else %}
<div class="alert alert-warning mb-2"> <div class="alert alert-warning mb-2">

View file

@ -12051,6 +12051,18 @@ Please note, that you can not impersonate a disabled user. If you try you will g
<target>Part information</target> <target>Part information</target>
</segment> </segment>
</unit> </unit>
<unit id="k9lvxgf" name="label_scanner.target_found">
<segment state="translated">
<source>label_scanner.target_found</source>
<target>Item Found</target>
</segment>
</unit>
<unit id="kd6G2gf" name="label_scanner.scan_result.title">
<segment state="translated">
<source>label_scanner.scan_result.title</source>
<target>Scan result</target>
</segment>
</unit>
<unit id="kG2vk5p" name="label_scanner.no_locations"> <unit id="kG2vk5p" name="label_scanner.no_locations">
<segment state="translated"> <segment state="translated">
<source>label_scanner.no_locations</source> <source>label_scanner.no_locations</source>