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
31require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
32require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
33require_once DOL_DOCUMENT_ROOT.'/core/class/commonincoterm.class.php';
34require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
35if (isModEnabled("propal")) {
36 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
37}
38if (isModEnabled('commande')) {
39 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
40}
41
42
47{
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).
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.
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...)
print $langs trans("Ref").' m m m statut
Definition index.php:152
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($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)
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
$conf db user
Definition repair.php:124