dolibarr.handybarcodescanner/ajax/findproduct.php
data cf244aac31 Initial release: HandyBarcodeScanner Dolibarr Module v1.0
Features:
- Order mode: Scan products, select supplier, add to draft orders
- Shop mode: Scan products, access supplier shop links
- Inventory mode: Scan products, update stock levels

- Touch-optimized mobile interface
- QuaggaJS for browser-based barcode scanning
- Supports EAN-13, EAN-8, Code128, Code39
- Integrated into Dolibarr standard layout
- Admin settings with QR code for mobile access
- German and English translations

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-17 11:08:17 +01:00

138 lines
3.9 KiB
PHP

<?php
/* Copyright (C) 2026 Eduard Wisch <data@data-it-solution.de>
*
* AJAX: Find product by barcode
* Searches in: product.barcode, product_fournisseur_price (supplier EAN)
*/
if (!defined('NOTOKENRENEWAL')) {
define('NOTOKENRENEWAL', '1');
}
if (!defined('NOREQUIREMENU')) {
define('NOREQUIREMENU', '1');
}
if (!defined('NOREQUIREHTML')) {
define('NOREQUIREHTML', '1');
}
if (!defined('NOREQUIREAJAX')) {
define('NOREQUIREAJAX', '1');
}
// Load Dolibarr environment
$res = 0;
if (!$res && file_exists("../../main.inc.php")) {
$res = @include "../../main.inc.php";
}
if (!$res && file_exists("../../../main.inc.php")) {
$res = @include "../../../main.inc.php";
}
if (!$res && file_exists("../../../../main.inc.php")) {
$res = @include "../../../../main.inc.php";
}
if (!$res) {
die(json_encode(['success' => false, 'error' => 'Failed to load Dolibarr']));
}
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
header('Content-Type: application/json; charset=utf-8');
// Security check
if (!$user->hasRight('produit', 'lire') && !$user->hasRight('product', 'read')) {
echo json_encode(['success' => false, 'error' => 'Access denied']);
exit;
}
$barcode = GETPOST('barcode', 'alphanohtml');
if (empty($barcode)) {
echo json_encode(['success' => false, 'error' => 'No barcode provided']);
exit;
}
$product = new Product($db);
$found = false;
// 1. Search by product barcode
$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."product WHERE barcode = '".$db->escape($barcode)."' AND entity IN (".getEntity('product').")";
$resql = $db->query($sql);
if ($resql && $db->num_rows($resql) > 0) {
$obj = $db->fetch_object($resql);
$product->fetch($obj->rowid);
$found = true;
}
// 2. Search by supplier barcode (EAN in product_fournisseur_price)
if (!$found) {
$sql = "SELECT DISTINCT pfp.fk_product FROM ".MAIN_DB_PREFIX."product_fournisseur_price as pfp";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON pfp.fk_product = p.rowid";
$sql .= " WHERE (pfp.barcode = '".$db->escape($barcode)."' OR pfp.ref_fourn = '".$db->escape($barcode)."')";
$sql .= " AND p.entity IN (".getEntity('product').")";
$resql = $db->query($sql);
if ($resql && $db->num_rows($resql) > 0) {
$obj = $db->fetch_object($resql);
$product->fetch($obj->fk_product);
$found = true;
}
}
// 3. Search by product ref (in case barcode equals ref)
if (!$found) {
$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."product WHERE ref = '".$db->escape($barcode)."' AND entity IN (".getEntity('product').")";
$resql = $db->query($sql);
if ($resql && $db->num_rows($resql) > 0) {
$obj = $db->fetch_object($resql);
$product->fetch($obj->rowid);
$found = true;
}
}
if (!$found) {
echo json_encode(['success' => false, 'error' => 'Product not found']);
exit;
}
// Get supplier prices
$suppliers = [];
$productFourn = new ProductFournisseur($db);
$resql = $productFourn->list_product_fournisseur_price($product->id);
if ($resql) {
foreach ($resql as $supplierPrice) {
// Get supplier info
$supplierSql = "SELECT nom, url FROM ".MAIN_DB_PREFIX."societe WHERE rowid = ".((int) $supplierPrice->fourn_id);
$supplierRes = $db->query($supplierSql);
$supplierObj = $db->fetch_object($supplierRes);
$suppliers[] = [
'id' => $supplierPrice->fourn_id,
'name' => $supplierObj->nom ?? 'Unknown',
'price' => (float) $supplierPrice->fourn_price,
'ref_fourn' => $supplierPrice->ref_fourn ?? '',
'url' => $supplierObj->url ?? ''
];
}
// Sort by price (cheapest first)
usort($suppliers, function($a, $b) {
return $a['price'] <=> $b['price'];
});
}
// Response
$response = [
'success' => true,
'product' => [
'id' => $product->id,
'ref' => $product->ref,
'label' => $product->label,
'barcode' => $product->barcode,
'stock' => (float) $product->stock_reel,
'stock_unit' => $product->fk_unit ? $product->getLabelOfUnit() : 'Stk',
'suppliers' => $suppliers
]
];
echo json_encode($response);