dolibarr  13.0.2
ticket.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2013-2018 Jean-François Ferry <hello@librethic.io>
3  * Copyright (C) 2016 Christophe Battarel <christophe@altairis.fr>
4  * Copyright (C) 2019-2020 Frédéric France <frederic.france@netlogic.fr>
5  * Copyright (C) 2020 Laurent Destailleur <eldy@users.sourceforge.net>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <https://www.gnu.org/licenses/>.
19  */
20 
27 // Put here all includes required by your class file
28 require_once DOL_DOCUMENT_ROOT."/core/class/commonobject.class.php";
29 require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
30 require_once DOL_DOCUMENT_ROOT.'/core/lib/ticket.lib.php';
31 
32 
36 class Ticket extends CommonObject
37 {
41  public $element = 'ticket';
42 
46  public $table_element = 'ticket';
47 
51  public $fk_element = 'fk_ticket';
52 
56  public $ismultientitymanaged = 1;
57 
61  public $isextrafieldmanaged = 1;
62 
66  public $picto = 'ticket';
67 
68 
72  public $track_id;
73 
77  public $fk_soc;
78 
82  public $fk_project;
83 
87  public $origin_email;
88 
92  public $fk_user_create;
93 
97  public $fk_user_assign;
98 
102  public $subject;
103 
107  public $message;
108 
113  public $fk_statut;
114 
118  public $status;
119 
123  public $resolution;
124 
128  public $progress;
129 
133  public $timing;
134 
138  public $type_code;
139 
143  public $category_code;
144 
148  public $severity_code;
149 
153  public $type_label;
154 
159 
164 
168  public $email_from;
169 
173  public $datec = '';
174 
178  public $date_read = '';
179 
183  public $date_close = '';
184 
188  public $cache_types_tickets;
189 
193  public $cache_category_tickets;
194 
198  public $notify_tiers_at_create;
199 
203  public $email_msgid;
204 
205  public $lines;
206 
210  public $regeximgext = '\.jpg|\.jpeg|\.bmp|\.gif|\.png|\.tiff';
211 
215  const STATUS_NOT_READ = 0;
216  const STATUS_READ = 1;
217  const STATUS_ASSIGNED = 2;
218  const STATUS_IN_PROGRESS = 3;
219  const STATUS_NEED_MORE_INFO = 5;
220  const STATUS_WAITING = 7; // on hold
221  const STATUS_CLOSED = 8;
222  const STATUS_CANCELED = 9;
223 
224 
251  // BEGIN MODULEBUILDER PROPERTIES
252  public $fields = array(
253  'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'position'=>1, 'visible'=>-2, 'enabled'=>1, 'position'=>1, 'notnull'=>1, 'index'=>1, 'comment'=>"Id"),
254  'entity' => array('type'=>'integer', 'label'=>'Entity', 'visible'=>0, 'enabled'=>1, 'position'=>5, 'notnull'=>1, 'index'=>1),
255  'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'visible'=>1, 'enabled'=>1, 'position'=>10, 'notnull'=>1, 'index'=>1, 'searchall'=>1, 'comment'=>"Reference of object", 'css'=>''),
256  'track_id' => array('type'=>'varchar(255)', 'label'=>'TicketTrackId', 'visible'=>-2, 'enabled'=>1, 'position'=>11, 'notnull'=>-1, 'searchall'=>1, 'help'=>"Help text"),
257  'fk_user_create' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'Author', 'visible'=>1, 'enabled'=>1, 'position'=>15, 'notnull'=>1, 'css'=>'tdoverflowmax125 maxwidth150onsmartphone'),
258  'origin_email' => array('type'=>'mail', 'label'=>'OriginEmail', 'visible'=>-2, 'enabled'=>1, 'position'=>16, 'notnull'=>1, 'index'=>1, 'searchall'=>1, 'comment'=>"Reference of object", 'css'=>'tdoverflowmax150'),
259  'subject' => array('type'=>'varchar(255)', 'label'=>'Subject', 'visible'=>1, 'enabled'=>1, 'position'=>18, 'notnull'=>-1, 'searchall'=>1, 'help'=>"", 'css'=>'maxwidth200 tdoverflowmax200', 'autofocusoncreate'=>1),
260  'type_code' => array('type'=>'varchar(32)', 'label'=>'Type', 'visible'=>1, 'enabled'=>1, 'position'=>20, 'notnull'=>-1, 'help'=>"", 'css'=>'maxwidth125 tdoverflowmax50'),
261  'category_code' => array('type'=>'varchar(32)', 'label'=>'TicketCategory', 'visible'=>-1, 'enabled'=>1, 'position'=>21, 'notnull'=>-1, 'help'=>"", 'css'=>'maxwidth100'),
262  'severity_code' => array('type'=>'varchar(32)', 'label'=>'Severity', 'visible'=>1, 'enabled'=>1, 'position'=>22, 'notnull'=>-1, 'help'=>"", 'css'=>'maxwidth100'),
263  'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'visible'=>1, 'enabled'=>'$conf->societe->enabled', 'position'=>50, 'notnull'=>-1, 'index'=>1, 'searchall'=>1, 'help'=>"LinkToThirparty", 'css'=>'tdoverflowmax150 maxwidth150onsmartphone'),
264  'notify_tiers_at_create' => array('type'=>'integer', 'label'=>'NotifyThirdparty', 'visible'=>-1, 'enabled'=>0, 'position'=>51, 'notnull'=>1, 'index'=>1),
265  'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php', 'label'=>'Project', 'visible'=>-1, 'enabled'=>1, 'position'=>52, 'notnull'=>-1, 'index'=>1, 'help'=>"LinkToProject"),
266  'timing' => array('type'=>'varchar(20)', 'label'=>'Timing', 'visible'=>-1, 'enabled'=>1, 'position'=>42, 'notnull'=>-1, 'help'=>""),
267  'datec' => array('type'=>'datetime', 'label'=>'DateCreation', 'visible'=>1, 'enabled'=>1, 'position'=>500, 'notnull'=>1),
268  'date_read' => array('type'=>'datetime', 'label'=>'TicketReadOn', 'visible'=>-1, 'enabled'=>1, 'position'=>501, 'notnull'=>1),
269  'fk_user_assign' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'AssignedTo', 'visible'=>1, 'enabled'=>1, 'position'=>505, 'notnull'=>1, 'css'=>'tdoverflowmax125'),
270  'date_close' => array('type'=>'datetime', 'label'=>'TicketCloseOn', 'visible'=>-1, 'enabled'=>1, 'position'=>510, 'notnull'=>1),
271  'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'visible'=>-1, 'enabled'=>1, 'position'=>520, 'notnull'=>1),
272  'message' => array('type'=>'text', 'label'=>'Message', 'visible'=>-2, 'enabled'=>1, 'position'=>540, 'notnull'=>-1,),
273  'email_msgid' => array('type'=>'varchar(255)', 'label'=>'EmailMsgID', 'visible'=>-2, 'enabled'=>1, 'position'=>540, 'notnull'=>-1, 'help'=>'EmailMsgIDDesc'),
274  'progress' => array('type'=>'varchar(100)', 'label'=>'Progression', 'visible'=>-1, 'enabled'=>1, 'position'=>540, 'notnull'=>-1, 'css'=>'right', 'help'=>"", 'isameasure'=>1),
275  'resolution' => array('type'=>'integer', 'label'=>'Resolution', 'visible'=>-1, 'enabled'=>1, 'position'=>550, 'notnull'=>1),
276  'fk_statut' => array('type'=>'integer', 'label'=>'Status', 'visible'=>1, 'enabled'=>1, 'position'=>600, 'notnull'=>1, 'index'=>1, 'arrayofkeyval'=>array(0 => 'Unread', 1 => 'Read', 3 => 'Answered', 4 => 'Assigned', 5 => 'InProgress', 6 => 'Waiting', 8 => 'Closed', 9 => 'Deleted')),
277  'import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>900),
278  );
279  // END MODULEBUILDER PROPERTIES
280 
281 
287  public function __construct($db)
288  {
289  $this->db = $db;
290 
291  $this->statuts_short = array(
292  self::STATUS_NOT_READ => 'Unread',
293  self::STATUS_READ => 'Read',
294  self::STATUS_ASSIGNED => 'Assigned',
295  self::STATUS_IN_PROGRESS => 'InProgress',
296  self::STATUS_WAITING => 'OnHold',
297  self::STATUS_NEED_MORE_INFO => 'NeedMoreInformation',
298  self::STATUS_CLOSED => 'Closed',
299  self::STATUS_CANCELED => 'Canceled'
300  );
301  $this->statuts = array(
302  self::STATUS_NOT_READ => 'Unread',
303  self::STATUS_READ => 'Read',
304  self::STATUS_ASSIGNED => 'Assigned',
305  self::STATUS_IN_PROGRESS => 'InProgress',
306  self::STATUS_WAITING => 'OnHold',
307  self::STATUS_NEED_MORE_INFO => 'NeedMoreInformation',
308  self::STATUS_CLOSED => 'Closed',
309  self::STATUS_CANCELED => 'Canceled'
310  );
311  }
312 
319  private function verify()
320  {
321  $this->errors = array();
322 
323  $result = 0;
324 
325  // Clean parameters
326  if (isset($this->ref)) {
327  $this->ref = trim($this->ref);
328  }
329 
330  if (isset($this->track_id)) {
331  $this->track_id = trim($this->track_id);
332  }
333 
334  if (isset($this->fk_soc)) {
335  $this->fk_soc = (int) $this->fk_soc;
336  }
337 
338  if (isset($this->fk_project)) {
339  $this->fk_project = (int) $this->fk_project;
340  }
341 
342  if (isset($this->origin_email)) {
343  $this->origin_email = trim($this->origin_email);
344  }
345 
346  if (isset($this->fk_user_create)) {
347  $this->fk_user_create = (int) $this->fk_user_create;
348  }
349 
350  if (isset($this->fk_user_assign)) {
351  $this->fk_user_assign = (int) $this->fk_user_assign;
352  }
353 
354  if (isset($this->subject)) {
355  $this->subject = trim($this->subject);
356  }
357 
358  if (isset($this->message)) {
359  $this->message = trim($this->message);
360  }
361 
362  if (isset($this->fk_statut)) {
363  $this->fk_statut = (int) $this->fk_statut;
364  }
365 
366  if (isset($this->resolution)) {
367  $this->resolution = trim($this->resolution);
368  }
369 
370  if (isset($this->progress)) {
371  $this->progress = trim($this->progress);
372  }
373 
374  if (isset($this->timing)) {
375  $this->timing = trim($this->timing);
376  }
377 
378  if (isset($this->type_code)) {
379  $this->type_code = trim($this->type_code);
380  }
381 
382  if (isset($this->category_code)) {
383  $this->category_code = trim($this->category_code);
384  }
385 
386  if (isset($this->severity_code)) {
387  $this->severity_code = trim($this->severity_code);
388  }
389 
390  if (empty($this->ref)) {
391  $this->errors[] = 'ErrorTicketRefRequired';
392  dol_syslog(get_class($this)."::create error -1 ref null", LOG_ERR);
393  $result = -1;
394  }
395 
396  return $result;
397  }
398 
406  public function create($user, $notrigger = 0)
407  {
408  global $conf, $langs;
409  $error = 0;
410 
411  // Clean parameters
412  $this->datec = dol_now();
413  if (empty($this->track_id)) $this->track_id = generate_random_id(16);
414 
415  // Check more parameters
416  // If error, this->errors[] is filled
417  $result = $this->verify();
418 
419  if ($result >= 0) {
420  // Insert request
421  $sql = "INSERT INTO ".MAIN_DB_PREFIX."ticket(";
422  $sql .= "ref,";
423  $sql .= "track_id,";
424  $sql .= "fk_soc,";
425  $sql .= "fk_project,";
426  $sql .= "origin_email,";
427  $sql .= "fk_user_create,";
428  $sql .= "fk_user_assign,";
429  $sql .= "email_msgid,";
430  $sql .= "subject,";
431  $sql .= "message,";
432  $sql .= "fk_statut,";
433  $sql .= "resolution,";
434  $sql .= "progress,";
435  $sql .= "timing,";
436  $sql .= "type_code,";
437  $sql .= "category_code,";
438  $sql .= "severity_code,";
439  $sql .= "datec,";
440  $sql .= "date_read,";
441  $sql .= "date_close,";
442  $sql .= "entity,";
443  $sql .= "notify_tiers_at_create";
444  $sql .= ") VALUES (";
445  $sql .= " ".(!isset($this->ref) ? '' : "'".$this->db->escape($this->ref)."'").",";
446  $sql .= " ".(!isset($this->track_id) ? 'NULL' : "'".$this->db->escape($this->track_id)."'").",";
447  $sql .= " ".($this->fk_soc > 0 ? $this->db->escape($this->fk_soc) : "null").",";
448  $sql .= " ".($this->fk_project > 0 ? $this->db->escape($this->fk_project) : "null").",";
449  $sql .= " ".(!isset($this->origin_email) ? 'NULL' : "'".$this->db->escape($this->origin_email)."'").",";
450  $sql .= " ".($this->fk_user_create > 0 ? $this->fk_user_create : ($user->id > 0 ? $user->id : 'NULL')).",";
451  $sql .= " ".($this->fk_user_assign > 0 ? $this->fk_user_assign : 'NULL').",";
452  $sql .= " ".(empty($this->email_msgid) ? 'NULL' : "'".$this->db->escape($this->email_msgid)."'").",";
453  $sql .= " ".(!isset($this->subject) ? 'NULL' : "'".$this->db->escape($this->subject)."'").",";
454  $sql .= " ".(!isset($this->message) ? 'NULL' : "'".$this->db->escape($this->message)."'").",";
455  $sql .= " ".(!isset($this->fk_statut) ? '0' : "'".$this->db->escape($this->fk_statut)."'").",";
456  $sql .= " ".(!isset($this->resolution) ? 'NULL' : "'".$this->db->escape($this->resolution)."'").",";
457  $sql .= " ".(!isset($this->progress) ? '0' : "'".$this->db->escape($this->progress)."'").",";
458  $sql .= " ".(!isset($this->timing) ? 'NULL' : "'".$this->db->escape($this->timing)."'").",";
459  $sql .= " ".(!isset($this->type_code) ? 'NULL' : "'".$this->db->escape($this->type_code)."'").",";
460  $sql .= " ".(!isset($this->category_code) ? 'NULL' : "'".$this->db->escape($this->category_code)."'").",";
461  $sql .= " ".(!isset($this->severity_code) ? 'NULL' : "'".$this->db->escape($this->severity_code)."'").",";
462  $sql .= " ".(!isset($this->datec) || dol_strlen($this->datec) == 0 ? 'NULL' : "'".$this->db->idate($this->datec)."'").",";
463  $sql .= " ".(!isset($this->date_read) || dol_strlen($this->date_read) == 0 ? 'NULL' : "'".$this->db->idate($this->date_read)."'").",";
464  $sql .= " ".(!isset($this->date_close) || dol_strlen($this->date_close) == 0 ? 'NULL' : "'".$this->db->idate($this->date_close)."'")."";
465  $sql .= ", ".$conf->entity;
466  $sql .= ", ".(!isset($this->notify_tiers_at_create) ? '1' : "'".$this->db->escape($this->notify_tiers_at_create)."'");
467  $sql .= ")";
468 
469  $this->db->begin();
470 
471  dol_syslog(get_class($this)."::create sql=".$sql, LOG_DEBUG);
472  $resql = $this->db->query($sql);
473  if (!$resql) {
474  $error++;
475  $this->errors[] = "Error ".$this->db->lasterror();
476  }
477 
478  if (!$error) {
479  $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."ticket");
480 
481  if (!$notrigger) {
482  // Call trigger
483  $result = $this->call_trigger('TICKET_CREATE', $user);
484  if ($result < 0) {
485  $error++;
486  }
487  // End call triggers
488  }
489  }
490 
491  //Update extrafield
492  if (!$error) {
493  $result = $this->insertExtraFields();
494  if ($result < 0) {
495  $error++;
496  }
497  }
498 
499  // Commit or rollback
500  if ($error) {
501  foreach ($this->errors as $errmsg) {
502  dol_syslog(get_class($this)."::create ".$errmsg, LOG_ERR);
503  $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
504  }
505  $this->db->rollback();
506  return -1 * $error;
507  } else {
508  $this->db->commit();
509  return $this->id;
510  }
511  } else {
512  $this->db->rollback();
513  dol_syslog(get_class($this)."::Create fails verify ".join(',', $this->errors), LOG_WARNING);
514  return -3;
515  }
516  }
517 
527  public function fetch($id = '', $ref = '', $track_id = '', $email_msgid = '')
528  {
529  global $langs;
530 
531  // Check parameters
532  if (!$id && !$track_id && !$ref && !$email_msgid) {
533  $this->error = 'ErrorWrongParameters';
534  dol_print_error(get_class($this)."::fetch ".$this->error);
535  return -1;
536  }
537 
538  $sql = "SELECT";
539  $sql .= " t.rowid,";
540  $sql .= " t.entity,";
541  $sql .= " t.ref,";
542  $sql .= " t.track_id,";
543  $sql .= " t.fk_soc,";
544  $sql .= " t.fk_project,";
545  $sql .= " t.origin_email,";
546  $sql .= " t.fk_user_create,";
547  $sql .= " t.fk_user_assign,";
548  $sql .= " t.email_msgid,";
549  $sql .= " t.subject,";
550  $sql .= " t.message,";
551  $sql .= " t.fk_statut as status,";
552  $sql .= " t.resolution,";
553  $sql .= " t.progress,";
554  $sql .= " t.timing,";
555  $sql .= " t.type_code,";
556  $sql .= " t.category_code,";
557  $sql .= " t.severity_code,";
558  $sql .= " t.datec,";
559  $sql .= " t.date_read,";
560  $sql .= " t.date_close,";
561  $sql .= " t.tms";
562  $sql .= ", type.code as type_code, type.label as type_label, category.code as category_code, category.label as category_label, severity.code as severity_code, severity.label as severity_label";
563  $sql .= " FROM ".MAIN_DB_PREFIX."ticket as t";
564  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_type as type ON type.code=t.type_code";
565  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_category as category ON category.code=t.category_code";
566  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_severity as severity ON severity.code=t.severity_code";
567 
568  if ($id) {
569  $sql .= " WHERE t.rowid = ".$this->db->escape($id);
570  } else {
571  $sql .= " WHERE t.entity IN (".getEntity($this->element, 1).")";
572  if (!empty($ref)) {
573  $sql .= " AND t.ref = '".$this->db->escape($ref)."'";
574  } elseif ($track_id) {
575  $sql .= " AND t.track_id = '".$this->db->escape($track_id)."'";
576  } else {
577  $sql .= " AND t.email_msgid = '".$this->db->escape($email_msgid)."'";
578  }
579  }
580 
581  dol_syslog(get_class($this)."::fetch sql=".$sql, LOG_DEBUG);
582  $resql = $this->db->query($sql);
583  if ($resql) {
584  if ($this->db->num_rows($resql))
585  {
586  $obj = $this->db->fetch_object($resql);
587 
588  $this->id = $obj->rowid;
589  $this->ref = $obj->ref;
590  $this->track_id = $obj->track_id;
591  $this->fk_soc = $obj->fk_soc;
592  $this->socid = $obj->fk_soc; // for fetch_thirdparty() method
593  $this->fk_project = $obj->fk_project;
594  $this->origin_email = $obj->origin_email;
595  $this->fk_user_create = $obj->fk_user_create;
596  $this->fk_user_assign = $obj->fk_user_assign;
597  $this->email_msgid = $obj->email_msgid;
598  $this->subject = $obj->subject;
599  $this->message = $obj->message;
600 
601  $this->status = $obj->status;
602  $this->fk_statut = $this->status; // For backward compatibility
603 
604  $this->resolution = $obj->resolution;
605  $this->progress = $obj->progress;
606  $this->timing = $obj->timing;
607 
608  $this->type_code = $obj->type_code;
609  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
610  $label_type = ($langs->trans("TicketTypeShort".$obj->type_code) != ("TicketTypeShort".$obj->type_code) ? $langs->trans("TicketTypeShort".$obj->type_code) : ($obj->type_label != '-' ? $obj->type_label : ''));
611  $this->type_label = $label_type;
612 
613  $this->category_code = $obj->category_code;
614  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
615  $label_category = ($langs->trans("TicketCategoryShort".$obj->category_code) != ("TicketCategoryShort".$obj->category_code) ? $langs->trans("TicketCategoryShort".$obj->category_code) : ($obj->category_label != '-' ? $obj->category_label : ''));
616  $this->category_label = $label_category;
617 
618  $this->severity_code = $obj->severity_code;
619  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
620  $label_severity = ($langs->trans("TicketSeverityShort".$obj->severity_code) != ("TicketSeverityShort".$obj->severity_code) ? $langs->trans("TicketSeverityShort".$obj->severity_code) : ($obj->severity_label != '-' ? $obj->severity_label : ''));
621  $this->severity_label = $label_severity;
622 
623  $this->datec = $this->db->jdate($obj->datec);
624  $this->date_creation = $this->db->jdate($obj->datec);
625  $this->date_read = $this->db->jdate($obj->date_read);
626  $this->date_validation = $this->db->jdate($obj->date_read);
627  $this->date_close = $this->db->jdate($obj->date_close);
628  $this->tms = $this->db->jdate($obj->tms);
629  $this->date_modification = $this->db->jdate($obj->tms);
630 
631  $this->fetch_optionals();
632 
633  $this->db->free($resql);
634  return 1;
635  } else {
636  return 0;
637  }
638  } else {
639  $this->error = "Error ".$this->db->lasterror();
640  dol_syslog(get_class($this)."::fetch ".$this->error, LOG_ERR);
641  return -1;
642  }
643  }
644 
658  public function fetchAll($user, $sortorder = 'ASC', $sortfield = 't.datec', $limit = '', $offset = 0, $arch = '', $filter = '')
659  {
660  global $langs;
661 
662  $extrafields = new ExtraFields($this->db);
663 
664  // fetch optionals attributes and labels
665  $extrafields->fetch_name_optionals_label($this->table_element);
666 
667  $sql = "SELECT";
668  $sql .= " t.rowid,";
669  $sql .= " t.ref,";
670  $sql .= " t.track_id,";
671  $sql .= " t.fk_soc,";
672  $sql .= " t.fk_project,";
673  $sql .= " t.origin_email,";
674  $sql .= " t.fk_user_create, uc.lastname as user_create_lastname, uc.firstname as user_create_firstname,";
675  $sql .= " t.fk_user_assign, ua.lastname as user_assign_lastname, ua.firstname as user_assign_firstname,";
676  $sql .= " t.subject,";
677  $sql .= " t.message,";
678  $sql .= " t.fk_statut,";
679  $sql .= " t.resolution,";
680  $sql .= " t.progress,";
681  $sql .= " t.timing,";
682  $sql .= " t.type_code,";
683  $sql .= " t.category_code,";
684  $sql .= " t.severity_code,";
685  $sql .= " t.datec,";
686  $sql .= " t.date_read,";
687  $sql .= " t.date_close,";
688  $sql .= " t.tms";
689  $sql .= ", type.label as type_label, category.label as category_label, severity.label as severity_label";
690  // Add fields for extrafields
691  foreach ($extrafields->attributes[$this->table_element]['label'] as $key => $val) {
692  $sql .= ($extrafields->attributes[$this->table_element]['type'][$key] != 'separate' ? ",ef.".$key.' as options_'.$key : '');
693  }
694  $sql .= " FROM ".MAIN_DB_PREFIX."ticket as t";
695  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_type as type ON type.code=t.type_code";
696  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_category as category ON category.code=t.category_code";
697  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_severity as severity ON severity.code=t.severity_code";
698  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid=t.fk_soc";
699  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as uc ON uc.rowid=t.fk_user_create";
700  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as ua ON ua.rowid=t.fk_user_assign";
701  if (is_array($extrafields->attributes[$this->table_element]['label']) && count($extrafields->attributes[$this->table_element]['label'])) {
702  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."ticket_extrafields as ef on (t.rowid = ef.fk_object)";
703  }
704  if (!$user->rights->societe->client->voir && !$user->socid) {
705  $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
706  }
707 
708  $sql .= " WHERE t.entity IN (".getEntity('ticket').")";
709 
710  // Manage filter
711  if (!empty($filter)) {
712  foreach ($filter as $key => $value) {
713  if (strpos($key, 'date')) { // To allow $filter['YEAR(s.dated)']=>$year
714  $sql .= ' AND '.$key." = '".$this->db->escape($value)."'";
715  } elseif (($key == 't.fk_user_assign') || ($key == 't.type_code') || ($key == 't.category_code') || ($key == 't.severity_code') || ($key == 't.fk_soc')) {
716  $sql .= " AND ".$key." = '".$this->db->escape($value)."'";
717  } elseif ($key == 't.fk_statut') {
718  if (is_array($value) && count($value) > 0) {
719  $sql .= 'AND '.$key.' IN ('.implode(',', $value).')';
720  } else {
721  $sql .= ' AND '.$key.' = '.$this->db->escape($value);
722  }
723  } else {
724  $sql .= ' AND '.$key.' LIKE \'%'.$value.'%\'';
725  }
726  }
727  }
728  if (!$user->rights->societe->client->voir && !$user->socid) {
729  $sql .= " AND t.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
730  } elseif ($user->socid) {
731  $sql .= " AND t.fk_soc = ".$user->socid;
732  }
733 
734  $sql .= " ORDER BY ".$sortfield.' '.$sortorder;
735  if (!empty($limit)) {
736  $sql .= ' '.$this->db->plimit($limit + 1, $offset);
737  }
738 
739  dol_syslog(get_class($this)."::fetch_all sql=".$sql, LOG_DEBUG);
740  $resql = $this->db->query($sql);
741 
742  if ($resql) {
743  $this->lines = array();
744 
745  $num = $this->db->num_rows($resql);
746  $i = 0;
747 
748  if ($num) {
749  while ($i < $num) {
750  $obj = $this->db->fetch_object($resql);
751 
752  $line = new TicketsLine();
753 
754  $line->id = $obj->rowid;
755  $line->rowid = $obj->rowid;
756  $line->ref = $obj->ref;
757  $line->track_id = $obj->track_id;
758  $line->fk_soc = $obj->fk_soc;
759  $line->fk_project = $obj->fk_project;
760  $line->origin_email = $obj->origin_email;
761 
762  $line->fk_user_create = $obj->fk_user_create;
763  $line->user_create_lastname = $obj->user_create_lastname;
764  $line->user_create_firstname = $obj->user_create_firstname;
765 
766  $line->fk_user_assign = $obj->fk_user_assign;
767  $line->user_assign_lastname = $obj->user_assign_lastname;
768  $line->user_assign_firstname = $obj->user_assign_firstname;
769 
770  $line->subject = $obj->subject;
771  $line->message = $obj->message;
772  $line->fk_statut = $obj->fk_statut;
773  $line->resolution = $obj->resolution;
774  $line->progress = $obj->progress;
775  $line->timing = $obj->timing;
776 
777  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
778  $label_type = ($langs->trans("TicketTypeShort".$obj->type_code) != ("TicketTypeShort".$obj->type_code) ? $langs->trans("TicketTypeShort".$obj->type_code) : ($obj->type_label != '-' ? $obj->type_label : ''));
779  $line->type_label = $label_type;
780 
781  $this->category_code = $obj->category_code;
782  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
783  $label_category = ($langs->trans("TicketCategoryShort".$obj->category_code) != ("TicketCategoryShort".$obj->category_code) ? $langs->trans("TicketCategoryShort".$obj->category_code) : ($obj->category_label != '-' ? $obj->category_label : ''));
784  $line->category_label = $label_category;
785 
786  $this->severity_code = $obj->severity_code;
787  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
788  $label_severity = ($langs->trans("TicketSeverityShort".$obj->severity_code) != ("TicketSeverityShort".$obj->severity_code) ? $langs->trans("TicketSeverityShort".$obj->severity_code) : ($obj->severity_label != '-' ? $obj->severity_label : ''));
789  $line->severity_label = $label_severity;
790 
791  $line->datec = $this->db->jdate($obj->datec);
792  $line->date_read = $this->db->jdate($obj->date_read);
793  $line->date_close = $this->db->jdate($obj->date_close);
794 
795  // Extra fields
796  if (is_array($extrafields->attributes[$this->table_element]['label']) && count($extrafields->attributes[$this->table_element]['label'])) {
797  foreach ($extrafields->attributes[$this->table_element]['label'] as $key => $val) {
798  $tmpkey = 'options_'.$key;
799  $line->{$tmpkey} = $obj->$tmpkey;
800  }
801  }
802 
803  $this->lines[$i] = $line;
804  $i++;
805  }
806  }
807  $this->db->free($resql);
808  return $num;
809  } else {
810  $this->error = "Error ".$this->db->lasterror();
811  dol_syslog(get_class($this)."::fetch_all ".$this->error, LOG_ERR);
812  return -1;
813  }
814  }
815 
823  public function update($user = 0, $notrigger = 0)
824  {
825  global $conf, $langs, $hookmanager;
826  $error = 0;
827 
828  // Clean parameters
829  if (isset($this->ref)) {
830  $this->ref = trim($this->ref);
831  }
832 
833  if (isset($this->track_id)) {
834  $this->track_id = trim($this->track_id);
835  }
836 
837  if (isset($this->fk_soc)) {
838  $this->fk_soc = (int) $this->fk_soc;
839  }
840 
841  if (isset($this->fk_project)) {
842  $this->fk_project = (int) $this->fk_project;
843  }
844 
845  if (isset($this->origin_email)) {
846  $this->origin_email = trim($this->origin_email);
847  }
848 
849  if (isset($this->fk_user_create)) {
850  $this->fk_user_create = (int) $this->fk_user_create;
851  }
852 
853  if (isset($this->fk_user_assign)) {
854  $this->fk_user_assign = (int) $this->fk_user_assign;
855  }
856 
857  if (isset($this->subject)) {
858  $this->subject = trim($this->subject);
859  }
860 
861  if (isset($this->message)) {
862  $this->message = trim($this->message);
863  }
864 
865  if (isset($this->fk_statut)) {
866  $this->fk_statut = (int) $this->fk_statut;
867  }
868 
869  if (isset($this->resolution)) {
870  $this->resolution = trim($this->resolution);
871  }
872 
873  if (isset($this->progress)) {
874  $this->progress = trim($this->progress);
875  }
876 
877  if (isset($this->timing)) {
878  $this->timing = trim($this->timing);
879  }
880 
881  if (isset($this->type_code)) {
882  $this->timing = trim($this->type_code);
883  }
884 
885  if (isset($this->category_code)) {
886  $this->timing = trim($this->category_code);
887  }
888 
889  if (isset($this->severity_code)) {
890  $this->timing = trim($this->severity_code);
891  }
892 
893  // Check parameters
894  // Put here code to add a control on parameters values
895  // Update request
896  $sql = "UPDATE ".MAIN_DB_PREFIX."ticket SET";
897  $sql .= " ref=".(isset($this->ref) ? "'".$this->db->escape($this->ref)."'" : "").",";
898  $sql .= " track_id=".(isset($this->track_id) ? "'".$this->db->escape($this->track_id)."'" : "null").",";
899  $sql .= " fk_soc=".(isset($this->fk_soc) ? "'".$this->db->escape($this->fk_soc)."'" : "null").",";
900  $sql .= " fk_project=".(isset($this->fk_project) ? "'".$this->db->escape($this->fk_project)."'" : "null").",";
901  $sql .= " origin_email=".(isset($this->origin_email) ? "'".$this->db->escape($this->origin_email)."'" : "null").",";
902  $sql .= " fk_user_create=".(isset($this->fk_user_create) ? $this->fk_user_create : "null").",";
903  $sql .= " fk_user_assign=".(isset($this->fk_user_assign) ? $this->fk_user_assign : "null").",";
904  $sql .= " subject=".(isset($this->subject) ? "'".$this->db->escape($this->subject)."'" : "null").",";
905  $sql .= " message=".(isset($this->message) ? "'".$this->db->escape($this->message)."'" : "null").",";
906  $sql .= " fk_statut=".(isset($this->fk_statut) ? $this->fk_statut : "null").",";
907  $sql .= " resolution=".(isset($this->resolution) ? $this->resolution : "null").",";
908  $sql .= " progress=".(isset($this->progress) ? "'".$this->db->escape($this->progress)."'" : "null").",";
909  $sql .= " timing=".(isset($this->timing) ? "'".$this->db->escape($this->timing)."'" : "null").",";
910  $sql .= " type_code=".(isset($this->type_code) ? "'".$this->db->escape($this->type_code)."'" : "null").",";
911  $sql .= " category_code=".(isset($this->category_code) ? "'".$this->db->escape($this->category_code)."'" : "null").",";
912  $sql .= " severity_code=".(isset($this->severity_code) ? "'".$this->db->escape($this->severity_code)."'" : "null").",";
913  $sql .= " datec=".(dol_strlen($this->datec) != 0 ? "'".$this->db->idate($this->datec)."'" : 'null').",";
914  $sql .= " date_read=".(dol_strlen($this->date_read) != 0 ? "'".$this->db->idate($this->date_read)."'" : 'null').",";
915  $sql .= " date_close=".(dol_strlen($this->date_close) != 0 ? "'".$this->db->idate($this->date_close)."'" : 'null')."";
916  $sql .= " WHERE rowid=".$this->id;
917 
918  $this->db->begin();
919 
920  $resql = $this->db->query($sql);
921  if (!$resql) {
922  $error++;
923  $this->errors[] = "Error ".$this->db->lasterror();
924  }
925 
926  if (!$error) {
927  // Update extrafields
928  $result = $this->insertExtraFields();
929  if ($result < 0) {
930  $error++;
931  }
932  }
933 
934  if (!$error && !$notrigger) {
935  // Call trigger
936  $result = $this->call_trigger('TICKET_MODIFY', $user);
937  if ($result < 0) {
938  $error++;
939  }
940  // End call triggers
941  }
942 
943  // Commit or rollback
944  if ($error) {
945  foreach ($this->errors as $errmsg) {
946  dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
947  $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
948  }
949  $this->db->rollback();
950  return -1 * $error;
951  } else {
952  $this->db->commit();
953  return 1;
954  }
955  }
956 
964  public function delete($user, $notrigger = 0)
965  {
966  global $conf, $langs;
967  $error = 0;
968 
969  $this->db->begin();
970 
971  if (!$error) {
972  if (!$notrigger) {
973  // Call trigger
974  $result = $this->call_trigger('TICKET_DELETE', $user);
975  if ($result < 0) {
976  $error++;
977  }
978  // End call triggers
979  }
980  }
981 
982  if (!$error) {
983  // Delete linked contacts
984  $res = $this->delete_linked_contact();
985  if ($res < 0) {
986  dol_syslog(get_class($this)."::delete error", LOG_ERR);
987  $error++;
988  }
989  }
990 
991  if (!$error) {
992  // Delete linked object
993  $res = $this->deleteObjectLinked();
994  if ($res < 0) $error++;
995  }
996 
997  // Removed extrafields
998  if (!$error) {
999  $result = $this->deleteExtraFields();
1000  if ($result < 0) {
1001  $error++;
1002  dol_syslog(get_class($this)."::delete error -3 ".$this->error, LOG_ERR);
1003  }
1004  }
1005 
1006  if (!$error) {
1007  $sql = "DELETE FROM ".MAIN_DB_PREFIX."ticket";
1008  $sql .= " WHERE rowid=".$this->id;
1009 
1010  dol_syslog(get_class($this)."::delete sql=".$sql);
1011  $resql = $this->db->query($sql);
1012  if (!$resql) {
1013  $error++;
1014  $this->errors[] = "Error ".$this->db->lasterror();
1015  }
1016  }
1017 
1018  // Commit or rollback
1019  if ($error) {
1020  foreach ($this->errors as $errmsg) {
1021  dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
1022  $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
1023  }
1024  $this->db->rollback();
1025  return -1 * $error;
1026  } else {
1027  $this->db->commit();
1028  return 1;
1029  }
1030  }
1031 
1039  public function createFromClone(User $user, $fromid)
1040  {
1041  $error = 0;
1042 
1043  $object = new Ticket($this->db);
1044 
1045  $this->db->begin();
1046 
1047  // Load source object
1048  $object->fetch($fromid);
1049  $object->id = 0;
1050  $object->statut = 0;
1051 
1052  // Clear fields
1053  // ...
1054  // Create clone
1055  $object->context['createfromclone'] = 'createfromclone';
1056  $result = $object->create($user);
1057 
1058  // Other options
1059  if ($result < 0) {
1060  $this->error = $object->error;
1061  $error++;
1062  }
1063 
1064  if (!$error) {
1065  }
1066 
1067  unset($object->context['createfromclone']);
1068 
1069  // End
1070  if (!$error) {
1071  $this->db->commit();
1072  return $object->id;
1073  } else {
1074  $this->db->rollback();
1075  return -1;
1076  }
1077  }
1078 
1085  public function initAsSpecimen()
1086  {
1087  $this->id = 0;
1088  $this->entity = 1;
1089  $this->ref = 'TI0501-001';
1090  $this->track_id = 'XXXXaaaa';
1091  $this->origin_email = 'email@email.com';
1092  $this->fk_project = 1;
1093  $this->fk_user_create = 1;
1094  $this->fk_user_assign = 1;
1095  $this->subject = 'Subject of ticket';
1096  $this->message = 'Message of ticket';
1097  $this->status = 0;
1098  $this->resolution = '1';
1099  $this->progress = '10';
1100  $this->timing = '30';
1101  $this->type_code = 'TYPECODE';
1102  $this->category_code = 'CATEGORYCODE';
1103  $this->severity_code = 'SEVERITYCODE';
1104  $this->datec = '';
1105  $this->date_read = '';
1106  $this->date_close = '';
1107  $this->tms = '';
1108  return 1;
1109  }
1110 
1117  public function printSelectStatus($selected = "")
1118  {
1119  print Form::selectarray('search_fk_statut', $this->statuts_short, $selected, $show_empty = 1, $key_in_label = 0, $value_as_key = 0, $option = '', $translate = 1, $maxlen = 0, $disabled = 0, $sort = '', $morecss = '');
1120  }
1121 
1122 
1128  public function loadCacheTypesTickets()
1129  {
1130  global $langs;
1131 
1132  if (!empty($this->cache_types_tickets) && count($this->cache_types_tickets)) {
1133  return 0;
1134  }
1135  // Cache deja charge
1136 
1137  $sql = "SELECT rowid, code, label, use_default, pos, description";
1138  $sql .= " FROM ".MAIN_DB_PREFIX."c_ticket_type";
1139  $sql .= " WHERE active > 0";
1140  $sql .= " ORDER BY pos";
1141  dol_syslog(get_class($this)."::load_cache_type_tickets sql=".$sql, LOG_DEBUG);
1142  $resql = $this->db->query($sql);
1143  if ($resql) {
1144  $num = $this->db->num_rows($resql);
1145  $i = 0;
1146  while ($i < $num) {
1147  $obj = $this->db->fetch_object($resql);
1148  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
1149  $label = ($langs->trans("TicketTypeShort".$obj->code) != ("TicketTypeShort".$obj->code) ? $langs->trans("TicketTypeShort".$obj->code) : ($obj->label != '-' ? $obj->label : ''));
1150  $this->cache_types_tickets[$obj->rowid]['code'] = $obj->code;
1151  $this->cache_types_tickets[$obj->rowid]['label'] = $label;
1152  $this->cache_types_tickets[$obj->rowid]['use_default'] = $obj->use_default;
1153  $this->cache_types_tickets[$obj->rowid]['pos'] = $obj->pos;
1154  $i++;
1155  }
1156  return $num;
1157  } else {
1158  dol_print_error($this->db);
1159  return -1;
1160  }
1161  }
1162 
1168  public function loadCacheCategoriesTickets()
1169  {
1170  global $langs;
1171 
1172  if (!empty($this->cache_category_ticket) && count($this->cache_category_tickets)) {
1173  return 0;
1174  }
1175  // Cache deja charge
1176 
1177  $sql = "SELECT rowid, code, label, use_default, pos, description";
1178  $sql .= " FROM ".MAIN_DB_PREFIX."c_ticket_category";
1179  $sql .= " WHERE active > 0";
1180  $sql .= " ORDER BY pos";
1181  dol_syslog(get_class($this)."::load_cache_categories_tickets sql=".$sql, LOG_DEBUG);
1182  $resql = $this->db->query($sql);
1183  if ($resql) {
1184  $num = $this->db->num_rows($resql);
1185  $i = 0;
1186  while ($i < $num) {
1187  $obj = $this->db->fetch_object($resql);
1188  $this->cache_category_tickets[$obj->rowid]['code'] = $obj->code;
1189  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
1190  $label = ($langs->trans("TicketCategoryShort".$obj->code) != ("TicketCategoryShort".$obj->code) ? $langs->trans("TicketCategoryShort".$obj->code) : ($obj->label != '-' ? $obj->label : ''));
1191  $this->cache_category_tickets[$obj->rowid]['label'] = $label;
1192  $this->cache_category_tickets[$obj->rowid]['use_default'] = $obj->use_default;
1193  $this->cache_category_tickets[$obj->rowid]['pos'] = $obj->pos;
1194  $i++;
1195  }
1196  return $num;
1197  } else {
1198  dol_print_error($this->db);
1199  return -1;
1200  }
1201  }
1202 
1208  public function loadCacheSeveritiesTickets()
1209  {
1210  global $langs;
1211 
1212  if (!empty($this->cache_severity_tickets) && count($this->cache_severity_tickets)) {
1213  return 0;
1214  }
1215  // Cache deja charge
1216 
1217  $sql = "SELECT rowid, code, label, use_default, pos, description";
1218  $sql .= " FROM ".MAIN_DB_PREFIX."c_ticket_severity";
1219  $sql .= " WHERE active > 0";
1220  $sql .= " ORDER BY pos";
1221  dol_syslog(get_class($this)."::loadCacheSeveritiesTickets sql=".$sql, LOG_DEBUG);
1222  $resql = $this->db->query($sql);
1223  if ($resql) {
1224  $num = $this->db->num_rows($resql);
1225  $i = 0;
1226  while ($i < $num) {
1227  $obj = $this->db->fetch_object($resql);
1228 
1229  $this->cache_severity_tickets[$obj->rowid]['code'] = $obj->code;
1230  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
1231  $label = ($langs->trans("TicketSeverityShort".$obj->code) != ("TicketSeverityShort".$obj->code) ? $langs->trans("TicketSeverityShort".$obj->code) : ($obj->label != '-' ? $obj->label : ''));
1232  $this->cache_severity_tickets[$obj->rowid]['label'] = $label;
1233  $this->cache_severity_tickets[$obj->rowid]['use_default'] = $obj->use_default;
1234  $this->cache_severity_tickets[$obj->rowid]['pos'] = $obj->pos;
1235  $i++;
1236  }
1237  return $num;
1238  } else {
1239  dol_print_error($this->db);
1240  return -1;
1241  }
1242  }
1243 
1244 
1251  public function getLibStatut($mode = 0)
1252  {
1253  return $this->libStatut($this->fk_statut, $mode);
1254  }
1255 
1256 
1257  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1266  public function LibStatut($status, $mode = 0, $notooltip = 0)
1267  {
1268  // phpcs:enable
1269  global $langs;
1270 
1271  $labelStatus = $this->statuts[$status];
1272  $labelStatusShort = $this->statuts_short[$status];
1273 
1274  if ($status == self::STATUS_NOT_READ) {
1275  $statusType = 'status0';
1276  } elseif ($status == self::STATUS_READ) {
1277  $statusType = 'status1';
1278  } elseif ($status == self::STATUS_ASSIGNED) {
1279  $statusType = 'status2';
1280  } elseif ($status == self::STATUS_IN_PROGRESS) {
1281  $statusType = 'status4';
1282  } elseif ($status == self::STATUS_WAITING) {
1283  $statusType = 'status7';
1284  } elseif ($status == self::STATUS_NEED_MORE_INFO) {
1285  $statusType = 'status3';
1286  } elseif ($status == self::STATUS_CANCELED) {
1287  $statusType = 'status9';
1288  } elseif ($status == self::STATUS_CLOSED) {
1289  $statusType = 'status6';
1290  } else {
1291  $labelStatus = $langs->trans('Unknown');
1292  $labelStatusShort = $langs->trans('Unknown');
1293  $statusType = 'status0';
1294  $mode = 0;
1295  }
1296 
1297  $params = array();
1298  if ($notooltip) {
1299  $params = array('tooltip' => 'no');
1300  }
1301 
1302  return dolGetStatus($langs->trans($labelStatus), $langs->trans($labelStatusShort), '', $statusType, $mode, '', $params);
1303  }
1304 
1305 
1316  public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
1317  {
1318  global $db, $conf, $langs;
1319  global $dolibarr_main_authentication, $dolibarr_main_demo;
1320  global $menumanager;
1321 
1322  if (!empty($conf->dol_no_mouse_hover)) $notooltip = 1; // Force disable tooltips
1323 
1324  $result = '';
1325 
1326  $label = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("Ticket").'</u>';
1327  $label .= ' '.$this->getLibStatut(4);
1328  $label .= '<br>';
1329  $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref.'<br>';
1330  $label .= '<b>'.$langs->trans('TicketTrackId').':</b> '.$this->track_id.'<br>';
1331  $label .= '<b>'.$langs->trans('Subject').':</b> '.$this->subject;
1332 
1333  $url = dol_buildpath('/ticket/card.php', 1).'?id='.$this->id;
1334 
1335  if ($option != 'nolink')
1336  {
1337  // Add param to save lastsearch_values or not
1338  $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1339  if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) $add_save_lastsearch_values = 1;
1340  if ($add_save_lastsearch_values) $url .= '&save_lastsearch_values=1';
1341  }
1342 
1343  $linkclose = '';
1344  if (empty($notooltip))
1345  {
1346  if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
1347  {
1348  $label = $langs->trans("ShowTicket");
1349  $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
1350  }
1351  $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
1352  $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
1353  } else $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1354 
1355  $linkstart = '<a href="'.$url.'"';
1356  $linkstart .= $linkclose.'>';
1357  $linkend = '</a>';
1358 
1359  $result .= $linkstart;
1360  if ($withpicto) $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
1361  if ($withpicto != 2) $result .= $this->ref;
1362  $result .= $linkend;
1363  //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
1364 
1365  return $result;
1366  }
1367 
1368 
1376  public function markAsRead($user, $notrigger = 0)
1377  {
1378  global $conf, $langs;
1379 
1380  $error = 0;
1381 
1382  if ($this->statut != self::STATUS_CANCELED) { // no closed
1383  $this->db->begin();
1384 
1385  $sql = "UPDATE ".MAIN_DB_PREFIX."ticket";
1386  $sql .= " SET fk_statut = ".Ticket::STATUS_READ.", date_read='".$this->db->idate(dol_now())."'";
1387  $sql .= " WHERE rowid = ".$this->id;
1388 
1389  dol_syslog(get_class($this)."::markAsRead");
1390  $resql = $this->db->query($sql);
1391  if ($resql) {
1392  $this->actionmsg = $langs->trans('TicketLogMesgReadBy', $this->ref, $user->getFullName($langs));
1393  $this->actionmsg2 = $langs->trans('TicketLogMesgReadBy', $this->ref, $user->getFullName($langs));
1394 
1395  if (!$error && !$notrigger) {
1396  // Call trigger
1397  $result = $this->call_trigger('TICKET_MODIFY', $user);
1398  if ($result < 0) {
1399  $error++;
1400  }
1401  // End call triggers
1402  }
1403 
1404  if (!$error) {
1405  $this->db->commit();
1406  return 1;
1407  } else {
1408  $this->db->rollback();
1409  $this->error = join(',', $this->errors);
1410  dol_syslog(get_class($this)."::markAsRead ".$this->error, LOG_ERR);
1411  return -1;
1412  }
1413  } else {
1414  $this->db->rollback();
1415  $this->error = $this->db->lasterror();
1416  dol_syslog(get_class($this)."::markAsRead ".$this->error, LOG_ERR);
1417  return -1;
1418  }
1419  }
1420  }
1421 
1430  public function assignUser($user, $id_assign_user, $notrigger = 0)
1431  {
1432  global $conf, $langs;
1433 
1434  $error = 0;
1435  $this->db->begin();
1436 
1437  $this->oldcopy = dol_clone($this);
1438 
1439  $sql = "UPDATE ".MAIN_DB_PREFIX."ticket";
1440  if ($id_assign_user > 0)
1441  {
1442  $sql .= " SET fk_user_assign=".$id_assign_user.", fk_statut = ".Ticket::STATUS_ASSIGNED;
1443  } else {
1444  $sql .= " SET fk_user_assign=null, fk_statut = ".Ticket::STATUS_READ;
1445  }
1446  $sql .= " WHERE rowid = ".$this->id;
1447 
1448  dol_syslog(get_class($this)."::assignUser sql=".$sql);
1449  $resql = $this->db->query($sql);
1450  if ($resql)
1451  {
1452  $this->fk_user_assign = $id_assign_user; // May be used by trigger
1453 
1454  if (!$notrigger) {
1455  // Call trigger
1456  $result = $this->call_trigger('TICKET_ASSIGNED', $user);
1457  if ($result < 0) {
1458  $error++;
1459  }
1460  // End call triggers
1461  }
1462 
1463  if (!$error) {
1464  $this->db->commit();
1465  return 1;
1466  } else {
1467  $this->db->rollback();
1468  $this->error = join(',', $this->errors);
1469  dol_syslog(get_class($this)."::assignUser ".$this->error, LOG_ERR);
1470  return -1;
1471  }
1472  } else {
1473  $this->db->rollback();
1474  $this->error = $this->db->lasterror();
1475  dol_syslog(get_class($this)."::assignUser ".$this->error, LOG_ERR);
1476  return -1;
1477  }
1478  }
1479 
1480 
1488  private function sendLogByEmail($user, $message)
1489  {
1490  global $conf, $langs;
1491 
1492  $nb_sent = 0;
1493 
1494  $langs->load('ticket');
1495 
1496  // Retrieve email of all contacts (internal and external)
1497  $contacts = $this->listeContact(-1, 'internal');
1498  $contacts = array_merge($contacts, $this->listeContact(-1, 'external'));
1499 
1500  /* If origin_email and no socid, we add email to the list * */
1501  if (!empty($this->origin_email) && empty($this->fk_soc)) {
1502  $array_ext = array(array('firstname' => '', 'lastname' => '', 'email' => $this->origin_email, 'libelle' => $langs->transnoentities('TicketEmailOriginIssuer'), 'socid' => "-1"));
1503  $contacts = array_merge($contacts, $array_ext);
1504  }
1505 
1506  if (!empty($this->fk_soc)) {
1507  $this->fetch_thirdparty($this->fk_soc);
1508  $array_company = array(array('firstname' => '', 'lastname' => $this->client->name, 'email' => $this->client->email, 'libelle' => $langs->transnoentities('Customer'), 'socid' => $this->client->id));
1509  $contacts = array_merge($contacts, $array_company);
1510  }
1511 
1512  // foreach contact send email with notification message
1513  if (count($contacts) > 0) {
1514  foreach ($contacts as $key => $info_sendto) {
1515  $message = '';
1516  $subject = '['.$conf->global->MAIN_INFO_SOCIETE_NOM.'] '.$langs->transnoentities('TicketNotificationEmailSubject', $this->track_id);
1517  $message .= $langs->transnoentities('TicketNotificationEmailBody', $this->track_id)."\n\n";
1518  $message .= $langs->transnoentities('Title').' : '.$this->subject."\n";
1519 
1520  $recipient_name = dolGetFirstLastname($info_sendto['firstname'], $info_sendto['lastname'], '-1');
1521  $recipient = (!empty($recipient_name) ? $recipient_name : $info_sendto['email']).' ('.strtolower($info_sendto['libelle']).')';
1522  $message .= $langs->transnoentities('TicketNotificationRecipient').' : '.$recipient."\n";
1523  $message .= "\n";
1524  $message .= '* '.$langs->transnoentities('TicketNotificationLogMessage').' *'."\n";
1525  $message .= dol_html_entity_decode($log_message, ENT_QUOTES | ENT_HTML5)."\n";
1526 
1527  if ($info_sendto['source'] == 'internal') {
1528  $url_internal_ticket = dol_buildpath('/ticket/card.php', 2).'?track_id='.$this->track_id;
1529  $message .= "\n".$langs->transnoentities('TicketNotificationEmailBodyInfosTrackUrlinternal').' : <a href="'.$url_internal_ticket.'">'.$this->track_id.'</a>'."\n";
1530  } else {
1531  $url_public_ticket = ($conf->global->TICKET_URL_PUBLIC_INTERFACE ? $conf->global->TICKET_URL_PUBLIC_INTERFACE.'/' : dol_buildpath('/public/ticket/view.php', 2)).'?track_id='.$this->track_id;
1532  $message .= "\n".$langs->transnoentities('TicketNewEmailBodyInfosTrackUrlCustomer').' : <a href="'.$url_public_ticket.'">'.$this->track_id.'</a>'."\n";
1533  }
1534 
1535  $message .= "\n";
1536  $message .= $langs->transnoentities('TicketEmailPleaseDoNotReplyToThisEmail')."\n";
1537 
1538  $from = $conf->global->MAIN_INFO_SOCIETE_NOM.'<'.$conf->global->TICKET_NOTIFICATION_EMAIL_FROM.'>';
1539  $replyto = $from;
1540 
1541  // Init to avoid errors
1542  $filepath = array();
1543  $filename = array();
1544  $mimetype = array();
1545 
1546  $message = dol_nl2br($message);
1547 
1548  if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
1549  $old_MAIN_MAIL_AUTOCOPY_TO = $conf->global->MAIN_MAIL_AUTOCOPY_TO;
1550  $conf->global->MAIN_MAIL_AUTOCOPY_TO = '';
1551  }
1552  include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
1553  $sendtocc = '';
1554  $deliveryreceipt = 0;
1555  $mailfile = new CMailFile($subject, $info_sendto['email'], $from, $message, $filepath, $mimetype, $filename, $sendtocc, '', $deliveryreceipt, 0);
1556  if ($mailfile->error || $mailfile->errors) {
1557  setEventMessages($mailfile->error, $mailfile->errors, 'errors');
1558  } else {
1559  $result = $mailfile->sendfile();
1560  if ($result > 0) {
1561  $nb_sent++;
1562  }
1563  }
1564  if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
1565  $conf->global->MAIN_MAIL_AUTOCOPY_TO = $old_MAIN_MAIL_AUTOCOPY_TO;
1566  }
1567  }
1568 
1569  setEventMessages($langs->trans('TicketNotificationNumberEmailSent', $nb_sent), null, 'mesgs');
1570  }
1571 
1572  return $nb_sent;
1573  }
1574 
1580  public function loadCacheLogsTicket()
1581  {
1582  global $langs;
1583 
1584  if (is_array($this->cache_logs_ticket) && count($this->cache_logs_ticket)) {
1585  return 0;
1586  }
1587  // Cache deja charge
1588 
1589  // TODO Read the table llx_actioncomm
1590  /*
1591  $sql = "SELECT rowid, fk_user_create, datec, message";
1592  $sql .= " FROM " . MAIN_DB_PREFIX . "ticket_logs";
1593  $sql .= " WHERE fk_track_id ='" . $this->db->escape($this->track_id) . "'";
1594  $sql .= " ORDER BY datec DESC";
1595 
1596  $resql = $this->db->query($sql);
1597  if ($resql) {
1598  $num = $this->db->num_rows($resql);
1599  $i = 0;
1600  while ($i < $num) {
1601  $obj = $this->db->fetch_object($resql);
1602  $this->cache_logs_ticket[$i]['id'] = $obj->rowid;
1603  $this->cache_logs_ticket[$i]['fk_user_create'] = $obj->fk_user_create;
1604  $this->cache_logs_ticket[$i]['datec'] = $this->db->jdate($obj->datec);
1605  $this->cache_logs_ticket[$i]['message'] = $obj->message;
1606  $i++;
1607  }
1608  return $num;
1609  } else {
1610  $this->error = "Error " . $this->db->lasterror();
1611  dol_syslog(get_class($this) . "::loadCacheLogsTicket " . $this->error, LOG_ERR);
1612  return -1;
1613  }*/
1614 
1615  return 0;
1616  }
1617 
1628  public function createTicketMessage($user, $notrigger = 0, $filename_list = array(), $mimetype_list = array(), $mimefilename_list = array())
1629  {
1630  global $conf, $langs;
1631  $error = 0;
1632 
1633  $now = dol_now();
1634 
1635  // Clean parameters
1636  if (isset($this->fk_track_id)) {
1637  $this->fk_track_id = trim($this->fk_track_id);
1638  }
1639 
1640  if (isset($this->message)) {
1641  $this->message = trim($this->message);
1642  }
1643 
1644  $this->db->begin();
1645 
1646  // Insert entry into agenda with code 'TICKET_MSG'
1647  include_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
1648  $actioncomm = new ActionComm($this->db);
1649  $actioncomm->type_code = 'AC_OTH';
1650  $actioncomm->code = 'TICKET_MSG';
1651  if ($this->private) {
1652  $actioncomm->code = 'TICKET_MSG_PRIVATE';
1653  }
1654  $actioncomm->socid = $this->socid;
1655  $actioncomm->label = $this->subject;
1656  $actioncomm->note_private = $this->message;
1657  $actioncomm->userassigned = array($user->id);
1658  $actioncomm->userownerid = $user->id;
1659  $actioncomm->datep = $now;
1660  $actioncomm->percentage = 100;
1661  $actioncomm->elementtype = 'ticket';
1662  $actioncomm->fk_element = $this->id;
1663 
1664  $attachedfiles = array();
1665  $attachedfiles['paths'] = $filename_list;
1666  $attachedfiles['names'] = $mimefilename_list;
1667  $attachedfiles['mimes'] = $mimetype_list;
1668  if (is_array($attachedfiles) && count($attachedfiles) > 0) {
1669  $actioncomm->attachedfiles = $attachedfiles;
1670  }
1671 
1672  if (!empty($mimefilename_list) && is_array($mimefilename_list))
1673  {
1674  $actioncomm->note_private = dol_concatdesc($actioncomm->note_private, "\n".$langs->transnoentities("AttachedFiles").': '.join(';', $mimefilename_list));
1675  }
1676 
1677  $actionid = $actioncomm->create($user);
1678  if ($actionid <= 0)
1679  {
1680  $error++;
1681  $this->error = $actioncomm->error;
1682  $this->errors = $actioncomm->errors;
1683  }
1684 
1685  // Commit or rollback
1686  if ($error) {
1687  $this->db->rollback();
1688  return -1 * $error;
1689  } else {
1690  $this->db->commit();
1691  return 1;
1692  }
1693  }
1694 
1700  public function loadCacheMsgsTicket()
1701  {
1702  if (is_array($this->cache_msgs_ticket) && count($this->cache_msgs_ticket)) {
1703  return 0;
1704  }
1705 
1706  // Cache already loaded
1707 
1708  $sql = "SELECT id as rowid, fk_user_author, datec, label, note as message, code";
1709  $sql .= " FROM ".MAIN_DB_PREFIX."actioncomm";
1710  $sql .= " WHERE fk_element = ".(int) $this->id;
1711  $sql .= " AND elementtype = 'ticket'";
1712  $sql .= " ORDER BY datec DESC";
1713 
1714  dol_syslog(get_class($this)."::load_cache_actions_ticket sql=".$sql, LOG_DEBUG);
1715  $resql = $this->db->query($sql);
1716  if ($resql) {
1717  $num = $this->db->num_rows($resql);
1718  $i = 0;
1719  while ($i < $num) {
1720  $obj = $this->db->fetch_object($resql);
1721  $this->cache_msgs_ticket[$i]['id'] = $obj->rowid;
1722  $this->cache_msgs_ticket[$i]['fk_user_author'] = $obj->fk_user_author;
1723  $this->cache_msgs_ticket[$i]['datec'] = $this->db->jdate($obj->datec);
1724  $this->cache_msgs_ticket[$i]['subject'] = $obj->label;
1725  $this->cache_msgs_ticket[$i]['message'] = $obj->message;
1726  $this->cache_msgs_ticket[$i]['private'] = ($obj->code == 'TICKET_MSG_PRIVATE' ? 1 : 0);
1727  $i++;
1728  }
1729  return $num;
1730  } else {
1731  $this->error = "Error ".$this->db->lasterror();
1732  dol_syslog(get_class($this)."::load_cache_actions_ticket ".$this->error, LOG_ERR);
1733  return -1;
1734  }
1735  }
1736 
1743  public function close(User $user)
1744  {
1745  global $conf, $langs;
1746 
1747  if ($this->fk_statut != Ticket::STATUS_CLOSED) { // not closed
1748  $this->db->begin();
1749 
1750  $sql = "UPDATE ".MAIN_DB_PREFIX."ticket";
1751  $sql .= " SET fk_statut=".Ticket::STATUS_CLOSED.", progress=100, date_close='".$this->db->idate(dol_now())."'";
1752  $sql .= " WHERE rowid = ".$this->id;
1753 
1754  dol_syslog(get_class($this)."::close sql=".$sql);
1755  $resql = $this->db->query($sql);
1756  if ($resql) {
1757  $error = 0;
1758 
1759  // Valid and close fichinter linked
1760  if (!empty($conf->ficheinter->enabled) && !empty($conf->global->WORKFLOW_TICKET_CLOSE_INTERVENTION)) {
1761  dol_syslog("We have closed the ticket, so we close all linked interventions");
1762  $this->fetchObjectLinked($this->id, $this->element, null, 'fichinter');
1763  if ($this->linkedObjectsIds)
1764  {
1765  foreach ($this->linkedObjectsIds['fichinter'] as $fichinter_id) {
1766  $fichinter = new Fichinter($this->db);
1767  $fichinter->fetch($fichinter_id);
1768  if ($fichinter->statut == 0) {
1769  $result = $fichinter->setValid($user);
1770  if (!$result) {
1771  $this->errors[] = $fichinter->error;
1772  $error++;
1773  }
1774  }
1775  if ($fichinter->statut < 3) {
1776  $result = $fichinter->setStatut(3);
1777  if (!$result) {
1778  $this->errors[] = $fichinter->error;
1779  $error++;
1780  }
1781  }
1782  }
1783  }
1784  }
1785 
1786  // Call trigger
1787  $result = $this->call_trigger('TICKET_CLOSE', $user);
1788  if ($result < 0) {
1789  $error++;
1790  }
1791  // End call triggers
1792 
1793  if (!$error) {
1794  $this->db->commit();
1795  return 1;
1796  } else {
1797  $this->db->rollback();
1798  $this->error = join(',', $this->errors);
1799  dol_syslog(get_class($this)."::close ".$this->error, LOG_ERR);
1800  return -1;
1801  }
1802  } else {
1803  $this->db->rollback();
1804  $this->error = $this->db->lasterror();
1805  dol_syslog(get_class($this)."::close ".$this->error, LOG_ERR);
1806  return -1;
1807  }
1808  }
1809  }
1810 
1820  public function searchSocidByEmail($email, $type = '0', $filters = array(), $clause = 'AND')
1821  {
1822  $thirdparties = array();
1823 
1824  // Generation requete recherche
1825  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."societe";
1826  $sql .= " WHERE entity IN (".getEntity('ticket', 1).")";
1827  if (!empty($type)) {
1828  if ($type == 1 || $type == 2) {
1829  $sql .= " AND client = ".$type;
1830  } elseif ($type == 3) {
1831  $sql .= " AND fournisseur = 1";
1832  }
1833  }
1834  if (!empty($email)) {
1835  if (!$exact) {
1836  if (preg_match('/^([\*])?[^*]+([\*])?$/', $email, $regs) && count($regs) > 1) {
1837  $email = str_replace('*', '%', $email);
1838  } else {
1839  $email = '%'.$email.'%';
1840  }
1841  }
1842  $sql .= " AND ";
1843  if (is_array($filters) && !empty($filters)) {
1844  $sql .= "(";
1845  }
1846 
1847  if (!$case) {
1848  $sql .= "email LIKE '".$this->db->escape($email)."'";
1849  } else {
1850  $sql .= "email LIKE BINARY '".$this->db->escape($email)."'";
1851  }
1852  }
1853  if (is_array($filters) && !empty($filters)) {
1854  foreach ($filters as $field => $value) {
1855  $sql .= " ".$clause." ".$field." LIKE BINARY '".$this->db->escape($value)."'";
1856  }
1857  if (!empty($email)) {
1858  $sql .= ")";
1859  }
1860  }
1861 
1862  $res = $this->db->query($sql);
1863  if ($res) {
1864  while ($rec = $this->db->fetch_array($res)) {
1865  $soc = new Societe($this->db);
1866  $soc->fetch($rec['rowid']);
1867  $thirdparties[] = $soc;
1868  }
1869 
1870  return $thirdparties;
1871  } else {
1872  $this->error = $this->db->error().' sql='.$sql;
1873  dol_syslog(get_class($this)."::searchSocidByEmail ".$this->error, LOG_ERR);
1874  return -1;
1875  }
1876  }
1877 
1886  public function searchContactByEmail($email, $socid = '', $case = '')
1887  {
1888  $contacts = array();
1889 
1890  // Generation requete recherche
1891  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."socpeople";
1892  $sql .= " WHERE entity IN (".getEntity('socpeople').")";
1893  if (!empty($socid)) {
1894  $sql .= " AND fk_soc='".$this->db->escape($socid)."'";
1895  }
1896 
1897  if (!empty($email)) {
1898  $sql .= " AND ";
1899 
1900  if (!$case) {
1901  $sql .= "email LIKE '".$this->db->escape($email)."'";
1902  } else {
1903  $sql .= "email LIKE BINARY '".$this->db->escape($email)."'";
1904  }
1905  }
1906 
1907  $res = $this->db->query($sql);
1908  if ($res) {
1909  while ($rec = $this->db->fetch_array($res)) {
1910  include_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
1911  $contactstatic = new Contact($this->db);
1912  $contactstatic->fetch($rec['rowid']);
1913  $contacts[] = $contactstatic;
1914  }
1915 
1916  return $contacts;
1917  } else {
1918  $this->error = $this->db->error().' sql='.$sql;
1919  dol_syslog(get_class($this)."::searchContactByEmail ".$this->error, LOG_ERR);
1920  return -1;
1921  }
1922  }
1923 
1930  public function setCustomer($id)
1931  {
1932  if ($this->id) {
1933  $sql = "UPDATE ".MAIN_DB_PREFIX."ticket";
1934  $sql .= " SET fk_soc = ".($id > 0 ? $id : "null");
1935  $sql .= " WHERE rowid = ".$this->id;
1936  dol_syslog(get_class($this).'::setCustomer sql='.$sql);
1937  $resql = $this->db->query($sql);
1938  if ($resql) {
1939  return 1;
1940  } else {
1941  return -1;
1942  }
1943  } else {
1944  return -1;
1945  }
1946  }
1947 
1954  public function setProgression($percent)
1955  {
1956  if ($this->id) {
1957  $sql = "UPDATE ".MAIN_DB_PREFIX."ticket";
1958  $sql .= " SET progress = ".($percent > 0 ? $percent : "null");
1959  $sql .= " WHERE rowid = ".$this->id;
1960  dol_syslog(get_class($this).'::set_progression sql='.$sql);
1961  $resql = $this->db->query($sql);
1962  if ($resql) {
1963  return 1;
1964  } else {
1965  return -1;
1966  }
1967  } else {
1968  return -1;
1969  }
1970  }
1971 
1979  public function setProject($projectid)
1980  {
1981  if (!$this->table_element) {
1982  dol_syslog(get_class($this)."::setProject was called on objet with property table_element not defined", LOG_ERR);
1983  return -1;
1984  }
1985 
1986  $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
1987  if ($projectid) {
1988  $sql .= ' SET fk_project = '.$projectid;
1989  } else {
1990  $sql .= ' SET fk_project = NULL';
1991  }
1992 
1993  $sql .= ' WHERE rowid = '.$this->id;
1994 
1995  dol_syslog(get_class($this)."::setProject sql=".$sql);
1996  if ($this->db->query($sql)) {
1997  $this->fk_project = $projectid;
1998  return 1;
1999  } else {
2000  dol_print_error($this->db);
2001  return -1;
2002  }
2003  }
2004 
2011  public function setContract($contractid)
2012  {
2013  if (!$this->table_element) {
2014  dol_syslog(get_class($this)."::setContract was called on objet with property table_element not defined", LOG_ERR);
2015  return -1;
2016  }
2017 
2018  $result = $this->add_object_linked('contrat', $contractid);
2019  if ($result) {
2020  $this->fk_contract = $contractid;
2021  return 1;
2022  } else {
2023  dol_print_error($this->db);
2024  return -1;
2025  }
2026  }
2027 
2028  /* gestion des contacts d'un ticket */
2029 
2035  public function getIdTicketInternalContact()
2036  {
2037  return $this->getIdContact('internal', 'SUPPORTTEC');
2038  }
2039 
2046  {
2047  return $this->listeContact(-1, 'internal');
2048  }
2049 
2055  public function getIdTicketCustomerContact()
2056  {
2057  return $this->getIdContact('external', 'SUPPORTCLI');
2058  }
2059 
2066  {
2067  return $this->listeContact(-1, 'external');
2068  }
2069 
2076  {
2077  return $this->getIdContact('internal', 'CONTRIBUTOR');
2078  }
2079 
2086  {
2087  return $this->getIdContact('external', 'CONTRIBUTOR');
2088  }
2089 
2095  public function getTicketAllContacts()
2096  {
2097  $array_contact = array();
2098 
2099  $array_contact = $this->getIdTicketInternalContact($exclude_self);
2100 
2101  $array_contact = array_merge($array_contact, $this->getIdTicketCustomerContact($exclude_self));
2102 
2103  $array_contact = array_merge($array_contact, $this->getIdTicketInternalInvolvedContact($exclude_self));
2104  $array_contact = array_merge($array_contact, $this->getIdTicketCustomerInvolvedContact($exclude_self));
2105 
2106  return $array_contact;
2107  }
2108 
2115  {
2116  $array_contact = array();
2117 
2118  $array_contact = array_merge($array_contact, $this->getIdTicketCustomerContact($exclude_self));
2119  $array_contact = array_merge($array_contact, $this->getIdTicketCustomerInvolvedContact($exclude_self));
2120 
2121  return $array_contact;
2122  }
2123 
2131  public function messageSend($subject, $texte)
2132  {
2133  global $conf, $langs, $mysoc, $dolibarr_main_url_root;
2134 
2135  $langs->load("other");
2136 
2137  dol_syslog(get_class($this)."::message_send action=$action, socid=$socid, texte=$texte, objet_type=$objet_type, objet_id=$objet_id, file=$file");
2138 
2139  $internal_contacts = $this->getIdContact('internal', 'SUPPORTTEC');
2140  $external_contacts = $this->getIdContact('external', 'SUPPORTTEC');
2141 
2142  if ($result) {
2143  $num = $this->db->num_rows($result);
2144  $i = 0;
2145  while ($i < $num) { // For each notification couple defined (third party/actioncode)
2146  $obj = $this->db->fetch_object($result);
2147 
2148  $sendto = $obj->firstname." ".$obj->lastname." <".$obj->email.">";
2149  $actiondefid = $obj->adid;
2150 
2151  if (dol_strlen($sendto))
2152  {
2153  include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
2154  $application = ($conf->global->MAIN_APPLICATION_TITLE ? $conf->global->MAIN_APPLICATION_TITLE : 'Dolibarr ERP/CRM');
2155 
2156  $subject = '['.$application.'] '.$langs->transnoentitiesnoconv("DolibarrNotification");
2157 
2158  $message = $langs->transnoentities("YouReceiveMailBecauseOfNotification", $application, $mysoc->name)."\n";
2159  $message .= $langs->transnoentities("YouReceiveMailBecauseOfNotification2", $application, $mysoc->name)."\n";
2160  $message .= "\n";
2161  $message .= $texte;
2162  // Add link
2163  $link = '';
2164  switch ($objet_type) {
2165  case 'ficheinter':
2166  $link = '/fichinter/card.php?id='.$objet_id;
2167  break;
2168  case 'propal':
2169  $link = '/comm/propal.php?id='.$objet_id;
2170  break;
2171  case 'facture':
2172  $link = '/compta/facture/card.php?facid='.$objet_id;
2173  break;
2174  case 'order':
2175  $link = '/commande/card.php?facid='.$objet_id;
2176  break;
2177  case 'order_supplier':
2178  $link = '/fourn/commande/card.php?facid='.$objet_id;
2179  break;
2180  }
2181  // Define $urlwithroot
2182  $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
2183  $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
2184  //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
2185  if ($link) {
2186  $message .= "\n".$urlwithroot.$link;
2187  }
2188 
2189  $filename = basename($file);
2190 
2191  $mimefile = dol_mimetype($file);
2192 
2193  $msgishtml = 0;
2194 
2195  $replyto = $conf->notification->email_from;
2196 
2197  $message = dol_nl2br($message);
2198 
2199  if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
2200  $old_MAIN_MAIL_AUTOCOPY_TO = $conf->global->MAIN_MAIL_AUTOCOPY_TO;
2201  $conf->global->MAIN_MAIL_AUTOCOPY_TO = '';
2202  }
2203  $mailfile = new CMailFile(
2204  $subject,
2205  $sendto,
2206  $replyto,
2207  $message,
2208  array($file),
2209  array($mimefile),
2210  array($filename[count($filename) - 1]),
2211  '',
2212  '',
2213  0,
2214  $msgishtml
2215  );
2216 
2217  if ($mailfile->sendfile()) {
2218  $now = dol_now();
2219  $sendto = htmlentities($sendto);
2220 
2221  $sql = "INSERT INTO ".MAIN_DB_PREFIX."notify (daten, fk_action, fk_contact, objet_type, objet_id, email)";
2222  $sql .= " VALUES ('".$this->db->idate($now)."', ".$actiondefid.", ".$obj->cid.", '".$this->db->escape($objet_type)."', ".$objet_id.", '".$this->db->escape($obj->email)."')";
2223  dol_syslog("Notify::send sql=".$sql);
2224  if (!$this->db->query($sql)) {
2225  dol_print_error($this->db);
2226  }
2227  } else {
2228  $this->error = $mailfile->error;
2229  //dol_syslog("Notify::send ".$this->error, LOG_ERR);
2230  }
2231  if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
2232  $conf->global->MAIN_MAIL_AUTOCOPY_TO = $old_MAIN_MAIL_AUTOCOPY_TO;
2233  }
2234  }
2235  $i++;
2236  }
2237  return $i;
2238  } else {
2239  $this->error = $this->db->error();
2240  return -1;
2241  }
2242  }
2243 
2254  public function listeContact($status = -1, $source = 'external', $list = 0, $code = '')
2255  {
2256  global $langs;
2257 
2258  $tab = array();
2259 
2260  $sql = "SELECT ec.rowid, ec.statut as statuslink, ec.fk_socpeople as id, ec.fk_c_type_contact"; // This field contains id of llx_socpeople or id of llx_user
2261  if ($source == 'internal') {
2262  $sql .= ", '-1' as socid, t.statut as statuscontact";
2263  }
2264 
2265  if ($source == 'external' || $source == 'thirdparty') {
2266  $sql .= ", t.fk_soc as socid, t.statut as statuscontact";
2267  }
2268 
2269  $sql .= ", t.civility, t.lastname as lastname, t.firstname, t.email";
2270  if ($source == 'internal') {
2271  $sql .= ", t.office_phone as phone, t.user_mobile as phone_mobile";
2272  }
2273 
2274  if ($source == 'external') {
2275  $sql .= ", t.phone as phone, t.phone_mobile as phone_mobile, t.phone_perso as phone_perso";
2276  }
2277 
2278  $sql .= ", tc.source, tc.element, tc.code, tc.libelle as type_contact_label";
2279  $sql .= " FROM ".MAIN_DB_PREFIX."c_type_contact tc";
2280  $sql .= ", ".MAIN_DB_PREFIX."element_contact ec";
2281  if ($source == 'internal') {
2282  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user t on ec.fk_socpeople = t.rowid";
2283  }
2284 
2285  if ($source == 'external' || $source == 'thirdparty') {
2286  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."socpeople t on ec.fk_socpeople = t.rowid";
2287  }
2288 
2289  $sql .= " WHERE ec.element_id =".$this->id;
2290  $sql .= " AND ec.fk_c_type_contact=tc.rowid";
2291  $sql .= " AND tc.element='".$this->db->escape($this->element)."'";
2292  if ($source == 'internal') {
2293  $sql .= " AND tc.source = 'internal'";
2294  }
2295 
2296  if ($source == 'external' || $source == 'thirdparty') {
2297  $sql .= " AND tc.source = 'external'";
2298  }
2299 
2300  $sql .= " AND tc.active=1";
2301  if ($status >= 0) {
2302  $sql .= " AND ec.statut = ".((int) $status);
2303  }
2304 
2305  $sql .= " ORDER BY t.lastname ASC";
2306 
2307  $resql = $this->db->query($sql);
2308  if ($resql) {
2309  $num = $this->db->num_rows($resql);
2310  $i = 0;
2311  while ($i < $num) {
2312  $obj = $this->db->fetch_object($resql);
2313 
2314  if (!$list) {
2315  $transkey = "TypeContact_".$obj->element."_".$obj->source."_".$obj->code;
2316  $libelle_type = ($langs->trans($transkey) != $transkey ? $langs->trans($transkey) : $obj->type_contact_label);
2317  $tab[$i] = array(
2318  'source' => $obj->source,
2319  'socid' => $obj->socid,
2320  'id' => $obj->id,
2321  'nom' => $obj->lastname, // For backward compatibility
2322  'civility' => $obj->civility,
2323  'lastname' => $obj->lastname,
2324  'firstname' => $obj->firstname,
2325  'email' => $obj->email,
2326  'rowid' => $obj->rowid,
2327  'code' => $obj->code,
2328  'libelle' => $libelle_type,
2329  'status' => $obj->statuslink,
2330  'statuscontact'=>$obj->statuscontact,
2331  'fk_c_type_contact' => $obj->fk_c_type_contact,
2332  'phone' => $obj->phone,
2333  'phone_mobile' => $obj->phone_mobile);
2334  } else {
2335  $tab[$i] = $obj->id;
2336  }
2337 
2338  $i++;
2339  }
2340 
2341  return $tab;
2342  } else {
2343  $this->error = $this->db->error();
2344  dol_print_error($this->db);
2345  return -1;
2346  }
2347  }
2348 
2355  public function getDefaultRef($thirdparty = '')
2356  {
2357  global $conf;
2358 
2359  $defaultref = '';
2360  $modele = empty($conf->global->TICKET_ADDON) ? 'mod_ticket_simple' : $conf->global->TICKET_ADDON;
2361 
2362  // Search template files
2363  $file = '';
2364  $classname = '';
2365  $filefound = 0;
2366  $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
2367  foreach ($dirmodels as $reldir) {
2368  $file = dol_buildpath($reldir."core/modules/ticket/".$modele.'.php', 0);
2369  if (file_exists($file)) {
2370  $filefound = 1;
2371  $classname = $modele;
2372  break;
2373  }
2374  }
2375 
2376  if ($filefound) {
2377  $result = dol_include_once($reldir."core/modules/ticket/".$modele.'.php');
2378  $modTicket = new $classname;
2379 
2380  $defaultref = $modTicket->getNextValue($thirdparty, $this);
2381  }
2382 
2383  if (is_numeric($defaultref) && $defaultref <= 0) {
2384  $defaultref = '';
2385  }
2386 
2387  return $defaultref;
2388  }
2389 
2390 
2391  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2398  public function is_photo_available($sdir)
2399  {
2400  // phpcs:enable
2401  include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
2402 
2403  global $conf;
2404 
2405  $dir = $sdir.'/';
2406  $nbphoto = 0;
2407 
2408  $dir_osencoded = dol_osencode($dir);
2409  if (file_exists($dir_osencoded)) {
2410  $handle = opendir($dir_osencoded);
2411  if (is_resource($handle)) {
2412  while (($file = readdir($handle)) !== false) {
2413  if (!utf8_check($file)) {
2414  $file = utf8_encode($file);
2415  }
2416  // To be sure data is stored in UTF8 in memory
2417  if (dol_is_file($dir.$file)) {
2418  return true;
2419  }
2420  }
2421  }
2422  }
2423  return false;
2424  }
2425 
2426 
2434  public function copyFilesForTicket()
2435  {
2436  global $conf;
2437 
2438  // Create form object
2439  include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
2440  include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
2441  include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
2442 
2443  $maxwidthsmall = 270;
2444  $maxheightsmall = 150;
2445  $maxwidthmini = 128;
2446  $maxheightmini = 72;
2447 
2448  $formmail = new FormMail($this->db);
2449 
2450  $attachedfiles = $formmail->get_attached_files();
2451 
2452  $filepath = $attachedfiles['paths'];
2453  $filename = $attachedfiles['names'];
2454  $mimetype = $attachedfiles['mimes'];
2455 
2456  // Copy files into ticket directory
2457  $destdir = $conf->ticket->dir_output.'/'.$this->ref;
2458 
2459  if (!dol_is_dir($destdir)) {
2460  dol_mkdir($destdir);
2461  }
2462 
2463  $listofpaths = array();
2464  $listofnames = array();
2465  foreach ($filename as $i => $val) {
2466  $destfile = $destdir.'/'.$filename[$i];
2467  // If destination file already exists, we add a suffix to avoid to overwrite
2468  if (is_file($destfile))
2469  {
2470  $pathinfo = pathinfo($filename[$i]);
2471  $now = dol_now();
2472  $destfile = $destdir.'/'.$pathinfo['filename'].' - '.dol_print_date($now, 'dayhourlog').'.'.$pathinfo['extension'];
2473  }
2474 
2475  $res = dol_move($filepath[$i], $destfile, 0, 1);
2476 
2477  if (image_format_supported($destfile) == 1) {
2478  // Create small thumbs for image (Ratio is near 16/9)
2479  // Used on logon for example
2480  $imgThumbSmall = vignette($destfile, $maxwidthsmall, $maxheightsmall, '_small', 50, "thumbs");
2481  // Create mini thumbs for image (Ratio is near 16/9)
2482  // Used on menu or for setup page for example
2483  $imgThumbMini = vignette($destfile, $maxwidthmini, $maxheightmini, '_mini', 50, "thumbs");
2484  }
2485 
2486  $formmail->remove_attached_files($i);
2487 
2488  // Fill array with new names
2489  $listofpaths[$i] = $destfile;
2490  $listofnames[$i] = basename($destfile);
2491  }
2492 
2493  return array('listofpaths'=>$listofpaths, 'listofnames'=>$listofnames, 'listofmimes'=>$mimetype);
2494  }
2495 
2496 
2506  public function newMessage($user, &$action, $private = 1, $public_area = 0)
2507  {
2508  global $mysoc, $conf, $langs;
2509 
2510  $error = 0;
2511 
2512  $object = new Ticket($this->db);
2513 
2514  $ret = $object->fetch('', '', GETPOST('track_id', 'alpha'));
2515 
2516  $object->socid = $object->fk_soc;
2517  $object->fetch_thirdparty();
2518 
2519  if ($ret < 0) {
2520  $error++;
2521  array_push($this->errors, $langs->trans("ErrorTicketIsNotValid"));
2522  $action = '';
2523  }
2524 
2525  if (!GETPOST("message")) {
2526  $error++;
2527  array_push($this->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("message")));
2528  $action = 'add_message';
2529  }
2530 
2531  if (!$error) {
2532  $object->subject = GETPOST('subject', 'alphanohtml');
2533  $object->message = GETPOST("message", "restricthtml");
2534  $object->private = GETPOST("private_message", "alpha");
2535 
2536  $send_email = GETPOST('send_email', 'int');
2537 
2538  // Copy attached files (saved into $_SESSION) as linked files to ticket. Return array with final name used.
2539  $resarray = $object->copyFilesForTicket();
2540 
2541  $listofpaths = $resarray['listofpaths'];
2542  $listofnames = $resarray['listofnames'];
2543  $listofmimes = $resarray['listofmimes'];
2544 
2545  $id = $object->createTicketMessage($user, 0, $listofpaths, $listofmimes, $listofnames);
2546  if ($id <= 0) {
2547  $error++;
2548  $this->error = $object->error;
2549  $this->errors = $object->errors;
2550  $action = 'add_message';
2551  }
2552 
2553  if (!$error && $id > 0) {
2554  setEventMessages($langs->trans('TicketMessageSuccessfullyAdded'), null, 'mesgs');
2555 
2556  //var_dump($_SESSION); var_dump($listofpaths);exit;
2557 
2558  /*
2559  * Public area
2560  */
2561  if (!empty($public_area)) {
2562  /*
2563  * Send emails to assigned users (public area notification)
2564  */
2565  if (!empty($conf->global->TICKET_PUBLIC_NOTIFICATION_NEW_MESSAGE_ENABLED)) {
2566  $assigned_user_dont_have_email = '';
2567  $sendto = array();
2568  if ($this->fk_user_assign > 0) {
2569  $assigned_user = new User($this->db);
2570  $assigned_user->fetch($this->fk_user_assign);
2571  if (!empty($assigned_user->email)) {
2572  $sendto[] = $assigned_user->getFullName($langs)." <".$assigned_user->email.">";
2573  } else {
2574  $assigned_user_dont_have_email = $assigned_user->getFullName($langs);
2575  }
2576  }
2577  if (empty($sendto)) {
2578  if (!empty($conf->global->TICKET_PUBLIC_NOTIFICATION_NEW_MESSAGE_DEFAULT_EMAIL)) {
2579  $sendto[] = $conf->global->TICKET_PUBLIC_NOTIFICATION_NEW_MESSAGE_DEFAULT_EMAIL;
2580  } elseif (!empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO)) {
2581  $sendto[] = $conf->global->TICKET_NOTIFICATION_EMAIL_TO;
2582  }
2583  }
2584 
2585  // Add global email address recipient
2586  if (!empty($conf->global->TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS) &&
2587  !empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO) && !in_array($conf->global->TICKET_NOTIFICATION_EMAIL_TO, $sendto)
2588  ) {
2589  $sendto[] = $conf->global->TICKET_NOTIFICATION_EMAIL_TO;
2590  }
2591 
2592  if (!empty($sendto)) {
2593  $label_title = empty($conf->global->MAIN_APPLICATION_TITLE) ? $mysoc->name : $conf->global->MAIN_APPLICATION_TITLE;
2594  $subject = '['.$label_title.'- ticket #'.$object->track_id.'] '.$langs->trans('TicketNewMessage');
2595 
2596  // Message send
2597  $message = $langs->trans('TicketMessageMailIntroText');
2598  $message .= '<br><br>';
2599  $messagePost = GETPOST('message', 'restricthtml');
2600  if (!dol_textishtml($messagePost)) {
2601  $messagePost = dol_nl2br($messagePost);
2602  }
2603  $message .= $messagePost;
2604 
2605  // Customer company infos
2606  $message .= '<br><br>';
2607  $message .= "==============================================";
2608  $message .= !empty($object->thirdparty->name) ? '<br>'.$langs->trans('Thirdparty')." : ".$object->thirdparty->name : '';
2609  $message .= !empty($object->thirdparty->town) ? '<br>'.$langs->trans('Town')." : ".$object->thirdparty->town : '';
2610  $message .= !empty($object->thirdparty->phone) ? '<br>'.$langs->trans('Phone')." : ".$object->thirdparty->phone : '';
2611 
2612  // Email send to
2613  $message .= '<br><br>';
2614  if (!empty($assigned_user_dont_have_email)) {
2615  $message .= '<br>'.$langs->trans('NoEMail').' : '.$assigned_user_dont_have_email;
2616  }
2617  foreach ($sendto as $val) {
2618  $message .= '<br>'.$langs->trans('TicketNotificationRecipient').' : '.$val;
2619  }
2620 
2621  // URL ticket
2622  $url_internal_ticket = dol_buildpath('/ticket/card.php', 2).'?track_id='.$object->track_id;
2623  $message .= '<br><br>';
2624  $message .= $langs->trans('TicketNotificationEmailBodyInfosTrackUrlinternal').' : <a href="'.$url_internal_ticket.'">'.$object->track_id.'</a>';
2625 
2626  $this->sendTicketMessageByEmail($subject, $message, '', $sendto, $listofpaths, $listofmimes, $listofnames);
2627  }
2628  }
2629  }
2630  /*
2631  * Private area
2632  */
2633  else {
2634  /*
2635  * Send emails to internal users (linked contacts)
2636  */
2637  if ($send_email > 0) {
2638  // Retrieve internal contact datas
2639  $internal_contacts = $object->getInfosTicketInternalContact();
2640 
2641  $sendto = array();
2642  if (is_array($internal_contacts) && count($internal_contacts) > 0) {
2643  // altairis: set default subject
2644  $label_title = empty($conf->global->MAIN_APPLICATION_TITLE) ? $mysoc->name : $conf->global->MAIN_APPLICATION_TITLE;
2645  $subject = GETPOST('subject', 'nohtml') ? GETPOST('subject', 'nohtml') : '['.$label_title.'- ticket #'.$object->track_id.'] '.$langs->trans('TicketNewMessage');
2646 
2647  $message_intro = $langs->trans('TicketNotificationEmailBody', "#".$object->id);
2648  $message_signature = GETPOST('mail_signature') ? GETPOST('mail_signature') : $conf->global->TICKET_MESSAGE_MAIL_SIGNATURE;
2649 
2650  $message = $langs->trans('TicketMessageMailIntroText');
2651  $message .= '<br><br>';
2652  $messagePost = GETPOST('message', 'restricthtml');
2653  if (!dol_textishtml($messagePost)) {
2654  $messagePost = dol_nl2br($messagePost);
2655  }
2656  $message .= $messagePost;
2657 
2658  // Coordonnées client
2659  $message .= '<br><br>';
2660  $message .= "==============================================<br>";
2661  $message .= !empty($object->thirdparty->name) ? $langs->trans('Thirdparty')." : ".$object->thirdparty->name : '';
2662  $message .= !empty($object->thirdparty->town) ? '<br>'.$langs->trans('Town')." : ".$object->thirdparty->town : '';
2663  $message .= !empty($object->thirdparty->phone) ? '<br>'.$langs->trans('Phone')." : ".$object->thirdparty->phone : '';
2664 
2665  // Build array to display recipient list
2666  foreach ($internal_contacts as $key => $info_sendto) {
2667  // altairis: avoid duplicate notifications
2668  if ($info_sendto['id'] == $user->id) {
2669  continue;
2670  }
2671 
2672  if ($info_sendto['email'] != '') {
2673  if (!empty($info_sendto['email'])) $sendto[] = trim($info_sendto['firstname']." ".$info_sendto['lastname'])." <".$info_sendto['email'].">";
2674 
2675  //Contact type
2676  $recipient = dolGetFirstLastname($info_sendto['firstname'], $info_sendto['lastname'], '-1').' ('.strtolower($info_sendto['libelle']).')';
2677  $message .= (!empty($recipient) ? $langs->trans('TicketNotificationRecipient').' : '.$recipient.'<br>' : '');
2678  }
2679  }
2680  $message .= '<br>';
2681  // URL ticket
2682  $url_internal_ticket = dol_buildpath('/ticket/card.php', 2).'?track_id='.$object->track_id;
2683 
2684  // altairis: make html link on url
2685  $message .= '<br>'.$langs->trans('TicketNotificationEmailBodyInfosTrackUrlinternal').' : <a href="'.$url_internal_ticket.'">'.$object->track_id.'</a><br>';
2686 
2687  // Add global email address recipient
2688  if ($conf->global->TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS && !in_array($conf->global->TICKET_NOTIFICATION_EMAIL_TO, $sendto)) {
2689  if (!empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO)) $sendto[] = $conf->global->TICKET_NOTIFICATION_EMAIL_TO;
2690  }
2691 
2692  // altairis: dont try to send email if no recipient
2693  if (!empty($sendto)) {
2694  $this->sendTicketMessageByEmail($subject, $message, '', $sendto, $listofpaths, $listofmimes, $listofnames);
2695  }
2696  }
2697 
2698  /*
2699  * Send emails for externals users if not private (linked contacts)
2700  */
2701  if (empty($object->private)) {
2702  // Retrieve email of all contacts (external)
2703  $external_contacts = $object->getInfosTicketExternalContact();
2704 
2705  // If no contact, get email from thirdparty
2706  if (is_array($external_contacts) && count($external_contacts) === 0) {
2707  if (!empty($object->fk_soc)) {
2708  $object->fetch_thirdparty($object->fk_soc);
2709  $array_company = array(array('firstname' => '', 'lastname' => $object->thirdparty->name, 'email' => $object->thirdparty->email, 'libelle' => $langs->transnoentities('Customer'), 'socid' => $object->thirdparty->id));
2710  $external_contacts = array_merge($external_contacts, $array_company);
2711  } elseif (empty($object->fk_soc) && !empty($object->origin_email)) {
2712  $array_external = array(array('firstname' => '', 'lastname' => $object->origin_email, 'email' => $object->thirdparty->email, 'libelle' => $langs->transnoentities('Customer'), 'socid' => $object->thirdparty->id));
2713  $external_contacts = array_merge($external_contacts, $array_external);
2714  }
2715  }
2716 
2717  $sendto = array();
2718  if (is_array($external_contacts) && count($external_contacts) > 0) {
2719  // altairis: get default subject for email to external contacts
2720  $label_title = empty($conf->global->MAIN_APPLICATION_TITLE) ? $mysoc->name : $conf->global->MAIN_APPLICATION_TITLE;
2721  $subject = GETPOST('subject') ? GETPOST('subject') : '['.$label_title.'- ticket #'.$object->track_id.'] '.$langs->trans('TicketNewMessage');
2722 
2723  $message_intro = GETPOST('mail_intro') ? GETPOST('mail_intro', 'restricthtml') : $conf->global->TICKET_MESSAGE_MAIL_INTRO;
2724  $message_signature = GETPOST('mail_signature') ? GETPOST('mail_signature', 'restricthtml') : $conf->global->TICKET_MESSAGE_MAIL_SIGNATURE;
2725  if (!dol_textishtml($message_intro)) {
2726  $message_intro = dol_nl2br($message_intro);
2727  }
2728  if (!dol_textishtml($message_signature)) {
2729  $message_signature = dol_nl2br($message_signature);
2730  }
2731 
2732  // We put intro after
2733  $messagePost = GETPOST('message', 'restricthtml');
2734  if (!dol_textishtml($messagePost)) {
2735  $messagePost = dol_nl2br($messagePost);
2736  }
2737  $message = $messagePost;
2738  $message .= '<br><br>';
2739 
2740  foreach ($external_contacts as $key => $info_sendto) {
2741  // altairis: avoid duplicate emails to external contacts
2742  if ($info_sendto['id'] == $user->contact_id) {
2743  continue;
2744  }
2745 
2746  if ($info_sendto['email'] != '' && $info_sendto['email'] != $object->origin_email) {
2747  if (!empty($info_sendto['email'])) $sendto[] = trim($info_sendto['firstname']." ".$info_sendto['lastname'])." <".$info_sendto['email'].">";
2748 
2749  $recipient = dolGetFirstLastname($info_sendto['firstname'], $info_sendto['lastname'], '-1').' ('.strtolower($info_sendto['libelle']).')';
2750  $message .= (!empty($recipient) ? $langs->trans('TicketNotificationRecipient').' : '.$recipient.'<br>' : '');
2751  }
2752  }
2753 
2754  // If public interface is not enable, use link to internal page into mail
2755  $url_public_ticket = (!empty($conf->global->TICKET_ENABLE_PUBLIC_INTERFACE) ?
2756  (!empty($conf->global->TICKET_URL_PUBLIC_INTERFACE) ? $conf->global->TICKET_URL_PUBLIC_INTERFACE.'/view.php' : dol_buildpath('/public/ticket/view.php', 2)) : dol_buildpath('/ticket/card.php', 2)).'?track_id='.$object->track_id;
2757  $message .= '<br>'.$langs->trans('TicketNewEmailBodyInfosTrackUrlCustomer').' : <a href="'.$url_public_ticket.'">'.$object->track_id.'</a><br>';
2758 
2759  // Build final message
2760  $message = $message_intro.'<br><br>'.$message;
2761 
2762  // Add signature
2763  $message .= '<br>'.$message_signature;
2764 
2765  if (!empty($object->origin_email)) {
2766  $sendto[] = $object->origin_email;
2767  }
2768 
2769  if ($object->fk_soc > 0 && !in_array($object->origin_email, $sendto)) {
2770  $object->socid = $object->fk_soc;
2771  $object->fetch_thirdparty();
2772  if (!empty($object->thirdparty->email)) $sendto[] = $object->thirdparty->email;
2773  }
2774 
2775  // altairis: Add global email address reciepient
2776  if ($conf->global->TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS && !in_array($conf->global->TICKET_NOTIFICATION_EMAIL_TO, $sendto)) {
2777  if (!empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO)) $sendto[] = $conf->global->TICKET_NOTIFICATION_EMAIL_TO;
2778  }
2779 
2780  // altairis: dont try to send email when no recipient
2781  if (!empty($sendto)) {
2782  $this->sendTicketMessageByEmail($subject, $message, '', $sendto, $listofpaths, $listofmimes, $listofnames);
2783  }
2784  }
2785  }
2786  }
2787  }
2788 
2789  // Set status to "answered" if not set yet, but only if internal user
2790  if ($object->fk_statut < 3 && !$user->socid)
2791  {
2792  $object->setStatut(3);
2793  }
2794 
2795  return 1;
2796  } else {
2797  setEventMessages($object->error, $object->errors, 'errors');
2798  return -1;
2799  }
2800  } else {
2801  setEventMessages($this->error, $this->errors, 'errors');
2802  return -1;
2803  }
2804  }
2805 
2806 
2819  public function sendTicketMessageByEmail($subject, $message, $send_internal_cc = 0, $array_receiver = array(), $filename_list = array(), $mimetype_list = array(), $mimefilename_list = array())
2820  {
2821  global $conf, $langs;
2822 
2823  if ($conf->global->TICKET_DISABLE_ALL_MAILS) {
2824  dol_syslog(get_class($this).'::sendTicketMessageByEmail: Emails are disable into ticket setup by option TICKET_DISABLE_ALL_MAILS', LOG_WARNING);
2825  return '';
2826  }
2827 
2828  $langs->load("mails");
2829 
2830  include_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
2831  //$contactstatic = new Contact($this->db);
2832 
2833  // If no receiver defined, load all ticket linked contacts
2834  if (!is_array($array_receiver) || !count($array_receiver) > 0) {
2835  $array_receiver = $this->getInfosTicketInternalContact();
2836  $array_receiver = array_merge($array_receiver, $this->getInfosTicketExternalContact());
2837  }
2838 
2839  if ($send_internal_cc) {
2840  $sendtocc = $conf->global->TICKET_NOTIFICATION_EMAIL_FROM;
2841  }
2842 
2843  $from = $conf->global->TICKET_NOTIFICATION_EMAIL_FROM;
2844  if (is_array($array_receiver) && count($array_receiver) > 0) {
2845  foreach ($array_receiver as $key => $receiver)
2846  {
2847  $deliveryreceipt = 0;
2848  $filepath = $filename_list;
2849  $filename = $mimefilename_list;
2850  $mimetype = $mimetype_list;
2851 
2852  // Envoi du mail
2853  if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
2854  $old_MAIN_MAIL_AUTOCOPY_TO = $conf->global->MAIN_MAIL_AUTOCOPY_TO;
2855  $conf->global->MAIN_MAIL_AUTOCOPY_TO = '';
2856  }
2857  include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
2858  $trackid = "tic".$this->id;
2859  $mailfile = new CMailFile($subject, $receiver, $from, $message, $filepath, $mimetype, $filename, $sendtocc, '', $deliveryreceipt, -1, '', '', $trackid, '', 'ticket');
2860  if ($mailfile->error) {
2861  setEventMessages($mailfile->error, null, 'errors');
2862  } else {
2863  $result = $mailfile->sendfile();
2864  if ($result) {
2865  setEventMessages($langs->trans('MailSuccessfulySent', $mailfile->getValidAddress($from, 2), $mailfile->getValidAddress($receiver, 2)), null, 'mesgs');
2866  } else {
2867  $langs->load("other");
2868  if ($mailfile->error) {
2869  setEventMessages($langs->trans('ErrorFailedToSendMail', $from, $receiver), null, 'errors');
2870  dol_syslog($langs->trans('ErrorFailedToSendMail', $from, $receiver).' : '.$mailfile->error);
2871  } else {
2872  setEventMessages('No mail sent. Feature is disabled by option MAIN_DISABLE_ALL_MAILS', null, 'errors');
2873  }
2874  }
2875  }
2876  if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
2877  $conf->global->MAIN_MAIL_AUTOCOPY_TO = $old_MAIN_MAIL_AUTOCOPY_TO;
2878  }
2879  }
2880  } else {
2881  $langs->load("other");
2882  setEventMessages($langs->trans('ErrorMailRecipientIsEmptyForSendTicketMessage'), null, 'warnings');
2883  }
2884  }
2885 
2886  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2894  public function load_board($user, $mode)
2895  {
2896  // phpcs:enable
2897  global $conf, $user, $langs;
2898 
2899  $now = dol_now();
2900 
2901  $this->nbtodo = $this->nbtodolate = 0;
2902  $clause = " WHERE";
2903 
2904  $sql = "SELECT p.rowid, p.ref, p.datec as datec";
2905  $sql .= " FROM ".MAIN_DB_PREFIX."ticket as p";
2906  if (!$user->rights->societe->client->voir && !$user->socid)
2907  {
2908  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON p.fk_soc = sc.fk_soc";
2909  $sql .= " WHERE sc.fk_user = ".$user->id;
2910  $clause = " AND";
2911  }
2912  $sql .= $clause." p.entity IN (".getEntity('ticket').")";
2913  if ($mode == 'opened') $sql .= " AND p.fk_statut NOT IN (".Ticket::STATUS_CLOSED.", ".Ticket::STATUS_CANCELED.")";
2914  if ($user->socid) $sql .= " AND p.fk_soc = ".$user->socid;
2915 
2916  $resql = $this->db->query($sql);
2917  if ($resql)
2918  {
2919  $label = $labelShort = '';
2920  $status = '';
2921  if ($mode == 'opened') {
2922  $status = 'openall';
2923  //$delay_warning = $conf->ticket->warning_delay;
2924  $delay_warning = 0;
2925  $label = $langs->trans("MenuListNonClosed");
2926  $labelShort = $langs->trans("MenuListNonClosed");
2927  }
2928 
2929  $response = new WorkboardResponse();
2930  //$response->warning_delay = $delay_warning / 60 / 60 / 24;
2931  $response->label = $label;
2932  $response->labelShort = $labelShort;
2933  $response->url = DOL_URL_ROOT.'/ticket/list.php?search_fk_statut[]='.$status;
2934  $response->img = img_object('', "ticket");
2935 
2936  // This assignment in condition is not a bug. It allows walking the results.
2937  while ($obj = $this->db->fetch_object($resql))
2938  {
2939  $response->nbtodo++;
2940  if ($mode == 'opened')
2941  {
2942  $datelimit = $this->db->jdate($obj->datefin);
2943  if ($datelimit < ($now - $delay_warning))
2944  {
2945  //$response->nbtodolate++;
2946  }
2947  }
2948  }
2949  return $response;
2950  } else {
2951  $this->error = $this->db->lasterror();
2952  return -1;
2953  }
2954  }
2955 
2956  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2962  public function load_state_board()
2963  {
2964  // phpcs:enable
2965  global $conf, $user;
2966 
2967  $this->nb = array();
2968  $clause = "WHERE";
2969 
2970  $sql = "SELECT count(p.rowid) as nb";
2971  $sql .= " FROM ".MAIN_DB_PREFIX."ticket as p";
2972  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON p.fk_soc = s.rowid";
2973  if (!$user->rights->societe->client->voir && !$user->socid)
2974  {
2975  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON s.rowid = sc.fk_soc";
2976  $sql .= " WHERE sc.fk_user = ".$user->id;
2977  $clause = "AND";
2978  }
2979  $sql .= " ".$clause." p.entity IN (".getEntity('ticket').")";
2980 
2981  $resql = $this->db->query($sql);
2982  if ($resql)
2983  {
2984  // This assignment in condition is not a bug. It allows walking the results.
2985  while ($obj = $this->db->fetch_object($resql))
2986  {
2987  $this->nb["ticket"] = $obj->nb;
2988  }
2989  $this->db->free($resql);
2990  return 1;
2991  } else {
2992  dol_print_error($this->db);
2993  $this->error = $this->db->lasterror();
2994  return -1;
2995  }
2996  }
2997 
3006  public static function replaceThirdparty($db, $origin_id, $dest_id)
3007  {
3008  $tables = array('ticket');
3009 
3010  return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
3011  }
3012 }
3013 
3014 
3019 {
3024  public $rowid;
3025 
3029  public $id;
3030 
3034  public $ref;
3035 
3039  public $track_id;
3040 
3044  public $fk_soc;
3045 
3049  public $fk_project;
3050 
3055 
3060 
3065 
3069  public $subject;
3070 
3074  public $message;
3075 
3079  public $fk_statut;
3080 
3084  public $resolution;
3085 
3089  public $progress;
3090 
3094  public $timing;
3095 
3099  public $type_code;
3100 
3105 
3110 
3114  public $type_label;
3115 
3120 
3125 
3129  public $datec = '';
3130 
3134  public $date_read = '';
3135 
3139  public $date_close = '';
3140 }
if(!function_exists('dol_getprefix')) dol_include_once($relpath, $classname= '')
Make an include_once using default root and alternate root if it fails.
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
GETPOST($paramname, $check= 'alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setProject($projectid)
Link element with a project Override core function because of key name &#39;fk_project&#39; used for this mod...
vignette($file, $maxWidth=160, $maxHeight=120, $extName= '_small', $quality=50, $outdir= 'thumbs', $targetformat=0)
Create a thumbnail from an image file (Supported extensions are gif, jpg, png and bmp)...
Definition: images.lib.php:425
static selectarray($htmlname, $array, $id= '', $show_empty=0, $key_in_label=0, $value_as_key=0, $moreparam= '', $translate=0, $maxlen=0, $disabled=0, $sort= '', $morecss= '', $addjscombo=0, $moreparamonempty= '', $disablebademail=0, $nohtmlescape=0)
Return a HTML select string, built from an array of key+value.
Classe permettant la generation du formulaire html d&#39;envoi de mail unitaire Usage: $formail = new For...
LibStatut($status, $mode=0, $notooltip=0)
Return status label of object.
$subject
Ticket subject.
if(!empty($arrayfields['u.datec']['checked'])) print_liste_field_titre("DateCreationShort"u if(!empty($arrayfields['u.tms']['checked'])) print_liste_field_titre("DateModificationShort"u if(!empty($arrayfields['u.statut']['checked'])) print_liste_field_titre("Status"u statut
Definition: list.php:632
fetchAll($user, $sortorder= 'ASC', $sortfield= 't.datec', $limit= '', $offset=0, $arch= '', $filter= '')
Load all objects in memory from database.
load_board($user, $mode)
Load indicators for dashboard (this-&gt;nbtodo and this-&gt;nbtodolate)
markAsRead($user, $notrigger=0)
Mark a message as read.
getIdTicketCustomerInvolvedContact()
Return id des contacts clients des intervenants.
Class to manage agenda events (actions)
$email_from
Email from user.
$category_label
Category label.
messageSend($subject, $texte)
Send message.
Class to manage contact/addresses.
setProgression($percent)
Define progression of current ticket.
copyFilesForTicket()
Copy files defined into $_SESSION array into the ticket directory of attached files.
$origin_email
Person email who have create ticket.
dol_html_entity_decode($a, $b, $c= 'UTF-8', $keepsomeentities=0)
Replace html_entity_decode functions to manage errors.
Class to manage interventions.
dol_now($mode= 'auto')
Return date for now.
$fk_user_create
User id who have create ticket.
getInfosTicketExternalContact()
Retrieve informations about external contacts.
printSelectStatus($selected="")
print selected status
Class to manage Dolibarr users.
Definition: user.class.php:44
getInfosTicketInternalContact()
Retrieve informations about internal contacts.
listeContact($status=-1, $source= 'external', $list=0, $code= '')
Get array of all contacts for a ticket Override method of file commonobject.class.php to add phone number.
$severity_code
Severity code.
createTicketMessage($user, $notrigger=0, $filename_list=array(), $mimetype_list=array(), $mimefilename_list=array())
Add message into database.
is_photo_available($sdir)
Return if at least one photo is available.
dol_clone($object, $native=0)
Create a clone of instance of object (new instance with same value for properties) With native = 0: P...
update($user=0, $notrigger=0)
Update object into database.
loadCacheCategoriesTickets()
Charge dans cache la liste des catégories de tickets (paramétrable dans dictionnaire) ...
create($user, $notrigger=0)
Create object into database.
dol_nl2br($stringtoencode, $nl2brmode=0, $forxml=false)
Replace CRLF in string with a HTML BR tag.
$resolution
State resolution.
sendLogByEmail($user, $message)
Send notification of changes by email.
dol_is_dir($folder)
Test if filename is a directory.
Definition: files.lib.php:432
__construct($db)
Constructor.
$fk_project
Project ID.
$fk_user_assign
User id who have ticket assigned.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
$conf db
API class for accounts.
Definition: inc.php:54
$progress
Progress in percent.
Class to manage ticket.
image_format_supported($file, $acceptsvg=0)
Return if a filename is file name of a supported image format.
Definition: images.lib.php:39
$date_close
Close ticket date.
$severity_label
Severity label.
dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvirus=0, $indexdatabase=1)
Move a file into another name.
Definition: files.lib.php:817
insertExtraFields($trigger= '', $userused=null)
Add/Update all extra fields values for the current object.
fetch($id= '', $ref= '', $track_id= '', $email_msgid= '')
Load object in memory from the database.
close(User $user)
Close a ticket.
Ticket line Class.
Class to manage standard extra fields.
setEventMessages($mesg, $mesgs, $style= 'mesgs', $messagekey= '')
Set event messages in dol_events session object.
$category_label
Category label.
loadCacheLogsTicket()
Charge la liste des actions sur le ticket.
Class to manage third parties objects (customers, suppliers, prospects...)
$subject
var string Ticket subject
sendTicketMessageByEmail($subject, $message, $send_internal_cc=0, $array_receiver=array(), $filename_list=array(), $mimetype_list=array(), $mimefilename_list=array())
Send ticket by email to linked contacts.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
load_state_board()
Load indicator this-&gt;nb of global stats widget.
setCustomer($id)
Define parent commany of current ticket.
dol_mimetype($file, $default= 'application/octet-stream', $mode=0)
Return mime type of a file.
dol_strlen($string, $stringencoding= 'UTF-8')
Make a strlen call.
$date_read
Read date.
$fk_statut
Ticket statut.
$message
Ticket message.
getTicketAllCustomerContacts()
Return id of all contacts for ticket.
$timing
Duration for ticket.
Class to send emails (with attachments or not) Usage: $mailfile = new CMailFile($subject,$sendto,$replyto,$message,$filepath,$mimetype,$filename,$cc,$ccc,$deliveryreceipt,$msgishtml,$errors_to,$css,$trackid,$moreinheader,$sendcontext,$replyto); $mailfile-&gt;sendfile();.
static commonReplaceThirdparty(DoliDB $db, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
img_picto($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt= '', $morecss= '', $marginleftonlyshort=2)
Show picto whatever it&#39;s its name (generic function)
$type_code
Type code.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename= '', $restricttologhandler= '', $logcontext=null)
Write log message into outputs.
$type_label
Type label.
generate_random_id($car=16)
Generate a random id.
Definition: ticket.lib.php:180
img_object($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
$fields
&#39;type&#39; field format (&#39;integer&#39;, &#39;integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]&#39;, &#39;sellist:TableName:LabelFieldName[:KeyFieldName[:KeyFieldParent[:Filter]]]&#39;, &#39;varchar(x)&#39;, &#39;double(24,8)&#39;, &#39;real&#39;, &#39;price&#39;, &#39;text&#39;, &#39;text:none&#39;, &#39;html&#39;, &#39;date&#39;, &#39;datetime&#39;, &#39;timestamp&#39;, &#39;duration&#39;, &#39;mail&#39;, &#39;phone&#39;, &#39;url&#39;, &#39;password&#39;) Note: Filter can be a string like &quot;(t.ref:like:&#39;SO-%&#39;) or (t.date_creation:&lt;:&#39;20160101&#39;) or (t.nature:is:NULL)&quot; &#39;label&#39; the translation key.
searchContactByEmail($email, $socid= '', $case= '')
Search and fetch contacts by email.
getIdTicketInternalInvolvedContact()
Return id des contacts clients des intervenants.
utf8_check($str)
Check if a string is in UTF8.
getIdTicketInternalContact()
Return id des contacts interne de suivi.
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this-&gt;array_options This method is in most cases call...
dol_is_file($pathoffile)
Return if path is a file.
Definition: files.lib.php:457
print $_SERVER["PHP_SELF"]
Edit parameters.
$track_id
Hash to identify ticket.
verify()
Check properties of ticket are ok (like ref, track_id, ...).
print
Draft customers invoices.
Definition: index.php:89
dol_print_date($time, $format= '', $tzoutput= 'auto', $outputlangs= '', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
call_trigger($triggerName, $user)
Call trigger based on this instance.
createFromClone(User $user, $fromid)
Load an object from its id and create a new one in database.
$category_code
Category code.
$datec
Creation date.
static replaceThirdparty($db, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
getIdTicketCustomerContact()
Return id des contacts clients pour le suivi ticket.
initAsSpecimen()
Initialise object with example values Id must be 0 if object instance is a specimen.
getNomUrl($withpicto=0, $option= '', $notooltip=0, $morecss= '', $save_lastsearch_value=-1)
Return a link to the object card (with optionaly the picto)
if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) if(!empty($conf->don->enabled)&&$user->rights->don->lire) if(!empty($conf->tax->enabled)&&$user->rights->tax->charges->lire) if(!empty($conf->facture->enabled)&&!empty($conf->commande->enabled)&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1232
dol_print_error($db= '', $error= '', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
$type_label
Type label.
dolGetStatus($statusLabel= '', $statusLabelShort= '', $html= '', $statusType= 'status0', $displayMode=0, $url= '', $params=array())
Output the badge of a status.
assignUser($user, $id_assign_user, $notrigger=0)
Mark a message as read.
const STATUS_NOT_READ
Status.
loadCacheSeveritiesTickets()
Charge dans cache la liste des sévérité de tickets (paramétrable dans dictionnaire) ...
loadCacheTypesTickets()
Charge dans cache la liste des types de tickets (paramétrable dans dictionnaire)
getLibStatut($mode=0)
Return status label of object.
loadCacheMsgsTicket()
Load the list of event on ticket into -&gt;cache_msgs_ticket.
getDefaultRef($thirdparty= '')
Get a default reference.
searchSocidByEmail($email, $type= '0', $filters=array(), $clause= 'AND')
Search and fetch thirparties by email.
setContract($contractid)
Link element with a contract.
Parent class of all other business classes (invoices, contracts, proposals, orders, ...)
getTicketAllContacts()
Return id of all contacts for ticket.
dol_mkdir($dir, $dataroot= '', $newmask=null)
Creation of a directory (this can create recursive subdir)
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
newMessage($user, &$action, $private=1, $public_area=0)
Add new message on a ticket (private/public area).
$severity_label
Severity label.
dol_textishtml($msg, $option=0)
Return if a text is a html content.