Passed
Push — EXTRACT_CLASSES ( c25e41...9f3ede )
by Rafael
55:18
created

Holiday::approve()   F

Complexity

Conditions 24
Paths > 20000

Size

Total Lines 117
Code Lines 83

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 24
eloc 83
nc 524289
nop 2
dl 0
loc 117
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/* Copyright (C) 2011       Dimitri Mouillard           <[email protected]>
4
 * Copyright (C) 2012-2014	Laurent Destailleur	        <[email protected]>
5
 * Copyright (C) 2012-2016	Regis Houssin		        <[email protected]>
6
 * Copyright (C) 2013		Florian Henry		        <[email protected]>
7
 * Copyright (C) 2016       Juanjo Menent               <[email protected]>
8
 * Copyright (C) 2018-2024  Frédéric France             <[email protected]>
9
 * Copyright (C) 2024		MDW							<[email protected]>
10
 * Copyright (C) 2024       Rafael San José             <[email protected]>
11
 *
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 3 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
24
 */
25
26
namespace Dolibarr\Code\Holiday\Classes;
27
28
use Dolibarr\Core\Base\CommonObject;
29
30
/**
31
 *    \file       holiday.class.php
32
 *    \ingroup    holiday
33
 *    \brief      Class file of the module paid holiday.
34
 */
35
36
/**
37
 *  Class of the module paid holiday. Developed by Teclib ( http://www.teclib.com/ )
38
 */
39
class Holiday extends CommonObject
40
{
41
    /**
42
     * @var string ID to identify managed object
43
     */
44
    public $element = 'holiday';
45
46
    /**
47
     * @var string Name of table without prefix where object is stored
48
     */
49
    public $table_element = 'holiday';
50
51
    /**
52
     * @var string Field with ID of parent key if this field has a parent
53
     */
54
    public $fk_element = 'fk_holiday';
55
56
    /**
57
     * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
58
     */
59
    public $picto = 'holiday';
60
61
    /**
62
     * @var int User ID
63
     */
64
    public $fk_user;
65
66
    public $date_create = '';
67
68
    /**
69
     * @var string description
70
     */
71
    public $description;
72
73
    /**
74
     * @var int|string Date start in PHP server TZ
75
     */
76
    public $date_debut = '';
77
78
    /**
79
     * @var int|string Date end in PHP server TZ
80
     */
81
    public $date_fin = '';
82
83
    /**
84
     * @var int|string Date start in GMT
85
     */
86
    public $date_debut_gmt = '';
87
88
    /**
89
     * @var int|string Date end in GMT
90
     */
91
    public $date_fin_gmt = '';
92
93
    /**
94
     * @var int|string 0:Full days, 2:Start afternoon end morning, -1:Start afternoon end afternoon, 1:Start morning end morning
95
     */
96
    public $halfday = '';
97
98
    /**
99
     * @var int Status 1=draft, 2=validated, 3=approved, 4 canceled, 5 refused
100
     * @deprecated
101
     */
102
    public $statut = 0;
103
104
    /**
105
     * @var int     ID of user that must approve. Real user for approval is fk_user_valid (old version) or fk_user_approve (new versions)
106
     */
107
    public $fk_validator;
108
109
    /**
110
     * @var int     Date of validation or approval. TODO: Use date_valid instead for validation.
111
     */
112
    public $date_valid = 0;
113
114
    /**
115
     * @var int     ID of user that has validated
116
     */
117
    public $fk_user_valid;
118
119
    /**
120
     * @var int     Date approval
121
     */
122
    public $date_approval;
123
124
    /**
125
     * @var int     ID of user that has approved
126
     */
127
    public $fk_user_approve;
128
129
    /**
130
     * @var int     Date for refuse
131
     */
132
    public $date_refuse = 0;
133
134
    /**
135
     * @var int     ID for refuse
136
     */
137
    public $fk_user_refuse;
138
139
    /**
140
     * @var int     Date for cancellation
141
     */
142
    public $date_cancel = 0;
143
144
    /**
145
     * @var int     ID for cancellation
146
     */
147
    public $fk_user_cancel;
148
149
    /**
150
     * @var int     ID for creation
151
     */
152
    public $fk_user_create;
153
154
    /**
155
     * @var string Detail of refuse
156
     */
157
    public $detail_refuse = '';
158
159
    /**
160
     * @var int ID
161
     */
162
    public $fk_type;
163
164
    public $holiday = array();
165
    public $events = array();
166
    public $logs = array();
167
168
    public $optName = '';
169
    public $optValue = '';
170
    public $optRowid = '';
171
172
    /**
173
     * Draft status
174
     */
175
    const STATUS_DRAFT = 1;
176
    /**
177
     * Validated status
178
     */
179
    const STATUS_VALIDATED = 2;
180
    /**
181
     * Approved
182
     */
183
    const STATUS_APPROVED = 3;
184
    /**
185
     * Canceled
186
     */
187
    const STATUS_CANCELED = 4;
188
    /**
189
     * Refused
190
     */
191
    const STATUS_REFUSED = 5;
192
193
194
    /**
195
     *   Constructor
196
     *
197
     *   @param     DoliDB      $db      Database handler
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Holiday\Classes\DoliDB was not found. Did you mean DoliDB? If so, make sure to prefix the type with \.
Loading history...
198
     */
199
    public function __construct($db)
200
    {
201
        $this->db = $db;
202
203
        $this->ismultientitymanaged = 0;
204
    }
205
206
207
    /**
208
     *  Returns the reference to the following non used Order depending on the active numbering module
209
     *  defined into HOLIDAY_ADDON
210
     *
211
     *  @param  Societe     $objsoc     third party object
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Holiday\Classes\Societe was not found. Did you mean Societe? If so, make sure to prefix the type with \.
Loading history...
212
     *  @return string                  Holiday free reference
213
     */
214
    public function getNextNumRef($objsoc)
215
    {
216
        global $langs, $conf;
217
        $langs->load("order");
218
219
        if (!getDolGlobalString('HOLIDAY_ADDON')) {
220
            $conf->global->HOLIDAY_ADDON = 'mod_holiday_madonna';
221
        }
222
223
        if (getDolGlobalString('HOLIDAY_ADDON')) {
224
            $mybool = false;
225
226
            $file = getDolGlobalString('HOLIDAY_ADDON') . ".php";
227
            $classname = getDolGlobalString('HOLIDAY_ADDON');
228
229
            // Include file with class
230
            $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
231
            foreach ($dirmodels as $reldir) {
232
                $dir = dol_buildpath($reldir . "core/modules/holiday/");
233
234
                // Load file with numbering class (if found)
235
                $mybool = ((bool) @include_once $dir . $file) || $mybool;
236
            }
237
238
            if ($mybool === false) {
239
                dol_print_error(null, "Failed to include file " . $file);
240
                return '';
241
            }
242
243
            $obj = new $classname();
244
            $numref = $obj->getNextValue($objsoc, $this);
245
246
            if ($numref != "") {
247
                return $numref;
248
            } else {
249
                $this->error = $obj->error;
250
                //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
251
                return "";
252
            }
253
        } else {
254
            print $langs->trans("Error") . " " . $langs->trans("Error_HOLIDAY_ADDON_NotDefined");
255
            return "";
256
        }
257
    }
258
259
    /**
260
     * Update balance of vacations and check table of users for holidays is complete. If not complete.
261
     *
262
     * @return  int         Return integer <0 if KO, >0 if OK
263
     */
264
    public function updateBalance()
265
    {
266
        $this->db->begin();
267
268
        // Update sold of vocations
269
        $result = $this->updateSoldeCP();
270
271
        // Check nb of users into table llx_holiday_users and update with empty lines
272
        //if ($result > 0) $result = $this->verifNbUsers($this->countActiveUsersWithoutCP(), $this->getConfCP('nbUser'));
273
274
        if ($result >= 0) {
275
            $this->db->commit();
276
            return 0; // for cronjob use (0 is OK, any other value is an error code)
277
        } else {
278
            $this->db->rollback();
279
            return -1;
280
        }
281
    }
282
283
    /**
284
     *   Créer un congés payés dans la base de données
285
     *
286
     *   @param     User    $user           User that create
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Holiday\Classes\User was not found. Did you mean User? If so, make sure to prefix the type with \.
Loading history...
287
     *   @param     int     $notrigger      0=launch triggers after, 1=disable triggers
288
     *   @return    int                     Return integer <0 if KO, Id of created object if OK
289
     */
290
    public function create($user, $notrigger = 0)
291
    {
292
        global $conf;
293
        $error = 0;
294
295
        $now = dol_now();
296
297
        // Check parameters
298
        if (empty($this->fk_user) || !is_numeric($this->fk_user) || $this->fk_user < 0) {
299
            $this->error = "ErrorBadParameterFkUser";
300
            return -1;
301
        }
302
        if (empty($this->fk_validator) || !is_numeric($this->fk_validator) || $this->fk_validator < 0) {
303
            $this->error = "ErrorBadParameterFkValidator";
304
            return -1;
305
        }
306
        if (empty($this->fk_type) || !is_numeric($this->fk_type) || $this->fk_type < 0) {
307
            $this->error = "ErrorBadParameterFkType";
308
            return -1;
309
        }
310
311
        // Insert request
312
        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "holiday(";
313
        $sql .= "ref,";
314
        $sql .= "fk_user,";
315
        $sql .= "date_create,";
316
        $sql .= "description,";
317
        $sql .= "date_debut,";
318
        $sql .= "date_fin,";
319
        $sql .= "halfday,";
320
        $sql .= "statut,";
321
        $sql .= "fk_validator,";
322
        $sql .= "fk_type,";
323
        $sql .= "fk_user_create,";
324
        $sql .= "entity";
325
        $sql .= ") VALUES (";
326
        $sql .= "'(PROV)',";
327
        $sql .= " " . ((int) $this->fk_user) . ",";
328
        $sql .= " '" . $this->db->idate($now) . "',";
329
        $sql .= " '" . $this->db->escape($this->description) . "',";
330
        $sql .= " '" . $this->db->idate($this->date_debut) . "',";
331
        $sql .= " '" . $this->db->idate($this->date_fin) . "',";
332
        $sql .= " " . ((int) $this->halfday) . ",";
333
        $sql .= " '1',";
334
        $sql .= " " . ((int) $this->fk_validator) . ",";
335
        $sql .= " " . ((int) $this->fk_type) . ",";
336
        $sql .= " " . ((int) $user->id) . ",";
337
        $sql .= " " . ((int) $conf->entity);
338
        $sql .= ")";
339
340
        $this->db->begin();
341
342
        dol_syslog(get_class($this) . "::create", LOG_DEBUG);
343
        $resql = $this->db->query($sql);
344
        if (!$resql) {
345
            $error++;
346
            $this->errors[] = "Error " . $this->db->lasterror();
347
        }
348
349
        if (!$error) {
350
            $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . "holiday");
351
352
            if ($this->id) {
353
                // update ref
354
                $initialref = '(PROV' . $this->id . ')';
355
                if (!empty($this->ref)) {
356
                    $initialref = $this->ref;
357
                }
358
359
                $sql = 'UPDATE ' . MAIN_DB_PREFIX . "holiday SET ref='" . $this->db->escape($initialref) . "' WHERE rowid=" . ((int) $this->id);
360
                if ($this->db->query($sql)) {
361
                    $this->ref = $initialref;
362
363
                    if (!$error) {
364
                        $result = $this->insertExtraFields();
365
                        if ($result < 0) {
366
                            $error++;
367
                        }
368
                    }
369
370
                    if (!$error && !$notrigger) {
371
                        // Call trigger
372
                        $result = $this->call_trigger('HOLIDAY_CREATE', $user);
373
                        if ($result < 0) {
374
                            $error++;
375
                        }
376
                        // End call triggers
377
                    }
378
                }
379
            }
380
        }
381
382
        // Commit or rollback
383
        if ($error) {
384
            foreach ($this->errors as $errmsg) {
385
                dol_syslog(get_class($this) . "::create " . $errmsg, LOG_ERR);
386
                $this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
387
            }
388
            $this->db->rollback();
389
            return -1 * $error;
390
        } else {
391
            $this->db->commit();
392
            return $this->id;
393
        }
394
    }
395
396
397
    /**
398
     *  Load object in memory from database
399
     *
400
     *  @param  int     $id         Id object
401
     *  @param  string  $ref        Ref object
402
     *  @return int                 Return integer <0 if KO, 0 if not found, >0 if OK
403
     */
404
    public function fetch($id, $ref = '')
405
    {
406
        $sql = "SELECT";
407
        $sql .= " cp.rowid,";
408
        $sql .= " cp.ref,";
409
        $sql .= " cp.fk_user,";
410
        $sql .= " cp.date_create,";
411
        $sql .= " cp.description,";
412
        $sql .= " cp.date_debut,";
413
        $sql .= " cp.date_fin,";
414
        $sql .= " cp.halfday,";
415
        $sql .= " cp.statut as status,";
416
        $sql .= " cp.fk_validator,";
417
        $sql .= " cp.date_valid,";
418
        $sql .= " cp.fk_user_valid,";
419
        $sql .= " cp.date_approval,";
420
        $sql .= " cp.fk_user_approve,";
421
        $sql .= " cp.date_refuse,";
422
        $sql .= " cp.fk_user_refuse,";
423
        $sql .= " cp.date_cancel,";
424
        $sql .= " cp.fk_user_cancel,";
425
        $sql .= " cp.detail_refuse,";
426
        $sql .= " cp.note_private,";
427
        $sql .= " cp.note_public,";
428
        $sql .= " cp.fk_user_create,";
429
        $sql .= " cp.fk_type,";
430
        $sql .= " cp.entity";
431
        $sql .= " FROM " . MAIN_DB_PREFIX . "holiday as cp";
432
        if ($id > 0) {
433
            $sql .= " WHERE cp.rowid = " . ((int) $id);
434
        } else {
435
            $sql .= " WHERE cp.ref = '" . $this->db->escape($ref) . "'";
436
        }
437
438
        dol_syslog(get_class($this) . "::fetch", LOG_DEBUG);
439
        $resql = $this->db->query($sql);
440
        if ($resql) {
441
            if ($this->db->num_rows($resql)) {
442
                $obj = $this->db->fetch_object($resql);
443
444
                $this->id    = $obj->rowid;
445
                $this->ref   = ($obj->ref ? $obj->ref : $obj->rowid);
446
                $this->fk_user = $obj->fk_user;
447
                $this->date_create = $this->db->jdate($obj->date_create);
448
                $this->description = $obj->description;
449
                $this->date_debut = $this->db->jdate($obj->date_debut);
450
                $this->date_fin = $this->db->jdate($obj->date_fin);
451
                $this->date_debut_gmt = $this->db->jdate($obj->date_debut, 1);
452
                $this->date_fin_gmt = $this->db->jdate($obj->date_fin, 1);
453
                $this->halfday = $obj->halfday;
454
                $this->status = $obj->status;
455
                $this->statut = $obj->status;   // deprecated
456
                $this->fk_validator = $obj->fk_validator;
457
                $this->date_valid = $this->db->jdate($obj->date_valid);
458
                $this->fk_user_valid = $obj->fk_user_valid;
459
                $this->user_validation_id = $obj->fk_user_valid;
460
                $this->date_approval = $this->db->jdate($obj->date_approval);
461
                $this->fk_user_approve = $obj->fk_user_approve;
462
                $this->date_refuse = $this->db->jdate($obj->date_refuse);
463
                $this->fk_user_refuse = $obj->fk_user_refuse;
464
                $this->date_cancel = $this->db->jdate($obj->date_cancel);
465
                $this->fk_user_cancel = $obj->fk_user_cancel;
466
                $this->detail_refuse = $obj->detail_refuse;
467
                $this->note_private = $obj->note_private;
468
                $this->note_public = $obj->note_public;
469
                $this->fk_user_create = $obj->fk_user_create;
470
                $this->fk_type = $obj->fk_type;
471
                $this->entity = $obj->entity;
472
473
                $this->fetch_optionals();
474
475
                $result = 1;
476
            } else {
477
                $result = 0;
478
            }
479
            $this->db->free($resql);
480
481
            return $result;
482
        } else {
483
            $this->error = "Error " . $this->db->lasterror();
484
            return -1;
485
        }
486
    }
487
488
    /**
489
     *  List holidays for a particular user or list of users
490
     *
491
     *  @param      int|string      $user_id    ID of user to list, or comma separated list of IDs of users to list
492
     *  @param      string          $order      Sort order
493
     *  @param      string          $filter     SQL Filter
494
     *  @return     int                         -1 if KO, 1 if OK, 2 if no result
495
     */
496
    public function fetchByUser($user_id, $order = '', $filter = '')
497
    {
498
        $sql = "SELECT";
499
        $sql .= " cp.rowid,";
500
        $sql .= " cp.ref,";
501
502
        $sql .= " cp.fk_user,";
503
        $sql .= " cp.fk_type,";
504
        $sql .= " cp.date_create,";
505
        $sql .= " cp.description,";
506
        $sql .= " cp.date_debut,";
507
        $sql .= " cp.date_fin,";
508
        $sql .= " cp.halfday,";
509
        $sql .= " cp.statut as status,";
510
        $sql .= " cp.fk_validator,";
511
        $sql .= " cp.date_valid,";
512
        $sql .= " cp.fk_user_valid,";
513
        $sql .= " cp.date_approval,";
514
        $sql .= " cp.fk_user_approve,";
515
        $sql .= " cp.date_refuse,";
516
        $sql .= " cp.fk_user_refuse,";
517
        $sql .= " cp.date_cancel,";
518
        $sql .= " cp.fk_user_cancel,";
519
        $sql .= " cp.detail_refuse,";
520
521
        $sql .= " uu.lastname as user_lastname,";
522
        $sql .= " uu.firstname as user_firstname,";
523
        $sql .= " uu.login as user_login,";
524
        $sql .= " uu.statut as user_status,";
525
        $sql .= " uu.photo as user_photo,";
526
527
        $sql .= " ua.lastname as validator_lastname,";
528
        $sql .= " ua.firstname as validator_firstname,";
529
        $sql .= " ua.login as validator_login,";
530
        $sql .= " ua.statut as validator_status,";
531
        $sql .= " ua.photo as validator_photo";
532
533
        $sql .= " FROM " . MAIN_DB_PREFIX . "holiday as cp, " . MAIN_DB_PREFIX . "user as uu, " . MAIN_DB_PREFIX . "user as ua";
534
        $sql .= " WHERE cp.entity IN (" . getEntity('holiday') . ")";
535
        $sql .= " AND cp.fk_user = uu.rowid AND cp.fk_validator = ua.rowid"; // Hack pour la recherche sur le tableau
536
        $sql .= " AND cp.fk_user IN (" . $this->db->sanitize($user_id) . ")";
537
538
        // Selection filter
539
        if (!empty($filter)) {
540
            $sql .= $filter;
541
        }
542
543
        // Order of display of the result
544
        if (!empty($order)) {
545
            $sql .= $order;
546
        }
547
548
        dol_syslog(get_class($this) . "::fetchByUser", LOG_DEBUG);
549
        $resql = $this->db->query($sql);
550
551
        // If no SQL error
552
        if ($resql) {
553
            $i = 0;
554
            $tab_result = $this->holiday;
555
            $num = $this->db->num_rows($resql);
556
557
            // If no registration
558
            if (!$num) {
559
                return 2;
560
            }
561
562
            // List the records and add them to the table
563
            while ($i < $num) {
564
                $obj = $this->db->fetch_object($resql);
565
566
                $tab_result[$i]['rowid'] = $obj->rowid;
567
                $tab_result[$i]['id'] = $obj->rowid;
568
                $tab_result[$i]['ref'] = ($obj->ref ? $obj->ref : $obj->rowid);
569
570
                $tab_result[$i]['fk_user'] = $obj->fk_user;
571
                $tab_result[$i]['fk_type'] = $obj->fk_type;
572
                $tab_result[$i]['date_create'] = $this->db->jdate($obj->date_create);
573
                $tab_result[$i]['description'] = $obj->description;
574
                $tab_result[$i]['date_debut'] = $this->db->jdate($obj->date_debut);
575
                $tab_result[$i]['date_fin'] = $this->db->jdate($obj->date_fin);
576
                $tab_result[$i]['date_debut_gmt'] = $this->db->jdate($obj->date_debut, 1);
577
                $tab_result[$i]['date_fin_gmt'] = $this->db->jdate($obj->date_fin, 1);
578
                $tab_result[$i]['halfday'] = $obj->halfday;
579
                $tab_result[$i]['statut'] = $obj->status;
580
                $tab_result[$i]['status'] = $obj->status;
581
                $tab_result[$i]['fk_validator'] = $obj->fk_validator;
582
                $tab_result[$i]['date_valid'] = $this->db->jdate($obj->date_valid);
583
                $tab_result[$i]['fk_user_valid'] = $obj->fk_user_valid;
584
                $tab_result[$i]['date_approval'] = $this->db->jdate($obj->date_approval);
585
                $tab_result[$i]['fk_user_approve'] = $obj->fk_user_approve;
586
                $tab_result[$i]['date_refuse'] = $this->db->jdate($obj->date_refuse);
587
                $tab_result[$i]['fk_user_refuse'] = $obj->fk_user_refuse;
588
                $tab_result[$i]['date_cancel'] = $this->db->jdate($obj->date_cancel);
589
                $tab_result[$i]['fk_user_cancel'] = $obj->fk_user_cancel;
590
                $tab_result[$i]['detail_refuse'] = $obj->detail_refuse;
591
592
                $tab_result[$i]['user_firstname'] = $obj->user_firstname;
593
                $tab_result[$i]['user_lastname'] = $obj->user_lastname;
594
                $tab_result[$i]['user_login'] = $obj->user_login;
595
                $tab_result[$i]['user_statut'] = $obj->user_status;
596
                $tab_result[$i]['user_status'] = $obj->user_status;
597
                $tab_result[$i]['user_photo'] = $obj->user_photo;
598
599
                $tab_result[$i]['validator_firstname'] = $obj->validator_firstname;
600
                $tab_result[$i]['validator_lastname'] = $obj->validator_lastname;
601
                $tab_result[$i]['validator_login'] = $obj->validator_login;
602
                $tab_result[$i]['validator_statut'] = $obj->validator_status;
603
                $tab_result[$i]['validator_status'] = $obj->validator_status;
604
                $tab_result[$i]['validator_photo'] = $obj->validator_photo;
605
606
                $i++;
607
            }
608
609
            // Returns 1 with the filled array
610
            $this->holiday = $tab_result;
611
            return 1;
612
        } else {
613
            // SQL Error
614
            $this->error = "Error " . $this->db->lasterror();
615
            return -1;
616
        }
617
    }
618
619
    /**
620
     *  List all holidays of all users
621
     *
622
     *  @param      string  $order      Sort order
623
     *  @param      string  $filter     SQL Filter
624
     *  @return     int                 -1 if KO, 1 if OK, 2 if no result
625
     */
626
    public function fetchAll($order, $filter)
627
    {
628
        $sql = "SELECT";
629
        $sql .= " cp.rowid,";
630
        $sql .= " cp.ref,";
631
        $sql .= " cp.fk_user,";
632
        $sql .= " cp.fk_type,";
633
        $sql .= " cp.date_create,";
634
        $sql .= " cp.tms as date_modification,";
635
        $sql .= " cp.description,";
636
        $sql .= " cp.date_debut,";
637
        $sql .= " cp.date_fin,";
638
        $sql .= " cp.halfday,";
639
        $sql .= " cp.statut as status,";
640
        $sql .= " cp.fk_validator,";
641
        $sql .= " cp.date_valid,";
642
        $sql .= " cp.fk_user_valid,";
643
        $sql .= " cp.date_approval,";
644
        $sql .= " cp.fk_user_approve,";
645
        $sql .= " cp.date_refuse,";
646
        $sql .= " cp.fk_user_refuse,";
647
        $sql .= " cp.date_cancel,";
648
        $sql .= " cp.fk_user_cancel,";
649
        $sql .= " cp.detail_refuse,";
650
651
        $sql .= " uu.lastname as user_lastname,";
652
        $sql .= " uu.firstname as user_firstname,";
653
        $sql .= " uu.login as user_login,";
654
        $sql .= " uu.statut as user_status,";
655
        $sql .= " uu.photo as user_photo,";
656
657
        $sql .= " ua.lastname as validator_lastname,";
658
        $sql .= " ua.firstname as validator_firstname,";
659
        $sql .= " ua.login as validator_login,";
660
        $sql .= " ua.statut as validator_status,";
661
        $sql .= " ua.photo as validator_photo";
662
663
        $sql .= " FROM " . MAIN_DB_PREFIX . "holiday as cp, " . MAIN_DB_PREFIX . "user as uu, " . MAIN_DB_PREFIX . "user as ua";
664
        $sql .= " WHERE cp.entity IN (" . getEntity('holiday') . ")";
665
        $sql .= " AND cp.fk_user = uu.rowid AND cp.fk_validator = ua.rowid "; // Hack pour la recherche sur le tableau
666
667
        // Selection filtering
668
        if (!empty($filter)) {
669
            $sql .= $filter;
670
        }
671
672
        // order of display
673
        if (!empty($order)) {
674
            $sql .= $order;
675
        }
676
677
        dol_syslog(get_class($this) . "::fetchAll", LOG_DEBUG);
678
        $resql = $this->db->query($sql);
679
680
        // If no SQL error
681
        if ($resql) {
682
            $i = 0;
683
            $tab_result = $this->holiday;
684
            $num = $this->db->num_rows($resql);
685
686
            // If no registration
687
            if (!$num) {
688
                return 2;
689
            }
690
691
            // List the records and add them to the table
692
            while ($i < $num) {
693
                $obj = $this->db->fetch_object($resql);
694
695
                $tab_result[$i]['rowid'] = $obj->rowid;
696
                $tab_result[$i]['id'] = $obj->rowid;
697
                $tab_result[$i]['ref'] = ($obj->ref ? $obj->ref : $obj->rowid);
698
699
                $tab_result[$i]['fk_user'] = $obj->fk_user;
700
                $tab_result[$i]['fk_type'] = $obj->fk_type;
701
                $tab_result[$i]['date_create'] = $this->db->jdate($obj->date_create);
702
                $tab_result[$i]['date_modification'] = $this->db->jdate($obj->date_modification);
703
                $tab_result[$i]['description'] = $obj->description;
704
                $tab_result[$i]['date_debut'] = $this->db->jdate($obj->date_debut);
705
                $tab_result[$i]['date_fin'] = $this->db->jdate($obj->date_fin);
706
                $tab_result[$i]['date_debut_gmt'] = $this->db->jdate($obj->date_debut, 1);
707
                $tab_result[$i]['date_fin_gmt'] = $this->db->jdate($obj->date_fin, 1);
708
                $tab_result[$i]['halfday'] = $obj->halfday;
709
                $tab_result[$i]['statut'] = $obj->status;
710
                $tab_result[$i]['status'] = $obj->status;
711
                $tab_result[$i]['fk_validator'] = $obj->fk_validator;
712
                $tab_result[$i]['date_valid'] = $this->db->jdate($obj->date_valid);
713
                $tab_result[$i]['fk_user_valid'] = $obj->fk_user_valid;
714
                $tab_result[$i]['date_approval'] = $this->db->jdate($obj->date_approval);
715
                $tab_result[$i]['fk_user_approve'] = $obj->fk_user_approve;
716
                $tab_result[$i]['date_refuse'] = $obj->date_refuse;
717
                $tab_result[$i]['fk_user_refuse'] = $obj->fk_user_refuse;
718
                $tab_result[$i]['date_cancel'] = $obj->date_cancel;
719
                $tab_result[$i]['fk_user_cancel'] = $obj->fk_user_cancel;
720
                $tab_result[$i]['detail_refuse'] = $obj->detail_refuse;
721
722
                $tab_result[$i]['user_firstname'] = $obj->user_firstname;
723
                $tab_result[$i]['user_lastname'] = $obj->user_lastname;
724
                $tab_result[$i]['user_login'] = $obj->user_login;
725
                $tab_result[$i]['user_statut'] = $obj->user_status;
726
                $tab_result[$i]['user_status'] = $obj->user_status;
727
                $tab_result[$i]['user_photo'] = $obj->user_photo;
728
729
                $tab_result[$i]['validator_firstname'] = $obj->validator_firstname;
730
                $tab_result[$i]['validator_lastname'] = $obj->validator_lastname;
731
                $tab_result[$i]['validator_login'] = $obj->validator_login;
732
                $tab_result[$i]['validator_statut'] = $obj->validator_status;
733
                $tab_result[$i]['validator_status'] = $obj->validator_status;
734
                $tab_result[$i]['validator_photo'] = $obj->validator_photo;
735
736
                $i++;
737
            }
738
            // Returns 1 and adds the array to the variable
739
            $this->holiday = $tab_result;
740
            return 1;
741
        } else {
742
            // SQL Error
743
            $this->error = "Error " . $this->db->lasterror();
744
            return -1;
745
        }
746
    }
747
748
749
    /**
750
     *  Validate leave request
751
     *
752
     *  @param  User    $user           User that validate
753
     *  @param  int     $notrigger      0=launch triggers after, 1=disable triggers
754
     *  @return int                     Return integer <0 if KO, >0 if OK
755
     */
756
    public function validate($user = null, $notrigger = 0)
757
    {
758
        global $conf, $langs;
759
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
760
        $error = 0;
761
762
        $checkBalance = getDictionaryValue('c_holiday_types', 'block_if_negative', $this->fk_type);
763
764
        if ($checkBalance > 0) {
765
            $balance = $this->getCPforUser($this->fk_user, $this->fk_type);
766
767
            if ($balance < 0) {
768
                $this->error = 'LeaveRequestCreationBlockedBecauseBalanceIsNegative';
769
                return -1;
770
            }
771
        }
772
773
        // Define new ref
774
        if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref) || $this->ref == $this->id)) {
775
            $num = $this->getNextNumRef(null);
776
        } else {
777
            $num = $this->ref;
778
        }
779
        $this->newref = dol_sanitizeFileName($num);
780
781
        // Update status
782
        $sql = "UPDATE " . MAIN_DB_PREFIX . "holiday SET";
783
        $sql .= " fk_user_valid = " . ((int) $user->id) . ",";
784
        $sql .= " date_valid = '" . $this->db->idate(dol_now()) . "',";
785
        if (!empty($this->status) && is_numeric($this->status)) {
786
            $sql .= " statut = " . ((int) $this->status) . ",";
787
        } else {
788
            $this->error = 'Property status must be a numeric value';
789
            $error++;
790
        }
791
        $sql .= " ref = '" . $this->db->escape($num) . "'";
792
        $sql .= " WHERE rowid = " . ((int) $this->id);
793
794
        $this->db->begin();
795
796
        dol_syslog(get_class($this) . "::validate", LOG_DEBUG);
797
        $resql = $this->db->query($sql);
798
        if (!$resql) {
799
            $error++;
800
            $this->errors[] = "Error " . $this->db->lasterror();
801
        }
802
803
        if (!$error) {
804
            if (!$notrigger) {
805
                // Call trigger
806
                $result = $this->call_trigger('HOLIDAY_VALIDATE', $user);
807
                if ($result < 0) {
808
                    $error++;
809
                }
810
                // End call triggers
811
            }
812
        }
813
814
        if (!$error) {
815
            $this->oldref = $this->ref;
816
817
            // Rename directory if dir was a temporary ref
818
            if (preg_match('/^[\(]?PROV/i', $this->ref)) {
819
                // Now we rename also files into index
820
                $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) . "'";
821
                $sql .= " WHERE filename LIKE '" . $this->db->escape($this->ref) . "%' AND filepath = 'holiday/" . $this->db->escape($this->ref) . "' and entity = " . ((int) $conf->entity);
822
                $resql = $this->db->query($sql);
823
                if (!$resql) {
824
                    $error++;
825
                    $this->error = $this->db->lasterror();
826
                }
827
                $sql = 'UPDATE ' . MAIN_DB_PREFIX . "ecm_files set filepath = 'holiday/" . $this->db->escape($this->newref) . "'";
828
                $sql .= " WHERE filepath = 'holiday/" . $this->db->escape($this->ref) . "' and entity = " . $conf->entity;
829
                $resql = $this->db->query($sql);
830
                if (!$resql) {
831
                    $error++;
832
                    $this->error = $this->db->lasterror();
833
                }
834
835
                // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
836
                $oldref = dol_sanitizeFileName($this->ref);
837
                $newref = dol_sanitizeFileName($num);
838
                $dirsource = $conf->holiday->multidir_output[$this->entity] . '/' . $oldref;
839
                $dirdest = $conf->holiday->multidir_output[$this->entity] . '/' . $newref;
840
                if (!$error && file_exists($dirsource)) {
841
                    dol_syslog(get_class($this) . "::validate rename dir " . $dirsource . " into " . $dirdest);
842
                    if (@rename($dirsource, $dirdest)) {
843
                        dol_syslog("Rename ok");
844
                        // Rename docs starting with $oldref with $newref
845
                        $listoffiles = dol_dir_list($dirdest, 'files', 1, '^' . preg_quote($oldref, '/'));
846
                        foreach ($listoffiles as $fileentry) {
847
                            $dirsource = $fileentry['name'];
848
                            $dirdest = preg_replace('/^' . preg_quote($oldref, '/') . '/', $newref, $dirsource);
849
                            $dirsource = $fileentry['path'] . '/' . $dirsource;
850
                            $dirdest = $fileentry['path'] . '/' . $dirdest;
851
                            @rename($dirsource, $dirdest);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for rename(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

851
                            /** @scrutinizer ignore-unhandled */ @rename($dirsource, $dirdest);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
852
                        }
853
                    }
854
                }
855
            }
856
        }
857
858
859
        // Commit or rollback
860
        if ($error) {
861
            foreach ($this->errors as $errmsg) {
862
                dol_syslog(get_class($this) . "::validate " . $errmsg, LOG_ERR);
863
                $this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
864
            }
865
            $this->db->rollback();
866
            return -1 * $error;
867
        } else {
868
            $this->db->commit();
869
            return 1;
870
        }
871
    }
872
873
874
    /**
875
     *  Approve leave request
876
     *
877
     *  @param  User    $user           User that approve
878
     *  @param  int     $notrigger      0=launch triggers after, 1=disable triggers
879
     *  @return int                     Return integer <0 if KO, >0 if OK
880
     */
881
    public function approve($user = null, $notrigger = 0)
882
    {
883
        $error = 0;
884
885
        $checkBalance = getDictionaryValue('c_holiday_types', 'block_if_negative', $this->fk_type);
886
887
        if ($checkBalance > 0) {
888
            $balance = $this->getCPforUser($this->fk_user, $this->fk_type);
889
890
            if ($balance < 0) {
891
                $this->error = 'LeaveRequestCreationBlockedBecauseBalanceIsNegative';
892
                return -1;
893
            }
894
        }
895
896
        // Update request
897
        $sql = "UPDATE " . MAIN_DB_PREFIX . "holiday SET";
898
        $sql .= " description= '" . $this->db->escape($this->description) . "',";
899
        if (!empty($this->date_debut)) {
900
            $sql .= " date_debut = '" . $this->db->idate($this->date_debut) . "',";
901
        } else {
902
            $error++;
903
        }
904
        if (!empty($this->date_fin)) {
905
            $sql .= " date_fin = '" . $this->db->idate($this->date_fin) . "',";
906
        } else {
907
            $error++;
908
        }
909
        $sql .= " halfday = " . ((int) $this->halfday) . ",";
910
        if (!empty($this->status) && is_numeric($this->status)) {
911
            $sql .= " statut = " . ((int) $this->status) . ",";
912
        } else {
913
            $error++;
914
        }
915
        if (!empty($this->fk_validator)) {
916
            $sql .= " fk_validator = " . ((int) $this->fk_validator) . ",";
917
        } else {
918
            $error++;
919
        }
920
        if (!empty($this->date_valid)) {
921
            $sql .= " date_valid = '" . $this->db->idate($this->date_valid) . "',";
922
        } else {
923
            $sql .= " date_valid = NULL,";
924
        }
925
        if (!empty($this->fk_user_valid)) {
926
            $sql .= " fk_user_valid = " . ((int) $this->fk_user_valid) . ",";
927
        } else {
928
            $sql .= " fk_user_valid = NULL,";
929
        }
930
        if (!empty($this->date_approval)) {
931
            $sql .= " date_approval = '" . $this->db->idate($this->date_approval) . "',";
932
        } else {
933
            $sql .= " date_approval = NULL,";
934
        }
935
        if (!empty($this->fk_user_approve)) {
936
            $sql .= " fk_user_approve = " . ((int) $this->fk_user_approve) . ",";
937
        } else {
938
            $sql .= " fk_user_approve = NULL,";
939
        }
940
        if (!empty($this->date_refuse)) {
941
            $sql .= " date_refuse = '" . $this->db->idate($this->date_refuse) . "',";
942
        } else {
943
            $sql .= " date_refuse = NULL,";
944
        }
945
        if (!empty($this->fk_user_refuse)) {
946
            $sql .= " fk_user_refuse = " . ((int) $this->fk_user_refuse) . ",";
947
        } else {
948
            $sql .= " fk_user_refuse = NULL,";
949
        }
950
        if (!empty($this->date_cancel)) {
951
            $sql .= " date_cancel = '" . $this->db->idate($this->date_cancel) . "',";
952
        } else {
953
            $sql .= " date_cancel = NULL,";
954
        }
955
        if (!empty($this->fk_user_cancel)) {
956
            $sql .= " fk_user_cancel = " . ((int) $this->fk_user_cancel) . ",";
957
        } else {
958
            $sql .= " fk_user_cancel = NULL,";
959
        }
960
        if (!empty($this->detail_refuse)) {
961
            $sql .= " detail_refuse = '" . $this->db->escape($this->detail_refuse) . "'";
962
        } else {
963
            $sql .= " detail_refuse = NULL";
964
        }
965
        $sql .= " WHERE rowid = " . ((int) $this->id);
966
967
        $this->db->begin();
968
969
        dol_syslog(get_class($this) . "::approve", LOG_DEBUG);
970
        $resql = $this->db->query($sql);
971
        if (!$resql) {
972
            $error++;
973
            $this->errors[] = "Error " . $this->db->lasterror();
974
        }
975
976
        if (!$error) {
977
            if (!$notrigger) {
978
                // Call trigger
979
                $result = $this->call_trigger('HOLIDAY_APPROVE', $user);
980
                if ($result < 0) {
981
                    $error++;
982
                }
983
                // End call triggers
984
            }
985
        }
986
987
        // Commit or rollback
988
        if ($error) {
989
            foreach ($this->errors as $errmsg) {
990
                dol_syslog(get_class($this) . "::approve " . $errmsg, LOG_ERR);
991
                $this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
992
            }
993
            $this->db->rollback();
994
            return -1 * $error;
995
        } else {
996
            $this->db->commit();
997
            return 1;
998
        }
999
    }
1000
1001
    /**
1002
     *  Update database
1003
     *
1004
     *  @param  User    $user           User that modify
1005
     *  @param  int     $notrigger      0=launch triggers after, 1=disable triggers
1006
     *  @return int                     Return integer <0 if KO, >0 if OK
1007
     */
1008
    public function update($user = null, $notrigger = 0)
1009
    {
1010
        global $conf, $langs;
1011
        $error = 0;
1012
1013
        $checkBalance = getDictionaryValue('c_holiday_types', 'block_if_negative', $this->fk_type);
1014
1015
        if ($checkBalance > 0 && $this->status != self::STATUS_DRAFT) {
1016
            $balance = $this->getCPforUser($this->fk_user, $this->fk_type);
1017
1018
            if ($balance < 0) {
1019
                $this->error = 'LeaveRequestCreationBlockedBecauseBalanceIsNegative';
1020
                return -1;
1021
            }
1022
        }
1023
1024
        // Update request
1025
        $sql = "UPDATE " . MAIN_DB_PREFIX . "holiday SET";
1026
1027
        $sql .= " description= '" . $this->db->escape($this->description) . "',";
1028
1029
        if (!empty($this->date_debut)) {
1030
            $sql .= " date_debut = '" . $this->db->idate($this->date_debut) . "',";
1031
        } else {
1032
            $error++;
1033
        }
1034
        if (!empty($this->date_fin)) {
1035
            $sql .= " date_fin = '" . $this->db->idate($this->date_fin) . "',";
1036
        } else {
1037
            $error++;
1038
        }
1039
        $sql .= " halfday = " . $this->halfday . ",";
1040
        if (!empty($this->status) && is_numeric($this->status)) {
1041
            $sql .= " statut = " . $this->status . ",";
1042
        } else {
1043
            $error++;
1044
        }
1045
        if (!empty($this->fk_validator)) {
1046
            $sql .= " fk_validator = '" . $this->db->escape($this->fk_validator) . "',";
1047
        } else {
1048
            $error++;
1049
        }
1050
        if (!empty($this->date_valid)) {
1051
            $sql .= " date_valid = '" . $this->db->idate($this->date_valid) . "',";
1052
        } else {
1053
            $sql .= " date_valid = NULL,";
1054
        }
1055
        if (!empty($this->fk_user_valid)) {
1056
            $sql .= " fk_user_valid = " . ((int) $this->fk_user_valid) . ",";
1057
        } else {
1058
            $sql .= " fk_user_valid = NULL,";
1059
        }
1060
        if (!empty($this->date_approval)) {
1061
            $sql .= " date_approval = '" . $this->db->idate($this->date_approval) . "',";
1062
        } else {
1063
            $sql .= " date_approval = NULL,";
1064
        }
1065
        if (!empty($this->fk_user_approve)) {
1066
            $sql .= " fk_user_approve = " . ((int) $this->fk_user_approve) . ",";
1067
        } else {
1068
            $sql .= " fk_user_approve = NULL,";
1069
        }
1070
        if (!empty($this->date_refuse)) {
1071
            $sql .= " date_refuse = '" . $this->db->idate($this->date_refuse) . "',";
1072
        } else {
1073
            $sql .= " date_refuse = NULL,";
1074
        }
1075
        if (!empty($this->fk_user_refuse)) {
1076
            $sql .= " fk_user_refuse = " . ((int) $this->fk_user_refuse) . ",";
1077
        } else {
1078
            $sql .= " fk_user_refuse = NULL,";
1079
        }
1080
        if (!empty($this->date_cancel)) {
1081
            $sql .= " date_cancel = '" . $this->db->idate($this->date_cancel) . "',";
1082
        } else {
1083
            $sql .= " date_cancel = NULL,";
1084
        }
1085
        if (!empty($this->fk_user_cancel)) {
1086
            $sql .= " fk_user_cancel = " . ((int) $this->fk_user_cancel) . ",";
1087
        } else {
1088
            $sql .= " fk_user_cancel = NULL,";
1089
        }
1090
        if (!empty($this->detail_refuse)) {
1091
            $sql .= " detail_refuse = '" . $this->db->escape($this->detail_refuse) . "'";
1092
        } else {
1093
            $sql .= " detail_refuse = NULL";
1094
        }
1095
1096
        $sql .= " WHERE rowid = " . ((int) $this->id);
1097
1098
        $this->db->begin();
1099
1100
        dol_syslog(get_class($this) . "::update", LOG_DEBUG);
1101
        $resql = $this->db->query($sql);
1102
        if (!$resql) {
1103
            $error++;
1104
            $this->errors[] = "Error " . $this->db->lasterror();
1105
        }
1106
1107
        if (!$error) {
1108
            if (!$notrigger) {
1109
                // Call trigger
1110
                $result = $this->call_trigger('HOLIDAY_MODIFY', $user);
1111
                if ($result < 0) {
1112
                    $error++;
1113
                }
1114
                // End call triggers
1115
            }
1116
        }
1117
1118
        // Commit or rollback
1119
        if ($error) {
1120
            foreach ($this->errors as $errmsg) {
1121
                dol_syslog(get_class($this) . "::update " . $errmsg, LOG_ERR);
1122
                $this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
1123
            }
1124
            $this->db->rollback();
1125
            return -1 * $error;
1126
        } else {
1127
            $this->db->commit();
1128
            return 1;
1129
        }
1130
    }
1131
1132
1133
    /**
1134
     *   Delete object in database
1135
     *
1136
     *   @param     User    $user           User that delete
1137
     *   @param     int     $notrigger      0=launch triggers after, 1=disable triggers
1138
     *   @return    int                     Return integer <0 if KO, >0 if OK
1139
     */
1140
    public function delete($user, $notrigger = 0)
1141
    {
1142
        global $conf, $langs;
1143
        $error = 0;
1144
1145
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "holiday";
1146
        $sql .= " WHERE rowid=" . ((int) $this->id);
1147
1148
        $this->db->begin();
1149
1150
        dol_syslog(get_class($this) . "::delete", LOG_DEBUG);
1151
        $resql = $this->db->query($sql);
1152
        if (!$resql) {
1153
            $error++;
1154
            $this->errors[] = "Error " . $this->db->lasterror();
1155
        }
1156
1157
        if (!$error) {
1158
            if (!$notrigger) {
1159
                // Call trigger
1160
                $result = $this->call_trigger('HOLIDAY_DELETE', $user);
1161
                if ($result < 0) {
1162
                    $error++;
1163
                }
1164
                // End call triggers
1165
            }
1166
        }
1167
1168
        // Commit or rollback
1169
        if ($error) {
1170
            foreach ($this->errors as $errmsg) {
1171
                dol_syslog(get_class($this) . "::delete " . $errmsg, LOG_ERR);
1172
                $this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
1173
            }
1174
            $this->db->rollback();
1175
            return -1 * $error;
1176
        } else {
1177
            $this->db->commit();
1178
            return 1;
1179
        }
1180
    }
1181
1182
    /**
1183
     *  Check if a user is on holiday (partially or completely) into a period.
1184
     *  This function can be used to avoid to have 2 leave requests on same period for example.
1185
     *  Warning: It consumes a lot of memory because it load in ->holiday all holiday of a dedicated user at each call.
1186
     *
1187
     *  @param  int     $fk_user        Id user
1188
     *  @param  integer $dateStart      Start date of period to check
1189
     *  @param  integer $dateEnd        End date of period to check
1190
     *  @param  int     $halfday        Tag to define how start and end the period to check:
1191
     *                                  0:Full days, 2:Start afternoon end morning, -1:Start afternoon end afternoon, 1:Start morning end morning
1192
     *  @return boolean                 False = New range overlap an existing holiday, True = no overlapping (is never on holiday during checked period).
1193
     *  @see verifDateHolidayForTimestamp()
1194
     */
1195
    public function verifDateHolidayCP($fk_user, $dateStart, $dateEnd, $halfday = 0)
1196
    {
1197
        $this->fetchByUser($fk_user, '', '');
1198
1199
        foreach ($this->holiday as $infos_CP) {
1200
            if ($infos_CP['statut'] == Holiday::STATUS_CANCELED) {
1201
                continue; // ignore not validated holidays
1202
            }
1203
            if ($infos_CP['statut'] == Holiday::STATUS_REFUSED) {
1204
                continue; // ignore refused holidays
1205
            }
1206
            //var_dump("--");
1207
            //var_dump("old: ".dol_print_date($infos_CP['date_debut'],'dayhour').' '.dol_print_date($infos_CP['date_fin'],'dayhour').' '.$infos_CP['halfday']);
1208
            //var_dump("new: ".dol_print_date($dateStart,'dayhour').' '.dol_print_date($dateEnd,'dayhour').' '.$halfday);
1209
1210
            if ($halfday == 0) {
1211
                if ($dateStart >= $infos_CP['date_debut'] && $dateStart <= $infos_CP['date_fin']) {
1212
                    return false;
1213
                }
1214
                if ($dateEnd <= $infos_CP['date_fin'] && $dateEnd >= $infos_CP['date_debut']) {
1215
                    return false;
1216
                }
1217
            } elseif ($halfday == -1) {
1218
                // new start afternoon, new end afternoon
1219
                if ($dateStart >= $infos_CP['date_debut'] && $dateStart <= $infos_CP['date_fin']) {
1220
                    if ($dateStart < $infos_CP['date_fin'] || in_array($infos_CP['halfday'], array(0, -1))) {
1221
                        return false;
1222
                    }
1223
                }
1224
                if ($dateEnd <= $infos_CP['date_fin'] && $dateEnd >= $infos_CP['date_debut']) {
1225
                    if ($dateStart < $dateEnd) {
1226
                        return false;
1227
                    }
1228
                    if ($dateEnd < $infos_CP['date_fin'] || in_array($infos_CP['halfday'], array(0, -1))) {
1229
                        return false;
1230
                    }
1231
                }
1232
            } elseif ($halfday == 1) {
1233
                // new start morning, new end morning
1234
                if ($dateStart >= $infos_CP['date_debut'] && $dateStart <= $infos_CP['date_fin']) {
1235
                    if ($dateStart < $dateEnd) {
1236
                        return false;
1237
                    }
1238
                    if ($dateStart > $infos_CP['date_debut'] || in_array($infos_CP['halfday'], array(0, 1))) {
1239
                        return false;
1240
                    }
1241
                }
1242
                if ($dateEnd <= $infos_CP['date_fin'] && $dateEnd >= $infos_CP['date_debut']) {
1243
                    if ($dateEnd > $infos_CP['date_debut'] || in_array($infos_CP['halfday'], array(0, 1))) {
1244
                        return false;
1245
                    }
1246
                }
1247
            } elseif ($halfday == 2) {
1248
                // new start afternoon, new end morning
1249
                if ($dateStart >= $infos_CP['date_debut'] && $dateStart <= $infos_CP['date_fin']) {
1250
                    if ($dateStart < $infos_CP['date_fin'] || in_array($infos_CP['halfday'], array(0, -1))) {
1251
                        return false;
1252
                    }
1253
                }
1254
                if ($dateEnd <= $infos_CP['date_fin'] && $dateEnd >= $infos_CP['date_debut']) {
1255
                    if ($dateEnd > $infos_CP['date_debut'] || in_array($infos_CP['halfday'], array(0, 1))) {
1256
                        return false;
1257
                    }
1258
                }
1259
            } else {
1260
                dol_print_error(null, 'Bad value of parameter halfday when calling function verifDateHolidayCP');
1261
            }
1262
        }
1263
1264
        return true;
1265
    }
1266
1267
1268
    /**
1269
     *  Check that a user is not on holiday for a particular timestamp. Can check approved leave requests and not into public holidays of company.
1270
     *
1271
     *  @param  int         $fk_user                Id user
1272
     *  @param  integer     $timestamp              Time stamp date for a day (YYYY-MM-DD) without hours  (= 12:00AM in english and not 12:00PM that is 12:00)
1273
     *  @param  string      $status                 Filter on holiday status. '-1' = no filter.
1274
     *  @return array                               array('morning'=> ,'afternoon'=> ), Boolean is true if user is available for day timestamp.
1275
     *  @see verifDateHolidayCP()
1276
     */
1277
    public function verifDateHolidayForTimestamp($fk_user, $timestamp, $status = '-1')
1278
    {
1279
        $isavailablemorning = true;
1280
        $isavailableafternoon = true;
1281
1282
        // Check into leave requests
1283
        $sql = "SELECT cp.rowid, cp.date_debut as date_start, cp.date_fin as date_end, cp.halfday, cp.statut as status";
1284
        $sql .= " FROM " . MAIN_DB_PREFIX . "holiday as cp";
1285
        $sql .= " WHERE cp.entity IN (" . getEntity('holiday') . ")";
1286
        $sql .= " AND cp.fk_user = " . (int) $fk_user;
1287
        $sql .= " AND cp.date_debut <= '" . $this->db->idate($timestamp) . "' AND cp.date_fin >= '" . $this->db->idate($timestamp) . "'";
1288
        if ($status != '-1') {
1289
            $sql .= " AND cp.statut IN (" . $this->db->sanitize($status) . ")";
1290
        }
1291
1292
        $resql = $this->db->query($sql);
1293
        if ($resql) {
1294
            $num_rows = $this->db->num_rows($resql); // Note, we can have 2 records if on is morning and the other one is afternoon
1295
            if ($num_rows > 0) {
1296
                $arrayofrecord = array();
1297
                $i = 0;
1298
                while ($i < $num_rows) {
1299
                    $obj = $this->db->fetch_object($resql);
1300
1301
                    // Note: $obj->halfday is  0:Full days, 2:Start afternoon end morning, -1:Start afternoon, 1:End morning
1302
                    $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);
1303
                    $i++;
1304
                }
1305
1306
                // We found a record, user is on holiday by default, so is not available is true.
1307
                $isavailablemorning = true;
1308
                foreach ($arrayofrecord as $record) {
1309
                    if ($timestamp == $record['date_start'] && $record['halfday'] == 2) {
1310
                        continue;
1311
                    }
1312
                    if ($timestamp == $record['date_start'] && $record['halfday'] == -1) {
1313
                        continue;
1314
                    }
1315
                    $isavailablemorning = false;
1316
                    break;
1317
                }
1318
                $isavailableafternoon = true;
1319
                foreach ($arrayofrecord as $record) {
1320
                    if ($timestamp == $record['date_end'] && $record['halfday'] == 2) {
1321
                        continue;
1322
                    }
1323
                    if ($timestamp == $record['date_end'] && $record['halfday'] == 1) {
1324
                        continue;
1325
                    }
1326
                    $isavailableafternoon = false;
1327
                    break;
1328
                }
1329
            }
1330
        } else {
1331
            dol_print_error($this->db);
1332
        }
1333
1334
        $result = array('morning' => $isavailablemorning, 'afternoon' => $isavailableafternoon);
1335
        if (!$isavailablemorning) {
1336
            $result['morning_reason'] = 'leave_request';
1337
        }
1338
        if (!$isavailableafternoon) {
1339
            $result['afternoon_reason'] = 'leave_request';
1340
        }
1341
        return $result;
1342
    }
1343
1344
    /**
1345
     * getTooltipContentArray
1346
     *
1347
     * @param array $params ex option, infologin
1348
     * @since v18
1349
     * @return array
1350
     */
1351
    public function getTooltipContentArray($params)
1352
    {
1353
        global $langs;
1354
1355
        $langs->load('holiday');
1356
        $nofetch = !empty($params['nofetch']);
1357
1358
        $datas = array();
1359
        $datas['picto'] = img_picto('', $this->picto) . ' <u class="paddingrightonly">' . $langs->trans("Holiday") . '</u>';
1360
        if (isset($this->status)) {
1361
            $datas['picto'] .= ' ' . $this->getLibStatut(5);
1362
        }
1363
        $datas['ref'] = '<br><b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
1364
        // show type for this record only in ajax to not overload lists
1365
        if (!$nofetch && !empty($this->fk_type)) {
1366
            $typeleaves = $this->getTypes(1, -1);
1367
            if (empty($typeleaves[$this->fk_type])) {
1368
                $labeltoshow = $langs->trans("TypeWasDisabledOrRemoved", $this->fk_type);
1369
            } else {
1370
                $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']);
1371
            }
1372
            $datas['type'] = '<br><b>' . $langs->trans("Type") . ':</b> ' . $labeltoshow;
1373
        }
1374
        if (isset($this->halfday) && !empty($this->date_debut) && !empty($this->date_fin)) {
1375
            $listhalfday = array(
1376
                'morning' => $langs->trans("Morning"),
1377
                "afternoon" => $langs->trans("Afternoon")
1378
            );
1379
            $starthalfday = ($this->halfday == -1 || $this->halfday == 2) ? 'afternoon' : 'morning';
1380
            $endhalfday = ($this->halfday == 1 || $this->halfday == 2) ? 'morning' : 'afternoon';
1381
            $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>';
1382
            $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>';
1383
        }
1384
1385
1386
        return $datas;
1387
    }
1388
1389
    /**
1390
     *  Return clicable name (with picto eventually)
1391
     *
1392
     *  @param  int         $withpicto                  0=_No picto, 1=Includes the picto in the linkn, 2=Picto only
1393
     *  @param  int         $save_lastsearch_value      -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
1394
     *  @param  int         $notooltip                  1=Disable tooltip
1395
     *  @param  string      $morecss                    Add more css on link
1396
     *  @return string                                  String with URL
1397
     */
1398
    public function getNomUrl($withpicto = 0, $save_lastsearch_value = -1, $notooltip = 0, $morecss = '')
1399
    {
1400
        global $conf, $langs, $hookmanager;
1401
1402
        if (!empty($conf->dol_no_mouse_hover)) {
1403
            $notooltip = 1; // Force disable tooltips
1404
        }
1405
1406
        $result = '';
1407
        $params = [
1408
            'id' => $this->id,
1409
            'objecttype' => $this->element,
1410
            'nofetch' => 1,
1411
        ];
1412
        $classfortooltip = 'classfortooltip';
1413
        $dataparams = '';
1414
        if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1415
            $classfortooltip = 'classforajaxtooltip';
1416
            $dataparams = ' data-params="' . dol_escape_htmltag(json_encode($params)) . '"';
1417
            $label = '';
1418
        } else {
1419
            $label = implode($this->getTooltipContentArray($params));
1420
        }
1421
1422
        $url = constant('BASE_URL') . '/holiday/card.php?id=' . $this->id;
1423
1424
        //if ($option != 'nolink')
1425
        //{
1426
        // Add param to save lastsearch_values or not
1427
        $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1428
        if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1429
            $add_save_lastsearch_values = 1;
1430
        }
1431
        if ($add_save_lastsearch_values) {
1432
            $url .= '&save_lastsearch_values=1';
1433
        }
1434
        //}
1435
1436
        $linkclose = '';
1437
        if (empty($notooltip)) {
1438
            if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1439
                $label = $langs->trans("ShowMyObject");
1440
                $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
1441
            }
1442
            $linkclose .= ($label ? ' title="' . dol_escape_htmltag($label, 1) . '"' : ' title="tocomplete"');
1443
            $linkclose .= $dataparams . ' class="' . $classfortooltip . ($morecss ? ' ' . $morecss : '') . '"';
1444
        } else {
1445
            $linkclose = ($morecss ? ' class="' . $morecss . '"' : '');
1446
        }
1447
1448
        $linkstart = '<a href="' . $url . '"';
1449
        $linkstart .= $linkclose . '>';
1450
        $linkend = '</a>';
1451
1452
        $result .= $linkstart;
1453
1454
        if ($withpicto) {
1455
            $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="' . (($withpicto != 2) ? 'paddingright ' : '') . '"'), 0, 0, $notooltip ? 0 : 1);
1456
        }
1457
        if ($withpicto != 2) {
1458
            $result .= $this->ref;
1459
        }
1460
        $result .= $linkend;
1461
1462
        global $action;
1463
        $hookmanager->initHooks(array($this->element . 'dao'));
1464
        $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1465
        $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1466
        if ($reshook > 0) {
1467
            $result = $hookmanager->resPrint;
1468
        } else {
1469
            $result .= $hookmanager->resPrint;
1470
        }
1471
        return $result;
1472
    }
1473
1474
1475
    /**
1476
     *  Returns the label status
1477
     *
1478
     *  @param      int     $mode       0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto
1479
     *  @return     string              Label
1480
     */
1481
    public function getLibStatut($mode = 0)
1482
    {
1483
        return $this->LibStatut($this->status, $mode, $this->date_debut);
1484
    }
1485
1486
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1487
    /**
1488
     *  Returns the label of a status
1489
     *
1490
     *  @param      int         $status     Id status
1491
     *  @param      int         $mode       0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto
1492
     *  @param      int|string  $startdate  Date holiday should start
1493
     *  @return     string                  Label
1494
     */
1495
    public function LibStatut($status, $mode = 0, $startdate = '')
1496
    {
1497
		// phpcs:enable
1498
        global $langs;
1499
1500
        if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
1501
            global $langs;
1502
            //$langs->load("mymodule");
1503
            $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('DraftCP');
1504
            $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('ToReviewCP');
1505
            $this->labelStatus[self::STATUS_APPROVED] = $langs->transnoentitiesnoconv('ApprovedCP');
1506
            $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('CancelCP');
1507
            $this->labelStatus[self::STATUS_REFUSED] = $langs->transnoentitiesnoconv('RefuseCP');
1508
            $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('DraftCP');
1509
            $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('ToReviewCP');
1510
            $this->labelStatusShort[self::STATUS_APPROVED] = $langs->transnoentitiesnoconv('ApprovedCP');
1511
            $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('CancelCP');
1512
            $this->labelStatusShort[self::STATUS_REFUSED] = $langs->transnoentitiesnoconv('RefuseCP');
1513
        }
1514
1515
        $params = array();
1516
        $statusType = 'status6';
1517
        if (!empty($startdate) && $startdate >= dol_now()) {        // If not yet passed, we use a green "in live" color
1518
            $statusType = 'status4';
1519
            $params = array('tooltip' => $this->labelStatus[$status] . ' - ' . $langs->trans("Forthcoming"));
1520
        }
1521
        if ($status == self::STATUS_DRAFT) {
1522
            $statusType = 'status0';
1523
        }
1524
        if ($status == self::STATUS_VALIDATED) {
1525
            $statusType = 'status1';
1526
        }
1527
        if ($status == self::STATUS_CANCELED) {
1528
            $statusType = 'status9';
1529
        }
1530
        if ($status == self::STATUS_REFUSED) {
1531
            $statusType = 'status9';
1532
        }
1533
1534
        return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode, '', $params);
1535
    }
1536
1537
1538
    /**
1539
     *   Show select with list of leave status
1540
     *
1541
     *   @param     int     $selected       Id of preselected status
1542
     *   @param     string  $htmlname       Name of HTML select field
1543
     *   @param     string  $morecss        More CSS on select component
1544
     *   @return    string                  Show select of status
1545
     */
1546
    public function selectStatutCP($selected = 0, $htmlname = 'select_statut', $morecss = 'minwidth125')
1547
    {
1548
        global $langs;
1549
1550
        // List of status label
1551
        $name = array('DraftCP', 'ToReviewCP', 'ApprovedCP', 'CancelCP', 'RefuseCP');
1552
        $nb = count($name) + 1;
1553
1554
        // Select HTML
1555
        $out = '<select name="' . $htmlname . '" id="' . $htmlname . '" class="flat' . ($morecss ? ' ' . $morecss : '') . '">' . "\n";
1556
        $out .= '<option value="-1">&nbsp;</option>' . "\n";
1557
1558
        // Loop on status
1559
        for ($i = 1; $i < $nb; $i++) {
1560
            if ($i == $selected) {
1561
                $out .= '<option value="' . $i . '" selected>' . $langs->trans($name[$i - 1]) . '</option>' . "\n";
1562
            } else {
1563
                $out .= '<option value="' . $i . '">' . $langs->trans($name[$i - 1]) . '</option>' . "\n";
1564
            }
1565
        }
1566
1567
        $out .= "</select>\n";
1568
1569
        $showempty = 0;
1570
        $out .= ajax_combobox($htmlname, array(), 0, 0, 'resolve', ($showempty < 0 ? (string) $showempty : '-1'), $morecss);
1571
1572
        return $out;
1573
    }
1574
1575
    /**
1576
     *  Met à jour une option du module Holiday Payés
1577
     *
1578
     *  @param  string  $name       name du paramètre de configuration
1579
     *  @param  string  $value      vrai si mise à jour OK sinon faux
1580
     *  @return boolean             ok or ko
1581
     */
1582
    public function updateConfCP($name, $value)
1583
    {
1584
        $sql = "UPDATE " . MAIN_DB_PREFIX . "holiday_config SET";
1585
        $sql .= " value = '" . $this->db->escape($value) . "'";
1586
        $sql .= " WHERE name = '" . $this->db->escape($name) . "'";
1587
1588
        dol_syslog(get_class($this) . '::updateConfCP name=' . $name, LOG_DEBUG);
1589
        $result = $this->db->query($sql);
1590
        if ($result) {
1591
            return true;
1592
        }
1593
1594
        return false;
1595
    }
1596
1597
    /**
1598
     *  Return value of a conf parameter for leave module
1599
     *  TODO Move this into llx_const table
1600
     *
1601
     *  @param  string  $name                 Name of parameter
1602
     *  @param  string  $createifnotfound     'stringvalue'=Create entry with string value if not found. For example 'YYYYMMDDHHMMSS'.
1603
     *  @return string|int<min,0>             Value of parameter. Example: 'YYYYMMDDHHMMSS' or < 0 if error
1604
     */
1605
    public function getConfCP($name, $createifnotfound = '')
1606
    {
1607
        $sql = "SELECT value";
1608
        $sql .= " FROM " . MAIN_DB_PREFIX . "holiday_config";
1609
        $sql .= " WHERE name = '" . $this->db->escape($name) . "'";
1610
1611
        dol_syslog(get_class($this) . '::getConfCP name=' . $name . ' createifnotfound=' . $createifnotfound, LOG_DEBUG);
1612
        $result = $this->db->query($sql);
1613
1614
        if ($result) {
1615
            $obj = $this->db->fetch_object($result);
1616
            // Return value
1617
            if (empty($obj)) {
1618
                if ($createifnotfound) {
1619
                    $sql = "INSERT INTO " . MAIN_DB_PREFIX . "holiday_config(name, value)";
1620
                    $sql .= " VALUES('" . $this->db->escape($name) . "', '" . $this->db->escape($createifnotfound) . "')";
1621
                    $result = $this->db->query($sql);
1622
                    if ($result) {
1623
                        return $createifnotfound;
1624
                    } else {
1625
                        $this->error = $this->db->lasterror();
1626
                        return -2;
1627
                    }
1628
                } else {
1629
                    return '';
1630
                }
1631
            } else {
1632
                return $obj->value;
1633
            }
1634
        } else {
1635
            // Erreur SQL
1636
            $this->error = $this->db->lasterror();
1637
            return -1;
1638
        }
1639
    }
1640
1641
    /**
1642
     *  Met à jour le timestamp de la dernière mise à jour du solde des CP
1643
     *
1644
     *  @param      int     $userID     Id of user
1645
     *  @param      float   $nbHoliday  Nb of days
1646
     *  @param      int     $fk_type    Type of vacation
1647
     *  @return     int                 0=Nothing done, 1=OK, -1=KO
1648
     */
1649
    public function updateSoldeCP($userID = 0, $nbHoliday = 0, $fk_type = 0)
1650
    {
1651
        global $user, $langs;
1652
1653
        $error = 0;
1654
1655
        if (empty($userID) && empty($nbHoliday) && empty($fk_type)) {
1656
            $langs->load("holiday");
1657
1658
            // Si mise à jour pour tout le monde en début de mois
1659
            $now = dol_now();
1660
1661
            $month = date('m', $now);
1662
            $newdateforlastupdate = dol_print_date($now, '%Y%m%d%H%M%S');
1663
1664
            // Get month of last update
1665
            $lastUpdate = $this->getConfCP('lastUpdate', $newdateforlastupdate);
1666
            $monthLastUpdate = $lastUpdate[4] . $lastUpdate[5];
1667
            //print 'month: '.$month.' lastUpdate:'.$lastUpdate.' monthLastUpdate:'.$monthLastUpdate;exit;
1668
1669
            // 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.
1670
            if ($month != $monthLastUpdate) {
1671
                $this->db->begin();
1672
1673
                $users = $this->fetchUsers(false, false, ' AND u.statut > 0');
1674
                $nbUser = count($users);
1675
1676
                $sql = "UPDATE " . MAIN_DB_PREFIX . "holiday_config SET";
1677
                $sql .= " value = '" . $this->db->escape($newdateforlastupdate) . "'";
1678
                $sql .= " WHERE name = 'lastUpdate'";
1679
                $result = $this->db->query($sql);
1680
1681
                $typeleaves = $this->getTypes(1, 1);
1682
1683
                // Update each user counter
1684
                foreach ($users as $userCounter) {
1685
                    $nbDaysToAdd = (isset($typeleaves[$userCounter['type']]['newbymonth']) ? $typeleaves[$userCounter['type']]['newbymonth'] : 0);
1686
                    if (empty($nbDaysToAdd)) {
1687
                        continue;
1688
                    }
1689
1690
                    dol_syslog("We update leave type id " . $userCounter['type'] . " for user id " . $userCounter['rowid'], LOG_DEBUG);
1691
1692
                    $nowHoliday = $userCounter['nb_holiday'];
1693
                    $newSolde = $nowHoliday + $nbDaysToAdd;
1694
1695
                    // We add a log for each user
1696
                    $this->addLogCP($user->id, $userCounter['rowid'], $langs->trans('HolidaysMonthlyUpdate'), $newSolde, $userCounter['type']);
1697
1698
                    $result = $this->updateSoldeCP($userCounter['rowid'], $newSolde, $userCounter['type']);
1699
1700
                    if ($result < 0) {
1701
                        $error++;
1702
                        break;
1703
                    }
1704
                }
1705
1706
                if (!$error) {
1707
                    $this->db->commit();
1708
                    return 1;
1709
                } else {
1710
                    $this->db->rollback();
1711
                    return -1;
1712
                }
1713
            }
1714
1715
            return 0;
1716
        } else {
1717
            // Mise à jour pour un utilisateur
1718
            $nbHoliday = price2num($nbHoliday, 5);
1719
1720
            $sql = "SELECT nb_holiday FROM " . MAIN_DB_PREFIX . "holiday_users";
1721
            $sql .= " WHERE fk_user = " . (int) $userID . " AND fk_type = " . (int) $fk_type;
1722
            $resql = $this->db->query($sql);
1723
            if ($resql) {
1724
                $num = $this->db->num_rows($resql);
1725
1726
                if ($num > 0) {
1727
                    // Update for user
1728
                    $sql = "UPDATE " . MAIN_DB_PREFIX . "holiday_users SET";
1729
                    $sql .= " nb_holiday = " . ((float) $nbHoliday);
1730
                    $sql .= " WHERE fk_user = " . (int) $userID . " AND fk_type = " . (int) $fk_type;
1731
                    $result = $this->db->query($sql);
1732
                    if (!$result) {
1733
                        $error++;
1734
                        $this->errors[] = $this->db->lasterror();
1735
                    }
1736
                } else {
1737
                    // Insert for user
1738
                    $sql = "INSERT INTO " . MAIN_DB_PREFIX . "holiday_users(nb_holiday, fk_user, fk_type) VALUES (";
1739
                    $sql .= ((float) $nbHoliday);
1740
                    $sql .= ", " . (int) $userID . ", " . (int) $fk_type . ")";
1741
                    $result = $this->db->query($sql);
1742
                    if (!$result) {
1743
                        $error++;
1744
                        $this->errors[] = $this->db->lasterror();
1745
                    }
1746
                }
1747
            } else {
1748
                $this->errors[] = $this->db->lasterror();
1749
                $error++;
1750
            }
1751
1752
            if (!$error) {
1753
                return 1;
1754
            } else {
1755
                return -1;
1756
            }
1757
        }
1758
    }
1759
1760
    /**
1761
     *  Create entries for each user at setup step
1762
     *
1763
     *  @param  boolean     $single     Single
1764
     *  @param  int         $userid     Id user
1765
     *  @return void
1766
     */
1767
    public function createCPusers($single = false, $userid = 0)
1768
    {
1769
        // do we have to add balance for all users ?
1770
        if (!$single) {
1771
            dol_syslog(get_class($this) . '::createCPusers');
1772
            $arrayofusers = $this->fetchUsers(false, true);
1773
1774
            foreach ($arrayofusers as $users) {
1775
                $sql = "INSERT INTO " . MAIN_DB_PREFIX . "holiday_users";
1776
                $sql .= " (fk_user, nb_holiday)";
1777
                $sql .= " VALUES (" . ((int) $users['rowid']) . "', '0')";
1778
1779
                $resql = $this->db->query($sql);
1780
                if (!$resql) {
1781
                    dol_print_error($this->db);
1782
                }
1783
            }
1784
        } else {
1785
            $sql = "INSERT INTO " . MAIN_DB_PREFIX . "holiday_users";
1786
            $sql .= " (fk_user, nb_holiday)";
1787
            $sql .= " VALUES (" . ((int) $userid) . "', '0')";
1788
1789
            $resql = $this->db->query($sql);
1790
            if (!$resql) {
1791
                dol_print_error($this->db);
1792
            }
1793
        }
1794
    }
1795
1796
    /**
1797
     *  Return the balance of annual leave of a user
1798
     *
1799
     *  @param  int     $user_id    User ID
1800
     *  @param  int     $fk_type    Filter on type
1801
     *  @return float|null          Balance of annual leave if OK, null if KO.
1802
     */
1803
    public function getCPforUser($user_id, $fk_type = 0)
1804
    {
1805
        $sql = "SELECT nb_holiday";
1806
        $sql .= " FROM " . MAIN_DB_PREFIX . "holiday_users";
1807
        $sql .= " WHERE fk_user = " . (int) $user_id;
1808
        if ($fk_type > 0) {
1809
            $sql .= " AND fk_type = " . (int) $fk_type;
1810
        }
1811
1812
        dol_syslog(get_class($this) . '::getCPforUser user_id=' . $user_id . ' type_id=' . $fk_type, LOG_DEBUG);
1813
        $result = $this->db->query($sql);
1814
        if ($result) {
1815
            $obj = $this->db->fetch_object($result);
1816
            //return number_format($obj->nb_holiday,2);
1817
            if ($obj) {
1818
                return $obj->nb_holiday;
1819
            } else {
1820
                return null;
1821
            }
1822
        } else {
1823
            return null;
1824
        }
1825
    }
1826
1827
    /**
1828
     *    Get list of Users or list of vacation balance.
1829
     *
1830
     *    @param      boolean           $stringlist     If true return a string list of id. If false, return an array with detail.
1831
     *    @param      boolean           $type           If true, read Dolibarr user list, if false, return vacation balance list.
1832
     *    @param      string            $filters        Filters. Warning: This must not contains data from user input.
1833
     *    @return     array|string|int                  Return an array
1834
     */
1835
    public function fetchUsers($stringlist = true, $type = true, $filters = '')
1836
    {
1837
        global $conf;
1838
1839
        dol_syslog(get_class($this) . "::fetchUsers", LOG_DEBUG);
1840
1841
        if ($stringlist) {
1842
            if ($type) {
1843
                // If user of Dolibarr
1844
                $sql = "SELECT";
1845
                if (isModEnabled('multicompany') && getDolGlobalString('MULTICOMPANY_TRANSVERSE_MODE')) {
1846
                    $sql .= " DISTINCT";
1847
                }
1848
                $sql .= " u.rowid";
1849
                $sql .= " FROM " . MAIN_DB_PREFIX . "user as u";
1850
1851
                if (isModEnabled('multicompany') && getDolGlobalString('MULTICOMPANY_TRANSVERSE_MODE')) {
1852
                    $sql .= ", " . MAIN_DB_PREFIX . "usergroup_user as ug";
1853
                    $sql .= " WHERE ((ug.fk_user = u.rowid";
1854
                    $sql .= " AND ug.entity IN (" . getEntity('usergroup') . "))";
1855
                    $sql .= " OR u.entity = 0)"; // Show always superadmin
1856
                } else {
1857
                    $sql .= " WHERE u.entity IN (" . getEntity('user') . ")";
1858
                }
1859
                $sql .= " AND u.statut > 0";
1860
                $sql .= " AND u.employee = 1"; // We only want employee users for holidays
1861
                if ($filters) {
1862
                    $sql .= $filters;
1863
                }
1864
1865
                $resql = $this->db->query($sql);
1866
1867
                // Si pas d'erreur SQL
1868
                if ($resql) {
1869
                    $i = 0;
1870
                    $num = $this->db->num_rows($resql);
1871
                    $stringlist = '';
1872
1873
                    // Boucles du listage des utilisateurs
1874
                    while ($i < $num) {
1875
                        $obj = $this->db->fetch_object($resql);
1876
1877
                        if ($i == 0) {
1878
                            $stringlist .= $obj->rowid;
1879
                        } else {
1880
                            $stringlist .= ', ' . $obj->rowid;
1881
                        }
1882
1883
                        $i++;
1884
                    }
1885
                    // Retoune le tableau des utilisateurs
1886
                    return $stringlist;
1887
                } else {
1888
                    // Erreur SQL
1889
                    $this->error = "Error " . $this->db->lasterror();
1890
                    return -1;
1891
                }
1892
            } else {
1893
                // We want only list of vacation balance for user ids
1894
                $sql = "SELECT DISTINCT cpu.fk_user";
1895
                $sql .= " FROM " . MAIN_DB_PREFIX . "holiday_users as cpu, " . MAIN_DB_PREFIX . "user as u";
1896
                $sql .= " WHERE cpu.fk_user = u.rowid";
1897
                if ($filters) {
1898
                    $sql .= $filters;
1899
                }
1900
1901
                $resql = $this->db->query($sql);
1902
1903
                // Si pas d'erreur SQL
1904
                if ($resql) {
1905
                    $i = 0;
1906
                    $num = $this->db->num_rows($resql);
1907
                    $stringlist = '';
1908
1909
                    // Boucles du listage des utilisateurs
1910
                    while ($i < $num) {
1911
                        $obj = $this->db->fetch_object($resql);
1912
1913
                        if ($i == 0) {
1914
                            $stringlist .= $obj->fk_user;
1915
                        } else {
1916
                            $stringlist .= ', ' . $obj->fk_user;
1917
                        }
1918
1919
                        $i++;
1920
                    }
1921
                    // Retoune le tableau des utilisateurs
1922
                    return $stringlist;
1923
                } else {
1924
                    // Erreur SQL
1925
                    $this->error = "Error " . $this->db->lasterror();
1926
                    return -1;
1927
                }
1928
            }
1929
        } else {
1930
            // Si faux donc return array
1931
            // List for Dolibarr users
1932
            if ($type) {
1933
                // If we need users of Dolibarr
1934
                $sql = "SELECT";
1935
                if (isModEnabled('multicompany') && getDolGlobalString('MULTICOMPANY_TRANSVERSE_MODE')) {
1936
                    $sql .= " DISTINCT";
1937
                }
1938
                $sql .= " u.rowid, u.lastname, u.firstname, u.gender, u.photo, u.employee, u.statut as status, u.fk_user";
1939
                $sql .= " FROM " . MAIN_DB_PREFIX . "user as u";
1940
1941
                if (isModEnabled('multicompany') && getDolGlobalString('MULTICOMPANY_TRANSVERSE_MODE')) {
1942
                    $sql .= ", " . MAIN_DB_PREFIX . "usergroup_user as ug";
1943
                    $sql .= " WHERE ((ug.fk_user = u.rowid";
1944
                    $sql .= " AND ug.entity IN (" . getEntity('usergroup') . "))";
1945
                    $sql .= " OR u.entity = 0)"; // Show always superadmin
1946
                } else {
1947
                    $sql .= " WHERE u.entity IN (" . getEntity('user') . ")";
1948
                }
1949
1950
                $sql .= " AND u.statut > 0";
1951
                $sql .= " AND u.employee = 1"; // We only want employee users for holidays
1952
                if ($filters) {
1953
                    $sql .= $filters;
1954
                }
1955
1956
                $resql = $this->db->query($sql);
1957
1958
                // Si pas d'erreur SQL
1959
                if ($resql) {
1960
                    $i = 0;
1961
                    $tab_result = $this->holiday;
1962
                    $num = $this->db->num_rows($resql);
1963
1964
                    // Boucles du listage des utilisateurs
1965
                    while ($i < $num) {
1966
                        $obj = $this->db->fetch_object($resql);
1967
1968
                        $tab_result[$i]['rowid'] = $obj->rowid; // rowid of user
1969
                        $tab_result[$i]['id'] = $obj->rowid; // id of user
1970
                        $tab_result[$i]['name'] = $obj->lastname; // deprecated
1971
                        $tab_result[$i]['lastname'] = $obj->lastname;
1972
                        $tab_result[$i]['firstname'] = $obj->firstname;
1973
                        $tab_result[$i]['gender'] = $obj->gender;
1974
                        $tab_result[$i]['status'] = $obj->status;
1975
                        $tab_result[$i]['employee'] = $obj->employee;
1976
                        $tab_result[$i]['photo'] = $obj->photo;
1977
                        $tab_result[$i]['fk_user'] = $obj->fk_user; // rowid of manager
1978
                        //$tab_result[$i]['type'] = $obj->type;
1979
                        //$tab_result[$i]['nb_holiday'] = $obj->nb_holiday;
1980
1981
                        $i++;
1982
                    }
1983
                    // Retoune le tableau des utilisateurs
1984
                    return $tab_result;
1985
                } else {
1986
                    // Erreur SQL
1987
                    $this->errors[] = "Error " . $this->db->lasterror();
1988
                    return -1;
1989
                }
1990
            } else {
1991
                // List of vacation balance users
1992
                $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";
1993
                $sql .= " FROM " . MAIN_DB_PREFIX . "holiday_users as cpu, " . MAIN_DB_PREFIX . "user as u";
1994
                $sql .= " WHERE cpu.fk_user = u.rowid";
1995
                if ($filters) {
1996
                    $sql .= $filters;
1997
                }
1998
1999
                $resql = $this->db->query($sql);
2000
2001
                // Si pas d'erreur SQL
2002
                if ($resql) {
2003
                    $i = 0;
2004
                    $tab_result = $this->holiday;
2005
                    $num = $this->db->num_rows($resql);
2006
2007
                    // Boucles du listage des utilisateurs
2008
                    while ($i < $num) {
2009
                        $obj = $this->db->fetch_object($resql);
2010
2011
                        $tab_result[$i]['rowid'] = $obj->rowid; // rowid of user
2012
                        $tab_result[$i]['id'] = $obj->rowid; // id of user
2013
                        $tab_result[$i]['name'] = $obj->lastname; // deprecated
2014
                        $tab_result[$i]['lastname'] = $obj->lastname;
2015
                        $tab_result[$i]['firstname'] = $obj->firstname;
2016
                        $tab_result[$i]['gender'] = $obj->gender;
2017
                        $tab_result[$i]['status'] = $obj->status;
2018
                        $tab_result[$i]['employee'] = $obj->employee;
2019
                        $tab_result[$i]['photo'] = $obj->photo;
2020
                        $tab_result[$i]['fk_user'] = $obj->fk_user; // rowid of manager
2021
2022
                        $tab_result[$i]['type'] = $obj->fk_type;
2023
                        $tab_result[$i]['nb_holiday'] = $obj->nb_holiday;
2024
2025
                        $i++;
2026
                    }
2027
                    // Retoune le tableau des utilisateurs
2028
                    return $tab_result;
2029
                } else {
2030
                    // Erreur SQL
2031
                    $this->error = "Error " . $this->db->lasterror();
2032
                    return -1;
2033
                }
2034
            }
2035
        }
2036
    }
2037
2038
2039
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2040
    /**
2041
     * Return list of people with permission to validate leave requests.
2042
     * Search for permission "approve leave requests"
2043
     *
2044
     * @return  array|int       Array of user ids or -1 if error
2045
     */
2046
    public function fetch_users_approver_holiday()
2047
    {
2048
		// phpcs:enable
2049
        $users_validator = array();
2050
2051
        $sql = "SELECT DISTINCT ur.fk_user";
2052
        $sql .= " FROM " . MAIN_DB_PREFIX . "user_rights as ur, " . MAIN_DB_PREFIX . "rights_def as rd";
2053
        $sql .= " WHERE ur.fk_id = rd.id and rd.module = 'holiday' AND rd.perms = 'approve'"; // Permission 'Approve';
2054
        $sql .= "UNION";
2055
        $sql .= " SELECT DISTINCT ugu.fk_user";
2056
        $sql .= " FROM " . MAIN_DB_PREFIX . "usergroup_user as ugu, " . MAIN_DB_PREFIX . "usergroup_rights as ur, " . MAIN_DB_PREFIX . "rights_def as rd";
2057
        $sql .= " WHERE ugu.fk_usergroup = ur.fk_usergroup AND ur.fk_id = rd.id and rd.module = 'holiday' AND rd.perms = 'approve'"; // Permission 'Approve';
2058
        //print $sql;
2059
2060
        dol_syslog(get_class($this) . "::fetch_users_approver_holiday sql=" . $sql);
2061
        $result = $this->db->query($sql);
2062
        if ($result) {
2063
            $num_rows = $this->db->num_rows($result);
2064
            $i = 0;
2065
            while ($i < $num_rows) {
2066
                $objp = $this->db->fetch_object($result);
2067
                array_push($users_validator, $objp->fk_user);
2068
                $i++;
2069
            }
2070
            return $users_validator;
2071
        } else {
2072
            $this->error = $this->db->lasterror();
2073
            dol_syslog(get_class($this) . "::fetch_users_approver_holiday  Error " . $this->error, LOG_ERR);
2074
            return -1;
2075
        }
2076
    }
2077
2078
2079
    /**
2080
     *  Compte le nombre d'utilisateur actifs dans Dolibarr
2081
     *
2082
     *  @return     int      retourne le nombre d'utilisateur
2083
     */
2084
    public function countActiveUsers()
2085
    {
2086
        $sql = "SELECT count(u.rowid) as compteur";
2087
        $sql .= " FROM " . MAIN_DB_PREFIX . "user as u";
2088
        $sql .= " WHERE u.statut > 0";
2089
2090
        $result = $this->db->query($sql);
2091
        $object = $this->db->fetch_object($result);
2092
2093
        return $object->compteur;
2094
    }
2095
    /**
2096
     *  Compte le nombre d'utilisateur actifs dans Dolibarr sans CP
2097
     *
2098
     *  @return     int      retourne le nombre d'utilisateur
2099
     */
2100
    public function countActiveUsersWithoutCP()
2101
    {
2102
        $sql = "SELECT count(u.rowid) as compteur";
2103
        $sql .= " FROM " . MAIN_DB_PREFIX . "user as u LEFT OUTER JOIN " . MAIN_DB_PREFIX . "holiday_users hu ON (hu.fk_user=u.rowid)";
2104
        $sql .= " WHERE u.statut > 0 AND hu.fk_user IS NULL";
2105
2106
        $result = $this->db->query($sql);
2107
        $object = $this->db->fetch_object($result);
2108
2109
        return $object->compteur;
2110
    }
2111
2112
    /**
2113
     *  Compare le nombre d'utilisateur actif de Dolibarr à celui des utilisateurs des congés payés
2114
     *
2115
     *  @param    int   $userDolibarrWithoutCP  Number of active users in Dolibarr without holidays
2116
     *  @param    int   $userCP                 Number of active users into table of holidays
2117
     *  @return   int                           Return integer <0 if KO, >0 if OK
2118
     */
2119
    public function verifNbUsers($userDolibarrWithoutCP, $userCP)
2120
    {
2121
        if (empty($userCP)) {
2122
            $userCP = 0;
2123
        }
2124
        dol_syslog(get_class($this) . '::verifNbUsers userDolibarr=' . $userDolibarrWithoutCP . ' userCP=' . $userCP);
2125
        return 1;
2126
    }
2127
2128
2129
    /**
2130
     * addLogCP
2131
     *
2132
     * @param   int     $fk_user_action     Id user creation
2133
     * @param   int     $fk_user_update     Id user update
2134
     * @param   string  $label              Label (Example: 'Leave', 'Manual update', 'Leave request cancelation'...)
2135
     * @param   int     $new_solde          New value
2136
     * @param   int     $fk_type            Type of vacation
2137
     * @return  int                         Id of record added, 0 if nothing done, < 0 if KO
2138
     */
2139
    public function addLogCP($fk_user_action, $fk_user_update, $label, $new_solde, $fk_type)
2140
    {
2141
        global $conf, $langs;
2142
2143
        $error = 0;
2144
2145
        $prev_solde = price2num($this->getCPforUser($fk_user_update, $fk_type), 5);
2146
        $new_solde = price2num($new_solde, 5);
2147
        //print "$prev_solde == $new_solde";
2148
2149
        if ($prev_solde == $new_solde) {
2150
            return 0;
2151
        }
2152
2153
        $this->db->begin();
2154
2155
        // Insert request
2156
        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "holiday_logs (";
2157
        $sql .= "date_action,";
2158
        $sql .= "fk_user_action,";
2159
        $sql .= "fk_user_update,";
2160
        $sql .= "type_action,";
2161
        $sql .= "prev_solde,";
2162
        $sql .= "new_solde,";
2163
        $sql .= "fk_type";
2164
        $sql .= ") VALUES (";
2165
        $sql .= " '" . $this->db->idate(dol_now()) . "',";
2166
        $sql .= " " . ((int) $fk_user_action) . ",";
2167
        $sql .= " " . ((int) $fk_user_update) . ",";
2168
        $sql .= " '" . $this->db->escape($label) . "',";
2169
        $sql .= " " . ((float) $prev_solde) . ",";
2170
        $sql .= " " . ((float) $new_solde) . ",";
2171
        $sql .= " " . ((int) $fk_type);
2172
        $sql .= ")";
2173
2174
        $resql = $this->db->query($sql);
2175
        if (!$resql) {
2176
            $error++;
2177
            $this->errors[] = "Error " . $this->db->lasterror();
2178
        }
2179
2180
        if (!$error) {
2181
            $this->optRowid = $this->db->last_insert_id(MAIN_DB_PREFIX . "holiday_logs");
2182
        }
2183
2184
        // Commit or rollback
2185
        if ($error) {
2186
            foreach ($this->errors as $errmsg) {
2187
                dol_syslog(get_class($this) . "::addLogCP " . $errmsg, LOG_ERR);
2188
                $this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
2189
            }
2190
            $this->db->rollback();
2191
            return -1 * $error;
2192
        } else {
2193
            $this->db->commit();
2194
            return $this->optRowid;
2195
        }
2196
    }
2197
2198
    /**
2199
     *  Liste le log des congés payés
2200
     *
2201
     *  @param  string  $order      Filtrage par ordre
2202
     *  @param  string  $filter     Filtre de séléction
2203
     *  @return int                 -1 si erreur, 1 si OK et 2 si pas de résultat
2204
     */
2205
    public function fetchLog($order, $filter)
2206
    {
2207
        $sql = "SELECT";
2208
        $sql .= " cpl.rowid,";
2209
        $sql .= " cpl.date_action,";
2210
        $sql .= " cpl.fk_user_action,";
2211
        $sql .= " cpl.fk_user_update,";
2212
        $sql .= " cpl.type_action,";
2213
        $sql .= " cpl.prev_solde,";
2214
        $sql .= " cpl.new_solde,";
2215
        $sql .= " cpl.fk_type";
2216
        $sql .= " FROM " . MAIN_DB_PREFIX . "holiday_logs as cpl";
2217
        $sql .= " WHERE cpl.rowid > 0"; // To avoid error with other search and criteria
2218
2219
        // Filtrage de séléction
2220
        if (!empty($filter)) {
2221
            $sql .= " " . $filter;
2222
        }
2223
2224
        // Ordre d'affichage
2225
        if (!empty($order)) {
2226
            $sql .= " " . $order;
2227
        }
2228
2229
        dol_syslog(get_class($this) . "::fetchLog", LOG_DEBUG);
2230
        $resql = $this->db->query($sql);
2231
2232
        // Si pas d'erreur SQL
2233
        if ($resql) {
2234
            $i = 0;
2235
            $tab_result = $this->logs;
2236
            $num = $this->db->num_rows($resql);
2237
2238
            // Si pas d'enregistrement
2239
            if (!$num) {
2240
                return 2;
2241
            }
2242
2243
            // On liste les résultats et on les ajoutent dans le tableau
2244
            while ($i < $num) {
2245
                $obj = $this->db->fetch_object($resql);
2246
2247
                $tab_result[$i]['rowid'] = $obj->rowid;
2248
                $tab_result[$i]['id'] = $obj->rowid;
2249
                $tab_result[$i]['date_action'] = $obj->date_action;
2250
                $tab_result[$i]['fk_user_action'] = $obj->fk_user_action;
2251
                $tab_result[$i]['fk_user_update'] = $obj->fk_user_update;
2252
                $tab_result[$i]['type_action'] = $obj->type_action;
2253
                $tab_result[$i]['prev_solde'] = $obj->prev_solde;
2254
                $tab_result[$i]['new_solde'] = $obj->new_solde;
2255
                $tab_result[$i]['fk_type'] = $obj->fk_type;
2256
2257
                $i++;
2258
            }
2259
            // Retourne 1 et ajoute le tableau à la variable
2260
            $this->logs = $tab_result;
2261
            return 1;
2262
        } else {
2263
            // Erreur SQL
2264
            $this->error = "Error " . $this->db->lasterror();
2265
            return -1;
2266
        }
2267
    }
2268
2269
2270
    /**
2271
     *  Return array with list of types
2272
     *
2273
     *  @param      int     $active     Status of type. -1 = Both
2274
     *  @param      int     $affect     Filter on affect (a request will change sold or not). -1 = Both
2275
     *  @return     array               Return array with list of types
2276
     */
2277
    public function getTypes($active = -1, $affect = -1)
2278
    {
2279
        global $mysoc;
2280
2281
        $sql = "SELECT rowid, code, label, affect, delay, newbymonth";
2282
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_holiday_types";
2283
        $sql .= " WHERE (fk_country IS NULL OR fk_country = " . ((int) $mysoc->country_id) . ')';
2284
        if ($active >= 0) {
2285
            $sql .= " AND active = " . ((int) $active);
2286
        }
2287
        if ($affect >= 0) {
2288
            $sql .= " AND affect = " . ((int) $affect);
2289
        }
2290
        $sql .= " ORDER BY sortorder";
2291
2292
        $result = $this->db->query($sql);
2293
        if ($result) {
2294
            $num = $this->db->num_rows($result);
2295
            if ($num) {
2296
                $types = array();
2297
                while ($obj = $this->db->fetch_object($result)) {
2298
                    $types[$obj->rowid] = array('id' => $obj->rowid, 'rowid' => $obj->rowid, 'code' => $obj->code, 'label' => $obj->label, 'affect' => $obj->affect, 'delay' => $obj->delay, 'newbymonth' => $obj->newbymonth);
2299
                }
2300
2301
                return $types;
2302
            }
2303
        } else {
2304
            dol_print_error($this->db);
2305
        }
2306
2307
        return array();
2308
    }
2309
2310
2311
    /**
2312
     *  Load information on object
2313
     *
2314
     *  @param  int     $id      Id of object
2315
     *  @return void
2316
     */
2317
    public function info($id)
2318
    {
2319
        global $conf;
2320
2321
        $sql = "SELECT f.rowid, f.statut as status,";
2322
        $sql .= " f.date_create as datec,";
2323
        $sql .= " f.tms as date_modification,";
2324
        $sql .= " f.date_valid as datev,";
2325
        $sql .= " f.date_approval as datea,";
2326
        $sql .= " f.date_refuse as dater,";
2327
        $sql .= " f.fk_user_create as fk_user_creation,";
2328
        $sql .= " f.fk_user_modif as fk_user_modification,";
2329
        $sql .= " f.fk_user_valid as fk_user_validation,";
2330
        $sql .= " f.fk_user_approve as fk_user_approval_done,";
2331
        $sql .= " f.fk_validator as fk_user_approval_expected,";
2332
        $sql .= " f.fk_user_refuse as fk_user_refuse";
2333
        $sql .= " FROM " . MAIN_DB_PREFIX . "holiday as f";
2334
        $sql .= " WHERE f.rowid = " . ((int) $id);
2335
        $sql .= " AND f.entity = " . $conf->entity;
2336
2337
        $resql = $this->db->query($sql);
2338
        if ($resql) {
2339
            if ($this->db->num_rows($resql)) {
2340
                $obj = $this->db->fetch_object($resql);
2341
2342
                $this->id = $obj->rowid;
2343
2344
                $this->date_creation = $this->db->jdate($obj->datec);
2345
                $this->date_modification = $this->db->jdate($obj->date_modification);
2346
                $this->date_validation = $this->db->jdate($obj->datev);
2347
                $this->date_approval = $this->db->jdate($obj->datea);
2348
2349
                $this->user_creation_id = $obj->fk_user_creation;
2350
                $this->user_validation_id = $obj->fk_user_validation;
2351
                $this->user_modification_id = $obj->fk_user_modification;
2352
2353
                if ($obj->status == Holiday::STATUS_APPROVED || $obj->status == Holiday::STATUS_CANCELED) {
2354
                    if ($obj->fk_user_approval_done) {
2355
                        $this->fk_user_approve = $obj->fk_user_approval_done;
2356
                    }
2357
                }
2358
            }
2359
            $this->db->free($resql);
2360
        } else {
2361
            dol_print_error($this->db);
2362
        }
2363
    }
2364
2365
2366
    /**
2367
     *  Initialise an instance with random values.
2368
     *  Used to build previews or test instances.
2369
     *  id must be 0 if object instance is a specimen.
2370
     *
2371
     *  @return int
2372
     */
2373
    public function initAsSpecimen()
2374
    {
2375
        global $user, $langs;
2376
2377
        // Initialise parameters
2378
        $this->id = 0;
2379
        $this->specimen = 1;
2380
2381
        $this->fk_user = $user->id;
2382
        $this->description = 'SPECIMEN description';
2383
        $this->date_debut = dol_now();
2384
        $this->date_fin = dol_now() + (24 * 3600);
2385
        $this->date_valid = dol_now();
2386
        $this->fk_validator = $user->id;
2387
        $this->halfday = 0;
2388
        $this->fk_type = 1;
2389
        $this->status = Holiday::STATUS_VALIDATED;
2390
2391
        return 1;
2392
    }
2393
2394
    /**
2395
     *      Load this->nb for dashboard
2396
     *
2397
     *      @return     int         Return integer <0 if KO, >0 if OK
2398
     */
2399
    public function loadStateBoard()
2400
    {
2401
        global $user;
2402
2403
        $this->nb = array();
2404
2405
        $sql = "SELECT count(h.rowid) as nb";
2406
        $sql .= " FROM " . MAIN_DB_PREFIX . "holiday as h";
2407
        $sql .= " WHERE h.statut > 1";
2408
        $sql .= " AND h.entity IN (" . getEntity('holiday') . ")";
2409
        if (!$user->hasRight('expensereport', 'readall')) {
2410
            $userchildids = $user->getAllChildIds(1);
2411
            $sql .= " AND (h.fk_user IN (" . $this->db->sanitize(implode(',', $userchildids)) . ")";
2412
            $sql .= " OR h.fk_validator IN (" . $this->db->sanitize(implode(',', $userchildids)) . "))";
2413
        }
2414
2415
        $resql = $this->db->query($sql);
2416
        if ($resql) {
2417
            while ($obj = $this->db->fetch_object($resql)) {
2418
                $this->nb["holidays"] = $obj->nb;
2419
            }
2420
            $this->db->free($resql);
2421
            return 1;
2422
        } else {
2423
            dol_print_error($this->db);
2424
            $this->error = $this->db->error();
2425
            return -1;
2426
        }
2427
    }
2428
2429
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2430
    /**
2431
     *      Load indicators for dashboard (this->nbtodo and this->nbtodolate)
2432
     *
2433
     *      @param  User    $user           Object user
2434
     *      @return WorkboardResponse|int   Return integer <0 if KO, WorkboardResponse if OK
2435
     */
2436
    public function load_board($user)
2437
    {
2438
		// phpcs:enable
2439
        global $conf, $langs;
2440
2441
        if ($user->socid) {
2442
            return -1; // protection pour eviter appel par utilisateur externe
2443
        }
2444
2445
        $now = dol_now();
2446
2447
        $sql = "SELECT h.rowid, h.date_debut";
2448
        $sql .= " FROM " . MAIN_DB_PREFIX . "holiday as h";
2449
        $sql .= " WHERE h.statut = 2";
2450
        $sql .= " AND h.entity IN (" . getEntity('holiday') . ")";
2451
        if (!$user->hasRight('expensereport', 'read_all')) {
2452
            $userchildids = $user->getAllChildIds(1);
2453
            $sql .= " AND (h.fk_user IN (" . $this->db->sanitize(implode(',', $userchildids)) . ")";
2454
            $sql .= " OR h.fk_validator IN (" . $this->db->sanitize(implode(',', $userchildids)) . "))";
2455
        }
2456
2457
        $resql = $this->db->query($sql);
2458
        if ($resql) {
2459
            $langs->load("members");
2460
2461
            $response = new WorkboardResponse();
2462
            $response->warning_delay = $conf->holiday->approve->warning_delay / 60 / 60 / 24;
2463
            $response->label = $langs->trans("HolidaysToApprove");
2464
            $response->labelShort = $langs->trans("ToApprove");
2465
            $response->url = constant('BASE_URL') . '/holiday/list.php?search_status=2&amp;mainmenu=hrm&amp;leftmenu=holiday';
2466
            $response->img = img_object('', "holiday");
2467
2468
            while ($obj = $this->db->fetch_object($resql)) {
2469
                $response->nbtodo++;
2470
2471
                if ($this->db->jdate($obj->date_debut) < ($now - $conf->holiday->approve->warning_delay)) {
2472
                    $response->nbtodolate++;
2473
                }
2474
            }
2475
2476
            return $response;
2477
        } else {
2478
            dol_print_error($this->db);
2479
            $this->error = $this->db->error();
2480
            return -1;
2481
        }
2482
    }
2483
    /**
2484
     *  Return clicable link of object (with eventually picto)
2485
     *
2486
     *  @param      string      $option                 Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link)
2487
     *  @param      array       $arraydata              Label of holiday type (if known)
2488
     *  @return     string      HTML Code for Kanban thumb.
2489
     */
2490
    public function getKanbanView($option = '', $arraydata = null)
2491
    {
2492
        global $langs;
2493
2494
        $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
2495
2496
        $return = '<div class="box-flex-item box-flex-grow-zero">';
2497
        $return .= '<div class="info-box info-box-sm">';
2498
        $return .= '<span class="info-box-icon bg-infobox-action">';
2499
        $return .= img_picto('', $this->picto);
2500
        $return .= '</span>';
2501
        $return .= '<div class="info-box-content">';
2502
        $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . $arraydata['user']->getNomUrl(-1) . '</span>';
2503
        if ($selected >= 0) {
2504
            $return .= '<input id="cb' . $this->id . '" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="' . $this->id . '"' . ($selected ? ' checked="checked"' : '') . '>';
2505
        }
2506
        if (property_exists($this, 'fk_type')) {
2507
            $return .= '<br>';
2508
            //$return .= '<span class="opacitymedium">'.$langs->trans("Type").'</span> : ';
2509
            $return .= '<div class="info_box-label tdoverflowmax100" title="' . dol_escape_htmltag($arraydata['labeltype']) . '">' . dol_escape_htmltag($arraydata['labeltype']) . '</div>';
2510
        }
2511
        if (property_exists($this, 'date_debut') && property_exists($this, 'date_fin')) {
2512
            $return .= '<span class="info-box-label small">' . dol_print_date($this->date_debut, 'day') . '</span>';
2513
            $return .= ' <span class="opacitymedium small">' . $langs->trans("To") . '</span> ';
2514
            $return .= '<span class="info-box-label small">' . dol_print_date($this->date_fin, 'day') . '</span>';
2515
            if (!empty($arraydata['nbopenedday'])) {
2516
                $return .= ' (' . $arraydata['nbopenedday'] . ')';
2517
            }
2518
        }
2519
        if (method_exists($this, 'getLibStatut')) {
2520
            $return .= '<div class="info-box-status">' . $this->getLibStatut(3) . '</div>';
2521
        }
2522
        $return .= '</div>';
2523
        $return .= '</div>';
2524
        $return .= '</div>';
2525
        return $return;
2526
    }
2527
}
2528