diff --git a/htdocs/admin/barcode.php b/htdocs/admin/barcode.php
index ee0fcd5d130..d03d227470a 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
@@ -251,7 +321,16 @@ print load_fiche_titre($langs->trans("BarcodeEncodeModule"), '', '');
if (empty($conf->use_javascript_ajax)) {
print '';
+
+ 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;
+ }
+}