dolibarr 25.0.0-alpha
fichinter.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2002-2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2014 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2011-2020 Juanjo Menent <jmenent@2byte.es>
6 * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
7 * Copyright (C) 2015-2026 Charlene Benke <charlene@patas-monkey.com>
8 * Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com>
9 * Copyright (C) 2018-2026 Frédéric France <frederic.france@free.fr>
10 * Copyright (C) 2023-2026 William Mead <william@m34d.com>
11 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program. If not, see <https://www.gnu.org/licenses/>.
25 */
26
32require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
33require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinterligne.class.php';
34require_once DOL_DOCUMENT_ROOT.'/core/class/commonsignedobject.class.php';
35require_once DOL_DOCUMENT_ROOT.'/subtotals/class/commonsubtotal.class.php';
36
37
44{
45 use CommonSignedObject;
46 use CommonSubtotal;
47
52 public $TRIGGER_PREFIX = 'FICHINTER';
53
54 public $fields = array(
55 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 10),
56 'fk_soc' => array('type' => 'integer:Societe:societe/class/societe.class.php', 'label' => 'ThirdParty', 'enabled' => 'isModEnabled("societe")', 'visible' => -1, 'notnull' => 1, 'position' => 15),
57 'fk_projet' => array('type' => 'integer:Project:projet/class/project.class.php:1:(fk_statut:=:1)', 'label' => 'Project', 'enabled' => 'isModEnabled("project")', 'visible' => -1, 'position' => 20),
58 'fk_contrat' => array('type' => 'integer:Contrat:contrat/class/contrat.class.php', 'label' => 'Contract', 'enabled' => 'isModEnabled("contract")', 'visible' => -1, 'position' => 25),
59 'ref' => array('type' => 'varchar(30)', 'label' => 'Ref', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'showoncombobox' => 1, 'position' => 30),
60 'ref_ext' => array('type' => 'varchar(255)', 'label' => 'RefExt', 'enabled' => 1, 'visible' => 0, 'position' => 35),
61 'ref_client' => array('type' => 'varchar(255)', 'label' => 'RefCustomer', 'enabled' => 1, 'visible' => -1, 'position' => 36),
62 'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => '1', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 40, 'index' => 1),
63 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 45),
64 'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -1, 'position' => 50),
65 'date_valid' => array('type' => 'datetime', 'label' => 'DateValidation', 'enabled' => 1, 'visible' => -1, 'position' => 55),
66 'datei' => array('type' => 'date', 'label' => 'Datei', 'enabled' => 1, 'visible' => -1, 'position' => 60),
67 'fk_user_author' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserAuthor', 'enabled' => 1, 'visible' => -1, 'position' => 65),
68 'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'position' => 70),
69 'fk_user_valid' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserValidation', 'enabled' => 1, 'visible' => -1, 'position' => 75),
70 'dateo' => array('type' => 'date', 'label' => 'Dateo', 'enabled' => 1, 'visible' => -1, 'position' => 85),
71 'datee' => array('type' => 'date', 'label' => 'Datee', 'enabled' => 1, 'visible' => -1, 'position' => 90),
72 'datet' => array('type' => 'date', 'label' => 'Datet', 'enabled' => 1, 'visible' => -1, 'position' => 95),
73 'duree' => array('type' => 'integer', 'label' => 'Duree', 'enabled' => 1, 'visible' => -1, 'position' => 100),
74 'signed_status' => array('type' => 'smallint(6)', 'label' => 'SignedStatus', 'enabled' => 1, 'visible' => -1, 'position' => 101, 'arrayofkeyval' => array(0 => 'NoSignature', 1 => 'SignedSender', 2 => 'SignedReceiver', 3 => 'SignedReceiverOnline', 9 => 'SignedAll')),
75 'description' => array('type' => 'html', 'label' => 'Description', 'enabled' => 1, 'visible' => -1, 'position' => 105, 'showoncombobox' => 2),
76 'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 110),
77 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 115),
78 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'PDFTemplate', 'enabled' => 1, 'visible' => 0, 'position' => 120),
79 'last_main_doc' => array('type' => 'varchar(255)', 'label' => 'LastMainDoc', 'enabled' => 1, 'visible' => -1, 'position' => 125),
80 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'position' => 130),
81 'extraparams' => array('type' => 'varchar(255)', 'label' => 'Extraparams', 'enabled' => 1, 'visible' => -1, 'position' => 135),
82 'fk_statut' => array('type' => 'integer', 'label' => 'Status', 'enabled' => 1, 'visible' => -1, 'position' => 500),
83 );
84
88 public $element = 'fichinter';
89
93 public $fk_element = 'fk_fichinter';
94
98 public $table_element = 'fichinter';
99
103 public $table_element_line = 'fichinterdet';
104
108 public $class_element_line = 'FichinterLigne';
109
113 public $picto = 'intervention';
114
118 protected $table_ref_field = 'ref';
119
123 public $socid;
124
128 public $author;
129
133 public $datec;
134
138 public $datev;
142 public $dateo;
146 public $datee;
147
151 public $datet;
152
158 public $datem;
159
163 public $duration;
164
169 public $statut = 0; // 0=draft, 1=validated, 2=invoiced, 3=Terminate
170
174 public $status = 0; // 0=draft, 1=validated, 2=invoiced, 3=Terminate
175
179 public $description;
180
184 public $fk_contrat = 0;
185
189 public $fk_project;
190
195 public $ref_client;
196
200 public $extraparams = array();
201
205 public $lines = array();
206
210 const STATUS_DRAFT = 0;
211
216
220 const STATUS_BILLED = 2;
221
225 const STATUS_CLOSED = 3;
226
231
237 public $date_delivery;
238
243 public $delivery_date_receipt;
244
249 public $user_author_id;
250
251
257 public function __construct($db)
258 {
259 $this->db = $db;
260 }
261
267 public function loadStateBoard()
268 {
269 global $user;
270
271 $this->nb = array();
272 $clause = "WHERE";
273
274 $sql = "SELECT count(fi.rowid) as nb";
275 $sql .= " FROM ".MAIN_DB_PREFIX."fichinter as fi";
276 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON fi.fk_soc = s.rowid";
277 if (!$user->hasRight('societe', 'client', 'voir')) {
278 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON s.rowid = sc.fk_soc";
279 $sql .= " WHERE sc.fk_user = ".((int) $user->id);
280 $clause = "AND";
281 }
282 $sql .= " ".$clause." fi.entity IN (".getEntity('intervention').")";
283
284 $resql = $this->db->query($sql);
285 if ($resql) {
286 while ($obj = $this->db->fetch_object($resql)) {
287 $this->nb["interventions"] = $obj->nb;
288 }
289 $this->db->free($resql);
290 return 1;
291 } else {
292 dol_print_error($this->db);
293 $this->error = $this->db->error();
294 return -1;
295 }
296 }
297
305 public function create($user, $notrigger = 0)
306 {
307 $error = 0;
308
309 dol_syslog(get_class($this)."::create ref=".$this->ref);
310
311 // Check parameters
312 if (!empty($this->ref)) { // We check that ref is not already used
313 $result = self::isExistingObject($this->element, 0, $this->ref); // Check ref is not yet used
314 if ($result > 0) {
315 $this->error = 'ErrorRefAlreadyExists';
316 dol_syslog(get_class($this)."::create ".$this->error, LOG_WARNING);
317 $this->db->rollback();
318 return -1;
319 }
320 }
321 if (!is_numeric($this->duration)) {
322 $this->duration = 0;
323 }
324 if (!empty($this->ref_client)) {
325 $this->ref_client = trim($this->ref_client);
326 }
327
328 if ($this->socid <= 0) {
329 $this->error = 'ErrorFicheinterCompanyDoesNotExist';
330 dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
331 return -1;
332 }
333 $this->entity = setEntity($this);
334
335 $soc = new Societe($this->db);
336 $result = $soc->fetch($this->socid);
337
338 $now = dol_now();
339
340 $this->db->begin();
341
342 $sql = "INSERT INTO ".MAIN_DB_PREFIX."fichinter (";
343 $sql .= "fk_soc";
344 $sql .= ", datec";
345 $sql .= ", ref";
346 $sql .= ", ref_client";
347 $sql .= ", entity";
348 $sql .= ", fk_user_author";
349 $sql .= ", fk_user_modif";
350 $sql .= ", description";
351 $sql .= ", model_pdf";
352 $sql .= ", fk_projet";
353 $sql .= ", fk_contrat";
354 $sql .= ", fk_statut";
355 $sql .= ", signed_status";
356 $sql .= ", note_private";
357 $sql .= ", note_public";
358 $sql .= ") ";
359 $sql .= " VALUES (";
360 $sql .= ((int) $this->socid);
361 $sql .= ", '".$this->db->idate($now)."'";
362 $sql .= ", '".$this->db->escape($this->ref)."'";
363 $sql .= ", ".($this->ref_client ? "'".$this->db->escape($this->ref_client)."'" : "null");
364 $sql .= ", ".((int) $this->entity);
365 $sql .= ", ".((int) $user->id);
366 $sql .= ", ".((int) $user->id);
367 $sql .= ", ".($this->description ? "'".$this->db->escape($this->description)."'" : "null");
368 $sql .= ", '".$this->db->escape($this->model_pdf)."'";
369 $sql .= ", ".((int) $this->fk_project > 0 ? ((int) $this->fk_project) : 0);
370 $sql .= ", ".((int) $this->fk_contrat > 0 ? ((int) $this->fk_contrat) : 0);
371 $sql .= ", ".((int) $this->status);
372 $sql .= ", ".((int) $this->signed_status);
373 $sql .= ", ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "null");
374 $sql .= ", ".($this->note_public ? "'".$this->db->escape($this->note_public)."'" : "null");
375 $sql .= ")";
376
377 dol_syslog(get_class($this)."::create", LOG_DEBUG);
378 $result = $this->db->query($sql);
379 if ($result) {
380 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."fichinter");
381
382 if ($this->id) {
383 $this->ref = '(PROV'.$this->id.')';
384 $sql = 'UPDATE '.MAIN_DB_PREFIX."fichinter SET ref='".$this->db->escape($this->ref)."' WHERE rowid=".((int) $this->id);
385
386 dol_syslog(get_class($this)."::create", LOG_DEBUG);
387 $resql = $this->db->query($sql);
388 if (!$resql) {
389 $error++;
390 }
391 }
392
393 if (!$error) {
394 $result = $this->insertExtraFields();
395 if ($result < 0) {
396 $error++;
397 }
398 }
399
400 // Add linked object
401 if (!$error && $this->origin && $this->origin_id) {
402 $ret = $this->add_object_linked();
403 if (!$ret) {
404 dol_print_error($this->db);
405 }
406 }
407
408
409 if (!$error && !$notrigger) {
410 // Call trigger
411 $result = $this->call_trigger('FICHINTER_CREATE', $user);
412 if ($result < 0) {
413 $error++;
414 }
415 // End call triggers
416 }
417
418 if (!$error) {
419 $this->db->commit();
420 return $this->id;
421 } else {
422 $this->db->rollback();
423 $this->error = implode(',', $this->errors);
424 dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
425 return -1;
426 }
427 } else {
428 $this->error = $this->db->error();
429 $this->db->rollback();
430 return -1;
431 }
432 }
433
441 public function update($user, $notrigger = 0)
442 {
443 global $conf;
444
445 if (!is_numeric($this->duration)) {
446 $this->duration = 0;
447 }
448 if (!dol_strlen((string) $this->fk_project)) {
449 $this->fk_project = 0;
450 }
451 if (!empty($this->ref_client)) {
452 $this->ref_client = trim($this->ref_client);
453 }
454
455 $error = 0;
456
457 $this->db->begin();
458
459 $sql = "UPDATE ".MAIN_DB_PREFIX."fichinter SET ";
460 $sql .= "description = '".$this->db->escape($this->description)."'";
461 $sql .= ", duree = ".((int) $this->duration);
462 $sql .= ", ref_client = ".($this->ref_client ? "'".$this->db->escape($this->ref_client)."'" : "null");
463 if ((int) $this->fk_project > 0) {
464 $sql .= ", fk_projet = ".((int) $this->fk_project);
465 }
466 if (isset($this->datec)) {
467 $sql .= ", datec = ".($this->datec ? "'".$this->db->idate($this->datec)."'" : "null");
468 }
469 if (isset($this->datev)) {
470 $sql .= ", date_valid = ".($this->datev ? "'".$this->db->idate($this->datev)."'" : "null");
471 }
472 if (isset($this->datet)) {
473 $sql .= ", datet = ".($this->datet ? "'".$this->db->idate($this->datet)."'" : "null");
474 }
475 $sql .= ", note_private = ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "null");
476 $sql .= ", note_public = ".($this->note_public ? "'".$this->db->escape($this->note_public)."'" : "null");
477 $sql .= ", fk_user_modif = ".((int) $user->id);
478 $sql .= " WHERE rowid = ".((int) $this->id);
479
480 dol_syslog(get_class($this)."::update", LOG_DEBUG);
481 if ($this->db->query($sql)) {
482 $result = $this->insertExtraFields();
483 if ($result < 0) {
484 $error++;
485 }
486
487 if (!$error && !$notrigger) {
488 // Call trigger
489 $result = $this->call_trigger('FICHINTER_MODIFY', $user);
490 if ($result < 0) {
491 $error++;
492 $this->db->rollback();
493 return -1;
494 }
495 // End call triggers
496 }
497
498 $this->db->commit();
499 return 1;
500 } else {
501 $this->error = $this->db->error();
502 $this->db->rollback();
503 return -1;
504 }
505 }
506
515 public function fetch($rowid, $ref = '', $ref_ext = '')
516 {
517 $sql = "SELECT f.rowid, f.ref, f.ref_client, f.description, f.fk_soc, f.fk_statut as status, f.signed_status,";
518 $sql .= " f.datec, f.dateo, f.datee, f.datet,";
519 $sql .= " f.date_valid as datev,";
520 $sql .= " f.tms as datem,";
521 $sql .= " f.fk_user_author, f.fk_user_modif,";
522 $sql .= " f.duree, f.fk_projet as fk_project, f.note_public, f.note_private, f.model_pdf, f.last_main_doc, f.extraparams, fk_contrat, f.entity as entity";
523 $sql .= " FROM ".MAIN_DB_PREFIX."fichinter as f";
524 $sql .= " WHERE f.entity IN (".getEntity('intervention').")";
525 if ($ref) {
526 $sql .= " AND f.ref = '".$this->db->escape($ref)."'";
527 } elseif ($ref_ext) {
528 $sql .= " AND f.ref_ext = '".$this->db->escape($ref_ext)."'";
529 } else {
530 $sql .= " AND f.rowid = ".((int) $rowid);
531 }
532
533 $resql = $this->db->query($sql);
534 if ($resql) {
535 if ($this->db->num_rows($resql)) {
536 $obj = $this->db->fetch_object($resql);
537
538 $this->id = $obj->rowid;
539 $this->ref = $obj->ref;
540 $this->ref_client = $obj->ref_client;
541 $this->description = $obj->description;
542 $this->socid = $obj->fk_soc;
543 $this->status = $obj->status;
544 $this->statut = $obj->status; // deprecated
545 $this->signed_status = $obj->signed_status;
546 $this->duration = $obj->duree;
547 $this->datec = $this->db->jdate($obj->datec);
548 $this->dateo = $this->db->jdate($obj->dateo);
549 $this->datee = $this->db->jdate($obj->datee);
550 $this->datet = $this->db->jdate($obj->datet);
551 $this->datev = $this->db->jdate($obj->datev);
552 $this->datem = $this->db->jdate($obj->datem);
553 $this->fk_project = $obj->fk_project;
554 $this->note_public = $obj->note_public;
555 $this->note_private = $obj->note_private;
556 $this->model_pdf = $obj->model_pdf;
557 $this->fk_contrat = $obj->fk_contrat;
558 $this->entity = $obj->entity;
559
560 $this->user_author_id = $this->user_creation_id = $obj->fk_user_author;
561 $this->user_modification_id = $obj->fk_user_modif;
562
563 $this->extraparams = is_null($obj->extraparams) ? [] : (array) json_decode($obj->extraparams, true);
564
565 $this->last_main_doc = $obj->last_main_doc;
566
567 // Retrieve extrafields
568 $this->fetch_optionals();
569
570 /*
571 * Lines
572 */
573 $result = $this->fetch_lines();
574 if ($result < 0) {
575 return -3;
576 }
577 $this->db->free($resql);
578 return 1;
579 }
580
581 return 0;
582 } else {
583 $this->error = $this->db->lasterror();
584 return -1;
585 }
586 }
587
594 public function setDraft($user)
595 {
596 $error = 0;
597
598 // Protection
599 if ($this->status <= self::STATUS_DRAFT) {
600 return 0;
601 }
602
603 dol_syslog(get_class($this)."::setDraft", LOG_DEBUG);
604
605 $this->oldcopy = dol_clone($this, 2);
606
607 $this->db->begin();
608
609 $sql = "UPDATE ".MAIN_DB_PREFIX."fichinter";
610 $sql .= " SET fk_statut = ".self::STATUS_DRAFT;
611 $sql .= " WHERE rowid = ".((int) $this->id);
612
613 $resql = $this->db->query($sql);
614 if ($resql) {
615 // Call trigger
616 $result = $this->call_trigger('FICHINTER_UNVALIDATE', $user);
617 if ($result < 0) {
618 $error++;
619 }
620
621 if (!$error) {
622 $this->status = self::STATUS_DRAFT;
623 $this->statut = self::STATUS_DRAFT; // deprecated
624 $this->db->commit();
625 return 1;
626 } else {
627 $this->db->rollback();
628 return -1;
629 }
630 } else {
631 $this->db->rollback();
632 $this->error = $this->db->lasterror();
633 return -1;
634 }
635 }
636
644 public function setValid($user, $notrigger = 0)
645 {
646 global $conf;
647 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
648
649 $error = 0;
650
651 if ($this->status != self::STATUS_VALIDATED) {
652 $this->db->begin();
653
654 $now = dol_now();
655
656 // Define new ref
657 if ((preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
658 $num = $this->getNextNumRef($this->thirdparty);
659 } else {
660 $num = (string) $this->ref;
661 }
662 $this->newref = dol_sanitizeFileName($num);
663
664 $sql = "UPDATE ".MAIN_DB_PREFIX."fichinter";
665 $sql .= " SET fk_statut = 1";
666 $sql .= ", ref = '".$this->db->escape($num)."'";
667 $sql .= ", date_valid = '".$this->db->idate($now)."'";
668 $sql .= ", fk_user_valid = ".($user->id > 0 ? (int) $user->id : "null");
669 $sql .= " WHERE rowid = ".((int) $this->id);
670 $sql .= " AND entity IN (".getEntity('intervention').")";
671
672 $sql .= " AND fk_statut = 0";
673
674 dol_syslog(get_class($this)."::setValid", LOG_DEBUG);
675 $resql = $this->db->query($sql);
676 if (!$resql) {
677 dol_print_error($this->db);
678 $error++;
679 }
680
681 if (!$error && !$notrigger) {
682 // Call trigger
683 $result = $this->call_trigger('FICHINTER_VALIDATE', $user);
684 if ($result < 0) {
685 $error++;
686 }
687 // End call triggers
688 }
689
690 if (!$error) {
691 $this->oldref = $this->ref;
692
693 // Rename directory if dir was a temporary ref
694 if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
695 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
696
697 // Now we rename also files into index
698 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'ficheinter/".$this->db->escape($this->newref)."'";
699 $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'ficheinter/".$this->db->escape($this->ref)."' and entity = ".((int) $this->entity);
700 $resql = $this->db->query($sql);
701 if (!$resql) {
702 $error++;
703 $this->error = $this->db->lasterror();
704 }
705 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'ficheinter/".$this->db->escape($this->newref)."'";
706 $sql .= " WHERE filepath = 'ficheinter/".$this->db->escape($this->ref)."' and entity = ".((int) $conf->entity);
707 $resql = $this->db->query($sql);
708 if (!$resql) {
709 $error++;
710 $this->error = $this->db->lasterror();
711 }
712
713 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
714 $oldref = dol_sanitizeFileName($this->ref);
715 $newref = dol_sanitizeFileName($num);
716 $dirsource = $conf->ficheinter->dir_output.'/'.$oldref;
717 $dirdest = $conf->ficheinter->dir_output.'/'.$newref;
718 if (!$error && file_exists($dirsource)) {
719 dol_syslog(get_class($this)."::setValid rename dir ".$dirsource." into ".$dirdest);
720
721 if (@rename($dirsource, $dirdest)) {
722 dol_syslog("Rename ok");
723 // Rename docs starting with $oldref with $newref
724 $listoffiles = dol_dir_list($conf->ficheinter->dir_output.'/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
725 foreach ($listoffiles as $fileentry) {
726 $dirsource = $fileentry['name'];
727 $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
728 $dirsource = $fileentry['path'].'/'.$dirsource;
729 $dirdest = $fileentry['path'].'/'.$dirdest;
730 @rename($dirsource, $dirdest);
731 }
732 }
733 }
734 }
735 }
736
737 // Set new ref and define current status
738 if (!$error) {
739 $this->ref = $num;
741 $this->statut = self::STATUS_VALIDATED; // deprecated
742 $this->date_validation = $now;
743 $this->db->commit();
744 return 1;
745 } else {
746 $this->db->rollback();
747 dol_syslog(get_class($this)."::setValid ".$this->error, LOG_ERR);
748 return -1;
749 }
750 }
751
752 return 0;
753 }
754
762 public function setCanceled($user, $notrigger = 0)
763 {
764 $error = 0;
765
766 if ($this->status == self::STATUS_CANCELED) {
767 return 0;
768 }
769
770 $this->db->begin();
771
772 $sql = "UPDATE ".MAIN_DB_PREFIX."fichinter";
773 $sql .= " SET fk_statut = ".self::STATUS_CANCELED.",";
774 $sql .= " fk_user_modif = ".((int) $user->id);
775 $sql .= " WHERE rowid = ".((int) $this->id);
776 $sql .= " AND fk_statut = ".self::STATUS_VALIDATED;
777 $sql .= " AND entity IN (".getEntity('intervention').")";
778
779 dol_syslog(get_class($this)."::setCanceled", LOG_DEBUG);
780 if ($this->db->query($sql)) {
781 if (!$notrigger) {
782 // Call trigger
783 $result = $this->call_trigger('FICHINTER_CANCEL', $user);
784 if ($result < 0) {
785 $error++;
786 }
787 // End call triggers
788 }
789
790 if (!$error) {
792 $this->statut = self::STATUS_CANCELED; // deprecated
793 $this->db->commit();
794 return 1;
795 } else {
796 foreach ($this->errors as $errmsg) {
797 dol_syslog(get_class($this)."::setCanceled ".$errmsg, LOG_ERR);
798 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
799 }
800 $this->db->rollback();
801 return -1 * $error;
802 }
803 } else {
804 $this->error = $this->db->error();
805 $this->db->rollback();
806 return -1;
807 }
808 }
809
810
819 public function setReopen($user, $notrigger = 0)
820 {
821 // phpcs:enable
822 $error = 0;
823
824 if ($this->statut != self::STATUS_CANCELED && $this->statut != self::STATUS_CLOSED) {
825 dol_syslog(get_class($this)."::setReopen intervention has not status closed or canceled", LOG_WARNING);
826 return 0;
827 }
828
829 $this->db->begin();
830
831 $sql = 'UPDATE '.MAIN_DB_PREFIX.'fichinter';
832 $sql .= ' SET fk_statut='.self::STATUS_VALIDATED;
833 $sql .= ", fk_user_modif = ".((int) $user->id);
834 $sql .= " WHERE rowid = ".((int) $this->id);
835
836 dol_syslog(get_class($this)."::setReopen", LOG_DEBUG);
837 $resql = $this->db->query($sql);
838 if ($resql) {
839 if (!$notrigger) {
840 // Call trigger
841 $result = $this->call_trigger('FICHINTER_REOPEN', $user);
842 if ($result < 0) {
843 $error++;
844 }
845 // End call triggers
846 }
847 } else {
848 $error++;
849 $this->error = $this->db->lasterror();
850 dol_print_error($this->db);
851 }
852
853 if (!$error) {
855 $this->statut = self::STATUS_VALIDATED; // deprecated
856 $this->billed = 0;
857
858 $this->db->commit();
859 return 1;
860 } else {
861 foreach ($this->errors as $errmsg) {
862 dol_syslog(get_class($this)."::setReopen ".$errmsg, LOG_ERR);
863 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
864 }
865 $this->db->rollback();
866 return -1 * $error;
867 }
868 }
869
877 public function setClose($user, $notrigger = 0)
878 {
879 global $conf;
880
881 $error = 0;
882
883 if ($this->status == self::STATUS_CLOSED) {
884 return 0;
885 } else {
886 $this->db->begin();
887
888 $now = dol_now();
889
890 $sql = 'UPDATE ' . MAIN_DB_PREFIX . $this->table_element;
891 $sql .= ' SET fk_statut = ' . self::STATUS_CLOSED . ',';
892 $sql .= " datet = '" . $this->db->idate($now) . "',";
893 $sql .= " fk_user_modif = " . ((int) $user->id);
894 $sql .= " WHERE rowid = " . ((int) $this->id);
895 $sql .= " AND fk_statut > " . self::STATUS_DRAFT;
896 $sql .= " AND entity IN (".getEntity('intervention').")";
897
898 if ($this->db->query($sql)) {
899 if (!$notrigger) {
900 // Call trigger
901 $result = $this->call_trigger('FICHINTER_CLOSE', $user);
902 if ($result < 0) {
903 $error++;
904 }
905 // End call triggers
906 }
907
908 if (!$error) {
910 $this->statut = self::STATUS_CLOSED; // deprecated
911 $this->db->commit();
912 return 1;
913 } else {
914 $this->db->rollback();
915 return -1;
916 }
917 } else {
918 $this->error = $this->db->lasterror();
919 $this->db->rollback();
920 return -1;
921 }
922 }
923 }
924
930 public function getAmount()
931 {
932 $amount = 0;
933
934 $this->author = new User($this->db);
935 $this->author->fetch($this->user_creation_id);
936
937 $thm = $this->author->thm;
938
939 foreach ($this->lines as $line) {
940 $amount += ($line->duration / 60 / 60 * (float) $thm);
941 }
942
943 return (float) price2num($amount, 'MT');
944 }
945
946
958 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
959 {
960 global $conf;
961
962 $outputlangs->load("interventions");
963
964 if (!dol_strlen($modele)) {
965 $modele = 'soleil';
966
967 if (!empty($this->model_pdf)) {
968 $modele = $this->model_pdf;
969 } elseif (getDolGlobalString('FICHEINTER_ADDON_PDF')) {
970 $modele = getDolGlobalString('FICHEINTER_ADDON_PDF');
971 }
972 }
973
974 $modelpath = "core/modules/fichinter/doc/";
975
976 return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
977 }
978
985 public function getLibStatut($mode = 0)
986 {
987 return $this->LibStatut((isset($this->statut) ? $this->statut : $this->status), $mode);
988 }
989
990 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
998 public function LibStatut($status, $mode = 0)
999 {
1000 // phpcs:enable
1001 global $langs;
1002 // Init/load array of translation of status
1003 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
1004 $langs->load("interventions");
1005 $langs->load("propal");
1006
1007 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
1008 $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
1009 $this->labelStatus[self::STATUS_BILLED] = $langs->transnoentitiesnoconv('StatusInterInvoiced');
1010 $this->labelStatus[self::STATUS_CLOSED] = $langs->transnoentitiesnoconv('Done');
1011 $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Canceled');
1012 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
1013 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
1014 $this->labelStatusShort[self::STATUS_BILLED] = $langs->transnoentitiesnoconv('StatusInterInvoiced');
1015 $this->labelStatusShort[self::STATUS_CLOSED] = $langs->transnoentitiesnoconv('Done');
1016 $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Canceled');
1017 }
1018
1019 $statuscode = 'status'.$status;
1020 if ($status == self::STATUS_BILLED || $status == self::STATUS_CLOSED) {
1021 $statuscode = 'status6';
1022 }
1023
1024 $signed_label = ' (' . $this->getLibSignedStatus() . ')';
1025 $status_label = $this->signed_status ? $this->labelStatus[$status] . $signed_label : $this->labelStatus[$status];
1026 $status_label_short = $this->signed_status ? $this->labelStatusShort[$status] . $signed_label : $this->labelStatusShort[$status];
1027
1028 return dolGetStatus($status_label, $status_label_short, '', $statuscode, $mode);
1029 }
1030
1037 public function getTooltipContentArray($params)
1038 {
1039 global $langs;
1040
1041 $langs->load('interventions');
1042
1043 $datas = [];
1044 $datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("ShowIntervention").'</u>';
1045 $datas['picto'] .= ' '.$this->getLibStatut(5);
1046 $datas['ref'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
1047
1048 return $datas;
1049 }
1050
1061 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $save_lastsearch_value = -1, $morecss = '')
1062 {
1063 global $conf, $langs, $hookmanager;
1064
1065 if (!empty($conf->dol_no_mouse_hover)) {
1066 $notooltip = 1; // Force disable tooltips
1067 }
1068
1069 $result = '';
1070 $params = [
1071 'id' => $this->id,
1072 'objecttype' => $this->element,
1073 'option' => $option,
1074 ];
1075 $classfortooltip = 'classfortooltip';
1076 $dataparams = '';
1077 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1078 $classfortooltip = 'classforajaxtooltip';
1079 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
1080 $label = '';
1081 } else {
1082 $label = implode($this->getTooltipContentArray($params));
1083 }
1084
1085 $url = DOL_URL_ROOT.'/fichinter/card.php?id='.$this->id;
1086
1087 if ($option !== 'nolink') {
1088 // Add param to save lastsearch_values or not
1089 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1090 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1091 $add_save_lastsearch_values = 1;
1092 }
1093 if ($add_save_lastsearch_values) {
1094 $url .= '&save_lastsearch_values=1';
1095 }
1096 }
1097
1098 $linkclose = '';
1099 if (empty($notooltip)) {
1100 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1101 $label = $langs->trans("ShowIntervention");
1102 $linkclose .= ' alt="'.dolPrintHTMLForAttribute($label).'"';
1103 }
1104 $linkclose .= ($label ? ' title="'.dolPrintHTMLForAttribute($label).'"' : ' title="tocomplete"');
1105 $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
1106 } else {
1107 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1108 }
1109
1110 if ($option == 'nolink') {
1111 $linkstart = '<span';
1112 } else {
1113 $linkstart = '<a href="'.$url.'"';
1114 }
1115 $linkstart .= $linkclose.'>';
1116 if ($option == 'nolink') {
1117 $linkend = '</span>';
1118 } else {
1119 $linkend = '</a>';
1120 }
1121
1122 $result .= $linkstart;
1123 if ($withpicto) {
1124 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"'), 0, 0, $notooltip ? 0 : 1);
1125 }
1126
1127 if ($withpicto != 2) {
1128 $result .= $this->ref;
1129 }
1130
1131 $result .= $linkend;
1132
1133 global $action;
1134 $hookmanager->initHooks(array('interventiondao'));
1135 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1136 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1137 if ($reshook > 0) {
1138 $result = $hookmanager->resPrint;
1139 } else {
1140 $result .= $hookmanager->resPrint;
1141 }
1142
1143 return $result;
1144 }
1145
1146
1154 public function getNextNumRef($soc)
1155 {
1156 global $conf, $db, $langs;
1157 $langs->load("interventions");
1158
1159 if (getDolGlobalString('FICHEINTER_ADDON')) {
1160 $mybool = false;
1161
1162 $file = "mod_" . getDolGlobalString('FICHEINTER_ADDON').".php";
1163 $classname = "mod_" . getDolGlobalString('FICHEINTER_ADDON');
1164
1165 // Include file with class
1166 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1167
1168 foreach ($dirmodels as $reldir) {
1169 $dir = dol_buildpath($reldir."core/modules/fichinter/");
1170
1171 // Load file with numbering class (if found)
1172 $mybool = ((bool) @include_once $dir.$file) || $mybool;
1173 }
1174
1175 if (!$mybool) {
1176 dol_print_error(null, "Failed to include file ".$file);
1177 return '';
1178 }
1179
1180 $obj = new $classname();
1181 '@phan-var-force ModeleNumRefFicheinter $obj';
1182 $numref = "";
1183 $numref = $obj->getNextValue($soc, $this);
1184
1185 if ($numref != "") {
1186 return $numref;
1187 } else {
1188 dol_print_error($db, "Fichinter::getNextNumRef ".$obj->error);
1189 return "";
1190 }
1191 } else {
1192 $langs->load("errors");
1193 print $langs->trans("Error")." ".$langs->trans("Error_FICHEINTER_ADDON_NotDefined");
1194 return "";
1195 }
1196 }
1197
1204 public function info($id)
1205 {
1206 $sql = "SELECT f.rowid,";
1207 $sql .= " f.datec,";
1208 $sql .= " f.tms as date_modification,";
1209 $sql .= " f.date_valid as datev,";
1210 $sql .= " f.fk_user_author,";
1211 $sql .= " f.fk_user_modif as fk_user_modification,";
1212 $sql .= " f.fk_user_valid";
1213 $sql .= " FROM ".MAIN_DB_PREFIX."fichinter as f";
1214 $sql .= " WHERE f.rowid = ".((int) $id);
1215
1216 $resql = $this->db->query($sql);
1217 if ($resql) {
1218 if ($this->db->num_rows($resql)) {
1219 $obj = $this->db->fetch_object($resql);
1220
1221 $this->id = $obj->rowid;
1222
1223 $this->date_creation = $this->db->jdate($obj->datec);
1224 $this->date_modification = $this->db->jdate($obj->date_modification);
1225 $this->date_validation = $this->db->jdate($obj->datev);
1226
1227 $this->user_creation_id = $obj->fk_user_author;
1228 $this->user_validation_id = $obj->fk_user_valid;
1229 $this->user_modification_id = $obj->fk_user_modification;
1230 }
1231 $this->db->free($resql);
1232 } else {
1233 dol_print_error($this->db);
1234 }
1235 }
1236
1244 public function delete(User $user, $notrigger = 0)
1245 {
1246 global $conf, $langs;
1247 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1248
1249 $error = 0;
1250
1251 $this->db->begin();
1252
1253 if (!$notrigger) {
1254 // Call trigger
1255 $result = $this->call_trigger('FICHINTER_DELETE', $user);
1256 if ($result < 0) {
1257 $error++;
1258 $this->db->rollback();
1259 return -1;
1260 }
1261 // End call triggers
1262 }
1263
1264 // Delete linked object
1265 $res = $this->deleteObjectLinked();
1266 if ($res < 0) {
1267 $error++;
1268 }
1269
1270 // Delete linked contacts
1271 if (!$error) {
1272 $res = $this->delete_linked_contact();
1273 if ($res < 0) {
1274 $this->error = 'ErrorFailToDeleteLinkedContact';
1275 $error++;
1276 }
1277 }
1278
1279 if (!$error) {
1280 $main = MAIN_DB_PREFIX.'fichinterdet';
1281 $ef = $main."_extrafields";
1282 $sql = "DELETE FROM ".$this->db->sanitize($ef)." WHERE fk_object IN (SELECT rowid FROM ".$this->db->sanitize($main)." WHERE fk_fichinter = ".((int) $this->id).")";
1283
1284 $resql = $this->db->query($sql);
1285 if (!$resql) {
1286 $error++;
1287 }
1288 }
1289
1290 if (!$error) {
1291 $sql = "DELETE FROM ".MAIN_DB_PREFIX."fichinterdet";
1292 $sql .= " WHERE fk_fichinter = ".((int) $this->id);
1293
1294 $resql = $this->db->query($sql);
1295 if (!$resql) {
1296 $error++;
1297 }
1298 }
1299
1300 if (!$error) {
1301 // Remove extrafields
1302 $res = $this->deleteExtraFields();
1303 if ($res < 0) {
1304 $error++;
1305 }
1306 }
1307
1308 if (!$error) {
1309 // Delete object
1310 $sql = "DELETE FROM ".MAIN_DB_PREFIX."fichinter";
1311 $sql .= " WHERE rowid = ".((int) $this->id);
1312
1313 dol_syslog("Fichinter::delete", LOG_DEBUG);
1314 $resql = $this->db->query($sql);
1315 if (!$resql) {
1316 $error++;
1317 }
1318 }
1319
1320 if (!$error) {
1321 // Delete record into ECM index (Note that delete is also done when deleting files with the dol_delete_dir_recursive
1322 $this->deleteEcmFiles(0); // Deleting files physically is done later with the dol_delete_dir_recursive
1323 $this->deleteEcmFiles(1); // Deleting files physically is done later with the dol_delete_dir_recursive
1324
1325 // Remove directory with files
1326 $fichinterref = dol_sanitizeFileName($this->ref);
1327 if ($conf->ficheinter->dir_output && !empty($fichinterref)) {
1328 $dir = $conf->ficheinter->dir_output."/".$fichinterref;
1329 $file = $conf->ficheinter->dir_output."/".$fichinterref."/".$fichinterref.".pdf";
1330 if (file_exists($file)) {
1331 dol_delete_preview($this);
1332
1333 if (!dol_delete_file($file, 0, 0, 0, $this)) { // For triggers
1334 $langs->load("errors");
1335 $this->error = $langs->trans("ErrorFailToDeleteFile", $file);
1336 return 0;
1337 }
1338 }
1339 if (file_exists($dir)) {
1340 if (!dol_delete_dir_recursive($dir)) {
1341 $langs->load("errors");
1342 $this->error = $langs->trans("ErrorFailToDeleteDir", $dir);
1343 return 0;
1344 }
1345 }
1346 }
1347 }
1348
1349 if (!$error) {
1350 $this->db->commit();
1351 return 1;
1352 } else {
1353 $this->db->rollback();
1354 return -1;
1355 }
1356 }
1357
1358 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1366 public function set_date_delivery($user, $delivery_date_receipt)
1367 {
1368 // phpcs:enable
1369 if ($user->hasRight('ficheinter', 'creer')) {
1370 $this->db->begin();
1371
1372 $sql = "UPDATE ".MAIN_DB_PREFIX."fichinter";
1373 $sql .= " SET datei = '".$this->db->idate($delivery_date_receipt)."'";
1374 $sql .= " WHERE rowid = ".((int) $this->id);
1375 $sql .= " AND fk_statut = 0";
1376
1377 if ($this->db->query($sql)) {
1378 $this->date_delivery = $delivery_date_receipt;
1379 $this->delivery_date_receipt = $delivery_date_receipt;
1380
1381 $result = $this->call_trigger($this->TRIGGER_PREFIX . '_MODIFY', $user);
1382 if ($result < 0) {
1383 $this->db->rollback();
1384 return -1;
1385 }
1386
1387 $this->db->commit();
1388 return 1;
1389 } else {
1390 $this->error = $this->db->error();
1391 dol_syslog("Fichinter::set_date_delivery Erreur SQL");
1392 $this->db->rollback();
1393 return -1;
1394 }
1395 }
1396
1397 return 0;
1398 }
1399
1400 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1408 public function set_description($user, $description)
1409 {
1410 // phpcs:enable
1411 if ($user->hasRight('ficheinter', 'creer')) {
1412 $this->db->begin();
1413
1414 $sql = "UPDATE ".MAIN_DB_PREFIX."fichinter ";
1415 $sql .= " SET description = '".$this->db->escape($description)."',";
1416 $sql .= " fk_user_modif = ".((int) $user->id);
1417 $sql .= " WHERE rowid = ".((int) $this->id);
1418
1419 if ($this->db->query($sql)) {
1420 $this->description = $description;
1421
1422 $result = $this->call_trigger($this->TRIGGER_PREFIX . '_MODIFY', $user);
1423 if ($result < 0) {
1424 $this->db->rollback();
1425 return -1;
1426 }
1427
1428 $this->db->commit();
1429 return 1;
1430 } else {
1431 $this->error = $this->db->error();
1432 dol_syslog("Fichinter::set_description Erreur SQL");
1433 $this->db->rollback();
1434 return -1;
1435 }
1436 }
1437
1438 return 0;
1439 }
1440
1441
1442 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1450 public function set_contrat($user, $contractid)
1451 {
1452 // phpcs:enable
1453 if ($user->hasRight('ficheinter', 'creer')) {
1454 $this->db->begin();
1455
1456 $sql = "UPDATE ".MAIN_DB_PREFIX."fichinter ";
1457 $sql .= " SET fk_contrat = ".((int) $contractid);
1458 $sql .= " WHERE rowid = ".((int) $this->id);
1459
1460 if ($this->db->query($sql)) {
1461 $this->fk_contrat = $contractid;
1462
1463 $result = $this->call_trigger($this->TRIGGER_PREFIX . '_MODIFY', $user);
1464 if ($result < 0) {
1465 $this->db->rollback();
1466 return -1;
1467 }
1468
1469 $this->db->commit();
1470 return 1;
1471 } else {
1472 $this->error = $this->db->error();
1473 $this->db->rollback();
1474 return -1;
1475 }
1476 }
1477
1478 return -2;
1479 }
1480
1481
1482
1492 public function createFromClone(User $user, $socid = 0, $clone_contacts = false, $clone_notes = false)
1493 {
1494 global $hookmanager, $langs;
1495 $langs->load("errors");
1496
1497 $error = 0;
1498
1499 $this->db->begin();
1500
1501 // get extrafields so they will be clone
1502 foreach ($this->lines as $line) {
1503 $line->fetch_optionals();
1504 }
1505
1506 // Load source object
1507 $objFrom = clone $this;
1508
1509 // Change socid if needed
1510 if (!empty($socid) && $socid != $this->socid) {
1511 $objsoc = new Societe($this->db);
1512
1513 if ($objsoc->fetch($socid) > 0) {
1514 $this->socid = $objsoc->id;
1515 //$this->cond_reglement_id = (!empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
1516 //$this->mode_reglement_id = (!empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
1517 $this->fk_project = 0;
1518 $this->fk_delivery_address = 0;
1519 }
1520
1521 // TODO Change product price if multi-prices
1522 }
1523
1524 $this->id = 0;
1525 $this->ref = '';
1526 $this->status = self::STATUS_DRAFT;
1527 $this->statut = self::STATUS_DRAFT; // deprecated
1528
1529 // Clear fields
1530 $this->user_author_id = $user->id;
1531 $this->user_validation_id = 0;
1532 $this->date_creation = '';
1533 $this->date_validation = '';
1534 $this->signed_status = 0;
1535
1536 $this->ref_client = '';
1537
1538 if (!$clone_notes) {
1539 $this->note_private = '';
1540 $this->note_public = '';
1541 }
1542
1543 // Create clone
1544 $this->context['createfromclone'] = 'createfromclone';
1545 $result = $this->create($user);
1546 if ($result < 0) {
1547 $error++;
1548 }
1549
1550 if (!$error) {
1551 // Add lines because it is not included into create function
1552 foreach ($this->lines as $line) {
1553 $this->addline($user, $this->id, $line->desc, $line->datei, $line->duration, $line->array_options);
1554 }
1555
1556 // Hook of thirdparty module
1557 if (is_object($hookmanager)) {
1558 $parameters = array('objFrom' => $objFrom);
1559 $action = '';
1560 $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1561 if ($reshook < 0) {
1562 $this->setErrorsFromObject($hookmanager);
1563 $error++;
1564 }
1565 }
1566 }
1567
1568 //Duplicate contact
1569 if ($clone_contacts) {
1570 foreach (array('internal', 'external') as $source) {
1571 $tab = $objFrom->liste_contact(-1, $source);
1572 if (is_array($tab) && count($tab) > 0) {
1573 foreach ($tab as $contacttoadd) {
1574 $retAddContact = $this->add_contact(
1575 $contacttoadd['id'],
1576 $contacttoadd['code'],
1577 $contacttoadd['source']
1578 );
1579 if ($this->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
1580 $this->error .= $langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType");
1581 $error++;
1582 } elseif ($retAddContact < 0) {
1583 $error++;
1584 }
1585 }
1586 } elseif ($tab < 0) {
1587 $this->error .= $objFrom->error;
1588 $error++;
1589 }
1590 }
1591 }
1592
1593 unset($this->context['createfromclone']);
1594
1595 // End
1596 if (!$error) {
1597 $this->db->commit();
1598 return $this->id;
1599 } else {
1600 $this->db->rollback();
1601 return -1;
1602 }
1603 }
1604
1605
1620 public function addline($user, $fichinterid, $desc, $date_intervention, $duration, $array_options = [], $type = 0, $rang = -1, $special_code = 0)
1621 {
1622 dol_syslog(get_class($this)."::addline $fichinterid, $desc, $date_intervention, $duration, $type, $rang, $special_code");
1623
1624 if ($this->status == self::STATUS_DRAFT) {
1625 $this->db->begin();
1626
1627 // Insert line
1628 $line = new FichinterLigne($this->db);
1629
1630 $line->fk_fichinter = $fichinterid;
1631 $line->desc = $desc;
1632 $line->date = $date_intervention;
1633 $line->datei = $date_intervention; // For backward compatibility
1634 $line->duration = $duration;
1635 $line->product_type = $type;
1636 $line->rang = $rang;
1637 $line->special_code = $special_code;
1638
1639
1640 if (is_array($array_options) && count($array_options) > 0) {
1641 $line->array_options = $array_options;
1642 }
1643
1644 $result = $line->insert($user);
1645
1646 if ($result >= 0) {
1647 $this->db->commit();
1648 return $line->id;
1649 } else {
1650 $this->error = $this->db->error();
1651 $this->db->rollback();
1652 return -1;
1653 }
1654 }
1655
1656 return 0;
1657 }
1658
1659
1667 public function initAsSpecimen()
1668 {
1669 global $langs;
1670
1671 $now = dol_now();
1672
1673 // Initialise parameters
1674 $this->id = 0;
1675 $this->ref = 'SPECIMEN';
1676 $this->ref_client = 'SPECIMEN CLIENT';
1677 $this->specimen = 1;
1678 $this->socid = 1;
1679 $this->datec = $now;
1680 $this->note_private = 'Private note';
1681 $this->note_public = 'SPECIMEN';
1682 $this->duration = 0;
1683 $this->user_creation_id = 1;
1684 $nbp = 25;
1685 $xnbp = 0;
1686 while ($xnbp < $nbp) {
1687 $line = new FichinterLigne($this->db);
1688 $line->desc = $langs->trans("Description")." ".$xnbp;
1689 $line->date = ($now - 3600 * (1 + $xnbp));
1690 $line->datei = ($now - 3600 * (1 + $xnbp)); // For backward compatibility
1691 $line->duration = 600;
1692 $line->fk_fichinter = 0;
1693 $this->lines[$xnbp] = $line;
1694 $xnbp++;
1695
1696 $this->duration += $line->duration;
1697 }
1698
1699 return 1;
1700 }
1701
1702 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1708 public function fetch_lines()
1709 {
1710 // phpcs:enable
1711 $this->lines = array();
1712
1713 $sql = "SELECT rowid, fk_fichinter, description, duree, date, rang, extraparams, special_code";
1714 $sql .= " FROM ".MAIN_DB_PREFIX."fichinterdet";
1715 $sql .= " WHERE fk_fichinter = ".((int) $this->id);
1716 $sql .= " ORDER BY rang ASC, date ASC";
1717
1718 dol_syslog(get_class($this)."::fetch_lines", LOG_DEBUG);
1719
1720 $resql = $this->db->query($sql);
1721 if ($resql) {
1722 $num = $this->db->num_rows($resql);
1723 $i = 0;
1724 while ($i < $num) {
1725 $objp = $this->db->fetch_object($resql);
1726
1727 $line = new FichinterLigne($this->db);
1728 $line->id = $objp->rowid;
1729 $line->fk_fichinter = $objp->fk_fichinter;
1730 $line->desc = $objp->description;
1731 $line->duration = $objp->duree;
1732 $line->special_code = (int) ($objp->special_code ?? 0);
1733 if ($line->special_code == SUBTOTALS_SPECIAL_CODE) {
1734 // Subtotals module lines store their depth (not a real duration) in duree — do not convert to hours
1735 $line->qty = (int) $objp->duree;
1736 } else {
1737 //For invoicing we calculing hours
1738 $line->qty = round($objp->duree / 3600, 2);
1739 }
1740 $line->date = $this->db->jdate($objp->date);
1741 $line->datei = $this->db->jdate($objp->date); // For backward compatibility
1742 $line->rang = $objp->rang;
1743 $line->product_type = 1;
1744 $line->fetch_optionals();
1745
1746 $line->extraparams = !empty($objp->extraparams) ? (array) json_decode($objp->extraparams, true) : array();
1747
1748 $this->lines[$i] = $line;
1749 $i++;
1750 }
1751 $this->db->free($resql);
1752
1753 return 1;
1754 } else {
1755 $this->error = $this->db->error();
1756 return -1;
1757 }
1758 }
1759
1768 public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
1769 {
1770 $tables = array(
1771 'fichinter'
1772 );
1773
1774 return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables);
1775 }
1776
1787 public function setCategories($categories)
1788 {
1789 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1790 return parent::setCategoriesCommon($categories, Categorie::TYPE_FICHINTER);
1791 }
1792
1801 public function setRefClient($user, $ref_client, $notrigger = 0)
1802 {
1803 // phpcs:enable
1804 if ($user->hasRight('ficheinter', 'creer')) {
1805 $error = 0;
1806
1807 $this->db->begin();
1808
1809 $this->oldcopy = dol_clone($this, 2);
1810
1811 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET ref_client = ".(empty($ref_client) ? 'NULL' : "'".$this->db->escape($ref_client)."'");
1812 $sql .= " WHERE rowid = ".((int) $this->id);
1813
1814 dol_syslog(__METHOD__.' $this->id='.$this->id.', ref_client='.$ref_client, LOG_DEBUG);
1815 $resql = $this->db->query($sql);
1816 if (!$resql) {
1817 $this->errors[] = $this->db->error();
1818 $error++;
1819 }
1820
1821 if (!$error) {
1822 $this->ref_client = $ref_client;
1823 }
1824
1825 if (!$notrigger && empty($error)) {
1826 // Call trigger
1827 $result = $this->call_trigger('FICHINTER_MODIFY', $user);
1828 if ($result < 0) {
1829 $error++;
1830 }
1831 // End call triggers
1832 }
1833
1834 if (!$error) {
1835 $this->db->commit();
1836 return 1;
1837 } else {
1838 foreach ($this->errors as $errmsg) {
1839 dol_syslog(__METHOD__.' Error: '.$errmsg, LOG_ERR);
1840 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
1841 }
1842 $this->db->rollback();
1843 return -1 * $error;
1844 }
1845 } else {
1846 return -1;
1847 }
1848 }
1849
1857 public function getKanbanView($option = '', $arraydata = null)
1858 {
1859 global $langs;
1860
1861 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
1862
1863 $return = '<div class="box-flex-item box-flex-grow-zero">';
1864 $return .= '<div class="info-box info-box-sm">';
1865 $return .= '<span class="info-box-icon bg-infobox-action">';
1866 $return .= img_picto('', $this->picto);
1867 $return .= '</span>';
1868 $return .= '<div class="info-box-content">';
1869 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . $this->getNomUrl() . '</span>';
1870 if ($selected >= 0) {
1871 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
1872 }
1873 if (!empty($arraydata['thirdparty'])) {
1874 $tmpthirdparty = $arraydata['thirdparty'];
1875 '@phan-var-force Societe $tmpthirdparty';
1877 $return .= '<br><span class="info-box-label">'.$tmpthirdparty->getNomUrl(1).'</span>';
1878 }
1879 if (!empty($this->duration)) {
1880 $return .= '<br><span class="info-box-label ">'.$langs->trans("Duration").' : '.convertSecondToTime($this->duration, 'allhourmin').'</span>';
1881 }
1882 $return .= '<br><div class="info-box-status">'.$this->getLibStatut(3).'</div>';
1883 $return .= '</div>';
1884 $return .= '</div>';
1885 $return .= '</div>';
1886 return $return;
1887 }
1888}
$object ref
Definition info.php:90
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...
deleteEcmFiles($mode=0)
Delete related files of object in database.
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.
setErrorsFromObject($object)
setErrorsFromObject
static isExistingObject($element, $id, $ref='', $ref_ext='')
Check if an object id or ref exists If you don't need or want to instantiate the object and just need...
deleteExtraFields()
Delete all extra fields values for the current object.
static commonReplaceThirdparty(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
delete_linked_contact($source='', $code='')
Delete all links between an object $this and all its contacts in llx_element_contact.
add_contact($fk_socpeople, $type_contact, $source='external', $notrigger=0)
Add a link between element $this->element and a contact.
Class to manage Dolibarr database access.
const STATUS_BILLED
Billed.
initAsSpecimen()
Initialise an instance with random values.
createFromClone(User $user, $socid=0, $clone_contacts=false, $clone_notes=false)
Load an object from its id and create a new one in database.
getLibStatut($mode=0)
Returns the label status.
update($user, $notrigger=0)
Update an intervention.
static replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
setClose($user, $notrigger=0)
Close intervention.
const STATUS_DRAFT
Draft status.
create($user, $notrigger=0)
Create an intervention into data base.
setCategories($categories)
Sets object to given categories.
set_description($user, $description)
Define the label of the intervention.
getTooltipContentArray($params)
getTooltipContentArray
const STATUS_CANCELED
Canceled status.
set_date_delivery($user, $delivery_date_receipt)
Defines a delivery date of the receipt of intervention.
const STATUS_VALIDATED
Validated status.
fetch($rowid, $ref='', $ref_ext='')
Fetch a intervention.
setReopen($user, $notrigger=0)
Tag the intervention as validated (opened) Function used when the intervention is reopened after bein...
const STATUS_CLOSED
Closed.
setDraft($user)
Set status to draft.
getNextNumRef($soc)
Returns the next non used reference of intervention depending on the module numbering assets within F...
getAmount()
Returns amount based on user thm.
addline($user, $fichinterid, $desc, $date_intervention, $duration, $array_options=[], $type=0, $rang=-1, $special_code=0)
Adding a line of intervention into data base.
setRefClient($user, $ref_client, $notrigger=0)
Set customer reference number.
set_contrat($user, $contractid)
Link intervention to a contract.
LibStatut($status, $mode=0)
Returns the label of a status.
setValid($user, $notrigger=0)
Validate a intervention.
loadStateBoard()
Load indicators into this->nb for board.
getNomUrl($withpicto=0, $option='', $notooltip=0, $save_lastsearch_value=-1, $morecss='')
Return clickable name (with picto eventually)
__construct($db)
Constructor.
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
info($id)
Load information on object.
setCanceled($user, $notrigger=0)
Cancel an intervention.
fetch_lines()
Load array lines ->lines.
Class to manage intervention lines.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage Dolibarr users.
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition index.php:169
getLibSignedStatus(int $mode=0)
Returns the label for signed status.
convertSecondToTime($iSecond, $format='all', $lengthOfDay=86400, $lengthOfWeek=7)
Return, in clear text, value of a number of seconds in days, hours and minutes.
Definition date.lib.php:248
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.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
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_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0, $indexdatabase=1, $nolog=0, $level=0)
Remove a directory $dir and its subdirectories (or only files and subdirectories)
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:65
dol_delete_preview($object)
Delete all preview files linked to object instance.
dol_now($mode='gmt')
Return date for now.
setEntity($currentobject)
Set entity id to use when to create an object.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_clone($srcobject, $native=2)
Create a clone of instance of object (new instance with same value for each properties) With native =...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string