Holiday::getNextNumRef()   B
last analyzed

Complexity

Conditions 7
Paths 20

Size

Total Lines 42
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 25
nc 20
nop 1
dl 0
loc 42
rs 8.5866
c 0
b 0
f 0
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\Code\Core\Classes\WorkboardResponse;
29
use Dolibarr\Core\Base\CommonObject;
30
use DoliDB;
31
32
/**
33
 *    \file       holiday.class.php
34
 *    \ingroup    holiday
35
 *    \brief      Class file of the module paid holiday.
36
 */
37
38
/**
39
 *  Class of the module paid holiday. Developed by Teclib ( http://www.teclib.com/ )
40
 */
41
class Holiday extends CommonObject
42
{
43
    /**
44
     * @var string ID to identify managed object
45
     */
46
    public $element = 'holiday';
47
48
    /**
49
     * @var string Name of table without prefix where object is stored
50
     */
51
    public $table_element = 'holiday';
52
53
    /**
54
     * @var string Field with ID of parent key if this field has a parent
55
     */
56
    public $fk_element = 'fk_holiday';
57
58
    /**
59
     * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
60
     */
61
    public $picto = 'holiday';
62
63
    /**
64
     * @var int User ID
65
     */
66
    public $fk_user;
67
68
    public $date_create = '';
69
70
    /**
71
     * @var string description
72
     */
73
    public $description;
74
75
    /**
76
     * @var int|string Date start in PHP server TZ
77
     */
78
    public $date_debut = '';
79
80
    /**
81
     * @var int|string Date end in PHP server TZ
82
     */
83
    public $date_fin = '';
84
85
    /**
86
     * @var int|string Date start in GMT
87
     */
88
    public $date_debut_gmt = '';
89
90
    /**
91
     * @var int|string Date end in GMT
92
     */
93
    public $date_fin_gmt = '';
94
95
    /**
96
     * @var int|string 0:Full days, 2:Start afternoon end morning, -1:Start afternoon end afternoon, 1:Start morning end morning
97
     */
98
    public $halfday = '';
99
100
    /**
101
     * @var int Status 1=draft, 2=validated, 3=approved, 4 canceled, 5 refused
102
     * @deprecated
103
     */
104
    public $statut = 0;
105
106
    /**
107
     * @var int     ID of user that must approve. Real user for approval is fk_user_valid (old version) or fk_user_approve (new versions)
108
     */
109
    public $fk_validator;
110
111
    /**
112
     * @var int     Date of validation or approval. TODO: Use date_valid instead for validation.
113
     */
114
    public $date_valid = 0;
115
116
    /**
117
     * @var int     ID of user that has validated
118
     */
119
    public $fk_user_valid;
120
121
    /**
122
     * @var int     Date approval
123
     */
124
    public $date_approval;
125
126
    /**
127
     * @var int     ID of user that has approved
128
     */
129
    public $fk_user_approve;
130
131
    /**
132
     * @var int     Date for refuse
133
     */
134
    public $date_refuse = 0;
135
136
    /**
137
     * @var int     ID for refuse
138
     */
139
    public $fk_user_refuse;
140
141
    /**
142
     * @var int     Date for cancellation
143
     */
144
    public $date_cancel = 0;
145
146
    /**
147
     * @var int     ID for cancellation
148
     */
149
    public $fk_user_cancel;
150
151
    /**
152
     * @var int     ID for creation
153
     */
154
    public $fk_user_create;
155
156
    /**
157
     * @var string Detail of refuse
158
     */
159
    public $detail_refuse = '';
160
161
    /**
162
     * @var int ID
163
     */
164
    public $fk_type;
165
166
    public $holiday = array();
167
    public $events = array();
168
    public $logs = array();
169
170
    public $optName = '';
171
    public $optValue = '';
172
    public $optRowid = '';
173
174
    /**
175
     * Draft status
176
     */
177
    const STATUS_DRAFT = 1;
178
    /**
179
     * Validated status
180
     */
181
    const STATUS_VALIDATED = 2;
182
    /**
183
     * Approved
184
     */
185
    const STATUS_APPROVED = 3;
186
    /**
187
     * Canceled
188
     */
189
    const STATUS_CANCELED = 4;
190
    /**
191
     * Refused
192
     */
193
    const STATUS_REFUSED = 5;
194
195
196
    /**
197
     *   Constructor
198
     *
199
     *   @param     DoliDB      $db      Database handler
200
     */
201
    public function __construct($db)
202
    {
203
        $this->db = $db;
204
205
        $this->ismultientitymanaged = 0;
206
    }
207
208
209
    /**
210
     *  Returns the reference to the following non used Order depending on the active numbering module
211
     *  defined into HOLIDAY_ADDON
212
     *
213
     *  @param  Societe     $objsoc     third party object
214
     *  @return string                  Holiday free reference
215
     */
216
    public function getNextNumRef($objsoc)
217
    {
218
        global $langs, $conf;
219
        $langs->load("order");
220
221
        if (!getDolGlobalString('HOLIDAY_ADDON')) {
222
            $conf->global->HOLIDAY_ADDON = 'mod_holiday_madonna';
223
        }
224
225
        if (getDolGlobalString('HOLIDAY_ADDON')) {
226
            $mybool = false;
227
228
            $file = getDolGlobalString('HOLIDAY_ADDON') . ".php";
229
            $classname = getDolGlobalString('HOLIDAY_ADDON');
230
231
            // Include file with class
232
            $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
233
            foreach ($dirmodels as $reldir) {
234
                $dir = dol_buildpath($reldir . "core/modules/holiday/");
235
236
                // Load file with numbering class (if found)
237
                $mybool = ((bool) @include_once $dir . $file) || $mybool;
238
            }
239
240
            if ($mybool === false) {
241
                dol_print_error(null, "Failed to include file " . $file);
242
                return '';
243
            }
244
245
            $obj = new $classname();
246
            $numref = $obj->getNextValue($objsoc, $this);
247
248
            if ($numref != "") {
249
                return $numref;
250
            } else {
251
                $this->error = $obj->error;
252
                //dol_print_error($this->db,get_only_class($this)."::getNextNumRef ".$obj->error);
253
                return "";
254
            }
255
        } else {
256
            print $langs->trans("Error") . " " . $langs->trans("Error_HOLIDAY_ADDON_NotDefined");
257
            return "";
258
        }
259
    }
260
261
    /**
262
     * Update balance of vacations and check table of users for holidays is complete. If not complete.
263
     *
264
     * @return  int         Return integer <0 if KO, >0 if OK
265
     */
266
    public function updateBalance()
267
    {
268
        $this->db->begin();
269
270
        // Update sold of vocations
271
        $result = $this->updateSoldeCP();
272
273
        // Check nb of users into table llx_holiday_users and update with empty lines
274
        //if ($result > 0) $result = $this->verifNbUsers($this->countActiveUsersWithoutCP(), $this->getConfCP('nbUser'));
275
276
        if ($result >= 0) {
277
            $this->db->commit();
278
            return 0; // for cronjob use (0 is OK, any other value is an error code)
279
        } else {
280
            $this->db->rollback();
281
            return -1;
282
        }
283
    }
284
285
    /**
286
     *   Créer un congés payés dans la base de données
287
     *
288
     *   @param     User    $user           User that create
289
     *   @param     int     $notrigger      0=launch triggers after, 1=disable triggers
290
     *   @return    int                     Return integer <0 if KO, Id of created object if OK
291
     */
292
    public function create($user, $notrigger = 0)
293
    {
294
        global $conf;
295
        $error = 0;
296
297
        $now = dol_now();
298
299
        // Check parameters
300
        if (empty($this->fk_user) || !is_numeric($this->fk_user) || $this->fk_user < 0) {
301
            $this->error = "ErrorBadParameterFkUser";
302
            return -1;
303
        }
304
        if (empty($this->fk_validator) || !is_numeric($this->fk_validator) || $this->fk_validator < 0) {
305
            $this->error = "ErrorBadParameterFkValidator";
306
            return -1;
307
        }
308
        if (empty($this->fk_type) || !is_numeric($this->fk_type) || $this->fk_type < 0) {
309
            $this->error = "ErrorBadParameterFkType";
310
            return -1;
311
        }
312
313
        // Insert request
314
        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "holiday(";
315
        $sql .= "ref,";
316
        $sql .= "fk_user,";
317
        $sql .= "date_create,";
318
        $sql .= "description,";
319
        $sql .= "date_debut,";
320
        $sql .= "date_fin,";
321
        $sql .= "halfday,";
322
        $sql .= "statut,";
323
        $sql .= "fk_validator,";
324
        $sql .= "fk_type,";
325
        $sql .= "fk_user_create,";
326
        $sql .= "entity";
327
        $sql .= ") VALUES (";
328
        $sql .= "'(PROV)',";
329
        $sql .= " " . ((int) $this->fk_user) . ",";
330
        $sql .= " '" . $this->db->idate($now) . "',";
331
        $sql .= " '" . $this->db->escape($this->description) . "',";
332
        $sql .= " '" . $this->db->idate($this->date_debut) . "',";
333
        $sql .= " '" . $this->db->idate($this->date_fin) . "',";
334
        $sql .= " " . ((int) $this->halfday) . ",";
335
        $sql .= " '1',";
336
        $sql .= " " . ((int) $this->fk_validator) . ",";
337
        $sql .= " " . ((int) $this->fk_type) . ",";
338
        $sql .= " " . ((int) $user->id) . ",";
339
        $sql .= " " . ((int) $conf->entity);
340
        $sql .= ")";
341
342
        $this->db->begin();
343
344
        dol_syslog(get_only_class($this) . "::create", LOG_DEBUG);
345
        $resql = $this->db->query($sql);
346
        if (!$resql) {
347
            $error++;
348
            $this->errors[] = "Error " . $this->db->lasterror();
349
        }
350
351
        if (!$error) {
352
            $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . "holiday");
353
354
            if ($this->id) {
355
                // update ref
356
                $initialref = '(PROV' . $this->id . ')';
357
                if (!empty($this->ref)) {
358
                    $initialref = $this->ref;
359
                }
360
361
                $sql = 'UPDATE ' . MAIN_DB_PREFIX . "holiday SET ref='" . $this->db->escape($initialref) . "' WHERE rowid=" . ((int) $this->id);
362
                if ($this->db->query($sql)) {
363
                    $this->ref = $initialref;
364
365
                    if (!$error) {
366
                        $result = $this->insertExtraFields();
367
                        if ($result < 0) {
368
                            $error++;
369
                        }
370
                    }
371
372
                    if (!$error && !$notrigger) {
373
                        // Call trigger
374
                        $result = $this->call_trigger('HOLIDAY_CREATE', $user);
375
                        if ($result < 0) {
376
                            $error++;
377
                        }
378
                        // End call triggers
379
                    }
380
                }
381
            }
382
        }
383
384
        // Commit or rollback
385
        if ($error) {
386
            foreach ($this->errors as $errmsg) {
387
                dol_syslog(get_only_class($this) . "::create " . $errmsg, LOG_ERR);
388
                $this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
389
            }
390
            $this->db->rollback();
391
            return -1 * $error;
392
        } else {
393
            $this->db->commit();
394
            return $this->id;
395
        }
396
    }
397
398
399
    /**
400
     *  Load object in memory from database
401
     *
402
     *  @param  int     $id         Id object
403
     *  @param  string  $ref        Ref object
404
     *  @return int                 Return integer <0 if KO, 0 if not found, >0 if OK
405
     */
406
    public function fetch($id, $ref = '')
407
    {
408
        $sql = "SELECT";
409
        $sql .= " cp.rowid,";
410
        $sql .= " cp.ref,";
411
        $sql .= " cp.fk_user,";
412
        $sql .= " cp.date_create,";
413
        $sql .= " cp.description,";
414
        $sql .= " cp.date_debut,";
415
        $sql .= " cp.date_fin,";
416
        $sql .= " cp.halfday,";
417
        $sql .= " cp.statut as status,";
418
        $sql .= " cp.fk_validator,";
419
        $sql .= " cp.date_valid,";
420
        $sql .= " cp.fk_user_valid,";
421
        $sql .= " cp.date_approval,";
422
        $sql .= " cp.fk_user_approve,";
423
        $sql .= " cp.date_refuse,";
424
        $sql .= " cp.fk_user_refuse,";
425
        $sql .= " cp.date_cancel,";
426
        $sql .= " cp.fk_user_cancel,";
427
        $sql .= " cp.detail_refuse,";
428
        $sql .= " cp.note_private,";
429
        $sql .= " cp.note_public,";
430
        $sql .= " cp.fk_user_create,";
431
        $sql .= " cp.fk_type,";
432
        $sql .= " cp.entity";
433
        $sql .= " FROM " . MAIN_DB_PREFIX . "holiday as cp";
434
        if ($id > 0) {
435
            $sql .= " WHERE cp.rowid = " . ((int) $id);
436
        } else {
437
            $sql .= " WHERE cp.ref = '" . $this->db->escape($ref) . "'";
438
        }
439
440
        dol_syslog(get_only_class($this) . "::fetch", LOG_DEBUG);
441
        $resql = $this->db->query($sql);
442
        if ($resql) {
443
            if ($this->db->num_rows($resql)) {
444
                $obj = $this->db->fetch_object($resql);
445
446
                $this->id    = $obj->rowid;
447
                $this->ref   = ($obj->ref ? $obj->ref : $obj->rowid);
448
                $this->fk_user = $obj->fk_user;
449
                $this->date_create = $this->db->jdate($obj->date_create);
450
                $this->description = $obj->description;
451
                $this->date_debut = $this->db->jdate($obj->date_debut);
452
                $this->date_fin = $this->db->jdate($obj->date_fin);
453
                $this->date_debut_gmt = $this->db->jdate($obj->date_debut, 1);
454
                $this->date_fin_gmt = $this->db->jdate($obj->date_fin, 1);
455
                $this->halfday = $obj->halfday;
456
                $this->status = $obj->status;
457
                $this->statut = $obj->status;   // deprecated
458
                $this->fk_validator = $obj->fk_validator;
459
                $this->date_valid = $this->db->jdate($obj->date_valid);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->db->jdate($obj->date_valid) can also be of type string. However, the property $date_valid is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
460
                $this->fk_user_valid = $obj->fk_user_valid;
461
                $this->user_validation_id = $obj->fk_user_valid;
462
                $this->date_approval = $this->db->jdate($obj->date_approval);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->db->jdate($obj->date_approval) can also be of type string. However, the property $date_approval is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
463
                $this->fk_user_approve = $obj->fk_user_approve;
464
                $this->date_refuse = $this->db->jdate($obj->date_refuse);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->db->jdate($obj->date_refuse) can also be of type string. However, the property $date_refuse is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
465
                $this->fk_user_refuse = $obj->fk_user_refuse;
466
                $this->date_cancel = $this->db->jdate($obj->date_cancel);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->db->jdate($obj->date_cancel) can also be of type string. However, the property $date_cancel is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
467
                $this->fk_user_cancel = $obj->fk_user_cancel;
468
                $this->detail_refuse = $obj->detail_refuse;
469
                $this->note_private = $obj->note_private;
470
                $this->note_public = $obj->note_public;
471
                $this->fk_user_create = $obj->fk_user_create;
472
                $this->fk_type = $obj->fk_type;
473
                $this->entity = $obj->entity;
474
475
                $this->fetch_optionals();
476
477
                $result = 1;
478
            } else {
479
                $result = 0;
480
            }
481
            $this->db->free($resql);
482
483
            return $result;
484
        } else {
485
            $this->error = "Error " . $this->db->lasterror();
486
            return -1;
487
        }
488
    }
489
490
    /**
491
     *  List holidays for a particular user or list of users
492
     *
493
     *  @param      int|string      $user_id    ID of user to list, or comma separated list of IDs of users to list
494
     *  @param      string          $order      Sort order
495
     *  @param      string          $filter     SQL Filter
496
     *  @return     int                         -1 if KO, 1 if OK, 2 if no result
497
     */
498
    public function fetchByUser($user_id, $order = '', $filter = '')
499
    {
500
        $sql = "SELECT";
501
        $sql .= " cp.rowid,";
502
        $sql .= " cp.ref,";
503
504
        $sql .= " cp.fk_user,";
505
        $sql .= " cp.fk_type,";
506
        $sql .= " cp.date_create,";
507
        $sql .= " cp.description,";
508
        $sql .= " cp.date_debut,";
509
        $sql .= " cp.date_fin,";
510
        $sql .= " cp.halfday,";
511
        $sql .= " cp.statut as status,";
512
        $sql .= " cp.fk_validator,";
513
        $sql .= " cp.date_valid,";
514
        $sql .= " cp.fk_user_valid,";
515
        $sql .= " cp.date_approval,";
516
        $sql .= " cp.fk_user_approve,";
517
        $sql .= " cp.date_refuse,";
518
        $sql .= " cp.fk_user_refuse,";
519
        $sql .= " cp.date_cancel,";
520
        $sql .= " cp.fk_user_cancel,";
521
        $sql .= " cp.detail_refuse,";
522
523
        $sql .= " uu.lastname as user_lastname,";
524
        $sql .= " uu.firstname as user_firstname,";
525
        $sql .= " uu.login as user_login,";
526
        $sql .= " uu.statut as user_status,";
527
        $sql .= " uu.photo as user_photo,";
528
529
        $sql .= " ua.lastname as validator_lastname,";
530
        $sql .= " ua.firstname as validator_firstname,";
531
        $sql .= " ua.login as validator_login,";
532
        $sql .= " ua.statut as validator_status,";
533
        $sql .= " ua.photo as validator_photo";
534
535
        $sql .= " FROM " . MAIN_DB_PREFIX . "holiday as cp, " . MAIN_DB_PREFIX . "user as uu, " . MAIN_DB_PREFIX . "user as ua";
536
        $sql .= " WHERE cp.entity IN (" . getEntity('holiday') . ")";
537
        $sql .= " AND cp.fk_user = uu.rowid AND cp.fk_validator = ua.rowid"; // Hack pour la recherche sur le tableau
538
        $sql .= " AND cp.fk_user IN (" . $this->db->sanitize($user_id) . ")";
539
540
        // Selection filter
541
        if (!empty($filter)) {
542
            $sql .= $filter;
543
        }
544
545
        // Order of display of the result
546
        if (!empty($order)) {
547
            $sql .= $order;
548
        }
549
550
        dol_syslog(get_only_class($this) . "::fetchByUser", LOG_DEBUG);
551
        $resql = $this->db->query($sql);
552
553
        // If no SQL error
554
        if ($resql) {
555
            $i = 0;
556
            $tab_result = $this->holiday;
557
            $num = $this->db->num_rows($resql);
558
559
            // If no registration
560
            if (!$num) {
561
                return 2;
562
            }
563
564
            // List the records and add them to the table
565
            while ($i < $num) {
566
                $obj = $this->db->fetch_object($resql);
567
568
                $tab_result[$i]['rowid'] = $obj->rowid;
569
                $tab_result[$i]['id'] = $obj->rowid;
570
                $tab_result[$i]['ref'] = ($obj->ref ? $obj->ref : $obj->rowid);
571
572
                $tab_result[$i]['fk_user'] = $obj->fk_user;
573
                $tab_result[$i]['fk_type'] = $obj->fk_type;
574
                $tab_result[$i]['date_create'] = $this->db->jdate($obj->date_create);
575
                $tab_result[$i]['description'] = $obj->description;
576
                $tab_result[$i]['date_debut'] = $this->db->jdate($obj->date_debut);
577
                $tab_result[$i]['date_fin'] = $this->db->jdate($obj->date_fin);
578
                $tab_result[$i]['date_debut_gmt'] = $this->db->jdate($obj->date_debut, 1);
579
                $tab_result[$i]['date_fin_gmt'] = $this->db->jdate($obj->date_fin, 1);
580
                $tab_result[$i]['halfday'] = $obj->halfday;
581
                $tab_result[$i]['statut'] = $obj->status;
582
                $tab_result[$i]['status'] = $obj->status;
583
                $tab_result[$i]['fk_validator'] = $obj->fk_validator;
584
                $tab_result[$i]['date_valid'] = $this->db->jdate($obj->date_valid);
585
                $tab_result[$i]['fk_user_valid'] = $obj->fk_user_valid;
586
                $tab_result[$i]['date_approval'] = $this->db->jdate($obj->date_approval);
587
                $tab_result[$i]['fk_user_approve'] = $obj->fk_user_approve;
588
                $tab_result[$i]['date_refuse'] = $this->db->jdate($obj->date_refuse);
589
                $tab_result[$i]['fk_user_refuse'] = $obj->fk_user_refuse;
590
                $tab_result[$i]['date_cancel'] = $this->db->jdate($obj->date_cancel);
591
                $tab_result[$i]['fk_user_cancel'] = $obj->fk_user_cancel;
592
                $tab_result[$i]['detail_refuse'] = $obj->detail_refuse;
593
594
                $tab_result[$i]['user_firstname'] = $obj->user_firstname;
595
                $tab_result[$i]['user_lastname'] = $obj->user_lastname;
596
                $tab_result[$i]['user_login'] = $obj->user_login;
597
                $tab_result[$i]['user_statut'] = $obj->user_status;
598
                $tab_result[$i]['user_status'] = $obj->user_status;
599
                $tab_result[$i]['user_photo'] = $obj->user_photo;
600
601
                $tab_result[$i]['validator_firstname'] = $obj->validator_firstname;
602
                $tab_result[$i]['validator_lastname'] = $obj->validator_lastname;
603
                $tab_result[$i]['validator_login'] = $obj->validator_login;
604
                $tab_result[$i]['validator_statut'] = $obj->validator_status;
605
                $tab_result[$i]['validator_status'] = $obj->validator_status;
606
                $tab_result[$i]['validator_photo'] = $obj->validator_photo;
607
608
                $i++;
609
            }
610
611
            // Returns 1 with the filled array
612
            $this->holiday = $tab_result;
613
            return 1;
614
        } else {
615
            // SQL Error
616
            $this->error = "Error " . $this->db->lasterror();
617
            return -1;
618
        }
619
    }
620
621
    /**
622
     *  List all holidays of all users
623
     *
624
     *  @param      string  $order      Sort order
625
     *  @param      string  $filter     SQL Filter
626
     *  @return     int                 -1 if KO, 1 if OK, 2 if no result
627
     */
628
    public function fetchAll($order, $filter)
629
    {
630
        $sql = "SELECT";
631
        $sql .= " cp.rowid,";
632
        $sql .= " cp.ref,";
633
        $sql .= " cp.fk_user,";
634
        $sql .= " cp.fk_type,";
635
        $sql .= " cp.date_create,";
636
        $sql .= " cp.tms as date_modification,";
637
        $sql .= " cp.description,";
638
        $sql .= " cp.date_debut,";
639
        $sql .= " cp.date_fin,";
640
        $sql .= " cp.halfday,";
641
        $sql .= " cp.statut as status,";
642
        $sql .= " cp.fk_validator,";
643
        $sql .= " cp.date_valid,";
644
        $sql .= " cp.fk_user_valid,";
645
        $sql .= " cp.date_approval,";
646
        $sql .= " cp.fk_user_approve,";
647
        $sql .= " cp.date_refuse,";
648
        $sql .= " cp.fk_user_refuse,";
649
        $sql .= " cp.date_cancel,";
650
        $sql .= " cp.fk_user_cancel,";
651
        $sql .= " cp.detail_refuse,";
652
653
        $sql .= " uu.lastname as user_lastname,";
654
        $sql .= " uu.firstname as user_firstname,";
655
        $sql .= " uu.login as user_login,";
656
        $sql .= " uu.statut as user_status,";
657
        $sql .= " uu.photo as user_photo,";
658
659
        $sql .= " ua.lastname as validator_lastname,";
660
        $sql .= " ua.firstname as validator_firstname,";
661
        $sql .= " ua.login as validator_login,";
662
        $sql .= " ua.statut as validator_status,";
663
        $sql .= " ua.photo as validator_photo";
664
665
        $sql .= " FROM " . MAIN_DB_PREFIX . "holiday as cp, " . MAIN_DB_PREFIX . "user as uu, " . MAIN_DB_PREFIX . "user as ua";
666
        $sql .= " WHERE cp.entity IN (" . getEntity('holiday') . ")";
667
        $sql .= " AND cp.fk_user = uu.rowid AND cp.fk_validator = ua.rowid "; // Hack pour la recherche sur le tableau
668
669
        // Selection filtering
670
        if (!empty($filter)) {
671
            $sql .= $filter;
672
        }
673
674
        // order of display
675
        if (!empty($order)) {
676
            $sql .= $order;
677
        }
678
679
        dol_syslog(get_only_class($this) . "::fetchAll", LOG_DEBUG);
680
        $resql = $this->db->query($sql);
681
682
        // If no SQL error
683
        if ($resql) {
684
            $i = 0;
685
            $tab_result = $this->holiday;
686
            $num = $this->db->num_rows($resql);
687
688
            // If no registration
689
            if (!$num) {
690
                return 2;
691
            }
692
693
            // List the records and add them to the table
694
            while ($i < $num) {
695
                $obj = $this->db->fetch_object($resql);
696
697
                $tab_result[$i]['rowid'] = $obj->rowid;
698
                $tab_result[$i]['id'] = $obj->rowid;
699
                $tab_result[$i]['ref'] = ($obj->ref ? $obj->ref : $obj->rowid);
700
701
                $tab_result[$i]['fk_user'] = $obj->fk_user;
702
                $tab_result[$i]['fk_type'] = $obj->fk_type;
703
                $tab_result[$i]['date_create'] = $this->db->jdate($obj->date_create);
704
                $tab_result[$i]['date_modification'] = $this->db->jdate($obj->date_modification);
705
                $tab_result[$i]['description'] = $obj->description;
706
                $tab_result[$i]['date_debut'] = $this->db->jdate($obj->date_debut);
707
                $tab_result[$i]['date_fin'] = $this->db->jdate($obj->date_fin);
708
                $tab_result[$i]['date_debut_gmt'] = $this->db->jdate($obj->date_debut, 1);
709
                $tab_result[$i]['date_fin_gmt'] = $this->db->jdate($obj->date_fin, 1);
710
                $tab_result[$i]['halfday'] = $obj->halfday;
711
                $tab_result[$i]['statut'] = $obj->status;
712
                $tab_result[$i]['status'] = $obj->status;
713
                $tab_result[$i]['fk_validator'] = $obj->fk_validator;
714
                $tab_result[$i]['date_valid'] = $this->db->jdate($obj->date_valid);
715
                $tab_result[$i]['fk_user_valid'] = $obj->fk_user_valid;
716
                $tab_result[$i]['date_approval'] = $this->db->jdate($obj->date_approval);
717
                $tab_result[$i]['fk_user_approve'] = $obj->fk_user_approve;
718
                $tab_result[$i]['date_refuse'] = $obj->date_refuse;
719
                $tab_result[$i]['fk_user_refuse'] = $obj->fk_user_refuse;
720
                $tab_result[$i]['date_cancel'] = $obj->date_cancel;
721
                $tab_result[$i]['fk_user_cancel'] = $obj->fk_user_cancel;
722
                $tab_result[$i]['detail_refuse'] = $obj->detail_refuse;
723
724
                $tab_result[$i]['user_firstname'] = $obj->user_firstname;
725
                $tab_result[$i]['user_lastname'] = $obj->user_lastname;
726
                $tab_result[$i]['user_login'] = $obj->user_login;
727
                $tab_result[$i]['user_statut'] = $obj->user_status;
728
                $tab_result[$i]['user_status'] = $obj->user_status;
729
                $tab_result[$i]['user_photo'] = $obj->user_photo;
730
731
                $tab_result[$i]['validator_firstname'] = $obj->validator_firstname;
732
                $tab_result[$i]['validator_lastname'] = $obj->validator_lastname;
733
                $tab_result[$i]['validator_login'] = $obj->validator_login;
734
                $tab_result[$i]['validator_statut'] = $obj->validator_status;
735
                $tab_result[$i]['validator_status'] = $obj->validator_status;
736
                $tab_result[$i]['validator_photo'] = $obj->validator_photo;
737
738
                $i++;
739
            }
740
            // Returns 1 and adds the array to the variable
741
            $this->holiday = $tab_result;
742
            return 1;
743
        } else {
744
            // SQL Error
745
            $this->error = "Error " . $this->db->lasterror();
746
            return -1;
747
        }
748
    }
749
750
751
    /**
752
     *  Validate leave request
753
     *
754
     *  @param  User    $user           User that validate
755
     *  @param  int     $notrigger      0=launch triggers after, 1=disable triggers
756
     *  @return int                     Return integer <0 if KO, >0 if OK
757
     */
758
    public function validate($user = null, $notrigger = 0)
759
    {
760
        global $conf, $langs;
761
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
762
        $error = 0;
763
764
        $checkBalance = getDictionaryValue('c_holiday_types', 'block_if_negative', $this->fk_type);
765
766
        if ($checkBalance > 0) {
767
            $balance = $this->getCPforUser($this->fk_user, $this->fk_type);
768
769
            if ($balance < 0) {
770
                $this->error = 'LeaveRequestCreationBlockedBecauseBalanceIsNegative';
771
                return -1;
772
            }
773
        }
774
775
        // Define new ref
776
        if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref) || $this->ref == $this->id)) {
777
            $num = $this->getNextNumRef(null);
778
        } else {
779
            $num = $this->ref;
780
        }
781
        $this->newref = dol_sanitizeFileName($num);
782
783
        // Update status
784
        $sql = "UPDATE " . MAIN_DB_PREFIX . "holiday SET";
785
        $sql .= " fk_user_valid = " . ((int) $user->id) . ",";
786
        $sql .= " date_valid = '" . $this->db->idate(dol_now()) . "',";
787
        if (!empty($this->status) && is_numeric($this->status)) {
788
            $sql .= " statut = " . ((int) $this->status) . ",";
789
        } else {
790
            $this->error = 'Property status must be a numeric value';
791
            $error++;
792
        }
793
        $sql .= " ref = '" . $this->db->escape($num) . "'";
794
        $sql .= " WHERE rowid = " . ((int) $this->id);
795
796
        $this->db->begin();
797
798
        dol_syslog(get_only_class($this) . "::validate", LOG_DEBUG);
799
        $resql = $this->db->query($sql);
800
        if (!$resql) {
801
            $error++;
802
            $this->errors[] = "Error " . $this->db->lasterror();
803
        }
804
805
        if (!$error) {
806
            if (!$notrigger) {
807
                // Call trigger
808
                $result = $this->call_trigger('HOLIDAY_VALIDATE', $user);
809
                if ($result < 0) {
810
                    $error++;
811
                }
812
                // End call triggers
813
            }
814
        }
815
816
        if (!$error) {
817
            $this->oldref = $this->ref;
818
819
            // Rename directory if dir was a temporary ref
820
            if (preg_match('/^[\(]?PROV/i', $this->ref)) {
821
                // Now we rename also files into index
822
                $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) . "'";
823
                $sql .= " WHERE filename LIKE '" . $this->db->escape($this->ref) . "%' AND filepath = 'holiday/" . $this->db->escape($this->ref) . "' and entity = " . ((int) $conf->entity);
824
                $resql = $this->db->query($sql);
825
                if (!$resql) {
826
                    $error++;
827
                    $this->error = $this->db->lasterror();
828
                }
829
                $sql = 'UPDATE ' . MAIN_DB_PREFIX . "ecm_files set filepath = 'holiday/" . $this->db->escape($this->newref) . "'";
830
                $sql .= " WHERE filepath = 'holiday/" . $this->db->escape($this->ref) . "' and entity = " . $conf->entity;
831
                $resql = $this->db->query($sql);
832
                if (!$resql) {
833
                    $error++;
834
                    $this->error = $this->db->lasterror();
835
                }
836
837
                // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
838
                $oldref = dol_sanitizeFileName($this->ref);
839
                $newref = dol_sanitizeFileName($num);
840
                $dirsource = $conf->holiday->multidir_output[$this->entity] . '/' . $oldref;
841
                $dirdest = $conf->holiday->multidir_output[$this->entity] . '/' . $newref;
842
                if (!$error && file_exists($dirsource)) {
843
                    dol_syslog(get_only_class($this) . "::validate rename dir " . $dirsource . " into " . $dirdest);
844
                    if (@rename($dirsource, $dirdest)) {
845
                        dol_syslog("Rename ok");
846
                        // Rename docs starting with $oldref with $newref
847
                        $listoffiles = dol_dir_list($dirdest, 'files', 1, '^' . preg_quote($oldref, '/'));
848
                        foreach ($listoffiles as $fileentry) {
849
                            $dirsource = $fileentry['name'];
850
                            $dirdest = preg_replace('/^' . preg_quote($oldref, '/') . '/', $newref, $dirsource);
851
                            $dirsource = $fileentry['path'] . '/' . $dirsource;
852
                            $dirdest = $fileentry['path'] . '/' . $dirdest;
853
                            @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

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

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
2350
2351
                $this->user_creation_id = $obj->fk_user_creation;
2352
                $this->user_validation_id = $obj->fk_user_validation;
2353
                $this->user_modification_id = $obj->fk_user_modification;
2354
2355
                if ($obj->status == Holiday::STATUS_APPROVED || $obj->status == Holiday::STATUS_CANCELED) {
2356
                    if ($obj->fk_user_approval_done) {
2357
                        $this->fk_user_approve = $obj->fk_user_approval_done;
2358
                    }
2359
                }
2360
            }
2361
            $this->db->free($resql);
2362
        } else {
2363
            dol_print_error($this->db);
2364
        }
2365
    }
2366
2367
2368
    /**
2369
     *  Initialise an instance with random values.
2370
     *  Used to build previews or test instances.
2371
     *  id must be 0 if object instance is a specimen.
2372
     *
2373
     *  @return int
2374
     */
2375
    public function initAsSpecimen()
2376
    {
2377
        global $user, $langs;
2378
2379
        // Initialise parameters
2380
        $this->id = 0;
2381
        $this->specimen = 1;
2382
2383
        $this->fk_user = $user->id;
2384
        $this->description = 'SPECIMEN description';
2385
        $this->date_debut = dol_now();
2386
        $this->date_fin = dol_now() + (24 * 3600);
2387
        $this->date_valid = dol_now();
2388
        $this->fk_validator = $user->id;
2389
        $this->halfday = 0;
2390
        $this->fk_type = 1;
2391
        $this->status = Holiday::STATUS_VALIDATED;
2392
2393
        return 1;
2394
    }
2395
2396
    /**
2397
     *      Load this->nb for dashboard
2398
     *
2399
     *      @return     int         Return integer <0 if KO, >0 if OK
2400
     */
2401
    public function loadStateBoard()
2402
    {
2403
        global $user;
2404
2405
        $this->nb = array();
2406
2407
        $sql = "SELECT count(h.rowid) as nb";
2408
        $sql .= " FROM " . MAIN_DB_PREFIX . "holiday as h";
2409
        $sql .= " WHERE h.statut > 1";
2410
        $sql .= " AND h.entity IN (" . getEntity('holiday') . ")";
2411
        if (!$user->hasRight('expensereport', 'readall')) {
2412
            $userchildids = $user->getAllChildIds(1);
2413
            $sql .= " AND (h.fk_user IN (" . $this->db->sanitize(implode(',', $userchildids)) . ")";
2414
            $sql .= " OR h.fk_validator IN (" . $this->db->sanitize(implode(',', $userchildids)) . "))";
2415
        }
2416
2417
        $resql = $this->db->query($sql);
2418
        if ($resql) {
2419
            while ($obj = $this->db->fetch_object($resql)) {
2420
                $this->nb["holidays"] = $obj->nb;
2421
            }
2422
            $this->db->free($resql);
2423
            return 1;
2424
        } else {
2425
            dol_print_error($this->db);
2426
            $this->error = $this->db->error();
2427
            return -1;
2428
        }
2429
    }
2430
2431
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2432
    /**
2433
     *      Load indicators for dashboard (this->nbtodo and this->nbtodolate)
2434
     *
2435
     *      @param  User    $user           Object user
2436
     *      @return WorkboardResponse|int   Return integer <0 if KO, WorkboardResponse if OK
2437
     */
2438
    public function load_board($user)
2439
    {
2440
		// phpcs:enable
2441
        global $conf, $langs;
2442
2443
        if ($user->socid) {
2444
            return -1; // protection pour eviter appel par utilisateur externe
2445
        }
2446
2447
        $now = dol_now();
2448
2449
        $sql = "SELECT h.rowid, h.date_debut";
2450
        $sql .= " FROM " . MAIN_DB_PREFIX . "holiday as h";
2451
        $sql .= " WHERE h.statut = 2";
2452
        $sql .= " AND h.entity IN (" . getEntity('holiday') . ")";
2453
        if (!$user->hasRight('expensereport', 'read_all')) {
2454
            $userchildids = $user->getAllChildIds(1);
2455
            $sql .= " AND (h.fk_user IN (" . $this->db->sanitize(implode(',', $userchildids)) . ")";
2456
            $sql .= " OR h.fk_validator IN (" . $this->db->sanitize(implode(',', $userchildids)) . "))";
2457
        }
2458
2459
        $resql = $this->db->query($sql);
2460
        if ($resql) {
2461
            $langs->load("members");
2462
2463
            $response = new WorkboardResponse();
2464
            $response->warning_delay = $conf->holiday->approve->warning_delay / 60 / 60 / 24;
2465
            $response->label = $langs->trans("HolidaysToApprove");
2466
            $response->labelShort = $langs->trans("ToApprove");
2467
            $response->url = constant('BASE_URL') . '/holiday/list.php?search_status=2&amp;mainmenu=hrm&amp;leftmenu=holiday';
2468
            $response->img = img_object('', "holiday");
2469
2470
            while ($obj = $this->db->fetch_object($resql)) {
2471
                $response->nbtodo++;
2472
2473
                if ($this->db->jdate($obj->date_debut) < ($now - $conf->holiday->approve->warning_delay)) {
2474
                    $response->nbtodolate++;
2475
                }
2476
            }
2477
2478
            return $response;
2479
        } else {
2480
            dol_print_error($this->db);
2481
            $this->error = $this->db->error();
2482
            return -1;
2483
        }
2484
    }
2485
    /**
2486
     *  Return clicable link of object (with eventually picto)
2487
     *
2488
     *  @param      string      $option                 Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link)
2489
     *  @param      array       $arraydata              Label of holiday type (if known)
2490
     *  @return     string      HTML Code for Kanban thumb.
2491
     */
2492
    public function getKanbanView($option = '', $arraydata = null)
2493
    {
2494
        global $langs;
2495
2496
        $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
2497
2498
        $return = '<div class="box-flex-item box-flex-grow-zero">';
2499
        $return .= '<div class="info-box info-box-sm">';
2500
        $return .= '<span class="info-box-icon bg-infobox-action">';
2501
        $return .= img_picto('', $this->picto);
2502
        $return .= '</span>';
2503
        $return .= '<div class="info-box-content">';
2504
        $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . $arraydata['user']->getNomUrl(-1) . '</span>';
2505
        if ($selected >= 0) {
2506
            $return .= '<input id="cb' . $this->id . '" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="' . $this->id . '"' . ($selected ? ' checked="checked"' : '') . '>';
2507
        }
2508
        if (property_exists($this, 'fk_type')) {
2509
            $return .= '<br>';
2510
            //$return .= '<span class="opacitymedium">'.$langs->trans("Type").'</span> : ';
2511
            $return .= '<div class="info_box-label tdoverflowmax100" title="' . dol_escape_htmltag($arraydata['labeltype']) . '">' . dol_escape_htmltag($arraydata['labeltype']) . '</div>';
2512
        }
2513
        if (property_exists($this, 'date_debut') && property_exists($this, 'date_fin')) {
2514
            $return .= '<span class="info-box-label small">' . dol_print_date($this->date_debut, 'day') . '</span>';
2515
            $return .= ' <span class="opacitymedium small">' . $langs->trans("To") . '</span> ';
2516
            $return .= '<span class="info-box-label small">' . dol_print_date($this->date_fin, 'day') . '</span>';
2517
            if (!empty($arraydata['nbopenedday'])) {
2518
                $return .= ' (' . $arraydata['nbopenedday'] . ')';
2519
            }
2520
        }
2521
        if (method_exists($this, 'getLibStatut')) {
2522
            $return .= '<div class="info-box-status">' . $this->getLibStatut(3) . '</div>';
2523
        }
2524
        $return .= '</div>';
2525
        $return .= '</div>';
2526
        $return .= '</div>';
2527
        return $return;
2528
    }
2529
}
2530