dolibarr  20.0.0-beta
mod_barcode_product_standard.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2006-2014 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2007-2012 Regis Houssin <regis.houssin@inodbox.com>
5  * Copyright (C) 2011 Juanjo Menent <jmenent@2byte.es>
6  * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
7  * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <https://www.gnu.org/licenses/>.
21  * or see https://www.gnu.org/
22  */
23 
30 require_once DOL_DOCUMENT_ROOT.'/core/modules/barcode/modules_barcode.class.php';
31 
32 
37 {
38  public $name = 'Standard'; // Model Name
39 
44  public $version = 'dolibarr'; // 'development', 'experimental', 'dolibarr'
45 
46  public $searchcode; // Search string
47 
48  public $numbitcounter; // Number of digits the counter
49 
53  public function __construct()
54  {
55  $this->code_null = 0;
56  $this->code_modifiable = 1;
57  $this->code_modifiable_invalide = 1;
58  $this->code_modifiable_null = 1;
59  $this->code_auto = 1;
60  $this->prefixIsRequired = 0;
61  }
62 
63 
69  public function info($langs)
70  {
71  global $conf, $mc;
72  global $form;
73 
74  $langs->load("products");
75 
76  $disabled = ((!empty($mc->sharings['referent']) && $mc->sharings['referent'] != $conf->entity) ? ' disabled' : '');
77 
78  $texte = $langs->trans('GenericNumRefModelDesc')."<br>\n";
79  $texte .= '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
80  $texte .= '<input type="hidden" name="token" value="'.newToken().'">';
81  $texte .= '<input type="hidden" name="page_y" value="">';
82  $texte .= '<input type="hidden" name="action" value="setModuleOptions">';
83  $texte .= '<input type="hidden" name="param1" value="BARCODE_STANDARD_PRODUCT_MASK">';
84  $texte .= '<table class="nobordernopadding" width="100%">';
85 
86  $tooltip = $langs->trans("GenericMaskCodes", $langs->transnoentities("BarCode"), $langs->transnoentities("BarCode"));
87  $tooltip .= $langs->trans("GenericMaskCodes3EAN");
88  $tooltip .= '<strong>'.$langs->trans("Example").':</strong><br>';
89  $tooltip .= '04{0000000000}? (for internal use)<br>';
90  $tooltip .= '9771234{00000}? (example of ISSN code with prefix 1234)<br>';
91  $tooltip .= '9791234{00000}? (example of ISMN code with prefix 1234)<br>';
92  //$tooltip.=$langs->trans("GenericMaskCodes5");
93 
94  // Mask parameter
95  //$texte.= '<tr><td>'.$langs->trans("Mask").' ('.$langs->trans("BarCodeModel").'):</td>';
96  $texte .= '<tr><td>'.$langs->trans("Mask").':</td>';
97  $texte .= '<td class="right">'.$form->textwithpicto('<input type="text" class="flat minwidth175" name="value1" value="'.(getDolGlobalString('BARCODE_STANDARD_PRODUCT_MASK') ? $conf->global->BARCODE_STANDARD_PRODUCT_MASK : '').'"'.$disabled.'>', $tooltip, 1, 1).'</td>';
98  $texte .= '<td class="left" rowspan="2">&nbsp; <input type="submit" class="button button-edit reposition smallpaddingimp" name="modify" value="'.$langs->trans("Modify").'"'.$disabled.'></td>';
99  $texte .= '</tr>';
100 
101  $texte .= '</table>';
102  $texte .= '</form>';
103 
104  return $texte;
105  }
106 
107 
115  public function getExample($langs, $objproduct = null)
116  {
117  $examplebarcode = $this->getNextValue($objproduct, '');
118  if (!$examplebarcode) {
119  $examplebarcode = $langs->trans('NotConfigured');
120  }
121  if ($examplebarcode == "ErrorBadMask") {
122  $langs->load("errors");
123  $examplebarcode = $langs->trans($examplebarcode);
124  }
125 
126  return $examplebarcode;
127  }
135  public function literalBarcodeType($db, $type = 0)
136  {
137  global $conf;
138  $out = '';
139 
140  $sql = "SELECT rowid, code, libelle as label";
141  $sql .= " FROM ".MAIN_DB_PREFIX."c_barcode_type";
142  $sql .= " WHERE rowid = ".(int) $type;
143  $sql .= " AND entity = ".((int) $conf->entity);
144  $result = $db->query($sql);
145  if ($result) {
146  $num = $db->num_rows($result);
147 
148  if ($num > 0) {
149  $obj = $db->fetch_object($result);
150  $out .= $obj->label; //take the label corresponding to the type rowid in the database
151  }
152  } else {
153  dol_print_error($db);
154  }
155 
156  return $out;
157  }
158 
166  public function getNextValue($objproduct = null, $type = '')
167  {
168  global $db;
169 
170  if (is_object($objproduct) && !$objproduct instanceof Product) {
171  dol_syslog(get_class($this)."::getNextValue used on incompatible".get_class($objproduct), LOG_ERR);
172  return -1;
173  }
174 
175  require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
176  require_once DOL_DOCUMENT_ROOT.'/core/lib/barcode.lib.php'; // to be able to call function barcode_gen_ean_sum($ean)
177 
178  // Get barcode type configuration for products if $type not set
179  if (empty($type)) {
180  $type = getDolGlobalString('PRODUIT_DEFAULT_BARCODE_TYPE');
181  }
182 
183  // Get Mask value
184  $mask = getDolGlobalString('BARCODE_STANDARD_PRODUCT_MASK');
185 
186  if (empty($mask)) {
187  $this->error = 'NotConfigured';
188  return '';
189  }
190 
191  $field = 'barcode';
192  $where = '';
193 
194  $now = dol_now();
195 
196  $numFinal = get_next_value($db, $mask, 'product', $field, $where, '', $now);
197  //Begin barcode with key: for barcode with key (EAN13...) calculate and substitute the last character (* or ?) used in the mask by the key
198  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...)
199  $literaltype = '';
200  $literaltype = $this->literalBarcodeType($db, $type);//get literal_Barcode_Type
201  switch ($literaltype) {
202  case 'EAN13': //EAN13 rowid = 2
203  if (strlen($numFinal) == 13) {// be sure that the mask length is correct for EAN13
204  $ean = substr($numFinal, 0, 12); //take first 12 digits
205  $eansum = barcode_gen_ean_sum($ean);
206  $ean .= $eansum; //substitute the las character by the key
207  $numFinal = $ean;
208  }
209  break;
210  // Other barcode cases with key could be written here
211  default:
212  break;
213  }
214  }
215  //End barcode with key
216 
217  return $numFinal;
218  }
219 
220 
235  public function verif($db, &$code, $product, $thirdparty_type, $type)
236  {
237  global $conf;
238 
239  //var_dump($code.' '.$product->ref.' '.$thirdparty_type);exit;
240 
241  require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
242 
243  $result = 0;
244  $code = strtoupper(trim($code));
245 
246  if (empty($code) && $this->code_null && !getDolGlobalString('BARCODE_STANDARD_PRODUCT_MASK')) {
247  $result = 0;
248  } elseif (empty($code) && (!$this->code_null || getDolGlobalString('BARCODE_STANDARD_PRODUCT_MASK'))) {
249  $result = -2;
250  } else {
251  if ($this->verif_syntax($code, $type) >= 0) {
252  $is_dispo = $this->verif_dispo($db, $code, $product);
253  if ($is_dispo != 0) {
254  $result = -3;
255  } else {
256  $result = 0;
257  }
258  } else {
259  if (dol_strlen($code) == 0) {
260  $result = -2;
261  } else {
262  $result = -1;
263  }
264  }
265  }
266 
267  dol_syslog(get_class($this)."::verif type=".$thirdparty_type." result=".$result);
268  return $result;
269  }
270 
271 
272  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
281  public function verif_dispo($db, $code, $product)
282  {
283  // phpcs:enable
284  $sql = "SELECT barcode FROM ".MAIN_DB_PREFIX."product";
285  $sql .= " WHERE barcode = '".$db->escape($code)."'";
286  $sql .= " AND entity IN (".getEntity('product').")";
287 
288  if ($product->id > 0) {
289  $sql .= " AND rowid <> ".$product->id;
290  }
291 
292  $resql = $db->query($sql);
293  if ($resql) {
294  if ($db->num_rows($resql) == 0) {
295  return 0;
296  } else {
297  return -1;
298  }
299  } else {
300  return -2;
301  }
302  }
303 
304  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
312  public function verif_syntax($codefortest, $typefortest)
313  {
314  // phpcs:enable
315  global $conf;
316 
317  $result = 0;
318 
319  // Get Mask value
320  $mask = !getDolGlobalString('BARCODE_STANDARD_PRODUCT_MASK') ? '' : $conf->global->BARCODE_STANDARD_PRODUCT_MASK;
321  if (!$mask) {
322  $this->error = 'NotConfigured';
323  return -1;
324  }
325 
326  dol_syslog(get_class($this).'::verif_syntax codefortest='.$codefortest." typefortest=".$typefortest);
327 
328  $newcodefortest = $codefortest;
329 
330  // Special case, if mask is on 12 digits instead of 13, we remove last char into code to test
331  if (in_array($typefortest, array('EAN13', 'ISBN'))) { // We remove the CRC char not included into mask
332  if (preg_match('/\{(0+)([@\+][0-9]+)?([@\+][0-9]+)?\}/i', $mask, $reg)) {
333  if (strlen($reg[1]) == 12) {
334  $newcodefortest = substr($newcodefortest, 0, 12);
335  }
336  dol_syslog(get_class($this).'::verif_syntax newcodefortest='.$newcodefortest);
337  }
338  }
339 
340  $result = check_value($mask, $newcodefortest);
341  if (is_string($result)) {
342  $this->error = $result;
343  return -1;
344  }
345 
346  return $result;
347  }
348 }
barcode_gen_ean_sum($ean)
Calculate EAN sum.
Parent class for barcode numbering models.
Class to manage products or services.
Class to manage barcode with standard rule.
getNextValue($objproduct=null, $type='')
Return next value.
verif_dispo($db, $code, $product)
Return if a code is used (by other element)
verif($db, &$code, $product, $thirdparty_type, $type)
Check validity of code according to its rules.
getExample($langs, $objproduct=null)
Return an example of result returned by getNextValue.
literalBarcodeType($db, $type=0)
Return literal barcode type code from numerical rowid type of barcode.
verif_syntax($codefortest, $typefortest)
Return if a barcode value match syntax.
info($langs)
Return description of module.
if(isModEnabled('invoice') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&!getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD') && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') && $user->hasRight('tax', 'charges', 'lire')) if(isModEnabled('invoice') &&isModEnabled('order') && $user->hasRight("commande", "lire") &&!getDolGlobalString('WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER')) $sql
Social contributions to pay.
Definition: index.php:745
check_value($mask, $value)
Check value.
get_next_value($db, $mask, $table, $field, $where='', $objsoc='', $date='', $mode='next', $bentityon=true, $objuser=null, $forceentity=null)
Return last or next value for a mask (according to area we should not reset)
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
dol_now($mode='auto')
Return date for now.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.