dolibarr 25.0.0-alpha
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
539 $sql .= " ua.lastname as validator_lastname,";
540 $sql .= " ua.firstname as validator_firstname,";
541 $sql .= " ua.login as validator_login,";
542 $sql .= " ua.statut as validator_status,";
543 $sql .= " ua.photo as validator_photo";
544
545 $sql .= " FROM ".MAIN_DB_PREFIX."holiday as cp, ".MAIN_DB_PREFIX."user as uu, ".MAIN_DB_PREFIX."user as ua";
546 $sql .= " WHERE cp.entity IN (".getEntity('holiday').")";
547 $sql .= " AND cp.fk_user = uu.rowid AND cp.fk_validator = ua.rowid"; // Hack needed for search on the list
548 $sql .= " AND cp.fk_user IN (".$this->db->sanitize($user_id).")";
549
550 // Selection filter
551 if (!empty($filter)) {
552 $sql .= $filter; // @phan-suppress-current-line SqlInjection
553 }
554
555 // Order of display of the result
556 if (!empty($order)) {
557 $sql .= $order; // @phan-suppress-current-line SqlInjection
558 }
559
560 dol_syslog(get_class($this)."::fetchByUser", LOG_DEBUG);
561 $resql = $this->db->query($sql);
562
563 // If no SQL error
564 if ($resql) {
565 $i = 0;
566 $tab_result = $this->holiday;
567 $num = $this->db->num_rows($resql);
568
569 // If no registration
570 if (!$num) {
571 return 2;
572 }
573
574 // List the records and add them to the table
575 while ($i < $num) {
576 $obj = $this->db->fetch_object($resql);
577
578 $tab_result[$i]['rowid'] = (int) $obj->rowid;
579 $tab_result[$i]['id'] = (int) $obj->rowid;
580 $tab_result[$i]['ref'] = (string) ($obj->ref ? $obj->ref : $obj->rowid);
581
582 $tab_result[$i]['fk_user'] = (int) $obj->fk_user;
583 $tab_result[$i]['fk_type'] = (int) $obj->fk_type;
584 $tab_result[$i]['date_create'] = $this->db->jdate($obj->date_create);
585 $tab_result[$i]['date_modification'] = $this->db->jdate($obj->date_modification);
586 $tab_result[$i]['description'] = (string) $obj->description;
587 $tab_result[$i]['date_debut'] = $this->db->jdate($obj->date_debut);
588 $tab_result[$i]['date_fin'] = $this->db->jdate($obj->date_fin);
589 $tab_result[$i]['date_debut_gmt'] = $this->db->jdate($obj->date_debut, 1);
590 $tab_result[$i]['date_fin_gmt'] = $this->db->jdate($obj->date_fin, 1);
591 $tab_result[$i]['halfday'] = (int) $obj->halfday;
592 $tab_result[$i]['statut'] = (int) $obj->status;
593 $tab_result[$i]['status'] = (int) $obj->status;
594 $tab_result[$i]['fk_validator'] = (int) $obj->fk_validator;
595 $tab_result[$i]['date_valid'] = $this->db->jdate($obj->date_valid);
596 $tab_result[$i]['fk_user_valid'] = (int) $obj->fk_user_valid;
597 $tab_result[$i]['date_approval'] = $this->db->jdate($obj->date_approval);
598 $tab_result[$i]['fk_user_approve'] = (int) $obj->fk_user_approve;
599 $tab_result[$i]['date_refuse'] = $this->db->jdate($obj->date_refuse);
600 $tab_result[$i]['fk_user_refuse'] = (int) $obj->fk_user_refuse;
601 $tab_result[$i]['date_cancel'] = $this->db->jdate($obj->date_cancel);
602 $tab_result[$i]['fk_user_cancel'] = (int) $obj->fk_user_cancel;
603 $tab_result[$i]['detail_refuse'] = (string) $obj->detail_refuse;
604
605 $tab_result[$i]['user_firstname'] = (string) $obj->user_firstname;
606 $tab_result[$i]['user_lastname'] = (string) $obj->user_lastname;
607 $tab_result[$i]['user_login'] = (string) $obj->user_login;
608 $tab_result[$i]['user_statut'] = (int) $obj->user_status;
609 $tab_result[$i]['user_status'] = (int) $obj->user_status;
610 $tab_result[$i]['user_photo'] = (string) $obj->user_photo;
611
612 $tab_result[$i]['validator_firstname'] = (string) $obj->validator_firstname;
613 $tab_result[$i]['validator_lastname'] = (string) $obj->validator_lastname;
614 $tab_result[$i]['validator_login'] = (string) $obj->validator_login;
615 $tab_result[$i]['validator_statut'] = (int) $obj->validator_status;
616 $tab_result[$i]['validator_status'] = (int) $obj->validator_status;
617 $tab_result[$i]['validator_photo'] = (string) $obj->validator_photo;
618
619 $i++;
620 }
621
622 // Returns 1 with the filled array
623 $this->holiday = $tab_result;
624 return 1;
625 } else {
626 // SQL Error
627 $this->error = "Error ".$this->db->lasterror();
628 return -1;
629 }
630 }
631
639 public function fetchAll($sqlOrder, $sqlFilter)
640 {
641 $sql = "SELECT";
642 $sql .= " cp.rowid,";
643 $sql .= " cp.ref,";
644 $sql .= " cp.fk_user,";
645 $sql .= " cp.fk_type,";
646 $sql .= " cp.date_create,";
647 $sql .= " cp.tms as date_modification,";
648 $sql .= " cp.description,";
649 $sql .= " cp.date_debut,";
650 $sql .= " cp.date_fin,";
651 $sql .= " cp.halfday,";
652 $sql .= " cp.statut as status,";
653 $sql .= " cp.fk_validator,";
654 $sql .= " cp.date_valid,";
655 $sql .= " cp.fk_user_valid,";
656 $sql .= " cp.date_approval,";
657 $sql .= " cp.fk_user_approve,";
658 $sql .= " cp.date_refuse,";
659 $sql .= " cp.fk_user_refuse,";
660 $sql .= " cp.date_cancel,";
661 $sql .= " cp.fk_user_cancel,";
662 $sql .= " cp.detail_refuse,";
663
664 $sql .= " uu.lastname as user_lastname,";
665 $sql .= " uu.firstname as user_firstname,";
666 $sql .= " uu.login as user_login,";
667 $sql .= " uu.statut as user_status,";
668 $sql .= " uu.photo as user_photo,";
669
670 $sql .= " ua.lastname as validator_lastname,";
671 $sql .= " ua.firstname as validator_firstname,";
672 $sql .= " ua.login as validator_login,";
673 $sql .= " ua.statut as validator_status,";
674 $sql .= " ua.photo as validator_photo";
675
676 $sql .= " FROM ".MAIN_DB_PREFIX."holiday as cp, ".MAIN_DB_PREFIX."user as uu, ".MAIN_DB_PREFIX."user as ua";
677 $sql .= " WHERE cp.entity IN (".getEntity('holiday').")";
678 $sql .= " AND cp.fk_user = uu.rowid AND cp.fk_validator = ua.rowid "; // Hack needed for search on the list
679
680 // Selection filtering
681 if (!empty($sqlFilter)) {
682 $sql .= $sqlFilter;
683 }
684
685 // order of display
686 if (!empty($sqlOrder)) {
687 $sql .= $sqlOrder;
688 }
689
690 dol_syslog(get_class($this)."::fetchAll", LOG_DEBUG);
691 $resql = $this->db->query($sql);
692
693 // If no SQL error
694 if ($resql) {
695 $i = 0;
696 $tab_result = $this->holiday;
697 $num = $this->db->num_rows($resql);
698
699 // If no registration
700 if (!$num) {
701 return 2;
702 }
703
704 // List the records and add them to the table
705 while ($i < $num) {
706 $obj = $this->db->fetch_object($resql);
707
708 $tab_result[$i]['rowid'] = (int) $obj->rowid;
709 $tab_result[$i]['id'] = (int) $obj->rowid;
710 $tab_result[$i]['ref'] = (string) ($obj->ref ? $obj->ref : $obj->rowid);
711
712 $tab_result[$i]['fk_user'] = (int) $obj->fk_user;
713 $tab_result[$i]['fk_type'] = (int) $obj->fk_type;
714 $tab_result[$i]['date_create'] = $this->db->jdate($obj->date_create);
715 $tab_result[$i]['date_modification'] = $this->db->jdate($obj->date_modification);
716 $tab_result[$i]['description'] = (string) $obj->description;
717 $tab_result[$i]['date_debut'] = $this->db->jdate($obj->date_debut);
718 $tab_result[$i]['date_fin'] = $this->db->jdate($obj->date_fin);
719 $tab_result[$i]['date_debut_gmt'] = $this->db->jdate($obj->date_debut, 1);
720 $tab_result[$i]['date_fin_gmt'] = $this->db->jdate($obj->date_fin, 1);
721 $tab_result[$i]['halfday'] = (int) $obj->halfday;
722 $tab_result[$i]['statut'] = (int) $obj->status;
723 $tab_result[$i]['status'] = (int) $obj->status;
724 $tab_result[$i]['fk_validator'] = (int) $obj->fk_validator;
725 $tab_result[$i]['date_valid'] = $this->db->jdate($obj->date_valid);
726 $tab_result[$i]['fk_user_valid'] = (int) $obj->fk_user_valid;
727 $tab_result[$i]['date_approval'] = $this->db->jdate($obj->date_approval);
728 $tab_result[$i]['fk_user_approve'] = (int) $obj->fk_user_approve;
729 $tab_result[$i]['date_refuse'] = $this->db->jdate($obj->date_refuse);
730 $tab_result[$i]['fk_user_refuse'] = (int) $obj->fk_user_refuse;
731 $tab_result[$i]['date_cancel'] = $this->db->jdate($obj->date_cancel);
732 $tab_result[$i]['fk_user_cancel'] = (int) $obj->fk_user_cancel;
733 $tab_result[$i]['detail_refuse'] = (string) $obj->detail_refuse;
734
735 $tab_result[$i]['user_firstname'] = (string) $obj->user_firstname;
736 $tab_result[$i]['user_lastname'] = (string) $obj->user_lastname;
737 $tab_result[$i]['user_login'] = (string) $obj->user_login;
738 $tab_result[$i]['user_statut'] = (int) $obj->user_status;
739 $tab_result[$i]['user_status'] = (int) $obj->user_status;
740 $tab_result[$i]['user_photo'] = (string) $obj->user_photo;
741
742 $tab_result[$i]['validator_firstname'] = (string) $obj->validator_firstname;
743 $tab_result[$i]['validator_lastname'] = (string) $obj->validator_lastname;
744 $tab_result[$i]['validator_login'] = (string) $obj->validator_login;
745 $tab_result[$i]['validator_statut'] = (int) $obj->validator_status;
746 $tab_result[$i]['validator_status'] = (int) $obj->validator_status;
747 $tab_result[$i]['validator_photo'] = (string) $obj->validator_photo;
748
749 $i++;
750 }
751 // Returns 1 and adds the array to the variable
752 $this->holiday = $tab_result;
753 return 1;
754 } else {
755 // SQL Error
756 $this->error = "Error ".$this->db->lasterror();
757 return -1;
758 }
759 }
760
761
769 public function validate($user = null, $notrigger = 0)
770 {
771 global $conf, $langs;
772 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
773 $error = 0;
774
775
776 $checkBalance = getDictionaryValue('c_holiday_types', 'block_if_negative', $this->fk_type, true);
777
778 if ($checkBalance > 0) {
779 $balance = $this->getCPforUser($this->fk_user, $this->fk_type);
780 $daysAsked = num_open_day($this->date_debut, $this->date_fin, 0, 1, 0, '', $this->fk_user);
781
782 if (($balance - $daysAsked) < 0 && getDolGlobalString('HOLIDAY_DISALLOW_NEGATIVE_BALANCE')) {
783 $this->error = 'LeaveRequestCreationBlockedBecauseBalanceIsNegative';
784 return -1;
785 }
786 }
787
788 // Define new ref
789 if (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref) || $this->ref == $this->id) {
790 $num = $this->getNextNumRef(null);
791 } else {
792 $num = (string) $this->ref;
793 }
794 $this->newref = dol_sanitizeFileName($num);
795
796 // Update status
797 $sql = "UPDATE ".MAIN_DB_PREFIX."holiday SET";
798 $sql .= " fk_user_valid = ".((int) $user->id).",";
799 $sql .= " date_valid = '".$this->db->idate(dol_now())."',";
800 if (!empty($this->status) && is_numeric($this->status)) {
801 $sql .= " statut = ".((int) $this->status).",";
802 } else {
803 $this->error = 'Property status must be a numeric value';
804 $error++;
805 }
806 $sql .= " ref = '".$this->db->escape($num)."'";
807 $sql .= " WHERE rowid = ".((int) $this->id);
808
809 $this->db->begin();
810
811 dol_syslog(get_class($this)."::validate", LOG_DEBUG);
812 $resql = $this->db->query($sql);
813 if (!$resql) {
814 $error++;
815 $this->errors[] = "Error ".$this->db->lasterror();
816 }
817
818 if (!$error) {
819 if (!$notrigger) {
820 // Call trigger
821 $result = $this->call_trigger('HOLIDAY_VALIDATE', $user);
822 if ($result < 0) {
823 $error++;
824 }
825 // End call triggers
826 }
827 }
828
829 if (!$error) {
830 $this->oldref = $this->ref;
831
832 // Rename directory if dir was a temporary ref
833 if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
834 // Now we rename also files into index
835 $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) . "'";
836 $sql .= " WHERE filename LIKE '" . $this->db->escape($this->ref) . "%' AND filepath = 'holiday/" . $this->db->escape($this->ref) . "' and entity = " . ((int) $conf->entity);
837 $resql = $this->db->query($sql);
838 if (!$resql) {
839 $error++;
840 $this->error = $this->db->lasterror();
841 }
842 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'holiday/".$this->db->escape($this->newref)."'";
843 $sql .= " WHERE filepath = 'holiday/".$this->db->escape($this->ref)."' and entity = ".((int) $conf->entity);
844 $resql = $this->db->query($sql);
845 if (!$resql) {
846 $error++;
847 $this->error = $this->db->lasterror();
848 }
849
850 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
851 $oldref = dol_sanitizeFileName($this->ref);
852 $newref = dol_sanitizeFileName($num);
853 $dirsource = $conf->holiday->multidir_output[$this->entity] . '/' . $oldref;
854 $dirdest = $conf->holiday->multidir_output[$this->entity] . '/' . $newref;
855 if (!$error && file_exists($dirsource)) {
856 dol_syslog(get_class($this) . "::validate rename dir " . $dirsource . " into " . $dirdest);
857 if (@rename($dirsource, $dirdest)) {
858 dol_syslog("Rename ok");
859 // Rename docs starting with $oldref with $newref
860 $listoffiles = dol_dir_list($dirdest, 'files', 1, '^' . preg_quote($oldref, '/'));
861 foreach ($listoffiles as $fileentry) {
862 $dirsource = $fileentry['name'];
863 $dirdest = preg_replace('/^' . preg_quote($oldref, '/') . '/', $newref, $dirsource);
864 $dirsource = $fileentry['path'] . '/' . $dirsource;
865 $dirdest = $fileentry['path'] . '/' . $dirdest;
866 @rename($dirsource, $dirdest);
867 }
868 }
869 }
870 }
871 }
872
873
874 // Commit or rollback
875 if ($error) {
876 foreach ($this->errors as $errmsg) {
877 dol_syslog(get_class($this)."::validate ".$errmsg, LOG_ERR);
878 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
879 }
880 $this->db->rollback();
881 return -1 * $error;
882 } else {
883 $this->db->commit();
884 return 1;
885 }
886 }
887
888
896 public function approve($user = null, $notrigger = 0)
897 {
898 $error = 0;
899
900 $checkBalance = getDictionaryValue('c_holiday_types', 'block_if_negative', $this->fk_type, true);
901
902 if ($checkBalance > 0) {
903 $balance = $this->getCPforUser($this->fk_user, $this->fk_type);
904 $daysAsked = num_open_day($this->date_debut, $this->date_fin, 0, 1, 0, '', $this->fk_user);
905
906 if (($balance - $daysAsked) < 0 && getDolGlobalString('HOLIDAY_DISALLOW_NEGATIVE_BALANCE')) {
907 $this->error = 'LeaveRequestCreationBlockedBecauseBalanceIsNegative';
908 return -1;
909 }
910 }
911
912 // Update request
913 $sql = "UPDATE ".MAIN_DB_PREFIX."holiday SET";
914 $sql .= " description= '".$this->db->escape($this->description)."',";
915 if (!empty($this->date_debut)) {
916 $sql .= " date_debut = '".$this->db->idate($this->date_debut)."',";
917 } else {
918 $error++;
919 }
920 if (!empty($this->date_fin)) {
921 $sql .= " date_fin = '".$this->db->idate($this->date_fin)."',";
922 } else {
923 $error++;
924 }
925 $sql .= " halfday = ".((int) $this->halfday).",";
926 if (!empty($this->status) && is_numeric($this->status)) {
927 $sql .= " statut = ".((int) $this->status).",";
928 } else {
929 $error++;
930 }
931 if (!empty($this->fk_validator)) {
932 $sql .= " fk_validator = ".((int) $this->fk_validator).",";
933 } else {
934 $error++;
935 }
936 if (!empty($this->date_valid)) {
937 $sql .= " date_valid = '".$this->db->idate($this->date_valid)."',";
938 } else {
939 $sql .= " date_valid = NULL,";
940 }
941 if (!empty($this->fk_user_valid)) {
942 $sql .= " fk_user_valid = ".((int) $this->fk_user_valid).",";
943 } else {
944 $sql .= " fk_user_valid = NULL,";
945 }
946 if (!empty($this->date_approval)) {
947 $sql .= " date_approval = '".$this->db->idate($this->date_approval)."',";
948 } else {
949 $sql .= " date_approval = NULL,";
950 }
951 if (!empty($this->fk_user_approve)) {
952 $sql .= " fk_user_approve = ".((int) $this->fk_user_approve).",";
953 } else {
954 $sql .= " fk_user_approve = NULL,";
955 }
956 if (!empty($this->date_refuse)) {
957 $sql .= " date_refuse = '".$this->db->idate($this->date_refuse)."',";
958 } else {
959 $sql .= " date_refuse = NULL,";
960 }
961 if (!empty($this->fk_user_refuse)) {
962 $sql .= " fk_user_refuse = ".((int) $this->fk_user_refuse).",";
963 } else {
964 $sql .= " fk_user_refuse = NULL,";
965 }
966 if (!empty($this->date_cancel)) {
967 $sql .= " date_cancel = '".$this->db->idate($this->date_cancel)."',";
968 } else {
969 $sql .= " date_cancel = NULL,";
970 }
971 if (!empty($this->fk_user_cancel)) {
972 $sql .= " fk_user_cancel = ".((int) $this->fk_user_cancel).",";
973 } else {
974 $sql .= " fk_user_cancel = NULL,";
975 }
976 if (!empty($this->detail_refuse)) {
977 $sql .= " detail_refuse = '".$this->db->escape($this->detail_refuse)."'";
978 } else {
979 $sql .= " detail_refuse = NULL";
980 }
981 $sql .= " WHERE rowid = ".((int) $this->id);
982
983 $this->db->begin();
984
985 dol_syslog(get_class($this)."::approve", LOG_DEBUG);
986 $resql = $this->db->query($sql);
987 if (!$resql) {
988 $error++;
989 $this->errors[] = "Error ".$this->db->lasterror();
990 }
991
992 if (!$error) {
993 if (!$notrigger) {
994 // Call trigger
995 $result = $this->call_trigger('HOLIDAY_APPROVE', $user);
996 if ($result < 0) {
997 $error++;
998 }
999 // End call triggers
1000 }
1001 }
1002
1003 // Commit or rollback
1004 if ($error) {
1005 foreach ($this->errors as $errmsg) {
1006 dol_syslog(get_class($this)."::approve ".$errmsg, LOG_ERR);
1007 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
1008 }
1009 $this->db->rollback();
1010 return -1 * $error;
1011 } else {
1012 $this->db->commit();
1013 return 1;
1014 }
1015 }
1016
1024 public function update($user = null, $notrigger = 0)
1025 {
1026 $error = 0;
1027
1028 $checkBalance = getDictionaryValue('c_holiday_types', 'block_if_negative', $this->fk_type, true);
1029
1030 if ($checkBalance > 0 && $this->status != self::STATUS_DRAFT && $this->status != self::STATUS_CANCELED) {
1031 $balance = $this->getCPforUser($this->fk_user, $this->fk_type);
1032 $daysAsked = num_open_day($this->date_debut, $this->date_fin, 0, 1, 0, '', $this->fk_user);
1033
1034 if (($balance - $daysAsked) < 0 && getDolGlobalString('HOLIDAY_DISALLOW_NEGATIVE_BALANCE')) {
1035 $this->error = 'LeaveRequestCreationBlockedBecauseBalanceIsNegative';
1036 return -1;
1037 }
1038 }
1039
1040 // Update request
1041 $sql = "UPDATE ".MAIN_DB_PREFIX."holiday SET";
1042
1043 $sql .= " description= '".$this->db->escape($this->description)."',";
1044
1045 if (!empty($this->date_create)) {
1046 $sql .= " date_create = '".$this->db->idate($this->date_create)."',";
1047 } else {
1048 $error++;
1049 }
1050 if (!empty($this->date_debut)) {
1051 $sql .= " date_debut = '".$this->db->idate($this->date_debut)."',";
1052 } else {
1053 $error++;
1054 }
1055 if (!empty($this->date_fin)) {
1056 $sql .= " date_fin = '".$this->db->idate($this->date_fin)."',";
1057 } else {
1058 $error++;
1059 }
1060 $sql .= " halfday = ".((int) $this->halfday).",";
1061 if (!empty($this->status) && is_numeric($this->status)) {
1062 $sql .= " statut = ".((int) $this->status).",";
1063 } else {
1064 $error++;
1065 }
1066 if (!empty($this->fk_validator)) {
1067 $sql .= " fk_validator = ".((int) $this->fk_validator).",";
1068 } else {
1069 $error++;
1070 }
1071 if (!empty($this->date_valid)) {
1072 $sql .= " date_valid = '".$this->db->idate($this->date_valid)."',";
1073 } else {
1074 $sql .= " date_valid = NULL,";
1075 }
1076 if (!empty($this->fk_user_valid)) {
1077 $sql .= " fk_user_valid = ".((int) $this->fk_user_valid).",";
1078 } else {
1079 $sql .= " fk_user_valid = NULL,";
1080 }
1081 if (!empty($this->date_approval)) {
1082 $sql .= " date_approval = '".$this->db->idate($this->date_approval)."',";
1083 } else {
1084 $sql .= " date_approval = NULL,";
1085 }
1086 if (!empty($this->fk_user_approve)) {
1087 $sql .= " fk_user_approve = ".((int) $this->fk_user_approve).",";
1088 } else {
1089 $sql .= " fk_user_approve = NULL,";
1090 }
1091 if (!empty($this->date_refuse)) {
1092 $sql .= " date_refuse = '".$this->db->idate($this->date_refuse)."',";
1093 } else {
1094 $sql .= " date_refuse = NULL,";
1095 }
1096 if (!empty($this->fk_user_refuse)) {
1097 $sql .= " fk_user_refuse = ".((int) $this->fk_user_refuse).",";
1098 } else {
1099 $sql .= " fk_user_refuse = NULL,";
1100 }
1101 if (!empty($this->date_cancel)) {
1102 $sql .= " date_cancel = '".$this->db->idate($this->date_cancel)."',";
1103 } else {
1104 $sql .= " date_cancel = NULL,";
1105 }
1106 if (!empty($this->fk_user_cancel)) {
1107 $sql .= " fk_user_cancel = ".((int) $this->fk_user_cancel).",";
1108 } else {
1109 $sql .= " fk_user_cancel = NULL,";
1110 }
1111 if (!empty($this->detail_refuse)) {
1112 $sql .= " detail_refuse = '".$this->db->escape($this->detail_refuse)."'";
1113 } else {
1114 $sql .= " detail_refuse = NULL";
1115 }
1116
1117 $sql .= " WHERE rowid = ".((int) $this->id);
1118
1119 $this->db->begin();
1120
1121 dol_syslog(get_class($this)."::update", LOG_DEBUG);
1122 $resql = $this->db->query($sql);
1123 if (!$resql) {
1124 $error++;
1125 $this->errors[] = "Error ".$this->db->lasterror();
1126 }
1127
1128 if (!$error) {
1129 $result = $this->insertExtraFields();
1130 if ($result < 0) {
1131 $error++;
1132 }
1133 }
1134
1135 if (!$error) {
1136 if (!$notrigger && $user !== null) {
1137 // Call trigger
1138 $result = $this->call_trigger('HOLIDAY_MODIFY', $user);
1139 if ($result < 0) {
1140 $error++;
1141 }
1142 // End call triggers
1143 }
1144 }
1145
1146 // Commit or rollback
1147 if ($error) {
1148 foreach ($this->errors as $errmsg) {
1149 dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
1150 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
1151 }
1152 $this->db->rollback();
1153 return -1 * $error;
1154 } else {
1155 $this->db->commit();
1156 return 1;
1157 }
1158 }
1159
1160
1168 public function delete($user, $notrigger = 0)
1169 {
1170 global $conf, $langs;
1171 $error = 0;
1172
1173 $sql = "DELETE FROM ".MAIN_DB_PREFIX."holiday";
1174 $sql .= " WHERE rowid=".((int) $this->id);
1175
1176 $this->db->begin();
1177
1178 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1179 $resql = $this->db->query($sql);
1180 if (!$resql) {
1181 $error++;
1182 $this->errors[] = "Error ".$this->db->lasterror();
1183 }
1184
1185 if (!$error) {
1186 if (!$notrigger) {
1187 // Call trigger
1188 $result = $this->call_trigger('HOLIDAY_DELETE', $user);
1189 if ($result < 0) {
1190 $error++;
1191 }
1192 // End call triggers
1193 }
1194 }
1195
1196 // Commit or rollback
1197 if ($error) {
1198 foreach ($this->errors as $errmsg) {
1199 dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
1200 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
1201 }
1202 $this->db->rollback();
1203 return -1 * $error;
1204 } else {
1205 $this->db->commit();
1206 return 1;
1207 }
1208 }
1209
1223 public function verifDateHolidayCP($fk_user, $dateStart, $dateEnd, $halfday = 0)
1224 {
1225 $this->fetchByUser($fk_user, '', '');
1226
1227 foreach ($this->holiday as $infos_CP) {
1228 if ($infos_CP['statut'] == Holiday::STATUS_CANCELED) {
1229 continue; // ignore not validated holidays
1230 }
1231 if ($infos_CP['statut'] == Holiday::STATUS_REFUSED) {
1232 continue; // ignore refused holidays
1233 }
1234 //var_dump("--");
1235 //var_dump("old: ".dol_print_date($infos_CP['date_debut'],'dayhour').' '.dol_print_date($infos_CP['date_fin'],'dayhour').' '.$infos_CP['halfday']);
1236 //var_dump("new: ".dol_print_date($dateStart,'dayhour').' '.dol_print_date($dateEnd,'dayhour').' '.$halfday);
1237
1238 // A new leave can fully contain an existing leave, so neither endpoint is inside the existing range.
1239 if ($dateStart < $infos_CP['date_debut'] && $dateEnd > $infos_CP['date_fin']) {
1240 return false;
1241 }
1242
1243 if ($halfday == 0) {
1244 if ($dateStart >= $infos_CP['date_debut'] && $dateStart <= $infos_CP['date_fin']) {
1245 return false;
1246 }
1247 if ($dateEnd <= $infos_CP['date_fin'] && $dateEnd >= $infos_CP['date_debut']) {
1248 return false;
1249 }
1250 } elseif ($halfday == -1) {
1251 // new start afternoon, new end afternoon
1252 if ($dateStart >= $infos_CP['date_debut'] && $dateStart <= $infos_CP['date_fin']) {
1253 if ($dateStart < $infos_CP['date_fin'] || in_array($infos_CP['halfday'], array(0, -1))) {
1254 return false;
1255 }
1256 }
1257 if ($dateEnd <= $infos_CP['date_fin'] && $dateEnd >= $infos_CP['date_debut']) {
1258 if ($dateStart < $dateEnd) {
1259 return false;
1260 }
1261 if ($dateEnd < $infos_CP['date_fin'] || in_array($infos_CP['halfday'], array(0, -1))) {
1262 return false;
1263 }
1264 }
1265 } elseif ($halfday == 1) {
1266 // new start morning, new end morning
1267 if ($dateStart >= $infos_CP['date_debut'] && $dateStart <= $infos_CP['date_fin']) {
1268 if ($dateStart < $dateEnd) {
1269 return false;
1270 }
1271 if ($dateStart > $infos_CP['date_debut'] || in_array($infos_CP['halfday'], array(0, 1))) {
1272 return false;
1273 }
1274 }
1275 if ($dateEnd <= $infos_CP['date_fin'] && $dateEnd >= $infos_CP['date_debut']) {
1276 if ($dateEnd > $infos_CP['date_debut'] || in_array($infos_CP['halfday'], array(0, 1))) {
1277 return false;
1278 }
1279 }
1280 } elseif ($halfday == 2) {
1281 // new start afternoon, new end morning
1282 if ($dateStart >= $infos_CP['date_debut'] && $dateStart <= $infos_CP['date_fin']) {
1283 if ($dateStart < $infos_CP['date_fin'] || in_array($infos_CP['halfday'], array(0, -1))) {
1284 return false;
1285 }
1286 }
1287 if ($dateEnd <= $infos_CP['date_fin'] && $dateEnd >= $infos_CP['date_debut']) {
1288 if ($dateEnd > $infos_CP['date_debut'] || in_array($infos_CP['halfday'], array(0, 1))) {
1289 return false;
1290 }
1291 }
1292 } else {
1293 dol_print_error(null, 'Bad value of parameter halfday when calling function verifDateHolidayCP');
1294 }
1295 }
1296
1297 return true;
1298 }
1299
1300
1310 public function verifDateHolidayForTimestamp($fk_user, $timestamp, $status = '-1')
1311 {
1312 $isavailablemorning = true;
1313 $isavailableafternoon = true;
1314
1315 // Check into leave requests
1316 $sql = "SELECT cp.rowid, cp.date_debut as date_start, cp.date_fin as date_end, cp.halfday, cp.statut as status";
1317 $sql .= " FROM ".MAIN_DB_PREFIX."holiday as cp";
1318 $sql .= " WHERE cp.entity IN (".getEntity('holiday').")";
1319 $sql .= " AND cp.fk_user = ".(int) $fk_user;
1320 $sql .= " AND cp.date_debut <= '".$this->db->idate($timestamp)."' AND cp.date_fin >= '".$this->db->idate($timestamp)."'";
1321 if ($status != '-1') {
1322 $sql .= " AND cp.statut IN (".$this->db->sanitize($status).")";
1323 }
1324
1325 $resql = $this->db->query($sql);
1326 if ($resql) {
1327 $num_rows = $this->db->num_rows($resql); // Note, we can have 2 records if on is morning and the other one is afternoon
1328 if ($num_rows > 0) {
1329 $arrayofrecord = array();
1330 $i = 0;
1331 while ($i < $num_rows) {
1332 $obj = $this->db->fetch_object($resql);
1333
1334 // Note: $obj->halfday is 0:Full days, 2:Start afternoon end morning, -1:Start afternoon, 1:End morning
1335 $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);
1336 $i++;
1337 }
1338
1339 // We found a record, user is on holiday by default, so is not available is true.
1340 $isavailablemorning = true;
1341 foreach ($arrayofrecord as $record) {
1342 if ($timestamp == $record['date_start'] && $record['halfday'] == 2) {
1343 continue;
1344 }
1345 if ($timestamp == $record['date_start'] && $record['halfday'] == -1) {
1346 continue;
1347 }
1348 $isavailablemorning = false;
1349 break;
1350 }
1351 $isavailableafternoon = true;
1352 foreach ($arrayofrecord as $record) {
1353 if ($timestamp == $record['date_end'] && $record['halfday'] == 2) {
1354 continue;
1355 }
1356 if ($timestamp == $record['date_end'] && $record['halfday'] == 1) {
1357 continue;
1358 }
1359 $isavailableafternoon = false;
1360 break;
1361 }
1362 }
1363 } else {
1364 dol_print_error($this->db);
1365 }
1366
1367 $result = array('morning' => (int) $isavailablemorning, 'afternoon' => (int) $isavailableafternoon);
1368 if (!$isavailablemorning) {
1369 $result['morning_reason'] = 'leave_request';
1370 }
1371 if (!$isavailableafternoon) {
1372 $result['afternoon_reason'] = 'leave_request';
1373 }
1374 return $result;
1375 }
1376
1383 public function getTooltipContentArray($params)
1384 {
1385 global $langs;
1386
1387 $langs->load('holiday');
1388 $nofetch = !empty($params['nofetch']);
1389
1390 $datas = array();
1391 $datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("Holiday").'</u>';
1392 if (isset($this->status)) {
1393 $datas['picto'] .= ' '.$this->getLibStatut(5);
1394 }
1395 $datas['ref'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
1396 // show type for this record only in ajax to not overload lists
1397 if (!$nofetch && !empty($this->fk_type)) {
1398 $typeleaves = $this->getTypes(1, -1);
1399 if (empty($typeleaves[$this->fk_type])) {
1400 $labeltoshow = $langs->trans("TypeWasDisabledOrRemoved", $this->fk_type);
1401 } else {
1402 $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']);
1403 }
1404 $datas['type'] = '<br><b>'.$langs->trans("Type") . ':</b> ' . $labeltoshow;
1405 }
1406 if (isset($this->halfday) && !empty($this->date_debut) && !empty($this->date_fin)) {
1407 $listhalfday = array(
1408 'morning' => $langs->trans("Morning"),
1409 "afternoon" => $langs->trans("Afternoon")
1410 );
1411 $starthalfday = ($this->halfday == -1 || $this->halfday == 2) ? 'afternoon' : 'morning';
1412 $endhalfday = ($this->halfday == 1 || $this->halfday == 2) ? 'morning' : 'afternoon';
1413 $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>';
1414 $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>';
1415 }
1416
1417
1418 return $datas;
1419 }
1420
1430 public function getNomUrl($withpicto = 0, $save_lastsearch_value = -1, $notooltip = 0, $morecss = '')
1431 {
1432 global $conf, $langs, $hookmanager;
1433
1434 if (!empty($conf->dol_no_mouse_hover)) {
1435 $notooltip = 1; // Force disable tooltips
1436 }
1437
1438 $result = '';
1439 $params = [
1440 'id' => $this->id,
1441 'objecttype' => $this->element,
1442 'nofetch' => 1,
1443 ];
1444 $classfortooltip = 'classfortooltip';
1445 $dataparams = '';
1446 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1447 $classfortooltip = 'classforajaxtooltip';
1448 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
1449 $label = '';
1450 } else {
1451 $label = implode($this->getTooltipContentArray($params));
1452 }
1453
1454 $url = DOL_URL_ROOT.'/holiday/card.php?id='.$this->id;
1455
1456 //if ($option != 'nolink')
1457 //{
1458 // Add param to save lastsearch_values or not
1459 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1460 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1461 $add_save_lastsearch_values = 1;
1462 }
1463 if ($add_save_lastsearch_values) {
1464 $url .= '&save_lastsearch_values=1';
1465 }
1466 //}
1467
1468 $linkclose = '';
1469 if (empty($notooltip)) {
1470 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1471 $label = $langs->trans("ShowMyObject");
1472 $linkclose .= ' alt="'.dolPrintHTMLForAttribute($label).'"';
1473 }
1474 $linkclose .= ($label ? ' title="'.dolPrintHTMLForAttribute($label).'"' : ' title="tocomplete"');
1475 $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
1476 } else {
1477 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1478 }
1479
1480 $linkstart = '<a href="'.$url.'"';
1481 $linkstart .= $linkclose.'>';
1482 $linkend = '</a>';
1483
1484 $result .= $linkstart;
1485
1486 if ($withpicto) {
1487 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"'), 0, 0, $notooltip ? 0 : 1);
1488 }
1489 if ($withpicto != 2) {
1490 $result .= $this->ref;
1491 }
1492 $result .= $linkend;
1493
1494 global $action;
1495 $hookmanager->initHooks(array($this->element . 'dao'));
1496 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1497 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1498 if ($reshook > 0) {
1499 $result = $hookmanager->resPrint;
1500 } else {
1501 $result .= $hookmanager->resPrint;
1502 }
1503 return $result;
1504 }
1505
1506
1513 public function getLibStatut($mode = 0)
1514 {
1515 return $this->LibStatut($this->status, $mode, $this->date_debut);
1516 }
1517
1518 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1527 public function LibStatut($status, $mode = 0, $startdate = '')
1528 {
1529 // phpcs:enable
1530 global $langs;
1531
1532 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
1533 global $langs;
1534 //$langs->load("mymodule");
1535 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('DraftCP');
1536 $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('ToReviewCP');
1537 $this->labelStatus[self::STATUS_APPROVED] = $langs->transnoentitiesnoconv('ApprovedCP');
1538 $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('CancelCP');
1539 $this->labelStatus[self::STATUS_REFUSED] = $langs->transnoentitiesnoconv('RefuseCP');
1540 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('DraftCP');
1541 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('ToReviewCP');
1542 $this->labelStatusShort[self::STATUS_APPROVED] = $langs->transnoentitiesnoconv('ApprovedCP');
1543 $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('CancelCP');
1544 $this->labelStatusShort[self::STATUS_REFUSED] = $langs->transnoentitiesnoconv('RefuseCP');
1545 }
1546
1547 $params = array();
1548 $statusType = 'status6';
1549 if (!empty($startdate) && $startdate >= dol_now()) { // If not yet passed, we use a green "in live" color
1550 $statusType = 'status4';
1551 $params = array('tooltip' => $this->labelStatus[$status].' - '.$langs->trans("Forthcoming"));
1552 }
1553 if ($status == self::STATUS_DRAFT) {
1554 $statusType = 'status0';
1555 }
1556 if ($status == self::STATUS_VALIDATED) {
1557 $statusType = 'status1';
1558 }
1559 if ($status == self::STATUS_CANCELED) {
1560 $statusType = 'status9';
1561 }
1562 if ($status == self::STATUS_REFUSED) {
1563 $statusType = 'status9';
1564 }
1565
1566 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode, '', $params);
1567 }
1568
1569
1578 public function selectStatutCP($selected = 0, $htmlname = 'select_statut', $morecss = 'minwidth125')
1579 {
1580 global $langs;
1581
1582 // List of status label
1583 $name = array('DraftCP', 'ToReviewCP', 'ApprovedCP', 'CancelCP', 'RefuseCP');
1584 $nb = count($name) + 1;
1585
1586 // Select HTML
1587 $out = '<select name="'.$htmlname.'" id="'.$htmlname.'" class="flat'.($morecss ? ' '.$morecss : '').'">'."\n";
1588 $out .= '<option value="-1">&nbsp;</option>'."\n";
1589
1590 // Loop on status
1591 for ($i = 1; $i < $nb; $i++) {
1592 if ($i == $selected) {
1593 $out .= '<option value="'.$i.'" selected>'.$langs->trans($name[$i - 1]).'</option>'."\n";
1594 } else {
1595 $out .= '<option value="'.$i.'">'.$langs->trans($name[$i - 1]).'</option>'."\n";
1596 }
1597 }
1598
1599 $out .= "</select>\n";
1600
1601 $showempty = 0;
1602 $out .= ajax_combobox($htmlname, array(), 0, 0, 'resolve', ($showempty < 0 ? (string) $showempty : '-1'), $morecss);
1603
1604 return $out;
1605 }
1606
1614 public function updateConfCP($name, $value)
1615 {
1616 $sql = "UPDATE ".MAIN_DB_PREFIX."holiday_config SET";
1617 $sql .= " value = '".$this->db->escape($value)."'";
1618 $sql .= " WHERE name = '".$this->db->escape($name)."'";
1619
1620 dol_syslog(get_class($this).'::updateConfCP name='.$name, LOG_DEBUG);
1621 $result = $this->db->query($sql);
1622 if ($result) {
1623 return true;
1624 }
1625
1626 return false;
1627 }
1628
1637 public function getConfCP($name, $createifnotfound = '')
1638 {
1639 $sql = "SELECT value";
1640 $sql .= " FROM ".MAIN_DB_PREFIX."holiday_config";
1641 $sql .= " WHERE name = '".$this->db->escape($name)."'";
1642
1643 dol_syslog(get_class($this).'::getConfCP name='.$name.' createifnotfound='.$createifnotfound, LOG_DEBUG);
1644 $result = $this->db->query($sql);
1645
1646 if ($result) {
1647 $obj = $this->db->fetch_object($result);
1648 // Return value
1649 if (empty($obj)) {
1650 if ($createifnotfound) {
1651 $sql = "INSERT INTO ".MAIN_DB_PREFIX."holiday_config(name, value)";
1652 $sql .= " VALUES('".$this->db->escape($name)."', '".$this->db->escape($createifnotfound)."')";
1653 $result = $this->db->query($sql);
1654 if ($result) {
1655 return $createifnotfound;
1656 } else {
1657 $this->error = $this->db->lasterror();
1658 return -2;
1659 }
1660 } else {
1661 return '';
1662 }
1663 } else {
1664 return $obj->value;
1665 }
1666 } else {
1667 // Erreur SQL
1668 $this->error = $this->db->lasterror();
1669 return -1;
1670 }
1671 }
1672
1681 public function updateSoldeCP($userID = 0, $nbHoliday = 0, $fk_type = 0)
1682 {
1683 global $user, $langs;
1684
1685 $error = 0;
1686
1687 if (empty($userID) && empty($nbHoliday) && empty($fk_type)) {
1688 include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
1689 $langs->load("holiday");
1690
1691 $decrease = getDolGlobalInt('HOLIDAY_DECREASE_AT_END_OF_MONTH');
1692
1693 // If updated for everyone at the beginning of the month
1694 $now = dol_now();
1695
1696 // Get month of last update
1697 $stringInDBForLastUpdate = $this->getConfCP('lastUpdate', dol_print_date($now, '%Y%m%d%H%M%S')); // Example '20200101120000'
1698 // The lastUpdate config row is created empty (value NULL) at install, so getConfCP() returns an empty value
1699 // the first time. Treat an empty value as "start from now" (like define_holiday.php does) instead of a very
1700 // old date, otherwise the catch-up loop below would credit every user with years of monthly accrual at once.
1701 if (empty($stringInDBForLastUpdate)) {
1702 $stringInDBForLastUpdate = dol_print_date($now, '%Y%m%d%H%M%S');
1703 }
1704 // Protection when $lastUpdate has a not valid value
1705 if ($stringInDBForLastUpdate < '20000101000000') {
1706 $stringInDBForLastUpdate = '20000101000000';
1707 }
1708 $lastUpdate = dol_stringtotime($stringInDBForLastUpdate);
1709 //print 'lastUpdate:'.$lastUpdate;exit;
1710
1711 $yearMonthLastUpdate = dol_print_date($lastUpdate, '%Y%m');
1712 $yearMonthNow = dol_print_date($now, '%Y%m');
1713 //print 'yearMonthLastUpdate='.$yearMonthLastUpdate.' yearMonthNow='.$yearMonthNow;
1714
1715 // 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,
1716 // catching up to the current month if a gap is detected
1717 while ($yearMonthLastUpdate < $yearMonthNow) {
1718 $this->db->begin();
1719
1720 $year = dol_print_date($lastUpdate, '%Y');
1721 $month = dol_print_date($lastUpdate, '%m');
1722
1723 $users = $this->fetchUsers(false, false, ' AND u.statut > 0');
1724 $nbUser = count($users);
1725
1726 $typeleaves = $this->getTypes(1, 1);
1727
1728 // Update each user counter
1729 foreach ($users as $userCounter) {
1730 $nbDaysToAdd = (isset($typeleaves[$userCounter['type']]['newbymonth']) ? $typeleaves[$userCounter['type']]['newbymonth'] : 0);
1731 if (empty($nbDaysToAdd)) {
1732 continue;
1733 }
1734
1735 dol_syslog("We update leave type id ".$userCounter['type']." for user id ".$userCounter['rowid'], LOG_DEBUG);
1736
1737 $nowHoliday = (float) $userCounter['nb_holiday'];
1738 $newSolde = $nowHoliday + $nbDaysToAdd;
1739
1740 // We add a log for each user when its balance gets increased
1741 $this->addLogCP($user->id, $userCounter['rowid'], $langs->trans('HolidayMonthlyCredit'), $newSolde, $userCounter['type']);
1742
1743 $result = $this->updateSoldeCP($userCounter['rowid'], $newSolde, $userCounter['type']);
1744
1745 if ($result < 0) {
1746 $this->db->rollback();
1747 return -1;
1748 }
1749
1750 if (empty($decrease)) {
1751 continue;
1752 }
1753
1754 // 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
1755 $filter = " AND cp.statut = ".((int) self::STATUS_APPROVED);
1756 $filter .= " AND cp.date_fin >= '".$this->db->idate(dol_stringtotime(dol_print_date($lastUpdate, '%Y-%m-01')))."'";
1757 $filter .= " AND cp.date_debut <= '".$this->db->idate(dol_stringtotime(dol_print_date($lastUpdate, '%Y-%m-t')))."'";
1758 $filter .= " AND cp.fk_type = ".((int) $userCounter['type']);
1759 $this->fetchByUser($userCounter['id'], '', $filter);
1760
1761 if (empty($this->holiday)) {
1762 continue;
1763 }
1764
1765 $startOfMonth = dol_mktime(0, 0, 0, (int) $month, 1, (int) $year, 1);
1766 $endOfMonth = dol_mktime(0, 0, 0, (int) $month, (int) dol_print_date($lastUpdate, 't'), (int) $year, 1);
1767
1768 foreach ($this->holiday as $obj) {
1769 $startDate = $obj['date_debut_gmt'];
1770 $endDate = $obj['date_fin_gmt'];
1771
1772 if ($startDate <= $endOfMonth && $startDate < $startOfMonth) {
1773 $startDate = $startOfMonth;
1774 }
1775
1776 if ($startOfMonth <= $endDate && $endDate > $endOfMonth) {
1777 $endDate = $endOfMonth;
1778 }
1779
1780 $nbDaysToDeduct = (int) num_open_day($startDate, $endDate, 0, 1, $obj['halfday'], $obj['country_id'], $obj['fk_user']);
1781
1782 if ($nbDaysToDeduct <= 0) {
1783 continue;
1784 }
1785
1786 $newSolde -= $nbDaysToDeduct;
1787
1788 // We add a log for each user when its balance gets decreased
1789 $this->addLogCP($user->id, $userCounter['rowid'], $obj['ref'].' - '.$langs->trans('HolidayConsumption'), $newSolde, $userCounter['type']);
1790
1791 $result = $this->updateSoldeCP($userCounter['rowid'], $newSolde, $userCounter['type']);
1792
1793 if ($result < 0) {
1794 $this->db->rollback();
1795 return -1;
1796 }
1797 }
1798 }
1799
1800 // Updating the date of the last monthly balance update
1801 $newMonth = dol_get_next_month((int) dol_print_date($lastUpdate, '%m'), (int) dol_print_date($lastUpdate, '%Y'));
1802 $lastUpdate = dol_mktime(0, 0, 0, (int) $newMonth['month'], 1, (int) $newMonth['year']);
1803
1804 $sql = "UPDATE ".MAIN_DB_PREFIX."holiday_config SET";
1805 $sql .= " value = '".$this->db->escape(dol_print_date($lastUpdate, '%Y%m%d%H%M%S'))."'";
1806 $sql .= " WHERE name = 'lastUpdate'";
1807 $result = $this->db->query($sql);
1808
1809 if (!$result) {
1810 $this->db->rollback();
1811 return -1;
1812 }
1813
1814 $this->db->commit();
1815
1816 $yearMonthLastUpdate = dol_print_date($lastUpdate, '%Y%m');
1817 }
1818
1819 return 1;
1820 } else {
1821 // Update for one user
1822 $nbHoliday = price2num($nbHoliday, 5);
1823
1824 $sql = "SELECT nb_holiday FROM ".MAIN_DB_PREFIX."holiday_users";
1825 $sql .= " WHERE fk_user = ".(int) $userID." AND fk_type = ".(int) $fk_type;
1826 $resql = $this->db->query($sql);
1827 if ($resql) {
1828 $num = $this->db->num_rows($resql);
1829
1830 if ($num > 0) {
1831 // Update for user
1832 $sql = "UPDATE ".MAIN_DB_PREFIX."holiday_users SET";
1833 $sql .= " nb_holiday = ".((float) $nbHoliday);
1834 $sql .= " WHERE fk_user = ".(int) $userID." AND fk_type = ".(int) $fk_type;
1835 $result = $this->db->query($sql);
1836 if (!$result) {
1837 $error++;
1838 $this->errors[] = $this->db->lasterror();
1839 }
1840 } else {
1841 // Insert for user
1842 $sql = "INSERT INTO ".MAIN_DB_PREFIX."holiday_users(nb_holiday, fk_user, fk_type) VALUES (";
1843 $sql .= ((float) $nbHoliday);
1844 $sql .= ", ".(int) $userID.", ".(int) $fk_type.")";
1845 $result = $this->db->query($sql);
1846 if (!$result) {
1847 $error++;
1848 $this->errors[] = $this->db->lasterror();
1849 }
1850 }
1851 } else {
1852 $this->errors[] = $this->db->lasterror();
1853 $error++;
1854 }
1855
1856 if (!$error) {
1857 return 1;
1858 } else {
1859 return -1;
1860 }
1861 }
1862 }
1863
1871 public function createCPusers($single = false, $userid = 0)
1872 {
1873 // do we have to add balance for all users ?
1874 if (!$single) {
1875 dol_syslog(get_class($this).'::createCPusers');
1876 $arrayofusers = $this->fetchUsers(false, true);
1877
1878 foreach ($arrayofusers as $users) {
1879 $sql = "INSERT INTO ".MAIN_DB_PREFIX."holiday_users";
1880 $sql .= " (fk_user, nb_holiday)";
1881 $sql .= " VALUES (".((int) $users['rowid'])."', '0')";
1882
1883 $resql = $this->db->query($sql);
1884 if (!$resql) {
1885 dol_print_error($this->db);
1886 }
1887 }
1888 } else {
1889 $sql = "INSERT INTO ".MAIN_DB_PREFIX."holiday_users";
1890 $sql .= " (fk_user, nb_holiday)";
1891 $sql .= " VALUES (".((int) $userid)."', '0')";
1892
1893 $resql = $this->db->query($sql);
1894 if (!$resql) {
1895 dol_print_error($this->db);
1896 }
1897 }
1898 }
1899
1907 public function getCPforUser($user_id, $fk_type = 0)
1908 {
1909 $sql = "SELECT nb_holiday";
1910 $sql .= " FROM ".MAIN_DB_PREFIX."holiday_users";
1911 $sql .= " WHERE fk_user = ".(int) $user_id;
1912 if ($fk_type > 0) {
1913 $sql .= " AND fk_type = ".(int) $fk_type;
1914 }
1915
1916 dol_syslog(get_class($this).'::getCPforUser user_id='.$user_id.' type_id='.$fk_type, LOG_DEBUG);
1917 $result = $this->db->query($sql);
1918 if ($result) {
1919 $obj = $this->db->fetch_object($result);
1920 //return number_format($obj->nb_holiday,2);
1921 if ($obj) {
1922 return $obj->nb_holiday;
1923 } else {
1924 return null;
1925 }
1926 } else {
1927 return null;
1928 }
1929 }
1930
1939 public function fetchUsers($stringlist = true, $type = true, $sqlFilters = '')
1940 {
1941 dol_syslog(get_class($this)."::fetchUsers", LOG_DEBUG);
1942
1943 if ($stringlist) {
1944 if ($type) {
1945 // If user of Dolibarr
1946 $sql = "SELECT";
1947 if (isModEnabled('multicompany') && getDolGlobalString('MULTICOMPANY_TRANSVERSE_MODE')) {
1948 $sql .= " DISTINCT";
1949 }
1950 $sql .= " u.rowid";
1951 $sql .= " FROM ".MAIN_DB_PREFIX."user as u";
1952
1953 if (isModEnabled('multicompany') && getDolGlobalString('MULTICOMPANY_TRANSVERSE_MODE')) {
1954 $sql .= ", ".MAIN_DB_PREFIX."usergroup_user as ug";
1955 $sql .= " WHERE ((ug.fk_user = u.rowid";
1956 $sql .= " AND ug.entity IN (".getEntity('usergroup')."))";
1957 $sql .= " OR u.entity = 0)"; // Show always superadmin
1958 } else {
1959 $sql .= " WHERE u.entity IN (".getEntity('user').")";
1960 }
1961 $sql .= " AND u.statut > 0";
1962 $sql .= " AND u.employee = 1"; // We only want employee users for holidays
1963 if ($sqlFilters) {
1964 $sql .= $sqlFilters;
1965 }
1966
1967 $resql = $this->db->query($sql);
1968
1969 // If no SQL error
1970 if ($resql) {
1971 $i = 0;
1972 $num = $this->db->num_rows($resql);
1973 $stringlist = '';
1974
1975 // User listing loops
1976 while ($i < $num) {
1977 $obj = $this->db->fetch_object($resql);
1978
1979 if ($i == 0) {
1980 $stringlist .= $obj->rowid;
1981 } else {
1982 $stringlist .= ', '.$obj->rowid;
1983 }
1984
1985 $i++;
1986 }
1987 // Returns the user table
1988 return $stringlist;
1989 } else {
1990 // SQL error
1991 $this->error = "Error ".$this->db->lasterror();
1992 return -1;
1993 }
1994 } else {
1995 // We want only list of vacation balance for user ids
1996 $sql = "SELECT DISTINCT cpu.fk_user";
1997 $sql .= " FROM ".MAIN_DB_PREFIX."holiday_users as cpu, ".MAIN_DB_PREFIX."user as u";
1998 $sql .= " WHERE cpu.fk_user = u.rowid";
1999 if ($sqlFilters) {
2000 $sql .= $sqlFilters;
2001 }
2002
2003 $resql = $this->db->query($sql);
2004
2005 // If no SQL error
2006 if ($resql) {
2007 $i = 0;
2008 $num = $this->db->num_rows($resql);
2009 $stringlist = '';
2010
2011 // User listing loops
2012 while ($i < $num) {
2013 $obj = $this->db->fetch_object($resql);
2014
2015 if ($i == 0) {
2016 $stringlist .= $obj->fk_user;
2017 } else {
2018 $stringlist .= ', '.$obj->fk_user;
2019 }
2020
2021 $i++;
2022 }
2023 // Returns the user table
2024 return $stringlist;
2025 } else {
2026 // SQL error
2027 $this->error = "Error ".$this->db->lasterror();
2028 return -1;
2029 }
2030 }
2031 } else {
2032 // If false, return array
2033 // List for Dolibarr users
2034 if ($type) {
2035 // If we need users of Dolibarr
2036 $sql = "SELECT";
2037 if (isModEnabled('multicompany') && getDolGlobalString('MULTICOMPANY_TRANSVERSE_MODE')) {
2038 $sql .= " DISTINCT";
2039 }
2040 $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";
2041 $sql .= " FROM ".MAIN_DB_PREFIX."user as u";
2042
2043 if (isModEnabled('multicompany') && getDolGlobalString('MULTICOMPANY_TRANSVERSE_MODE')) {
2044 $sql .= ", ".MAIN_DB_PREFIX."usergroup_user as ug";
2045 $sql .= " WHERE ((ug.fk_user = u.rowid";
2046 $sql .= " AND ug.entity IN (".getEntity('usergroup')."))";
2047 $sql .= " OR u.entity = 0)"; // Show always superadmin
2048 } else {
2049 $sql .= " WHERE u.entity IN (".getEntity('user').")";
2050 }
2051
2052 $sql .= " AND u.statut > 0";
2053 $sql .= " AND u.employee = 1"; // We only want employee users for holidays
2054 if ($sqlFilters) {
2055 $sql .= $sqlFilters;
2056 }
2057
2058 $resql = $this->db->query($sql);
2059
2060 // If no SQL error
2061 if ($resql) {
2062 $i = 0;
2063 $tab_result = $this->holiday;
2064 $num = $this->db->num_rows($resql);
2065
2066 // User listing loops
2067 while ($i < $num) {
2068 $obj = $this->db->fetch_object($resql);
2069
2070 $tab_result[$i]['rowid'] = (int) $obj->rowid; // rowid of user
2071 $tab_result[$i]['id'] = (int) $obj->rowid; // id of user
2072 $tab_result[$i]['name'] = $obj->lastname; // deprecated
2073 $tab_result[$i]['lastname'] = $obj->lastname;
2074 $tab_result[$i]['firstname'] = $obj->firstname;
2075 $tab_result[$i]['gender'] = $obj->gender;
2076 $tab_result[$i]['status'] = (int) $obj->status;
2077 $tab_result[$i]['employee'] = (int) $obj->employee;
2078 $tab_result[$i]['photo'] = $obj->photo;
2079 $tab_result[$i]['fk_user'] = (int) $obj->fk_user; // rowid of manager
2080 $tab_result[$i]['country_id'] = (int) $obj->country_id; // id of country of user
2081 //$tab_result[$i]['type'] = $obj->type;
2082 //$tab_result[$i]['nb_holiday'] = $obj->nb_holiday;
2083
2084 $i++;
2085 }
2086 // Returns the user table
2087 return $tab_result;
2088 } else {
2089 // SQL error
2090 $this->errors[] = "Error ".$this->db->lasterror();
2091 return -1;
2092 }
2093 } else {
2094 // List of vacation balance users
2095 $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";
2096 $sql .= " FROM ".MAIN_DB_PREFIX."holiday_users as cpu, ".MAIN_DB_PREFIX."user as u";
2097 $sql .= " WHERE cpu.fk_user = u.rowid";
2098 if ($sqlFilters) {
2099 $sql .= $sqlFilters;
2100 }
2101
2102 $resql = $this->db->query($sql);
2103
2104 // If no SQL error
2105 if ($resql) {
2106 $i = 0;
2107 $tab_result = $this->holiday;
2108 $num = $this->db->num_rows($resql);
2109
2110 // User listing loops
2111 while ($i < $num) {
2112 $obj = $this->db->fetch_object($resql);
2113
2114 $tab_result[$i]['rowid'] = $obj->rowid; // rowid of user
2115 $tab_result[$i]['id'] = $obj->rowid; // id of user
2116 $tab_result[$i]['name'] = $obj->lastname; // deprecated
2117 $tab_result[$i]['lastname'] = $obj->lastname;
2118 $tab_result[$i]['firstname'] = $obj->firstname;
2119 $tab_result[$i]['gender'] = $obj->gender;
2120 $tab_result[$i]['status'] = $obj->status;
2121 $tab_result[$i]['employee'] = $obj->employee;
2122 $tab_result[$i]['photo'] = $obj->photo;
2123 $tab_result[$i]['fk_user'] = $obj->fk_user; // rowid of manager
2124
2125 $tab_result[$i]['type'] = $obj->fk_type;
2126 $tab_result[$i]['nb_holiday'] = $obj->nb_holiday;
2127
2128 $i++;
2129 }
2130 // Returns the user table
2131 return $tab_result;
2132 } else {
2133 // SQL error
2134 $this->error = "Error ".$this->db->lasterror();
2135 return -1;
2136 }
2137 }
2138 }
2139 }
2140
2141
2142 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2150 {
2151 // phpcs:enable
2152 $users_validator = array();
2153
2154 $sql = "SELECT DISTINCT ur.fk_user";
2155 $sql .= " FROM ".MAIN_DB_PREFIX."user_rights as ur, ".MAIN_DB_PREFIX."rights_def as rd";
2156 $sql .= " WHERE ur.fk_id = rd.id and rd.module = 'holiday' AND rd.perms = 'approve'"; // Permission 'Approve';
2157 $sql .= "UNION";
2158 $sql .= " SELECT DISTINCT ugu.fk_user";
2159 $sql .= " FROM ".MAIN_DB_PREFIX."usergroup_user as ugu, ".MAIN_DB_PREFIX."usergroup_rights as ur, ".MAIN_DB_PREFIX."rights_def as rd";
2160 $sql .= " WHERE ugu.fk_usergroup = ur.fk_usergroup AND ur.fk_id = rd.id and rd.module = 'holiday' AND rd.perms = 'approve'"; // Permission 'Approve';
2161 //print $sql;
2162
2163 dol_syslog(get_class($this)."::fetch_users_approver_holiday sql=".$sql);
2164 $result = $this->db->query($sql);
2165 if ($result) {
2166 $num_rows = $this->db->num_rows($result);
2167 $i = 0;
2168 while ($i < $num_rows) {
2169 $objp = $this->db->fetch_object($result);
2170 array_push($users_validator, $objp->fk_user);
2171 $i++;
2172 }
2173 return $users_validator;
2174 } else {
2175 $this->error = $this->db->lasterror();
2176 dol_syslog(get_class($this)."::fetch_users_approver_holiday Error ".$this->error, LOG_ERR);
2177 return -1;
2178 }
2179 }
2180
2181
2187 public function countActiveUsers()
2188 {
2189 $sql = "SELECT count(u.rowid) as compteur";
2190 $sql .= " FROM ".MAIN_DB_PREFIX."user as u";
2191 $sql .= " WHERE u.statut > 0";
2192
2193 $result = $this->db->query($sql);
2194 $object = $this->db->fetch_object($result);
2195
2196 return $object->compteur;
2197 }
2204 {
2205 $sql = "SELECT count(u.rowid) as compteur";
2206 $sql .= " FROM ".MAIN_DB_PREFIX."user as u LEFT JOIN ".MAIN_DB_PREFIX."holiday_users hu ON (hu.fk_user=u.rowid)";
2207 $sql .= " WHERE u.statut > 0 AND hu.fk_user IS NULL";
2208
2209 $result = $this->db->query($sql);
2210 $object = $this->db->fetch_object($result);
2211
2212 return $object->compteur;
2213 }
2214
2222 public function verifNbUsers($userDolibarrWithoutCP, $userCP)
2223 {
2224 if (empty($userCP)) {
2225 $userCP = 0;
2226 }
2227 dol_syslog(get_class($this).'::verifNbUsers userDolibarr='.$userDolibarrWithoutCP.' userCP='.$userCP);
2228 return 1;
2229 }
2230
2231
2242 public function addLogCP($fk_user_action, $fk_user_update, $label, $new_solde, $fk_type)
2243 {
2244 $error = 0;
2245
2246 $prev_solde = price2num((float) $this->getCPforUser($fk_user_update, $fk_type), 5);
2247 $new_solde = price2num($new_solde, 5);
2248 //print "$prev_solde == $new_solde";
2249
2250 if ($prev_solde == $new_solde) {
2251 return 0;
2252 }
2253
2254 $this->db->begin();
2255
2256 // Insert request
2257 $sql = "INSERT INTO ".MAIN_DB_PREFIX."holiday_logs (";
2258 $sql .= "date_action,";
2259 $sql .= "fk_user_action,";
2260 $sql .= "fk_user_update,";
2261 $sql .= "type_action,";
2262 $sql .= "prev_solde,";
2263 $sql .= "new_solde,";
2264 $sql .= "fk_type";
2265 $sql .= ") VALUES (";
2266 $sql .= " '".$this->db->idate(dol_now())."',";
2267 $sql .= " ".((int) $fk_user_action).",";
2268 $sql .= " ".((int) $fk_user_update).",";
2269 $sql .= " '".$this->db->escape($label)."',";
2270 $sql .= " ".((float) $prev_solde).",";
2271 $sql .= " ".((float) $new_solde).",";
2272 $sql .= " ".((int) $fk_type);
2273 $sql .= ")";
2274
2275 $resql = $this->db->query($sql);
2276 if (!$resql) {
2277 $error++;
2278 $this->errors[] = "Error ".$this->db->lasterror();
2279 }
2280
2281 $optRowid = 0;
2282 if (!$error) {
2283 $optRowid = $this->db->last_insert_id(MAIN_DB_PREFIX."holiday_logs");
2284 }
2285
2286 // Commit or rollback
2287 if ($error) {
2288 foreach ($this->errors as $errmsg) {
2289 dol_syslog(get_class($this)."::addLogCP ".$errmsg, LOG_ERR);
2290 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
2291 }
2292 $this->db->rollback();
2293 return -1 * $error;
2294 } else {
2295 $this->db->commit();
2296 return $optRowid;
2297 }
2298 }
2299
2307 public function fetchLog($sqlorder, $sqlwhere)
2308 {
2309 $sql = "SELECT";
2310 $sql .= " cpl.rowid,";
2311 $sql .= " cpl.date_action,";
2312 $sql .= " cpl.fk_user_action,";
2313 $sql .= " cpl.fk_user_update,";
2314 $sql .= " cpl.type_action,";
2315 $sql .= " cpl.prev_solde,";
2316 $sql .= " cpl.new_solde,";
2317 $sql .= " cpl.fk_type";
2318 $sql .= " FROM ".MAIN_DB_PREFIX."holiday_logs as cpl";
2319 $sql .= " WHERE cpl.rowid > 0"; // To avoid error with other search and criteria
2320
2321 // Filter
2322 if (!empty($sqlwhere)) {
2323 $sql .= " ".$sqlwhere;
2324 }
2325
2326 // Order
2327 if (!empty($sqlorder)) {
2328 $sql .= " ".$sqlorder;
2329 }
2330
2331 dol_syslog(get_class($this)."::fetchLog", LOG_DEBUG);
2332 $resql = $this->db->query($sql);
2333
2334 // If no error SQL
2335 if ($resql) {
2336 $i = 0;
2337 $tab_result = $this->logs;
2338 $num = $this->db->num_rows($resql);
2339
2340 // If no record
2341 if (!$num) {
2342 return 2;
2343 }
2344
2345 // Loop on result to fill the array
2346 while ($i < $num) {
2347 $obj = $this->db->fetch_object($resql);
2348
2349 $tab_result[$i]['rowid'] = (int) $obj->rowid;
2350 $tab_result[$i]['id'] = (int) $obj->rowid;
2351 $tab_result[$i]['date_action'] = (string) $obj->date_action;
2352 $tab_result[$i]['fk_user_action'] = (int) $obj->fk_user_action;
2353 $tab_result[$i]['fk_user_update'] = (int) $obj->fk_user_update;
2354 $tab_result[$i]['type_action'] = (string) $obj->type_action;
2355 $tab_result[$i]['prev_solde'] = (float) $obj->prev_solde;
2356 $tab_result[$i]['new_solde'] = (float) $obj->new_solde;
2357 $tab_result[$i]['fk_type'] = (int) $obj->fk_type;
2358
2359 $i++;
2360 }
2361 // Returns 1 and adds the array to the variable
2362 $this->logs = $tab_result;
2363 return 1;
2364 } else {
2365 // SQL error
2366 $this->error = "Error ".$this->db->lasterror();
2367 return -1;
2368 }
2369 }
2370
2371
2379 public function getTypes($active = -1, $affect = -1)
2380 {
2381 global $mysoc;
2382
2383 $sql = "SELECT rowid, code, label, affect, delay, newbymonth";
2384 $sql .= " FROM ".MAIN_DB_PREFIX."c_holiday_types";
2385 $sql .= " WHERE (fk_country IS NULL OR fk_country = ".((int) $mysoc->country_id).')';
2386 $sql .= " AND entity IN (0, ".getEntity('c_holiday_types').")"; // Need entity 0 (holiday types common to all countries= + current entity).
2387 if ($active >= 0) {
2388 $sql .= " AND active = ".((int) $active);
2389 }
2390 if ($affect >= 0) {
2391 $sql .= " AND affect = ".((int) $affect);
2392 }
2393 $sql .= " ORDER BY sortorder";
2394
2395 $result = $this->db->query($sql);
2396 if ($result) {
2397 $num = $this->db->num_rows($result);
2398 if ($num) {
2399 $types = array();
2400 while ($obj = $this->db->fetch_object($result)) {
2401 $types[$obj->rowid] = array(
2402 'id' => $obj->rowid,
2403 'rowid' => $obj->rowid,
2404 'code' => $obj->code,
2405 'label' => $obj->label,
2406 'affect' => $obj->affect,
2407 'delay' => $obj->delay,
2408 'newbymonth' => $obj->newbymonth
2409 );
2410 }
2411
2412 return $types;
2413 }
2414 } else {
2415 dol_print_error($this->db);
2416 }
2417
2418 return array();
2419 }
2420
2421
2428 public function info($id)
2429 {
2430 global $conf;
2431
2432 $sql = "SELECT f.rowid, f.statut as status,";
2433 $sql .= " f.date_create as datec,";
2434 $sql .= " f.tms as date_modification,";
2435 $sql .= " f.date_valid as datev,";
2436 $sql .= " f.date_approval as datea,";
2437 $sql .= " f.date_refuse as dater,";
2438 $sql .= " f.fk_user_create as fk_user_creation,";
2439 $sql .= " f.fk_user_modif as fk_user_modification,";
2440 $sql .= " f.fk_user_valid as fk_user_validation,";
2441 $sql .= " f.fk_user_approve as fk_user_approval_done,";
2442 $sql .= " f.fk_validator as fk_user_approval_expected,";
2443 $sql .= " f.fk_user_refuse as fk_user_refuse";
2444 $sql .= " FROM ".MAIN_DB_PREFIX."holiday as f";
2445 $sql .= " WHERE f.rowid = ".((int) $id);
2446 $sql .= " AND f.entity = ".((int) $conf->entity);
2447
2448 $resql = $this->db->query($sql);
2449 if ($resql) {
2450 if ($this->db->num_rows($resql)) {
2451 $obj = $this->db->fetch_object($resql);
2452
2453 $this->id = $obj->rowid;
2454
2455 $this->date_creation = $this->db->jdate($obj->datec);
2456 $this->date_modification = $this->db->jdate($obj->date_modification);
2457 $this->date_validation = $this->db->jdate($obj->datev);
2458 $this->date_approval = $this->db->jdate($obj->datea);
2459
2460 $this->user_creation_id = $obj->fk_user_creation;
2461 $this->user_validation_id = $obj->fk_user_validation;
2462 $this->user_modification_id = $obj->fk_user_modification;
2463
2464 if ($obj->status == Holiday::STATUS_APPROVED || $obj->status == Holiday::STATUS_CANCELED) {
2465 if ($obj->fk_user_approval_done) {
2466 $this->fk_user_approve = $obj->fk_user_approval_done;
2467 }
2468 }
2469 }
2470 $this->db->free($resql);
2471 } else {
2472 dol_print_error($this->db);
2473 }
2474 }
2475
2476
2484 public function initAsSpecimen()
2485 {
2486 global $user, $langs;
2487
2488 // Initialise parameters
2489 $this->id = 0;
2490 $this->specimen = 1;
2491
2492 $this->fk_user = $user->id;
2493 $this->description = 'SPECIMEN description';
2494 $this->date_debut = dol_now();
2495 $this->date_fin = dol_now() + (24 * 3600);
2496 $this->date_valid = dol_now();
2497 $this->fk_validator = $user->id;
2498 $this->halfday = 0;
2499 $this->fk_type = 1;
2501
2502 return 1;
2503 }
2504
2510 public function loadStateBoard()
2511 {
2512 global $user;
2513
2514 $this->nb = array();
2515
2516 $sql = "SELECT count(h.rowid) as nb";
2517 $sql .= " FROM ".MAIN_DB_PREFIX."holiday as h";
2518 $sql .= " WHERE h.statut > 1";
2519 $sql .= " AND h.entity IN (".getEntity('holiday').")";
2520 if (!$user->hasRight('holiday', 'readall')) {
2521 $userchildids = $user->getAllChildIds(1);
2522 $sql .= " AND (h.fk_user IN (".$this->db->sanitize(implode(',', $userchildids)).")";
2523 $sql .= " OR h.fk_validator IN (".$this->db->sanitize(implode(',', $userchildids))."))";
2524 }
2525
2526 $resql = $this->db->query($sql);
2527 if ($resql) {
2528 while ($obj = $this->db->fetch_object($resql)) {
2529 $this->nb["holidays"] = $obj->nb;
2530 }
2531 $this->db->free($resql);
2532 return 1;
2533 } else {
2534 dol_print_error($this->db);
2535 $this->error = $this->db->error();
2536 return -1;
2537 }
2538 }
2539
2540 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2547 public function load_board($user)
2548 {
2549 // phpcs:enable
2550 global $conf, $langs;
2551
2552 if ($user->socid) {
2553 return -1; // Protection to prevent calls by external users
2554 }
2555
2556 $now = dol_now();
2557
2558 $sql = "SELECT h.rowid, h.date_debut";
2559 $sql .= " FROM ".MAIN_DB_PREFIX."holiday as h";
2560 $sql .= " WHERE h.statut = 2";
2561 $sql .= " AND h.entity IN (".getEntity('holiday').")";
2562 if (!$user->hasRight('holiday', 'read_all')) {
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 $langs->load("members");
2571
2572 $response = new WorkboardResponse();
2573 $response->warning_delay = $conf->holiday->approve->warning_delay / 60 / 60 / 24;
2574 $response->label = $langs->trans("HolidaysToApprove");
2575 $response->labelShort = $langs->trans("ToApprove");
2576 $response->url = DOL_URL_ROOT.'/holiday/list.php?search_status=2&amp;mainmenu=hrm&amp;leftmenu=holiday';
2577 $response->img = img_object('', "holiday");
2578
2579 while ($obj = $this->db->fetch_object($resql)) {
2580 $response->nbtodo++;
2581
2582 if ($this->db->jdate($obj->date_debut) < ($now - $conf->holiday->approve->warning_delay)) {
2583 $response->nbtodolate++;
2584 }
2585 }
2586
2587 return $response;
2588 } else {
2589 dol_print_error($this->db);
2590 $this->error = $this->db->error();
2591 return -1;
2592 }
2593 }
2601 public function getKanbanView($option = '', $arraydata = null)
2602 {
2603 global $langs;
2604
2605 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
2606
2607 $return = '<div class="box-flex-item box-flex-grow-zero">';
2608 $return .= '<div class="info-box info-box-sm">';
2609 $return .= '<span class="info-box-icon bg-infobox-action">';
2610 $return .= img_picto('', $this->picto);
2611 $return .= '</span>';
2612 $return .= '<div class="info-box-content">';
2613 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.$this->getNomUrl().'</span>';
2614 if ($selected >= 0) {
2615 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
2616 }
2617 if (property_exists($this, 'fk_type')) {
2618 $return .= '<br>';
2619 //$return .= '<span class="opacitymedium">'.$langs->trans("Type").'</span> : ';
2620 $return .= '<div class="info_box-label tdoverflowmax100" title="'.dol_escape_htmltag($arraydata['labeltype']).'">'.dol_escape_htmltag($arraydata['labeltype']).'</div>';
2621 }
2622 if (property_exists($this, 'date_debut') && property_exists($this, 'date_fin')) {
2623 $return .= '<span class="info-box-label small">'.dol_print_date($this->date_debut, 'day').'</span>';
2624 $return .= ' <span class="opacitymedium small">'.$langs->trans("To").'</span> ';
2625 $return .= '<span class="info-box-label small">'.dol_print_date($this->date_fin, 'day').'</span>';
2626 if (!empty($arraydata['nbopenedday'])) {
2627 $return .= ' ('.$arraydata['nbopenedday'].')';
2628 }
2629 }
2630 if (method_exists($this, 'getLibStatut')) {
2631 $return .= '<div class="info-box-status">'.$this->getLibStatut(3).'</div>';
2632 }
2633 $return .= '</div>';
2634 $return .= '</div>';
2635 $return .= '</div>';
2636 return $return;
2637 }
2638
2649 public function sendPreviousMonthHRInformations($mailto = "", $template = "", $newlang = "")
2650 {
2651 global $conf, $langs, $user;
2652
2653 $outputlangs = $langs;
2654
2655 $error = 0;
2656 $this->output = '';
2657 $this->error = '';
2658 $arrayfields = array(
2659 'user' => 'Employee',
2660 'type' => 'Type',
2661 'date_start' => 'DateDebCP',
2662 'date_end' => 'DateFinCP',
2663 'used_days' => 'NbUseDaysCPShort',
2664 );
2665
2666 if (!empty($newlang)) {
2667 $outputlangs = new Translate("", $conf);
2668 $outputlangs->setDefaultLang($newlang);
2669 }
2670 $outputlangs->loadLangs(array('main', 'holiday', 'hrm'));
2671
2672 if (empty($mailto) || !isValidEmail($mailto)) {
2673 $this->errors[] = 'Bad value for parameter mailto. Must be a valid email address.';
2674 return 1;
2675 }
2676
2677 $typeleaves = $this->getTypes(1, -1);
2678 $arraytypeleaves = array();
2679 foreach ($typeleaves as $val) {
2680 $labeltoshow = ($outputlangs->trans($val['code']) != $val['code'] ? $outputlangs->trans($val['code']) : $val['label']);
2681 $arraytypeleaves[$val['rowid']] = $labeltoshow;
2682 }
2683 $listhalfday = array('morning' => $outputlangs->trans("Morning"), "afternoon" => $outputlangs->trans("Afternoon"));
2684
2685 $datenow = dol_getdate(dol_now());
2686 $prev_month = dol_get_prev_month($datenow["mon"], $datenow["year"]);
2687 $year_month = sprintf("%04d", $prev_month["year"]).'-'.sprintf("%02d", $prev_month["month"]);
2688 $arrayleaves = array();
2689
2690 $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";
2691 $sql .= " FROM ".MAIN_DB_PREFIX."holiday cp";
2692 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user u ON cp.fk_user = u.rowid";
2693 $sql .= " WHERE cp.entity IN (".getEntity('holiday').") AND cp.rowid > 0";
2694 $sql .= " AND cp.statut = ".Holiday::STATUS_APPROVED;
2695 $sql .= " AND (";
2696 $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)."')";
2697 $sql .= " OR"; // For leave over several months
2698 $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)."') ";
2699 $sql .= " )";
2700 $sql .= $this->db->order("cp.fk_user, cp.date_debut", "ASC");
2701 $resql = $this->db->query($sql);
2702 if (empty($resql)) {
2703 $this->errors[] = $this->db->lasterror();
2704 return 1;
2705 }
2706 $num = $this->db->num_rows($resql);
2707 if ($num > 0) {
2708 $tmpuser = new User($this->db);
2709 while ($obj = $this->db->fetch_object($resql)) {
2710 $tmpuser->fetch($obj->fk_user);
2711
2712 $date_start = $this->db->jdate($obj->date_debut, true);
2713 $date_end = $this->db->jdate($obj->date_fin, true);
2714
2715 $tmpstart = dol_getdate($date_start);
2716 $tmpend = dol_getdate($date_end);
2717
2718 $starthalfday = ($obj->halfday == -1 || $obj->halfday == 2) ? 'afternoon' : 'morning';
2719 $endhalfday = ($obj->halfday == 1 || $obj->halfday == 2) ? 'morning' : 'afternoon';
2720
2721 $halfdayinmonth = $obj->halfday;
2722 $starthalfdayinmonth = $starthalfday;
2723 $endhalfdayinmonth = $endhalfday;
2724
2725 //0:Full days, 2:Start afternoon end morning, -1:Start afternoon end afternoon, 1:Start morning end morning
2726
2727 // Set date_start_gmt and date_end_gmt that are date to show for the selected month
2728 $date_start_inmonth = $this->db->jdate($obj->date_debut, true);
2729 $date_end_inmonth = $this->db->jdate($obj->date_fin, true);
2730 if ($tmpstart['year'] < $prev_month["year"] || $tmpstart['mon'] < $prev_month["month"]) {
2731 $date_start_inmonth = dol_get_first_day($prev_month["year"], $prev_month["month"], true);
2732 $starthalfdayinmonth = 'morning';
2733 if ($halfdayinmonth == 2) {
2734 $halfdayinmonth = 1;
2735 }
2736 if ($halfdayinmonth == -1) {
2737 $halfdayinmonth = 0;
2738 }
2739 }
2740 if ($tmpend['year'] > $prev_month["year"] || $tmpend['mon'] > $prev_month["month"]) {
2741 $date_end_inmonth = dol_get_last_day($prev_month["year"], $prev_month["month"], true) - ((24 * 3600) - 1);
2742 $endhalfdayinmonth = 'afternoon';
2743 if ($halfdayinmonth == 2) {
2744 $halfdayinmonth = -1;
2745 }
2746 if ($halfdayinmonth == 1) {
2747 $halfdayinmonth = 0;
2748 }
2749 }
2750 $arrayleaves[] = array(
2751 "user" => $tmpuser->getNomUrl(0, 'nolink', 0, 0, 24, 1),
2752 "type" => $arraytypeleaves[$obj->fk_type],
2753 "date_start" => dol_print_date($date_start_inmonth, 'day') . ' <span class="opacitymedium">('.$outputlangs->trans($listhalfday[$starthalfdayinmonth]).')</span>',
2754 "date_end" => dol_print_date($date_end_inmonth, 'day') . ' <span class="opacitymedium">('.$outputlangs->trans($listhalfday[$endhalfdayinmonth]).')</span>',
2755 "used_days" => num_open_day($date_start_inmonth, $date_end_inmonth, 0, 1, $halfdayinmonth, $tmpuser->country_id, $obj->fk_user)
2756 );
2757 }
2758 }
2759
2760 $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;">';
2761 $outputarrayleaves .= '<tr>';
2762 foreach ($arrayfields as $key => $label) {
2763 $outputarrayleaves .= '<td style="border-bottom:1px solid #b6b6b6;padding: 6px 10px 6px 12px;">';
2764 $outputarrayleaves .= $outputlangs->trans($label);
2765 $outputarrayleaves .= '</td>';
2766 }
2767 $outputarrayleaves .= '</tr>';
2768
2769 if (!empty($arrayleaves)) {
2770 foreach ($arrayleaves as $key => $fields) {
2771 $outputarrayleaves .= '<tr>';
2772 foreach ($fields as $field => $value) {
2773 $outputarrayleaves .= '<td style="border-bottom:1px solid #b6b6b6;padding: 6px 10px 6px 12px;" id="'.$field.'">';
2774 $outputarrayleaves .= $value;
2775 $outputarrayleaves .= '</td>';
2776 }
2777 $outputarrayleaves .= '</tr>';
2778 }
2779 } else {
2780 $outputarrayleaves .= '<tr>';
2781 $outputarrayleaves .= '<td style="border-bottom:1px solid #b6b6b6;padding: 6px 10px 6px 12px;" colspan="5">';
2782 $outputarrayleaves .= $outputlangs->trans("None");
2783 $outputarrayleaves .= '</td>';
2784 $outputarrayleaves .= '</tr>';
2785 }
2786 $outputarrayleaves .= '</table>';
2787
2788 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
2789 include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
2790
2791 $formmail = new FormMail($this->db);
2792 $templateId = 0;
2793 $templateLabel = '';
2794 if (empty($template) || $template == 'EmailTemplateCode') {
2795 $templateLabel = '(HolidayHrInformationsPreviousMonth)';
2796 } else {
2797 if (is_numeric($template)) {
2798 $templateId = $template;
2799 } else {
2800 $templateLabel = $template;
2801 }
2802 }
2803 $mailtemplate = $formmail->getEMailTemplate($this->db, "holiday", $user, $outputlangs, $templateId, 1, $templateLabel);
2804
2805 if (is_numeric($mailtemplate) || empty($mailtemplate->topic)) {
2806 $this->errors[] = 'No mail template found for code "'.$templateLabel.'" or id "'.$templateId.'".';
2807 $error++;
2808 }
2809
2810 if (!$error) {
2811 $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $this);
2812 complete_substitutions_array($substitutionarray, $outputlangs, $this);
2813
2814 $subject = make_substitutions($mailtemplate->topic, $substitutionarray, $outputlangs);
2815 $msg = make_substitutions($mailtemplate->content, $substitutionarray, $outputlangs);
2816 $from = dol_string_nospecial(getDolGlobalString('MAIN_INFO_SOCIETE_NOM'), ' ', array(",")).' <' . getDolGlobalString('MAIN_INFO_SOCIETE_MAIL').'>';
2817
2818 $msg = preg_replace('/__HOLIDAY_ARRAY_PER_EMPLOYEE_FOR_PERIOD__/', $outputarrayleaves, $msg);
2819 $cmail = new CMailFile($subject, $mailto, $from, $msg, array(), array(), array(), '', '', 0, 1);
2820 $result = $cmail->sendfile();
2821 if (!$result || !empty($cmail->error) || !empty($cmail->errors)) {
2822 $this->errors[] = $cmail->error;
2823 if (is_array($cmail->errors) && count($cmail->errors) > 0) {
2824 $this->errors = array_merge($this->errors, $cmail->errors);
2825 $error++;
2826 }
2827 }
2828 }
2829
2830 if (!empty($this->errors)) {
2831 $this->output .= "\n";
2832 // The $this->errors will be concatenated to the output by the function that call this method.
2833 }
2834 return ($error ? 1 : 0);
2835 }
2836}
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,...
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this->array_options This method is in most cases call...
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
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:524
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:605
dol_get_next_month($month, $year)
Return next month.
Definition date.lib.php:543
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:436
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition date.lib.php:624
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:65
$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...
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.
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...
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).
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.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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...
Definition html.lib.php:172
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