From 338c5ebf0bf548365ed96be9408e280f88ca8310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hmer?= Date: Sat, 21 Feb 2026 23:26:25 +0100 Subject: [PATCH] Refactored LCSCBarcocdeScanResult to be an value object like the other Barcode results --- src/Controller/ScanController.php | 2 +- .../BarcodeScanner/BarcodeRedirector.php | 4 +- .../BarcodeScanner/BarcodeScanHelper.php | 2 +- .../BarcodeScanResultInterface.php | 2 +- .../BarcodeScanner/LCSCBarcodeScanResult.php | 99 ++++++++++++------- .../BarcodeScanner/BarcodeRedirectorTest.php | 4 +- .../BarcodeScanner/BarcodeScanHelperTest.php | 8 +- 7 files changed, 74 insertions(+), 47 deletions(-) diff --git a/src/Controller/ScanController.php b/src/Controller/ScanController.php index 94c16b0b..330c50d5 100644 --- a/src/Controller/ScanController.php +++ b/src/Controller/ScanController.php @@ -170,7 +170,7 @@ class ScanController extends AbstractController { // LCSC if ($scanResult instanceof LCSCBarcodeScanResult) { - $lcscCode = $scanResult->getPC(); + $lcscCode = $scanResult->lcscCode; if ($lcscCode !== null && $lcscCode !== '') { return $this->generateUrl('info_providers_create_part', [ 'providerKey' => 'lcsc', diff --git a/src/Services/LabelSystem/BarcodeScanner/BarcodeRedirector.php b/src/Services/LabelSystem/BarcodeScanner/BarcodeRedirector.php index b8819d89..d4b7bed9 100644 --- a/src/Services/LabelSystem/BarcodeScanner/BarcodeRedirector.php +++ b/src/Services/LabelSystem/BarcodeScanner/BarcodeRedirector.php @@ -130,7 +130,7 @@ final class BarcodeRedirector private function getPartFromLCSC(LCSCBarcodeScanResult $barcodeScan): Part { // Try LCSC code (pc) as provider id if available - $pc = $barcodeScan->getPC(); // e.g. C138033 + $pc = $barcodeScan->lcscCode; // e.g. C138033 if ($pc) { $qb = $this->em->getRepository(Part::class)->createQueryBuilder('part'); $qb->where($qb->expr()->like('LOWER(part.providerReference.provider_id)', 'LOWER(:vendor_id)')); @@ -142,7 +142,7 @@ final class BarcodeRedirector } // Fallback to MPN (pm) - $pm = $barcodeScan->getPM(); // e.g. RC0402FR-071ML + $pm = $barcodeScan->mpn; // e.g. RC0402FR-071ML if (!$pm) { throw new EntityNotFoundException(); } diff --git a/src/Services/LabelSystem/BarcodeScanner/BarcodeScanHelper.php b/src/Services/LabelSystem/BarcodeScanner/BarcodeScanHelper.php index 393a0911..b2363ec8 100644 --- a/src/Services/LabelSystem/BarcodeScanner/BarcodeScanHelper.php +++ b/src/Services/LabelSystem/BarcodeScanner/BarcodeScanHelper.php @@ -131,7 +131,7 @@ final class BarcodeScanHelper } // Try LCSC barcode - if (LCSCBarcodeScanResult::looksLike($input)) { + if (LCSCBarcodeScanResult::isLCSCBarcode($input)) { return $this->parseLCSCBarcode($input); } diff --git a/src/Services/LabelSystem/BarcodeScanner/BarcodeScanResultInterface.php b/src/Services/LabelSystem/BarcodeScanner/BarcodeScanResultInterface.php index 88130351..befa91b6 100644 --- a/src/Services/LabelSystem/BarcodeScanner/BarcodeScanResultInterface.php +++ b/src/Services/LabelSystem/BarcodeScanner/BarcodeScanResultInterface.php @@ -33,4 +33,4 @@ interface BarcodeScanResultInterface * @return array */ public function getDecodedForInfoMode(): array; -} \ No newline at end of file +} diff --git a/src/Services/LabelSystem/BarcodeScanner/LCSCBarcodeScanResult.php b/src/Services/LabelSystem/BarcodeScanner/LCSCBarcodeScanResult.php index 236bad48..02f87b47 100644 --- a/src/Services/LabelSystem/BarcodeScanner/LCSCBarcodeScanResult.php +++ b/src/Services/LabelSystem/BarcodeScanner/LCSCBarcodeScanResult.php @@ -10,41 +10,67 @@ use InvalidArgumentException; * This class represents the content of a lcsc.com barcode * Its data structure is represented by {pbn:...,on:...,pc:...,pm:...,qty:...} */ -class LCSCBarcodeScanResult implements BarcodeScanResultInterface +readonly class LCSCBarcodeScanResult implements BarcodeScanResultInterface { + + /** @var string|null (pbn) */ + public ?string $pickBatchNumber; + + /** @var string|null (on) */ + public ?string $orderNumber; + + /** @var string|null LCSC Supplier part number (pc) */ + public ?string $lcscCode; + + /** @var string|null (pm) */ + public ?string $mpn; + + /** @var int|null (qty) */ + public ?int $quantity; + + /** @var string|null Country Channel as raw value (CC) */ + public ?string $countryChannel; + + /** + * @var string|null Warehouse code as raw value (WC) + */ + public ?string $warehouseCode; + + /** + * @var string|null Unknown numeric code (pdi) + */ + public ?string $pdi; + + /** + * @var string|null Unknown value (hp) + */ + public ?string $hp; + /** * @param array $fields */ public function __construct( - public readonly array $fields, - public readonly string $raw_input, - ) {} + public array $fields, + public string $raw_input, + ) { + + $this->pickBatchNumber = $this->fields['pbn'] ?? null; + $this->orderNumber = $this->fields['on'] ?? null; + $this->lcscCode = $this->fields['pc'] ?? null; + $this->mpn = $this->fields['pm'] ?? null; + $this->quantity = isset($this->fields['qty']) ? (int)$this->fields['qty'] : null; + $this->countryChannel = $this->fields['cc'] ?? null; + $this->warehouseCode = $this->fields['wc'] ?? null; + $this->pdi = $this->fields['pdi'] ?? null; + $this->hp = $this->fields['hp'] ?? null; + + } public function getSourceType(): BarcodeSourceType { return BarcodeSourceType::LCSC; } - /** - * @return string|null The manufactures part number - */ - public function getPM(): ?string - { - $v = $this->fields['pm'] ?? null; - $v = $v !== null ? trim($v) : null; - return ($v === '') ? null : $v; - } - - /** - * @return string|null The lcsc.com part number - */ - public function getPC(): ?string - { - $v = $this->fields['pc'] ?? null; - $v = $v !== null ? trim($v) : null; - return ($v === '') ? null : $v; - } - /** * @return array|float[]|int[]|null[]|string[] An array of fields decoded from the barcode */ @@ -53,13 +79,15 @@ class LCSCBarcodeScanResult implements BarcodeScanResultInterface // Keep it human-friendly return [ 'Barcode type' => 'LCSC', - 'MPN (pm)' => $this->getPM() ?? '', - 'LCSC code (pc)' => $this->getPC() ?? '', - 'Qty' => $this->fields['qty'] ?? '', - 'Order No (on)' => $this->fields['on'] ?? '', - 'Pick Batch (pbn)' => $this->fields['pbn'] ?? '', - 'Warehouse (wc)' => $this->fields['wc'] ?? '', - 'Country/Channel (cc)' => $this->fields['cc'] ?? '', + 'MPN (pm)' => $this->mpn ?? '', + 'LCSC code (pc)' => $this->lcscCode ?? '', + 'Qty' => $this->quantity !== null ? (string) $this->quantity : '', + 'Order No (on)' => $this->orderNumber ?? '', + 'Pick Batch (pbn)' => $this->pickBatchNumber ?? '', + 'Warehouse (wc)' => $this->warehouseCode ?? '', + 'Country/Channel (cc)' => $this->countryChannel ?? '', + 'PDI (unknown meaning)' => $this->pdi ?? '', + 'HP (unknown meaning)' => $this->hp ?? '', ]; } @@ -68,7 +96,7 @@ class LCSCBarcodeScanResult implements BarcodeScanResultInterface * @param string $input * @return bool */ - public static function looksLike(string $input): bool + public static function isLCSCBarcode(string $input): bool { $s = trim($input); @@ -90,18 +118,17 @@ class LCSCBarcodeScanResult implements BarcodeScanResultInterface { $raw = trim($input); - if (!self::looksLike($raw)) { + if (!self::isLCSCBarcode($raw)) { throw new InvalidArgumentException('Not an LCSC barcode'); } - $inner = trim($raw); - $inner = substr($inner, 1, -1); // remove { } + $inner = substr($raw, 1, -1); // remove { } $fields = []; // This format is comma-separated pairs, values do not contain commas in your sample. $pairs = array_filter( - array_map('trim', explode(',', $inner)), + array_map(trim(...), explode(',', $inner)), static fn(string $s): bool => $s !== '' ); diff --git a/tests/Services/LabelSystem/BarcodeScanner/BarcodeRedirectorTest.php b/tests/Services/LabelSystem/BarcodeScanner/BarcodeRedirectorTest.php index b9fd9582..f13604d3 100644 --- a/tests/Services/LabelSystem/BarcodeScanner/BarcodeRedirectorTest.php +++ b/tests/Services/LabelSystem/BarcodeScanner/BarcodeRedirectorTest.php @@ -149,8 +149,8 @@ final class BarcodeRedirectorTest extends KernelTestCase { $scan = LCSCBarcodeScanResult::parse('{pbn:PB1,on:ON1,pc:C138033,pm:RC0402FR-071ML,qty:10}'); - $this->assertSame('RC0402FR-071ML', $scan->getPM()); - $this->assertSame('C138033', $scan->getPC()); + $this->assertSame('RC0402FR-071ML', $scan->mpn); + $this->assertSame('C138033', $scan->lcscCode); $decoded = $scan->getDecodedForInfoMode(); $this->assertSame('LCSC', $decoded['Barcode type']); diff --git a/tests/Services/LabelSystem/BarcodeScanner/BarcodeScanHelperTest.php b/tests/Services/LabelSystem/BarcodeScanner/BarcodeScanHelperTest.php index b6711055..8f8c7a18 100644 --- a/tests/Services/LabelSystem/BarcodeScanner/BarcodeScanHelperTest.php +++ b/tests/Services/LabelSystem/BarcodeScanner/BarcodeScanHelperTest.php @@ -170,8 +170,8 @@ final class BarcodeScanHelperTest extends WebTestCase $result = $this->service->scanBarcodeContent($input); $this->assertInstanceOf(LCSCBarcodeScanResult::class, $result); - $this->assertSame('C138033', $result->getPC()); - $this->assertSame('RC0402FR-071ML', $result->getPM()); + $this->assertSame('C138033', $result->lcscCode); + $this->assertSame('RC0402FR-071ML', $result->mpn); } public function testLcscExplicitTypeParses(): void @@ -181,8 +181,8 @@ final class BarcodeScanHelperTest extends WebTestCase $result = $this->service->scanBarcodeContent($input, BarcodeSourceType::LCSC); $this->assertInstanceOf(LCSCBarcodeScanResult::class, $result); - $this->assertSame('C138033', $result->getPC()); - $this->assertSame('RC0402FR-071ML', $result->getPM()); + $this->assertSame('C138033', $result->lcscCode); + $this->assertSame('RC0402FR-071ML', $result->mpn); } public function testLcscExplicitTypeRejectsNonLcsc(): void