dolibarr 24.0.2
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-2026 Frédéric France <frederic.france@free.fr>
8 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
9 * Copyright (C) 2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23 */
24
30require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
31
32
36class Holiday extends CommonObject
37{
41 public $element = 'holiday';
42
47 public $TRIGGER_PREFIX = 'HOLIDAY';
48
52 public $table_element = 'holiday';
53
57 public $fk_element = 'fk_holiday';
58
62 public $picto = 'holiday';
63
67 public $fk_user;
68
72 public $date_create = '';
73
77 public $description;
78
82 public $date_debut = '';
83
87 public $date_fin = '';
88
92 public $date_debut_gmt = '';
93
97 public $date_fin_gmt = '';
98
102 public $halfday = '';
103
108 public $statut = 0;
109
113 public $fk_validator;
114
118 public $date_valid = 0;
119
123 public $fk_user_valid;
124
128 public $date_approval;
129
133 public $fk_user_approve;
134
138 public $date_refuse = 0;
139
143 public $fk_user_refuse;
144
148 public $date_cancel = 0;
149
153 public $fk_user_cancel;
154
158 public $fk_user_create;
159
163 public $detail_refuse = '';
164
168 public $fk_type;
169
173 public $holiday = array();
174
175 public $events = array();
176
180 public $logs = array();
181
182
186 const STATUS_DRAFT = 1;
202 const STATUS_REFUSED = 5;
203
204
210 public function __construct($db)
211 {
212 $this->db = $db;
213
214 $this->ismultientitymanaged = 0;
215 }
216
217
225 public function getNextNumRef($objsoc)
226 {
227 global $langs, $conf;
228 $langs->load("order");
229
230 if (!getDolGlobalString('HOLIDAY_ADDON')) {
231 $conf->global->HOLIDAY_ADDON = 'mod_holiday_madonna';
232 }
233
234 if (getDolGlobalString('HOLIDAY_ADDON')) {
235 $mybool = false;
236
237 $file = getDolGlobalString('HOLIDAY_ADDON') . ".php";
238 $classname = getDolGlobalString('HOLIDAY_ADDON');
239
240 // Include file with class
241 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
242 foreach ($dirmodels as $reldir) {
243 $dir = dol_buildpath($reldir."core/modules/holiday/");
244
245 // Load file with numbering class (if found)
246 $mybool = ((bool) @include_once $dir.$file) || $mybool;
247 }
248
249 if (!$mybool) {
250 dol_print_error(null, "Failed to include file ".$file);
251 return '';
252 }
253
254 $obj = new $classname();
255 '@phan-var-force ModelNumRefHolidays $obj';
257 $numref = $obj->getNextValue($objsoc, $this);
258
259 if ($numref != "") {
260 return $numref;
261 } else {
262 $this->error = $obj->error;
263 //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
264 return "";
265 }
266 } else {
267 print $langs->trans("Error")." ".$langs->trans("Error_HOLIDAY_ADDON_NotDefined");
268 return "";
269 }
270 }
271
277 public function updateBalance()
278 {
279 $this->db->begin();
280
281 // Update sold of vocations
282 $result = $this->updateSoldeCP();
283
284 // Check nb of users into table llx_holiday_users and update with empty lines
285 //if ($result > 0) $result = $this->verifNbUsers($this->countActiveUsersWithoutCP(), $this->getConfCP('nbUser'));
286
287 if ($result >= 0) {
288 $this->db->commit();
289 return 0; // for cronjob use (0 is OK, any other value is an error code)
290 } else {
291 $this->db->rollback();
292 return -1;
293 }
294 }
295
303 public function create($user, $notrigger = 0)
304 {
305 global $conf;
306 $error = 0;
307
308 $now = dol_now();
309
310 // Check parameters
311 if (empty($this->fk_user) || !is_numeric($this->fk_user) || $this->fk_user < 0) {
312 $this->error = "ErrorBadParameterFkUser";
313 return -1;
314 }
315 if (empty($this->fk_validator) || !is_numeric($this->fk_validator) || $this->fk_validator < 0) {
316 $this->error = "ErrorBadParameterFkValidator";
317 return -1;
318 }
319 if (empty($this->fk_type) || !is_numeric($this->fk_type) || $this->fk_type < 0) {
320 $this->error = "ErrorBadParameterFkType";
321 return -1;
322 }
323
324 // Insert request
325 $sql = "INSERT INTO ".MAIN_DB_PREFIX."holiday(";
326 $sql .= "ref,";
327 $sql .= "fk_user,";
328 $sql .= "date_create,";
329 $sql .= "description,";
330 $sql .= "date_debut,";
331 $sql .= "date_fin,";
332 $sql .= "halfday,";
333 $sql .= "statut,";
334 $sql .= "fk_validator,";
335 $sql .= "fk_type,";
336 $sql .= "fk_user_create,";
337 $sql .= "entity";
338 $sql .= ") VALUES (";
339 $sql .= "'(PROV)',";
340 $sql .= " ".((int) $this->fk_user).",";
341 $sql .= " '".$this->db->idate($now)."',";
342 $sql .= " '".$this->db->escape($this->description)."',";
343 $sql .= " '".$this->db->idate($this->date_debut)."',";
344 $sql .= " '".$this->db->idate($this->date_fin)."',";
345 $sql .= " ".((int) $this->halfday).",";
346 $sql .= " '1',";
347 $sql .= " ".((int) $this->fk_validator).",";
348 $sql .= " ".((int) $this->fk_type).",";
349 $sql .= " ".((int) $user->id).",";
350 $sql .= " ".((int) $conf->entity);
351 $sql .= ")";
352
353 $this->db->begin();
354
355 dol_syslog(get_class($this)."::create", LOG_DEBUG);
356 $resql = $this->db->query($sql);
357 if (!$resql) {
358 $error++;
359 $this->errors[] = "Error ".$this->db->lasterror();
360 }
361
362 if (!$error) {
363 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."holiday");
364
365 if ($this->id) {
366 // update ref
367 $initialref = '(PROV'.$this->id.')';
368 if (!empty($this->ref)) {
369 $initialref = $this->ref;
370 }
371
372 $sql = 'UPDATE '.MAIN_DB_PREFIX."holiday SET ref='".$this->db->escape($initialref)."' WHERE rowid=".((int) $this->id);
373 if ($this->db->query($sql)) {
374 $this->ref = $initialref;
375 $result = $this->insertExtraFields();
376 if ($result < 0) {
377 $error++;
378 }
379
380 if (!$error && !$notrigger) {
381 // Call trigger
382 $result = $this->call_trigger('HOLIDAY_CREATE', $user);
383 if ($result < 0) {
384 $error++;
385 }
386 // End call triggers
387 }
388 }
389 }
390 }
391
392 // Commit or rollback
393 if ($error) {
394 foreach ($this->errors as $errmsg) {
395 dol_syslog(get_class($this)."::create ".$errmsg, LOG_ERR);
396 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
397 }
398 $this->db->rollback();
399 return -1 * $error;
400 } else {
401 $this->db->commit();
402 return $this->id;
403 }
404 }
405
406
414 public function fetch($id, $ref = '')
415 {
416 $sql = "SELECT";
417 $sql .= " cp.rowid,";
418 $sql .= " cp.ref,";
419 $sql .= " cp.fk_user,";
420 $sql .= " cp.date_create,";
421 $sql .= " cp.description,";
422 $sql .= " cp.date_debut,";
423 $sql .= " cp.date_fin,";
424 $sql .= " cp.halfday,";
425 $sql .= " cp.statut as status,";
426 $sql .= " cp.fk_validator,";
427 $sql .= " cp.date_valid,";
428 $sql .= " cp.fk_user_valid,";
429 $sql .= " cp.date_approval,";
430 $sql .= " cp.fk_user_approve,";
431 $sql .= " cp.date_refuse,";
432 $sql .= " cp.fk_user_refuse,";
433 $sql .= " cp.date_cancel,";
434 $sql .= " cp.fk_user_cancel,";
435 $sql .= " cp.detail_refuse,";
436 $sql .= " cp.note_private,";
437 $sql .= " cp.note_public,";
438 $sql .= " cp.fk_user_create,";
439 $sql .= " cp.fk_type,";
440 $sql .= " cp.entity";
441 $sql .= " FROM ".MAIN_DB_PREFIX."holiday as cp";
442 if ($id > 0) {
443 $sql .= " WHERE cp.rowid = ".((int) $id);
444 } else {
445 $sql .= " WHERE cp.ref = '".$this->db->escape($ref)."'";
446 }
447
448 dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
449 $resql = $this->db->query($sql);
450 if ($resql) {
451 if ($this->db->num_rows($resql)) {
452 $obj = $this->db->fetch_object($resql);
453
454 $this->id = (int) $obj->rowid;
455 $this->ref = (string) ($obj->ref ? $obj->ref : $obj->rowid);
456 $this->fk_user = (int) $obj->fk_user;
457 $this->date_create = $this->db->jdate($obj->date_create);
458 $this->description = $obj->description;
459 $this->date_debut = $this->db->jdate($obj->date_debut);
460 $this->date_fin = $this->db->jdate($obj->date_fin);
461 $this->date_debut_gmt = $this->db->jdate($obj->date_debut, 1);
462 $this->date_fin_gmt = $this->db->jdate($obj->date_fin, 1);
463 $this->halfday = (int) $obj->halfday;
464 $this->status = (int) $obj->status;
465 $this->statut = (int) $obj->status; // deprecated
466 $this->fk_validator = $obj->fk_validator;
467 $this->date_valid = $this->db->jdate($obj->date_valid);
468 $this->fk_user_valid = $obj->fk_user_valid;
469 $this->user_validation_id = $obj->fk_user_valid;
470 $this->date_approval = $this->db->jdate($obj->date_approval);
471 $this->fk_user_approve = $obj->fk_user_approve;
472 $this->date_refuse = $this->db->jdate($obj->date_refuse);
473 $this->fk_user_refuse = $obj->fk_user_refuse;
474 $this->date_cancel = $this->db->jdate($obj->date_cancel);
475 $this->fk_user_cancel = $obj->fk_user_cancel;
476 $this->detail_refuse = $obj->detail_refuse;
477 $this->note_private = $obj->note_private;
478 $this->note_public = $obj->note_public;
479 $this->fk_user_create = $obj->fk_user_create;
480 $this->fk_type = $obj->fk_type;
481 $this->entity = $obj->entity;
482
483 $this->fetch_optionals();
484
485 $result = 1;
486 } else {
487 $result = 0;
488 }
489 $this->db->free($resql);
490
491 return $result;
492 } else {
493 $this->error = "Error ".$this->db->lasterror();
494 return -1;
495 }
496 }
497
506 public function fetchByUser($user_id, $order = '', $filter = '')
507 {
508 $this->holiday = [];
509 $sql = "SELECT";
510 $sql .= " cp.rowid,";
511 $sql .= " cp.ref,";
512
513 $sql .= " cp.fk_user,";
514 $sql .= " cp.fk_type,";
515 $sql .= " cp.date_create,";
516 $sql .= " cp.tms as date_modification,";
517 $sql .= " cp.description,";
518 $sql .= " cp.date_debut,";
519 $sql .= " cp.date_fin,";
520 $sql .= " cp.halfday,";
521 $sql .= " cp.statut as status,";
522 $sql .= " cp.fk_validator,";
523 $sql .= " cp.date_valid,";
524 $sql .= " cp.fk_user_valid,";
525 $sql .= " cp.date_approval,";
526 $sql .= " cp.fk_user_approve,";
527 $sql .= " cp.date_refuse,";
528 $sql .= " cp.fk_user_refuse,";
529 $sql .= " cp.date_cancel,";
530 $sql .= " cp.fk_user_cancel,";
531 $sql .= " cp.detail_refuse,";
532
533 $sql .= " uu.lastname as user_lastname,";
534 $sql .= " uu.firstname as user_firstname,";
535 $sql .= " uu.login as user_login,";
536 $sql .= " uu.statut as user_status,";
537 $sql .= " uu.photo as user_photo,";
538 $sql .= " uu.fk_country as country_id,";
539
540 $sql .= " ua.lastname as validator_lastname,";
541 $sql .= " ua.firstname as validator_firstname,";
542 $sql .= " ua.login as validator_login,";
543 $sql .= " ua.statut as validator_status,";
544 $sql .= " ua.photo as validator_photo";
545
546 $sql .= " FROM ".MAIN_DB_PREFIX."holiday as cp, ".MAIN_DB_PREFIX."user as uu, ".MAIN_DB_PREFIX."user as ua";
547 $sql .= " WHERE cp.entity IN (".getEntity('holiday').")";
548 $sql .= " AND cp.fk_user = uu.rowid AND cp.fk_validator = ua.rowid"; // Hack needed for search on the list
549 $sql .= " AND cp.fk_user IN (".$this->db->sanitize($user_id).")";
550
551 // Selection filter
552 if (!empty($filter)) {
553 $sql .= $filter; // @phan-suppress-current-line SqlInjection
554 }
555
556 // Order of display of the result
557 if (!empty($order)) {
558 $sql .= $order; // @phan-suppress-current-line SqlInjection
559 }
560
561 dol_syslog(get_class($this)."::fetchByUser", LOG_DEBUG);
562 $resql = $this->db->query($sql);
563
564 // If no SQL error
565 if ($resql) {
566 $i = 0;
567 $tab_result = $this->holiday;
568 $num = $this->db->num_rows($resql);
569
570 // If no registration
571 if (!$num) {
572 return 2;
573 }
574
575 // List the records and add them to the table
576 while ($i < $num) {
577 $obj = $this->db->fetch_object($resql);
578
579 $tab_result[$i]['rowid'] = (int) $obj->rowid;
580 $tab_result[$i]['id'] = (int) $obj->rowid;
581 $tab_result[$i]['ref'] = (string) ($obj->ref ? $obj->ref : $obj->rowid);
582
583 $tab_result[$i]['fk_user'] = (int) $obj->fk_user;
584 $tab_result[$i]['fk_type'] = (int) $obj->fk_type;
585 $tab_result[$i]['date_create'] = $this->db->jdate($obj->date_create);
586 $tab_result[$i]['date_modification'] = $this->db->jdate($obj->date_modification);
587 $tab_result[$i]['description'] = (string) $obj->description;
588 $tab_result[$i]['date_debut'] = $this->db->jdate($obj->date_debut);
589 $tab_result[$i]['date_fin'] = $this->db->jdate($obj->date_fin);
590 $tab_result[$i]['date_debut_gmt'] = $this->db->jdate($obj->date_debut, 1);
591 $tab_result[$i]['date_fin_gmt'] = $this->db->jdate($obj->date_fin, 1);
592 $tab_result[$i]['halfday'] = (int) $obj->halfday;
593 $tab_result[$i]['statut'] = (int) $obj->status;
594 $tab_result[$i]['status'] = (int) $obj->status;
595 $tab_result[$i]['fk_validator'] = (int) $obj->fk_validator;
596 $tab_result[$i]['date_valid'] = $this->db->jdate($obj->date_valid);
597 $tab_result[$i]['fk_user_valid'] = (int) $obj->fk_user_valid;
598 $tab_result[$i]['date_approval'] = $this->db->jdate($obj->date_approval);
599 $tab_result[$i]['fk_user_approve'] = (int) $obj->fk_user_approve;
600 $tab_result[$i]['date_refuse'] = $this->db->jdate($obj->date_refuse);
601 $tab_result[$i]['fk_user_refuse'] = (int) $obj->fk_user_refuse;
602 $tab_result[$i]['date_cancel'] = $this->db->jdate($obj->date_cancel);
603 $tab_result[$i]['fk_user_cancel'] = (int) $obj->fk_user_cancel;
604 $tab_result[$i]['detail_refuse'] = (string) $obj->detail_refuse;
605
606 $tab_result[$i]['user_firstname'] = (string) $obj->user_firstname;
607 $tab_result[$i]['user_lastname'] = (string) $obj->user_lastname;
608 $tab_result[$i]['user_login'] = (string) $obj->user_login;
609 $tab_result[$i]['user_statut'] = (int) $obj->user_status;
610 $tab_result[$i]['user_status'] = (int) $obj->user_status;
611 $tab_result[$i]['user_photo'] = (string) $obj->user_photo;
612
613 $tab_result[$i]['validator_firstname'] = (string) $obj->validator_firstname;
614 $tab_result[$i]['validator_lastname'] = (string) $obj->validator_lastname;
615 $tab_result[$i]['validator_login'] = (string) $obj->validator_login;
616 $tab_result[$i]['validator_statut'] = (int) $obj->validator_status;
617 $tab_result[$i]['validator_status'] = (int) $obj->validator_status;
618 $tab_result[$i]['validator_photo'] = (string) $obj->validator_photo;
619
620 $tab_result[$i]['country_id'] = (int) $obj->country_id; // id of country of user
621
622 $i++;
623 }
624
625 // Returns 1 with the filled array
626 $this->holiday = $tab_result;
627 return 1;
628 } else {
629 // SQL Error
630 $this->error = "Error ".$this->db->lasterror();
631 return -1;
632 }
633 }
634
642 public function fetchAll($sqlOrder, $sqlFilter)
643 {
644 $sql = "SELECT";
645 $sql .= " cp.rowid,";
646 $sql .= " cp.ref,";
647 $sql .= " cp.fk_user,";
648 $sql .= " cp.fk_type,";
649 $sql .= " cp.date_create,";
650 $sql .= " cp.tms as date_modification,";
651 $sql .= " cp.description,";
652 $sql .= " cp.date_debut,";
653 $sql .= " cp.date_fin,";
654 $sql .= " cp.halfday,";
655 $sql .= " cp.statut as status,";
656 $sql .= " cp.fk_validator,";
657 $sql .= " cp.date_valid,";
658 $sql .= " cp.fk_user_valid,";
659 $sql .= " cp.date_approval,";
660 $sql .= " cp.fk_user_approve,";
661 $sql .= " cp.date_refuse,";
662 $sql .= " cp.fk_user_refuse,";
663 $sql .= " cp.date_cancel,";
664 $sql .= " cp.fk_user_cancel,";
665 $sql .= " cp.detail_refuse,";
666
667 $sql .= " uu.lastname as user_lastname,";
668 $sql .= " uu.firstname as user_firstname,";
669 $sql .= " uu.login as user_login,";
670 $sql .= " uu.statut as user_status,";
671 $sql .= " uu.photo as user_photo,";
672
673 $sql .= " ua.lastname as validator_lastname,";
674 $sql .= " ua.firstname as validator_firstname,";
675 $sql .= " ua.login as validator_login,";
676 $sql .= " ua.statut as validator_status,";
677 $sql .= " ua.photo as validator_photo";
678
679 $sql .= " FROM ".MAIN_DB_PREFIX."holiday as cp, ".MAIN_DB_PREFIX."user as uu, ".MAIN_DB_PREFIX."user as ua";
680 $sql .= " WHERE cp.entity IN (".getEntity('holiday').")";
681 $sql .= " AND cp.fk_user = uu.rowid AND cp.fk_validator = ua.rowid "; // Hack needed for search on the list
682
683 // Selection filtering
684 if (!empty($sqlFilter)) {
685 $sql .= $sqlFilter;
686 }
687
688 // order of display
689 if (!empty($sqlOrder)) {
690 $sql .= $sqlOrder;
691 }
692
693 dol_syslog(get_class($this)."::fetchAll", LOG_DEBUG);
694 $resql = $this->db->query($sql);
695
696 // If no SQL error
697 if ($resql) {
698 $i = 0;
699 $tab_result = $this->holiday;
700 $num = $this->db->num_rows($resql);
701
702 // If no registration
703 if (!$num) {
704 return 2;
705 }
706
707 // List the records and add them to the table
708 while ($i < $num) {
709 $obj = $this->db->fetch_object($resql);
710
711 $tab_result[$i]['rowid'] = (int) $obj->rowid;
712 $tab_result[$i]['id'] = (int) $obj->rowid;
713 $tab_result[$i]['ref'] = (string) ($obj->ref ? $obj->ref : $obj->rowid);
714
715 $tab_result[$i]['fk_user'] = (int) $obj->fk_user;
716 $tab_result[$i]['fk_type'] = (int) $obj->fk_type;
717 $tab_result[$i]['date_create'] = $this->db->jdate($obj->date_create);
718 $tab_result[$i]['date_modification'] = $this->db->jdate($obj->date_modification);
719 $tab_result[$i]['description'] = (string) $obj->description;
720 $tab_result[$i]['date_debut'] = $this->db->jdate($obj->date_debut);
721 $tab_result[$i]['date_fin'] = $this->db->jdate($obj->date_fin);
722 $tab_result[$i]['date_debut_gmt'] = $this->db->jdate($obj->date_debut, 1);
723 $tab_result[$i]['date_fin_gmt'] = $this->db->jdate($obj->date_fin, 1);
724 $tab_result[$i]['halfday'] = (int) $obj->halfday;
725 $tab_result[$i]['statut'] = (int) $obj->status;
726 $tab_result[$i]['status'] = (int) $obj->status;
727 $tab_result[$i]['fk_validator'] = (int) $obj->fk_validator;
728 $tab_result[$i]['date_valid'] = $this->db->jdate($obj->date_valid);
729 $tab_result[$i]['fk_user_valid'] = (int) $obj->fk_user_valid;
730 $tab_result[$i]['date_approval'] = $this->db->jdate($obj->date_approval);
731 $tab_result[$i]['fk_user_approve'] = (int) $obj->fk_user_approve;
732 $tab_result[$i]['date_refuse'] = $this->db->jdate($obj->date_refuse);
733 $tab_result[$i]['fk_user_refuse'] = (int) $obj->fk_user_refuse;
734 $tab_result[$i]['date_cancel'] = $this->db->jdate($obj->date_cancel);
735 $tab_result[$i]['fk_user_cancel'] = (int) $obj->fk_user_cancel;
736 $tab_result[$i]['detail_refuse'] = (string) $obj->detail_refuse;
737
738 $tab_result[$i]['user_firstname'] = (string) $obj->user_firstname;
739 $tab_result[$i]['user_lastname'] = (string) $obj->user_lastname;
740 $tab_result[$i]['user_login'] = (string) $obj->user_login;
741 $tab_result[$i]['user_statut'] = (int) $obj->user_status;
742 $tab_result[$i]['user_status'] = (int) $obj->user_status;
743 $tab_result[$i]['user_photo'] = (string) $obj->user_photo;
744
745 $tab_result[$i]['validator_firstname'] = (string) $obj->validator_firstname;
746 $tab_result[$i]['validator_lastname'] = (string) $obj->validator_lastname;
747 $tab_result[$i]['validator_login'] = (string) $obj->validator_login;
748 $tab_result[$i]['validator_statut'] = (int) $obj->validator_status;
749 $tab_result[$i]['validator_status'] = (int) $obj->validator_status;
750 $tab_result[$i]['validator_photo'] = (string) $obj->validator_photo;
751
752 $i++;
753 }
754 // Returns 1 and adds the array to the variable
755 $this->holiday = $tab_result;
756 return 1;
757 } else {
758 // SQL Error
759 $this->error = "Error ".$this->db->lasterror();
760 return -1;
761 }
762 }
763
764
772 public function validate($user = null, $notrigger = 0)
773 {
774 global $conf, $langs;
775 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
776 $error = 0;
777
778
779 $checkBalance = getDictionaryValue('c_holiday_types', 'block_if_negative', $this->fk_type, true);
780
781 if ($checkBalance > 0) {
782 $balance = $this->getCPforUser($this->fk_user, $this->fk_type);
783
784 // Use the GMT variants: num_public_holiday(), called by num_open_day(), refuses a range whose
785 // length is not a whole number of days, and a range spanning a DST transition is 23h or 25h
786 // long in the server timezone. It then returns a string and the subtraction fatals.
787 $datedebutforcount = !empty($this->date_debut_gmt) ? $this->date_debut_gmt : $this->date_debut;
788 $datefinforcount = !empty($this->date_fin_gmt) ? $this->date_fin_gmt : $this->date_fin;
789 $daysAsked = num_open_day($datedebutforcount, $datefinforcount, 0, 1, (int) $this->halfday, '', $this->fk_user);
790
791 if (($balance - $daysAsked) < 0) {
792 $this->error = 'LeaveRequestCreationBlockedBecauseBalanceIsNegative';
793 return -1;
794 }
795 }
796
797 // Define new ref
798 if (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref) || $this->ref == $this->id) {
799 $num = $this->getNextNumRef(null);
800 } else {
801 $num = (string) $this->ref;
802 }
803 $this->newref = dol_sanitizeFileName($num);
804
805 // Update status
806 $sql = "UPDATE ".MAIN_DB_PREFIX."holiday SET";
807 $sql .= " fk_user_valid = ".((int) $user->id).",";
808 $sql .= " date_valid = '".$this->db->idate(dol_now())."',";
809 if (!empty($this->status) && is_numeric($this->status)) {
810 $sql .= " statut = ".((int) $this->status).",";
811 } else {
812 $this->error = 'Property status must be a numeric value';
813 $error++;
814 }
815 $sql .= " ref = '".$this->db->escape($num)."'";
816 $sql .= " WHERE rowid = ".((int) $this->id);
817
818 $this->db->begin();
819
820 dol_syslog(get_class($this)."::validate", LOG_DEBUG);
821 $resql = $this->db->query($sql);
822 if (!$resql) {
823 $error++;
824 $this->errors[] = "Error ".$this->db->lasterror();
825 }
826
827 if (!$error) {
828 if (!$notrigger) {
829 // Call trigger
830 $result = $this->call_trigger('HOLIDAY_VALIDATE', $user);
831 if ($result < 0) {
832 $error++;
833 }
834 // End call triggers
835 }
836 }
837
838 if (!$error) {
839 $this->oldref = $this->ref;
840
841 // Rename directory if dir was a temporary ref
842 if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
843 // Now we rename also files into index
844 $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) . "'";
845 $sql .= " WHERE filename LIKE '" . $this->db->escape($this->ref) . "%' AND filepath = 'holiday/" . $this->db->escape($this->ref) . "' and entity = " . ((int) $conf->entity);
846 $resql = $this->db->query($sql);
847 if (!$resql) {
848 $error++;
849 $this->error = $this->db->lasterror();
850 }
851 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'holiday/".$this->db->escape($this->newref)."'";
852 $sql .= " WHERE filepath = 'holiday/".$this->db->escape($this->ref)."' and entity = ".((int) $conf->entity);
853 $resql = $this->db->query($sql);
854 if (!$resql) {
855 $error++;
856 $this->error = $this->db->lasterror();
857 }
858
859 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
860 $oldref = dol_sanitizeFileName($this->ref);
861 $newref = dol_sanitizeFileName($num);
862 $dirsource = $conf->holiday->multidir_output[$this->entity] . '/' . $oldref;
863 $dirdest = $conf->holiday->multidir_output[$this->entity] . '/' . $newref;
864 if (!$error && file_exists($dirsource)) {
865 dol_syslog(get_class($this) . "::validate rename dir " . $dirsource . " into " . $dirdest);
866 if (@rename($dirsource, $dirdest)) {
867 dol_syslog("Rename ok");
868 // Rename docs starting with $oldref with $newref
869 $listoffiles = dol_dir_list($dirdest, 'files', 1, '^' . preg_quote($oldref, '/'));
870 foreach ($listoffiles as $fileentry) {
871 $dirsource = $fileentry['name'];
872 $dirdest = preg_replace('/^' . preg_quote($oldref, '/') . '/', $newref, $dirsource);
873 $dirsource = $fileentry['path'] . '/' . $dirsource;
874 $dirdest = $fileentry['path'] . '/' . $dirdest;
875 @rename($dirsource, $dirdest);
876 }
877 }
878 }
879 }
880 }
881
882
883 // Commit or rollback
884 if ($error) {
885 foreach ($this->errors as $errmsg) {
886 dol_syslog(get_class($this)."::validate ".$errmsg, LOG_ERR);
887 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
888 }
889 $this->db->rollback();
890 return -1 * $error;
891 } else {
892 $this->db->commit();
893 return 1;
894 }
895 }
896
897
905 public function approve($user = null, $notrigger = 0)
906 {
907 $error = 0;
908
909 $checkBalance = getDictionaryValue('c_holiday_types', 'block_if_negative', $this->fk_type, true);
910
911 if ($checkBalance > 0) {
912 $balance = $this->getCPforUser($this->fk_user, $this->fk_type);
913
914 // Use the GMT variants: num_public_holiday(), called by num_open_day(), refuses a range whose
915 // length is not a whole number of days, and a range spanning a DST transition is 23h or 25h
916 // long in the server timezone. It then returns a string and the subtraction fatals.
917 $datedebutforcount = !empty($this->date_debut_gmt) ? $this->date_debut_gmt : $this->date_debut;
918 $datefinforcount = !empty($this->date_fin_gmt) ? $this->date_fin_gmt : $this->date_fin;
919 $daysAsked = num_open_day($datedebutforcount, $datefinforcount, 0, 1, (int) $this->halfday, '', $this->fk_user);
920
921 if (($balance - $daysAsked) < 0) {
922 $this->error = 'LeaveRequestCreationBlockedBecauseBalanceIsNegative';
923 return -1;
924 }
925 }
926
927 // Update request
928 $sql = "UPDATE ".MAIN_DB_PREFIX."holiday SET";
929 $sql .= " description= '".$this->db->escape($this->description)."',";
930 if (!empty($this->date_debut)) {
931 $sql .= " date_debut = '".$this->db->idate($this->date_debut)."',";
932 } else {
933 $error++;
934 }
935 if (!empty($this->date_fin)) {
936 $sql .= " date_fin = '".$this->db->idate($this->date_fin)."',";
937 } else {
938 $error++;
939 }
940 $sql .= " halfday = ".((int) $this->halfday).",";
941 if (!empty($this->status) && is_numeric($this->status)) {
942 $sql .= " statut = ".((int) $this->status).",";
943 } else {
944 $error++;
945 }
946 if (!empty($this->fk_validator)) {
947 $sql .= " fk_validator = ".((int) $this->fk_validator).",";
948 } else {
949 $error++;
950 }
951 if (!empty($this->date_valid)) {
952 $sql .= " date_valid = '".$this->db->idate($this->date_valid)."',";
953 } else {
954 $sql .= " date_valid = NULL,";
955 }
956 if (!empty($this->fk_user_valid)) {
957 $sql .= " fk_user_valid = ".((int) $this->fk_user_valid).",";
958 } else {
959 $sql .= " fk_user_valid = NULL,";
960 }
961 if (!empty($this->date_approval)) {
962 $sql .= " date_approval = '".$this->db->idate($this->date_approval)."',";
963 } else {
964 $sql .= " date_approval = NULL,";
965 }
966 if (!empty($this->fk_user_approve)) {
967 $sql .= " fk_user_approve = ".((int) $this->fk_user_approve).",";
968 } else {
969 $sql .= " fk_user_approve = NULL,";
970 }
971 if (!empty($this->date_refuse)) {
972 $sql .= " date_refuse = '".$this->db->idate($this->date_refuse)."',";
973 } else {
974 $sql .= " date_refuse = NULL,";
975 }
976 if (!empty($this->fk_user_refuse)) {
977 $sql .= " fk_user_refuse = ".((int) $this->fk_user_refuse).",";
978 } else {
979 $sql .= " fk_user_refuse = NULL,";
980 }
981 if (!empty($this->date_cancel)) {
982 $sql .= " date_cancel = '".$this->db->idate($this->date_cancel)."',";
983 } else {
984 $sql .= " date_cancel = NULL,";
985 }
986 if (!empty($this->fk_user_cancel)) {
987 $sql .= " fk_user_cancel = ".((int) $this->fk_user_cancel).",";
988 } else {
989 $sql .= " fk_user_cancel = NULL,";
990 }
991 if (!empty($this->detail_refuse)) {
992 $sql .= " detail_refuse = '".$this->db->escape($this->detail_refuse)."'";
993 } else {
994 $sql .= " detail_refuse = NULL";
995 }
996 $sql .= " WHERE rowid = ".((int) $this->id);
997
998 $this->db->begin();
999
1000 dol_syslog(get_class($this)."::approve", LOG_DEBUG);
1001 $resql = $this->db->query($sql);
1002 if (!$resql) {
1003 $error++;
1004 $this->errors[] = "Error ".$this->db->lasterror();
1005 }
1006
1007 if (!$error) {
1008 if (!$notrigger) {
1009 // Call trigger
1010 $result = $this->call_trigger('HOLIDAY_APPROVE', $user);
1011 if ($result < 0) {
1012 $error++;
1013 }
1014 // End call triggers
1015 }
1016 }
1017
1018 // Commit or rollback
1019 if ($error) {
1020 foreach ($this->errors as $errmsg) {
1021 dol_syslog(get_class($this)."::approve ".$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 update($user = null, $notrigger = 0)
1040 {
1041 $error = 0;
1042
1043 $checkBalance = getDictionaryValue('c_holiday_types', 'block_if_negative', $this->fk_type, true);
1044 if ($this->status == self::STATUS_REFUSED || $this->status == self::STATUS_APPROVED) {
1045 $checkBalance = 0; // No balance check to refuse a request, nor on an approved request (its days are already debited)
1046 }
1047
1048 if ($checkBalance > 0 && $this->status != self::STATUS_DRAFT && $this->status != self::STATUS_CANCELED) {
1049 $balance = $this->getCPforUser($this->fk_user, $this->fk_type);
1050
1051 // Use the GMT variants: num_public_holiday(), called by num_open_day(), refuses a range whose
1052 // length is not a whole number of days, and a range spanning a DST transition is 23h or 25h
1053 // long in the server timezone. It then returns a string and the subtraction fatals.
1054 $datedebutforcount = !empty($this->date_debut_gmt) ? $this->date_debut_gmt : $this->date_debut;
1055 $datefinforcount = !empty($this->date_fin_gmt) ? $this->date_fin_gmt : $this->date_fin;
1056 $daysAsked = num_open_day($datedebutforcount, $datefinforcount, 0, 1, (int) $this->halfday, '', $this->fk_user);
1057
1058 if (($balance - $daysAsked) < 0) {
1059 $this->error = 'LeaveRequestCreationBlockedBecauseBalanceIsNegative';
1060 return -1;
1061 }
1062 }
1063
1064 // Update request
1065 $sql = "UPDATE ".MAIN_DB_PREFIX."holiday SET";
1066
1067 $sql .= " description= '".$this->db->escape($this->description)."',";
1068
1069 if (!empty($this->date_create)) {
1070 $sql .= " date_create = '".$this->db->idate($this->date_create)."',";
1071 } else {
1072 $error++;
1073 }
1074 if (!empty($this->date_debut)) {
1075 $sql .= " date_debut = '".$this->db->idate($this->date_debut)."',";
1076 } else {
1077 $error++;
1078 }
1079 if (!empty($this->date_fin)) {
1080 $sql .= " date_fin = '".$this->db->idate($this->date_fin)."',";
1081 } else {
1082 $error++;
1083 }
1084 $sql .= " halfday = ".((int) $this->halfday).",";
1085 if (!empty($this->status) && is_numeric($this->status)) {
1086 $sql .= " statut = ".((int) $this->status).",";
1087 } else {
1088 $error++;
1089 }
1090 if (!empty($this->fk_validator)) {
1091 $sql .= " fk_validator = ".((int) $this->fk_validator).",";
1092 } else {
1093 $error++;
1094 }
1095 if (!empty($this->date_valid)) {
1096 $sql .= " date_valid = '".$this->db->idate($this->date_valid)."',";
1097 } else {
1098 $sql .= " date_valid = NULL,";
1099 }
1100 if (!empty($this->fk_user_valid)) {
1101 $sql .= " fk_user_valid = ".((int) $this->fk_user_valid).",";
1102 } else {
1103 $sql .= " fk_user_valid = NULL,";
1104 }
1105 if (!empty($this->date_approval)) {
1106 $sql .= " date_approval = '".$this->db->idate($this->date_approval)."',";
1107 } else {
1108 $sql .= " date_approval = NULL,";
1109 }
1110 if (!empty($this->fk_user_approve)) {
1111 $sql .= " fk_user_approve = ".((int) $this->fk_user_approve).",";
1112 } else {
1113 $sql .= " fk_user_approve = NULL,";
1114 }
1115 if (!empty($this->date_refuse)) {
1116 $sql .= " date_refuse = '".$this->db->idate($this->date_refuse)."',";
1117 } else {
1118 $sql .= " date_refuse = NULL,";
1119 }
1120 if (!empty($this->fk_user_refuse)) {
1121 $sql .= " fk_user_refuse = ".((int) $this->fk_user_refuse).",";
1122 } else {
1123 $sql .= " fk_user_refuse = NULL,";
1124 }
1125 if (!empty($this->date_cancel)) {
1126 $sql .= " date_cancel = '".$this->db->idate($this->date_cancel)."',";
1127 } else {
1128 $sql .= " date_cancel = NULL,";
1129 }
1130 if (!empty($this->fk_user_cancel)) {
1131 $sql .= " fk_user_cancel = ".((int) $this->fk_user_cancel).",";
1132 } else {
1133 $sql .= " fk_user_cancel = NULL,";
1134 }
1135 if (!empty($this->detail_refuse)) {
1136 $sql .= " detail_refuse = '".$this->db->escape($this->detail_refuse)."'";
1137 } else {
1138 $sql .= " detail_refuse = NULL";
1139 }
1140
1141 $sql .= " WHERE rowid = ".((int) $this->id);
1142
1143 $this->db->begin();
1144
1145 dol_syslog(get_class($this)."::update", LOG_DEBUG);
1146 $resql = $this->db->query($sql);
1147 if (!$resql) {
1148 $error++;
1149 $this->errors[] = "Error ".$this->db->lasterror();
1150 }
1151
1152 if (!$error) {
1153 $result = $this->insertExtraFields();
1154 if ($result < 0) {
1155 $error++;
1156 }
1157 }
1158
1159 if (!$error) {
1160 if (!$notrigger && $user !== null) {
1161 // Call trigger
1162 $result = $this->call_trigger('HOLIDAY_MODIFY', $user);
1163 if ($result < 0) {
1164 $error++;
1165 }
1166 // End call triggers
1167 }
1168 }
1169
1170 // Commit or rollback
1171 if ($error) {
1172 foreach ($this->errors as $errmsg) {
1173 dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
1174 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
1175 }
1176 $this->db->rollback();
1177 return -1 * $error;
1178 } else {
1179 $this->db->commit();
1180 return 1;
1181 }
1182 }
1183
1184
1192 public function delete($user, $notrigger = 0)
1193 {
1194 global $conf, $langs;
1195 $error = 0;
1196
1197 $sql = "DELETE FROM ".MAIN_DB_PREFIX."holiday";
1198 $sql .= " WHERE rowid=".((int) $this->id);
1199
1200 $this->db->begin();
1201
1202 // Delete extrafields before the leave request
1203 $result = $this->deleteExtraFields();
1204 if ($result < 0) {
1205 $error++;
1206 }
1207
1208 if (!$error) {
1209 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1210 $resql = $this->db->query($sql);
1211 if (!$resql) {
1212 $error++;
1213 $this->errors[] = "Error ".$this->db->lasterror();
1214 }
1215 }
1216
1217 if (!$error) {
1218 if (!$notrigger) {
1219 // Call trigger
1220 $result = $this->call_trigger('HOLIDAY_DELETE', $user);
1221 if ($result < 0) {
1222 $error++;
1223 }
1224 // End call triggers
1225 }
1226 }
1227
1228 // Commit or rollback
1229 if ($error) {
1230 foreach ($this->errors as $errmsg) {
1231 dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
1232 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
1233 }
1234 $this->db->rollback();
1235 return -1 * $error;
1236 } else {
1237 $this->db->commit();
1238 return 1;
1239 }
1240 }
1241
1255 public function verifDateHolidayCP($fk_user, $dateStart, $dateEnd, $halfday = 0)
1256 {
1257 $this->fetchByUser($fk_user, '', '');
1258
1259 foreach ($this->holiday as $infos_CP) {
1260 if ($infos_CP['statut'] == Holiday::STATUS_CANCELED) {
1261 continue; // ignore not validated holidays
1262 }
1263 if ($infos_CP['statut'] == Holiday::STATUS_REFUSED) {
1264 continue; // ignore refused holidays
1265 }
1266 //var_dump("--");
1267 //var_dump("old: ".dol_print_date($infos_CP['date_debut'],'dayhour').' '.dol_print_date($infos_CP['date_fin'],'dayhour').' '.$infos_CP['halfday']);
1268 //var_dump("new: ".dol_print_date($dateStart,'dayhour').' '.dol_print_date($dateEnd,'dayhour').' '.$halfday);
1269
1270 // A new leave can fully contain an existing leave, so neither endpoint is inside the existing range.
1271 if ($dateStart < $infos_CP['date_debut'] && $dateEnd > $infos_CP['date_fin']) {
1272 return false;
1273 }
1274
1275 if ($halfday == 0) {
1276 if ($dateStart >= $infos_CP['date_debut'] && $dateStart <= $infos_CP['date_fin']) {
1277 return false;
1278 }
1279 if ($dateEnd <= $infos_CP['date_fin'] && $dateEnd >= $infos_CP['date_debut']) {
1280 return false;
1281 }
1282 } elseif ($halfday == -1) {
1283 // new start afternoon, new end afternoon
1284 if ($dateStart >= $infos_CP['date_debut'] && $dateStart <= $infos_CP['date_fin']) {
1285 if ($dateStart < $infos_CP['date_fin'] || in_array($infos_CP['halfday'], array(0, -1))) {
1286 return false;
1287 }
1288 }
1289 if ($dateEnd <= $infos_CP['date_fin'] && $dateEnd >= $infos_CP['date_debut']) {
1290 if ($dateStart < $dateEnd) {
1291 return false;
1292 }
1293 if ($dateEnd < $infos_CP['date_fin'] || in_array($infos_CP['halfday'], array(0, -1))) {
1294 return false;
1295 }
1296 }
1297 } elseif ($halfday == 1) {
1298 // new start morning, new end morning
1299 if ($dateStart >= $infos_CP['date_debut'] && $dateStart <= $infos_CP['date_fin']) {
1300 if ($dateStart < $dateEnd) {
1301 return false;
1302 }
1303 if ($dateStart > $infos_CP['date_debut'] || in_array($infos_CP['halfday'], array(0, 1))) {
1304 return false;
1305 }
1306 }
1307 if ($dateEnd <= $infos_CP['date_fin'] && $dateEnd >= $infos_CP['date_debut']) {
1308 if ($dateEnd > $infos_CP['date_debut'] || in_array($infos_CP['halfday'], array(0, 1))) {
1309 return false;
1310 }
1311 }
1312 } elseif ($halfday == 2) {
1313 // new start afternoon, new end morning
1314 if ($dateStart >= $infos_CP['date_debut'] && $dateStart <= $infos_CP['date_fin']) {
1315 if ($dateStart < $infos_CP['date_fin'] || in_array($infos_CP['halfday'], array(0, -1))) {
1316 return false;
1317 }
1318 }
1319 if ($dateEnd <= $infos_CP['date_fin'] && $dateEnd >= $infos_CP['date_debut']) {
1320 if ($dateEnd > $infos_CP['date_debut'] || in_array($infos_CP['halfday'], array(0, 1))) {
1321 return false;
1322 }
1323 }
1324 } else {
1325 dol_print_error(null, 'Bad value of parameter halfday when calling function verifDateHolidayCP');
1326 }
1327 }
1328
1329 return true;
1330 }
1331
1332
1342 public function verifDateHolidayForTimestamp($fk_user, $timestamp, $status = '-1')
1343 {
1344 $isavailablemorning = true;
1345 $isavailableafternoon = true;
1346
1347 // Check into leave requests
1348 $sql = "SELECT cp.rowid, cp.date_debut as date_start, cp.date_fin as date_end, cp.halfday, cp.statut as status";
1349 $sql .= " FROM ".MAIN_DB_PREFIX."holiday as cp";
1350 $sql .= " WHERE cp.entity IN (".getEntity('holiday').")";
1351 $sql .= " AND cp.fk_user = ".(int) $fk_user;
1352 $sql .= " AND cp.date_debut <= '".$this->db->idate($timestamp)."' AND cp.date_fin >= '".$this->db->idate($timestamp)."'";
1353 if ($status != '-1') {
1354 $sql .= " AND cp.statut IN (".$this->db->sanitize($status).")";
1355 }
1356
1357 $resql = $this->db->query($sql);
1358 if ($resql) {
1359 $num_rows = $this->db->num_rows($resql); // Note, we can have 2 records if on is morning and the other one is afternoon
1360 if ($num_rows > 0) {
1361 $arrayofrecord = array();
1362 $i = 0;
1363 while ($i < $num_rows) {
1364 $obj = $this->db->fetch_object($resql);
1365
1366 // Note: $obj->halfday is 0:Full days, 2:Start afternoon end morning, -1:Start afternoon, 1:End morning
1367 $arrayofrecord[$obj->rowid] = array('date_start' => $this->db->jdate($obj->date_start), 'date_end' => $this->db->jdate($obj->date_end), 'halfday' => $obj->halfday, 'status' => $obj->status);
1368 $i++;
1369 }
1370
1371 // We found a record, user is on holiday by default, so is not available is true.
1372 $isavailablemorning = true;
1373 foreach ($arrayofrecord as $record) {
1374 if ($timestamp == $record['date_start'] && $record['halfday'] == 2) {
1375 continue;
1376 }
1377 if ($timestamp == $record['date_start'] && $record['halfday'] == -1) {
1378 continue;
1379 }
1380 $isavailablemorning = false;
1381 break;
1382 }
1383 $isavailableafternoon = true;
1384 foreach ($arrayofrecord as $record) {
1385 if ($timestamp == $record['date_end'] && $record['halfday'] == 2) {
1386 continue;
1387 }
1388 if ($timestamp == $record['date_end'] && $record['halfday'] == 1) {
1389 continue;
1390 }
1391 $isavailableafternoon = false;
1392 break;
1393 }
1394 }
1395 } else {
1396 dol_print_error($this->db);
1397 }
1398
1399 $result = array('morning' => (int) $isavailablemorning, 'afternoon' => (int) $isavailableafternoon);
1400 if (!$isavailablemorning) {
1401 $result['morning_reason'] = 'leave_request';
1402 }
1403 if (!$isavailableafternoon) {
1404 $result['afternoon_reason'] = 'leave_request';
1405 }
1406 return $result;
1407 }
1408
1415 public function getTooltipContentArray($params)
1416 {
1417 global $langs;
1418
1419 $langs->load('holiday');
1420 $nofetch = !empty($params['nofetch']);
1421
1422 $datas = array();
1423 $datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("Holiday").'</u>';
1424 if (isset($this->status)) {
1425 $datas['picto'] .= ' '.$this->getLibStatut(5);
1426 }
1427 $datas['ref'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
1428 // show type for this record only in ajax to not overload lists
1429 if (!$nofetch && !empty($this->fk_type)) {
1430 $typeleaves = $this->getTypes(1, -1);
1431 if (empty($typeleaves[$this->fk_type])) {
1432 $labeltoshow = $langs->trans("TypeWasDisabledOrRemoved", $this->fk_type);
1433 } else {
1434 $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']);
1435 }
1436 $datas['type'] = '<br><b>'.$langs->trans("Type") . ':</b> ' . $labeltoshow;
1437 }
1438 if (isset($this->halfday) && !empty($this->date_debut) && !empty($this->date_fin)) {
1439 $listhalfday = array(
1440 'morning' => $langs->trans("Morning"),
1441 "afternoon" => $langs->trans("Afternoon")
1442 );
1443 $starthalfday = ($this->halfday == -1 || $this->halfday == 2) ? 'afternoon' : 'morning';
1444 $endhalfday = ($this->halfday == 1 || $this->halfday == 2) ? 'morning' : 'afternoon';
1445 $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>';
1446 $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>';
1447 }
1448
1449
1450 return $datas;
1451 }
1452
1462 public function getNomUrl($withpicto = 0, $save_lastsearch_value = -1, $notooltip = 0, $morecss = '')
1463 {
1464 global $conf, $langs, $hookmanager;
1465
1466 if (!empty($conf->dol_no_mouse_hover)) {
1467 $notooltip = 1; // Force disable tooltips
1468 }
1469
1470 $result = '';
1471 $params = [
1472 'id' => $this->id,
1473 'objecttype' => $this->element,
1474 'nofetch' => 1,
1475 ];
1476 $classfortooltip = 'classfortooltip';
1477 $dataparams = '';
1478 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1479 $classfortooltip = 'classforajaxtooltip';
1480 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
1481 $label = '';
1482 } else {
1483 $label = implode($this->getTooltipContentArray($params));
1484 }
1485
1486 $url = DOL_URL_ROOT.'/holiday/card.php?id='.$this->id;
1487
1488 //if ($option != 'nolink')
1489 //{
1490 // Add param to save lastsearch_values or not
1491 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1492 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1493 $add_save_lastsearch_values = 1;
1494 }
1495 if ($add_save_lastsearch_values) {
1496 $url .= '&save_lastsearch_values=1';
1497 }
1498 //}
1499
1500 $linkclose = '';
1501 if (empty($notooltip)) {
1502 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1503 $label = $langs->trans("ShowMyObject");
1504 $linkclose .= ' alt="'.dolPrintHTMLForAttribute($label).'"';
1505 }
1506 $linkclose .= ($label ? ' title="'.dolPrintHTMLForAttribute($label).'"' : ' title="tocomplete"');
1507 $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
1508 } else {
1509 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1510 }
1511
1512 $linkstart = '<a href="'.$url.'"';
1513 $linkstart .= $linkclose.'>';
1514 $linkend = '</a>';
1515
1516 $result .= $linkstart;
1517
1518 if ($withpicto) {
1519 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"'), 0, 0, $notooltip ? 0 : 1);
1520 }
1521 if ($withpicto != 2) {
1522 $result .= $this->ref;
1523 }
1524 $result .= $linkend;
1525
1526 global $action;
1527 $hookmanager->initHooks(array($this->element . 'dao'));
1528 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1529 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1530 if ($reshook > 0) {
1531 $result = $hookmanager->resPrint;
1532 } else {
1533 $result .= $hookmanager->resPrint;
1534 }
1535 return $result;
1536 }
1537
1538
1545 public function getLibStatut($mode = 0)
1546 {
1547 return $this->LibStatut($this->status, $mode, $this->date_debut);
1548 }
1549
1550 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1559 public function LibStatut($status, $mode = 0, $startdate = '')
1560 {
1561 // phpcs:enable
1562 global $langs;
1563
1564 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
1565 global $langs;
1566 //$langs->load("mymodule");
1567 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('DraftCP');
1568 $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('ToReviewCP');
1569 $this->labelStatus[self::STATUS_APPROVED] = $langs->transnoentitiesnoconv('ApprovedCP');
1570 $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('CancelCP');
1571 $this->labelStatus[self::STATUS_REFUSED] = $langs->transnoentitiesnoconv('RefuseCP');
1572 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('DraftCP');
1573 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('ToReviewCP');
1574 $this->labelStatusShort[self::STATUS_APPROVED] = $langs->transnoentitiesnoconv('ApprovedCP');
1575 $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('CancelCP');
1576 $this->labelStatusShort[self::STATUS_REFUSED] = $langs->transnoentitiesnoconv('RefuseCP');
1577 }
1578
1579 $params = array();
1580 $statusType = 'status6';
1581 if (!empty($startdate) && $startdate >= dol_now()) { // If not yet passed, we use a green "in live" color
1582 $statusType = 'status4';
1583 $params = array('tooltip' => $this->labelStatus[$status].' - '.$langs->trans("Forthcoming"));
1584 }
1585 if ($status == self::STATUS_DRAFT) {
1586 $statusType = 'status0';
1587 }
1588 if ($status == self::STATUS_VALIDATED) {
1589 $statusType = 'status1';
1590 }
1591 if ($status == self::STATUS_CANCELED) {
1592 $statusType = 'status9';
1593 }
1594 if ($status == self::STATUS_REFUSED) {
1595 $statusType = 'status9';
1596 }
1597
1598 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode, '', $params);
1599 }
1600
1601
1610 public function selectStatutCP($selected = 0, $htmlname = 'select_statut', $morecss = 'minwidth125')
1611 {
1612 global $langs;
1613
1614 // List of status label
1615 $name = array('DraftCP', 'ToReviewCP', 'ApprovedCP', 'CancelCP', 'RefuseCP');
1616 $nb = count($name) + 1;
1617
1618 // Select HTML
1619 $out = '<select name="'.$htmlname.'" id="'.$htmlname.'" class="flat'.($morecss ? ' '.$morecss : '').'">'."\n";
1620 $out .= '<option value="-1">&nbsp;</option>'."\n";
1621
1622 // Loop on status
1623 for ($i = 1; $i < $nb; $i++) {
1624 if ($i == $selected) {
1625 $out .= '<option value="'.$i.'" selected>'.$langs->trans($name[$i - 1]).'</option>'."\n";
1626 } else {
1627 $out .= '<option value="'.$i.'">'.$langs->trans($name[$i - 1]).'</option>'."\n";
1628 }
1629 }
1630
1631 $out .= "</select>\n";
1632
1633 $showempty = 0;
1634 $out .= ajax_combobox($htmlname, array(), 0, 0, 'resolve', ($showempty < 0 ? (string) $showempty : '-1'), $morecss);
1635
1636 return $out;
1637 }
1638
1646 public function updateConfCP($name, $value)
1647 {
1648 $sql = "UPDATE ".MAIN_DB_PREFIX."holiday_config SET";
1649 $sql .= " value = '".$this->db->escape($value)."'";
1650 $sql .= " WHERE name = '".$this->db->escape($name)."'";
1651
1652 dol_syslog(get_class($this).'::updateConfCP name='.$name, LOG_DEBUG);
1653 $result = $this->db->query($sql);
1654 if ($result) {
1655 return true;
1656 }
1657
1658 return false;
1659 }
1660
1669 public function getConfCP($name, $createifnotfound = '')
1670 {
1671 $sql = "SELECT value";
1672 $sql .= " FROM ".MAIN_DB_PREFIX."holiday_config";
1673 $sql .= " WHERE name = '".$this->db->escape($name)."'";
1674
1675 dol_syslog(get_class($this).'::getConfCP name='.$name.' createifnotfound='.$createifnotfound, LOG_DEBUG);
1676 $result = $this->db->query($sql);
1677
1678 if ($result) {
1679 $obj = $this->db->fetch_object($result);
1680 // Return value
1681 if (empty($obj)) {
1682 if ($createifnotfound) {
1683 $sql = "INSERT INTO ".MAIN_DB_PREFIX."holiday_config(name, value)";
1684 $sql .= " VALUES('".$this->db->escape($name)."', '".$this->db->escape($createifnotfound)."')";
1685 $result = $this->db->query($sql);
1686 if ($result) {
1687 return $createifnotfound;
1688 } else {
1689 $this->error = $this->db->lasterror();
1690 return -2;
1691 }
1692 } else {
1693 return '';
1694 }
1695 } else {
1696 return $obj->value;
1697 }
1698 } else {
1699 // Erreur SQL
1700 $this->error = $this->db->lasterror();
1701 return -1;
1702 }
1703 }
1704
1713 public function updateSoldeCP($userID = 0, $nbHoliday = 0, $fk_type = 0)
1714 {
1715 global $user, $langs;
1716
1717 $error = 0;
1718
1719 if (empty($userID) && empty($nbHoliday) && empty($fk_type)) {
1720 include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
1721 $langs->load("holiday");
1722
1723 $decrease = getDolGlobalInt('HOLIDAY_DECREASE_AT_END_OF_MONTH');
1724
1725 // If updated for everyone at the beginning of the month
1726 $now = dol_now();
1727
1728 // Get month of last update
1729 $stringInDBForLastUpdate = $this->getConfCP('lastUpdate', dol_print_date($now, '%Y%m%d%H%M%S')); // Example '20200101120000'
1730 // The lastUpdate config row is created empty (value NULL) at install, so getConfCP() returns an empty value
1731 // the first time. Treat an empty value as "start from now" instead of a very old date, otherwise the catch-up
1732 // loop below would credit every user with years of monthly accrual at once. Store it, because the loop is the
1733 // only other place that writes it: an empty value would stay empty and no month would ever be credited.
1734 if (empty($stringInDBForLastUpdate)) {
1735 $stringInDBForLastUpdate = dol_print_date($now, '%Y%m%d%H%M%S');
1736
1737 $sql = "UPDATE ".MAIN_DB_PREFIX."holiday_config SET";
1738 $sql .= " value = '".$this->db->escape($stringInDBForLastUpdate)."'";
1739 $sql .= " WHERE name = 'lastUpdate'";
1740 $result = $this->db->query($sql);
1741 if (!$result) {
1742 $this->error = $this->db->lasterror();
1743 return -1;
1744 }
1745 }
1746 // Protection when $lastUpdate has a not valid value
1747 if ($stringInDBForLastUpdate < '20000101000000') {
1748 $stringInDBForLastUpdate = '20000101000000';
1749 }
1750 $lastUpdate = dol_stringtotime($stringInDBForLastUpdate);
1751 //print 'lastUpdate:'.$lastUpdate;exit;
1752
1753 $yearMonthLastUpdate = dol_print_date($lastUpdate, '%Y%m');
1754 $yearMonthNow = dol_print_date($now, '%Y%m');
1755 //print 'yearMonthLastUpdate='.$yearMonthLastUpdate.' yearMonthNow='.$yearMonthNow;
1756
1757 // 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,
1758 // catching up to the current month if a gap is detected
1759 while ($yearMonthLastUpdate < $yearMonthNow) {
1760 $this->db->begin();
1761
1762 $year = dol_print_date($lastUpdate, '%Y');
1763 $month = dol_print_date($lastUpdate, '%m');
1764
1765 $users = $this->fetchUsers(false, false, ' AND u.statut > 0');
1766 $nbUser = count($users);
1767
1768 $typeleaves = $this->getTypes(1, 1);
1769
1770 // Update each user counter
1771 foreach ($users as $userCounter) {
1772 $nbDaysToAdd = (isset($typeleaves[$userCounter['type']]['newbymonth']) ? $typeleaves[$userCounter['type']]['newbymonth'] : 0);
1773 if (empty($nbDaysToAdd)) {
1774 continue;
1775 }
1776
1777 dol_syslog("We update leave type id ".$userCounter['type']." for user id ".$userCounter['rowid'], LOG_DEBUG);
1778
1779 $nowHoliday = (float) $userCounter['nb_holiday'];
1780 $newSolde = $nowHoliday + $nbDaysToAdd;
1781
1782 // We add a log for each user when its balance gets increased
1783 $this->addLogCP($user->id, $userCounter['rowid'], $langs->trans('HolidayMonthlyCredit'), $newSolde, $userCounter['type']);
1784
1785 $result = $this->updateSoldeCP($userCounter['rowid'], $newSolde, $userCounter['type']);
1786
1787 if ($result < 0) {
1788 $this->db->rollback();
1789 return -1;
1790 }
1791
1792 if (empty($decrease)) {
1793 continue;
1794 }
1795
1796 // We fetch a user's holiday in the current month and then calculate the number of days to deduct if he has at least one registered
1797 $filter = " AND cp.statut = ".((int) self::STATUS_APPROVED);
1798 $filter .= " AND cp.date_fin >= '".$this->db->idate(dol_stringtotime(dol_print_date($lastUpdate, '%Y-%m-01')))."'";
1799 $filter .= " AND cp.date_debut <= '".$this->db->idate(dol_stringtotime(dol_print_date($lastUpdate, '%Y-%m-t')))."'";
1800 $filter .= " AND cp.fk_type = ".((int) $userCounter['type']);
1801 $this->fetchByUser($userCounter['id'], '', $filter);
1802
1803 if (empty($this->holiday)) {
1804 continue;
1805 }
1806
1807 $startOfMonth = dol_mktime(0, 0, 0, (int) $month, 1, (int) $year, 1);
1808 $endOfMonth = dol_mktime(0, 0, 0, (int) $month, (int) dol_print_date($lastUpdate, 't'), (int) $year, 1);
1809
1810 foreach ($this->holiday as $obj) {
1811 $startDate = $obj['date_debut_gmt'];
1812 $endDate = $obj['date_fin_gmt'];
1813
1814 if ($startDate <= $endOfMonth && $startDate < $startOfMonth) {
1815 $startDate = $startOfMonth;
1816 }
1817
1818 if ($startOfMonth <= $endDate && $endDate > $endOfMonth) {
1819 $endDate = $endOfMonth;
1820 }
1821
1822 $nbDaysToDeduct = (float) num_open_day($startDate, $endDate, 0, 1, $obj['halfday'], $obj['country_id'], $obj['fk_user']);
1823
1824 if ($nbDaysToDeduct <= 0) {
1825 continue;
1826 }
1827
1828 $newSolde -= $nbDaysToDeduct;
1829
1830 // We add a log for each user when its balance gets decreased
1831 $this->addLogCP($user->id, $userCounter['rowid'], $obj['ref'].' - '.$langs->trans('HolidayConsumption'), $newSolde, $userCounter['type']);
1832
1833 $result = $this->updateSoldeCP($userCounter['rowid'], $newSolde, $userCounter['type']);
1834
1835 if ($result < 0) {
1836 $this->db->rollback();
1837 return -1;
1838 }
1839 }
1840 }
1841
1842 // Updating the date of the last monthly balance update
1843 $newMonth = dol_get_next_month((int) dol_print_date($lastUpdate, '%m'), (int) dol_print_date($lastUpdate, '%Y'));
1844 $lastUpdate = dol_mktime(0, 0, 0, (int) $newMonth['month'], 1, (int) $newMonth['year']);
1845
1846 $sql = "UPDATE ".MAIN_DB_PREFIX."holiday_config SET";
1847 $sql .= " value = '".$this->db->escape(dol_print_date($lastUpdate, '%Y%m%d%H%M%S'))."'";
1848 $sql .= " WHERE name = 'lastUpdate'";
1849 $result = $this->db->query($sql);
1850
1851 if (!$result) {
1852 $this->db->rollback();
1853 return -1;
1854 }
1855
1856 $this->db->commit();
1857
1858 $yearMonthLastUpdate = dol_print_date($lastUpdate, '%Y%m');
1859 }
1860
1861 return 1;
1862 } else {
1863 // Update for one user
1864 $nbHoliday = price2num($nbHoliday, 5);
1865
1866 $sql = "SELECT nb_holiday FROM ".MAIN_DB_PREFIX."holiday_users";
1867 $sql .= " WHERE fk_user = ".(int) $userID." AND fk_type = ".(int) $fk_type;
1868 $resql = $this->db->query($sql);
1869 if ($resql) {
1870 $num = $this->db->num_rows($resql);
1871
1872 if ($num > 0) {
1873 // Update for user
1874 $sql = "UPDATE ".MAIN_DB_PREFIX."holiday_users SET";
1875 $sql .= " nb_holiday = ".((float) $nbHoliday);
1876 $sql .= " WHERE fk_user = ".(int) $userID." AND fk_type = ".(int) $fk_type;
1877 $result = $this->db->query($sql);
1878 if (!$result) {
1879 $error++;
1880 $this->errors[] = $this->db->lasterror();
1881 }
1882 } else {
1883 // Insert for user
1884 $sql = "INSERT INTO ".MAIN_DB_PREFIX."holiday_users(nb_holiday, fk_user, fk_type) VALUES (";
1885 $sql .= ((float) $nbHoliday);
1886 $sql .= ", ".(int) $userID.", ".(int) $fk_type.")";
1887 $result = $this->db->query($sql);
1888 if (!$result) {
1889 $error++;
1890 $this->errors[] = $this->db->lasterror();
1891 }
1892 }
1893 } else {
1894 $this->errors[] = $this->db->lasterror();
1895 $error++;
1896 }
1897
1898 if (!$error) {
1899 return 1;
1900 } else {
1901 return -1;
1902 }
1903 }
1904 }
1905
1913 public function createCPusers($single = false, $userid = 0)
1914 {
1915 // do we have to add balance for all users ?
1916 if (!$single) {
1917 dol_syslog(get_class($this).'::createCPusers');
1918 $arrayofusers = $this->fetchUsers(false, true);
1919
1920 foreach ($arrayofusers as $users) {
1921 $sql = "INSERT INTO ".MAIN_DB_PREFIX."holiday_users";
1922 $sql .= " (fk_user, nb_holiday)";
1923 $sql .= " VALUES (".((int) $users['rowid'])."', '0')";
1924
1925 $resql = $this->db->query($sql);
1926 if (!$resql) {
1927 dol_print_error($this->db);
1928 }
1929 }
1930 } else {
1931 $sql = "INSERT INTO ".MAIN_DB_PREFIX."holiday_users";
1932 $sql .= " (fk_user, nb_holiday)";
1933 $sql .= " VALUES (".((int) $userid)."', '0')";
1934
1935 $resql = $this->db->query($sql);
1936 if (!$resql) {
1937 dol_print_error($this->db);
1938 }
1939 }
1940 }
1941
1949 public function getCPforUser($user_id, $fk_type = 0)
1950 {
1951 $sql = "SELECT nb_holiday";
1952 $sql .= " FROM ".MAIN_DB_PREFIX."holiday_users";
1953 $sql .= " WHERE fk_user = ".(int) $user_id;
1954 if ($fk_type > 0) {
1955 $sql .= " AND fk_type = ".(int) $fk_type;
1956 }
1957
1958 dol_syslog(get_class($this).'::getCPforUser user_id='.$user_id.' type_id='.$fk_type, LOG_DEBUG);
1959 $result = $this->db->query($sql);
1960 if ($result) {
1961 $obj = $this->db->fetch_object($result);
1962 //return number_format($obj->nb_holiday,2);
1963 if ($obj) {
1964 return $obj->nb_holiday;
1965 } else {
1966 return null;
1967 }
1968 } else {
1969 return null;
1970 }
1971 }
1972
1981 public function fetchUsers($stringlist = true, $type = true, $sqlFilters = '')
1982 {
1983 dol_syslog(get_class($this)."::fetchUsers", LOG_DEBUG);
1984
1985 if ($stringlist) {
1986 if ($type) {
1987 // If user of Dolibarr
1988 $sql = "SELECT";
1989 if (isModEnabled('multicompany') && getDolGlobalString('MULTICOMPANY_TRANSVERSE_MODE')) {
1990 $sql .= " DISTINCT";
1991 }
1992 $sql .= " u.rowid";
1993 $sql .= " FROM ".MAIN_DB_PREFIX."user as u";
1994
1995 if (isModEnabled('multicompany') && getDolGlobalString('MULTICOMPANY_TRANSVERSE_MODE')) {
1996 $sql .= ", ".MAIN_DB_PREFIX."usergroup_user as ug";
1997 $sql .= " WHERE ((ug.fk_user = u.rowid";
1998 $sql .= " AND ug.entity IN (".getEntity('usergroup')."))";
1999 $sql .= " OR u.entity = 0)"; // Show always superadmin
2000 } else {
2001 $sql .= " WHERE u.entity IN (".getEntity('user').")";
2002 }
2003 $sql .= " AND u.statut > 0";
2004 $sql .= " AND u.employee = 1"; // We only want employee users for holidays
2005 if ($sqlFilters) {
2006 $sql .= $sqlFilters;
2007 }
2008
2009 $resql = $this->db->query($sql);
2010
2011 // If no SQL error
2012 if ($resql) {
2013 $i = 0;
2014 $num = $this->db->num_rows($resql);
2015 $stringlist = '';
2016
2017 // User listing loops
2018 while ($i < $num) {
2019 $obj = $this->db->fetch_object($resql);
2020
2021 if ($i == 0) {
2022 $stringlist .= $obj->rowid;
2023 } else {
2024 $stringlist .= ', '.$obj->rowid;
2025 }
2026
2027 $i++;
2028 }
2029 // Returns the user table
2030 return $stringlist;
2031 } else {
2032 // SQL error
2033 $this->error = "Error ".$this->db->lasterror();
2034 return -1;
2035 }
2036 } else {
2037 // We want only list of vacation balance for user ids
2038 $sql = "SELECT DISTINCT cpu.fk_user";
2039 $sql .= " FROM ".MAIN_DB_PREFIX."holiday_users as cpu, ".MAIN_DB_PREFIX."user as u";
2040 $sql .= " WHERE cpu.fk_user = u.rowid";
2041 if ($sqlFilters) {
2042 $sql .= $sqlFilters;
2043 }
2044
2045 $resql = $this->db->query($sql);
2046
2047 // If no SQL error
2048 if ($resql) {
2049 $i = 0;
2050 $num = $this->db->num_rows($resql);
2051 $stringlist = '';
2052
2053 // User listing loops
2054 while ($i < $num) {
2055 $obj = $this->db->fetch_object($resql);
2056
2057 if ($i == 0) {
2058 $stringlist .= $obj->fk_user;
2059 } else {
2060 $stringlist .= ', '.$obj->fk_user;
2061 }
2062
2063 $i++;
2064 }
2065 // Returns the user table
2066 return $stringlist;
2067 } else {
2068 // SQL error
2069 $this->error = "Error ".$this->db->lasterror();
2070 return -1;
2071 }
2072 }
2073 } else {
2074 // If false, return array
2075 // List for Dolibarr users
2076 if ($type) {
2077 // If we need users of Dolibarr
2078 $sql = "SELECT";
2079 if (isModEnabled('multicompany') && getDolGlobalString('MULTICOMPANY_TRANSVERSE_MODE')) {
2080 $sql .= " DISTINCT";
2081 }
2082 $sql .= " u.rowid, u.lastname, u.firstname, u.gender, u.fk_country as country_id, u.photo, u.employee, u.statut as status, u.fk_user";
2083 $sql .= " FROM ".MAIN_DB_PREFIX."user as u";
2084
2085 if (isModEnabled('multicompany') && getDolGlobalString('MULTICOMPANY_TRANSVERSE_MODE')) {
2086 $sql .= ", ".MAIN_DB_PREFIX."usergroup_user as ug";
2087 $sql .= " WHERE ((ug.fk_user = u.rowid";
2088 $sql .= " AND ug.entity IN (".getEntity('usergroup')."))";
2089 $sql .= " OR u.entity = 0)"; // Show always superadmin
2090 } else {
2091 $sql .= " WHERE u.entity IN (".getEntity('user').")";
2092 }
2093
2094 $sql .= " AND u.statut > 0";
2095 $sql .= " AND u.employee = 1"; // We only want employee users for holidays
2096 if ($sqlFilters) {
2097 $sql .= $sqlFilters;
2098 }
2099
2100 $resql = $this->db->query($sql);
2101
2102 // If no SQL error
2103 if ($resql) {
2104 $i = 0;
2105 $tab_result = $this->holiday;
2106 $num = $this->db->num_rows($resql);
2107
2108 // User listing loops
2109 while ($i < $num) {
2110 $obj = $this->db->fetch_object($resql);
2111
2112 $tab_result[$i]['rowid'] = (int) $obj->rowid; // rowid of user
2113 $tab_result[$i]['id'] = (int) $obj->rowid; // id of user
2114 $tab_result[$i]['name'] = $obj->lastname; // deprecated
2115 $tab_result[$i]['lastname'] = $obj->lastname;
2116 $tab_result[$i]['firstname'] = $obj->firstname;
2117 $tab_result[$i]['gender'] = $obj->gender;
2118 $tab_result[$i]['status'] = (int) $obj->status;
2119 $tab_result[$i]['employee'] = (int) $obj->employee;
2120 $tab_result[$i]['photo'] = $obj->photo;
2121 $tab_result[$i]['fk_user'] = (int) $obj->fk_user; // rowid of manager
2122 $tab_result[$i]['country_id'] = (int) $obj->country_id; // id of country of user
2123 //$tab_result[$i]['type'] = $obj->type;
2124 //$tab_result[$i]['nb_holiday'] = $obj->nb_holiday;
2125
2126 $i++;
2127 }
2128 // Returns the user table
2129 return $tab_result;
2130 } else {
2131 // SQL error
2132 $this->errors[] = "Error ".$this->db->lasterror();
2133 return -1;
2134 }
2135 } else {
2136 // List of vacation balance users
2137 $sql = "SELECT cpu.fk_type, cpu.nb_holiday, u.rowid, u.lastname, u.firstname, u.gender, u.photo, u.employee, u.statut as status, u.fk_user";
2138 $sql .= " FROM ".MAIN_DB_PREFIX."holiday_users as cpu, ".MAIN_DB_PREFIX."user as u";
2139 $sql .= " WHERE cpu.fk_user = u.rowid";
2140 if ($sqlFilters) {
2141 $sql .= $sqlFilters;
2142 }
2143
2144 $resql = $this->db->query($sql);
2145
2146 // If no SQL error
2147 if ($resql) {
2148 $i = 0;
2149 $tab_result = $this->holiday;
2150 $num = $this->db->num_rows($resql);
2151
2152 // User listing loops
2153 while ($i < $num) {
2154 $obj = $this->db->fetch_object($resql);
2155
2156 $tab_result[$i]['rowid'] = $obj->rowid; // rowid of user
2157 $tab_result[$i]['id'] = $obj->rowid; // id of user
2158 $tab_result[$i]['name'] = $obj->lastname; // deprecated
2159 $tab_result[$i]['lastname'] = $obj->lastname;
2160 $tab_result[$i]['firstname'] = $obj->firstname;
2161 $tab_result[$i]['gender'] = $obj->gender;
2162 $tab_result[$i]['status'] = $obj->status;
2163 $tab_result[$i]['employee'] = $obj->employee;
2164 $tab_result[$i]['photo'] = $obj->photo;
2165 $tab_result[$i]['fk_user'] = $obj->fk_user; // rowid of manager
2166
2167 $tab_result[$i]['type'] = $obj->fk_type;
2168 $tab_result[$i]['nb_holiday'] = $obj->nb_holiday;
2169
2170 $i++;
2171 }
2172 // Returns the user table
2173 return $tab_result;
2174 } else {
2175 // SQL error
2176 $this->error = "Error ".$this->db->lasterror();
2177 return -1;
2178 }
2179 }
2180 }
2181 }
2182
2183
2184 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2192 {
2193 // phpcs:enable
2194 $users_validator = array();
2195
2196 $sql = "SELECT DISTINCT ur.fk_user";
2197 $sql .= " FROM ".MAIN_DB_PREFIX."user_rights as ur, ".MAIN_DB_PREFIX."rights_def as rd";
2198 $sql .= " WHERE ur.fk_id = rd.id and rd.module = 'holiday' AND rd.perms = 'approve'"; // Permission 'Approve';
2199 $sql .= "UNION";
2200 $sql .= " SELECT DISTINCT ugu.fk_user";
2201 $sql .= " FROM ".MAIN_DB_PREFIX."usergroup_user as ugu, ".MAIN_DB_PREFIX."usergroup_rights as ur, ".MAIN_DB_PREFIX."rights_def as rd";
2202 $sql .= " WHERE ugu.fk_usergroup = ur.fk_usergroup AND ur.fk_id = rd.id and rd.module = 'holiday' AND rd.perms = 'approve'"; // Permission 'Approve';
2203 //print $sql;
2204
2205 dol_syslog(get_class($this)."::fetch_users_approver_holiday sql=".$sql);
2206 $result = $this->db->query($sql);
2207 if ($result) {
2208 $num_rows = $this->db->num_rows($result);
2209 $i = 0;
2210 while ($i < $num_rows) {
2211 $objp = $this->db->fetch_object($result);
2212 array_push($users_validator, $objp->fk_user);
2213 $i++;
2214 }
2215 return $users_validator;
2216 } else {
2217 $this->error = $this->db->lasterror();
2218 dol_syslog(get_class($this)."::fetch_users_approver_holiday Error ".$this->error, LOG_ERR);
2219 return -1;
2220 }
2221 }
2222
2223
2229 public function countActiveUsers()
2230 {
2231 $sql = "SELECT count(u.rowid) as compteur";
2232 $sql .= " FROM ".MAIN_DB_PREFIX."user as u";
2233 $sql .= " WHERE u.statut > 0";
2234
2235 $result = $this->db->query($sql);
2236 $object = $this->db->fetch_object($result);
2237
2238 return $object->compteur;
2239 }
2246 {
2247 $sql = "SELECT count(u.rowid) as compteur";
2248 $sql .= " FROM ".MAIN_DB_PREFIX."user as u LEFT JOIN ".MAIN_DB_PREFIX."holiday_users hu ON (hu.fk_user=u.rowid)";
2249 $sql .= " WHERE u.statut > 0 AND hu.fk_user IS NULL";
2250
2251 $result = $this->db->query($sql);
2252 $object = $this->db->fetch_object($result);
2253
2254 return $object->compteur;
2255 }
2256
2264 public function verifNbUsers($userDolibarrWithoutCP, $userCP)
2265 {
2266 if (empty($userCP)) {
2267 $userCP = 0;
2268 }
2269 dol_syslog(get_class($this).'::verifNbUsers userDolibarr='.$userDolibarrWithoutCP.' userCP='.$userCP);
2270 return 1;
2271 }
2272
2273
2284 public function addLogCP($fk_user_action, $fk_user_update, $label, $new_solde, $fk_type)
2285 {
2286 $error = 0;
2287
2288 $prev_solde = price2num((float) $this->getCPforUser($fk_user_update, $fk_type), 5);
2289 $new_solde = price2num($new_solde, 5);
2290 //print "$prev_solde == $new_solde";
2291
2292 if ($prev_solde == $new_solde) {
2293 return 0;
2294 }
2295
2296 $this->db->begin();
2297
2298 // Insert request
2299 $sql = "INSERT INTO ".MAIN_DB_PREFIX."holiday_logs (";
2300 $sql .= "date_action,";
2301 $sql .= "fk_user_action,";
2302 $sql .= "fk_user_update,";
2303 $sql .= "type_action,";
2304 $sql .= "prev_solde,";
2305 $sql .= "new_solde,";
2306 $sql .= "fk_type";
2307 $sql .= ") VALUES (";
2308 $sql .= " '".$this->db->idate(dol_now())."',";
2309 $sql .= " ".((int) $fk_user_action).",";
2310 $sql .= " ".((int) $fk_user_update).",";
2311 $sql .= " '".$this->db->escape($label)."',";
2312 $sql .= " ".((float) $prev_solde).",";
2313 $sql .= " ".((float) $new_solde).",";
2314 $sql .= " ".((int) $fk_type);
2315 $sql .= ")";
2316
2317 $resql = $this->db->query($sql);
2318 if (!$resql) {
2319 $error++;
2320 $this->errors[] = "Error ".$this->db->lasterror();
2321 }
2322
2323 $optRowid = 0;
2324 if (!$error) {
2325 $optRowid = $this->db->last_insert_id(MAIN_DB_PREFIX."holiday_logs");
2326 }
2327
2328 // Commit or rollback
2329 if ($error) {
2330 foreach ($this->errors as $errmsg) {
2331 dol_syslog(get_class($this)."::addLogCP ".$errmsg, LOG_ERR);
2332 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
2333 }
2334 $this->db->rollback();
2335 return -1 * $error;
2336 } else {
2337 $this->db->commit();
2338 return $optRowid;
2339 }
2340 }
2341
2349 public function fetchLog($sqlorder, $sqlwhere)
2350 {
2351 $sql = "SELECT";
2352 $sql .= " cpl.rowid,";
2353 $sql .= " cpl.date_action,";
2354 $sql .= " cpl.fk_user_action,";
2355 $sql .= " cpl.fk_user_update,";
2356 $sql .= " cpl.type_action,";
2357 $sql .= " cpl.prev_solde,";
2358 $sql .= " cpl.new_solde,";
2359 $sql .= " cpl.fk_type";
2360 $sql .= " FROM ".MAIN_DB_PREFIX."holiday_logs as cpl";
2361 $sql .= " WHERE cpl.rowid > 0"; // To avoid error with other search and criteria
2362
2363 // Filter
2364 if (!empty($sqlwhere)) {
2365 $sql .= " ".$sqlwhere;
2366 }
2367
2368 // Order
2369 if (!empty($sqlorder)) {
2370 $sql .= " ".$sqlorder;
2371 }
2372
2373 dol_syslog(get_class($this)."::fetchLog", LOG_DEBUG);
2374 $resql = $this->db->query($sql);
2375
2376 // If no error SQL
2377 if ($resql) {
2378 $i = 0;
2379 $tab_result = $this->logs;
2380 $num = $this->db->num_rows($resql);
2381
2382 // If no record
2383 if (!$num) {
2384 return 2;
2385 }
2386
2387 // Loop on result to fill the array
2388 while ($i < $num) {
2389 $obj = $this->db->fetch_object($resql);
2390
2391 $tab_result[$i]['rowid'] = (int) $obj->rowid;
2392 $tab_result[$i]['id'] = (int) $obj->rowid;
2393 $tab_result[$i]['date_action'] = (string) $obj->date_action;
2394 $tab_result[$i]['fk_user_action'] = (int) $obj->fk_user_action;
2395 $tab_result[$i]['fk_user_update'] = (int) $obj->fk_user_update;
2396 $tab_result[$i]['type_action'] = (string) $obj->type_action;
2397 $tab_result[$i]['prev_solde'] = (float) $obj->prev_solde;
2398 $tab_result[$i]['new_solde'] = (float) $obj->new_solde;
2399 $tab_result[$i]['fk_type'] = (int) $obj->fk_type;
2400
2401 $i++;
2402 }
2403 // Returns 1 and adds the array to the variable
2404 $this->logs = $tab_result;
2405 return 1;
2406 } else {
2407 // SQL error
2408 $this->error = "Error ".$this->db->lasterror();
2409 return -1;
2410 }
2411 }
2412
2413
2421 public function getTypes($active = -1, $affect = -1)
2422 {
2423 global $mysoc;
2424
2425 $sql = "SELECT rowid, code, label, affect, delay, newbymonth";
2426 $sql .= " FROM ".MAIN_DB_PREFIX."c_holiday_types";
2427 $sql .= " WHERE (fk_country IS NULL OR fk_country = ".((int) $mysoc->country_id).')';
2428 $sql .= " AND entity IN (0, ".getEntity('c_holiday_types').")"; // Need entity 0 (holiday types common to all countries= + current entity).
2429 if ($active >= 0) {
2430 $sql .= " AND active = ".((int) $active);
2431 }
2432 if ($affect >= 0) {
2433 $sql .= " AND affect = ".((int) $affect);
2434 }
2435 $sql .= " ORDER BY sortorder";
2436
2437 $result = $this->db->query($sql);
2438 if ($result) {
2439 $num = $this->db->num_rows($result);
2440 if ($num) {
2441 $types = array();
2442 while ($obj = $this->db->fetch_object($result)) {
2443 $types[$obj->rowid] = array(
2444 'id' => $obj->rowid,
2445 'rowid' => $obj->rowid,
2446 'code' => $obj->code,
2447 'label' => $obj->label,
2448 'affect' => $obj->affect,
2449 'delay' => $obj->delay,
2450 'newbymonth' => $obj->newbymonth
2451 );
2452 }
2453
2454 return $types;
2455 }
2456 } else {
2457 dol_print_error($this->db);
2458 }
2459
2460 return array();
2461 }
2462
2463
2470 public function info($id)
2471 {
2472 global $conf;
2473
2474 $sql = "SELECT f.rowid, f.statut as status,";
2475 $sql .= " f.date_create as datec,";
2476 $sql .= " f.tms as date_modification,";
2477 $sql .= " f.date_valid as datev,";
2478 $sql .= " f.date_approval as datea,";
2479 $sql .= " f.date_refuse as dater,";
2480 $sql .= " f.fk_user_create as fk_user_creation,";
2481 $sql .= " f.fk_user_modif as fk_user_modification,";
2482 $sql .= " f.fk_user_valid as fk_user_validation,";
2483 $sql .= " f.fk_user_approve as fk_user_approval_done,";
2484 $sql .= " f.fk_validator as fk_user_approval_expected,";
2485 $sql .= " f.fk_user_refuse as fk_user_refuse";
2486 $sql .= " FROM ".MAIN_DB_PREFIX."holiday as f";
2487 $sql .= " WHERE f.rowid = ".((int) $id);
2488 $sql .= " AND f.entity = ".((int) $conf->entity);
2489
2490 $resql = $this->db->query($sql);
2491 if ($resql) {
2492 if ($this->db->num_rows($resql)) {
2493 $obj = $this->db->fetch_object($resql);
2494
2495 $this->id = $obj->rowid;
2496
2497 $this->date_creation = $this->db->jdate($obj->datec);
2498 $this->date_modification = $this->db->jdate($obj->date_modification);
2499 $this->date_validation = $this->db->jdate($obj->datev);
2500 $this->date_approval = $this->db->jdate($obj->datea);
2501
2502 $this->user_creation_id = $obj->fk_user_creation;
2503 $this->user_validation_id = $obj->fk_user_validation;
2504 $this->user_modification_id = $obj->fk_user_modification;
2505
2506 if ($obj->status == Holiday::STATUS_APPROVED || $obj->status == Holiday::STATUS_CANCELED) {
2507 if ($obj->fk_user_approval_done) {
2508 $this->fk_user_approve = $obj->fk_user_approval_done;
2509 }
2510 }
2511 }
2512 $this->db->free($resql);
2513 } else {
2514 dol_print_error($this->db);
2515 }
2516 }
2517
2518
2526 public function initAsSpecimen()
2527 {
2528 global $user, $langs;
2529
2530 // Initialise parameters
2531 $this->id = 0;
2532 $this->specimen = 1;
2533
2534 $this->fk_user = $user->id;
2535 $this->description = 'SPECIMEN description';
2536 $this->date_debut = dol_now();
2537 $this->date_fin = dol_now() + (24 * 3600);
2538 $this->date_valid = dol_now();
2539 $this->fk_validator = $user->id;
2540 $this->halfday = 0;
2541 $this->fk_type = 1;
2543
2544 return 1;
2545 }
2546
2552 public function loadStateBoard()
2553 {
2554 global $user;
2555
2556 $this->nb = array();
2557
2558 $sql = "SELECT count(h.rowid) as nb";
2559 $sql .= " FROM ".MAIN_DB_PREFIX."holiday as h";
2560 $sql .= " WHERE h.statut > 1";
2561 $sql .= " AND h.entity IN (".getEntity('holiday').")";
2562 if (!$user->hasRight('holiday', 'readall')) {
2563 $userchildids = $user->getAllChildIds(1);
2564 $sql .= " AND (h.fk_user IN (".$this->db->sanitize(implode(',', $userchildids)).")";
2565 $sql .= " OR h.fk_validator IN (".$this->db->sanitize(implode(',', $userchildids))."))";
2566 }
2567
2568 $resql = $this->db->query($sql);
2569 if ($resql) {
2570 while ($obj = $this->db->fetch_object($resql)) {
2571 $this->nb["holidays"] = $obj->nb;
2572 }
2573 $this->db->free($resql);
2574 return 1;
2575 } else {
2576 dol_print_error($this->db);
2577 $this->error = $this->db->error();
2578 return -1;
2579 }
2580 }
2581
2582 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2589 public function load_board($user)
2590 {
2591 // phpcs:enable
2592 global $conf, $langs;
2593
2594 if ($user->socid) {
2595 return -1; // Protection to prevent calls by external users
2596 }
2597
2598 $now = dol_now();
2599
2600 $sql = "SELECT h.rowid, h.date_debut";
2601 $sql .= " FROM ".MAIN_DB_PREFIX."holiday as h";
2602 $sql .= " WHERE h.statut = 2";
2603 $sql .= " AND h.entity IN (".getEntity('holiday').")";
2604 if (!$user->hasRight('holiday', 'read_all')) {
2605 $userchildids = $user->getAllChildIds(1);
2606 $sql .= " AND (h.fk_user IN (".$this->db->sanitize(implode(',', $userchildids)).")";
2607 $sql .= " OR h.fk_validator IN (".$this->db->sanitize(implode(',', $userchildids))."))";
2608 }
2609
2610 $resql = $this->db->query($sql);
2611 if ($resql) {
2612 $langs->load("members");
2613
2614 $response = new WorkboardResponse();
2615 $response->warning_delay = $conf->holiday->approve->warning_delay / 60 / 60 / 24;
2616 $response->label = $langs->trans("HolidaysToApprove");
2617 $response->labelShort = $langs->trans("ToApprove");
2618 $response->url = DOL_URL_ROOT.'/holiday/list.php?search_status=2&amp;mainmenu=hrm&amp;leftmenu=holiday';
2619 $response->img = img_object('', "holiday");
2620
2621 while ($obj = $this->db->fetch_object($resql)) {
2622 $response->nbtodo++;
2623
2624 if ($this->db->jdate($obj->date_debut) < ($now - $conf->holiday->approve->warning_delay)) {
2625 $response->nbtodolate++;
2626 }
2627 }
2628
2629 return $response;
2630 } else {
2631 dol_print_error($this->db);
2632 $this->error = $this->db->error();
2633 return -1;
2634 }
2635 }
2643 public function getKanbanView($option = '', $arraydata = null)
2644 {
2645 global $langs;
2646
2647 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
2648
2649 $return = '<div class="box-flex-item box-flex-grow-zero">';
2650 $return .= '<div class="info-box info-box-sm">';
2651 $return .= '<span class="info-box-icon bg-infobox-action">';
2652 $return .= img_picto('', $this->picto);
2653 $return .= '</span>';
2654 $return .= '<div class="info-box-content">';
2655 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.$this->getNomUrl().'</span>';
2656 if ($selected >= 0) {
2657 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
2658 }
2659 if (property_exists($this, 'fk_type')) {
2660 $return .= '<br>';
2661 //$return .= '<span class="opacitymedium">'.$langs->trans("Type").'</span> : ';
2662 $return .= '<div class="info_box-label tdoverflowmax100" title="'.dol_escape_htmltag($arraydata['labeltype']).'">'.dol_escape_htmltag($arraydata['labeltype']).'</div>';
2663 }
2664 if (property_exists($this, 'date_debut') && property_exists($this, 'date_fin')) {
2665 $return .= '<span class="info-box-label small">'.dol_print_date($this->date_debut, 'day').'</span>';
2666 $return .= ' <span class="opacitymedium small">'.$langs->trans("To").'</span> ';
2667 $return .= '<span class="info-box-label small">'.dol_print_date($this->date_fin, 'day').'</span>';
2668 if (!empty($arraydata['nbopenedday'])) {
2669 $return .= ' ('.$arraydata['nbopenedday'].')';
2670 }
2671 }
2672 if (method_exists($this, 'getLibStatut')) {
2673 $return .= '<div class="info-box-status">'.$this->getLibStatut(3).'</div>';
2674 }
2675 $return .= '</div>';
2676 $return .= '</div>';
2677 $return .= '</div>';
2678 return $return;
2679 }
2680
2691 public function sendPreviousMonthHRInformations($mailto = "", $template = "", $newlang = "")
2692 {
2693 global $conf, $langs, $user;
2694
2695 $outputlangs = $langs;
2696
2697 $error = 0;
2698 $this->output = '';
2699 $this->error = '';
2700 $arrayfields = array(
2701 'user' => 'Employee',
2702 'type' => 'Type',
2703 'date_start' => 'DateDebCP',
2704 'date_end' => 'DateFinCP',
2705 'used_days' => 'NbUseDaysCPShort',
2706 );
2707
2708 if (!empty($newlang)) {
2709 $outputlangs = new Translate("", $conf);
2710 $outputlangs->setDefaultLang($newlang);
2711 }
2712 $outputlangs->loadLangs(array('main', 'holiday', 'hrm'));
2713
2714 if (empty($mailto) || !isValidEmail($mailto)) {
2715 $this->errors[] = 'Bad value for parameter mailto. Must be a valid email address.';
2716 return 1;
2717 }
2718
2719 $typeleaves = $this->getTypes(1, -1);
2720 $arraytypeleaves = array();
2721 foreach ($typeleaves as $val) {
2722 $labeltoshow = ($outputlangs->trans($val['code']) != $val['code'] ? $outputlangs->trans($val['code']) : $val['label']);
2723 $arraytypeleaves[$val['rowid']] = $labeltoshow;
2724 }
2725 $listhalfday = array('morning' => $outputlangs->trans("Morning"), "afternoon" => $outputlangs->trans("Afternoon"));
2726
2727 $datenow = dol_getdate(dol_now());
2728 $prev_month = dol_get_prev_month($datenow["mon"], $datenow["year"]);
2729 $year_month = sprintf("%04d", $prev_month["year"]).'-'.sprintf("%02d", $prev_month["month"]);
2730 $arrayleaves = array();
2731
2732 $sql = "SELECT cp.rowid, cp.ref, cp.fk_user, cp.date_debut, cp.date_fin, cp.fk_type, cp.description, cp.halfday, cp.statut as status";
2733 $sql .= " FROM ".MAIN_DB_PREFIX."holiday cp";
2734 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user u ON cp.fk_user = u.rowid";
2735 $sql .= " WHERE cp.entity IN (".getEntity('holiday').") AND cp.rowid > 0";
2736 $sql .= " AND cp.statut = ".Holiday::STATUS_APPROVED;
2737 $sql .= " AND (";
2738 $sql .= " (date_format(cp.date_debut, '%Y-%m') = '".$this->db->escape($year_month)."' OR date_format(cp.date_fin, '%Y-%m') = '".$this->db->escape($year_month)."')";
2739 $sql .= " OR"; // For leave over several months
2740 $sql .= " (date_format(cp.date_debut, '%Y-%m') < '".$this->db->escape($year_month)."' AND date_format(cp.date_fin, '%Y-%m') > '".$this->db->escape($year_month)."') ";
2741 $sql .= " )";
2742 $sql .= $this->db->order("cp.fk_user, cp.date_debut", "ASC");
2743 $resql = $this->db->query($sql);
2744 if (empty($resql)) {
2745 $this->errors[] = $this->db->lasterror();
2746 return 1;
2747 }
2748 $num = $this->db->num_rows($resql);
2749 if ($num > 0) {
2750 $tmpuser = new User($this->db);
2751 while ($obj = $this->db->fetch_object($resql)) {
2752 $tmpuser->fetch($obj->fk_user);
2753
2754 $date_start = $this->db->jdate($obj->date_debut, true);
2755 $date_end = $this->db->jdate($obj->date_fin, true);
2756
2757 $tmpstart = dol_getdate($date_start);
2758 $tmpend = dol_getdate($date_end);
2759
2760 $starthalfday = ($obj->halfday == -1 || $obj->halfday == 2) ? 'afternoon' : 'morning';
2761 $endhalfday = ($obj->halfday == 1 || $obj->halfday == 2) ? 'morning' : 'afternoon';
2762
2763 $halfdayinmonth = $obj->halfday;
2764 $starthalfdayinmonth = $starthalfday;
2765 $endhalfdayinmonth = $endhalfday;
2766
2767 //0:Full days, 2:Start afternoon end morning, -1:Start afternoon end afternoon, 1:Start morning end morning
2768
2769 // Set date_start_gmt and date_end_gmt that are date to show for the selected month
2770 $date_start_inmonth = $this->db->jdate($obj->date_debut, true);
2771 $date_end_inmonth = $this->db->jdate($obj->date_fin, true);
2772 if ($tmpstart['year'] < $prev_month["year"] || $tmpstart['mon'] < $prev_month["month"]) {
2773 $date_start_inmonth = dol_get_first_day($prev_month["year"], $prev_month["month"], true);
2774 $starthalfdayinmonth = 'morning';
2775 if ($halfdayinmonth == 2) {
2776 $halfdayinmonth = 1;
2777 }
2778 if ($halfdayinmonth == -1) {
2779 $halfdayinmonth = 0;
2780 }
2781 }
2782 if ($tmpend['year'] > $prev_month["year"] || $tmpend['mon'] > $prev_month["month"]) {
2783 $date_end_inmonth = dol_get_last_day($prev_month["year"], $prev_month["month"], true) - ((24 * 3600) - 1);
2784 $endhalfdayinmonth = 'afternoon';
2785 if ($halfdayinmonth == 2) {
2786 $halfdayinmonth = -1;
2787 }
2788 if ($halfdayinmonth == 1) {
2789 $halfdayinmonth = 0;
2790 }
2791 }
2792 $arrayleaves[] = array(
2793 "user" => $tmpuser->getNomUrl(0, 'nolink', 0, 0, 24, 1),
2794 "type" => $arraytypeleaves[$obj->fk_type],
2795 "date_start" => dol_print_date($date_start_inmonth, 'day') . ' <span class="opacitymedium">('.$outputlangs->trans($listhalfday[$starthalfdayinmonth]).')</span>',
2796 "date_end" => dol_print_date($date_end_inmonth, 'day') . ' <span class="opacitymedium">('.$outputlangs->trans($listhalfday[$endhalfdayinmonth]).')</span>',
2797 "used_days" => num_open_day($date_start_inmonth, $date_end_inmonth, 0, 1, $halfdayinmonth, $tmpuser->country_id, $obj->fk_user)
2798 );
2799 }
2800 }
2801
2802 $outputarrayleaves = '<br><table style="width: 100%;border-collapse: separate !important;border-spacing: 0px;border-top: 1px solid #b6b6b6;border-left: 1px solid #b6b6b6;border-right: 1px solid #b6b6b6;margin: 0px 0px 20px 0px;">';
2803 $outputarrayleaves .= '<tr>';
2804 foreach ($arrayfields as $key => $label) {
2805 $outputarrayleaves .= '<td style="border-bottom:1px solid #b6b6b6;padding: 6px 10px 6px 12px;">';
2806 $outputarrayleaves .= $outputlangs->trans($label);
2807 if ($key == 'date_end') {
2808 $outputarrayleaves .=" (".$langs->trans("Included").")";
2809 }
2810 $outputarrayleaves .= '</td>';
2811 }
2812 $outputarrayleaves .= '</tr>';
2813
2814 if (!empty($arrayleaves)) {
2815 foreach ($arrayleaves as $fields) {
2816 $outputarrayleaves .= '<tr>';
2817 foreach ($fields as $field => $value) {
2818 $outputarrayleaves .= '<td style="border-bottom:1px solid #b6b6b6;padding: 6px 10px 6px 12px;" id="'.$field.'">';
2819 $outputarrayleaves .= $value;
2820 $outputarrayleaves .= '</td>';
2821 }
2822 $outputarrayleaves .= '</tr>';
2823 }
2824 } else {
2825 $outputarrayleaves .= '<tr>';
2826 $outputarrayleaves .= '<td style="border-bottom:1px solid #b6b6b6;padding: 6px 10px 6px 12px;" colspan="5">';
2827 $outputarrayleaves .= $outputlangs->trans("None");
2828 $outputarrayleaves .= '</td>';
2829 $outputarrayleaves .= '</tr>';
2830 }
2831 $outputarrayleaves .= '</table>';
2832
2833 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
2834 include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
2835
2836 $formmail = new FormMail($this->db);
2837 $templateId = 0;
2838 $templateLabel = '';
2839 if (empty($template) || $template == 'EmailTemplateCode') {
2840 $templateLabel = '(HolidayHrInformationsPreviousMonth)';
2841 } else {
2842 if (is_numeric($template)) {
2843 $templateId = $template;
2844 } else {
2845 $templateLabel = $template;
2846 }
2847 }
2848 $mailtemplate = $formmail->getEMailTemplate($this->db, "holiday", $user, $outputlangs, $templateId, 1, $templateLabel);
2849
2850 if (is_numeric($mailtemplate) || empty($mailtemplate->topic)) {
2851 $this->errors[] = 'No mail template found for code "'.$templateLabel.'" or id "'.$templateId.'".';
2852 $error++;
2853 }
2854
2855 if (!$error) {
2856 $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $this);
2857 complete_substitutions_array($substitutionarray, $outputlangs, $this);
2858
2859 $subject = make_substitutions($mailtemplate->topic, $substitutionarray, $outputlangs);
2860 $msg = make_substitutions($mailtemplate->content, $substitutionarray, $outputlangs);
2861 $from = dol_string_nospecial(getDolGlobalString('MAIN_INFO_SOCIETE_NOM'), ' ', array(",")).' <' . getDolGlobalString('MAIN_INFO_SOCIETE_MAIL').'>';
2862
2863 $msg = preg_replace('/__HOLIDAY_ARRAY_PER_EMPLOYEE_FOR_PERIOD__/', $outputarrayleaves, $msg);
2864 $cmail = new CMailFile($subject, $mailto, $from, $msg, array(), array(), array(), '', '', 0, 1);
2865 $result = $cmail->sendfile();
2866 if (!$result || !empty($cmail->error) || !empty($cmail->errors)) {
2867 $this->errors[] = $cmail->error;
2868 if (is_array($cmail->errors) && count($cmail->errors) > 0) {
2869 $this->errors = array_merge($this->errors, $cmail->errors);
2870 $error++;
2871 }
2872 }
2873 }
2874
2875 if (!empty($this->errors)) {
2876 $this->output .= "\n";
2877 // The $this->errors will be concatenated to the output by the function that call this method.
2878 }
2879 return ($error ? 1 : 0);
2880 }
2881}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
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:476
$object ref
Definition info.php:90
Class to send emails (with attachments or not) Usage: $mailfile = new CMailFile($subject,...
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...
deleteExtraFields()
Delete all extra fields values for the current object.
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
Class to manage a HTML form to send a unitary email Usage: $formail = new FormMail($db) $formmail->pr...
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 clickable 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.
fetchUsers($stringlist=true, $type=true, $sqlFilters='')
Get list of Users or list of vacation balance.
info($id)
Load information on object.
updateBalance()
Update balance of vacations and check table of users for holidays is complete.
updateConfCP($name, $value)
Update an option of the Holiday module.
const STATUS_VALIDATED
Validated status.
const STATUS_DRAFT
Draft status.
fetchAll($sqlOrder, $sqlFilter)
List all holidays of all users.
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 the number of active Dolibarr users to the number of paid leave users.
verifDateHolidayForTimestamp($fk_user, $timestamp, $status='-1')
Check that a user is not on holiday for a particular timestamp.
approve($user=null, $notrigger=0)
Approve leave request.
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.
create($user, $notrigger=0)
Create a paid leave entry in the database.
selectStatutCP($selected=0, $htmlname='select_statut', $morecss='minwidth125')
Show select with list of leave status.
countActiveUsersWithoutCP()
Count number of active users in Dolibarr without Paid leave.
updateSoldeCP($userID=0, $nbHoliday=0, $fk_type=0)
Updates the timestamp of the last CP balance update.
update($user=null, $notrigger=0)
Update database.
getCPforUser($user_id, $fk_type=0)
Return the balance of annual leave of a user.
sendPreviousMonthHRInformations($mailto="", $template="", $newlang="")
Send a mail with previous month Hr information CAN BE A CRON TASK.
fetch_users_approver_holiday()
Return list of people with permission to validate leave requests.
__construct($db)
Constructor.
loadStateBoard()
Load this->nb for dashboard.
getLibStatut($mode=0)
Returns the label status.
createCPusers($single=false, $userid=0)
Create entries for each user at setup step.
const STATUS_CANCELED
Canceled.
fetchLog($sqlorder, $sqlwhere)
List log of leaves.
countActiveUsers()
Count number of active users in Dolibarr.
fetchByUser($user_id, $order='', $filter='')
List holidays for a particular user or list of users.
const STATUS_APPROVED
Approved.
getTooltipContentArray($params)
getTooltipContentArray
getKanbanView($option='', $arraydata=null)
Return clickable link of object (with eventually picto)
LibStatut($status, $mode=0, $startdate='')
Returns the label of a status.
Class to manage translations.
Class to manage Dolibarr users.
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition index.php:169
global $mysoc
dol_get_prev_month($month, $year)
Return previous month.
Definition date.lib.php:539
num_open_day($timestampStart, $timestampEnd, $inhour=0, $lastday=0, $halfday=0, $countryCodeOrId='', $user_id=0)
Function to return number of working days (and text of units) between two dates (working days)
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
Definition date.lib.php:620
dol_get_next_month($month, $year)
Return next month.
Definition date.lib.php:558
dol_stringtotime($string, $gm=1)
Convert a string date into a GM Timestamps date Warning: YYYY-MM-DDTHH:MM:SS+02:00 (RFC3339) is not s...
Definition date.lib.php:451
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition date.lib.php:639
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
dol_dir_list($utf8_path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition files.lib.php:64
$date_start
Variables from include:
dol_now($mode='gmt')
Return date for now.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_string_nospecial($str, $newstr='_', $badcharstoreplace='', $badcharstoremove='', $keepspaces=0)
Clean a string from all punctuation characters to use it as a ref or login.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
isValidEmail($address, $acceptsupervisorkey=0, $acceptuserkey=0)
Return true if email syntax is ok.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
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.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
buildzip.php