dolibarr  13.0.2
reception.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2003-2008 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@capnetworks.com>
4  * Copyright (C) 2007 Franky Van Liedekerke <franky.van.liedekerke@telenet.be>
5  * Copyright (C) 2006-2012 Laurent Destailleur <eldy@users.sourceforge.net>
6  * Copyright (C) 2011-2017 Juanjo Menent <jmenent@2byte.es>
7  * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
8  * Copyright (C) 2014 Cedric GROSS <c.gross@kreiz-it.fr>
9  * Copyright (C) 2014-2015 Marcos GarcĂ­a <marcosgdf@gmail.com>
10  * Copyright (C) 2014-2020 Francis Appels <francis.appels@yahoo.com>
11  * Copyright (C) 2015 Claudio Aschieri <c.aschieri@19.coop>
12  * Copyright (C) 2016 Ferran Marcet <fmarcet@2byte.es>
13  * Copyright (C) 2018 Quentin Vial-Gouteyron <quentin.vial-gouteyron@atm-consulting.fr>
14  *
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 3 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program. If not, see <https://www.gnu.org/licenses/>.
27  */
28 
35 require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
36 require_once DOL_DOCUMENT_ROOT."/core/class/commonobjectline.class.php";
37 require_once DOL_DOCUMENT_ROOT.'/core/class/commonincoterm.class.php';
38 if (!empty($conf->propal->enabled)) require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
39 if (!empty($conf->commande->enabled)) require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
40 
41 
45 class Reception extends CommonObject
46 {
47  use CommonIncoterm;
48 
52  public $element = "reception";
53 
57  public $fk_element = "fk_reception";
58  public $table_element = "reception";
59  public $table_element_line = "commande_fournisseur_dispatch";
60  public $ismultientitymanaged = 1; // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
61 
65  public $picto = 'dollyrevert';
66 
67  public $socid;
68  public $ref_supplier;
69 
74  public $ref_int;
75 
76  public $brouillon;
77  public $entrepot_id;
78  public $tracking_number;
79  public $tracking_url;
80  public $billed;
81  public $model_pdf;
82 
83  public $trueWeight;
84  public $weight_units;
85  public $trueWidth;
86  public $width_units;
87  public $trueHeight;
88  public $height_units;
89  public $trueDepth;
90  public $depth_units;
91  // A denormalized value
92  public $trueSize;
93 
94  public $date_delivery; // Date delivery planed
95 
96 
100  public $date_reception;
101 
105  public $date_creation;
106 
110  public $date_valid;
111 
112  public $meths;
113  public $listmeths; // List of carriers
114 
115  public $lines = array();
116 
117 
118  const STATUS_DRAFT = 0;
119  const STATUS_VALIDATED = 1;
120  const STATUS_CLOSED = 2;
121 
122 
123 
129  public function __construct($db)
130  {
131  $this->db = $db;
132 
133  // List of long language codes for status
134  $this->statuts = array();
135  $this->statuts[-1] = 'StatusReceptionCanceled';
136  $this->statuts[0] = 'StatusReceptionDraft';
137  $this->statuts[1] = 'StatusReceptionValidated';
138  $this->statuts[2] = 'StatusReceptionProcessed';
139 
140  // List of short language codes for status
141  $this->statutshorts = array();
142  $this->statutshorts[-1] = 'StatusReceptionCanceledShort';
143  $this->statutshorts[0] = 'StatusReceptionDraftShort';
144  $this->statutshorts[1] = 'StatusReceptionValidatedShort';
145  $this->statutshorts[2] = 'StatusReceptionProcessedShort';
146  }
147 
154  public function getNextNumRef($soc)
155  {
156  global $langs, $conf;
157  $langs->load("receptions");
158 
159  if (!empty($conf->global->RECEPTION_ADDON_NUMBER))
160  {
161  $mybool = false;
162 
163  $file = $conf->global->RECEPTION_ADDON_NUMBER.".php";
164  $classname = $conf->global->RECEPTION_ADDON_NUMBER;
165 
166  // Include file with class
167  $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
168 
169  foreach ($dirmodels as $reldir) {
170  $dir = dol_buildpath($reldir."core/modules/reception/");
171 
172  // Load file with numbering class (if found)
173  $mybool |= @include_once $dir.$file;
174  }
175 
176  if (!$mybool)
177  {
178  dol_print_error('', "Failed to include file ".$file);
179  return '';
180  }
181 
182  $obj = new $classname();
183 
184  $numref = "";
185  $numref = $obj->getNextValue($soc, $this);
186 
187  if ($numref != "")
188  {
189  return $numref;
190  } else {
191  dol_print_error($this->db, get_class($this)."::getNextNumRef ".$obj->error);
192  return "";
193  }
194  } else {
195  print $langs->trans("Error")." ".$langs->trans("Error_RECEPTION_ADDON_NUMBER_NotDefined");
196  return "";
197  }
198  }
199 
207  public function create($user, $notrigger = 0)
208  {
209  global $conf, $hookmanager;
210 
211  $now = dol_now();
212 
213  require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
214  $error = 0;
215 
216  // Clean parameters
217  $this->brouillon = 1;
218  $this->tracking_number = dol_sanitizeFileName($this->tracking_number);
219  if (empty($this->fk_project)) $this->fk_project = 0;
220  if (empty($this->weight_units)) $this->weight_units = 0;
221  if (empty($this->size_units)) $this->size_units = 0;
222 
223  $this->user = $user;
224 
225 
226  $this->db->begin();
227 
228  $sql = "INSERT INTO ".MAIN_DB_PREFIX."reception (";
229  $sql .= "ref";
230  $sql .= ", entity";
231  $sql .= ", ref_supplier";
232  $sql .= ", date_creation";
233  $sql .= ", fk_user_author";
234  $sql .= ", date_reception";
235  $sql .= ", date_delivery";
236  $sql .= ", fk_soc";
237  $sql .= ", fk_projet";
238  $sql .= ", fk_shipping_method";
239  $sql .= ", tracking_number";
240  $sql .= ", weight";
241  $sql .= ", size";
242  $sql .= ", width";
243  $sql .= ", height";
244  $sql .= ", weight_units";
245  $sql .= ", size_units";
246  $sql .= ", note_private";
247  $sql .= ", note_public";
248  $sql .= ", model_pdf";
249  $sql .= ", fk_incoterms, location_incoterms";
250  $sql .= ") VALUES (";
251  $sql .= "'(PROV)'";
252  $sql .= ", ".$conf->entity;
253  $sql .= ", ".($this->ref_supplier ? "'".$this->db->escape($this->ref_supplier)."'" : "null");
254  $sql .= ", '".$this->db->idate($now)."'";
255  $sql .= ", ".$user->id;
256  $sql .= ", ".($this->date_reception > 0 ? "'".$this->db->idate($this->date_reception)."'" : "null");
257  $sql .= ", ".($this->date_delivery > 0 ? "'".$this->db->idate($this->date_delivery)."'" : "null");
258  $sql .= ", ".$this->socid;
259  $sql .= ", ".$this->fk_project;
260  $sql .= ", ".($this->shipping_method_id > 0 ? $this->shipping_method_id : "null");
261  $sql .= ", '".$this->db->escape($this->tracking_number)."'";
262  $sql .= ", ".$this->weight;
263  $sql .= ", ".$this->sizeS; // TODO Should use this->trueDepth
264  $sql .= ", ".$this->sizeW; // TODO Should use this->trueWidth
265  $sql .= ", ".$this->sizeH; // TODO Should use this->trueHeight
266  $sql .= ", ".$this->weight_units;
267  $sql .= ", ".$this->size_units;
268  $sql .= ", ".(!empty($this->note_private) ? "'".$this->db->escape($this->note_private)."'" : "null");
269  $sql .= ", ".(!empty($this->note_public) ? "'".$this->db->escape($this->note_public)."'" : "null");
270  $sql .= ", ".(!empty($this->model_pdf) ? "'".$this->db->escape($this->model_pdf)."'" : "null");
271  $sql .= ", ".(int) $this->fk_incoterms;
272  $sql .= ", '".$this->db->escape($this->location_incoterms)."'";
273  $sql .= ")";
274 
275  dol_syslog(get_class($this)."::create", LOG_DEBUG);
276 
277  $resql = $this->db->query($sql);
278 
279  if ($resql)
280  {
281  $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."reception");
282 
283  $sql = "UPDATE ".MAIN_DB_PREFIX."reception";
284  $sql .= " SET ref = '(PROV".$this->id.")'";
285  $sql .= " WHERE rowid = ".$this->id;
286 
287  dol_syslog(get_class($this)."::create", LOG_DEBUG);
288  if ($this->db->query($sql))
289  {
290  // Insert of lines
291  $num = count($this->lines);
292  for ($i = 0; $i < $num; $i++)
293  {
294  $this->lines[$i]->fk_reception = $this->id;
295 
296  if (!$this->lines[$i]->create($user) > 0)
297  {
298  $error++;
299  }
300  }
301 
302  if (!$error && $this->id && $this->origin_id)
303  {
304  $ret = $this->add_object_linked();
305  if (!$ret)
306  {
307  $error++;
308  }
309  }
310 
311  // Create extrafields
312  if (!$error)
313  {
314  $result = $this->insertExtraFields();
315  if ($result < 0) $error++;
316  }
317 
318  if (!$error && !$notrigger)
319  {
320  // Call trigger
321  $result = $this->call_trigger('RECEPTION_CREATE', $user);
322  if ($result < 0) { $error++; }
323  // End call triggers
324  }
325 
326  if (!$error)
327  {
328  $this->db->commit();
329  return $this->id;
330  } else {
331  foreach ($this->errors as $errmsg)
332  {
333  dol_syslog(get_class($this)."::create ".$errmsg, LOG_ERR);
334  $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
335  }
336  $this->db->rollback();
337  return -1 * $error;
338  }
339  } else {
340  $error++;
341  $this->error = $this->db->lasterror()." - sql=$sql";
342  $this->db->rollback();
343  return -2;
344  }
345  } else {
346  $error++;
347  $this->error = $this->db->error()." - sql=$sql";
348  $this->db->rollback();
349  return -1;
350  }
351  }
352 
353 
354 
364  public function fetch($id, $ref = '', $ref_ext = '', $notused = '')
365  {
366  global $conf;
367 
368  // Check parameters
369  if (empty($id) && empty($ref) && empty($ref_ext)) return -1;
370 
371  $sql = "SELECT e.rowid, e.ref, e.fk_soc as socid, e.date_creation, e.ref_supplier, e.ref_ext, e.fk_user_author, e.fk_statut";
372  $sql .= ", e.weight, e.weight_units, e.size, e.size_units, e.width, e.height";
373  $sql .= ", e.date_reception as date_reception, e.model_pdf, e.date_delivery";
374  $sql .= ", e.fk_shipping_method, e.tracking_number";
375  $sql .= ", el.fk_source as origin_id, el.sourcetype as origin";
376  $sql .= ", e.note_private, e.note_public";
377  $sql .= ', e.fk_incoterms, e.location_incoterms';
378  $sql .= ', i.libelle as label_incoterms';
379  $sql .= " FROM ".MAIN_DB_PREFIX."reception as e";
380  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."element_element as el ON el.fk_target = e.rowid AND el.targettype = '".$this->db->escape($this->element)."'";
381  $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_incoterms as i ON e.fk_incoterms = i.rowid';
382  $sql .= " WHERE e.entity IN (".getEntity('reception').")";
383  if ($id) $sql .= " AND e.rowid=".$id;
384  if ($ref) $sql .= " AND e.ref='".$this->db->escape($ref)."'";
385  if ($ref_ext) $sql .= " AND e.ref_ext='".$this->db->escape($ref_ext)."'";
386  if ($notused) $sql .= " AND e.ref_int='".$this->db->escape($notused)."'";
387 
388  dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
389  $result = $this->db->query($sql);
390  if ($result)
391  {
392  if ($this->db->num_rows($result))
393  {
394  $obj = $this->db->fetch_object($result);
395 
396  $this->id = $obj->rowid;
397  $this->ref = $obj->ref;
398  $this->socid = $obj->socid;
399  $this->ref_supplier = $obj->ref_supplier;
400  $this->ref_ext = $obj->ref_ext;
401  $this->statut = $obj->fk_statut;
402  $this->user_author_id = $obj->fk_user_author;
403  $this->date_creation = $this->db->jdate($obj->date_creation);
404  $this->date = $this->db->jdate($obj->date_reception); // TODO deprecated
405  $this->date_reception = $this->db->jdate($obj->date_reception); // TODO deprecated
406  $this->date_reception = $this->db->jdate($obj->date_reception); // Date real
407  $this->date_delivery = $this->db->jdate($obj->date_delivery); // Date planed
408  $this->model_pdf = $obj->model_pdf;
409  $this->modelpdf = $obj->model_pdf; // deprecated
410  $this->shipping_method_id = $obj->fk_shipping_method;
411  $this->tracking_number = $obj->tracking_number;
412  $this->origin = ($obj->origin ? $obj->origin : 'commande'); // For compatibility
413  $this->origin_id = $obj->origin_id;
414  $this->billed = ($obj->fk_statut == 2 ? 1 : 0);
415 
416  $this->trueWeight = $obj->weight;
417  $this->weight_units = $obj->weight_units;
418 
419  $this->trueWidth = $obj->width;
420  $this->width_units = $obj->size_units;
421  $this->trueHeight = $obj->height;
422  $this->height_units = $obj->size_units;
423  $this->trueDepth = $obj->size;
424  $this->depth_units = $obj->size_units;
425 
426  $this->note_public = $obj->note_public;
427  $this->note_private = $obj->note_private;
428 
429  // A denormalized value
430  $this->trueSize = $obj->size."x".$obj->width."x".$obj->height;
431  $this->size_units = $obj->size_units;
432 
433  //Incoterms
434  $this->fk_incoterms = $obj->fk_incoterms;
435  $this->location_incoterms = $obj->location_incoterms;
436  $this->label_incoterms = $obj->label_incoterms;
437 
438  $this->db->free($result);
439 
440  if ($this->statut == 0) $this->brouillon = 1;
441 
442  $file = $conf->reception->dir_output."/".get_exdir($this->id, 2, 0, 0, $this, 'reception')."/".$this->id.".pdf";
443  $this->pdf_filename = $file;
444 
445  // Tracking url
446  $this->getUrlTrackingStatus($obj->tracking_number);
447 
448  /*
449  * Thirdparty
450  */
451  $result = $this->fetch_thirdparty();
452 
453 
454  // Retrieve all extrafields for reception
455  // fetch optionals attributes and labels
456  require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
457  $extrafields = new ExtraFields($this->db);
458  $extrafields->fetch_name_optionals_label($this->table_element, true);
459  $this->fetch_optionals();
460 
461  /*
462  * Lines
463  */
464  $result = $this->fetch_lines();
465  if ($result < 0)
466  {
467  return -3;
468  }
469 
470  return 1;
471  } else {
472  dol_syslog(get_class($this).'::Fetch no reception found', LOG_ERR);
473  $this->error = 'Delivery with id '.$id.' not found';
474  return 0;
475  }
476  } else {
477  $this->error = $this->db->error();
478  return -1;
479  }
480  }
481 
489  public function valid($user, $notrigger = 0)
490  {
491  global $conf, $langs;
492 
493  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
494 
495  dol_syslog(get_class($this)."::valid");
496 
497  // Protection
498  if ($this->statut)
499  {
500  dol_syslog(get_class($this)."::valid no draft status", LOG_WARNING);
501  return 0;
502  }
503 
504  if (!((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->reception->creer))
505  || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->reception->reception_advance->validate))))
506  {
507  $this->error = 'Permission denied';
508  dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
509  return -1;
510  }
511 
512  $this->db->begin();
513 
514  $error = 0;
515 
516  // Define new ref
517  $soc = new Societe($this->db);
518  $soc->fetch($this->socid);
519 
520 
521  // Define new ref
522  if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) // empty should not happened, but when it occurs, the test save life
523  {
524  $numref = $this->getNextNumRef($soc);
525  } else {
526  $numref = $this->ref;
527  }
528 
529  $this->newref = dol_sanitizeFileName($numref);
530 
531  $now = dol_now();
532 
533  // Validate
534  $sql = "UPDATE ".MAIN_DB_PREFIX."reception SET";
535  $sql .= " ref='".$this->db->escape($numref)."'";
536  $sql .= ", fk_statut = 1";
537  $sql .= ", date_valid = '".$this->db->idate($now)."'";
538  $sql .= ", fk_user_valid = ".$user->id;
539  $sql .= " WHERE rowid = ".$this->id;
540  dol_syslog(get_class($this)."::valid update reception", LOG_DEBUG);
541  $resql = $this->db->query($sql);
542  if (!$resql)
543  {
544  $this->error = $this->db->lasterror();
545  $error++;
546  }
547 
548  // If stock increment is done on reception (recommanded choice)
549  if (!$error && !empty($conf->stock->enabled) && !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION))
550  {
551  require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
552 
553  $langs->load("agenda");
554 
555  // Loop on each product line to add a stock movement
556  // TODO in future, reception lines may not be linked to order line
557  $sql = "SELECT cd.fk_product, cd.subprice,";
558  $sql .= " ed.rowid, ed.qty, ed.fk_entrepot,";
559  $sql .= " ed.eatby, ed.sellby, ed.batch";
560  $sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseurdet as cd,";
561  $sql .= " ".MAIN_DB_PREFIX."commande_fournisseur_dispatch as ed";
562  $sql .= " WHERE ed.fk_reception = ".$this->id;
563  $sql .= " AND cd.rowid = ed.fk_commandefourndet";
564 
565  dol_syslog(get_class($this)."::valid select details", LOG_DEBUG);
566  $resql = $this->db->query($sql);
567  if ($resql)
568  {
569  $cpt = $this->db->num_rows($resql);
570  for ($i = 0; $i < $cpt; $i++)
571  {
572  $obj = $this->db->fetch_object($resql);
573 
574  $qty = $obj->qty;
575 
576  if ($qty <= 0) continue;
577  dol_syslog(get_class($this)."::valid movement index ".$i." ed.rowid=".$obj->rowid." edb.rowid=".$obj->edbrowid);
578 
579  //var_dump($this->lines[$i]);
580  $mouvS = new MouvementStock($this->db);
581  $mouvS->origin = &$this;
582 
583  if (empty($obj->batch))
584  {
585  // line without batch detail
586 
587  // We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record.
588  $result = $mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans("ReceptionValidatedInDolibarr", $numref));
589  if ($result < 0) {
590  $error++;
591  $this->errors[] = $mouvS->error;
592  $this->errors = array_merge($this->errors, $mouvS->errors);
593  break;
594  }
595  } else {
596  // line with batch detail
597 
598  // We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record.
599  // Note: ->fk_origin_stock = id into table llx_product_batch (may be rename into llx_product_stock_batch in another version)
600  $result = $mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans("ReceptionValidatedInDolibarr", $numref), $this->db->jdate($obj->eatby), $this->db->jdate($obj->sellby), $obj->batch);
601  if ($result < 0) {
602  $error++;
603  $this->errors[] = $mouvS->error;
604  $this->errors = array_merge($this->errors, $mouvS->errors);
605  break;
606  }
607  }
608  }
609  } else {
610  $this->db->rollback();
611  $this->error = $this->db->error();
612  return -2;
613  }
614  }
615 
616  // Change status of order to "reception in process"
617  $ret = $this->setStatut(4, $this->origin_id, 'commande_fournisseur');
618 
619  if (!$ret)
620  {
621  $error++;
622  }
623 
624  if (!$error && !$notrigger)
625  {
626  // Call trigger
627  $result = $this->call_trigger('RECEPTION_VALIDATE', $user);
628  if ($result < 0) { $error++; }
629  // End call triggers
630  }
631 
632  if (!$error)
633  {
634  $this->oldref = $this->ref;
635 
636  // Rename directory if dir was a temporary ref
637  if (preg_match('/^[\(]?PROV/i', $this->ref))
638  {
639  // Now we rename also files into index
640  $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'reception/".$this->db->escape($this->newref)."'";
641  $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'reception/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
642  $resql = $this->db->query($sql);
643  if (!$resql) { $error++; $this->error = $this->db->lasterror(); }
644 
645  // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
646  $oldref = dol_sanitizeFileName($this->ref);
647  $newref = dol_sanitizeFileName($numref);
648  $dirsource = $conf->reception->dir_output.'/'.$oldref;
649  $dirdest = $conf->reception->dir_output.'/'.$newref;
650  if (!$error && file_exists($dirsource))
651  {
652  dol_syslog(get_class($this)."::valid rename dir ".$dirsource." into ".$dirdest);
653 
654  if (@rename($dirsource, $dirdest))
655  {
656  dol_syslog("Rename ok");
657  // Rename docs starting with $oldref with $newref
658  $listoffiles = dol_dir_list($conf->reception->dir_output.'/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
659  foreach ($listoffiles as $fileentry)
660  {
661  $dirsource = $fileentry['name'];
662  $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
663  $dirsource = $fileentry['path'].'/'.$dirsource;
664  $dirdest = $fileentry['path'].'/'.$dirdest;
665  @rename($dirsource, $dirdest);
666  }
667  }
668  }
669  }
670  }
671 
672  // Set new ref and current status
673  if (!$error)
674  {
675  $this->ref = $numref;
676  $this->statut = 1;
677  }
678 
679  if (!$error)
680  {
681  $this->db->commit();
682  return 1;
683  } else {
684  foreach ($this->errors as $errmsg)
685  {
686  dol_syslog(get_class($this)."::valid ".$errmsg, LOG_ERR);
687  $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
688  }
689  $this->db->rollback();
690  return -1 * $error;
691  }
692  }
693 
694 
695 
711  public function addline($entrepot_id, $id, $qty, $array_options = 0, $comment = '', $eatby = '', $sellby = '', $batch = '')
712  {
713  global $conf, $langs, $user;
714 
715  $num = count($this->lines);
716  $line = new CommandeFournisseurDispatch($this->db);
717 
718  $line->fk_entrepot = $entrepot_id;
719  $line->fk_commandefourndet = $id;
720  $line->qty = $qty;
721 
722  $supplierorderline = new CommandeFournisseurLigne($this->db);
723  $supplierorderline->fetch($id);
724 
725  if (!empty($conf->stock->enabled) && !empty($supplierorderline->fk_product))
726  {
727  $fk_product = $supplierorderline->fk_product;
728 
729  if (!($entrepot_id > 0) && empty($conf->global->STOCK_WAREHOUSE_NOT_REQUIRED_FOR_RECEPTIONS))
730  {
731  $langs->load("errors");
732  $this->error = $langs->trans("ErrorWarehouseRequiredIntoReceptionLine");
733  return -1;
734  }
735  }
736 
737  // extrafields
738  $line->array_options = $supplierorderline->array_options;
739  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($array_options) && count($array_options) > 0)
740  {
741  foreach ($array_options as $key => $value) {
742  $line->array_options[$key] = $value;
743  }
744  }
745 
746  $line->fk_product = $fk_product;
747  $line->fk_commande = $supplierorderline->fk_commande;
748  $line->fk_user = $user->id;
749  $line->comment = $comment;
750  $line->batch = $batch;
751  $line->eatby = $eatby;
752  $line->sellby = $sellby;
753  $line->status = 1;
754  $line->fk_reception = $this->id;
755 
756  $this->lines[$num] = $line;
757 
758  return $num;
759  }
760 
761 
769  public function update($user = null, $notrigger = 0)
770  {
771  global $conf;
772  $error = 0;
773 
774  // Clean parameters
775 
776  if (isset($this->ref)) $this->ref = trim($this->ref);
777  if (isset($this->entity)) $this->entity = trim($this->entity);
778  if (isset($this->ref_supplier)) $this->ref_supplier = trim($this->ref_supplier);
779  if (isset($this->socid)) $this->socid = trim($this->socid);
780  if (isset($this->fk_user_author)) $this->fk_user_author = trim($this->fk_user_author);
781  if (isset($this->fk_user_valid)) $this->fk_user_valid = trim($this->fk_user_valid);
782  if (isset($this->shipping_method_id)) $this->shipping_method_id = trim($this->shipping_method_id);
783  if (isset($this->tracking_number)) $this->tracking_number = trim($this->tracking_number);
784  if (isset($this->statut)) $this->statut = (int) $this->statut;
785  if (isset($this->trueDepth)) $this->trueDepth = trim($this->trueDepth);
786  if (isset($this->trueWidth)) $this->trueWidth = trim($this->trueWidth);
787  if (isset($this->trueHeight)) $this->trueHeight = trim($this->trueHeight);
788  if (isset($this->size_units)) $this->size_units = trim($this->size_units);
789  if (isset($this->weight_units)) $this->weight_units = trim($this->weight_units);
790  if (isset($this->trueWeight)) $this->weight = trim($this->trueWeight);
791  if (isset($this->note_private)) $this->note_private = trim($this->note_private);
792  if (isset($this->note_public)) $this->note_public = trim($this->note_public);
793  if (isset($this->model_pdf)) $this->model_pdf = trim($this->model_pdf);
794 
795 
796  // Check parameters
797  // Put here code to add control on parameters values
798 
799  // Update request
800  $sql = "UPDATE ".MAIN_DB_PREFIX."reception SET";
801 
802  $sql .= " ref=".(isset($this->ref) ? "'".$this->db->escape($this->ref)."'" : "null").",";
803  $sql .= " ref_supplier=".(isset($this->ref_supplier) ? "'".$this->db->escape($this->ref_supplier)."'" : "null").",";
804  $sql .= " fk_soc=".(isset($this->socid) ? $this->socid : "null").",";
805  $sql .= " date_creation=".(dol_strlen($this->date_creation) != 0 ? "'".$this->db->idate($this->date_creation)."'" : 'null').",";
806  $sql .= " fk_user_author=".(isset($this->fk_user_author) ? $this->fk_user_author : "null").",";
807  $sql .= " date_valid=".(dol_strlen($this->date_valid) != 0 ? "'".$this->db->idate($this->date_valid)."'" : 'null').",";
808  $sql .= " fk_user_valid=".(isset($this->fk_user_valid) ? $this->fk_user_valid : "null").",";
809  $sql .= " date_reception=".(dol_strlen($this->date_reception) != 0 ? "'".$this->db->idate($this->date_reception)."'" : 'null').",";
810  $sql .= " date_delivery=".(dol_strlen($this->date_delivery) != 0 ? "'".$this->db->idate($this->date_delivery)."'" : 'null').",";
811  $sql .= " fk_shipping_method=".((isset($this->shipping_method_id) && $this->shipping_method_id > 0) ? $this->shipping_method_id : "null").",";
812  $sql .= " tracking_number=".(isset($this->tracking_number) ? "'".$this->db->escape($this->tracking_number)."'" : "null").",";
813  $sql .= " fk_statut=".(isset($this->statut) ? $this->statut : "null").",";
814  $sql .= " height=".(($this->trueHeight != '') ? $this->trueHeight : "null").",";
815  $sql .= " width=".(($this->trueWidth != '') ? $this->trueWidth : "null").",";
816  $sql .= " size_units=".(isset($this->size_units) ? $this->size_units : "null").",";
817  $sql .= " size=".(($this->trueDepth != '') ? $this->trueDepth : "null").",";
818  $sql .= " weight_units=".(isset($this->weight_units) ? $this->weight_units : "null").",";
819  $sql .= " weight=".(($this->trueWeight != '') ? $this->trueWeight : "null").",";
820  $sql .= " note_private=".(isset($this->note_private) ? "'".$this->db->escape($this->note_private)."'" : "null").",";
821  $sql .= " note_public=".(isset($this->note_public) ? "'".$this->db->escape($this->note_public)."'" : "null").",";
822  $sql .= " model_pdf=".(isset($this->modelpdf) ? "'".$this->db->escape($this->modelpdf)."'" : "null").",";
823  $sql .= " entity=".$conf->entity;
824 
825  $sql .= " WHERE rowid=".$this->id;
826 
827  $this->db->begin();
828 
829  dol_syslog(get_class($this)."::update", LOG_DEBUG);
830  $resql = $this->db->query($sql);
831  if (!$resql) { $error++; $this->errors[] = "Error ".$this->db->lasterror(); }
832 
833  if (!$error)
834  {
835  if (!$notrigger)
836  {
837  // Call trigger
838  $result = $this->call_trigger('RECEPTION_MODIFY', $user);
839  if ($result < 0) { $error++; }
840  // End call triggers
841  }
842  }
843 
844  // Commit or rollback
845  if ($error)
846  {
847  foreach ($this->errors as $errmsg)
848  {
849  dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
850  $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
851  }
852  $this->db->rollback();
853  return -1 * $error;
854  } else {
855  $this->db->commit();
856  return 1;
857  }
858  }
859 
866  public function delete(User $user)
867  {
868  global $conf, $langs, $user;
869  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
870 
871  $error = 0;
872  $this->error = '';
873 
874 
875  $this->db->begin();
876 
877  // Stock control
878  if ($conf->stock->enabled && $conf->global->STOCK_CALCULATE_ON_RECEPTION && $this->statut > 0)
879  {
880  require_once DOL_DOCUMENT_ROOT."/product/stock/class/mouvementstock.class.php";
881 
882  $langs->load("agenda");
883 
884  // Loop on each product line to add a stock movement
885  $sql = "SELECT cd.fk_product, cd.subprice, ed.qty, ed.fk_entrepot, ed.eatby, ed.sellby, ed.batch, ed.rowid as commande_fournisseur_dispatch_id";
886  $sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseurdet as cd,";
887  $sql .= " ".MAIN_DB_PREFIX."commande_fournisseur_dispatch as ed";
888  $sql .= " WHERE ed.fk_reception = ".$this->id;
889  $sql .= " AND cd.rowid = ed.fk_commandefourndet";
890 
891  dol_syslog(get_class($this)."::delete select details", LOG_DEBUG);
892  $resql = $this->db->query($sql);
893  if ($resql)
894  {
895  $cpt = $this->db->num_rows($resql);
896  for ($i = 0; $i < $cpt; $i++)
897  {
898  dol_syslog(get_class($this)."::delete movement index ".$i);
899  $obj = $this->db->fetch_object($resql);
900 
901  $mouvS = new MouvementStock($this->db);
902  // we do not log origin because it will be deleted
903  $mouvS->origin = null;
904 
905  $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, $obj->qty, 0, $langs->trans("ReceptionDeletedInDolibarr", $this->ref), '', $obj->eatby, $obj->sellby, $obj->batch); // Price is set to 0, because we don't want to see WAP changed
906  }
907  } else {
908  $error++; $this->errors[] = "Error ".$this->db->lasterror();
909  }
910  }
911 
912  if (!$error)
913  {
914  $main = MAIN_DB_PREFIX.'commande_fournisseur_dispatch';
915  $ef = $main."_extrafields";
916  $sqlef = "DELETE FROM $ef WHERE fk_object IN (SELECT rowid FROM $main WHERE fk_reception = ".$this->id.")";
917 
918  $sql = "DELETE FROM ".MAIN_DB_PREFIX."commande_fournisseur_dispatch";
919  $sql .= " WHERE fk_reception = ".$this->id;
920 
921  if ($this->db->query($sqlef) && $this->db->query($sql))
922  {
923  // Delete linked object
924  $res = $this->deleteObjectLinked();
925  if ($res < 0) $error++;
926 
927  if (!$error)
928  {
929  $sql = "DELETE FROM ".MAIN_DB_PREFIX."reception";
930  $sql .= " WHERE rowid = ".$this->id;
931 
932  if ($this->db->query($sql))
933  {
934  // Call trigger
935  $result = $this->call_trigger('RECEPTION_DELETE', $user);
936  if ($result < 0) { $error++; }
937  // End call triggers
938 
939  if (!empty($this->origin) && $this->origin_id > 0)
940  {
941  $this->fetch_origin();
942  $origin = $this->origin;
943  if ($this->$origin->statut == 4) // If order source of reception is "partially received"
944  {
945  // Check if there is no more reception. If not, we can move back status of order to "validated" instead of "reception in progress"
946  $this->$origin->loadReceptions();
947  //var_dump($this->$origin->receptions);exit;
948  if (count($this->$origin->receptions) <= 0)
949  {
950  $this->$origin->setStatut(3); // ordered
951  }
952  }
953  }
954 
955  if (!$error)
956  {
957  $this->db->commit();
958 
959  // We delete PDFs
960  $ref = dol_sanitizeFileName($this->ref);
961  if (!empty($conf->reception->dir_output))
962  {
963  $dir = $conf->reception->dir_output.'/'.$ref;
964  $file = $dir.'/'.$ref.'.pdf';
965  if (file_exists($file))
966  {
967  if (!dol_delete_file($file))
968  {
969  return 0;
970  }
971  }
972  if (file_exists($dir))
973  {
974  if (!dol_delete_dir_recursive($dir))
975  {
976  $this->error = $langs->trans("ErrorCanNotDeleteDir", $dir);
977  return 0;
978  }
979  }
980  }
981 
982  return 1;
983  } else {
984  $this->db->rollback();
985  return -1;
986  }
987  } else {
988  $this->error = $this->db->lasterror()." - sql=$sql";
989  $this->db->rollback();
990  return -3;
991  }
992  } else {
993  $this->error = $this->db->lasterror()." - sql=$sql";
994  $this->db->rollback();
995  return -2;
996  }
997  } else {
998  $this->error = $this->db->lasterror()." - sql=$sql";
999  $this->db->rollback();
1000  return -1;
1001  }
1002  } else {
1003  $this->db->rollback();
1004  return -1;
1005  }
1006  }
1007 
1008  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1014  public function fetch_lines()
1015  {
1016  // phpcs:enable
1017  dol_include_once('/fourn/class/fournisseur.commande.dispatch.class.php');
1018  $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'commande_fournisseur_dispatch WHERE fk_reception='.$this->id;
1019  $resql = $this->db->query($sql);
1020 
1021  if (!empty($resql)) {
1022  $this->lines = array();
1023  while ($obj = $this->db->fetch_object($resql)) {
1024  $line = new CommandeFournisseurDispatch($this->db);
1025  $line->fetch($obj->rowid);
1026  $line->fetch_product();
1027  $sql_commfourndet = 'SELECT qty, ref, label, tva_tx, vat_src_code, subprice, multicurrency_subprice, remise_percent FROM llx_commande_fournisseurdet WHERE rowid='.$line->fk_commandefourndet;
1028  $resql_commfourndet = $this->db->query($sql_commfourndet);
1029  if (!empty($resql_commfourndet)) {
1030  $obj = $this->db->fetch_object($resql_commfourndet);
1031  $line->qty_asked = $obj->qty;
1032  $line->description = $line->comment;
1033  $line->desc = $line->comment;
1034  $line->tva_tx = $obj->tva_tx;
1035  $line->vat_src_code = $obj->vat_src_code;
1036  $line->subprice = $obj->subprice;
1037  $line->multicurrency_subprice = $obj->multicurrency_subprice;
1038  $line->remise_percent = $obj->remise_percent;
1039  $line->label = !empty($obj->label) ? $obj->label : $line->product->label;
1040  $line->ref_supplier = $obj->ref;
1041  } else {
1042  $line->qty_asked = 0;
1043  $line->description = '';
1044  $line->label = $obj->label;
1045  }
1046 
1047  $pu_ht = ($line->subprice * $line->qty) * (100 - $line->remise_percent) / 100;
1048  $tva = $pu_ht * $line->tva_tx / 100;
1049  $this->total_ht += $pu_ht;
1050  $this->total_tva += $pu_ht * $line->tva_tx / 100;
1051 
1052  $this->total_ttc += $pu_ht + $tva;
1053 
1054 
1055  $this->lines[] = $line;
1056  }
1057 
1058  return 1;
1059  } else {
1060  return -1;
1061  }
1062  }
1063 
1074  public function getNomUrl($withpicto = 0, $option = 0, $max = 0, $short = 0, $notooltip = 0)
1075  {
1076  global $conf, $langs;
1077  $result = '';
1078  $label = img_picto('', $this->picto).' <u>'.$langs->trans("Reception").'</u>';
1079  $label .= '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
1080  $label .= '<br><b>'.$langs->trans('RefSupplier').':</b> '.($this->ref_supplier ? $this->ref_supplier : $this->ref_client);
1081 
1082  $url = DOL_URL_ROOT.'/reception/card.php?id='.$this->id;
1083 
1084  if ($short) return $url;
1085 
1086  $linkclose = '';
1087  if (empty($notooltip))
1088  {
1089  if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
1090  {
1091  $label = $langs->trans("Reception");
1092  $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
1093  }
1094  $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
1095  $linkclose .= ' class="classfortooltip"';
1096  }
1097 
1098  $linkstart = '<a href="'.$url.'"';
1099  $linkstart .= $linkclose.'>';
1100  $linkend = '</a>';
1101 
1102  if ($withpicto) $result .= ($linkstart.img_object(($notooltip ? '' : $label), $this->picto, ($notooltip ? '' : 'class="classfortooltip"'), 0, 0, $notooltip ? 0 : 1).$linkend);
1103  if ($withpicto && $withpicto != 2) $result .= ' ';
1104  $result .= $linkstart.$this->ref.$linkend;
1105  return $result;
1106  }
1107 
1114  public function getLibStatut($mode = 0)
1115  {
1116  return $this->LibStatut($this->statut, $mode);
1117  }
1118 
1119  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1127  public function LibStatut($status, $mode)
1128  {
1129  // phpcs:enable
1130  global $langs;
1131 
1132  $labelStatus = $langs->trans($this->statuts[$status]);
1133  $labelStatusShort = $langs->trans($this->statutshorts[$status]);
1134 
1135  $statusType = 'status'.$status;
1136  if ($status == self::STATUS_VALIDATED) $statusType = 'status4';
1137  if ($status == self::STATUS_CLOSED) $statusType = 'status6';
1138 
1139  return dolGetStatus($labelStatus, $labelStatusShort, '', $statusType, $mode);
1140  }
1141 
1149  public function initAsSpecimen()
1150  {
1151  global $langs;
1152 
1153  include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
1154  include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.dispatch.class.php';
1155  $now = dol_now();
1156 
1157  dol_syslog(get_class($this)."::initAsSpecimen");
1158 
1159  // Load array of products prodids
1160  $num_prods = 0;
1161  $prodids = array();
1162  $sql = "SELECT rowid";
1163  $sql .= " FROM ".MAIN_DB_PREFIX."product";
1164  $sql .= " WHERE entity IN (".getEntity('product').")";
1165  $sql .= $this->db->plimit(100);
1166 
1167  $resql = $this->db->query($sql);
1168  if ($resql)
1169  {
1170  $num_prods = $this->db->num_rows($resql);
1171  $i = 0;
1172  while ($i < $num_prods)
1173  {
1174  $i++;
1175  $row = $this->db->fetch_row($resql);
1176  $prodids[$i] = $row[0];
1177  }
1178  }
1179 
1180  $order = new CommandeFournisseur($this->db);
1181  $order->initAsSpecimen();
1182 
1183  // Initialise parametres
1184  $this->id = 0;
1185  $this->ref = 'SPECIMEN';
1186  $this->specimen = 1;
1187  $this->statut = 1;
1188  $this->livraison_id = 0;
1189  $this->date = $now;
1190  $this->date_creation = $now;
1191  $this->date_valid = $now;
1192  $this->date_delivery = $now;
1193  $this->date_reception = $now + 24 * 3600;
1194 
1195  $this->entrepot_id = 0;
1196  $this->socid = 1;
1197 
1198  $this->commande_id = 0;
1199  $this->commande = $order;
1200 
1201  $this->origin_id = 1;
1202  $this->origin = 'commande';
1203 
1204  $this->note_private = 'Private note';
1205  $this->note_public = 'Public note';
1206 
1207  $nbp = 5;
1208  $xnbp = 0;
1209  while ($xnbp < $nbp)
1210  {
1211  $line = new CommandeFournisseurDispatch($this->db);
1212  $line->desc = $langs->trans("Description")." ".$xnbp;
1213  $line->libelle = $langs->trans("Description")." ".$xnbp;
1214  $line->qty = 10;
1215 
1216  $line->fk_product = $this->commande->lines[$xnbp]->fk_product;
1217 
1218  $this->lines[] = $line;
1219  $xnbp++;
1220  }
1221  }
1222 
1230  public function setDeliveryDate($user, $delivery_date)
1231  {
1232  // phpcs:enable
1233  if ($user->rights->reception->creer)
1234  {
1235  $sql = "UPDATE ".MAIN_DB_PREFIX."reception";
1236  $sql .= " SET date_delivery = ".($delivery_date ? "'".$this->db->idate($delivery_date)."'" : 'null');
1237  $sql .= " WHERE rowid = ".$this->id;
1238 
1239  dol_syslog(get_class($this)."::setDeliveryDate", LOG_DEBUG);
1240  $resql = $this->db->query($sql);
1241  if ($resql)
1242  {
1243  $this->date_delivery = $delivery_date;
1244  return 1;
1245  } else {
1246  $this->error = $this->db->error();
1247  return -1;
1248  }
1249  } else {
1250  return -2;
1251  }
1252  }
1253 
1254  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1260  public function fetch_delivery_methods()
1261  {
1262  // phpcs:enable
1263  global $langs;
1264  $this->meths = array();
1265 
1266  $sql = "SELECT em.rowid, em.code, em.libelle";
1267  $sql .= " FROM ".MAIN_DB_PREFIX."c_shipment_mode as em";
1268  $sql .= " WHERE em.active = 1";
1269  $sql .= " ORDER BY em.libelle ASC";
1270 
1271  $resql = $this->db->query($sql);
1272  if ($resql)
1273  {
1274  while ($obj = $this->db->fetch_object($resql))
1275  {
1276  $label = $langs->trans('ReceptionMethod'.$obj->code);
1277  $this->meths[$obj->rowid] = ($label != 'ReceptionMethod'.$obj->code ? $label : $obj->libelle);
1278  }
1279  }
1280  }
1281 
1282  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1289  public function list_delivery_methods($id = '')
1290  {
1291  // phpcs:enable
1292  global $langs;
1293 
1294  $this->listmeths = array();
1295  $i = 0;
1296 
1297  $sql = "SELECT em.rowid, em.code, em.libelle, em.description, em.tracking, em.active";
1298  $sql .= " FROM ".MAIN_DB_PREFIX."c_shipment_mode as em";
1299  if ($id != '') $sql .= " WHERE em.rowid=".$id;
1300 
1301  $resql = $this->db->query($sql);
1302  if ($resql) {
1303  while ($obj = $this->db->fetch_object($resql)) {
1304  $this->listmeths[$i]['rowid'] = $obj->rowid;
1305  $this->listmeths[$i]['code'] = $obj->code;
1306  $label = $langs->trans('ReceptionMethod'.$obj->code);
1307  $this->listmeths[$i]['libelle'] = ($label != 'ReceptionMethod'.$obj->code ? $label : $obj->libelle);
1308  $this->listmeths[$i]['description'] = $obj->description;
1309  $this->listmeths[$i]['tracking'] = $obj->tracking;
1310  $this->listmeths[$i]['active'] = $obj->active;
1311  $i++;
1312  }
1313  }
1314  }
1315 
1316  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1324  public function update_delivery_method($id = '')
1325  {
1326  // phpcs:enable
1327  if ($id == '')
1328  {
1329  $sql = "INSERT INTO ".MAIN_DB_PREFIX."c_shipment_mode (code, libelle, description, tracking)";
1330  $sql .= " VALUES ('".$this->db->escape($this->update['code'])."','".$this->db->escape($this->update['libelle'])."','".$this->db->escape($this->update['description'])."','".$this->db->escape($this->update['tracking'])."')";
1331  $resql = $this->db->query($sql);
1332  } else {
1333  $sql = "UPDATE ".MAIN_DB_PREFIX."c_shipment_mode SET";
1334  $sql .= " code='".$this->db->escape($this->update['code'])."'";
1335  $sql .= ",libelle='".$this->db->escape($this->update['libelle'])."'";
1336  $sql .= ",description='".$this->db->escape($this->update['description'])."'";
1337  $sql .= ",tracking='".$this->db->escape($this->update['tracking'])."'";
1338  $sql .= " WHERE rowid=".$id;
1339  $resql = $this->db->query($sql);
1340  }
1341  if ($resql < 0) dol_print_error($this->db, '');
1342  }
1343 
1344  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1352  public function activ_delivery_method($id)
1353  {
1354  // phpcs:enable
1355  $sql = 'UPDATE '.MAIN_DB_PREFIX.'c_shipment_mode SET active=1';
1356  $sql .= ' WHERE rowid='.$id;
1357 
1358  $resql = $this->db->query($sql);
1359  }
1360 
1361  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1369  public function disable_delivery_method($id)
1370  {
1371  // phpcs:enable
1372  $sql = 'UPDATE '.MAIN_DB_PREFIX.'c_shipment_mode SET active=0';
1373  $sql .= ' WHERE rowid='.$id;
1374 
1375  $resql = $this->db->query($sql);
1376  }
1377 
1378 
1385  public function getUrlTrackingStatus($value = '')
1386  {
1387  if (!empty($this->shipping_method_id))
1388  {
1389  $sql = "SELECT em.code, em.tracking";
1390  $sql .= " FROM ".MAIN_DB_PREFIX."c_shipment_mode as em";
1391  $sql .= " WHERE em.rowid = ".$this->shipping_method_id;
1392 
1393  $resql = $this->db->query($sql);
1394  if ($resql)
1395  {
1396  if ($obj = $this->db->fetch_object($resql))
1397  {
1398  $tracking = $obj->tracking;
1399  }
1400  }
1401  }
1402 
1403  if (!empty($tracking) && !empty($value))
1404  {
1405  $url = str_replace('{TRACKID}', $value, $tracking);
1406  $this->tracking_url = sprintf('<a target="_blank" href="%s">'.($value ? $value : 'url').'</a>', $url, $url);
1407  } else {
1408  $this->tracking_url = $value;
1409  }
1410  }
1411 
1417  public function setClosed()
1418  {
1419  global $conf, $langs, $user;
1420 
1421  $error = 0;
1422 
1423  $this->db->begin();
1424 
1425  $sql = 'UPDATE '.MAIN_DB_PREFIX.'reception SET fk_statut='.self::STATUS_CLOSED;
1426  $sql .= ' WHERE rowid = '.$this->id.' AND fk_statut > 0';
1427 
1428  $resql = $this->db->query($sql);
1429  if ($resql)
1430  {
1431  // Set order billed if 100% of order is received (qty in reception lines match qty in order lines)
1432  if ($this->origin == 'order_supplier' && $this->origin_id > 0)
1433  {
1434  $order = new CommandeFournisseur($this->db);
1435  $order->fetch($this->origin_id);
1436 
1437  $order->loadReceptions(self::STATUS_CLOSED); // Fill $order->receptions = array(orderlineid => qty)
1438 
1439  $receptions_match_order = 1;
1440  foreach ($order->lines as $line)
1441  {
1442  $lineid = $line->id;
1443  $qty = $line->qty;
1444  if (($line->product_type == 0 || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) && $order->receptions[$lineid] < $qty)
1445  {
1446  $receptions_match_order = 0;
1447  $text = 'Qty for order line id '.$lineid.' is '.$qty.'. However in the receptions with status Reception::STATUS_CLOSED='.self::STATUS_CLOSED.' we have qty = '.$order->receptions[$lineid].', so we can t close order';
1448  dol_syslog($text);
1449  break;
1450  }
1451  }
1452  if ($receptions_match_order)
1453  {
1454  dol_syslog("Qty for the ".count($order->lines)." lines of order have same value for receptions with status Reception::STATUS_CLOSED=".self::STATUS_CLOSED.', so we close order');
1455  $order->Livraison($user, dol_now(), 'tot', 'Reception '.$this->ref);
1456  }
1457  }
1458 
1459  $this->statut = self::STATUS_CLOSED;
1460 
1461 
1462  // If stock increment is done on closing
1463  if (!$error && !empty($conf->stock->enabled) && !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE))
1464  {
1465  require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
1466 
1467  $langs->load("agenda");
1468 
1469  // Loop on each product line to add a stock movement
1470  // TODO possibilite de receptionner a partir d'une propale ou autre origine ?
1471  $sql = "SELECT cd.fk_product, cd.subprice,";
1472  $sql .= " ed.rowid, ed.qty, ed.fk_entrepot,";
1473  $sql .= " ed.eatby, ed.sellby, ed.batch";
1474  $sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseurdet as cd,";
1475  $sql .= " ".MAIN_DB_PREFIX."commande_fournisseur_dispatch as ed";
1476  $sql .= " WHERE ed.fk_reception = ".$this->id;
1477  $sql .= " AND cd.rowid = ed.fk_commandefourndet";
1478 
1479  dol_syslog(get_class($this)."::valid select details", LOG_DEBUG);
1480  $resql = $this->db->query($sql);
1481 
1482  if ($resql)
1483  {
1484  $cpt = $this->db->num_rows($resql);
1485  for ($i = 0; $i < $cpt; $i++)
1486  {
1487  $obj = $this->db->fetch_object($resql);
1488 
1489  $qty = $obj->qty;
1490 
1491  if ($qty <= 0) continue;
1492  dol_syslog(get_class($this)."::valid movement index ".$i." ed.rowid=".$obj->rowid." edb.rowid=".$obj->edbrowid);
1493 
1494  $mouvS = new MouvementStock($this->db);
1495  $mouvS->origin = &$this;
1496 
1497  if (empty($obj->batch))
1498  {
1499  // line without batch detail
1500 
1501  // We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record
1502  $result = $mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans("ReceptionClassifyClosedInDolibarr", $numref));
1503  if ($result < 0) {
1504  $this->error = $mouvS->error;
1505  $this->errors = $mouvS->errors;
1506  $error++; break;
1507  }
1508  } else {
1509  // line with batch detail
1510 
1511  // We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record
1512  $result = $mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans("ReceptionClassifyClosedInDolibarr", $numref), $this->db->jdate($obj->eatby), $this->db->jdate($obj->sellby), $obj->batch);
1513 
1514  if ($result < 0) {
1515  $this->error = $mouvS->error;
1516  $this->errors = $mouvS->errors;
1517  $error++; break;
1518  }
1519  }
1520  }
1521  } else {
1522  $this->error = $this->db->lasterror();
1523  $error++;
1524  }
1525  }
1526 
1527  // Call trigger
1528  if (!$error)
1529  {
1530  $result = $this->call_trigger('RECEPTION_CLOSED', $user);
1531  if ($result < 0) {
1532  $error++;
1533  }
1534  }
1535  } else {
1536  dol_print_error($this->db);
1537  $error++;
1538  }
1539 
1540  if (!$error)
1541  {
1542  $this->db->commit();
1543  return 1;
1544  } else {
1545  $this->db->rollback();
1546  return -1;
1547  }
1548  }
1549 
1550  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1556  public function set_billed()
1557  {
1558  // phpcs:enable
1559  global $user;
1560  $error = 0;
1561 
1562  $this->db->begin();
1563 
1564  $this->setClosed();
1565 
1566  $sql = 'UPDATE '.MAIN_DB_PREFIX.'reception SET billed=1';
1567  $sql .= ' WHERE rowid = '.$this->id.' AND fk_statut > 0';
1568 
1569  $resql = $this->db->query($sql);
1570  if ($resql)
1571  {
1572  $this->statut = 2;
1573  $this->billed = 1;
1574 
1575  // Call trigger
1576  $result = $this->call_trigger('RECEPTION_BILLED', $user);
1577  if ($result < 0) {
1578  $error++;
1579  }
1580  } else {
1581  $error++;
1582  $this->errors[] = $this->db->lasterror;
1583  }
1584 
1585  if (empty($error)) {
1586  $this->db->commit();
1587  return 1;
1588  } else {
1589  $this->db->rollback();
1590  return -1;
1591  }
1592  }
1593 
1599  public function reOpen()
1600  {
1601  global $conf, $langs, $user;
1602 
1603  $error = 0;
1604 
1605  $this->db->begin();
1606 
1607  $sql = 'UPDATE '.MAIN_DB_PREFIX.'reception SET fk_statut=1, billed=0';
1608  $sql .= ' WHERE rowid = '.$this->id.' AND fk_statut > 0';
1609 
1610  $resql = $this->db->query($sql);
1611  if ($resql)
1612  {
1613  $this->statut = 1;
1614  $this->billed = 0;
1615 
1616  // If stock increment is done on closing
1617  if (!$error && !empty($conf->stock->enabled) && !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE))
1618  {
1619  require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
1620  $numref = $this->ref;
1621  $langs->load("agenda");
1622 
1623  // Loop on each product line to add a stock movement
1624  // TODO possibilite de receptionner a partir d'une propale ou autre origine
1625  $sql = "SELECT ed.fk_product, cd.subprice,";
1626  $sql .= " ed.rowid, ed.qty, ed.fk_entrepot,";
1627  $sql .= " ed.eatby, ed.sellby, ed.batch";
1628  $sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseurdet as cd,";
1629  $sql .= " ".MAIN_DB_PREFIX."commande_fournisseur_dispatch as ed";
1630  $sql .= " WHERE ed.fk_reception = ".$this->id;
1631  $sql .= " AND cd.rowid = ed.fk_commandefourndet";
1632 
1633  dol_syslog(get_class($this)."::valid select details", LOG_DEBUG);
1634  $resql = $this->db->query($sql);
1635  if ($resql)
1636  {
1637  $cpt = $this->db->num_rows($resql);
1638  for ($i = 0; $i < $cpt; $i++)
1639  {
1640  $obj = $this->db->fetch_object($resql);
1641 
1642  $qty = $obj->qty;
1643 
1644  if ($qty <= 0) continue;
1645 
1646  dol_syslog(get_class($this)."::reopen reception movement index ".$i." ed.rowid=".$obj->rowid);
1647 
1648  //var_dump($this->lines[$i]);
1649  $mouvS = new MouvementStock($this->db);
1650  $mouvS->origin = &$this;
1651 
1652  if (empty($obj->batch))
1653  {
1654  // line without batch detail
1655 
1656  // We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record
1657  $result = $mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, -$qty, $obj->subprice, $langs->trans("ReceptionUnClassifyCloseddInDolibarr", $numref));
1658  if ($result < 0) {
1659  $this->error = $mouvS->error;
1660  $this->errors = $mouvS->errors;
1661  $error++; break;
1662  }
1663  } else {
1664  // line with batch detail
1665 
1666  // We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record
1667  $result = $mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, -$qty, $obj->subprice, $langs->trans("ReceptionUnClassifyCloseddInDolibarr", $numref), $this->db->jdate($obj->eatby), $this->db->jdate($obj->sellby), $obj->batch, $obj->fk_origin_stock);
1668  if ($result < 0) {
1669  $this->error = $mouvS->error;
1670  $this->errors = $mouvS->errors;
1671  $error++; break;
1672  }
1673  }
1674  }
1675  } else {
1676  $this->error = $this->db->lasterror();
1677  $error++;
1678  }
1679  }
1680 
1681  if (!$error)
1682  {
1683  // Call trigger
1684  $result = $this->call_trigger('RECEPTION_REOPEN', $user);
1685  if ($result < 0) {
1686  $error++;
1687  }
1688  }
1689 
1690  if ($this->origin == 'order_supplier') {
1691  $commande = new CommandeFournisseur($this->db);
1692  $commande->fetch($this->origin_id);
1693  $commande->setStatus($user, 4);
1694  }
1695  } else {
1696  $error++;
1697  $this->errors[] = $this->db->lasterror();
1698  }
1699 
1700  if (!$error)
1701  {
1702  $this->db->commit();
1703  return 1;
1704  } else {
1705  $this->db->rollback();
1706  return -1;
1707  }
1708  }
1709 
1716  public function setDraft($user)
1717  {
1718  // phpcs:enable
1719  global $conf, $langs;
1720 
1721  $error = 0;
1722 
1723  // Protection
1724  if ($this->statut <= self::STATUS_DRAFT)
1725  {
1726  return 0;
1727  }
1728 
1729  if (!((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->reception->creer))
1730  || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->reception->reception_advance->validate))))
1731  {
1732  $this->error = 'Permission denied';
1733  return -1;
1734  }
1735 
1736  $this->db->begin();
1737 
1738  $sql = "UPDATE ".MAIN_DB_PREFIX."reception";
1739  $sql .= " SET fk_statut = ".self::STATUS_DRAFT;
1740  $sql .= " WHERE rowid = ".$this->id;
1741 
1742  dol_syslog(__METHOD__, LOG_DEBUG);
1743  if ($this->db->query($sql))
1744  {
1745  // If stock increment is done on closing
1746  if (!$error && !empty($conf->stock->enabled) && !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION))
1747  {
1748  require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
1749 
1750  $langs->load("agenda");
1751 
1752  // Loop on each product line to add a stock movement
1753  // TODO possibilite de receptionner a partir d'une propale ou autre origine
1754  $sql = "SELECT cd.fk_product, cd.subprice,";
1755  $sql .= " ed.rowid, ed.qty, ed.fk_entrepot,";
1756  $sql .= " ed.eatby, ed.sellby, ed.batch";
1757  $sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseurdet as cd,";
1758  $sql .= " ".MAIN_DB_PREFIX."commande_fournisseur_dispatch as ed";
1759  $sql .= " WHERE ed.fk_reception = ".$this->id;
1760  $sql .= " AND cd.rowid = ed.fk_commandefourndet";
1761 
1762  dol_syslog(get_class($this)."::valid select details", LOG_DEBUG);
1763  $resql = $this->db->query($sql);
1764  if ($resql)
1765  {
1766  $cpt = $this->db->num_rows($resql);
1767  for ($i = 0; $i < $cpt; $i++)
1768  {
1769  $obj = $this->db->fetch_object($resql);
1770 
1771  $qty = $obj->qty;
1772 
1773 
1774  if ($qty <= 0) continue;
1775  dol_syslog(get_class($this)."::reopen reception movement index ".$i." ed.rowid=".$obj->rowid." edb.rowid=".$obj->edbrowid);
1776 
1777  //var_dump($this->lines[$i]);
1778  $mouvS = new MouvementStock($this->db);
1779  $mouvS->origin = &$this;
1780 
1781  if (empty($obj->batch))
1782  {
1783  // line without batch detail
1784 
1785  // We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record
1786  $result = $mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, -$qty, $obj->subprice, $langs->trans("ReceptionBackToDraftInDolibarr", $this->ref));
1787  if ($result < 0) {
1788  $this->error = $mouvS->error;
1789  $this->errors = $mouvS->errors;
1790  $error++;
1791  break;
1792  }
1793  } else {
1794  // line with batch detail
1795 
1796  // We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record
1797  $result = $mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, -$qty, $obj->subprice, $langs->trans("ReceptionBackToDraftInDolibarr", $this->ref), $this->db->jdate($obj->eatby), $this->db->jdate($obj->sellby), $obj->batch);
1798  if ($result < 0) {
1799  $this->error = $mouvS->error;
1800  $this->errors = $mouvS->errors;
1801  $error++; break;
1802  }
1803  }
1804  }
1805  } else {
1806  $this->error = $this->db->lasterror();
1807  $error++;
1808  }
1809  }
1810 
1811  if (!$error) {
1812  // Call trigger
1813  $result = $this->call_trigger('RECEPTION_UNVALIDATE', $user);
1814  if ($result < 0) $error++;
1815  }
1816  if ($this->origin == 'order_supplier')
1817  {
1818  if (!empty($this->origin) && $this->origin_id > 0)
1819  {
1820  $this->fetch_origin();
1821  $origin = $this->origin;
1822  if ($this->$origin->statut == 4) // If order source of reception is "partially received"
1823  {
1824  // Check if there is no more reception validated.
1825  $this->$origin->fetchObjectLinked();
1826  $setStatut = 1;
1827  if (!empty($this->$origin->linkedObjects['reception']))
1828  {
1829  foreach ($this->$origin->linkedObjects['reception'] as $rcption)
1830  {
1831  if ($rcption->statut > 0)
1832  {
1833  $setStatut = 0;
1834  break;
1835  }
1836  }
1837  //var_dump($this->$origin->receptions);exit;
1838  if ($setStatut)
1839  {
1840  $this->$origin->setStatut(3); // ordered
1841  }
1842  }
1843  }
1844  }
1845  }
1846 
1847  if (!$error) {
1848  $this->statut = self::STATUS_DRAFT;
1849  $this->db->commit();
1850  return 1;
1851  } else {
1852  $this->db->rollback();
1853  return -1;
1854  }
1855  } else {
1856  $this->error = $this->db->error();
1857  $this->db->rollback();
1858  return -1;
1859  }
1860  }
1861 
1872  public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
1873  {
1874  global $conf, $langs;
1875 
1876  $langs->load("receptions");
1877 
1878  if (!dol_strlen($modele))
1879  {
1880  $modele = 'squille';
1881 
1882  if ($this->model_pdf) {
1883  $modele = $this->model_pdf;
1884  } elseif (!empty($conf->global->RECEPTION_ADDON_PDF)) {
1885  $modele = $conf->global->RECEPTION_ADDON_PDF;
1886  }
1887  }
1888 
1889  $modelpath = "core/modules/reception/doc/";
1890 
1891  $this->fetch_origin();
1892 
1893  return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref);
1894  }
1895 
1904  public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
1905  {
1906  $tables = array('reception');
1907 
1908  return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
1909  }
1910 }
if(!function_exists('dol_getprefix')) dol_include_once($relpath, $classname= '')
Make an include_once using default root and alternate root if it fails.
Class to manage stock movements.
LibStatut($status, $mode)
Return label of a status.
getLibStatut($mode=0)
Return status label.
disable_delivery_method($id)
DesActivate delivery method.
if(!empty($arrayfields['u.datec']['checked'])) print_liste_field_titre("DateCreationShort"u if(!empty($arrayfields['u.tms']['checked'])) print_liste_field_titre("DateModificationShort"u if(!empty($arrayfields['u.statut']['checked'])) print_liste_field_titre("Status"u statut
Definition: list.php:632
activ_delivery_method($id)
Activate delivery method.
setClosed()
Classify the reception as closed.
getUrlTrackingStatus($value= '')
Forge an set tracking url.
update($user=null, $notrigger=0)
Update database.
Class to manage table commandefournisseurdispatch.
reOpen()
Classify the reception as validated/opened.
setDeliveryDate($user, $delivery_date)
Set the planned delivery date.
dol_now($mode= 'auto')
Return date for now.
Class to manage Dolibarr users.
Definition: user.class.php:44
Class to manage Dolibarr database access.
list_delivery_methods($id= '')
Fetch all deliveries method and return an array.
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
fetch($id, $ref= '', $ref_ext= '', $notused= '')
Get object and lines from database.
fetch_origin()
Read linked origin object.
fetch_thirdparty($force_thirdparty_id=0)
Load the third party of object, from id $this-&gt;socid or $this-&gt;fk_soc, into this-&gt;thirdparty.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
update_delivery_method($id= '')
Update/create delivery method.
$conf db
API class for accounts.
Definition: inc.php:54
insertExtraFields($trigger= '', $userused=null)
Add/Update all extra fields values for the current object.
Class to manage standard extra fields.
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
Create a document onto disk according to template module.
Class to manage third parties objects (customers, suppliers, prospects...)
getNomUrl($withpicto=0, $option=0, $max=0, $short=0, $notooltip=0)
Return clicable link of object (with eventually picto)
dol_strlen($string, $stringencoding= 'UTF-8')
Make a strlen call.
setDraft($user)
Set draft status.
$conf db user
Definition: repair.php:109
static commonReplaceThirdparty(DoliDB $db, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
set_billed()
Classify the reception as invoiced (used when WORKFLOW_BILL_ON_RECEPTION is on)
img_picto($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt= '', $morecss= '', $marginleftonlyshort=2)
Show picto whatever it&#39;s its name (generic function)
Class to manage receptions.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename= '', $restricttologhandler= '', $logcontext=null)
Write log message into outputs.
addline($entrepot_id, $id, $qty, $array_options=0, $comment= '', $eatby= '', $sellby= '', $batch= '')
Add an reception line.
get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart= '')
Return a path to have a the directory according to object where files are stored. ...
dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0)
Remove a directory $dir and its subdirectories (or only files and subdirectories) ...
Definition: files.lib.php:1286
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1)
Remove a file or several files with a mask.
Definition: files.lib.php:1144
dol_sanitizeFileName($str, $newstr= '_', $unaccent=1)
Clean a string to use it as a file name.
dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0)
Scan a directory and return a list of files/directories.
Definition: files.lib.php:60
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this-&gt;array_options This method is in most cases call...
Class to manage predefined suppliers products.
deleteObjectLinked($sourceid=null, $sourcetype= '', $targetid=null, $targettype= '', $rowid= '')
Delete all links between an object $this.
getNextNumRef($soc)
Return next contract ref.
create($user, $notrigger=0)
Create reception en base.
fetch_lines()
Load lines.
trait CommonIncoterm
Superclass for incoterm classes.
static replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
print
Draft customers invoices.
Definition: index.php:89
call_trigger($triggerName, $user)
Call trigger based on this instance.
__construct($db)
Constructor.
setStatut($status, $elementId=null, $elementType= '', $trigkey= '')
Set status of an object.
if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) if(!empty($conf->don->enabled)&&$user->rights->don->lire) if(!empty($conf->tax->enabled)&&$user->rights->tax->charges->lire) if(!empty($conf->facture->enabled)&&!empty($conf->commande->enabled)&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1232
dol_print_error($db= '', $error= '', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dolGetStatus($statusLabel= '', $statusLabelShort= '', $html= '', $statusType= 'status0', $displayMode=0, $url= '', $params=array())
Output the badge of a status.
add_object_linked($origin=null, $origin_id=null)
Add objects linked in llx_element_element.
initAsSpecimen()
Initialise an instance with random values.
Parent class of all other business classes (invoices, contracts, proposals, orders, ...)
valid($user, $notrigger=0)
Validate object and update stock if option enabled.
fetch_delivery_methods()
Fetch deliveries method and return an array.
Class to manage line orders.