Product Lookup
Overview
Section titled “Overview”Product lookup enables field users to quickly retrieve product information by scanning barcodes during sales order creation. The feature supports multiple barcode formats and integrates with the offline-first architecture to ensure reliable operation in low-connectivity environments.
Primary use case: Sales representatives scan product barcodes to auto-add items to cart when creating sales orders.
API Endpoint
Section titled “API Endpoint”Get Product by Barcode
Section titled “Get Product by Barcode”GET /app/v1/products/barcode/:barcodeAuthorization: Bearer <token>Path Parameters:
| Param | Type | Description |
|---|---|---|
| barcode | string | Product barcode (EAN-13, UPC, Code-128) |
Query Parameters:
None
Example Request
Section titled “Example Request”GET /app/v1/products/barcode/8991234567890Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Example Response
Section titled “Example Response”{ "data": { "id": 123, "name": "Coca Cola 330ml", "sku": "COKE-330", "barcode": "8991234567890", "brand": "Coca Cola", "unit_price": 5000, "category": "Beverages", "active": true }, "message": "product retrieved", "code": "PRODUCT_BARCODE_DETAIL"}Error Responses
Section titled “Error Responses”Product Not Found:
HTTP/1.1 404 Not Found{ "success": false, "message": "Product not found", "code": "PRODUCT_BARCODE_NOT_FOUND"}Invalid Barcode Format:
HTTP/1.1 400 Bad Request{ "success": false, "message": "Invalid barcode format", "code": "PRODUCT_BARCODE_INVALID"}Query Hook
Section titled “Query Hook”useProductByBarcodeQuery
Section titled “useProductByBarcodeQuery”export function useProductByBarcodeQuery(barcode: string) { const profile = useAtomValue(profileAtom);
return useQuery({ queryKey: ['product', 'barcode', barcode], queryFn: () => productService.getByBarcode(barcode), enabled: !!barcode && !!profile, networkMode: 'offlineFirst', staleTime: 5 * 60 * 1000, // 5 minutes select: (res) => res?.data?.data, });}Usage in Sales Order
Section titled “Usage in Sales Order”function CreateSalesOrderScreen() { const [scannedBarcode, setScannedBarcode] = useState<string | null>(null);
const { data: product, isLoading } = useProductByBarcodeQuery(scannedBarcode || '');
const handleScanResult = useCallback((code: string) => { setScannedBarcode(code); // Auto-add to cart when product loaded }, []);
useEffect(() => { if (product) { addToCart(product, 1); setScannedBarcode(null); // Reset for next scan } }, [product]);
return ( <View> <Button onPress={() => navigate('camera', { enableScan: true })}> Scan Barcode </Button> {isLoading && <Text>Looking up product...</Text>} </View> );}Barcode Camera Integration
Section titled “Barcode Camera Integration”CommonCamera Component
Section titled “CommonCamera Component”interface CommonCameraProps { mode: 'scan' | 'photo'; enableScan?: boolean; onScanResult?: (barcode: string) => void; onPhotoTaken?: (uri: string) => void;}
// Usage<CommonCamera mode="scan" enableScan={true} onScanResult={handleScanResult}/>Navigation Pattern
Section titled “Navigation Pattern”// From sales order screenfunction handleOpenScanner() { navigation.navigate('camera', { mode: 'scan', enableScan: true, onScanResult: (code) => { handleScanResult(code); navigation.goBack(); }, });}Supported Barcode Formats
Section titled “Supported Barcode Formats”The camera scanner supports the following formats:
| Format | Description | Common Use |
|---|---|---|
| EAN-13 | 13-digit European Article Number | Retail products |
| EAN-8 | 8-digit EAN (small packages) | Small items |
| UPC-A | 12-digit Universal Product Code | US products |
| Code-128 | Alphanumeric barcode | Logistics, inventory |
| QR Code | 2D matrix code | URLs, complex data |
Note: Product barcodes in Merq are typically EAN-13 or UPC-A.
Caching Strategy
Section titled “Caching Strategy”Query Cache
Section titled “Query Cache”- staleTime: 5 minutes
- cacheTime: 1 hour
- networkMode: offlineFirst
Offline Behavior
Section titled “Offline Behavior”- First scan (online): Fetch from API, cache result
- Same barcode scan (offline): Return cached result
- Same barcode scan (after 5 min): Try fetch, fall back to cache if offline
Manual Cache Invalidation
Section titled “Manual Cache Invalidation”// After product update (admin only)queryClient.invalidateQueries({ queryKey: ['product', 'barcode'],});