diff --git a/htdocs/langs/en_US/cashdesk.lang b/htdocs/langs/en_US/cashdesk.lang index 5792e015040..a5d4e9062e4 100644 --- a/htdocs/langs/en_US/cashdesk.lang +++ b/htdocs/langs/en_US/cashdesk.lang @@ -134,3 +134,5 @@ PrintWithoutDetailsButton=Add "Print without details" button PrintWithoutDetailsLabelDefault=Line label by default on printing without details PrintWithoutDetails=Print without details YearNotDefined=Year is not defined +TakeposBarcodeRuleToInsertProduct=Barcode rule to insert product +TakeposBarcodeRuleToInsertProductDesc=Format rule "ref:NB+qu:NB+qd:NB+other:NB" where NB is the number of characters to compose a part of the barcode with : diff --git a/htdocs/langs/fr_FR/cashdesk.lang b/htdocs/langs/fr_FR/cashdesk.lang index 31218616e1c..c101e8c7931 100644 --- a/htdocs/langs/fr_FR/cashdesk.lang +++ b/htdocs/langs/fr_FR/cashdesk.lang @@ -134,3 +134,5 @@ PrintWithoutDetailsButton=Affiche le bouton "Générer sans les détails" PrintWithoutDetailsLabelDefault=Libellé de ligne par défaut à l'impression sans détails PrintWithoutDetails=Générer sans les détails YearNotDefined=L'année n'est pas définie +TakeposBarcodeRuleToInsertProduct=Règle sur le code-barre pour insérer un produit +TakeposBarcodeRuleToInsertProductDesc=Règle sous la forme "ref:NB+qu:NB+qd:NB+other:NB" où NB correpond au nombre de caractères composant la partie du code-barre avec : diff --git a/htdocs/takepos/admin/setup.php b/htdocs/takepos/admin/setup.php index 870fe1844ad..e631776490a 100644 --- a/htdocs/takepos/admin/setup.php +++ b/htdocs/takepos/admin/setup.php @@ -82,6 +82,9 @@ if ($action == 'set') { $res = dolibarr_set_const($db, "TAKEPOS_SUMUP_AFFILIATE", GETPOST('TAKEPOS_SUMUP_AFFILIATE', 'alpha'), 'chaine', 0, '', $conf->entity); $res = dolibarr_set_const($db, "TAKEPOS_SUMUP_APPID", GETPOST('TAKEPOS_SUMUP_APPID', 'alpha'), 'chaine', 0, '', $conf->entity); } + if (!empty($conf->barcode->enabled)) { + $res = dolibarr_set_const($db, 'TAKEPOS_BARCODE_RULE_TO_INSERT_PRODUCT', GETPOST('TAKEPOS_BARCODE_RULE_TO_INSERT_PRODUCT', 'alpha'), 'chaine', 0, '', $conf->entity); + } dol_syslog("admin/cashdesk: level ".GETPOST('level', 'alpha')); @@ -384,6 +387,15 @@ print ''; print ajax_constantonoff("TAKEPOS_SHOW_HT", array(), $conf->entity, 0, 0, 1, 0); print "\n"; +// Barcode rule to insert product +if (!empty($conf->barcode->enabled)) { + print ''; + print $form->textwithpicto($langs->trans("TakeposBarcodeRuleToInsertProduct"), $langs->trans("TakeposBarcodeRuleToInsertProductDesc")); + print ''; + print ''; + print "\n"; +} + // Numbering module //print ''; //print $langs->trans("BillsNumberingModule"); diff --git a/htdocs/takepos/ajax/ajax.php b/htdocs/takepos/ajax/ajax.php index 58c1906cd42..9b44e536a2b 100644 --- a/htdocs/takepos/ajax/ajax.php +++ b/htdocs/takepos/ajax/ajax.php @@ -111,6 +111,102 @@ if ($action == 'getProducts') { } } + if (!empty($conf->barcode->enabled) && !empty($conf->global->TAKEPOS_BARCODE_RULE_TO_INSERT_PRODUCT)) { + $barcode_rules = $conf->global->TAKEPOS_BARCODE_RULE_TO_INSERT_PRODUCT; + $barcode_rules_list = array(); + + // get barcode rules + $barcode_char_nb = 0; + $barcode_rules_arr = explode('+', $barcode_rules); + foreach ($barcode_rules_arr as $barcode_rules_values) { + $barcode_rules_values_arr = explode(':', $barcode_rules_values); + if (count($barcode_rules_values_arr) == 2) { + $char_nb = intval($barcode_rules_values_arr[1]); + $barcode_rules_list[] = array('code' => $barcode_rules_values_arr[0], 'char_nb' => $char_nb); + $barcode_char_nb += $char_nb; + } + } + + $barcode_value_list = array(); + $barcode_offset = 0; + $barcode_length = dol_strlen($term); + if ($barcode_length == $barcode_char_nb) { + $rows = array(); + + // split term with barcode rules + foreach ($barcode_rules_list as $barcode_rule_arr) { + $code = $barcode_rule_arr['code']; + $char_nb = $barcode_rule_arr['char_nb']; + $barcode_value_list[$code] = substr($term, $barcode_offset, $char_nb); + $barcode_offset += $char_nb; + } + + if (isset($barcode_value_list['ref'])) { + //search product from reference + $sql = "SELECT rowid, ref, label, tosell, tobuy, barcode, price"; + $sql .= " FROM " . $db->prefix() . "product as p"; + $sql .= " WHERE entity IN (" . getEntity('product') . ")"; + $sql .= " AND ref = '" . $db->escape($barcode_value_list['ref']) . "'"; + if ($filteroncategids) { + $sql .= " AND EXISTS (SELECT cp.fk_product FROM " . $db->prefix() . "categorie_product as cp WHERE cp.fk_product = p.rowid AND cp.fk_categorie IN (".$db->sanitize($filteroncategids)."))"; + } + $sql .= " AND tosell = 1"; + + $resql = $db->query($sql); + if ($resql && $db->num_rows($resql) == 1) { + if ($obj = $db->fetch_object($resql)) { + $qty = 1; + if (isset($barcode_value_list['qu'])) { + $qty_str = $barcode_value_list['qu']; + if (isset($barcode_value_list['qd'])) { + $qty_str .= '.' . $barcode_value_list['qd']; + } + $qty = floatval($qty_str); + } + + $ig = '../public/theme/common/nophoto.png'; + if (empty($conf->global->TAKEPOS_HIDE_PRODUCT_IMAGES)) { + $objProd = new Product($db); + $objProd->fetch($obj->rowid); + $image = $objProd->show_photos('product', $conf->product->multidir_output[$objProd->entity], 'small', 1); + + $match = array(); + preg_match('@src="([^"]+)"@', $image, $match); + $file = array_pop($match); + + if ($file != '') { + if (!defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) { + $ig = $file.'&cache=1'; + } else { + $ig = $file.'&cache=1&publictakepos=1&modulepart=product'; + } + } + } + + $rows[] = array( + 'rowid' => $obj->rowid, + 'ref' => $obj->ref, + 'label' => $obj->label, + 'tosell' => $obj->tosell, + 'tobuy' => $obj->tobuy, + 'barcode' => $obj->barcode, + 'price' => $obj->price, + 'object' => 'product', + 'img' => $ig, + 'qty' => $qty, + ); + } + $db->free($resql); + } + } + + if (count($rows) == 1) { + echo json_encode($rows); + exit(); + } + } + } + $sql = 'SELECT rowid, ref, label, tosell, tobuy, barcode, price' ; // Add fields from hooks $parameters=array(); diff --git a/htdocs/takepos/index.php b/htdocs/takepos/index.php index 0b159e96a38..24a30b8ea7e 100644 --- a/htdocs/takepos/index.php +++ b/htdocs/takepos/index.php @@ -430,7 +430,7 @@ function MoreProducts(moreorless) { ClearSearch(); } -function ClickProduct(position) { +function ClickProduct(position, qty = 1) { console.log("ClickProduct"); $('#proimg'+position).animate({opacity: '0.5'}, 1); $('#proimg'+position).animate({opacity: '1'}, 100); @@ -440,10 +440,10 @@ function ClickProduct(position) { } else{ idproduct=$('#prodiv'+position).data('rowid'); - console.log("Click on product at position "+position+" for idproduct "+idproduct); + console.log("Click on product at position "+position+" for idproduct "+idproduct+", qty="+qty); if (idproduct=="") return; // Call page invoice.php to generate the section with product lines - $("#poslines").load("invoice.php?action=addline&token=&place="+place+"&idproduct="+idproduct+"&selectedline="+selectedline, function() { + $("#poslines").load("invoice.php?action=addline&token=&place="+place+"&idproduct="+idproduct+"&selectedline="+selectedline+"&qty="+qty, function() { global->TAKEPOS_CUSTOMER_DISPLAY)) echo "CustomerDisplay();";?> }); } @@ -619,9 +619,9 @@ function Search2(keyCodeForEnter) { console.log("There is only 1 answer with barcode matching the search, so we change the thirdparty "+data[0]['rowid']); ChangeThirdparty(data[0]['rowid']); } - else if ($('#search').val() == data[0]['barcode'] && 'product' == data[0]['object']) { + else if ('product' == data[0]['object']) { console.log("There is only 1 answer with barcode matching the search, so we add the product in basket"); - ClickProduct(0); + ClickProduct(0, data[0]['qty']); } } if (eventKeyCode == keyCodeForEnter){ diff --git a/htdocs/takepos/invoice.php b/htdocs/takepos/invoice.php index f1d4f62587f..66a75ef7050 100644 --- a/htdocs/takepos/invoice.php +++ b/htdocs/takepos/invoice.php @@ -505,6 +505,7 @@ if ($action == "addline") { $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0); + $qty = GETPOSTISSET('qty') ? GETPOST('qty', 'int') : 1; $price = $datapriceofproduct['pu_ht']; $price_ttc = $datapriceofproduct['pu_ttc']; //$price_min = $datapriceofproduct['price_min']; @@ -538,7 +539,7 @@ if ($action == "addline") { foreach ($invoice->lines as $line) { if ($line->product_ref == $prod->ref) { if ($line->special_code==4) continue; // If this line is sended to printer create new line - $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $line->qty + 1, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit); + $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $line->qty + $qty, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit); if ($result < 0) { dol_htmloutput_errors($invoice->error, $invoice->errors, 1); } else { @@ -550,7 +551,7 @@ if ($action == "addline") { } if ($idoflineadded <= 0) { $invoice->fetch_thirdparty(); - $idoflineadded = $invoice->addline($prod->description, $price, 1, $tva_tx, $localtax1_tx, $localtax2_tx, $idproduct, $customer->remise_percent, '', 0, 0, 0, '', $price_base_type, $price_ttc, $prod->type, -1, 0, '', 0, (!empty($parent_line)) ? $parent_line : '', null, '', '', 0, 100, '', null, 0); + $idoflineadded = $invoice->addline($prod->description, $price, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idproduct, $customer->remise_percent, '', 0, 0, 0, '', $price_base_type, $price_ttc, $prod->type, -1, 0, '', 0, (!empty($parent_line)) ? $parent_line : '', null, '', '', 0, 100, '', null, 0); if (!empty($conf->global->TAKEPOS_CUSTOMER_DISPLAY)) { $CUSTOMER_DISPLAY_line1 = $prod->label; $CUSTOMER_DISPLAY_line2 = price($price_ttc);