dolibarr 20.0.0
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-2024 Frédéric France <frederic.france@free.fr>
10 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <https://www.gnu.org/licenses/>.
24 */
25
32require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
33require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
34require_once DOL_DOCUMENT_ROOT.'/core/class/commonincoterm.class.php';
35require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
36if (isModEnabled("propal")) {
37 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
38}
39if (isModEnabled('order')) {
40 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
41}
42
43
48{
50
54 public $element = "delivery";
55
59 public $fk_element = "fk_delivery";
60
64 public $table_element = "delivery";
65
69 public $table_element_line = "deliverydet";
70
74 public $picto = 'sending';
75
79 public $draft;
80
84 public $socid;
85
89 public $ref_customer;
90
94 public $date_delivery;
95
99 public $date_creation;
100
104 public $date_valid;
105
109 public $model_pdf;
110
111 public $commande_id;
112
116 public $lines = array();
117
121 public $user_author_id;
122
123
124 const STATUS_DRAFT = 0;
125 const STATUS_VALIDATED = 1;
126 const STATUS_CANCELED = -1;
127
128
134 public function __construct($db)
135 {
136 $this->db = $db;
137
138 // List of short language codes for status
139 $this->labelStatus[-1] = 'StatusDeliveryCanceled';
140 $this->labelStatus[0] = 'StatusDeliveryDraft';
141 $this->labelStatus[1] = 'StatusDeliveryValidated';
142 }
143
150 public function create($user)
151 {
152 global $conf;
153
154 dol_syslog("Delivery::create");
155
156 if (empty($this->model_pdf)) {
157 $this->model_pdf = getDolGlobalString('DELIVERY_ADDON_PDF');
158 }
159
160 $error = 0;
161
162 $now = dol_now();
163
164 /* Delivery note as draft On positionne en mode draft le bon de livraison */
165 $this->draft = 1;
166
167 $this->user = $user;
168
169 $this->db->begin();
170
171 $sql = "INSERT INTO ".MAIN_DB_PREFIX."delivery (";
172 $sql .= "ref";
173 $sql .= ", entity";
174 $sql .= ", fk_soc";
175 $sql .= ", ref_customer";
176 $sql .= ", date_creation";
177 $sql .= ", fk_user_author";
178 $sql .= ", date_delivery";
179 $sql .= ", fk_address";
180 $sql .= ", note_private";
181 $sql .= ", note_public";
182 $sql .= ", model_pdf";
183 $sql .= ", fk_incoterms, location_incoterms";
184 $sql .= ") VALUES (";
185 $sql .= "'(PROV)'";
186 $sql .= ", ".((int) $conf->entity);
187 $sql .= ", ".((int) $this->socid);
188 $sql .= ", '".$this->db->escape($this->ref_customer)."'";
189 $sql .= ", '".$this->db->idate($now)."'";
190 $sql .= ", ".((int) $user->id);
191 $sql .= ", ".($this->date_delivery ? "'".$this->db->idate($this->date_delivery)."'" : "null");
192 $sql .= ", ".($this->fk_delivery_address > 0 ? $this->fk_delivery_address : "null");
193 $sql .= ", ".(!empty($this->note_private) ? "'".$this->db->escape($this->note_private)."'" : "null");
194 $sql .= ", ".(!empty($this->note_public) ? "'".$this->db->escape($this->note_public)."'" : "null");
195 $sql .= ", ".(!empty($this->model_pdf) ? "'".$this->db->escape($this->model_pdf)."'" : "null");
196 $sql .= ", ".(int) $this->fk_incoterms;
197 $sql .= ", '".$this->db->escape($this->location_incoterms)."'";
198 $sql .= ")";
199
200 dol_syslog("Delivery::create", LOG_DEBUG);
201 $resql = $this->db->query($sql);
202 if ($resql) {
203 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."delivery");
204
205 $numref = "(PROV".$this->id.")";
206
207 $sql = "UPDATE ".MAIN_DB_PREFIX."delivery ";
208 $sql .= "SET ref = '".$this->db->escape($numref)."'";
209 $sql .= " WHERE rowid = ".((int) $this->id);
210
211 dol_syslog("Delivery::create", LOG_DEBUG);
212 $resql = $this->db->query($sql);
213 if ($resql) {
214 if (!getDolGlobalInt('MAIN_SUBMODULE_EXPEDITION')) {
215 $commande = new Commande($this->db);
216 $commande->id = $this->commande_id;
217 $commande->fetch_lines();
218 }
219
220
221 /*
222 * Inserting products into the database
223 */
224 $num = count($this->lines);
225 for ($i = 0; $i < $num; $i++) {
226 $origin_id = $this->lines[$i]->origin_line_id;
227 if (!$origin_id) {
228 $origin_id = $this->lines[$i]->commande_ligne_id; // For backward compatibility
229 }
230
231 if (!$this->create_line($origin_id, $this->lines[$i]->qty, $this->lines[$i]->fk_product, $this->lines[$i]->description, $this->lines[$i]->array_options)) {
232 $error++;
233 }
234 }
235
236 if (!$error && $this->id && $this->origin_id) {
237 $ret = $this->add_object_linked();
238 if (!$ret) {
239 $error++;
240 }
241
242 if (!getDolGlobalInt('MAIN_SUBMODULE_EXPEDITION')) {
243 $ret = $this->setStatut(2, $this->origin_id, $this->origin);
244 if (!$ret) {
245 $error++;
246 }
247 }
248 }
249
250 if (!$error) {
251 $this->db->commit();
252 return $this->id;
253 } else {
254 $error++;
255 $this->error = $this->db->lasterror()." - sql=".$this->db->lastqueryerror;
256 $this->db->rollback();
257 return -3;
258 }
259 } else {
260 $error++;
261 $this->error = $this->db->lasterror()." - sql=".$this->db->lastqueryerror;
262 $this->db->rollback();
263 return -2;
264 }
265 } else {
266 $error++;
267 $this->error = $this->db->lasterror()." - sql=".$this->db->lastqueryerror;
268 $this->db->rollback();
269 return -1;
270 }
271 }
272
273 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
284 public function create_line($origin_id, $qty, $fk_product, $description, $array_options = [])
285 {
286 // phpcs:enable
287 $error = 0;
288 $idprod = $fk_product;
289
290 $sql = "INSERT INTO ".MAIN_DB_PREFIX."deliverydet (fk_delivery, fk_origin_line,";
291 $sql .= " fk_product, description, qty)";
292 $sql .= " VALUES (".$this->id.",".((int) $origin_id).",";
293 $sql .= " ".($idprod > 0 ? ((int) $idprod) : "null").",";
294 $sql .= " ".($description ? "'".$this->db->escape($description)."'" : "null").",";
295 $sql .= (price2num($qty, 'MS')).")";
296
297 dol_syslog(get_class($this)."::create_line", LOG_DEBUG);
298 if (!$this->db->query($sql)) {
299 $error++;
300 }
301
302 $id = $this->db->last_insert_id(MAIN_DB_PREFIX."deliverydet");
303
304 if (is_array($array_options) && count($array_options) > 0) {
305 $line = new DeliveryLine($this->db);
306 $line->id = $id;
307 $line->array_options = $array_options;
308 $result = $line->insertExtraFields();
309 }
310
311 if (!$error) {
312 return 1;
313 }
314
315 return -1;
316 }
317
324 public function fetch($id)
325 {
326 $sql = "SELECT l.rowid, l.fk_soc, l.date_creation, l.date_valid, l.ref, l.ref_customer, l.fk_user_author,";
327 $sql .= " l.total_ht, l.fk_statut, l.fk_user_valid, l.note_private, l.note_public";
328 $sql .= ", l.date_delivery, l.fk_address, l.model_pdf";
329 $sql .= ", el.fk_source as origin_id, el.sourcetype as origin";
330 $sql .= ', l.fk_incoterms, l.location_incoterms';
331 $sql .= ", i.libelle as label_incoterms";
332 $sql .= " FROM ".MAIN_DB_PREFIX."delivery as l";
333 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."element_element as el ON el.fk_target = l.rowid AND el.targettype = '".$this->db->escape($this->element)."'";
334 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_incoterms as i ON l.fk_incoterms = i.rowid';
335 $sql .= " WHERE l.rowid = ".((int) $id);
336
337 dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
338 $result = $this->db->query($sql);
339 if ($result) {
340 if ($this->db->num_rows($result)) {
341 $obj = $this->db->fetch_object($result);
342
343 $this->id = $obj->rowid;
344 $this->date_delivery = $this->db->jdate($obj->date_delivery);
345 $this->date_creation = $this->db->jdate($obj->date_creation);
346 $this->date_valid = $this->db->jdate($obj->date_valid);
347 $this->ref = $obj->ref;
348 $this->ref_customer = $obj->ref_customer;
349 $this->socid = $obj->fk_soc;
350 $this->statut = $obj->fk_statut;
351 $this->status = $obj->fk_statut;
352 $this->user_author_id = $obj->fk_user_author;
353 $this->user_validation_id = $obj->fk_user_valid;
354 $this->fk_delivery_address = $obj->fk_address;
355 $this->note = $obj->note_private; //TODO deprecated
356 $this->note_private = $obj->note_private;
357 $this->note_public = $obj->note_public;
358 $this->model_pdf = $obj->model_pdf;
359 $this->origin = $obj->origin; // May be 'shipping'
360 $this->origin_id = $obj->origin_id; // May be id of shipping
361
362 //Incoterms
363 $this->fk_incoterms = $obj->fk_incoterms;
364 $this->location_incoterms = $obj->location_incoterms;
365 $this->label_incoterms = $obj->label_incoterms;
366 $this->db->free($result);
367
368 if ($this->statut == 0) {
369 $this->draft = 1;
370 }
371
372 // Retrieve all extrafields
373 // fetch optionals attributes and labels
374 $this->fetch_optionals();
375
376 // Load lines
377 $result = $this->fetch_lines();
378 if ($result < 0) {
379 return -3;
380 }
381
382 return 1;
383 } else {
384 $this->error = 'Delivery with id '.$id.' not found sql='.$sql;
385 dol_syslog(get_class($this).'::fetch Error '.$this->error, LOG_ERR);
386 return -2;
387 }
388 } else {
389 $this->error = $this->db->error();
390 return -1;
391 }
392 }
393
401 public function valid($user, $notrigger = 0)
402 {
403 global $conf;
404
405 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
406
407 dol_syslog(get_class($this)."::valid begin");
408
409 $this->db->begin();
410
411 $error = 0;
412
413 if ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('expedition', 'delivery', 'creer'))
414 || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('expedition', 'delivery_advance', 'validate'))) {
415 if (getDolGlobalString('DELIVERY_ADDON_NUMBER')) {
416 // Setting the command numbering module name
417 $modName = getDolGlobalString('DELIVERY_ADDON_NUMBER');
418
419 if (is_readable(DOL_DOCUMENT_ROOT.'/core/modules/delivery/'.$modName.'.php')) {
420 require_once DOL_DOCUMENT_ROOT.'/core/modules/delivery/'.$modName.'.php';
421
422 $now = dol_now();
423
424 // Retrieving the new reference
425 $objMod = new $modName($this->db);
426 $soc = new Societe($this->db);
427 $soc->fetch($this->socid);
428
429 if (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref)) { // empty should not happened, but when it occurs, the test save life
430 $numref = $objMod->getNextValue($soc, $this);
431 } else {
432 $numref = $this->ref;
433 }
434 $this->newref = dol_sanitizeFileName($numref);
435
436 // Test if is not already in valid status. If so, we stop to avoid decrementing the stock twice.
437 $sql = "SELECT ref";
438 $sql .= " FROM ".MAIN_DB_PREFIX."delivery";
439 $sql .= " WHERE ref = '".$this->db->escape($numref)."'";
440 $sql .= " AND fk_statut <> 0";
441 $sql .= " AND entity = ".((int) $conf->entity);
442
443 $resql = $this->db->query($sql);
444 if ($resql) {
445 $num = $this->db->num_rows($resql);
446 if ($num > 0) {
447 return 0;
448 }
449 }
450
451 $sql = "UPDATE ".MAIN_DB_PREFIX."delivery SET";
452 $sql .= " ref='".$this->db->escape($numref)."'";
453 $sql .= ", fk_statut = 1";
454 $sql .= ", date_valid = '".$this->db->idate($now)."'";
455 $sql .= ", fk_user_valid = ".$user->id;
456 $sql .= " WHERE rowid = ".((int) $this->id);
457 $sql .= " AND fk_statut = 0";
458
459 $resql = $this->db->query($sql);
460 if (!$resql) {
461 dol_print_error($this->db);
462 $this->error = $this->db->lasterror();
463 $error++;
464 }
465
466 if (!$error && !$notrigger) {
467 // Call trigger
468 $result = $this->call_trigger('DELIVERY_VALIDATE', $user);
469 if ($result < 0) {
470 $error++;
471 }
472 // End call triggers
473 }
474
475 if (!$error) {
476 $this->oldref = $this->ref;
477
478 // Rename directory if dir was a temporary ref
479 if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
480 // Now we rename also files into index
481 $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)."'";
482 $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'expedition/receipt/".$this->db->escape($this->ref)."' and entity = ".((int) $conf->entity);
483 $resql = $this->db->query($sql);
484 if (!$resql) {
485 $error++;
486 $this->error = $this->db->lasterror();
487 }
488 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'expedition/receipt/".$this->db->escape($this->newref)."'";
489 $sql .= " WHERE filepath = 'expedition/receipt/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
490 $resql = $this->db->query($sql);
491 if (!$resql) {
492 $error++;
493 $this->error = $this->db->lasterror();
494 }
495
496 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
497 $oldref = dol_sanitizeFileName($this->ref);
498 $newref = dol_sanitizeFileName($numref);
499 $dirsource = $conf->expedition->dir_output.'/receipt/'.$oldref;
500 $dirdest = $conf->expedition->dir_output.'/receipt/'.$newref;
501 if (!$error && file_exists($dirsource)) {
502 dol_syslog(get_class($this)."::valid rename dir ".$dirsource." into ".$dirdest);
503
504 if (@rename($dirsource, $dirdest)) {
505 dol_syslog("Rename ok");
506 // Rename docs starting with $oldref with $newref
507 $listoffiles = dol_dir_list($conf->expedition->dir_output.'/receipt/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
508 foreach ($listoffiles as $fileentry) {
509 $dirsource = $fileentry['name'];
510 $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
511 $dirsource = $fileentry['path'].'/'.$dirsource;
512 $dirdest = $fileentry['path'].'/'.$dirdest;
513 @rename($dirsource, $dirdest);
514 }
515 }
516 }
517 }
518
519 // Set new ref and current status
520 if (!$error) {
521 $this->ref = $numref;
522 $this->statut = 1;
523 }
524
525 dol_syslog(get_class($this)."::valid ok");
526 }
527
528 if (!$error) {
529 $this->db->commit();
530 return 1;
531 } else {
532 $this->db->rollback();
533 return -1;
534 }
535 }
536 }
537
538 return -1;
539 } else {
540 $this->error = "NotAllowed";
541 dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
542 return -1;
543 }
544 }
545
546 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
554 public function create_from_sending($user, $sending_id)
555 {
556 // phpcs:enable
557 global $conf;
558
559 $expedition = new Expedition($this->db);
560 $result = $expedition->fetch($sending_id);
561 if ($result <= 0) {
562 return $result;
563 }
564
565 $this->lines = array();
566
567 $num = count($expedition->lines);
568 for ($i = 0; $i < $num; $i++) {
569 $line = new DeliveryLine($this->db);
570 $line->origin_line_id = $expedition->lines[$i]->origin_line_id;
571 $line->label = $expedition->lines[$i]->label;
572 $line->description = $expedition->lines[$i]->description;
573 $line->qty = $expedition->lines[$i]->qty_shipped;
574 $line->fk_product = $expedition->lines[$i]->fk_product;
575 if (!getDolGlobalString('MAIN_EXTRAFIELDS_DISABLED') && is_array($expedition->lines[$i]->array_options) && count($expedition->lines[$i]->array_options) > 0) { // For avoid conflicts if trigger used
576 $line->array_options = $expedition->lines[$i]->array_options;
577 }
578 $this->lines[$i] = $line;
579 }
580
581 $this->origin = $expedition->element;
582 $this->origin_id = $expedition->id;
583 $this->note_private = $expedition->note_private;
584 $this->note_public = $expedition->note_public;
585 $this->fk_project = $expedition->fk_project;
586 $this->date_delivery = $expedition->date_delivery;
587 $this->fk_delivery_address = $expedition->fk_delivery_address;
588 $this->socid = $expedition->socid;
589 $this->ref_customer = $expedition->ref_customer;
590
591 //Incoterms
592 $this->fk_incoterms = $expedition->fk_incoterms;
593 $this->location_incoterms = $expedition->location_incoterms;
594
595 return $this->create($user);
596 }
597
598 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
606 public function update_line($id, $array_options = [])
607 {
608 // phpcs:enable
609 global $conf;
610 $error = 0;
611
612 if ($id > 0 && !$error && !getDolGlobalString('MAIN_EXTRAFIELDS_DISABLED') && is_array($array_options) && count($array_options) > 0) { // For avoid conflicts if trigger used
613 $line = new DeliveryLine($this->db);
614 $line->array_options = $array_options;
615 $line->id = $id;
616 $result = $line->insertExtraFields();
617
618 if ($result < 0) {
619 $this->errors[] = $line->error;
620 $error++;
621 }
622 }
623
624 if (!$error) {
625 return 1;
626 } else {
627 return -1;
628 }
629 }
630
631
640 public function addline($origin_id, $qty, $array_options = [])
641 {
642 global $conf;
643
644 $num = count($this->lines);
645 $line = new DeliveryLine($this->db);
646
647 $line->origin_id = $origin_id;
648 $line->qty = $qty;
649 if (!getDolGlobalString('MAIN_EXTRAFIELDS_DISABLED') && is_array($array_options) && count($array_options) > 0) { // For avoid conflicts if trigger used
650 $line->array_options = $array_options;
651 }
652 $this->lines[$num] = $line;
653 }
654
661 public function deleteLine($lineid)
662 {
663 if ($this->statut == 0) {
664 $sql = "DELETE FROM ".MAIN_DB_PREFIX."commandedet";
665 $sql .= " WHERE rowid = ".((int) $lineid);
666
667 if ($this->db->query($sql)) {
668 $this->update_price(1);
669
670 return 1;
671 } else {
672 return -1;
673 }
674 }
675
676 return 0;
677 }
678
685 public function delete($user = null)
686 {
687 global $conf, $langs;
688
689 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
690
691 $this->db->begin();
692
693 $error = 0;
694
695 $sql = "DELETE FROM ".MAIN_DB_PREFIX."deliverydet";
696 $sql .= " WHERE fk_delivery = ".((int) $this->id);
697 if ($this->db->query($sql)) {
698 // Delete linked object
699 $res = $this->deleteObjectLinked();
700 if ($res < 0) {
701 $error++;
702 }
703
704 if (!$error) {
705 $sql = "DELETE FROM ".MAIN_DB_PREFIX."delivery";
706 $sql .= " WHERE rowid = ".((int) $this->id);
707 if ($this->db->query($sql)) {
708 $this->db->commit();
709
710 // Deleting pdf folder's draft On efface le repertoire de pdf provisoire
711 $ref = dol_sanitizeFileName($this->ref);
712 if (!empty($conf->expedition->dir_output)) {
713 $dir = $conf->expedition->dir_output.'/receipt/'.$ref;
714 $file = $dir.'/'.$ref.'.pdf';
715 if (file_exists($file)) {
716 if (!dol_delete_file($file)) {
717 return 0;
718 }
719 }
720 if (file_exists($dir)) {
721 if (!dol_delete_dir($dir)) {
722 $this->error = $langs->trans("ErrorCanNotDeleteDir", $dir);
723 return 0;
724 }
725 }
726 }
727
728 // Call trigger
729 $result = $this->call_trigger('DELIVERY_DELETE', $user);
730 if ($result < 0) {
731 $this->db->rollback();
732 return -4;
733 }
734 // End call triggers
735
736 return 1;
737 } else {
738 $this->error = $this->db->lasterror()." - sql=$sql";
739 $this->db->rollback();
740 return -3;
741 }
742 } else {
743 $this->error = $this->db->lasterror()." - sql=$sql";
744 $this->db->rollback();
745 return -2;
746 }
747 } else {
748 $this->error = $this->db->lasterror()." - sql=$sql";
749 $this->db->rollback();
750 return -1;
751 }
752 }
753
760 public function getTooltipContentArray($params)
761 {
762 global $langs;
763
764 $langs->load('deliveries');
765
766 $datas = [];
767
768 $datas['picto'] = img_picto('', $this->picto).' <u>'.$langs->trans("ShowReceiving").'</u>:<br>';
769 $datas['picto'] .= '<b>'.$langs->trans("Status").'</b>: '.$this->ref;
770
771 return $datas;
772 }
773
781 public function getNomUrl($withpicto = 0, $save_lastsearch_value = -1)
782 {
783 global $langs, $hookmanager;
784
785 $result = '';
786
787 $params = [
788 'id' => $this->id,
789 'objecttype' => $this->element,
790 ];
791 $classfortooltip = 'classfortooltip';
792 $dataparams = '';
793 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
794 $classfortooltip = 'classforajaxtooltip';
795 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
796 $label = '';
797 } else {
798 $label = implode($this->getTooltipContentArray($params));
799 }
800
801 $url = DOL_URL_ROOT.'/delivery/card.php?id='.$this->id;
802
803 //if ($option !== 'nolink')
804 //{
805 // Add param to save lastsearch_values or not
806 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
807 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
808 $add_save_lastsearch_values = 1;
809 }
810 if ($add_save_lastsearch_values) {
811 $url .= '&save_lastsearch_values=1';
812 }
813 //}
814
815 $linkstart = '<a href="'.$url.'"';
816 $linkstart .= ($label ? ' title="'.dol_escape_htmltag($label, 1).'"' : ' title="tocomplete"');
817 $linkstart .= $dataparams.' class="'.$classfortooltip.'">';
818 $linkend = '</a>';
819
820 if ($withpicto) {
821 $result .= ($linkstart.img_object($label, $this->picto, $dataparams.' class="'.$classfortooltip.'"').$linkend);
822 }
823 if ($withpicto && $withpicto != 2) {
824 $result .= ' ';
825 }
826 $result .= $linkstart.$this->ref.$linkend;
827
828 global $action;
829 $hookmanager->initHooks(array($this->element . 'dao'));
830 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
831 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
832 if ($reshook > 0) {
833 $result = $hookmanager->resPrint;
834 } else {
835 $result .= $hookmanager->resPrint;
836 }
837 return $result;
838 }
839
840 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
846 public function fetch_lines()
847 {
848 // phpcs:enable
849 $this->lines = array();
850
851 $sql = "SELECT ld.rowid, ld.fk_product, ld.description, ld.subprice, ld.total_ht, ld.qty as qty_shipped, ld.fk_origin_line, ";
852 $sql .= " cd.qty as qty_asked, cd.label as custom_label, cd.fk_unit,";
853 $sql .= " p.ref as product_ref, p.fk_product_type as fk_product_type, p.label as product_label, p.description as product_desc,";
854 $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";
855 $sql .= " FROM ".MAIN_DB_PREFIX."commandedet as cd, ".MAIN_DB_PREFIX."deliverydet as ld";
856 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p on p.rowid = ld.fk_product";
857 $sql .= " WHERE ld.fk_origin_line = cd.rowid";
858 $sql .= " AND ld.fk_delivery = ".((int) $this->id);
859
860 dol_syslog(get_class($this)."::fetch_lines", LOG_DEBUG);
861 $resql = $this->db->query($sql);
862 if ($resql) {
863 $num = $this->db->num_rows($resql);
864 $i = 0;
865 while ($i < $num) {
866 $obj = $this->db->fetch_object($resql);
867
868 $line = new DeliveryLine($this->db);
869
870 $line->id = $obj->rowid;
871 $line->label = $obj->custom_label;
872 $line->description = $obj->description;
873 $line->fk_product = $obj->fk_product;
874 $line->qty_asked = $obj->qty_asked;
875 $line->qty_shipped = $obj->qty_shipped;
876
877 $line->product_label = $obj->product_label; // Product label
878 $line->product_ref = $obj->product_ref; // Product ref
879 $line->product_desc = $obj->product_desc; // Product description
880 $line->product_type = $obj->fk_product_type;
881
882 $line->fk_origin_line = $obj->fk_origin_line;
883
884 $line->price = $obj->subprice;
885 $line->total_ht = $obj->total_ht;
886
887 // units
888 $line->weight = $obj->weight;
889 $line->weight_units = $obj->weight_units;
890 $line->width = $obj->width;
891 $line->width_units = $obj->width_units;
892 $line->height = $obj->height;
893 $line->height_units = $obj->height_units;
894 $line->length = $obj->length;
895 $line->length_units = $obj->length_units;
896 $line->surface = $obj->surface;
897 $line->surface_units = $obj->surface_units;
898 $line->volume = $obj->volume;
899 $line->volume_units = $obj->volume_units;
900
901 $line->fk_unit = $obj->fk_unit;
902 $line->fetch_optionals();
903
904 $this->lines[$i] = $line;
905
906 $i++;
907 }
908 $this->db->free($resql);
909
910 return 1;
911 } else {
912 return -1;
913 }
914 }
915
916
923 public function getLibStatut($mode = 0)
924 {
925 return $this->LibStatut($this->statut, $mode);
926 }
927
928 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
936 public function LibStatut($status, $mode)
937 {
938 // phpcs:enable
939 global $langs;
940
941 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
942 global $langs;
943 //$langs->load("mymodule");
944 $this->labelStatus[-1] = $langs->transnoentitiesnoconv('StatusDeliveryCanceled');
945 $this->labelStatus[0] = $langs->transnoentitiesnoconv('StatusDeliveryDraft');
946 $this->labelStatus[1] = $langs->transnoentitiesnoconv('StatusDeliveryValidated');
947 $this->labelStatusShort[-1] = $langs->transnoentitiesnoconv('StatusDeliveryCanceled');
948 $this->labelStatusShort[0] = $langs->transnoentitiesnoconv('StatusDeliveryDraft');
949 $this->labelStatusShort[1] = $langs->transnoentitiesnoconv('StatusDeliveryValidated');
950 }
951
952 $statusType = 'status0';
953 if ($status == -1) {
954 $statusType = 'status5';
955 }
956 if ($status == 1) {
957 $statusType = 'status4';
958 }
959
960 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
961 }
962
963
971 public function initAsSpecimen()
972 {
973 $now = dol_now();
974
975 // Load array of products prodids
976 $num_prods = 0;
977 $prodids = array();
978 $sql = "SELECT rowid";
979 $sql .= " FROM ".MAIN_DB_PREFIX."product";
980 $sql .= " WHERE entity IN (".getEntity('product').")";
981 $sql .= " AND tosell = 1";
982 $sql .= $this->db->plimit(100);
983
984 $resql = $this->db->query($sql);
985 if ($resql) {
986 $num_prods = $this->db->num_rows($resql);
987 $i = 0;
988 while ($i < $num_prods) {
989 $i++;
990 $row = $this->db->fetch_row($resql);
991 $prodids[$i] = $row[0];
992 }
993 }
994
995 // Initialise parameters
996 $this->id = 0;
997 $this->ref = 'SPECIMEN';
998 $this->specimen = 1;
999 $this->socid = 1;
1000 $this->date_delivery = $now;
1001 $this->note_public = 'Public note';
1002 $this->note_private = 'Private note';
1003
1004 $i = 0;
1005 $line = new DeliveryLine($this->db);
1006 $line->fk_product = reset($prodids);
1007 $line->qty_asked = 10;
1008 $line->qty_shipped = 9;
1009 $line->ref = 'REFPROD';
1010 $line->label = 'Specimen';
1011 $line->description = 'Description';
1012 $line->price = 100;
1013 $line->total_ht = 100;
1014
1015 $this->lines[$i] = $line;
1016
1017 return 1;
1018 }
1019
1026 public function getRemainingDelivered()
1027 {
1028 // Get the linked object
1029 $this->fetchObjectLinked('', '', $this->id, $this->element);
1030 //var_dump($this->linkedObjectsIds);
1031 // Get the product ref and qty in source
1032 $sqlSourceLine = "SELECT st.rowid, st.description, st.qty";
1033 $sqlSourceLine .= ", p.ref, p.label";
1034 $sqlSourceLine .= " FROM ".MAIN_DB_PREFIX.$this->linkedObjectsIds[0]['type']."det as st";
1035 $sqlSourceLine .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON st.fk_product = p.rowid";
1036 $sqlSourceLine .= " WHERE fk_".$this->linked_objects[0]['type']." = ".((int) $this->linked_objects[0]['linkid']);
1037
1038 $resultSourceLine = $this->db->query($sqlSourceLine);
1039 if ($resultSourceLine) {
1040 $num_lines = $this->db->num_rows($resultSourceLine);
1041 $i = 0;
1042 $array = array();
1043 while ($i < $num_lines) {
1044 $objSourceLine = $this->db->fetch_object($resultSourceLine);
1045
1046 // Get lines of sources already delivered
1047 $sql = "SELECT ld.fk_origin_line, sum(ld.qty) as qty";
1048 $sql .= " FROM ".MAIN_DB_PREFIX."deliverydet as ld, ".MAIN_DB_PREFIX."delivery as l,";
1049 $sql .= " ".MAIN_DB_PREFIX.$this->linked_objects[0]['type']." as c";
1050 $sql .= ", ".MAIN_DB_PREFIX.$this->linked_objects[0]['type']."det as cd";
1051 $sql .= " WHERE ld.fk_delivery = l.rowid";
1052 $sql .= " AND ld.fk_origin_line = cd.rowid";
1053 $sql .= " AND cd.fk_".$this->linked_objects[0]['type']." = c.rowid";
1054 $sql .= " AND cd.fk_".$this->linked_objects[0]['type']." = ".((int) $this->linked_objects[0]['linkid']);
1055 $sql .= " AND ld.fk_origin_line = ".((int) $objSourceLine->rowid);
1056 $sql .= " GROUP BY ld.fk_origin_line";
1057
1058 $result = $this->db->query($sql);
1059 $row = $this->db->fetch_row($result);
1060
1061 if ($objSourceLine->qty - $row[1] > 0) {
1062 if ($row[0] == $objSourceLine->rowid) {
1063 $array[$i]['qty'] = $objSourceLine->qty - $row[1];
1064 } else {
1065 $array[$i]['qty'] = $objSourceLine->qty;
1066 }
1067
1068 $array[$i]['ref'] = $objSourceLine->ref;
1069 $array[$i]['label'] = $objSourceLine->label ? $objSourceLine->label : $objSourceLine->description;
1070 } elseif ($objSourceLine->qty - $row[1] < 0) {
1071 $array[$i]['qty'] = $objSourceLine->qty - $row[1]." Erreur livraison !";
1072 $array[$i]['ref'] = $objSourceLine->ref;
1073 $array[$i]['label'] = $objSourceLine->label ? $objSourceLine->label : $objSourceLine->description;
1074 }
1075
1076 $i++;
1077 }
1078 return $array;
1079 } else {
1080 $this->error = $this->db->error()." - sql=$sqlSourceLine";
1081 return -1;
1082 }
1083 }
1084
1092 public function setDeliveryDate($user, $delivery_date)
1093 {
1094 if ($user->hasRight('expedition', 'creer')) {
1095 $sql = "UPDATE ".MAIN_DB_PREFIX."delivery";
1096 $sql .= " SET date_delivery = ".($delivery_date ? "'".$this->db->idate($delivery_date)."'" : 'null');
1097 $sql .= " WHERE rowid = ".((int) $this->id);
1098
1099 dol_syslog(get_class($this)."::setDeliveryDate", LOG_DEBUG);
1100 $resql = $this->db->query($sql);
1101 if ($resql) {
1102 $this->date_delivery = $delivery_date;
1103 return 1;
1104 } else {
1105 $this->error = $this->db->error();
1106 return -1;
1107 }
1108 } else {
1109 return -2;
1110 }
1111 }
1112
1123 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
1124 {
1125 global $conf, $langs;
1126
1127 $langs->load("deliveries");
1128 $outputlangs->load("products");
1129
1130 if (!dol_strlen($modele)) {
1131 $modele = 'typhon';
1132
1133 if ($this->model_pdf) {
1134 $modele = $this->model_pdf;
1135 } elseif (getDolGlobalString('DELIVERY_ADDON_PDF')) {
1136 $modele = getDolGlobalString('DELIVERY_ADDON_PDF');
1137 }
1138 }
1139
1140 $modelpath = "core/modules/delivery/doc/";
1141
1142 return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref);
1143 }
1144
1153 public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
1154 {
1155 $tables = array(
1156 'delivery'
1157 );
1158
1159 return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables);
1160 }
1161
1170 public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
1171 {
1172 $tables = array(
1173 'deliverydet'
1174 );
1175
1176 return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables);
1177 }
1178}
1179
1180
1185{
1189 public $db;
1190
1194 public $element = 'deliverydet';
1195
1199 public $table_element = 'deliverydet';
1200
1204 public $label;
1205
1209 public $description;
1210
1215 public $ref;
1220 public $libelle;
1221
1222 // From llx_expeditiondet
1226 public $qty;
1227
1231 public $qty_asked;
1232
1236 public $qty_shipped;
1237
1238 public $fk_product;
1239 public $product_desc;
1240 public $product_type;
1241 public $product_ref;
1242 public $product_label;
1243
1244 public $price;
1245
1246 public $fk_origin_line;
1247 public $origin_id;
1248
1252 public $origin_line_id;
1253
1259 public $commande_ligne_id;
1260
1261
1267 public function __construct($db)
1268 {
1269 $this->db = $db;
1270 }
1271}
print $langs trans("AuditedSecurityEvents").'</strong >< span class="opacitymedium"></span >< br > status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition security.php:636
$object ref
Definition info.php:79
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...
update_price($exclspec=0, $roundingadjust='auto', $nodatabaseupdate=0, $seller=null)
Update total_ht, total_ttc, total_vat, total_localtax1, total_localtax2 for an object (sum of lines).
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=0, $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.
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 commonReplaceThirdparty(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
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.
create_line($origin_id, $qty, $fk_product, $description, $array_options=[])
Create a line.
valid($user, $notrigger=0)
Validate object and update stock if option enabled.
__construct($db)
Constructor.
static replaceProduct(DoliDB $db, $origin_id, $dest_id)
Function used to replace a product id with another one.
deleteLine($lineid)
Delete line.
setDeliveryDate($user, $delivery_date)
Set the planned delivery date.
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
Create object on disk.
update_line($id, $array_options=[])
Update a livraison line (only extrafields)
addline($origin_id, $qty, $array_options=[])
Add line.
fetch($id)
Load a delivery receipt.
create($user)
Create delivery receipt in database.
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.
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.
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after 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.
dol_delete_dir($dir, $nophperrors=0)
Remove a directory (not recursive, so content must be empty).
dol_dir_list($utf8_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:63
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
$conf db user
Active Directory does not allow anonymous connections.
Definition repair.php:143
publicphonebutton2 phonegreen basiclayout basiclayout TotalHT VATCode TotalVAT TotalLT1 TotalLT2 TotalTTC TotalHT clearboth nowraponall TAKEPOS_SHOW_SUBPRICE right right right takeposterminal SELECT e e e e e statut
Definition invoice.php:1991