Skip to content

PRD: Barcode Scan & Identification at the Counter

ModuleProductsPRD IDPRD-PID-001
StatusReady to devFEATPID
EpicBANA-1319PlaneBANA-1752
Date2026-07-06Versionv1.0
Packages@nx/commerceURDPID
SurfaceSale · POS
OwnerPhát Nguyễn

What barcode scan & identification is

A cashier scans or types a barcode at the counter and gets exactly one answer: the variant it names, priced and ready for the cart, or a plain "not found" so they can fall back to search. This PRD is the shared identification contract - scheme-priority disambiguation, not-found handling, scanner/manual-entry parity - that every counter-selling flow (retail counter mode, product picker's scan bypass) already assumes but none of them fully own today.

Why this needs its own contract

Barcode identifiers already exist on variants (URD-PID-001…004, Built), and a basic lookup already resolves a scanned code to a variant - both the product picker and retail counter mode reference it as a working head start (URD-PCK-007, URD-RTL-005). But neither owns the identification behavior itself - each treats "scan → item in cart" as an assumed black box:

  • No defined not-found contract. What the cashier sees when a scanned code matches nothing is unspecified - today's shallow lookup does not guarantee a clean, actionable response.
  • No disambiguation rule. Identifiers are unique per scheme (URD-PID-001), not globally - the same string can legally exist as a barcode on one variant and a SKU on another.
  • No scanner/manual-entry parity guarantee - the POS already models a dedicated BARCODE_SCANNER device type, but a cashier typing the same digits by hand should behave identically; this is assumed, not specified.
  • No home for the retail edge case. Grocery-style variable-weight barcodes (a fixed prefix + item code + an embedded weight or price, common on scale-printed labels) need a different resolution rule than a plain product barcode.

One scan, from code to cart

A cashier scans a code at the counter. The system checks identifier schemes in a fixed order - barcode first, then SKU, QR code, slug, system code - and returns the first scheme's match. If that string is both a barcode on variant A and a SKU on variant B, the result is always variant A, because barcode comes first. The resolved variant carries its live price and availability, identical to a manual pick - the item is added to the cart right away. If the string matches nothing, the cashier gets a plain "not found" message and a prompt to search by name or SKU instead of re-scanning the same code.

Where this goes wrong

A string can be valid under two schemes at once

Identifiers are unique per scheme, not globally. A merchant can legally register the exact same string as a barcode on one variant and a SKU on another - both are valid at creation time.

A naive lookup could return the wrong variant, or both. A fixed scheme-priority order is the only thing that makes resolution deterministic.

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.