dolibarr  19.0.0-dev
holiday.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2011 Dimitri Mouillard <dmouillard@teclib.com>
3  * Copyright (C) 2012-2014 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2012-2016 Regis Houssin <regis.houssin@inodbox.com>
5  * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
6  * Copyright (C) 2016 Juanjo Menent <jmenent@2byte.es>
7  * Copyright (C) 2018-2023 Frédéric France <frederic.france@netlogic.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <https://www.gnu.org/licenses/>.
21  */
22 
28 require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
29 
30 
34 class Holiday extends CommonObject
35 {
39  public $element = 'holiday';
40 
44  public $table_element = 'holiday';
45 
50  public $ismultientitymanaged = 0;
51 
55  public $fk_element = 'fk_holiday';
56 
60  public $picto = 'holiday';
61 
65  public $fk_user;
66 
67  public $date_create = '';
68 
72  public $description;
73 
74  public $date_debut = ''; // Date start in PHP server TZ
75  public $date_fin = ''; // Date end in PHP server TZ
76  public $date_debut_gmt = ''; // Date start in GMT
77  public $date_fin_gmt = ''; // Date end in GMT
78  public $halfday = ''; // 0:Full days, 2:Start afternoon end morning, -1:Start afternoon end afternoon, 1:Start morning end morning
79  public $statut = ''; // 1=draft, 2=validated, 3=approved
80 
84  public $fk_validator;
85 
89  public $date_valid = '';
90 
94  public $fk_user_valid;
95 
99  public $date_approval;
100 
104  public $fk_user_approve;
105 
109  public $date_refuse = '';
110 
114  public $fk_user_refuse;
115 
119  public $date_cancel = '';
120 
124  public $fk_user_cancel;
125 
126 
127  public $detail_refuse = '';
128 
132  public $fk_type;
133 
134  public $holiday = array();
135  public $events = array();
136  public $logs = array();
137 
138  public $optName = '';
139  public $optValue = '';
140  public $optRowid = '';
141 
145  const STATUS_DRAFT = 1;
149  const STATUS_VALIDATED = 2;
153  const STATUS_APPROVED = 3;
157  const STATUS_CANCELED = 4;
161  const STATUS_REFUSED = 5;
162 
163 
169  public function __construct($db)
170  {
171  $this->db = $db;
172  }
173 
174 
182  public function getNextNumRef($objsoc)
183  {
184  global $langs, $conf;
185  $langs->load("order");
186 
187  if (empty($conf->global->HOLIDAY_ADDON)) {
188  $conf->global->HOLIDAY_ADDON = 'mod_holiday_madonna';
189  }
190 
191  if (!empty($conf->global->HOLIDAY_ADDON)) {
192  $mybool = false;
193 
194  $file = $conf->global->HOLIDAY_ADDON.".php";
195  $classname = $conf->global->HOLIDAY_ADDON;
196 
197  // Include file with class
198  $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
199  foreach ($dirmodels as $reldir) {
200  $dir = dol_buildpath($reldir."core/modules/holiday/");
201 
202  // Load file with numbering class (if found)
203  $mybool |= @include_once $dir.$file;
204  }
205 
206  if ($mybool === false) {
207  dol_print_error('', "Failed to include file ".$file);
208  return '';
209  }
210 
211  $obj = new $classname();
212  $numref = $obj->getNextValue($objsoc, $this);
213 
214  if ($numref != "") {
215  return $numref;
216  } else {
217  $this->error = $obj->error;
218  //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
219  return "";
220  }
221  } else {
222  print $langs->trans("Error")." ".$langs->trans("Error_HOLIDAY_ADDON_NotDefined");
223  return "";
224  }
225  }
226 
232  public function updateBalance()
233  {
234  $this->db->begin();
235 
236  // Update sold of vocations
237  $result = $this->updateSoldeCP();
238 
239  // Check nb of users into table llx_holiday_users and update with empty lines
240  //if ($result > 0) $result = $this->verifNbUsers($this->countActiveUsersWithoutCP(), $this->getConfCP('nbUser'));
241 
242  if ($result >= 0) {
243  $this->db->commit();
244  return 0; // for cronjob use (0 is OK, any other value is an error code)
245  } else {
246  $this->db->rollback();
247  return -1;
248  }
249  }
250 
258  public function create($user, $notrigger = 0)
259  {
260  global $conf;
261  $error = 0;
262 
263  $now = dol_now();
264 
265  // Check parameters
266  if (empty($this->fk_user) || !is_numeric($this->fk_user) || $this->fk_user < 0) {
267  $this->error = "ErrorBadParameterFkUser"; return -1;
268  }
269  if (empty($this->fk_validator) || !is_numeric($this->fk_validator) || $this->fk_validator < 0) {
270  $this->error = "ErrorBadParameterFkValidator"; return -1;
271  }
272  if (empty($this->fk_type) || !is_numeric($this->fk_type) || $this->fk_type < 0) {
273  $this->error = "ErrorBadParameterFkType"; return -1;
274  }
275 
276  // Insert request
277  $sql = "INSERT INTO ".MAIN_DB_PREFIX."holiday(";
278  $sql .= "ref,";
279  $sql .= "fk_user,";
280  $sql .= "date_create,";
281  $sql .= "description,";
282  $sql .= "date_debut,";
283  $sql .= "date_fin,";
284  $sql .= "halfday,";
285  $sql .= "statut,";
286  $sql .= "fk_validator,";
287  $sql .= "fk_type,";
288  $sql .= "fk_user_create,";
289  $sql .= "entity";
290  $sql .= ") VALUES (";
291  $sql .= "'(PROV)',";
292  $sql .= " ".((int) $this->fk_user).",";
293  $sql .= " '".$this->db->idate($now)."',";
294  $sql .= " '".$this->db->escape($this->description)."',";
295  $sql .= " '".$this->db->idate($this->date_debut)."',";
296  $sql .= " '".$this->db->idate($this->date_fin)."',";
297  $sql .= " ".((int) $this->halfday).",";
298  $sql .= " '1',";
299  $sql .= " ".((int) $this->fk_validator).",";
300  $sql .= " ".((int) $this->fk_type).",";
301  $sql .= " ".((int) $user->id).",";
302  $sql .= " ".((int) $conf->entity);
303  $sql .= ")";
304 
305  $this->db->begin();
306 
307  dol_syslog(get_class($this)."::create", LOG_DEBUG);
308  $resql = $this->db->query($sql);
309  if (!$resql) {
310  $error++; $this->errors[] = "Error ".$this->db->lasterror();
311  }
312 
313  if (!$error) {
314  $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."holiday");
315 
316  if ($this->id) {
317  // update ref
318  $initialref = '(PROV'.$this->id.')';
319  if (!empty($this->ref)) {
320  $initialref = $this->ref;
321  }
322 
323  $sql = 'UPDATE '.MAIN_DB_PREFIX."holiday SET ref='".$this->db->escape($initialref)."' WHERE rowid=".((int) $this->id);
324  if ($this->db->query($sql)) {
325  $this->ref = $initialref;
326 
327  if (!$error) {
328  $result = $this->insertExtraFields();
329  if ($result < 0) {
330  $error++;
331  }
332  }
333 
334  if (!$error && !$notrigger) {
335  // Call trigger
336  $result = $this->call_trigger('HOLIDAY_CREATE', $user);
337  if ($result < 0) {
338  $error++;
339  }
340  // End call triggers
341  }
342  }
343  }
344  }
345 
346  // Commit or rollback
347  if ($error) {
348  foreach ($this->errors as $errmsg) {
349  dol_syslog(get_class($this)."::create ".$errmsg, LOG_ERR);
350  $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
351  }
352  $this->db->rollback();
353  return -1 * $error;
354  } else {
355  $this->db->commit();
356  return $this->id;
357  }
358  }
359 
360 
368  public function fetch($id, $ref = '')
369  {
370  global $langs;
371 
372  $sql = "SELECT";
373  $sql .= " cp.rowid,";
374  $sql .= " cp.ref,";
375  $sql .= " cp.fk_user,";
376  $sql .= " cp.date_create,";
377  $sql .= " cp.description,";
378  $sql .= " cp.date_debut,";
379  $sql .= " cp.date_fin,";
380  $sql .= " cp.halfday,";
381  $sql .= " cp.statut,";
382  $sql .= " cp.fk_validator,";
383  $sql .= " cp.date_valid,";
384  $sql .= " cp.fk_user_valid,";
385  $sql .= " cp.date_approval,";
386  $sql .= " cp.fk_user_approve,";
387  $sql .= " cp.date_refuse,";
388  $sql .= " cp.fk_user_refuse,";
389  $sql .= " cp.date_cancel,";
390  $sql .= " cp.fk_user_cancel,";
391  $sql .= " cp.detail_refuse,";
392  $sql .= " cp.note_private,";
393  $sql .= " cp.note_public,";
394  $sql .= " cp.fk_user_create,";
395  $sql .= " cp.fk_type,";
396  $sql .= " cp.entity";
397  $sql .= " FROM ".MAIN_DB_PREFIX."holiday as cp";
398  if ($id > 0) {
399  $sql .= " WHERE cp.rowid = ".((int) $id);
400  } else {
401  $sql .= " WHERE cp.ref = '".$this->db->escape($ref)."'";
402  }
403 
404  dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
405  $resql = $this->db->query($sql);
406  if ($resql) {
407  if ($this->db->num_rows($resql)) {
408  $obj = $this->db->fetch_object($resql);
409 
410  $this->id = $obj->rowid;
411  $this->ref = ($obj->ref ? $obj->ref : $obj->rowid);
412  $this->fk_user = $obj->fk_user;
413  $this->date_create = $this->db->jdate($obj->date_create);
414  $this->description = $obj->description;
415  $this->date_debut = $this->db->jdate($obj->date_debut);
416  $this->date_fin = $this->db->jdate($obj->date_fin);
417  $this->date_debut_gmt = $this->db->jdate($obj->date_debut, 1);
418  $this->date_fin_gmt = $this->db->jdate($obj->date_fin, 1);
419  $this->halfday = $obj->halfday;
420  $this->statut = $obj->statut;
421  $this->fk_validator = $obj->fk_validator;
422  $this->date_valid = $this->db->jdate($obj->date_valid);
423  $this->fk_user_valid = $obj->fk_user_valid;
424  $this->user_validation_id = $obj->fk_user_valid;
425  $this->date_approval = $this->db->jdate($obj->date_approval);
426  $this->fk_user_approve = $obj->fk_user_approve;
427  $this->date_refuse = $this->db->jdate($obj->date_refuse);
428  $this->fk_user_refuse = $obj->fk_user_refuse;
429  $this->date_cancel = $this->db->jdate($obj->date_cancel);
430  $this->fk_user_cancel = $obj->fk_user_cancel;
431  $this->detail_refuse = $obj->detail_refuse;
432  $this->note_private = $obj->note_private;
433  $this->note_public = $obj->note_public;
434  $this->fk_user_create = $obj->fk_user_create;
435  $this->fk_type = $obj->fk_type;
436  $this->entity = $obj->entity;
437 
438  $this->fetch_optionals();
439 
440  $result = 1;
441  } else {
442  $result = 0;
443  }
444  $this->db->free($resql);
445 
446  return $result;
447  } else {
448  $this->error = "Error ".$this->db->lasterror();
449  return -1;
450  }
451  }
452 
461  public function fetchByUser($user_id, $order = '', $filter = '')
462  {
463  global $langs, $conf;
464 
465  $sql = "SELECT";
466  $sql .= " cp.rowid,";
467  $sql .= " cp.ref,";
468 
469  $sql .= " cp.fk_user,";
470  $sql .= " cp.fk_type,";
471  $sql .= " cp.date_create,";
472  $sql .= " cp.description,";
473  $sql .= " cp.date_debut,";
474  $sql .= " cp.date_fin,";
475  $sql .= " cp.halfday,";
476  $sql .= " cp.statut,";
477  $sql .= " cp.fk_validator,";
478  $sql .= " cp.date_valid,";
479  $sql .= " cp.fk_user_valid,";
480  $sql .= " cp.date_approval,";
481  $sql .= " cp.fk_user_approve,";
482  $sql .= " cp.date_refuse,";
483  $sql .= " cp.fk_user_refuse,";
484  $sql .= " cp.date_cancel,";
485  $sql .= " cp.fk_user_cancel,";
486  $sql .= " cp.detail_refuse,";
487 
488  $sql .= " uu.lastname as user_lastname,";
489  $sql .= " uu.firstname as user_firstname,";
490  $sql .= " uu.login as user_login,";
491  $sql .= " uu.statut as user_statut,";
492  $sql .= " uu.photo as user_photo,";
493 
494  $sql .= " ua.lastname as validator_lastname,";
495  $sql .= " ua.firstname as validator_firstname,";
496  $sql .= " ua.login as validator_login,";
497  $sql .= " ua.statut as validator_statut,";
498  $sql .= " ua.photo as validator_photo";
499 
500  $sql .= " FROM ".MAIN_DB_PREFIX."holiday as cp, ".MAIN_DB_PREFIX."user as uu, ".MAIN_DB_PREFIX."user as ua";
501  $sql .= " WHERE cp.entity IN (".getEntity('holiday').")";
502  $sql .= " AND cp.fk_user = uu.rowid AND cp.fk_validator = ua.rowid"; // Hack pour la recherche sur le tableau
503  $sql .= " AND cp.fk_user IN (".$this->db->sanitize($user_id).")";
504 
505  // Selection filter
506  if (!empty($filter)) {
507  $sql .= $filter;
508  }
509 
510  // Order of display of the result
511  if (!empty($order)) {
512  $sql .= $order;
513  }
514 
515  dol_syslog(get_class($this)."::fetchByUser", LOG_DEBUG);
516  $resql = $this->db->query($sql);
517 
518  // If no SQL error
519  if ($resql) {
520  $i = 0;
521  $tab_result = $this->holiday;
522  $num = $this->db->num_rows($resql);
523 
524  // If no registration
525  if (!$num) {
526  return 2;
527  }
528 
529  // List the records and add them to the table
530  while ($i < $num) {
531  $obj = $this->db->fetch_object($resql);
532 
533  $tab_result[$i]['rowid'] = $obj->rowid;
534  $tab_result[$i]['id'] = $obj->rowid;
535  $tab_result[$i]['ref'] = ($obj->ref ? $obj->ref : $obj->rowid);
536 
537  $tab_result[$i]['fk_user'] = $obj->fk_user;
538  $tab_result[$i]['fk_type'] = $obj->fk_type;
539  $tab_result[$i]['date_create'] = $this->db->jdate($obj->date_create);
540  $tab_result[$i]['description'] = $obj->description;
541  $tab_result[$i]['date_debut'] = $this->db->jdate($obj->date_debut);
542  $tab_result[$i]['date_fin'] = $this->db->jdate($obj->date_fin);
543  $tab_result[$i]['date_debut_gmt'] = $this->db->jdate($obj->date_debut, 1);
544  $tab_result[$i]['date_fin_gmt'] = $this->db->jdate($obj->date_fin, 1);
545  $tab_result[$i]['halfday'] = $obj->halfday;
546  $tab_result[$i]['statut'] = $obj->statut;
547  $tab_result[$i]['fk_validator'] = $obj->fk_validator;
548  $tab_result[$i]['date_valid'] = $this->db->jdate($obj->date_valid);
549  $tab_result[$i]['fk_user_valid'] = $obj->fk_user_valid;
550  $tab_result[$i]['date_approval'] = $this->db->jdate($obj->date_approval);
551  $tab_result[$i]['fk_user_approve'] = $obj->fk_user_approve;
552  $tab_result[$i]['date_refuse'] = $this->db->jdate($obj->date_refuse);
553  $tab_result[$i]['fk_user_refuse'] = $obj->fk_user_refuse;
554  $tab_result[$i]['date_cancel'] = $this->db->jdate($obj->date_cancel);
555  $tab_result[$i]['fk_user_cancel'] = $obj->fk_user_cancel;
556  $tab_result[$i]['detail_refuse'] = $obj->detail_refuse;
557 
558  $tab_result[$i]['user_firstname'] = $obj->user_firstname;
559  $tab_result[$i]['user_lastname'] = $obj->user_lastname;
560  $tab_result[$i]['user_login'] = $obj->user_login;
561  $tab_result[$i]['user_statut'] = $obj->user_statut;
562  $tab_result[$i]['user_photo'] = $obj->user_photo;
563 
564  $tab_result[$i]['validator_firstname'] = $obj->validator_firstname;
565  $tab_result[$i]['validator_lastname'] = $obj->validator_lastname;
566  $tab_result[$i]['validator_login'] = $obj->validator_login;
567  $tab_result[$i]['validator_statut'] = $obj->validator_statut;
568  $tab_result[$i]['validator_photo'] = $obj->validator_photo;
569 
570  $i++;
571  }
572 
573  // Returns 1 with the filled array
574  $this->holiday = $tab_result;
575  return 1;
576  } else {
577  // SQL Error
578  $this->error = "Error ".$this->db->lasterror();
579  return -1;
580  }
581  }
582 
590  public function fetchAll($order, $filter)
591  {
592  global $langs;
593 
594  $sql = "SELECT";
595  $sql .= " cp.rowid,";
596  $sql .= " cp.ref,";
597 
598  $sql .= " cp.fk_user,";
599  $sql .= " cp.fk_type,";
600  $sql .= " cp.date_create,";
601  $sql .= " cp.tms as date_update,";
602  $sql .= " cp.description,";
603  $sql .= " cp.date_debut,";
604  $sql .= " cp.date_fin,";
605  $sql .= " cp.halfday,";
606  $sql .= " cp.statut,";
607  $sql .= " cp.fk_validator,";
608  $sql .= " cp.date_valid,";
609  $sql .= " cp.fk_user_valid,";
610  $sql .= " cp.date_approval,";
611  $sql .= " cp.fk_user_approve,";
612  $sql .= " cp.date_refuse,";
613  $sql .= " cp.fk_user_refuse,";
614  $sql .= " cp.date_cancel,";
615  $sql .= " cp.fk_user_cancel,";
616  $sql .= " cp.detail_refuse,";
617 
618  $sql .= " uu.lastname as user_lastname,";
619  $sql .= " uu.firstname as user_firstname,";
620  $sql .= " uu.login as user_login,";
621  $sql .= " uu.statut as user_statut,";
622  $sql .= " uu.photo as user_photo,";
623 
624  $sql .= " ua.lastname as validator_lastname,";
625  $sql .= " ua.firstname as validator_firstname,";
626  $sql .= " ua.login as validator_login,";
627  $sql .= " ua.statut as validator_statut,";
628  $sql .= " ua.photo as validator_photo";
629 
630  $sql .= " FROM ".MAIN_DB_PREFIX."holiday as cp, ".MAIN_DB_PREFIX."user as uu, ".MAIN_DB_PREFIX."user as ua";
631  $sql .= " WHERE cp.entity IN (".getEntity('holiday').")";
632  $sql .= " AND cp.fk_user = uu.rowid AND cp.fk_validator = ua.rowid "; // Hack pour la recherche sur le tableau
633 
634  // Selection filtering
635  if (!empty($filter)) {
636  $sql .= $filter;
637  }
638 
639  // order of display
640  if (!empty($order)) {
641  $sql .= $order;
642  }
643 
644  dol_syslog(get_class($this)."::fetchAll", LOG_DEBUG);
645  $resql = $this->db->query($sql);
646 
647  // If no SQL error
648  if ($resql) {
649  $i = 0;
650  $tab_result = $this->holiday;
651  $num = $this->db->num_rows($resql);
652 
653  // If no registration
654  if (!$num) {
655  return 2;
656  }
657 
658  // List the records and add them to the table
659  while ($i < $num) {
660  $obj = $this->db->fetch_object($resql);
661 
662  $tab_result[$i]['rowid'] = $obj->rowid;
663  $tab_result[$i]['id'] = $obj->rowid;
664  $tab_result[$i]['ref'] = ($obj->ref ? $obj->ref : $obj->rowid);
665 
666  $tab_result[$i]['fk_user'] = $obj->fk_user;
667  $tab_result[$i]['fk_type'] = $obj->fk_type;
668  $tab_result[$i]['date_create'] = $this->db->jdate($obj->date_create);
669  $tab_result[$i]['date_update'] = $this->db->jdate($obj->date_update);
670  $tab_result[$i]['description'] = $obj->description;
671  $tab_result[$i]['date_debut'] = $this->db->jdate($obj->date_debut);
672  $tab_result[$i]['date_fin'] = $this->db->jdate($obj->date_fin);
673  $tab_result[$i]['date_debut_gmt'] = $this->db->jdate($obj->date_debut, 1);
674  $tab_result[$i]['date_fin_gmt'] = $this->db->jdate($obj->date_fin, 1);
675  $tab_result[$i]['halfday'] = $obj->halfday;
676  $tab_result[$i]['statut'] = $obj->statut;
677  $tab_result[$i]['fk_validator'] = $obj->fk_validator;
678  $tab_result[$i]['date_valid'] = $this->db->jdate($obj->date_valid);
679  $tab_result[$i]['fk_user_valid'] = $obj->fk_user_valid;
680  $tab_result[$i]['date_approval'] = $this->db->jdate($obj->date_approval);
681  $tab_result[$i]['fk_user_approve'] = $obj->fk_user_approve;
682  $tab_result[$i]['date_refuse'] = $obj->date_refuse;
683  $tab_result[$i]['fk_user_refuse'] = $obj->fk_user_refuse;
684  $tab_result[$i]['date_cancel'] = $obj->date_cancel;
685  $tab_result[$i]['fk_user_cancel'] = $obj->fk_user_cancel;
686  $tab_result[$i]['detail_refuse'] = $obj->detail_refuse;
687 
688  $tab_result[$i]['user_firstname'] = $obj->user_firstname;
689  $tab_result[$i]['user_lastname'] = $obj->user_lastname;
690  $tab_result[$i]['user_login'] = $obj->user_login;
691  $tab_result[$i]['user_statut'] = $obj->user_statut;
692  $tab_result[$i]['user_photo'] = $obj->user_photo;
693 
694  $tab_result[$i]['validator_firstname'] = $obj->validator_firstname;
695  $tab_result[$i]['validator_lastname'] = $obj->validator_lastname;
696  $tab_result[$i]['validator_login'] = $obj->validator_login;
697  $tab_result[$i]['validator_statut'] = $obj->validator_statut;
698  $tab_result[$i]['validator_photo'] = $obj->validator_photo;
699 
700  $i++;
701  }
702  // Returns 1 and adds the array to the variable
703  $this->holiday = $tab_result;
704  return 1;
705  } else {
706  // SQL Error
707  $this->error = "Error ".$this->db->lasterror();
708  return -1;
709  }
710  }
711 
712 
720  public function validate($user = null, $notrigger = 0)
721  {
722  global $conf, $langs;
723  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
724  $error = 0;
725 
726  $checkBalance = getDictionaryValue('c_holiday_types', 'block_if_negative', $this->fk_type);
727 
728  if ($checkBalance > 0) {
729  $balance = $this->getCPforUser($this->fk_user, $this->fk_type);
730 
731  if ($balance < 0) {
732  $this->error = 'LeaveRequestCreationBlockedBecauseBalanceIsNegative';
733  return -1;
734  }
735  }
736 
737  // Define new ref
738  if (!$error && (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref) || $this->ref == $this->id)) {
739  $num = $this->getNextNumRef(null);
740  } else {
741  $num = $this->ref;
742  }
743  $this->newref = dol_sanitizeFileName($num);
744 
745  // Update status
746  $sql = "UPDATE ".MAIN_DB_PREFIX."holiday SET";
747  $sql .= " fk_user_valid = ".((int) $user->id).",";
748  $sql .= " date_valid = '".$this->db->idate(dol_now())."',";
749  if (!empty($this->statut) && is_numeric($this->statut)) {
750  $sql .= " statut = ".((int) $this->statut).",";
751  } else {
752  $this->error = 'Property status must be a numeric value';
753  $error++;
754  }
755  $sql .= " ref = '".$this->db->escape($num)."'";
756  $sql .= " WHERE rowid = ".((int) $this->id);
757 
758  $this->db->begin();
759 
760  dol_syslog(get_class($this)."::validate", LOG_DEBUG);
761  $resql = $this->db->query($sql);
762  if (!$resql) {
763  $error++; $this->errors[] = "Error ".$this->db->lasterror();
764  }
765 
766  if (!$error) {
767  if (!$notrigger) {
768  // Call trigger
769  $result = $this->call_trigger('HOLIDAY_VALIDATE', $user);
770  if ($result < 0) {
771  $error++;
772  }
773  // End call triggers
774  }
775  }
776 
777  if (!$error) {
778  $this->oldref = $this->ref;
779 
780  // Rename directory if dir was a temporary ref
781  if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
782  // Now we rename also files into index
783  $sql = 'UPDATE ' . MAIN_DB_PREFIX . "ecm_files set filename = CONCAT('" . $this->db->escape($this->newref) . "', SUBSTR(filename, " . (strlen($this->ref) + 1) . ")), filepath = 'holiday/" . $this->db->escape($this->newref) . "'";
784  $sql .= " WHERE filename LIKE '" . $this->db->escape($this->ref) . "%' AND filepath = 'holiday/" . $this->db->escape($this->ref) . "' and entity = " . ((int) $conf->entity);
785  $resql = $this->db->query($sql);
786  if (!$resql) {
787  $error++;
788  $this->error = $this->db->lasterror();
789  }
790 
791  // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
792  $oldref = dol_sanitizeFileName($this->ref);
793  $newref = dol_sanitizeFileName($num);
794  $dirsource = $conf->holiday->multidir_output[$this->entity] . '/' . $oldref;
795  $dirdest = $conf->holiday->multidir_output[$this->entity] . '/' . $newref;
796  if (!$error && file_exists($dirsource)) {
797  dol_syslog(get_class($this) . "::validate rename dir " . $dirsource . " into " . $dirdest);
798  if (@rename($dirsource, $dirdest)) {
799  dol_syslog("Rename ok");
800  // Rename docs starting with $oldref with $newref
801  $listoffiles = dol_dir_list($dirdest, 'files', 1, '^' . preg_quote($oldref, '/'));
802  foreach ($listoffiles as $fileentry) {
803  $dirsource = $fileentry['name'];
804  $dirdest = preg_replace('/^' . preg_quote($oldref, '/') . '/', $newref, $dirsource);
805  $dirsource = $fileentry['path'] . '/' . $dirsource;
806  $dirdest = $fileentry['path'] . '/' . $dirdest;
807  @rename($dirsource, $dirdest);
808  }
809  }
810  }
811  }
812  }
813 
814 
815  // Commit or rollback
816  if ($error) {
817  foreach ($this->errors as $errmsg) {
818  dol_syslog(get_class($this)."::validate ".$errmsg, LOG_ERR);
819  $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
820  }
821  $this->db->rollback();
822  return -1 * $error;
823  } else {
824  $this->db->commit();
825  return 1;
826  }
827  }
828 
829 
837  public function approve($user = null, $notrigger = 0)
838  {
839  global $conf, $langs;
840  $error = 0;
841 
842  $checkBalance = getDictionaryValue('c_holiday_types', 'block_if_negative', $this->fk_type);
843 
844  if ($checkBalance > 0) {
845  $balance = $this->getCPforUser($this->fk_user, $this->fk_type);
846 
847  if ($balance < 0) {
848  $this->error = 'LeaveRequestCreationBlockedBecauseBalanceIsNegative';
849  return -1;
850  }
851  }
852 
853  // Update request
854  $sql = "UPDATE ".MAIN_DB_PREFIX."holiday SET";
855 
856  $sql .= " description= '".$this->db->escape($this->description)."',";
857 
858  if (!empty($this->date_debut)) {
859  $sql .= " date_debut = '".$this->db->idate($this->date_debut)."',";
860  } else {
861  $error++;
862  }
863  if (!empty($this->date_fin)) {
864  $sql .= " date_fin = '".$this->db->idate($this->date_fin)."',";
865  } else {
866  $error++;
867  }
868  $sql .= " halfday = ".((int) $this->halfday).",";
869  if (!empty($this->statut) && is_numeric($this->statut)) {
870  $sql .= " statut = ".((int) $this->statut).",";
871  } else {
872  $error++;
873  }
874  if (!empty($this->fk_validator)) {
875  $sql .= " fk_validator = ".((int) $this->fk_validator).",";
876  } else {
877  $error++;
878  }
879  if (!empty($this->date_valid)) {
880  $sql .= " date_valid = '".$this->db->idate($this->date_valid)."',";
881  } else {
882  $sql .= " date_valid = NULL,";
883  }
884  if (!empty($this->fk_user_valid)) {
885  $sql .= " fk_user_valid = ".((int) $this->fk_user_valid).",";
886  } else {
887  $sql .= " fk_user_valid = NULL,";
888  }
889  if (!empty($this->date_approval)) {
890  $sql .= " date_approval = '".$this->db->idate($this->date_approval)."',";
891  } else {
892  $sql .= " date_approval = NULL,";
893  }
894  if (!empty($this->fk_user_approve)) {
895  $sql .= " fk_user_approve = ".((int) $this->fk_user_approve).",";
896  } else {
897  $sql .= " fk_user_approve = NULL,";
898  }
899  if (!empty($this->date_refuse)) {
900  $sql .= " date_refuse = '".$this->db->idate($this->date_refuse)."',";
901  } else {
902  $sql .= " date_refuse = NULL,";
903  }
904  if (!empty($this->fk_user_refuse)) {
905  $sql .= " fk_user_refuse = ".((int) $this->fk_user_refuse).",";
906  } else {
907  $sql .= " fk_user_refuse = NULL,";
908  }
909  if (!empty($this->date_cancel)) {
910  $sql .= " date_cancel = '".$this->db->idate($this->date_cancel)."',";
911  } else {
912  $sql .= " date_cancel = NULL,";
913  }
914  if (!empty($this->fk_user_cancel)) {
915  $sql .= " fk_user_cancel = ".((int) $this->fk_user_cancel).",";
916  } else {
917  $sql .= " fk_user_cancel = NULL,";
918  }
919  if (!empty($this->detail_refuse)) {
920  $sql .= " detail_refuse = '".$this->db->escape($this->detail_refuse)."'";
921  } else {
922  $sql .= " detail_refuse = NULL";
923  }
924  $sql .= " WHERE rowid = ".((int) $this->id);
925 
926  $this->db->begin();
927 
928  dol_syslog(get_class($this)."::approve", LOG_DEBUG);
929  $resql = $this->db->query($sql);
930  if (!$resql) {
931  $error++; $this->errors[] = "Error ".$this->db->lasterror();
932  }
933 
934  if (!$error) {
935  if (!$notrigger) {
936  // Call trigger
937  $result = $this->call_trigger('HOLIDAY_APPROVE', $user);
938  if ($result < 0) {
939  $error++;
940  }
941  // End call triggers
942  }
943  }
944 
945  // Commit or rollback
946  if ($error) {
947  foreach ($this->errors as $errmsg) {
948  dol_syslog(get_class($this)."::approve ".$errmsg, LOG_ERR);
949  $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
950  }
951  $this->db->rollback();
952  return -1 * $error;
953  } else {
954  $this->db->commit();
955  return 1;
956  }
957  }
958 
966  public function update($user = null, $notrigger = 0)
967  {
968  global $conf, $langs;
969  $error = 0;
970 
971  $checkBalance = getDictionaryValue('c_holiday_types', 'block_if_negative', $this->fk_type);
972 
973  if ($checkBalance > 0 && $this->statut != self::STATUS_DRAFT) {
974  $balance = $this->getCPforUser($this->fk_user, $this->fk_type);
975 
976  if ($balance < 0) {
977  $this->error = 'LeaveRequestCreationBlockedBecauseBalanceIsNegative';
978  return -1;
979  }
980  }
981 
982  // Update request
983  $sql = "UPDATE ".MAIN_DB_PREFIX."holiday SET";
984 
985  $sql .= " description= '".$this->db->escape($this->description)."',";
986 
987  if (!empty($this->date_debut)) {
988  $sql .= " date_debut = '".$this->db->idate($this->date_debut)."',";
989  } else {
990  $error++;
991  }
992  if (!empty($this->date_fin)) {
993  $sql .= " date_fin = '".$this->db->idate($this->date_fin)."',";
994  } else {
995  $error++;
996  }
997  $sql .= " halfday = ".$this->halfday.",";
998  if (!empty($this->statut) && is_numeric($this->statut)) {
999  $sql .= " statut = ".$this->statut.",";
1000  } else {
1001  $error++;
1002  }
1003  if (!empty($this->fk_validator)) {
1004  $sql .= " fk_validator = '".$this->db->escape($this->fk_validator)."',";
1005  } else {
1006  $error++;
1007  }
1008  if (!empty($this->date_valid)) {
1009  $sql .= " date_valid = '".$this->db->idate($this->date_valid)."',";
1010  } else {
1011  $sql .= " date_valid = NULL,";
1012  }
1013  if (!empty($this->fk_user_valid)) {
1014  $sql .= " fk_user_valid = ".((int) $this->fk_user_valid).",";
1015  } else {
1016  $sql .= " fk_user_valid = NULL,";
1017  }
1018  if (!empty($this->date_approval)) {
1019  $sql .= " date_approval = '".$this->db->idate($this->date_approval)."',";
1020  } else {
1021  $sql .= " date_approval = NULL,";
1022  }
1023  if (!empty($this->fk_user_approve)) {
1024  $sql .= " fk_user_approve = ".((int) $this->fk_user_approve).",";
1025  } else {
1026  $sql .= " fk_user_approve = NULL,";
1027  }
1028  if (!empty($this->date_refuse)) {
1029  $sql .= " date_refuse = '".$this->db->idate($this->date_refuse)."',";
1030  } else {
1031  $sql .= " date_refuse = NULL,";
1032  }
1033  if (!empty($this->fk_user_refuse)) {
1034  $sql .= " fk_user_refuse = ".((int) $this->fk_user_refuse).",";
1035  } else {
1036  $sql .= " fk_user_refuse = NULL,";
1037  }
1038  if (!empty($this->date_cancel)) {
1039  $sql .= " date_cancel = '".$this->db->idate($this->date_cancel)."',";
1040  } else {
1041  $sql .= " date_cancel = NULL,";
1042  }
1043  if (!empty($this->fk_user_cancel)) {
1044  $sql .= " fk_user_cancel = ".((int) $this->fk_user_cancel).",";
1045  } else {
1046  $sql .= " fk_user_cancel = NULL,";
1047  }
1048  if (!empty($this->detail_refuse)) {
1049  $sql .= " detail_refuse = '".$this->db->escape($this->detail_refuse)."'";
1050  } else {
1051  $sql .= " detail_refuse = NULL";
1052  }
1053 
1054  $sql .= " WHERE rowid = ".((int) $this->id);
1055 
1056  $this->db->begin();
1057 
1058  dol_syslog(get_class($this)."::update", LOG_DEBUG);
1059  $resql = $this->db->query($sql);
1060  if (!$resql) {
1061  $error++; $this->errors[] = "Error ".$this->db->lasterror();
1062  }
1063 
1064  if (!$error) {
1065  if (!$notrigger) {
1066  // Call trigger
1067  $result = $this->call_trigger('HOLIDAY_MODIFY', $user);
1068  if ($result < 0) {
1069  $error++;
1070  }
1071  // End call triggers
1072  }
1073  }
1074 
1075  // Commit or rollback
1076  if ($error) {
1077  foreach ($this->errors as $errmsg) {
1078  dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
1079  $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
1080  }
1081  $this->db->rollback();
1082  return -1 * $error;
1083  } else {
1084  $this->db->commit();
1085  return 1;
1086  }
1087  }
1088 
1089 
1097  public function delete($user, $notrigger = 0)
1098  {
1099  global $conf, $langs;
1100  $error = 0;
1101 
1102  $sql = "DELETE FROM ".MAIN_DB_PREFIX."holiday";
1103  $sql .= " WHERE rowid=".((int) $this->id);
1104 
1105  $this->db->begin();
1106 
1107  dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1108  $resql = $this->db->query($sql);
1109  if (!$resql) {
1110  $error++; $this->errors[] = "Error ".$this->db->lasterror();
1111  }
1112 
1113  if (!$error) {
1114  if (!$notrigger) {
1115  // Call trigger
1116  $result = $this->call_trigger('HOLIDAY_DELETE', $user);
1117  if ($result < 0) {
1118  $error++;
1119  }
1120  // End call triggers
1121  }
1122  }
1123 
1124  // Commit or rollback
1125  if ($error) {
1126  foreach ($this->errors as $errmsg) {
1127  dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
1128  $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
1129  }
1130  $this->db->rollback();
1131  return -1 * $error;
1132  } else {
1133  $this->db->commit();
1134  return 1;
1135  }
1136  }
1137 
1151  public function verifDateHolidayCP($fk_user, $dateStart, $dateEnd, $halfday = 0)
1152  {
1153  $this->fetchByUser($fk_user, '', '');
1154 
1155  foreach ($this->holiday as $infos_CP) {
1156  if ($infos_CP['statut'] == Holiday::STATUS_CANCELED) {
1157  continue; // ignore not validated holidays
1158  }
1159  if ($infos_CP['statut'] == Holiday::STATUS_REFUSED) {
1160  continue; // ignore refused holidays
1161  }
1162  //var_dump("--");
1163  //var_dump("old: ".dol_print_date($infos_CP['date_debut'],'dayhour').' '.dol_print_date($infos_CP['date_fin'],'dayhour').' '.$infos_CP['halfday']);
1164  //var_dump("new: ".dol_print_date($dateStart,'dayhour').' '.dol_print_date($dateEnd,'dayhour').' '.$halfday);
1165 
1166  if ($halfday == 0) {
1167  if ($dateStart >= $infos_CP['date_debut'] && $dateStart <= $infos_CP['date_fin']) {
1168  return false;
1169  }
1170  if ($dateEnd <= $infos_CP['date_fin'] && $dateEnd >= $infos_CP['date_debut']) {
1171  return false;
1172  }
1173  } elseif ($halfday == -1) {
1174  // new start afternoon, new end afternoon
1175  if ($dateStart >= $infos_CP['date_debut'] && $dateStart <= $infos_CP['date_fin']) {
1176  if ($dateStart < $infos_CP['date_fin'] || in_array($infos_CP['halfday'], array(0, -1))) {
1177  return false;
1178  }
1179  }
1180  if ($dateEnd <= $infos_CP['date_fin'] && $dateEnd >= $infos_CP['date_debut']) {
1181  if ($dateStart < $dateEnd) {
1182  return false;
1183  }
1184  if ($dateEnd < $infos_CP['date_fin'] || in_array($infos_CP['halfday'], array(0, -1))) {
1185  return false;
1186  }
1187  }
1188  } elseif ($halfday == 1) {
1189  // new start morning, new end morning
1190  if ($dateStart >= $infos_CP['date_debut'] && $dateStart <= $infos_CP['date_fin']) {
1191  if ($dateStart < $dateEnd) {
1192  return false;
1193  }
1194  if ($dateStart > $infos_CP['date_debut'] || in_array($infos_CP['halfday'], array(0, 1))) {
1195  return false;
1196  }
1197  }
1198  if ($dateEnd <= $infos_CP['date_fin'] && $dateEnd >= $infos_CP['date_debut']) {
1199  if ($dateEnd > $infos_CP['date_debut'] || in_array($infos_CP['halfday'], array(0, 1))) {
1200  return false;
1201  }
1202  }
1203  } elseif ($halfday == 2) {
1204  // new start afternoon, new end morning
1205  if ($dateStart >= $infos_CP['date_debut'] && $dateStart <= $infos_CP['date_fin']) {
1206  if ($dateStart < $infos_CP['date_fin'] || in_array($infos_CP['halfday'], array(0, -1))) {
1207  return false;
1208  }
1209  }
1210  if ($dateEnd <= $infos_CP['date_fin'] && $dateEnd >= $infos_CP['date_debut']) {
1211  if ($dateEnd > $infos_CP['date_debut'] || in_array($infos_CP['halfday'], array(0, 1))) {
1212  return false;
1213  }
1214  }
1215  } else {
1216  dol_print_error('', 'Bad value of parameter halfday when calling function verifDateHolidayCP');
1217  }
1218  }
1219 
1220  return true;
1221  }
1222 
1223 
1233  public function verifDateHolidayForTimestamp($fk_user, $timestamp, $status = '-1')
1234  {
1235  global $langs, $conf;
1236 
1237  $isavailablemorning = true;
1238  $isavailableafternoon = true;
1239 
1240  // Check into leave requests
1241  $sql = "SELECT cp.rowid, cp.date_debut as date_start, cp.date_fin as date_end, cp.halfday, cp.statut";
1242  $sql .= " FROM ".MAIN_DB_PREFIX."holiday as cp";
1243  $sql .= " WHERE cp.entity IN (".getEntity('holiday').")";
1244  $sql .= " AND cp.fk_user = ".(int) $fk_user;
1245  $sql .= " AND cp.date_debut <= '".$this->db->idate($timestamp)."' AND cp.date_fin >= '".$this->db->idate($timestamp)."'";
1246  if ($status != '-1') {
1247  $sql .= " AND cp.statut IN (".$this->db->sanitize($status).")";
1248  }
1249 
1250  $resql = $this->db->query($sql);
1251  if ($resql) {
1252  $num_rows = $this->db->num_rows($resql); // Note, we can have 2 records if on is morning and the other one is afternoon
1253  if ($num_rows > 0) {
1254  $arrayofrecord = array();
1255  $i = 0;
1256  while ($i < $num_rows) {
1257  $obj = $this->db->fetch_object($resql);
1258 
1259  // Note: $obj->halfday is 0:Full days, 2:Sart afternoon end morning, -1:Start afternoon, 1:End morning
1260  $arrayofrecord[$obj->rowid] = array('date_start'=>$this->db->jdate($obj->date_start), 'date_end'=>$this->db->jdate($obj->date_end), 'halfday'=>$obj->halfday);
1261  $i++;
1262  }
1263 
1264  // We found a record, user is on holiday by default, so is not available is true.
1265  $isavailablemorning = true;
1266  foreach ($arrayofrecord as $record) {
1267  if ($timestamp == $record['date_start'] && $record['halfday'] == 2) {
1268  continue;
1269  }
1270  if ($timestamp == $record['date_start'] && $record['halfday'] == -1) {
1271  continue;
1272  }
1273  $isavailablemorning = false;
1274  break;
1275  }
1276  $isavailableafternoon = true;
1277  foreach ($arrayofrecord as $record) {
1278  if ($timestamp == $record['date_end'] && $record['halfday'] == 2) {
1279  continue;
1280  }
1281  if ($timestamp == $record['date_end'] && $record['halfday'] == 1) {
1282  continue;
1283  }
1284  $isavailableafternoon = false;
1285  break;
1286  }
1287  }
1288  } else {
1289  dol_print_error($this->db);
1290  }
1291 
1292  $result = array('morning'=>$isavailablemorning, 'afternoon'=>$isavailableafternoon);
1293  if (!$isavailablemorning) {
1294  $result['morning_reason'] = 'leave_request';
1295  }
1296  if (!$isavailableafternoon) {
1297  $result['afternoon_reason'] = 'leave_request';
1298  }
1299  return $result;
1300  }
1301 
1309  public function getTooltipContentArray($params)
1310  {
1311  global $conf, $langs;
1312 
1313  $langs->load('holiday');
1314  $nofetch = !empty($params['nofetch']);
1315 
1316  $datas = array();
1317  $datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("Holiday").'</u>';
1318  if (isset($this->statut)) {
1319  $datas['picto'] .= ' '.$this->getLibStatut(5);
1320  }
1321  $datas['ref'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
1322  // show type for this record only in ajax to not overload lists
1323  if (!$nofetch && !empty($this->fk_type)) {
1324  $typeleaves = $this->getTypes(1, -1);
1325  $labeltoshow = (($typeleaves[$this->fk_type]['code'] && $langs->trans($typeleaves[$this->fk_type]['code']) != $typeleaves[$this->fk_type]['code']) ? $langs->trans($typeleaves[$this->fk_type]['code']) : $typeleaves[$this->fk_type]['label']);
1326  $datas['type'] = '<br><b>'.$langs->trans("Type") . ':</b> ' . (empty($labeltoshow) ? $langs->trans("TypeWasDisabledOrRemoved", $this->fk_type) : $labeltoshow);
1327  }
1328  if (isset($this->halfday) && !empty($this->date_debut) && !empty($this->date_fin)) {
1329  $listhalfday = array(
1330  'morning' => $langs->trans("Morning"),
1331  "afternoon" => $langs->trans("Afternoon")
1332  );
1333  $starthalfday = ($this->halfday == -1 || $this->halfday == 2) ? 'afternoon' : 'morning';
1334  $endhalfday = ($this->halfday == 1 || $this->halfday == 2) ? 'morning' : 'afternoon';
1335  $datas['date_start'] = '<br><b>'.$langs->trans('DateDebCP') . '</b>: '. dol_print_date($this->date_debut, 'day') . '&nbsp;&nbsp;<span class="opacitymedium">'.$langs->trans($listhalfday[$starthalfday]).'</span>';
1336  $datas['date_end'] = '<br><b>'.$langs->trans('DateFinCP') . '</b>: '. dol_print_date($this->date_fin, 'day') . '&nbsp;&nbsp;<span class="opacitymedium">'.$langs->trans($listhalfday[$endhalfday]).'</span>';
1337  }
1338 
1339 
1340  return $datas;
1341  }
1342 
1352  public function getNomUrl($withpicto = 0, $save_lastsearch_value = -1, $notooltip = 0, $morecss = '')
1353  {
1354  global $conf, $langs, $hookmanager;
1355 
1356  if (!empty($conf->dol_no_mouse_hover)) {
1357  $notooltip = 1; // Force disable tooltips
1358  }
1359 
1360  $result = '';
1361  $params = [
1362  'id' => $this->id,
1363  'objecttype' => $this->element,
1364  'nofetch' => 1,
1365  ];
1366  $classfortooltip = 'classfortooltip';
1367  $dataparams = '';
1368  if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1369  $classfortooltip = 'classforajaxtooltip';
1370  $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
1371  $label = '';
1372  } else {
1373  $label = implode($this->getTooltipContentArray($params));
1374  }
1375 
1376  $url = DOL_URL_ROOT.'/holiday/card.php?id='.$this->id;
1377 
1378  //if ($option != 'nolink')
1379  //{
1380  // Add param to save lastsearch_values or not
1381  $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1382  if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1383  $add_save_lastsearch_values = 1;
1384  }
1385  if ($add_save_lastsearch_values) {
1386  $url .= '&save_lastsearch_values=1';
1387  }
1388  //}
1389 
1390  $linkclose = '';
1391  if (empty($notooltip)) {
1392  if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1393  $label = $langs->trans("ShowMyObject");
1394  $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
1395  }
1396  $linkclose .= ($label ? ' title="'.dol_escape_htmltag($label, 1).'"' : ' title="tocomplete"');
1397  $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
1398  } else {
1399  $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1400  }
1401 
1402  $linkstart = '<a href="'.$url.'"';
1403  $linkstart .= $linkclose.'>';
1404  $linkend = '</a>';
1405 
1406  $result .= $linkstart;
1407 
1408  if ($withpicto) {
1409  $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"'), 0, 0, $notooltip ? 0 : 1);
1410  }
1411  if ($withpicto != 2) {
1412  $result .= $this->ref;
1413  }
1414  $result .= $linkend;
1415 
1416  global $action;
1417  $hookmanager->initHooks(array($this->element . 'dao'));
1418  $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
1419  $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1420  if ($reshook > 0) {
1421  $result = $hookmanager->resPrint;
1422  } else {
1423  $result .= $hookmanager->resPrint;
1424  }
1425  return $result;
1426  }
1427 
1428 
1435  public function getLibStatut($mode = 0)
1436  {
1437  return $this->LibStatut($this->statut, $mode, $this->date_debut);
1438  }
1439 
1440  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1449  public function LibStatut($status, $mode = 0, $startdate = '')
1450  {
1451  // phpcs:enable
1452  global $langs;
1453 
1454  if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
1455  global $langs;
1456  //$langs->load("mymodule");
1457  $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('DraftCP');
1458  $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('ToReviewCP');
1459  $this->labelStatus[self::STATUS_APPROVED] = $langs->transnoentitiesnoconv('ApprovedCP');
1460  $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('CancelCP');
1461  $this->labelStatus[self::STATUS_REFUSED] = $langs->transnoentitiesnoconv('RefuseCP');
1462  $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('DraftCP');
1463  $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('ToReviewCP');
1464  $this->labelStatusShort[self::STATUS_APPROVED] = $langs->transnoentitiesnoconv('ApprovedCP');
1465  $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('CancelCP');
1466  $this->labelStatusShort[self::STATUS_REFUSED] = $langs->transnoentitiesnoconv('RefuseCP');
1467  }
1468 
1469  $params = array();
1470  $statusType = 'status6';
1471  if (!empty($startdate) && $startdate >= dol_now()) { // If not yet passed, we use a green "in live" color
1472  $statusType = 'status4';
1473  $params = array('tooltip'=>$this->labelStatus[$status].' - '.$langs->trans("Forthcoming"));
1474  }
1475  if ($status == self::STATUS_DRAFT) {
1476  $statusType = 'status0';
1477  }
1478  if ($status == self::STATUS_VALIDATED) {
1479  $statusType = 'status1';
1480  }
1481  if ($status == self::STATUS_CANCELED) {
1482  $statusType = 'status5';
1483  }
1484  if ($status == self::STATUS_REFUSED) {
1485  $statusType = 'status5';
1486  }
1487 
1488  return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode, '', $params);
1489  }
1490 
1491 
1500  public function selectStatutCP($selected = '', $htmlname = 'select_statut', $morecss = 'minwidth125')
1501  {
1502  global $langs;
1503 
1504  // Liste des statuts
1505  $name = array('DraftCP', 'ToReviewCP', 'ApprovedCP', 'CancelCP', 'RefuseCP');
1506  $nb = count($name) + 1;
1507 
1508  // Select HTML
1509  $out = '<select name="'.$htmlname.'" id="'.$htmlname.'" class="flat'.($morecss ? ' '.$morecss : '').'">'."\n";
1510  $out .= '<option value="-1">&nbsp;</option>'."\n";
1511 
1512  // Boucle des statuts
1513  for ($i = 1; $i < $nb; $i++) {
1514  if ($i == $selected) {
1515  $out .= '<option value="'.$i.'" selected>'.$langs->trans($name[$i - 1]).'</option>'."\n";
1516  } else {
1517  $out .= '<option value="'.$i.'">'.$langs->trans($name[$i - 1]).'</option>'."\n";
1518  }
1519  }
1520 
1521  $out .= '</select>'."\n";
1522 
1523  $showempty= 0;
1524  $out .= ajax_combobox($htmlname, array(), 0, 0, 'resolve', ($showempty < 0 ? (string) $showempty : '-1'), $morecss);
1525 
1526  return $out;
1527  }
1528 
1536  public function updateConfCP($name, $value)
1537  {
1538 
1539  $sql = "UPDATE ".MAIN_DB_PREFIX."holiday_config SET";
1540  $sql .= " value = '".$this->db->escape($value)."'";
1541  $sql .= " WHERE name = '".$this->db->escape($name)."'";
1542 
1543  dol_syslog(get_class($this).'::updateConfCP name='.$name, LOG_DEBUG);
1544  $result = $this->db->query($sql);
1545  if ($result) {
1546  return true;
1547  }
1548 
1549  return false;
1550  }
1551 
1560  public function getConfCP($name, $createifnotfound = '')
1561  {
1562  $sql = "SELECT value";
1563  $sql .= " FROM ".MAIN_DB_PREFIX."holiday_config";
1564  $sql .= " WHERE name = '".$this->db->escape($name)."'";
1565 
1566  dol_syslog(get_class($this).'::getConfCP name='.$name.' createifnotfound='.$createifnotfound, LOG_DEBUG);
1567  $result = $this->db->query($sql);
1568 
1569  if ($result) {
1570  $obj = $this->db->fetch_object($result);
1571  // Return value
1572  if (empty($obj)) {
1573  if ($createifnotfound) {
1574  $sql = "INSERT INTO ".MAIN_DB_PREFIX."holiday_config(name, value)";
1575  $sql .= " VALUES('".$this->db->escape($name)."', '".$this->db->escape($createifnotfound)."')";
1576  $result = $this->db->query($sql);
1577  if ($result) {
1578  return $createifnotfound;
1579  } else {
1580  $this->error = $this->db->lasterror();
1581  return -2;
1582  }
1583  } else {
1584  return '';
1585  }
1586  } else {
1587  return $obj->value;
1588  }
1589  } else {
1590  // Erreur SQL
1591  $this->error = $this->db->lasterror();
1592  return -1;
1593  }
1594  }
1595 
1604  public function updateSoldeCP($userID = '', $nbHoliday = '', $fk_type = '')
1605  {
1606  global $user, $langs;
1607 
1608  $error = 0;
1609 
1610  if (empty($userID) && empty($nbHoliday) && empty($fk_type)) {
1611  $langs->load("holiday");
1612 
1613  // Si mise à jour pour tout le monde en début de mois
1614  $now = dol_now();
1615 
1616  $month = date('m', $now);
1617  $newdateforlastupdate = dol_print_date($now, '%Y%m%d%H%M%S');
1618 
1619  // Get month of last update
1620  $lastUpdate = $this->getConfCP('lastUpdate', $newdateforlastupdate);
1621  $monthLastUpdate = $lastUpdate[4].$lastUpdate[5];
1622  //print 'month: '.$month.' lastUpdate:'.$lastUpdate.' monthLastUpdate:'.$monthLastUpdate;exit;
1623 
1624  // If month date is not same than the one of last update (the one we saved in database), then we update the timestamp and balance of each open user.
1625  if ($month != $monthLastUpdate) {
1626  $this->db->begin();
1627 
1628  $users = $this->fetchUsers(false, false, ' AND u.statut > 0');
1629  $nbUser = count($users);
1630 
1631  $sql = "UPDATE ".MAIN_DB_PREFIX."holiday_config SET";
1632  $sql .= " value = '".$this->db->escape($newdateforlastupdate)."'";
1633  $sql .= " WHERE name = 'lastUpdate'";
1634  $result = $this->db->query($sql);
1635 
1636  $typeleaves = $this->getTypes(1, 1);
1637 
1638  // Update each user counter
1639  foreach ($users as $userCounter) {
1640  $nbDaysToAdd = (isset($typeleaves[$userCounter['type']]['newbymonth']) ? $typeleaves[$userCounter['type']]['newbymonth'] : 0);
1641  if (empty($nbDaysToAdd)) {
1642  continue;
1643  }
1644 
1645  dol_syslog("We update leave type id ".$userCounter['type']." for user id ".$userCounter['rowid'], LOG_DEBUG);
1646 
1647  $nowHoliday = $userCounter['nb_holiday'];
1648  $newSolde = $nowHoliday + $nbDaysToAdd;
1649 
1650  // We add a log for each user
1651  $this->addLogCP($user->id, $userCounter['rowid'], $langs->trans('HolidaysMonthlyUpdate'), $newSolde, $userCounter['type']);
1652 
1653  $result = $this->updateSoldeCP($userCounter['rowid'], $newSolde, $userCounter['type']);
1654 
1655  if ($result < 0) {
1656  $error++;
1657  break;
1658  }
1659  }
1660 
1661  if (!$error) {
1662  $this->db->commit();
1663  return 1;
1664  } else {
1665  $this->db->rollback();
1666  return -1;
1667  }
1668  }
1669 
1670  return 0;
1671  } else {
1672  // Mise à jour pour un utilisateur
1673  $nbHoliday = price2num($nbHoliday, 5);
1674 
1675  $sql = "SELECT nb_holiday FROM ".MAIN_DB_PREFIX."holiday_users";
1676  $sql .= " WHERE fk_user = ".(int) $userID." AND fk_type = ".(int) $fk_type;
1677  $resql = $this->db->query($sql);
1678  if ($resql) {
1679  $num = $this->db->num_rows($resql);
1680 
1681  if ($num > 0) {
1682  // Update for user
1683  $sql = "UPDATE ".MAIN_DB_PREFIX."holiday_users SET";
1684  $sql .= " nb_holiday = ".((float) $nbHoliday);
1685  $sql .= " WHERE fk_user = ".(int) $userID." AND fk_type = ".(int) $fk_type;
1686  $result = $this->db->query($sql);
1687  if (!$result) {
1688  $error++;
1689  $this->errors[] = $this->db->lasterror();
1690  }
1691  } else {
1692  // Insert for user
1693  $sql = "INSERT INTO ".MAIN_DB_PREFIX."holiday_users(nb_holiday, fk_user, fk_type) VALUES (";
1694  $sql .= ((float) $nbHoliday);
1695  $sql .= ", ".(int) $userID.", ".(int) $fk_type.")";
1696  $result = $this->db->query($sql);
1697  if (!$result) {
1698  $error++;
1699  $this->errors[] = $this->db->lasterror();
1700  }
1701  }
1702  } else {
1703  $this->errors[] = $this->db->lasterror();
1704  $error++;
1705  }
1706 
1707  if (!$error) {
1708  return 1;
1709  } else {
1710  return -1;
1711  }
1712  }
1713  }
1714 
1722  public function createCPusers($single = false, $userid = '')
1723  {
1724  // do we have to add balance for all users ?
1725  if (!$single) {
1726  dol_syslog(get_class($this).'::createCPusers');
1727  $arrayofusers = $this->fetchUsers(false, true);
1728 
1729  foreach ($arrayofusers as $users) {
1730  $sql = "INSERT INTO ".MAIN_DB_PREFIX."holiday_users";
1731  $sql .= " (fk_user, nb_holiday)";
1732  $sql .= " VALUES (".((int) $users['rowid'])."', '0')";
1733 
1734  $resql = $this->db->query($sql);
1735  if (!$resql) {
1736  dol_print_error($this->db);
1737  }
1738  }
1739  } else {
1740  $sql = "INSERT INTO ".MAIN_DB_PREFIX."holiday_users";
1741  $sql .= " (fk_user, nb_holiday)";
1742  $sql .= " VALUES (".((int) $userid)."', '0')";
1743 
1744  $resql = $this->db->query($sql);
1745  if (!$resql) {
1746  dol_print_error($this->db);
1747  }
1748  }
1749  }
1750 
1758  public function getCPforUser($user_id, $fk_type = 0)
1759  {
1760  $sql = "SELECT nb_holiday";
1761  $sql .= " FROM ".MAIN_DB_PREFIX."holiday_users";
1762  $sql .= " WHERE fk_user = ".(int) $user_id;
1763  if ($fk_type > 0) {
1764  $sql .= " AND fk_type = ".(int) $fk_type;
1765  }
1766 
1767  dol_syslog(get_class($this).'::getCPforUser user_id='.$user_id.' type_id='.$fk_type, LOG_DEBUG);
1768  $result = $this->db->query($sql);
1769  if ($result) {
1770  $obj = $this->db->fetch_object($result);
1771  //return number_format($obj->nb_holiday,2);
1772  if ($obj) {
1773  return $obj->nb_holiday;
1774  } else {
1775  return null;
1776  }
1777  } else {
1778  return null;
1779  }
1780  }
1781 
1790  public function fetchUsers($stringlist = true, $type = true, $filters = '')
1791  {
1792  global $conf;
1793 
1794  dol_syslog(get_class($this)."::fetchUsers", LOG_DEBUG);
1795 
1796  if ($stringlist) {
1797  if ($type) {
1798  // If user of Dolibarr
1799  $sql = "SELECT";
1800  if (isModEnabled('multicompany') && !empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) {
1801  $sql .= " DISTINCT";
1802  }
1803  $sql .= " u.rowid";
1804  $sql .= " FROM ".MAIN_DB_PREFIX."user as u";
1805 
1806  if (isModEnabled('multicompany') && !empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) {
1807  $sql .= ", ".MAIN_DB_PREFIX."usergroup_user as ug";
1808  $sql .= " WHERE ((ug.fk_user = u.rowid";
1809  $sql .= " AND ug.entity IN (".getEntity('usergroup')."))";
1810  $sql .= " OR u.entity = 0)"; // Show always superadmin
1811  } else {
1812  $sql .= " WHERE u.entity IN (".getEntity('user').")";
1813  }
1814  $sql .= " AND u.statut > 0";
1815  $sql .= " AND u.employee = 1"; // We only want employee users for holidays
1816  if ($filters) {
1817  $sql .= $filters;
1818  }
1819 
1820  $resql = $this->db->query($sql);
1821 
1822  // Si pas d'erreur SQL
1823  if ($resql) {
1824  $i = 0;
1825  $num = $this->db->num_rows($resql);
1826  $stringlist = '';
1827 
1828  // Boucles du listage des utilisateurs
1829  while ($i < $num) {
1830  $obj = $this->db->fetch_object($resql);
1831 
1832  if ($i == 0) {
1833  $stringlist .= $obj->rowid;
1834  } else {
1835  $stringlist .= ', '.$obj->rowid;
1836  }
1837 
1838  $i++;
1839  }
1840  // Retoune le tableau des utilisateurs
1841  return $stringlist;
1842  } else {
1843  // Erreur SQL
1844  $this->error = "Error ".$this->db->lasterror();
1845  return -1;
1846  }
1847  } else {
1848  // We want only list of vacation balance for user ids
1849  $sql = "SELECT DISTINCT cpu.fk_user";
1850  $sql .= " FROM ".MAIN_DB_PREFIX."holiday_users as cpu, ".MAIN_DB_PREFIX."user as u";
1851  $sql .= " WHERE cpu.fk_user = u.rowid";
1852  if ($filters) {
1853  $sql .= $filters;
1854  }
1855 
1856  $resql = $this->db->query($sql);
1857 
1858  // Si pas d'erreur SQL
1859  if ($resql) {
1860  $i = 0;
1861  $num = $this->db->num_rows($resql);
1862  $stringlist = '';
1863 
1864  // Boucles du listage des utilisateurs
1865  while ($i < $num) {
1866  $obj = $this->db->fetch_object($resql);
1867 
1868  if ($i == 0) {
1869  $stringlist .= $obj->fk_user;
1870  } else {
1871  $stringlist .= ', '.$obj->fk_user;
1872  }
1873 
1874  $i++;
1875  }
1876  // Retoune le tableau des utilisateurs
1877  return $stringlist;
1878  } else {
1879  // Erreur SQL
1880  $this->error = "Error ".$this->db->lasterror();
1881  return -1;
1882  }
1883  }
1884  } else {
1885  // Si faux donc return array
1886  // List for Dolibarr users
1887  if ($type) {
1888  // If we need users of Dolibarr
1889  $sql = "SELECT";
1890  if (isModEnabled('multicompany') && !empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) {
1891  $sql .= " DISTINCT";
1892  }
1893  $sql .= " u.rowid, u.lastname, u.firstname, u.gender, u.photo, u.employee, u.statut, u.fk_user";
1894  $sql .= " FROM ".MAIN_DB_PREFIX."user as u";
1895 
1896  if (isModEnabled('multicompany') && !empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) {
1897  $sql .= ", ".MAIN_DB_PREFIX."usergroup_user as ug";
1898  $sql .= " WHERE ((ug.fk_user = u.rowid";
1899  $sql .= " AND ug.entity IN (".getEntity('usergroup')."))";
1900  $sql .= " OR u.entity = 0)"; // Show always superadmin
1901  } else {
1902  $sql .= " WHERE u.entity IN (".getEntity('user').")";
1903  }
1904 
1905  $sql .= " AND u.statut > 0";
1906  $sql .= " AND u.employee = 1"; // We only want employee users for holidays
1907  if ($filters) {
1908  $sql .= $filters;
1909  }
1910 
1911  $resql = $this->db->query($sql);
1912 
1913  // Si pas d'erreur SQL
1914  if ($resql) {
1915  $i = 0;
1916  $tab_result = $this->holiday;
1917  $num = $this->db->num_rows($resql);
1918 
1919  // Boucles du listage des utilisateurs
1920  while ($i < $num) {
1921  $obj = $this->db->fetch_object($resql);
1922 
1923  $tab_result[$i]['rowid'] = $obj->rowid; // rowid of user
1924  $tab_result[$i]['id'] = $obj->rowid; // id of user
1925  $tab_result[$i]['name'] = $obj->lastname; // deprecated
1926  $tab_result[$i]['lastname'] = $obj->lastname;
1927  $tab_result[$i]['firstname'] = $obj->firstname;
1928  $tab_result[$i]['gender'] = $obj->gender;
1929  $tab_result[$i]['status'] = $obj->statut;
1930  $tab_result[$i]['employee'] = $obj->employee;
1931  $tab_result[$i]['photo'] = $obj->photo;
1932  $tab_result[$i]['fk_user'] = $obj->fk_user; // rowid of manager
1933  //$tab_result[$i]['type'] = $obj->type;
1934  //$tab_result[$i]['nb_holiday'] = $obj->nb_holiday;
1935 
1936  $i++;
1937  }
1938  // Retoune le tableau des utilisateurs
1939  return $tab_result;
1940  } else {
1941  // Erreur SQL
1942  $this->errors[] = "Error ".$this->db->lasterror();
1943  return -1;
1944  }
1945  } else {
1946  // List of vacation balance users
1947  $sql = "SELECT cpu.fk_type, cpu.nb_holiday, u.rowid, u.lastname, u.firstname, u.gender, u.photo, u.employee, u.statut, u.fk_user";
1948  $sql .= " FROM ".MAIN_DB_PREFIX."holiday_users as cpu, ".MAIN_DB_PREFIX."user as u";
1949  $sql .= " WHERE cpu.fk_user = u.rowid";
1950  if ($filters) {
1951  $sql .= $filters;
1952  }
1953 
1954  $resql = $this->db->query($sql);
1955 
1956  // Si pas d'erreur SQL
1957  if ($resql) {
1958  $i = 0;
1959  $tab_result = $this->holiday;
1960  $num = $this->db->num_rows($resql);
1961 
1962  // Boucles du listage des utilisateurs
1963  while ($i < $num) {
1964  $obj = $this->db->fetch_object($resql);
1965 
1966  $tab_result[$i]['rowid'] = $obj->rowid; // rowid of user
1967  $tab_result[$i]['id'] = $obj->rowid; // id of user
1968  $tab_result[$i]['name'] = $obj->lastname; // deprecated
1969  $tab_result[$i]['lastname'] = $obj->lastname;
1970  $tab_result[$i]['firstname'] = $obj->firstname;
1971  $tab_result[$i]['gender'] = $obj->gender;
1972  $tab_result[$i]['status'] = $obj->statut;
1973  $tab_result[$i]['employee'] = $obj->employee;
1974  $tab_result[$i]['photo'] = $obj->photo;
1975  $tab_result[$i]['fk_user'] = $obj->fk_user; // rowid of manager
1976 
1977  $tab_result[$i]['type'] = $obj->fk_type;
1978  $tab_result[$i]['nb_holiday'] = $obj->nb_holiday;
1979 
1980  $i++;
1981  }
1982  // Retoune le tableau des utilisateurs
1983  return $tab_result;
1984  } else {
1985  // Erreur SQL
1986  $this->error = "Error ".$this->db->lasterror();
1987  return -1;
1988  }
1989  }
1990  }
1991  }
1992 
1993 
1994  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2002  {
2003  // phpcs:enable
2004  $users_validator = array();
2005 
2006  $sql = "SELECT DISTINCT ur.fk_user";
2007  $sql .= " FROM ".MAIN_DB_PREFIX."user_rights as ur, ".MAIN_DB_PREFIX."rights_def as rd";
2008  $sql .= " WHERE ur.fk_id = rd.id and rd.module = 'holiday' AND rd.perms = 'approve'"; // Permission 'Approve';
2009  $sql .= "UNION";
2010  $sql .= " SELECT DISTINCT ugu.fk_user";
2011  $sql .= " FROM ".MAIN_DB_PREFIX."usergroup_user as ugu, ".MAIN_DB_PREFIX."usergroup_rights as ur, ".MAIN_DB_PREFIX."rights_def as rd";
2012  $sql .= " WHERE ugu.fk_usergroup = ur.fk_usergroup AND ur.fk_id = rd.id and rd.module = 'holiday' AND rd.perms = 'approve'"; // Permission 'Approve';
2013  //print $sql;
2014 
2015  dol_syslog(get_class($this)."::fetch_users_approver_holiday sql=".$sql);
2016  $result = $this->db->query($sql);
2017  if ($result) {
2018  $num_rows = $this->db->num_rows($result); $i = 0;
2019  while ($i < $num_rows) {
2020  $objp = $this->db->fetch_object($result);
2021  array_push($users_validator, $objp->fk_user);
2022  $i++;
2023  }
2024  return $users_validator;
2025  } else {
2026  $this->error = $this->db->lasterror();
2027  dol_syslog(get_class($this)."::fetch_users_approver_holiday Error ".$this->error, LOG_ERR);
2028  return -1;
2029  }
2030  }
2031 
2032 
2038  public function countActiveUsers()
2039  {
2040  $sql = "SELECT count(u.rowid) as compteur";
2041  $sql .= " FROM ".MAIN_DB_PREFIX."user as u";
2042  $sql .= " WHERE u.statut > 0";
2043 
2044  $result = $this->db->query($sql);
2045  $objet = $this->db->fetch_object($result);
2046 
2047  return $objet->compteur;
2048  }
2054  public function countActiveUsersWithoutCP()
2055  {
2056 
2057  $sql = "SELECT count(u.rowid) as compteur";
2058  $sql .= " FROM ".MAIN_DB_PREFIX."user as u LEFT OUTER JOIN ".MAIN_DB_PREFIX."holiday_users hu ON (hu.fk_user=u.rowid)";
2059  $sql .= " WHERE u.statut > 0 AND hu.fk_user IS NULL";
2060 
2061  $result = $this->db->query($sql);
2062  $objet = $this->db->fetch_object($result);
2063 
2064  return $objet->compteur;
2065  }
2066 
2074  public function verifNbUsers($userDolibarrWithoutCP, $userCP)
2075  {
2076  if (empty($userCP)) {
2077  $userCP = 0;
2078  }
2079  dol_syslog(get_class($this).'::verifNbUsers userDolibarr='.$userDolibarrWithoutCP.' userCP='.$userCP);
2080  return 1;
2081  }
2082 
2083 
2094  public function addLogCP($fk_user_action, $fk_user_update, $label, $new_solde, $fk_type)
2095  {
2096  global $conf, $langs;
2097 
2098  $error = 0;
2099 
2100  $prev_solde = price2num($this->getCPforUser($fk_user_update, $fk_type), 5);
2101  $new_solde = price2num($new_solde, 5);
2102  //print "$prev_solde == $new_solde";
2103 
2104  if ($prev_solde == $new_solde) {
2105  return 0;
2106  }
2107 
2108  $this->db->begin();
2109 
2110  // Insert request
2111  $sql = "INSERT INTO ".MAIN_DB_PREFIX."holiday_logs (";
2112  $sql .= "date_action,";
2113  $sql .= "fk_user_action,";
2114  $sql .= "fk_user_update,";
2115  $sql .= "type_action,";
2116  $sql .= "prev_solde,";
2117  $sql .= "new_solde,";
2118  $sql .= "fk_type";
2119  $sql .= ") VALUES (";
2120  $sql .= " '".$this->db->idate(dol_now())."',";
2121  $sql .= " ".((int) $fk_user_action).",";
2122  $sql .= " ".((int) $fk_user_update).",";
2123  $sql .= " '".$this->db->escape($label)."',";
2124  $sql .= " ".((float) $prev_solde).",";
2125  $sql .= " ".((float) $new_solde).",";
2126  $sql .= " ".((int) $fk_type);
2127  $sql .= ")";
2128 
2129  $resql = $this->db->query($sql);
2130  if (!$resql) {
2131  $error++; $this->errors[] = "Error ".$this->db->lasterror();
2132  }
2133 
2134  if (!$error) {
2135  $this->optRowid = $this->db->last_insert_id(MAIN_DB_PREFIX."holiday_logs");
2136  }
2137 
2138  // Commit or rollback
2139  if ($error) {
2140  foreach ($this->errors as $errmsg) {
2141  dol_syslog(get_class($this)."::addLogCP ".$errmsg, LOG_ERR);
2142  $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
2143  }
2144  $this->db->rollback();
2145  return -1 * $error;
2146  } else {
2147  $this->db->commit();
2148  return $this->optRowid;
2149  }
2150  }
2151 
2159  public function fetchLog($order, $filter)
2160  {
2161  $sql = "SELECT";
2162  $sql .= " cpl.rowid,";
2163  $sql .= " cpl.date_action,";
2164  $sql .= " cpl.fk_user_action,";
2165  $sql .= " cpl.fk_user_update,";
2166  $sql .= " cpl.type_action,";
2167  $sql .= " cpl.prev_solde,";
2168  $sql .= " cpl.new_solde,";
2169  $sql .= " cpl.fk_type";
2170  $sql .= " FROM ".MAIN_DB_PREFIX."holiday_logs as cpl";
2171  $sql .= " WHERE cpl.rowid > 0"; // To avoid error with other search and criteria
2172 
2173  // Filtrage de séléction
2174  if (!empty($filter)) {
2175  $sql .= " ".$filter;
2176  }
2177 
2178  // Ordre d'affichage
2179  if (!empty($order)) {
2180  $sql .= " ".$order;
2181  }
2182 
2183  dol_syslog(get_class($this)."::fetchLog", LOG_DEBUG);
2184  $resql = $this->db->query($sql);
2185 
2186  // Si pas d'erreur SQL
2187  if ($resql) {
2188  $i = 0;
2189  $tab_result = $this->logs;
2190  $num = $this->db->num_rows($resql);
2191 
2192  // Si pas d'enregistrement
2193  if (!$num) {
2194  return 2;
2195  }
2196 
2197  // On liste les résultats et on les ajoutent dans le tableau
2198  while ($i < $num) {
2199  $obj = $this->db->fetch_object($resql);
2200 
2201  $tab_result[$i]['rowid'] = $obj->rowid;
2202  $tab_result[$i]['id'] = $obj->rowid;
2203  $tab_result[$i]['date_action'] = $obj->date_action;
2204  $tab_result[$i]['fk_user_action'] = $obj->fk_user_action;
2205  $tab_result[$i]['fk_user_update'] = $obj->fk_user_update;
2206  $tab_result[$i]['type_action'] = $obj->type_action;
2207  $tab_result[$i]['prev_solde'] = $obj->prev_solde;
2208  $tab_result[$i]['new_solde'] = $obj->new_solde;
2209  $tab_result[$i]['fk_type'] = $obj->fk_type;
2210 
2211  $i++;
2212  }
2213  // Retourne 1 et ajoute le tableau à la variable
2214  $this->logs = $tab_result;
2215  return 1;
2216  } else {
2217  // Erreur SQL
2218  $this->error = "Error ".$this->db->lasterror();
2219  return -1;
2220  }
2221  }
2222 
2223 
2231  public function getTypes($active = -1, $affect = -1)
2232  {
2233  global $mysoc;
2234 
2235  $sql = "SELECT rowid, code, label, affect, delay, newbymonth";
2236  $sql .= " FROM ".MAIN_DB_PREFIX."c_holiday_types";
2237  $sql .= " WHERE (fk_country IS NULL OR fk_country = ".((int) $mysoc->country_id).')';
2238  if ($active >= 0) {
2239  $sql .= " AND active = ".((int) $active);
2240  }
2241  if ($affect >= 0) {
2242  $sql .= " AND affect = ".((int) $affect);
2243  }
2244  $sql .= " ORDER BY sortorder";
2245 
2246  $result = $this->db->query($sql);
2247  if ($result) {
2248  $num = $this->db->num_rows($result);
2249  if ($num) {
2250  while ($obj = $this->db->fetch_object($result)) {
2251  $types[$obj->rowid] = array('id'=> $obj->rowid, 'rowid'=> $obj->rowid, 'code'=> $obj->code, 'label'=>$obj->label, 'affect'=>$obj->affect, 'delay'=>$obj->delay, 'newbymonth'=>$obj->newbymonth);
2252  }
2253 
2254  return $types;
2255  }
2256  } else {
2257  dol_print_error($this->db);
2258  }
2259 
2260  return array();
2261  }
2262 
2263 
2270  public function info($id)
2271  {
2272  global $conf;
2273 
2274  $sql = "SELECT f.rowid, f.statut as status,";
2275  $sql .= " f.date_create as datec,";
2276  $sql .= " f.tms as date_modification,";
2277  $sql .= " f.date_valid as datev,";
2278  $sql .= " f.date_approval as datea,";
2279  $sql .= " f.date_refuse as dater,";
2280  $sql .= " f.fk_user_create as fk_user_creation,";
2281  $sql .= " f.fk_user_modif as fk_user_modification,";
2282  $sql .= " f.fk_user_valid as fk_user_validation,";
2283  $sql .= " f.fk_user_approve as fk_user_approval_done,";
2284  $sql .= " f.fk_validator as fk_user_approval_expected,";
2285  $sql .= " f.fk_user_refuse as fk_user_refuse";
2286  $sql .= " FROM ".MAIN_DB_PREFIX."holiday as f";
2287  $sql .= " WHERE f.rowid = ".((int) $id);
2288  $sql .= " AND f.entity = ".$conf->entity;
2289 
2290  $resql = $this->db->query($sql);
2291  if ($resql) {
2292  if ($this->db->num_rows($resql)) {
2293  $obj = $this->db->fetch_object($resql);
2294 
2295  $this->id = $obj->rowid;
2296 
2297  $this->date_creation = $this->db->jdate($obj->datec);
2298  $this->date_modification = $this->db->jdate($obj->date_modification);
2299  $this->date_validation = $this->db->jdate($obj->datev);
2300  $this->date_approval = $this->db->jdate($obj->datea);
2301 
2302  if (!empty($obj->fk_user_creation)) {
2303  $cuser = new User($this->db);
2304  $cuser->fetch($obj->fk_user_creation);
2305  $this->user_creation = $cuser;
2306  }
2307  if (!empty($obj->fk_user_valid)) {
2308  $vuser = new User($this->db);
2309  $vuser->fetch($obj->fk_user_valid);
2310  $this->user_validation = $vuser;
2311  }
2312  if (!empty($obj->fk_user_modification)) {
2313  $muser = new User($this->db);
2314  $muser->fetch($obj->fk_user_modification);
2315  $this->user_modification = $muser;
2316  }
2317 
2318  if ($obj->status == Holiday::STATUS_APPROVED || $obj->status == Holiday::STATUS_CANCELED) {
2319  if ($obj->fk_user_approval_done) {
2320  $auser = new User($this->db);
2321  $auser->fetch($obj->fk_user_approval_done);
2322  $this->user_approve = $auser;
2323  }
2324  }
2325  }
2326  $this->db->free($resql);
2327  } else {
2328  dol_print_error($this->db);
2329  }
2330  }
2331 
2332 
2340  public function initAsSpecimen()
2341  {
2342  global $user, $langs;
2343 
2344  // Initialise parameters
2345  $this->id = 0;
2346  $this->specimen = 1;
2347 
2348  $this->fk_user = $user->id;
2349  $this->description = 'SPECIMEN description';
2350  $this->date_debut = dol_now();
2351  $this->date_fin = dol_now() + (24 * 3600);
2352  $this->date_valid = dol_now();
2353  $this->fk_validator = $user->id;
2354  $this->halfday = 0;
2355  $this->fk_type = 1;
2356  $this->statut = Holiday::STATUS_VALIDATED;
2357  }
2358 
2359  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2365  public function load_state_board()
2366  {
2367  // phpcs:enable
2368  global $user;
2369 
2370  $this->nb = array();
2371 
2372  $sql = "SELECT count(h.rowid) as nb";
2373  $sql .= " FROM ".MAIN_DB_PREFIX."holiday as h";
2374  $sql .= " WHERE h.statut > 1";
2375  $sql .= " AND h.entity IN (".getEntity('holiday').")";
2376  if (empty($user->rights->expensereport->readall)) {
2377  $userchildids = $user->getAllChildIds(1);
2378  $sql .= " AND (h.fk_user IN (".$this->db->sanitize(join(',', $userchildids)).")";
2379  $sql .= " OR h.fk_validator IN (".$this->db->sanitize(join(',', $userchildids))."))";
2380  }
2381 
2382  $resql = $this->db->query($sql);
2383  if ($resql) {
2384  while ($obj = $this->db->fetch_object($resql)) {
2385  $this->nb["holidays"] = $obj->nb;
2386  }
2387  $this->db->free($resql);
2388  return 1;
2389  } else {
2390  dol_print_error($this->db);
2391  $this->error = $this->db->error();
2392  return -1;
2393  }
2394  }
2395 
2396  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2403  public function load_board($user)
2404  {
2405  // phpcs:enable
2406  global $conf, $langs;
2407 
2408  if ($user->socid) {
2409  return -1; // protection pour eviter appel par utilisateur externe
2410  }
2411 
2412  $now = dol_now();
2413 
2414  $sql = "SELECT h.rowid, h.date_debut";
2415  $sql .= " FROM ".MAIN_DB_PREFIX."holiday as h";
2416  $sql .= " WHERE h.statut = 2";
2417  $sql .= " AND h.entity IN (".getEntity('holiday').")";
2418  if (empty($user->rights->expensereport->read_all)) {
2419  $userchildids = $user->getAllChildIds(1);
2420  $sql .= " AND (h.fk_user IN (".$this->db->sanitize(join(',', $userchildids)).")";
2421  $sql .= " OR h.fk_validator IN (".$this->db->sanitize(join(',', $userchildids))."))";
2422  }
2423 
2424  $resql = $this->db->query($sql);
2425  if ($resql) {
2426  $langs->load("members");
2427 
2428  $response = new WorkboardResponse();
2429  $response->warning_delay = $conf->holiday->approve->warning_delay / 60 / 60 / 24;
2430  $response->label = $langs->trans("HolidaysToApprove");
2431  $response->labelShort = $langs->trans("ToApprove");
2432  $response->url = DOL_URL_ROOT.'/holiday/list.php?search_status=2&amp;mainmenu=hrm&amp;leftmenu=holiday';
2433  $response->img = img_object('', "holiday");
2434 
2435  while ($obj = $this->db->fetch_object($resql)) {
2436  $response->nbtodo++;
2437 
2438  if ($this->db->jdate($obj->date_debut) < ($now - $conf->holiday->approve->warning_delay)) {
2439  $response->nbtodolate++;
2440  }
2441  }
2442 
2443  return $response;
2444  } else {
2445  dol_print_error($this->db);
2446  $this->error = $this->db->error();
2447  return -1;
2448  }
2449  }
2457  public function getKanbanView($option = '', $arraydata = null)
2458  {
2459  global $langs;
2460 
2461  $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
2462 
2463  $return = '<div class="box-flex-item box-flex-grow-zero">';
2464  $return .= '<div class="info-box info-box-sm">';
2465  $return .= '<span class="info-box-icon bg-infobox-action">';
2466  $return .= img_picto('', $this->picto);
2467  $return .= '</span>';
2468  $return .= '<div class="info-box-content">';
2469  $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.$arraydata['user']->getNomUrl(-1).'</span>';
2470  $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
2471  if (property_exists($this, 'fk_type')) {
2472  $return .= '<br>';
2473  //$return .= '<span class="opacitymedium">'.$langs->trans("Type").'</span> : ';
2474  $return .= '<span class="info_box-label maxwidth100">'.$arraydata['labeltype'].'</span>';
2475  }
2476  if (property_exists($this, 'date_debut') && property_exists($this, 'date_fin')) {
2477  $return .= '<br><span class="info-box-label small">'.dol_print_date($this->date_debut, 'day').'</span>';
2478  $return .= ' <span class="opacitymedium small">'.$langs->trans("To").'</span> ';
2479  $return .= '<span class="info-box-label small">'.dol_print_date($this->date_fin, 'day').'</span>';
2480  }
2481  if (method_exists($this, 'getLibStatut')) {
2482  $return .= '<br><div class="info-box-status margintoponly">'.$this->getLibStatut(3).'</div>';
2483  }
2484  $return .= '</div>';
2485  $return .= '</div>';
2486  $return .= '</div>';
2487  return $return;
2488  }
2489 }
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve', $idforemptyvalue='-1', $morecss='')
Convert a html select field into an ajax combobox.
Definition: ajax.lib.php:449
$object ref
Definition: info.php:78
Parent class of all other business classes (invoices, contracts, proposals, orders,...
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this->array_options This method is in most cases call...
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Class of the module paid holiday.
getTypes($active=-1, $affect=-1)
Return array with list of types.
getNomUrl($withpicto=0, $save_lastsearch_value=-1, $notooltip=0, $morecss='')
Return clicable name (with picto eventually)
verifDateHolidayCP($fk_user, $dateStart, $dateEnd, $halfday=0)
Check if a user is on holiday (partially or completely) into a period.
validate($user=null, $notrigger=0)
Validate leave request.
info($id)
Load information on object.
updateBalance()
Update balance of vacations and check table of users for holidays is complete.
updateConfCP($name, $value)
Met à jour une option du module Holiday Payés.
const STATUS_VALIDATED
Validated status.
load_state_board()
Load this->nb for dashboard.
const STATUS_DRAFT
Draft status.
createCPusers($single=false, $userid='')
Create entries for each user at setup step.
fetch($id, $ref='')
Load object in memory from database.
addLogCP($fk_user_action, $fk_user_update, $label, $new_solde, $fk_type)
addLogCP
verifNbUsers($userDolibarrWithoutCP, $userCP)
Compare le nombre d'utilisateur actif de Dolibarr à celui des utilisateurs des congés payés.
verifDateHolidayForTimestamp($fk_user, $timestamp, $status='-1')
Check that a user is not on holiday for a particular timestamp.
updateSoldeCP($userID='', $nbHoliday='', $fk_type='')
Met à jour le timestamp de la dernière mise à jour du solde des CP.
approve($user=null, $notrigger=0)
Approve leave request.
getNextNumRef($objsoc)
Returns the reference to the following non used Order depending on the active numbering module define...
const STATUS_REFUSED
Refused.
getConfCP($name, $createifnotfound='')
Return value of a conf parameter for leave module TODO Move this into llx_const table.
load_board($user)
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
initAsSpecimen()
Initialise an instance with random values.
selectStatutCP($selected='', $htmlname='select_statut', $morecss='minwidth125')
Affiche un select HTML des statuts de congés payés.
create($user, $notrigger=0)
Créer un congés payés dans la base de données.
countActiveUsersWithoutCP()
Compte le nombre d'utilisateur actifs dans Dolibarr sans CP.
fetchLog($order, $filter)
Liste le log des congés payés.
update($user=null, $notrigger=0)
Update database.
getCPforUser($user_id, $fk_type=0)
Return balance of holiday for one user.
fetch_users_approver_holiday()
Return list of people with permission to validate leave requests.
__construct($db)
Constructor.
getLibStatut($mode=0)
Returns the label status.
fetchAll($order, $filter)
List all holidays of all users.
const STATUS_CANCELED
Canceled.
countActiveUsers()
Compte le nombre d'utilisateur actifs dans Dolibarr.
fetchByUser($user_id, $order='', $filter='')
List holidays for a particular user or list of users.
const STATUS_APPROVED
Approved.
getTooltipContentArray($params)
getTooltipContentArray
fetchUsers($stringlist=true, $type=true, $filters='')
Get list of Users or list of vacation balance.
getKanbanView($option='', $arraydata=null)
Return clicable link of object (with eventually picto)
LibStatut($status, $mode=0, $startdate='')
Returns the label of a status.
Class to manage Dolibarr users.
Definition: user.class.php:48
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
print *****$script_file(".$version.") pid cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition: files.lib.php:62
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
isModEnabled($module)
Is Dolibarr module enabled.
getDictionaryValue($tablename, $field, $id, $checkentity=false, $rowidfield='rowid')
Return the value of a filed into a dictionary for the record $id.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
div float
Buy price without taxes.
Definition: style.css.php:921