dolibarr  18.0.6
delivery.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2005-2014 Regis Houssin <regis.houssin@inodbox.com>
4  * Copyright (C) 2006-2007 Laurent Destailleur <eldy@users.sourceforge.net>
5  * Copyright (C) 2007 Franky Van Liedekerke <franky.van.liedekerke@telenet.be>
6  * Copyright (C) 2011-2023 Philippe Grand <philippe.grand@atoo-net.com>
7  * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
8  * Copyright (C) 2014-2015 Marcos García <marcosgdf@gmail.com>
9  * Copyright (C) 2023 Frédéric France <frederic.france@netlogic.fr>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program. If not, see <https://www.gnu.org/licenses/>.
23  */
24 
31 require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
32 require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
33 require_once DOL_DOCUMENT_ROOT.'/core/class/commonincoterm.class.php';
34 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
35 if (isModEnabled("propal")) {
36  require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
37 }
38 if (isModEnabled('commande')) {
39  require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
40 }
41 
42 
46 class Delivery extends CommonObject
47 {
48  use CommonIncoterm;
49 
53  public $element = "delivery";
54 
58  public $fk_element = "fk_delivery";
59 
63  public $table_element = "delivery";
64 
68  public $table_element_line = "deliverydet";
69 
73  public $picto = 'sending';
74 
78  public $draft;
79 
83  public $socid;
84 
88  public $ref_customer;
89 
93  public $date_delivery;
94 
98  public $date_creation;
99 
103  public $date_valid;
104 
108  public $model_pdf;
109 
110  public $commande_id;
111 
115  public $statuts;
116 
120  public $lines = array();
121 
122 
128  public function __construct($db)
129  {
130  $this->db = $db;
131 
132  // List of short language codes for status
133  $this->statuts[-1] = 'StatusDeliveryCanceled';
134  $this->statuts[0] = 'StatusDeliveryDraft';
135  $this->statuts[1] = 'StatusDeliveryValidated';
136  }
137 
144  public function create($user)
145  {
146  global $conf;
147 
148  dol_syslog("Delivery::create");
149 
150  if (empty($this->model_pdf)) {
151  $this->model_pdf = $conf->global->DELIVERY_ADDON_PDF;
152  }
153 
154  $error = 0;
155 
156  $now = dol_now();
157 
158  /* Delivery note as draft On positionne en mode draft le bon de livraison */
159  $this->draft = 1;
160 
161  $this->user = $user;
162 
163  $this->db->begin();
164 
165  $sql = "INSERT INTO ".MAIN_DB_PREFIX."delivery (";
166  $sql .= "ref";
167  $sql .= ", entity";
168  $sql .= ", fk_soc";
169  $sql .= ", ref_customer";
170  $sql .= ", date_creation";
171  $sql .= ", fk_user_author";
172  $sql .= ", date_delivery";
173  $sql .= ", fk_address";
174  $sql .= ", note_private";
175  $sql .= ", note_public";
176  $sql .= ", model_pdf";
177  $sql .= ", fk_incoterms, location_incoterms";
178  $sql .= ") VALUES (";
179  $sql .= "'(PROV)'";
180  $sql .= ", ".((int) $conf->entity);
181  $sql .= ", ".((int) $this->socid);
182  $sql .= ", '".$this->db->escape($this->ref_customer)."'";
183  $sql .= ", '".$this->db->idate($now)."'";
184  $sql .= ", ".((int) $user->id);
185  $sql .= ", ".($this->date_delivery ? "'".$this->db->idate($this->date_delivery)."'" : "null");
186  $sql .= ", ".($this->fk_delivery_address > 0 ? $this->fk_delivery_address : "null");
187  $sql .= ", ".(!empty($this->note_private) ? "'".$this->db->escape($this->note_private)."'" : "null");
188  $sql .= ", ".(!empty($this->note_public) ? "'".$this->db->escape($this->note_public)."'" : "null");
189  $sql .= ", ".(!empty($this->model_pdf) ? "'".$this->db->escape($this->model_pdf)."'" : "null");
190  $sql .= ", ".(int) $this->fk_incoterms;
191  $sql .= ", '".$this->db->escape($this->location_incoterms)."'";
192  $sql .= ")";
193 
194  dol_syslog("Delivery::create", LOG_DEBUG);
195  $resql = $this->db->query($sql);
196  if ($resql) {
197  $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."delivery");
198 
199  $numref = "(PROV".$this->id.")";
200 
201  $sql = "UPDATE ".MAIN_DB_PREFIX."delivery ";
202  $sql .= "SET ref = '".$this->db->escape($numref)."'";
203  $sql .= " WHERE rowid = ".((int) $this->id);
204 
205  dol_syslog("Delivery::create", LOG_DEBUG);
206  $resql = $this->db->query($sql);
207  if ($resql) {
208  if (!getDolGlobalInt('MAIN_SUBMODULE_EXPEDITION')) {
209  $commande = new Commande($this->db);
210  $commande->id = $this->commande_id;
211  $commande->fetch_lines();
212  }
213 
214 
215  /*
216  * Inserting products into the database
217  */
218  $num = count($this->lines);
219  for ($i = 0; $i < $num; $i++) {
220  $origin_id = $this->lines[$i]->origin_line_id;
221  if (!$origin_id) {
222  $origin_id = $this->lines[$i]->commande_ligne_id; // For backward compatibility
223  }
224 
225  if (!$this->create_line($origin_id, $this->lines[$i]->qty, $this->lines[$i]->fk_product, $this->lines[$i]->description, $this->lines[$i]->array_options)) {
226  $error++;
227  }
228  }
229 
230  if (!$error && $this->id && $this->origin_id) {
231  $ret = $this->add_object_linked();
232  if (!$ret) {
233  $error++;
234  }
235 
236  if (!getDolGlobalInt('MAIN_SUBMODULE_EXPEDITION')) {
237  $ret = $this->setStatut(2, $this->origin_id, $this->origin);
238  if (!$ret) {
239  $error++;
240  }
241  }
242  }
243 
244  if (!$error) {
245  $this->db->commit();
246  return $this->id;
247  } else {
248  $error++;
249  $this->error = $this->db->lasterror()." - sql=".$this->db->lastqueryerror;
250  $this->db->rollback();
251  return -3;
252  }
253  } else {
254  $error++;
255  $this->error = $this->db->lasterror()." - sql=".$this->db->lastqueryerror;
256  $this->db->rollback();
257  return -2;
258  }
259  } else {
260  $error++;
261  $this->error = $this->db->lasterror()." - sql=".$this->db->lastqueryerror;
262  $this->db->rollback();
263  return -1;
264  }
265  }
266 
267  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
278  public function create_line($origin_id, $qty, $fk_product, $description, $array_options = null)
279  {
280  // phpcs:enable
281  $error = 0;
282  $idprod = $fk_product;
283 
284  $sql = "INSERT INTO ".MAIN_DB_PREFIX."deliverydet (fk_delivery, fk_origin_line,";
285  $sql .= " fk_product, description, qty)";
286  $sql .= " VALUES (".$this->id.",".((int) $origin_id).",";
287  $sql .= " ".($idprod > 0 ? ((int) $idprod) : "null").",";
288  $sql .= " ".($description ? "'".$this->db->escape($description)."'" : "null").",";
289  $sql .= (price2num($qty, 'MS')).")";
290 
291  dol_syslog(get_class($this)."::create_line", LOG_DEBUG);
292  if (!$this->db->query($sql)) {
293  $error++;
294  }
295 
296  $id = $this->db->last_insert_id(MAIN_DB_PREFIX."deliverydet");
297 
298  if (is_array($array_options) && count($array_options) > 0) {
299  $line = new DeliveryLine($this->db);
300  $line->id = $id;
301  $line->array_options = $array_options;
302  $result = $line->insertExtraFields();
303  }
304 
305  if (!$error) {
306  return 1;
307  }
308 
309  return -1;
310  }
311 
318  public function fetch($id)
319  {
320  $sql = "SELECT l.rowid, l.fk_soc, l.date_creation, l.date_valid, l.ref, l.ref_customer, l.fk_user_author,";
321  $sql .= " l.total_ht, l.fk_statut, l.fk_user_valid, l.note_private, l.note_public";
322  $sql .= ", l.date_delivery, l.fk_address, l.model_pdf";
323  $sql .= ", el.fk_source as origin_id, el.sourcetype as origin";
324  $sql .= ', l.fk_incoterms, l.location_incoterms';
325  $sql .= ", i.libelle as label_incoterms";
326  $sql .= " FROM ".MAIN_DB_PREFIX."delivery as l";
327  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."element_element as el ON el.fk_target = l.rowid AND el.targettype = '".$this->db->escape($this->element)."'";
328  $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_incoterms as i ON l.fk_incoterms = i.rowid';
329  $sql .= " WHERE l.rowid = ".((int) $id);
330 
331  dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
332  $result = $this->db->query($sql);
333  if ($result) {
334  if ($this->db->num_rows($result)) {
335  $obj = $this->db->fetch_object($result);
336 
337  $this->id = $obj->rowid;
338  $this->date_delivery = $this->db->jdate($obj->date_delivery);
339  $this->date_creation = $this->db->jdate($obj->date_creation);
340  $this->date_valid = $this->db->jdate($obj->date_valid);
341  $this->ref = $obj->ref;
342  $this->ref_customer = $obj->ref_customer;
343  $this->socid = $obj->fk_soc;
344  $this->statut = $obj->fk_statut;
345  $this->user_author_id = $obj->fk_user_author;
346  $this->user_valid_id = $obj->fk_user_valid;
347  $this->fk_delivery_address = $obj->fk_address;
348  $this->note = $obj->note_private; //TODO deprecated
349  $this->note_private = $obj->note_private;
350  $this->note_public = $obj->note_public;
351  $this->model_pdf = $obj->model_pdf;
352  $this->modelpdf = $obj->model_pdf; // deprecated
353  $this->origin = $obj->origin; // May be 'shipping'
354  $this->origin_id = $obj->origin_id; // May be id of shipping
355 
356  //Incoterms
357  $this->fk_incoterms = $obj->fk_incoterms;
358  $this->location_incoterms = $obj->location_incoterms;
359  $this->label_incoterms = $obj->label_incoterms;
360  $this->db->free($result);
361 
362  if ($this->statut == 0) {
363  $this->draft = 1;
364  }
365 
366  // Retrieve all extrafields
367  // fetch optionals attributes and labels
368  $this->fetch_optionals();
369 
370  // Load lines
371  $result = $this->fetch_lines();
372  if ($result < 0) {
373  return -3;
374  }
375 
376  return 1;
377  } else {
378  $this->error = 'Delivery with id '.$id.' not found sql='.$sql;
379  dol_syslog(get_class($this).'::fetch Error '.$this->error, LOG_ERR);
380  return -2;
381  }
382  } else {
383  $this->error = $this->db->error();
384  return -1;
385  }
386  }
387 
395  public function valid($user, $notrigger = 0)
396  {
397  global $conf;
398 
399  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
400 
401  dol_syslog(get_class($this)."::valid begin");
402 
403  $this->db->begin();
404 
405  $error = 0;
406 
407  if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->expedition->delivery->creer))
408  || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->expedition->delivery_advance->validate))) {
409  if (!empty($conf->global->DELIVERY_ADDON_NUMBER)) {
410  // Setting the command numbering module name
411  $modName = $conf->global->DELIVERY_ADDON_NUMBER;
412 
413  if (is_readable(DOL_DOCUMENT_ROOT.'/core/modules/delivery/'.$modName.'.php')) {
414  require_once DOL_DOCUMENT_ROOT.'/core/modules/delivery/'.$modName.'.php';
415 
416  $now = dol_now();
417 
418  // Retrieving the new reference
419  $objMod = new $modName($this->db);
420  $soc = new Societe($this->db);
421  $soc->fetch($this->socid);
422 
423  if (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref)) { // empty should not happened, but when it occurs, the test save life
424  $numref = $objMod->delivery_get_num($soc, $this);
425  } else {
426  $numref = $this->ref;
427  }
428  $this->newref = dol_sanitizeFileName($numref);
429 
430  // Test if is not already in valid status. If so, we stop to avoid decrementing the stock twice.
431  $sql = "SELECT ref";
432  $sql .= " FROM ".MAIN_DB_PREFIX."delivery";
433  $sql .= " WHERE ref = '".$this->db->escape($numref)."'";
434  $sql .= " AND fk_statut <> 0";
435  $sql .= " AND entity = ".((int) $conf->entity);
436 
437  $resql = $this->db->query($sql);
438  if ($resql) {
439  $num = $this->db->num_rows($resql);
440  if ($num > 0) {
441  return 0;
442  }
443  }
444 
445  $sql = "UPDATE ".MAIN_DB_PREFIX."delivery SET";
446  $sql .= " ref='".$this->db->escape($numref)."'";
447  $sql .= ", fk_statut = 1";
448  $sql .= ", date_valid = '".$this->db->idate($now)."'";
449  $sql .= ", fk_user_valid = ".$user->id;
450  $sql .= " WHERE rowid = ".((int) $this->id);
451  $sql .= " AND fk_statut = 0";
452 
453  $resql = $this->db->query($sql);
454  if (!$resql) {
455  dol_print_error($this->db);
456  $this->error = $this->db->lasterror();
457  $error++;
458  }
459 
460  if (!$error && !$notrigger) {
461  // Call trigger
462  $result = $this->call_trigger('DELIVERY_VALIDATE', $user);
463  if ($result < 0) {
464  $error++;
465  }
466  // End call triggers
467  }
468 
469  if (!$error) {
470  $this->oldref = $this->ref;
471 
472  // Rename directory if dir was a temporary ref
473  if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
474  // Now we rename also files into index
475  $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'expedition/receipt/".$this->db->escape($this->newref)."'";
476  $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'expedition/receipt/".$this->db->escape($this->ref)."' and entity = ".((int) $conf->entity);
477  $resql = $this->db->query($sql);
478  if (!$resql) {
479  $error++; $this->error = $this->db->lasterror();
480  }
481  $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'expedition/receipt/".$this->db->escape($this->newref)."'";
482  $sql .= " WHERE filepath = 'expedition/receipt/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
483  $resql = $this->db->query($sql);
484  if (!$resql) {
485  $error++; $this->error = $this->db->lasterror();
486  }
487 
488  // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
489  $oldref = dol_sanitizeFileName($this->ref);
490  $newref = dol_sanitizeFileName($numref);
491  $dirsource = $conf->expedition->dir_output.'/receipt/'.$oldref;
492  $dirdest = $conf->expedition->dir_output.'/receipt/'.$newref;
493  if (!$error && file_exists($dirsource)) {
494  dol_syslog(get_class($this)."::valid rename dir ".$dirsource." into ".$dirdest);
495 
496  if (@rename($dirsource, $dirdest)) {
497  dol_syslog("Rename ok");
498  // Rename docs starting with $oldref with $newref
499  $listoffiles = dol_dir_list($conf->expedition->dir_output.'/receipt/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
500  foreach ($listoffiles as $fileentry) {
501  $dirsource = $fileentry['name'];
502  $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
503  $dirsource = $fileentry['path'].'/'.$dirsource;
504  $dirdest = $fileentry['path'].'/'.$dirdest;
505  @rename($dirsource, $dirdest);
506  }
507  }
508  }
509  }
510 
511  // Set new ref and current status
512  if (!$error) {
513  $this->ref = $numref;
514  $this->statut = 1;
515  }
516 
517  dol_syslog(get_class($this)."::valid ok");
518  }
519 
520  if (!$error) {
521  $this->db->commit();
522  return 1;
523  } else {
524  $this->db->rollback();
525  return -1;
526  }
527  }
528  }
529 
530  return -1;
531  } else {
532  $this->error = "NotAllowed";
533  dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
534  return -1;
535  }
536  }
537 
538  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
546  public function create_from_sending($user, $sending_id)
547  {
548  // phpcs:enable
549  global $conf;
550 
551  $expedition = new Expedition($this->db);
552  $result = $expedition->fetch($sending_id);
553  if ($result <= 0) {
554  return $result;
555  }
556 
557  $this->lines = array();
558 
559  $num = count($expedition->lines);
560  for ($i = 0; $i < $num; $i++) {
561  $line = new DeliveryLine($this->db);
562  $line->origin_line_id = $expedition->lines[$i]->origin_line_id;
563  $line->label = $expedition->lines[$i]->label;
564  $line->description = $expedition->lines[$i]->description;
565  $line->qty = $expedition->lines[$i]->qty_shipped;
566  $line->fk_product = $expedition->lines[$i]->fk_product;
567  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($expedition->lines[$i]->array_options) && count($expedition->lines[$i]->array_options) > 0) { // For avoid conflicts if trigger used
568  $line->array_options = $expedition->lines[$i]->array_options;
569  }
570  $this->lines[$i] = $line;
571  }
572 
573  $this->origin = $expedition->element;
574  $this->origin_id = $expedition->id;
575  $this->note_private = $expedition->note_private;
576  $this->note_public = $expedition->note_public;
577  $this->fk_project = $expedition->fk_project;
578  $this->date_delivery = $expedition->date_delivery;
579  $this->fk_delivery_address = $expedition->fk_delivery_address;
580  $this->socid = $expedition->socid;
581  $this->ref_customer = $expedition->ref_customer;
582 
583  //Incoterms
584  $this->fk_incoterms = $expedition->fk_incoterms;
585  $this->location_incoterms = $expedition->location_incoterms;
586 
587  return $this->create($user);
588  }
589 
590  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
598  public function update_line($id, $array_options = 0)
599  {
600  // phpcs:enable
601  global $conf;
602  $error = 0;
603 
604  if ($id > 0 && !$error && empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($array_options) && count($array_options) > 0) { // For avoid conflicts if trigger used
605  $line = new DeliveryLine($this->db);
606  $line->array_options = $array_options;
607  $line->id = $id;
608  $result = $line->insertExtraFields();
609 
610  if ($result < 0) {
611  $this->error[] = $line->error;
612  $error++;
613  }
614  }
615 
616  if (!$error) {
617  return 1;
618  } else {
619  return -1;
620  }
621  }
622 
623 
632  public function addline($origin_id, $qty, $array_options = null)
633  {
634  global $conf;
635 
636  $num = count($this->lines);
637  $line = new DeliveryLine($this->db);
638 
639  $line->origin_id = $origin_id;
640  $line->qty = $qty;
641  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($array_options) && count($array_options) > 0) { // For avoid conflicts if trigger used
642  $line->array_options = $array_options;
643  }
644  $this->lines[$num] = $line;
645  }
646 
653  public function deleteline($lineid)
654  {
655  if ($this->statut == 0) {
656  $sql = "DELETE FROM ".MAIN_DB_PREFIX."commandedet";
657  $sql .= " WHERE rowid = ".((int) $lineid);
658 
659  if ($this->db->query($sql)) {
660  $this->update_price(1);
661 
662  return 1;
663  } else {
664  return -1;
665  }
666  }
667 
668  return 0;
669  }
670 
676  public function delete()
677  {
678  global $conf, $langs, $user;
679 
680  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
681  $this->db->begin();
682 
683  $error = 0;
684 
685  $sql = "DELETE FROM ".MAIN_DB_PREFIX."deliverydet";
686  $sql .= " WHERE fk_delivery = ".((int) $this->id);
687  if ($this->db->query($sql)) {
688  // Delete linked object
689  $res = $this->deleteObjectLinked();
690  if ($res < 0) {
691  $error++;
692  }
693 
694  if (!$error) {
695  $sql = "DELETE FROM ".MAIN_DB_PREFIX."delivery";
696  $sql .= " WHERE rowid = ".((int) $this->id);
697  if ($this->db->query($sql)) {
698  $this->db->commit();
699 
700  // Deleting pdf folder's draft On efface le repertoire de pdf provisoire
701  $ref = dol_sanitizeFileName($this->ref);
702  if (!empty($conf->expedition->dir_output)) {
703  $dir = $conf->expedition->dir_output.'/receipt/'.$ref;
704  $file = $dir.'/'.$ref.'.pdf';
705  if (file_exists($file)) {
706  if (!dol_delete_file($file)) {
707  return 0;
708  }
709  }
710  if (file_exists($dir)) {
711  if (!dol_delete_dir($dir)) {
712  $this->error = $langs->trans("ErrorCanNotDeleteDir", $dir);
713  return 0;
714  }
715  }
716  }
717 
718  // Call trigger
719  $result = $this->call_trigger('DELIVERY_DELETE', $user);
720  if ($result < 0) {
721  $this->db->rollback();
722  return -4;
723  }
724  // End call triggers
725 
726  return 1;
727  } else {
728  $this->error = $this->db->lasterror()." - sql=$sql";
729  $this->db->rollback();
730  return -3;
731  }
732  } else {
733  $this->error = $this->db->lasterror()." - sql=$sql";
734  $this->db->rollback();
735  return -2;
736  }
737  } else {
738  $this->error = $this->db->lasterror()." - sql=$sql";
739  $this->db->rollback();
740  return -1;
741  }
742  }
743 
750  public function getTooltipContentArray($params)
751  {
752  global $langs;
753 
754  $datas = [];
755 
756  $datas['picto'] = img_picto('', $this->picto).' <u>'.$langs->trans("ShowReceiving").'</u>:<br>';
757  $datas['picto'] .= '<b>'.$langs->trans("Status").'</b>: '.$this->ref;
758 
759  return $datas;
760  }
761 
769  public function getNomUrl($withpicto = 0, $save_lastsearch_value = -1)
770  {
771  global $langs, $hookmanager;
772 
773  $result = '';
774 
775  $params = [
776  'id' => $this->id,
777  'objecttype' => $this->element,
778  ];
779  $classfortooltip = 'classfortooltip';
780  $dataparams = '';
781  if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
782  $classfortooltip = 'classforajaxtooltip';
783  $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
784  $label = '';
785  } else {
786  $label = implode($this->getTooltipContentArray($params));
787  }
788 
789  $url = DOL_URL_ROOT.'/delivery/card.php?id='.$this->id;
790 
791  //if ($option !== 'nolink')
792  //{
793  // Add param to save lastsearch_values or not
794  $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
795  if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
796  $add_save_lastsearch_values = 1;
797  }
798  if ($add_save_lastsearch_values) {
799  $url .= '&save_lastsearch_values=1';
800  }
801  //}
802 
803  $linkstart = '<a href="'.$url.'"';
804  $linkstart .= ($label ? ' title="'.dol_escape_htmltag($label, 1).'"' : ' title="tocomplete"');
805  $linkstart .= $dataparams.' class="'.$classfortooltip.'">';
806  $linkend = '</a>';
807 
808  if ($withpicto) {
809  $result .= ($linkstart.img_object($label, $this->picto, $dataparams.' class="'.$classfortooltip.'"').$linkend);
810  }
811  if ($withpicto && $withpicto != 2) {
812  $result .= ' ';
813  }
814  $result .= $linkstart.$this->ref.$linkend;
815 
816  global $action;
817  $hookmanager->initHooks(array($this->element . 'dao'));
818  $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
819  $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
820  if ($reshook > 0) {
821  $result = $hookmanager->resPrint;
822  } else {
823  $result .= $hookmanager->resPrint;
824  }
825  return $result;
826  }
827 
828  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
834  public function fetch_lines()
835  {
836  // phpcs:enable
837  $this->lines = array();
838 
839  $sql = "SELECT ld.rowid, ld.fk_product, ld.description, ld.subprice, ld.total_ht, ld.qty as qty_shipped, ld.fk_origin_line, ";
840  $sql .= " cd.qty as qty_asked, cd.label as custom_label, cd.fk_unit,";
841  $sql .= " p.ref as product_ref, p.fk_product_type as fk_product_type, p.label as product_label, p.description as product_desc,";
842  $sql .= " p.weight, p.weight_units, p.width, p.width_units, p.length, p.length_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units, p.tobatch as product_tobatch";
843  $sql .= " FROM ".MAIN_DB_PREFIX."commandedet as cd, ".MAIN_DB_PREFIX."deliverydet as ld";
844  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p on p.rowid = ld.fk_product";
845  $sql .= " WHERE ld.fk_origin_line = cd.rowid";
846  $sql .= " AND ld.fk_delivery = ".((int) $this->id);
847 
848  dol_syslog(get_class($this)."::fetch_lines", LOG_DEBUG);
849  $resql = $this->db->query($sql);
850  if ($resql) {
851  $num = $this->db->num_rows($resql);
852  $i = 0;
853  while ($i < $num) {
854  $obj = $this->db->fetch_object($resql);
855 
856  $line = new DeliveryLine($this->db);
857 
858  $line->id = $obj->rowid;
859  $line->label = $obj->custom_label;
860  $line->description = $obj->description;
861  $line->fk_product = $obj->fk_product;
862  $line->qty_asked = $obj->qty_asked;
863  $line->qty_shipped = $obj->qty_shipped;
864 
865  $line->ref = $obj->product_ref; // deprecated
866  $line->libelle = $obj->product_label; // deprecated
867  $line->product_label = $obj->product_label; // Product label
868  $line->product_ref = $obj->product_ref; // Product ref
869  $line->product_desc = $obj->product_desc; // Product description
870  $line->product_type = $obj->fk_product_type;
871  $line->fk_origin_line = $obj->fk_origin_line;
872 
873  $line->price = $obj->subprice;
874  $line->total_ht = $obj->total_ht;
875 
876  // units
877  $line->weight = $obj->weight;
878  $line->weight_units = $obj->weight_units;
879  $line->width = $obj->width;
880  $line->width_units = $obj->width_units;
881  $line->height = $obj->height;
882  $line->height_units = $obj->height_units;
883  $line->length = $obj->length;
884  $line->length_units = $obj->length_units;
885  $line->surface = $obj->surface;
886  $line->surface_units = $obj->surface_units;
887  $line->volume = $obj->volume;
888  $line->volume_units = $obj->volume_units;
889 
890  $line->fk_unit = $obj->fk_unit;
891  $line->fetch_optionals();
892 
893  $this->lines[$i] = $line;
894 
895  $i++;
896  }
897  $this->db->free($resql);
898 
899  return 1;
900  } else {
901  return -1;
902  }
903  }
904 
905 
912  public function getLibStatut($mode = 0)
913  {
914  return $this->LibStatut($this->statut, $mode);
915  }
916 
917  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
925  public function LibStatut($status, $mode)
926  {
927  // phpcs:enable
928  global $langs;
929 
930  if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
931  global $langs;
932  //$langs->load("mymodule");
933  $this->labelStatus[-1] = $langs->transnoentitiesnoconv('StatusDeliveryCanceled');
934  $this->labelStatus[0] = $langs->transnoentitiesnoconv('StatusDeliveryDraft');
935  $this->labelStatus[1] = $langs->transnoentitiesnoconv('StatusDeliveryValidated');
936  $this->labelStatusShort[-1] = $langs->transnoentitiesnoconv('StatusDeliveryCanceled');
937  $this->labelStatusShort[0] = $langs->transnoentitiesnoconv('StatusDeliveryDraft');
938  $this->labelStatusShort[1] = $langs->transnoentitiesnoconv('StatusDeliveryValidated');
939  }
940 
941  $statusType = 'status0';
942  if ($status == -1) {
943  $statusType = 'status5';
944  }
945  if ($status == 1) {
946  $statusType = 'status4';
947  }
948 
949  return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
950  }
951 
952 
960  public function initAsSpecimen()
961  {
962  $now = dol_now();
963 
964  // Load array of products prodids
965  $num_prods = 0;
966  $prodids = array();
967  $sql = "SELECT rowid";
968  $sql .= " FROM ".MAIN_DB_PREFIX."product";
969  $sql .= " WHERE entity IN (".getEntity('product').")";
970  $sql .= " AND tosell = 1";
971  $sql .= $this->db->plimit(100);
972 
973  $resql = $this->db->query($sql);
974  if ($resql) {
975  $num_prods = $this->db->num_rows($resql);
976  $i = 0;
977  while ($i < $num_prods) {
978  $i++;
979  $row = $this->db->fetch_row($resql);
980  $prodids[$i] = $row[0];
981  }
982  }
983 
984  // Initialise parametres
985  $this->id = 0;
986  $this->ref = 'SPECIMEN';
987  $this->specimen = 1;
988  $this->socid = 1;
989  $this->date_delivery = $now;
990  $this->note_public = 'Public note';
991  $this->note_private = 'Private note';
992 
993  $i = 0;
994  $line = new DeliveryLine($this->db);
995  $line->fk_product = reset($prodids);
996  $line->qty_asked = 10;
997  $line->qty_shipped = 9;
998  $line->ref = 'REFPROD';
999  $line->label = 'Specimen';
1000  $line->description = 'Description';
1001  $line->price = 100;
1002  $line->total_ht = 100;
1003 
1004  $this->lines[$i] = $line;
1005  }
1006 
1013  public function getRemainingDelivered()
1014  {
1015  // Get the linked object
1016  $this->fetchObjectLinked('', '', $this->id, $this->element);
1017  //var_dump($this->linkedObjectsIds);
1018  // Get the product ref and qty in source
1019  $sqlSourceLine = "SELECT st.rowid, st.description, st.qty";
1020  $sqlSourceLine .= ", p.ref, p.label";
1021  $sqlSourceLine .= " FROM ".MAIN_DB_PREFIX.$this->linkedObjectsIds[0]['type']."det as st";
1022  $sqlSourceLine .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON st.fk_product = p.rowid";
1023  $sqlSourceLine .= " WHERE fk_".$this->linked_objects[0]['type']." = ".((int) $this->linked_objects[0]['linkid']);
1024 
1025  $resultSourceLine = $this->db->query($sqlSourceLine);
1026  if ($resultSourceLine) {
1027  $num_lines = $this->db->num_rows($resultSourceLine);
1028  $i = 0;
1029  $array = array();
1030  while ($i < $num_lines) {
1031  $objSourceLine = $this->db->fetch_object($resultSourceLine);
1032 
1033  // Get lines of sources alread delivered
1034  $sql = "SELECT ld.fk_origin_line, sum(ld.qty) as qty";
1035  $sql .= " FROM ".MAIN_DB_PREFIX."deliverydet as ld, ".MAIN_DB_PREFIX."delivery as l,";
1036  $sql .= " ".MAIN_DB_PREFIX.$this->linked_objects[0]['type']." as c";
1037  $sql .= ", ".MAIN_DB_PREFIX.$this->linked_objects[0]['type']."det as cd";
1038  $sql .= " WHERE ld.fk_delivery = l.rowid";
1039  $sql .= " AND ld.fk_origin_line = cd.rowid";
1040  $sql .= " AND cd.fk_".$this->linked_objects[0]['type']." = c.rowid";
1041  $sql .= " AND cd.fk_".$this->linked_objects[0]['type']." = ".((int) $this->linked_objects[0]['linkid']);
1042  $sql .= " AND ld.fk_origin_line = ".((int) $objSourceLine->rowid);
1043  $sql .= " GROUP BY ld.fk_origin_line";
1044 
1045  $result = $this->db->query($sql);
1046  $row = $this->db->fetch_row($result);
1047 
1048  if ($objSourceLine->qty - $row[1] > 0) {
1049  if ($row[0] == $objSourceLine->rowid) {
1050  $array[$i]['qty'] = $objSourceLine->qty - $row[1];
1051  } else {
1052  $array[$i]['qty'] = $objSourceLine->qty;
1053  }
1054 
1055  $array[$i]['ref'] = $objSourceLine->ref;
1056  $array[$i]['label'] = $objSourceLine->label ? $objSourceLine->label : $objSourceLine->description;
1057  } elseif ($objSourceLine->qty - $row[1] < 0) {
1058  $array[$i]['qty'] = $objSourceLine->qty - $row[1]." Erreur livraison !";
1059  $array[$i]['ref'] = $objSourceLine->ref;
1060  $array[$i]['label'] = $objSourceLine->label ? $objSourceLine->label : $objSourceLine->description;
1061  }
1062 
1063  $i++;
1064  }
1065  return $array;
1066  } else {
1067  $this->error = $this->db->error()." - sql=$sqlSourceLine";
1068  return -1;
1069  }
1070  }
1071 
1079  public function setDeliveryDate($user, $delivery_date)
1080  {
1081  if ($user->rights->expedition->creer) {
1082  $sql = "UPDATE ".MAIN_DB_PREFIX."delivery";
1083  $sql .= " SET date_delivery = ".($delivery_date ? "'".$this->db->idate($delivery_date)."'" : 'null');
1084  $sql .= " WHERE rowid = ".((int) $this->id);
1085 
1086  dol_syslog(get_class($this)."::setDeliveryDate", LOG_DEBUG);
1087  $resql = $this->db->query($sql);
1088  if ($resql) {
1089  $this->date_delivery = $delivery_date;
1090  return 1;
1091  } else {
1092  $this->error = $this->db->error();
1093  return -1;
1094  }
1095  } else {
1096  return -2;
1097  }
1098  }
1099 
1110  public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
1111  {
1112  global $conf, $langs;
1113 
1114  $langs->load("deliveries");
1115  $outputlangs->load("products");
1116 
1117  if (!dol_strlen($modele)) {
1118  $modele = 'typhon';
1119 
1120  if ($this->model_pdf) {
1121  $modele = $this->model_pdf;
1122  } elseif (!empty($conf->global->DELIVERY_ADDON_PDF)) {
1123  $modele = $conf->global->DELIVERY_ADDON_PDF;
1124  }
1125  }
1126 
1127  $modelpath = "core/modules/delivery/doc/";
1128 
1129  return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref);
1130  }
1131 
1140  public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
1141  {
1142  $tables = array(
1143  'delivery'
1144  );
1145 
1146  return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables);
1147  }
1148 
1157  public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
1158  {
1159  $tables = array(
1160  'deliverydet'
1161  );
1162 
1163  return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables);
1164  }
1165 }
1166 
1167 
1172 {
1176  public $db;
1177 
1181  public $element = 'deliverydet';
1182 
1186  public $table_element = 'deliverydet';
1187 
1191  public $label;
1192 
1196  public $description;
1197 
1202  public $ref;
1207  public $libelle;
1208 
1209  // From llx_expeditiondet
1210  public $qty;
1211  public $qty_asked;
1212  public $qty_shipped;
1213 
1214  public $fk_product;
1215  public $product_desc;
1216  public $product_type;
1217  public $product_ref;
1218  public $product_label;
1219 
1220  public $price;
1221 
1222  public $fk_origin_line;
1223  public $origin_id;
1224 
1228  public $origin_line_id;
1229 
1235  public $commande_ligne_id;
1236 
1237 
1243  public function __construct($db)
1244  {
1245  $this->db = $db;
1246  }
1247 }
$object ref
Definition: info.php:78
Class to manage customers orders.
Parent class of all other business classes (invoices, contracts, proposals, orders,...
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this->array_options This method is in most cases call...
add_object_linked($origin=null, $origin_id=null, $f_user=null, $notrigger=0)
Add an object link into llx_element_element.
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
deleteObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $rowid='', $f_user=null, $notrigger=0)
Delete all links between an object $this.
setStatut($status, $elementId=null, $elementType='', $trigkey='', $fieldstatus='fk_statut')
Set status of an object.
update_price($exclspec=0, $roundingadjust='none', $nodatabaseupdate=0, $seller=null)
Update total_ht, total_ttc, total_vat, total_localtax1, total_localtax2 for an object (sum of lines).
static commonReplaceThirdparty(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
fetchObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $clause='OR', $alsosametype=1, $orderby='sourcetype', $loadalsoobjects=1)
Fetch array of objects linked to current object (object of enabled modules only).
static commonReplaceProduct(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a product id with another one.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Parent class for class inheritance lines of business objects This class is useless for the moment so ...
Class to manage receptions.
valid($user, $notrigger=0)
Validate object and update stock if option enabled.
addline($origin_id, $qty, $array_options=null)
Add line.
__construct($db)
Constructor.
static replaceProduct(DoliDB $db, $origin_id, $dest_id)
Function used to replace a product id with another one.
setDeliveryDate($user, $delivery_date)
Set the planned delivery date.
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
Create object on disk.
fetch($id)
Load a delivery receipt.
create($user)
Create delivery receipt in database.
create_line($origin_id, $qty, $fk_product, $description, $array_options=null)
Create a line.
initAsSpecimen()
Initialise an instance with random values.
create_from_sending($user, $sending_id)
Creating the delivery slip from an existing shipment.
static replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
getTooltipContentArray($params)
getTooltipContentArray
getLibStatut($mode=0)
Return the label of the status.
LibStatut($status, $mode)
Return the label of a given status.
update_line($id, $array_options=0)
Update a livraison line (only extrafields)
deleteline($lineid)
Delete line.
fetch_lines()
Load lines insto $this->lines.
getRemainingDelivered()
Renvoie la quantite de produit restante a livrer pour une commande.
getNomUrl($withpicto=0, $save_lastsearch_value=-1)
Return clicable name (with picto eventually)
Management class of delivery note lines.
__construct($db)
Constructor.
Class to manage Dolibarr database access.
Class to manage shipments.
Class to manage third parties objects (customers, suppliers, prospects...)
trait CommonIncoterm
Superclass for incoterm classes.
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->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') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
print *****$script_file(".$version.") pid cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
Definition: files.lib.php:1356
dol_delete_dir($dir, $nophperrors=0)
Remove a directory (not recursive, so content must be empty).
Definition: files.lib.php:1482
dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition: files.lib.php:62
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
$conf db user
Definition: repair.php:124