diff --git a/htdocs/admin/barcode.php b/htdocs/admin/barcode.php
index ee0fcd5d130..57c32d79318 100644
--- a/htdocs/admin/barcode.php
+++ b/htdocs/admin/barcode.php
@@ -55,6 +55,16 @@ if ($action == 'setbarcodeproducton') {
$res = dolibarr_del_const($db, "BARCODE_PRODUCT_ADDON_NUM", $conf->entity);
}
+if ($action == 'setbarcodethirdpartyon') {
+ $barcodenumberingmodule = GETPOST('value', 'alpha');
+ $res = dolibarr_set_const($db, "BARCODE_THIRDPARTY_ADDON_NUM", $barcodenumberingmodule, 'chaine', 0, '', $conf->entity);
+ if ($barcodenumberingmodule == 'mod_barcode_thirdparty_standard' && empty($conf->global->BARCODE_STANDARD_THIRDPARTY_MASK)) {
+ $res = dolibarr_set_const($db, "BARCODE_STANDARD_THIRDPARTY_MASK", '020{000000000}', 'chaine', 0, '', $conf->entity);
+ }
+} elseif ($action == 'setbarcodethirdpartyoff') {
+ $res = dolibarr_del_const($db, "BARCODE_THIRDPARTY_ADDON_NUM", $conf->entity);
+}
+
if ($action == 'setcoder') {
$coder = GETPOST('coder', 'alpha');
$code_id = GETPOST('code_id', 'int');
@@ -241,6 +251,66 @@ if ($conf->product->enabled) {
print '';
}
+// Select barcode numbering module
+if ($conf->societe->enabled) {
+ print load_fiche_titre($langs->trans("BarCodeNumberManager")." (".$langs->trans("ThirdParty").")", '', '');
+
+ print '
';
+ print '
';
+ print '';
+ print '| '.$langs->trans("Name").' | ';
+ print ''.$langs->trans("Description").' | ';
+ print ''.$langs->trans("Example").' | ';
+ print ''.$langs->trans("Status").' | ';
+ print ''.$langs->trans("ShortInfo").' | ';
+ print "
\n";
+
+ $dirbarcodenum = array_merge(array('/core/modules/barcode/'), $conf->modules_parts['barcode']);
+
+ foreach ($dirbarcodenum as $dirroot) {
+ $dir = dol_buildpath($dirroot, 0);
+
+ $handle = @opendir($dir);
+ if (is_resource($handle)) {
+ while (($file = readdir($handle)) !== false) {
+ if (preg_match('/^mod_barcode_thirdparty_.*php$/', $file)) {
+ $file = substr($file, 0, dol_strlen($file) - 4);
+
+ try {
+ dol_include_once($dirroot.$file.'.php');
+ } catch (Exception $e) {
+ dol_syslog($e->getMessage(), LOG_ERR);
+ }
+
+ $modBarCode = new $file();
+ print '';
+ print '| '.(isset($modBarCode->name) ? $modBarCode->name : $modBarCode->nom)." | \n";
+ print $modBarCode->info($langs);
+ print ' | ';
+ print ''.$modBarCode->getExample($langs)." | \n";
+
+ if (!empty($conf->global->BARCODE_THIRDPARTY_ADDON_NUM) && $conf->global->BARCODE_THIRDPARTY_ADDON_NUM == "$file") {
+ print '';
+ print img_picto($langs->trans("Activated"), 'switch_on');
+ print ' | ';
+ } else {
+ print '';
+ print img_picto($langs->trans("Disabled"), 'switch_off');
+ print ' | ';
+ }
+ print '';
+ $s = $modBarCode->getToolTip($langs, null, -1);
+ print $form->textwithpicto('', $s, 1);
+ print ' | ';
+ print "
\n";
+ }
+ }
+ closedir($handle);
+ }
+ }
+ print "
\n";
+ print '
';
+}
/*
* CHOIX ENCODAGE
diff --git a/htdocs/barcode/codeinit.php b/htdocs/barcode/codeinit.php
index b4e365fe018..95fb287d2b8 100644
--- a/htdocs/barcode/codeinit.php
+++ b/htdocs/barcode/codeinit.php
@@ -35,7 +35,8 @@ $month = dol_print_date($now, '%m');
$day = dol_print_date($now, '%d');
$forbarcode = GETPOST('forbarcode');
$fk_barcode_type = GETPOST('fk_barcode_type');
-$eraseallbarcode = GETPOST('eraseallbarcode');
+$eraseallproductbarcode = GETPOST('eraseallproductbarcode');
+$eraseallthirdpartybarcode = GETPOST('eraseallthirdpartybarcode');
$action = GETPOST('action', 'aZ09');
@@ -43,6 +44,7 @@ $producttmp = new Product($db);
$thirdpartytmp = new Societe($db);
$modBarCodeProduct = '';
+$modBarCodeThirdparty = '';
$maxperinit = 1000;
@@ -51,6 +53,106 @@ $maxperinit = 1000;
* Actions
*/
+// Define barcode template for third-party
+if (!empty($conf->global->BARCODE_THIRDPARTY_ADDON_NUM)) {
+ $dirbarcodenum = array_merge(array('/core/modules/barcode/'), $conf->modules_parts['barcode']);
+
+ foreach ($dirbarcodenum as $dirroot) {
+ $dir = dol_buildpath($dirroot, 0);
+
+ $handle = @opendir($dir);
+ if (is_resource($handle)) {
+ while (($file = readdir($handle)) !== false) {
+ if (preg_match('/^mod_barcode_thirdparty_.*php$/', $file)) {
+ $file = substr($file, 0, dol_strlen($file) - 4);
+
+ try {
+ dol_include_once($dirroot.$file.'.php');
+ } catch (Exception $e) {
+ dol_syslog($e->getMessage(), LOG_ERR);
+ }
+
+ $modBarCodeThirdparty = new $file();
+ break;
+ }
+ }
+ closedir($handle);
+ }
+ }
+}
+
+if ($action == 'initbarcodethirdparties') {
+ if (!is_object($modBarCodeThirdparty)) {
+ $error++;
+ setEventMessages($langs->trans("NoBarcodeNumberingTemplateDefined"), null, 'errors');
+ }
+
+ if (!$error) {
+ $thirdpartystatic = new Societe($db);
+
+ $db->begin();
+
+ $nbok = 0;
+ if (!empty($eraseallthirdpartybarcode)) {
+ $sql = "UPDATE ".MAIN_DB_PREFIX."societe";
+ $sql .= " SET barcode = NULL";
+ $resql = $db->query($sql);
+ if ($resql) {
+ setEventMessages($langs->trans("AllBarcodeReset"), null, 'mesgs');
+ } else {
+ $error++;
+ dol_print_error($db);
+ }
+ } else {
+ $sql = "SELECT rowid";
+ $sql .= " FROM ".MAIN_DB_PREFIX."societe";
+ $sql .= " WHERE barcode IS NULL or barcode = ''";
+ $sql .= $db->order("datec", "ASC");
+ $sql .= $db->plimit($maxperinit);
+
+ dol_syslog("codeinit", LOG_DEBUG);
+ $resql = $db->query($sql);
+ if ($resql) {
+ $num = $db->num_rows($resql);
+
+ $i = 0; $nbok = $nbtry = 0;
+ while ($i < min($num, $maxperinit)) {
+ $obj = $db->fetch_object($resql);
+ if ($obj) {
+ $thirdpartystatic->id = $obj->rowid;
+ $nextvalue = $modBarCodeThirdparty->getNextValue($thirdpartystatic, '');
+
+ $result = $thirdpartystatic->setValueFrom('barcode', $nextvalue, '', '', 'text', '', $user, 'THIRDPARTY_MODIFY');
+
+ $nbtry++;
+ if ($result > 0) {
+ $nbok++;
+ }
+ }
+
+ $i++;
+ }
+ } else {
+ $error++;
+ dol_print_error($db);
+ }
+
+ if (!$error) {
+ setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs');
+ }
+ }
+
+ if (!$error) {
+ //$db->rollback();
+ $db->commit();
+ } else {
+ $db->rollback();
+ }
+ }
+
+ $action = '';
+}
+
// Define barcode template for products
if (!empty($conf->global->BARCODE_PRODUCT_ADDON_NUM)) {
$dirbarcodenum = array_merge(array('/core/modules/barcode/'), $conf->modules_parts['barcode']);
@@ -91,7 +193,7 @@ if ($action == 'initbarcodeproducts') {
$db->begin();
$nbok = 0;
- if (!empty($eraseallbarcode)) {
+ if (!empty($eraseallproductbarcode)) {
$sql = "UPDATE ".MAIN_DB_PREFIX."product";
$sql .= " SET barcode = NULL";
$resql = $db->query($sql);
@@ -155,7 +257,6 @@ if ($action == 'initbarcodeproducts') {
}
-
/*
* View
*/
@@ -180,16 +281,25 @@ print '
';
//print img_picto('','puce').' '.$langs->trans("PrintsheetForOneBarCode").'
';
//print '
';
-print '';
}
// For products
if ($conf->product->enabled || $conf->product->service) {
- // Example 1 : Adding jquery code
- print '';
+ print '';
}
@@ -297,7 +427,6 @@ print $langs->trans("ClickHereToGoTo").' : sharings['referent']) && $mc->sharings['referent'] != $conf->entity) ? ' disabled' : '');
+
+ $texte = $langs->trans('GenericNumRefModelDesc')."
\n";
+ $texte .= '';
+
+ return $texte;
+ }
+
+
+ /**
+ * Return an example of result returned by getNextValue
+ *
+ * @param Translate $langs Object langs
+ * @param Societe $objthirdparty Object third-party
+ * @return string Return string example
+ */
+ public function getExample($langs, $objthirdparty = 0)
+ {
+ $examplebarcode = $this->getNextValue($objthirdparty, '');
+ if (!$examplebarcode) {
+ $examplebarcode = $langs->trans('NotConfigured');
+ }
+ if ($examplebarcode == "ErrorBadMask") {
+ $langs->load("errors");
+ $examplebarcode = $langs->trans($examplebarcode);
+ }
+
+ return $examplebarcode;
+ }
+ /**
+ * Return literal barcode type code from numerical rowid type of barcode
+ *
+ * @param Database $db Database
+ * @param int $type Type of barcode (EAN, ISBN, ...) as rowid
+ * @return string
+ */
+ public function literalBarcodeType($db, $type = '')
+ {
+ global $conf;
+ $out = '';
+
+ $sql = "SELECT rowid, code, libelle as label";
+ $sql .= " FROM ".MAIN_DB_PREFIX."c_barcode_type";
+ $sql .= " WHERE rowid = '".$db->escape($type)."'";
+ $sql .= " AND entity = ".((int) $conf->entity);
+ $result = $db->query($sql);
+ if ($result) {
+ $num = $db->num_rows($result);
+
+ if ($num > 0) {
+ $obj = $db->fetch_object($result);
+ $out .= $obj->label; //take the label corresponding to the type rowid in the database
+ }
+ } else {
+ dol_print_error($db);
+ }
+
+ return $out;
+ }
+ /**
+ * Return next value
+ *
+ * @param Societe $objthirdparty Object third-party
+ * @param string $type Type of barcode (EAN, ISBN, ...)
+ * @return string Value if OK, '' if module not configured, <0 if KO
+ */
+ public function getNextValue($objthirdparty, $type = '')
+ {
+ global $db, $conf;
+
+ require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
+ require_once DOL_DOCUMENT_ROOT.'/core/lib/barcode.lib.php'; // to be able to call function barcode_gen_ean_sum($ean)
+
+ if (empty($type)) {
+ $type = $conf->global->GENBARCODE_BARCODETYPE_THIRDPARTY;
+ } //get barcode type configuration for companies if $type not set
+
+ // TODO
+
+ // Get Mask value
+ $mask = '';
+ if (!empty($conf->global->BARCODE_STANDARD_THIRDPARTY_MASK)) {
+ $mask = $conf->global->BARCODE_STANDARD_THIRDPARTY_MASK;
+ }
+
+ if (empty($mask)) {
+ $this->error = 'NotConfigured';
+ return '';
+ }
+
+ $field = 'barcode';
+ $where = '';
+
+ $now = dol_now();
+
+ $numFinal = get_next_value($db, $mask, 'societe', $field, $where, '', $now);
+ //Begin barcode with key: for barcode with key (EAN13...) calculate and substitute the last character (* or ?) used in the mask by the key
+ if ((substr($numFinal, -1)=='*') or (substr($numFinal, -1)=='?')) { // if last mask character is * or ? a joker, probably we have to calculate a key as last character (EAN13...)
+ $literaltype = '';
+ $literaltype = $this->literalBarcodeType($db, $type);//get literal_Barcode_Type
+ switch ($literaltype) {
+ case 'EAN13': //EAN13 rowid = 2
+ if (strlen($numFinal)==13) {// be sure that the mask length is correct for EAN13
+ $ean = substr($numFinal, 0, 12); //take first 12 digits
+ $eansum = barcode_gen_ean_sum($ean);
+ $ean .= $eansum; //substitute the las character by the key
+ $numFinal = $ean;
+ }
+ break;
+ // Other barcode cases with key could be written here
+ default:
+ break;
+ }
+ }
+ //End barcode with key
+ return $numFinal;
+ }
+
+
+ /**
+ * Check validity of code according to its rules
+ *
+ * @param DoliDB $db Database handler
+ * @param string $code Code to check/correct
+ * @param Societe $thirdparty Object third-party
+ * @param int $thirdparty_type 0 = customer/prospect , 1 = supplier
+ * @param string $type type of barcode (EAN, ISBN, ...)
+ * @return int 0 if OK
+ * -1 ErrorBadCustomerCodeSyntax
+ * -2 ErrorCustomerCodeRequired
+ * -3 ErrorCustomerCodeAlreadyUsed
+ * -4 ErrorPrefixRequired
+ */
+ public function verif($db, &$code, $thirdparty, $thirdparty_type, $type)
+ {
+ global $conf;
+
+ //var_dump($code.' '.$thirdparty->ref.' '.$thirdparty_type);exit;
+
+ require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
+
+ $result = 0;
+ $code = strtoupper(trim($code));
+
+ if (empty($code) && $this->code_null && empty($conf->global->BARCODE_STANDARD_THIRDPARTY_MASK)) {
+ $result = 0;
+ } elseif (empty($code) && (!$this->code_null || !empty($conf->global->BARCODE_STANDARD_THIRDPARTY_MASK))) {
+ $result = -2;
+ } else {
+ if ($this->verif_syntax($code, $type) >= 0) {
+ $is_dispo = $this->verif_dispo($db, $code, $thirdparty);
+ if ($is_dispo <> 0) {
+ $result = -3;
+ } else {
+ $result = 0;
+ }
+ } else {
+ if (dol_strlen($code) == 0) {
+ $result = -2;
+ } else {
+ $result = -1;
+ }
+ }
+ }
+
+ dol_syslog(get_class($this)."::verif type=".$thirdparty_type." result=".$result);
+ return $result;
+ }
+
+
+ // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+ /**
+ * Return if a code is used (by other element)
+ *
+ * @param DoliDB $db Handler acces base
+ * @param string $code Code to check
+ * @param Societe $thirdparty Objet third-party
+ * @return int 0 if available, <0 if KO
+ */
+ public function verif_dispo($db, $code, $thirdparty)
+ {
+ // phpcs:enable
+ $sql = "SELECT barcode FROM ".MAIN_DB_PREFIX."societe";
+ $sql .= " WHERE barcode = '".$db->escape($code)."'";
+ if ($thirdparty->id > 0) {
+ $sql .= " AND rowid <> ".$thirdparty->id;
+ }
+
+ $resql = $db->query($sql);
+ if ($resql) {
+ if ($db->num_rows($resql) == 0) {
+ return 0;
+ } else {
+ return -1;
+ }
+ } else {
+ return -2;
+ }
+ }
+
+ // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+ /**
+ * Return if a barcode value match syntax
+ *
+ * @param string $codefortest Code to check syntax
+ * @param string $typefortest Type of barcode (ISBN, EAN, ...)
+ * @return int 0 if OK, <0 if KO
+ */
+ public function verif_syntax($codefortest, $typefortest)
+ {
+ // phpcs:enable
+ global $conf;
+
+ $result = 0;
+
+ // Get Mask value
+ $mask = empty($conf->global->BARCODE_STANDARD_THIRDPARTY_MASK) ? '' : $conf->global->BARCODE_STANDARD_THIRDPARTY_MASK;
+ if (!$mask) {
+ $this->error = 'NotConfigured';
+ return -1;
+ }
+
+ dol_syslog(get_class($this).'::verif_syntax codefortest='.$codefortest." typefortest=".$typefortest);
+
+ $newcodefortest = $codefortest;
+
+ // Special case, if mask is on 12 digits instead of 13, we remove last char into code to test
+ if (in_array($typefortest, array('EAN13', 'ISBN'))) { // We remove the CRC char not included into mask
+ if (preg_match('/\{(0+)([@\+][0-9]+)?([@\+][0-9]+)?\}/i', $mask, $reg)) {
+ if (strlen($reg[1]) == 12) {
+ $newcodefortest = substr($newcodefortest, 0, 12);
+ }
+ dol_syslog(get_class($this).'::verif_syntax newcodefortest='.$newcodefortest);
+ }
+ }
+
+ $result = check_value($mask, $newcodefortest);
+ if (is_string($result)) {
+ $this->error = $result;
+ return -1;
+ }
+
+ return $result;
+ }
+}