Passed
Push — EXTRACT_CLASSES ( ae6b5c...83d77a )
by Rafael
60:14 queued 23:58
created

Salary   F

Complexity

Total Complexity 120

Size/Duplication

Total Lines 944
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 469
dl 0
loc 944
rs 2
c 0
b 0
f 0
wmc 120

19 Methods

Rating   Name   Duplication   Size   Complexity  
A initAsSpecimen() 0 18 1
B update() 0 65 11
D getKanbanView() 0 38 14
C demande_prelevement() 0 107 15
A getLibStatut() 0 3 1
B LibStatut() 0 36 10
A setPaid() 0 13 2
A demande_prelevement_delete() 0 12 2
A getTooltipContentArray() 0 21 5
A set_unpaid() 0 14 2
A delete() 0 3 1
A info() 0 23 4
F create() 0 109 17
F getNomUrl() 0 74 23
A __construct() 0 5 1
A getSommePaiement() 0 39 5
A set_paid() 0 5 1
A fetch() 0 61 3
A update_fk_bank() 0 11 2

How to fix   Complexity   

Complex Class

Complex classes like Salary often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Salary, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/* Copyright (C) 2011-2022  Alexandre Spangaro          <[email protected]>
4
 * Copyright (C) 2014       Juanjo Menent               <[email protected]>
5
 * Copyright (C) 2021       Gauthier VERDOL             <[email protected]>
6
 * Copyright (C) 2024       Frédéric France             <[email protected]>
7
 * Copyright (C) 2024		MDW							<[email protected]>
8
 * Copyright (C) 2024       Rafael San José             <[email protected]>
9
 *
10
 * This program is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation; either version 3 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22
 */
23
24
namespace Dolibarr\Code\Salaries\Classes;
25
26
use Dolibarr\Core\Base\CommonObject;
27
28
/**
29
 *  \file       htdocs/salaries/class/salary.class.php
30
 *  \ingroup    salaries
31
 *  \brief      Class for salaries module payment
32
 */
33
34
/**
35
 *  Class to manage salary payments
36
 */
37
class Salary extends CommonObject
38
{
39
    /**
40
     * @var string ID to identify managed object
41
     */
42
    public $element = 'salary';
43
44
    /**
45
     * @var string Name of table without prefix where object is stored
46
     */
47
    public $table_element = 'salary';
48
49
    /**
50
     * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
51
     */
52
    public $picto = 'salary';
53
54
    /**
55
     * @var array<string, array<string>>    List of child tables. To test if we can delete object.
56
     */
57
    protected $childtables = array('payment_salary' => array('name' => 'SalaryPayment', 'fk_element' => 'fk_salary'));
58
59
    // /**
60
    //  * @var array    List of child tables. To know object to delete on cascade.
61
    //  *               If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will
62
    //  *               call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object
63
    //  */
64
    //protected $childtablesoncascade = array('mymodule_myobjectdet');
65
66
67
    /**
68
     * @var int User ID
69
     */
70
    public $fk_user;
71
72
    public $datep;
73
    public $datev;
74
75
    public $salary;
76
    public $amount;
77
78
    /**
79
     * @var int ID
80
     */
81
    public $fk_project;
82
83
    public $type_payment;
84
85
    /**
86
     * @var string salary payments label
87
     */
88
    public $label;
89
90
    public $datesp;
91
    public $dateep;
92
93
    /**
94
     * @var int ID
95
     */
96
    public $fk_bank;
97
98
    /**
99
     * @var int
100
     * @see $accountid
101
     */
102
    public $fk_account;
103
104
    /**
105
     * @var int
106
     */
107
    public $accountid;
108
109
    /**
110
     * @var int ID
111
     */
112
    public $fk_user_author;
113
114
    /**
115
     * @var int ID
116
     */
117
    public $fk_user_modif;
118
119
    /**
120
     * @var user    User
121
     */
122
    public $user;
123
124
    /**
125
     * @var int 1 if salary paid COMPLETELY, 0 otherwise (do not use it anymore, use statut and close_code)
126
     * @deprecated
127
     */
128
    public $paye;
129
130
    const STATUS_UNPAID = 0;
131
    const STATUS_PAID = 1;
132
133
    public $resteapayer;
134
135
    /**
136
     *  Constructor
137
     *
138
     *  @param      DoliDB      $db      Database handler
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Salaries\Classes\DoliDB was not found. Did you mean DoliDB? If so, make sure to prefix the type with \.
Loading history...
139
     */
140
    public function __construct($db)
141
    {
142
        $this->db = $db;
143
        $this->element = 'salary';
144
        $this->table_element = 'salary';
145
    }
146
147
    /**
148
     * Update database
149
     *
150
     * @param   User    $user           User that modify
151
     * @param   int     $notrigger      0=no, 1=yes (no update trigger)
152
     * @return  int                     Return integer <0 if KO, >0 if OK
153
     */
154
    public function update($user = null, $notrigger = 0)
155
    {
156
        $error = 0;
157
158
        // Clean parameters
159
        $this->amount = trim($this->amount);
160
        $this->label = trim($this->label);
161
        $this->note = trim($this->note);
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$note has been deprecated: Use $note_private instead. ( Ignorable by Annotation )

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

161
        /** @scrutinizer ignore-deprecated */ $this->note = trim($this->note);

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
162
163
        // Check parameters
164
        if (empty($this->fk_user) || $this->fk_user < 0) {
165
            $this->error = 'ErrorBadParameter';
166
            return -1;
167
        }
168
169
        $this->db->begin();
170
171
        // Update request
172
        $sql = "UPDATE " . MAIN_DB_PREFIX . "salary SET";
173
        $sql .= " tms='" . $this->db->idate(dol_now()) . "',";
174
        $sql .= " fk_user=" . ((int) $this->fk_user) . ",";
175
        /*$sql .= " datep='".$this->db->idate($this->datep)."',";
176
        $sql .= " datev='".$this->db->idate($this->datev)."',";*/
177
        $sql .= " amount=" . price2num($this->amount) . ",";
178
        $sql .= " fk_projet=" . ((int) $this->fk_project) . ",";
179
        $sql .= " fk_typepayment=" . ((int) $this->type_payment) . ",";
180
        $sql .= " label='" . $this->db->escape($this->label) . "',";
181
        $sql .= " datesp='" . $this->db->idate($this->datesp) . "',";
182
        $sql .= " dateep='" . $this->db->idate($this->dateep) . "',";
183
        $sql .= " note='" . $this->db->escape($this->note) . "',";
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$note has been deprecated: Use $note_private instead. ( Ignorable by Annotation )

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

183
        $sql .= " note='" . $this->db->escape(/** @scrutinizer ignore-deprecated */ $this->note) . "',";

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
184
        $sql .= " fk_bank=" . ($this->fk_bank > 0 ? (int) $this->fk_bank : "null") . ",";
185
        $sql .= " fk_user_author=" . ((int) $this->fk_user_author) . ",";
186
        $sql .= " fk_user_modif=" . ($this->fk_user_modif > 0 ? (int) $this->fk_user_modif : (int) $user->id);
187
        $sql .= " WHERE rowid=" . ((int) $this->id);
188
189
        dol_syslog(get_class($this) . "::update", LOG_DEBUG);
190
        $resql = $this->db->query($sql);
191
        if (!$resql) {
192
            $this->error = "Error " . $this->db->lasterror();
193
            return -1;
194
        }
195
196
        // Update extrafield
197
        if (!$error) {
198
            $result = $this->insertExtraFields();
199
            if ($result < 0) {
200
                $error++;
201
            }
202
        }
203
204
        if (!$notrigger) {
205
            // Call trigger
206
            $result = $this->call_trigger('SALARY_MODIFY', $user);
207
            if ($result < 0) {
208
                $error++;
209
            }
210
            // End call triggers
211
        }
212
213
        if (!$error) {
214
            $this->db->commit();
215
            return 1;
216
        } else {
217
            $this->db->rollback();
218
            return -1;
219
        }
220
    }
221
222
223
    /**
224
     *  Load object in memory from database
225
     *
226
     *  @param  int     $id         id object
227
     *  @param  User    $user       User that load
228
     *  @return int                 Return integer <0 if KO, >0 if OK
229
     */
230
    public function fetch($id, $user = null)
231
    {
232
        $sql = "SELECT";
233
        $sql .= " s.rowid,";
234
        $sql .= " s.tms,";
235
        $sql .= " s.fk_user,";
236
        $sql .= " s.datep,";
237
        $sql .= " s.datev,";
238
        $sql .= " s.amount,";
239
        $sql .= " s.fk_projet as fk_project,";
240
        $sql .= " s.fk_typepayment,";
241
        $sql .= " s.label,";
242
        $sql .= " s.datesp,";
243
        $sql .= " s.dateep,";
244
        $sql .= " s.note,";
245
        $sql .= " s.paye,";
246
        $sql .= " s.fk_bank,";
247
        $sql .= " s.fk_user_author,";
248
        $sql .= " s.fk_user_modif,";
249
        $sql .= " s.fk_account";
250
        $sql .= " FROM " . MAIN_DB_PREFIX . "salary as s";
251
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "bank as b ON s.fk_bank = b.rowid";
252
        $sql .= " WHERE s.rowid = " . ((int) $id);
253
254
        dol_syslog(get_class($this) . "::fetch", LOG_DEBUG);
255
        $resql = $this->db->query($sql);
256
        if ($resql) {
257
            if ($this->db->num_rows($resql)) {
258
                $obj = $this->db->fetch_object($resql);
259
260
                $this->id               = $obj->rowid;
261
                $this->ref              = $obj->rowid;
262
                $this->tms              = $this->db->jdate($obj->tms);
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$tms has been deprecated: Use $date_modification ( Ignorable by Annotation )

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

262
                /** @scrutinizer ignore-deprecated */ $this->tms              = $this->db->jdate($obj->tms);

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
263
                $this->fk_user          = $obj->fk_user;
264
                $this->datep            = $this->db->jdate($obj->datep);
265
                $this->datev            = $this->db->jdate($obj->datev);
266
                $this->amount           = $obj->amount;
267
                $this->fk_project       = $obj->fk_project;
268
                $this->type_payment     = $obj->fk_typepayment;
269
                $this->label            = $obj->label;
270
                $this->datesp           = $this->db->jdate($obj->datesp);
271
                $this->dateep           = $this->db->jdate($obj->dateep);
272
                $this->note             = $obj->note;
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$note has been deprecated: Use $note_private instead. ( Ignorable by Annotation )

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

272
                /** @scrutinizer ignore-deprecated */ $this->note             = $obj->note;

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
273
                $this->paye             = $obj->paye;
274
                $this->status           = $obj->paye;
275
                $this->fk_bank          = $obj->fk_bank;
276
                $this->fk_user_author   = $obj->fk_user_author;
277
                $this->fk_user_modif    = $obj->fk_user_modif;
278
                $this->fk_account = $obj->fk_account;
279
                $this->accountid = $obj->fk_account;
280
281
                // Retrieve all extrafield
282
                // fetch optionals attributes and labels
283
                $this->fetch_optionals();
284
            }
285
            $this->db->free($resql);
286
287
            return 1;
288
        } else {
289
            $this->error = "Error " . $this->db->lasterror();
290
            return -1;
291
        }
292
    }
293
294
295
    /**
296
     *  Delete object in database
297
     *
298
     *  @param  User    $user       User that delete
299
     *  @param  int     $notrigger  0=launch triggers after, 1=disable triggers
300
     *  @return int                 Return integer <0 if KO, >0 if OK
301
     */
302
    public function delete($user, $notrigger = 0)
303
    {
304
        return $this->deleteCommon($user, $notrigger);
305
    }
306
307
308
    /**
309
     *  Initialise an instance with random values.
310
     *  Used to build previews or test instances.
311
     *  id must be 0 if object instance is a specimen.
312
     *
313
     *  @return int
314
     */
315
    public function initAsSpecimen()
316
    {
317
        $this->id = 0;
318
319
        $this->tms = dol_now();
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$tms has been deprecated: Use $date_modification ( Ignorable by Annotation )

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

319
        /** @scrutinizer ignore-deprecated */ $this->tms = dol_now();

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
320
        $this->fk_user = 0;
321
        $this->datep = '';
322
        $this->datev = '';
323
        $this->amount = '';
324
        $this->label = '';
325
        $this->datesp = '';
326
        $this->dateep = '';
327
        $this->note = '';
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$note has been deprecated: Use $note_private instead. ( Ignorable by Annotation )

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

327
        /** @scrutinizer ignore-deprecated */ $this->note = '';

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
328
        $this->fk_bank = 0;
329
        $this->fk_user_author = 0;
330
        $this->fk_user_modif = 0;
331
332
        return 1;
333
    }
334
335
    /**
336
     *  Create in database
337
     *
338
     *  @param      User    $user       User that create
339
     *  @return     int                 Return integer <0 if KO, >0 if OK
340
     */
341
    public function create($user)
342
    {
343
        global $conf, $langs;
344
345
        $error = 0;
346
        $now = dol_now();
347
348
        // Clean parameters
349
        $this->amount = price2num(trim($this->amount));
350
        $this->label = trim($this->label);
351
        $this->note = trim($this->note);
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$note has been deprecated: Use $note_private instead. ( Ignorable by Annotation )

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

351
        $this->note = trim(/** @scrutinizer ignore-deprecated */ $this->note);

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
352
        $this->fk_bank = (int) $this->fk_bank;
353
        $this->fk_user_author = (int) $this->fk_user_author;
354
        $this->fk_user_modif = (int) $this->fk_user_modif;
355
        $this->accountid = (int) $this->accountid;
356
        $this->paye = (int) $this->paye;
357
358
        // Check parameters
359
        if (!$this->label) {
360
            $this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentities("Label"));
361
            return -3;
362
        }
363
        if ($this->fk_user < 0 || $this->fk_user == '') {
364
            $this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentities("Employee"));
365
            return -4;
366
        }
367
        if ($this->amount == '') {
368
            $this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentities("Amount"));
369
            return -5;
370
        }
371
372
        $this->db->begin();
373
374
        // Insert into llx_salary
375
        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "salary (fk_user";
376
        //$sql .= ", datep";
377
        //$sql .= ", datev";
378
        $sql .= ", amount";
379
        $sql .= ", fk_projet";
380
        $sql .= ", salary";
381
        $sql .= ", fk_typepayment";
382
        $sql .= ", fk_account";
383
        if ($this->note) {
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$note has been deprecated: Use $note_private instead. ( Ignorable by Annotation )

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

383
        if (/** @scrutinizer ignore-deprecated */ $this->note) {

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
384
            $sql .= ", note";
385
        }
386
        $sql .= ", label";
387
        $sql .= ", datesp";
388
        $sql .= ", dateep";
389
        $sql .= ", fk_user_author";
390
        $sql .= ", datec";
391
        $sql .= ", fk_bank";
392
        $sql .= ", entity";
393
        $sql .= ") ";
394
        $sql .= " VALUES (";
395
        $sql .= "'" . $this->db->escape($this->fk_user) . "'";
396
        //$sql .= ", '".$this->db->idate($this->datep)."'";
397
        //$sql .= ", '".$this->db->idate($this->datev)."'";
398
        $sql .= ", " . ((float) $this->amount);
399
        $sql .= ", " . ($this->fk_project > 0 ? ((int) $this->fk_project) : 0);
400
        $sql .= ", " . ($this->salary > 0 ? ((float) $this->salary) : "null");
401
        $sql .= ", " . ($this->type_payment > 0 ? ((int) $this->type_payment) : 0);
402
        $sql .= ", " . ($this->accountid > 0 ? ((int) $this->accountid) : "null");
403
        if ($this->note) {
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$note has been deprecated: Use $note_private instead. ( Ignorable by Annotation )

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

403
        if (/** @scrutinizer ignore-deprecated */ $this->note) {

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
404
            $sql .= ", '" . $this->db->escape($this->note) . "'";
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$note has been deprecated: Use $note_private instead. ( Ignorable by Annotation )

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

404
            $sql .= ", '" . $this->db->escape(/** @scrutinizer ignore-deprecated */ $this->note) . "'";

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
405
        }
406
        $sql .= ", '" . $this->db->escape($this->label) . "'";
407
        $sql .= ", '" . $this->db->idate($this->datesp) . "'";
408
        $sql .= ", '" . $this->db->idate($this->dateep) . "'";
409
        $sql .= ", '" . $this->db->escape($user->id) . "'";
410
        $sql .= ", '" . $this->db->idate($now) . "'";
411
        $sql .= ", NULL";
412
        $sql .= ", " . ((int) $conf->entity);
413
        $sql .= ")";
414
415
        dol_syslog(get_class($this) . "::create", LOG_DEBUG);
416
        $result = $this->db->query($sql);
417
        if ($result) {
418
            $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . "salary");
419
420
            if ($this->id > 0) {
421
                // Update extrafield
422
                if (!$error) {
423
                    $result = $this->insertExtraFields();
424
                    if ($result < 0) {
425
                        $error++;
426
                    }
427
                }
428
429
                // Call trigger
430
                $result = $this->call_trigger('SALARY_CREATE', $user);
431
                if ($result < 0) {
432
                    $error++;
433
                }
434
                // End call triggers
435
            } else {
436
                $error++;
437
            }
438
439
            if (!$error) {
440
                $this->db->commit();
441
                return $this->id;
442
            } else {
443
                $this->db->rollback();
444
                return -2;
445
            }
446
        } else {
447
            $this->error = $this->db->error();
448
            $this->db->rollback();
449
            return -1;
450
        }
451
    }
452
453
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
454
    /**
455
     *  Update link between payment salary and line generate into llx_bank
456
     *
457
     *  @param  int     $id_bank    Id bank account
458
     *  @return int                 Return integer <0 if KO, >0 if OK
459
     */
460
    public function update_fk_bank($id_bank)
461
    {
462
		// phpcs:enable
463
        $sql = 'UPDATE ' . MAIN_DB_PREFIX . 'salary SET fk_bank = ' . ((int) $id_bank);
464
        $sql .= " WHERE rowid = " . ((int) $this->id);
465
        $result = $this->db->query($sql);
466
        if ($result) {
467
            return 1;
468
        } else {
469
            dol_print_error($this->db);
470
            return -1;
471
        }
472
    }
473
474
    /**
475
     * getTooltipContentArray
476
     *
477
     * @param array     $params         params to construct tooltip data
478
     * @since v18
479
     * @return array
480
     */
481
    public function getTooltipContentArray($params)
482
    {
483
        global $langs;
484
485
        $langs->loadLangs(['salaries']);
486
487
        // Complete datas
488
        if (!empty($params['fromajaxtooltip']) && !isset($this->alreadypaid)) {
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$alreadypaid has been deprecated: Use $totalpaid instead ( Ignorable by Annotation )

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

488
        if (!empty($params['fromajaxtooltip']) && !isset(/** @scrutinizer ignore-deprecated */ $this->alreadypaid)) {

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
Bug Best Practice introduced by
The property $alreadypaid is declared private in Dolibarr\Core\Base\CommonObject. Since you implement __get, consider adding a @property or @property-read.
Loading history...
489
            // Load the alreadypaid field
490
            $this->alreadypaid = $this->getSommePaiement(0);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getSommePaiement(0) can also be of type array. However, the property $alreadypaid is declared as type double. 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...
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$alreadypaid has been deprecated: Use $totalpaid instead ( Ignorable by Annotation )

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

490
            /** @scrutinizer ignore-deprecated */ $this->alreadypaid = $this->getSommePaiement(0);

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
491
        }
492
493
        $datas = [];
494
495
        $datas['picto'] = '<u>' . $langs->trans("Salary") . '</u>';
496
        if (isset($this->status) && isset($this->alreadypaid)) {
497
            $datas['picto'] .= ' ' . $this->getLibStatut(5, $this->alreadypaid);
498
        }
499
        $datas['ref'] = '<br><b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
500
501
        return $datas;
502
    }
503
504
    /**
505
     *  Send name clicable (with possibly the picto)
506
     *
507
     *  @param  int     $withpicto                  0=No picto, 1=Include picto into link, 2=Only picto
508
     *  @param  string  $option                     link option
509
     *  @param  int     $notooltip                  1=Disable tooltip
510
     *  @param  string  $morecss                    Add more css on link
511
     *  @param  int     $save_lastsearch_value      -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
512
     *  @return string                              Chaine with URL
513
     */
514
    public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
515
    {
516
        global $conf, $langs, $hookmanager;
517
518
        if (!empty($conf->dol_no_mouse_hover)) {
519
            $notooltip = 1;
520
        } // Force disable tooltips
521
522
        $result = '';
523
        $params = [
524
            'id' => $this->id,
525
            'objecttype' => $this->element,
526
            'option' => $option,
527
        ];
528
        $classfortooltip = 'classfortooltip';
529
        $dataparams = '';
530
        if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
531
            $classfortooltip = 'classforajaxtooltip';
532
            $dataparams = ' data-params="' . dol_escape_htmltag(json_encode($params)) . '"';
533
            $label = '';
534
        } else {
535
            $label = implode($this->getTooltipContentArray($params));
536
        }
537
538
        $url = constant('BASE_URL') . '/salaries/card.php?id=' . $this->id;
539
540
        if ($option != 'nolink') {
541
            // Add param to save lastsearch_values or not
542
            $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
543
            if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
544
                $add_save_lastsearch_values = 1;
545
            }
546
            if ($add_save_lastsearch_values) {
547
                $url .= '&save_lastsearch_values=1';
548
            }
549
        }
550
551
        $linkclose = '';
552
        if (empty($notooltip)) {
553
            if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
554
                $label = $langs->trans("ShowMyObject");
555
                $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
556
            }
557
            $linkclose .= ($label ? ' title="' . dol_escape_htmltag($label, 1) . '"' : ' title="tocomplete"');
558
            $linkclose .= $dataparams . ' class="' . $classfortooltip . ($morecss ? ' ' . $morecss : '') . '"';
559
        } else {
560
            $linkclose = ($morecss ? ' class="' . $morecss . '"' : '');
561
        }
562
563
        $linkstart = '<a href="' . $url . '"';
564
        $linkstart .= $linkclose . '>';
565
        $linkend = '</a>';
566
567
        $result .= $linkstart;
568
        if ($withpicto) {
569
            $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="' . (($withpicto != 2) ? 'paddingright ' : '') . '"'), 0, 0, $notooltip ? 0 : 1);
570
        }
571
        if ($withpicto != 2) {
572
            $result .= $this->ref;
573
        }
574
        $result .= $linkend;
575
        //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
576
577
        global $action, $hookmanager;
578
        $hookmanager->initHooks(array('salarypayment'));
579
        $parameters = array('id' => $this->id, 'getnomurl' => &$result);
580
        $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
581
        if ($reshook > 0) {
582
            $result = $hookmanager->resPrint;
583
        } else {
584
            $result .= $hookmanager->resPrint;
585
        }
586
587
        return $result;
588
    }
589
590
    /**
591
     *  Return amount of payments already done
592
     *
593
     *  @param      int             $multicurrency      Return multicurrency_amount instead of amount. -1=Return both.
594
     *  @return     float|int|array                     Amount of payment already done, <0 and set ->error if KO
595
     */
596
    public function getSommePaiement($multicurrency = 0)
597
    {
598
        $table = 'payment_salary';
599
        $field = 'fk_salary';
600
601
        $sql = "SELECT sum(amount) as amount";
602
        //sum(multicurrency_amount) as multicurrency_amount     // Not yet supported
603
        $sql .= " FROM " . MAIN_DB_PREFIX . $table;
604
        $sql .= " WHERE " . $field . " = " . ((int) $this->id);
605
606
        dol_syslog(get_class($this) . "::getSommePaiement", LOG_DEBUG);
607
608
        $resql = $this->db->query($sql);
609
610
        if ($resql) {
611
            $obj = $this->db->fetch_object($resql);
612
613
            $this->db->free($resql);
614
615
            if ($obj) {
616
                if ($multicurrency < 0) {
617
                    //$this->sumpayed = $obj->amount;
618
                    //$this->sumpayed_multicurrency = $obj->multicurrency_amount;
619
                    //return array('alreadypaid'=>(float) $obj->amount, 'alreadypaid_multicurrency'=>(float) $obj->multicurrency_amount);
620
                    return array(); // Not yet supported
621
                } elseif ($multicurrency) {
622
                    //$this->sumpayed_multicurrency = $obj->multicurrency_amount;
623
                    //return (float) $obj->multicurrency_amount;
624
                    return -1;      // Not yet supported
625
                } else {
626
                    //$this->sumpayed = $obj->amount;
627
                    return (float) $obj->amount;
628
                }
629
            } else {
630
                return 0;
631
            }
632
        } else {
633
            $this->error = $this->db->lasterror();
634
            return -1;
635
        }
636
    }
637
638
    /**
639
     * Information on record
640
     *
641
     * @param   int     $id      Id of record
642
     * @return  void
643
     */
644
    public function info($id)
645
    {
646
        $sql = 'SELECT ps.rowid, ps.datec, ps.tms as datem, ps.fk_user_author, ps.fk_user_modif';
647
        $sql .= ' FROM ' . MAIN_DB_PREFIX . 'salary as ps';
648
        $sql .= ' WHERE ps.rowid = ' . ((int) $id);
649
650
        dol_syslog(get_class($this) . '::info', LOG_DEBUG);
651
        $result = $this->db->query($sql);
652
653
        if ($result) {
654
            if ($this->db->num_rows($result)) {
655
                $obj = $this->db->fetch_object($result);
656
657
                $this->id = $obj->rowid;
658
659
                $this->user_creation_id = $obj->fk_user_author;
660
                $this->user_modification_id = $obj->fk_user_modif;
661
                $this->date_creation     = $this->db->jdate($obj->datec);
662
                $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
663
            }
664
            $this->db->free($result);
665
        } else {
666
            dol_print_error($this->db);
667
        }
668
    }
669
670
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
671
    /**
672
     *    Tag social contribution as paid completely
673
     *
674
     *    @deprecated
675
     *    @see setPaid()
676
     *    @param    User    $user       Object user making change
677
     *    @return   int                 Return integer <0 if KO, >0 if OK
678
     */
679
    public function set_paid($user)
680
    {
681
		// phpcs:enable
682
        dol_syslog(get_class($this) . "::set_paid is deprecated, use setPaid instead", LOG_NOTICE);
683
        return $this->setPaid($user);
684
    }
685
686
    /**
687
     *    Tag social contribution as paid completely
688
     *
689
     *    @param    User    $user       Object user making change
690
     *    @return   int                 Return integer <0 if KO, >0 if OK
691
     */
692
    public function setPaid($user)
693
    {
694
        $sql = "UPDATE " . MAIN_DB_PREFIX . "salary SET";
695
        $sql .= " paye = 1";
696
        $sql .= " WHERE rowid = " . ((int) $this->id);
697
698
        $return = $this->db->query($sql);
699
700
        if ($return) {
701
            $this->paye = 1;
702
            return 1;
703
        } else {
704
            return -1;
705
        }
706
    }
707
708
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
709
    /**
710
     *    Remove tag paid on social contribution
711
     *
712
     *    @param    User    $user       Object user making change
713
     *    @return   int                 Return integer <0 if KO, >0 if OK
714
     */
715
    public function set_unpaid($user)
716
    {
717
		// phpcs:enable
718
        $sql = "UPDATE " . MAIN_DB_PREFIX . "salary SET";
719
        $sql .= " paye = 0";
720
        $sql .= " WHERE rowid = " . ((int) $this->id);
721
722
        $return = $this->db->query($sql);
723
724
        if ($return) {
725
            $this->paye = 0;
726
            return 1;
727
        } else {
728
            return -1;
729
        }
730
    }
731
732
733
    /**
734
     * Return label of current status
735
     *
736
     * @param   int         $mode           0=label long, 1=labels short, 2=Picto + Label short, 3=Picto, 4=Picto + Label long, 5=Label short + Picto
737
     * @param   double      $alreadypaid    0=No payment already done, >0=Some payments were already done (we recommend to put here amount paid if you have it, 1 otherwise)
738
     * @return  string                      Label
739
     */
740
    public function getLibStatut($mode = 0, $alreadypaid = -1)
741
    {
742
        return $this->LibStatut($this->paye, $mode, $alreadypaid);
743
    }
744
745
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
746
    /**
747
     *  Return label of a given status
748
     *
749
     *  @param  int     $status         Id status
750
     *  @param  int     $mode           0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=short label + picto, 6=Long label + picto
751
     *  @param  double  $alreadypaid    0=No payment already done, >0=Some payments were already done (we recommend to put here amount paid if you have it, 1 otherwise)
752
     *  @return string                  Label
753
     */
754
    public function LibStatut($status, $mode = 0, $alreadypaid = -1)
755
    {
756
		// phpcs:enable
757
        global $langs;
758
759
        // Load translation files required by the page
760
        $langs->loadLangs(array("customers", "bills"));
761
762
        // We reinit status array to force to redefine them because label may change according to properties values.
763
        $this->labelStatus = array();
764
        $this->labelStatusShort = array();
765
766
        if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
767
            global $langs;
768
            //$langs->load("mymodule");
769
            $this->labelStatus[self::STATUS_UNPAID] = $langs->transnoentitiesnoconv('BillStatusNotPaid');
770
            $this->labelStatus[self::STATUS_PAID] = $langs->transnoentitiesnoconv('BillStatusPaid');
771
            if ($status == self::STATUS_UNPAID && $alreadypaid != 0) {
772
                $this->labelStatus[self::STATUS_UNPAID] = $langs->transnoentitiesnoconv("BillStatusStarted");
773
            }
774
            $this->labelStatusShort[self::STATUS_UNPAID] = $langs->transnoentitiesnoconv('BillStatusNotPaid');
775
            $this->labelStatusShort[self::STATUS_PAID] = $langs->transnoentitiesnoconv('BillStatusPaid');
776
            if ($status == self::STATUS_UNPAID && $alreadypaid != 0) {
777
                $this->labelStatusShort[self::STATUS_UNPAID] = $langs->transnoentitiesnoconv("BillStatusStarted");
778
            }
779
        }
780
781
        $statusType = 'status1';
782
        if ($status == 0 && $alreadypaid != 0) {
783
            $statusType = 'status3';
784
        }
785
        if ($status == 1) {
786
            $statusType = 'status6';
787
        }
788
789
        return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
790
    }
791
792
    /**
793
     *  Return clicable link of object (with eventually picto)
794
     *
795
     *  @param      string      $option                 Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link)
796
     *  @param      array       $arraydata              Array of data
797
     *  @return     string                              HTML Code for Kanban thumb.
798
     */
799
    public function getKanbanView($option = '', $arraydata = null)
800
    {
801
        global $langs;
802
803
        $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
804
805
        $return = '<div class="box-flex-item box-flex-grow-zero">';
806
        $return .= '<div class="info-box info-box-sm">';
807
        $return .= '<span class="info-box-icon bg-infobox-action">';
808
        $return .= img_picto('', $this->picto);
809
        $return .= '</span>';
810
        $return .= '<div class="info-box-content">';
811
        $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . (method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref) . '</span>';
812
        if ($selected >= 0) {
813
            $return .= '<input id="cb' . $this->id . '" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="' . $this->id . '"' . ($selected ? ' checked="checked"' : '') . '>';
814
        }
815
        if (!empty($arraydata['user']) && is_object($arraydata['user'])) {
816
            $return .= '<br><span class="info-box-label">' . $arraydata['user']->getNomUrl(1, '', 0, 0, 16, 0, '', 'maxwidth100') . '</span>';
817
        }
818
        if (property_exists($this, 'amount')) {
819
            $return .= '<br><span class="info-box-label amount">' . price($this->amount) . '</span>';
820
            if (property_exists($this, 'type_payment') && !empty($this->type_payment)) {
821
                $return .= ' <span class="info-box-label opacitymedium small">';
822
                if ($langs->trans("PaymentTypeShort" . $this->type_payment) != "PaymentTypeShort" . $this->type_payment) {
823
                    $return .= $langs->trans("PaymentTypeShort" . $this->type_payment);
824
                } elseif ($langs->trans("PaymentType" . $this->type_payment) != "PaymentType" . $this->type_payment) {
825
                    $return .= $langs->trans("PaymentType" . $this->type_payment);
826
                }
827
                $return .= '</span>';
828
            }
829
        }
830
        if (method_exists($this, 'LibStatut')) {
831
            $return .= '<br><div class="info-box-status">' . $this->getLibStatut(3, isset($this->alreadypaid) ? $this->alreadypaid : $this->totalpaid) . '</div>';
0 ignored issues
show
Bug Best Practice introduced by
The property $alreadypaid is declared private in Dolibarr\Core\Base\CommonObject. Since you implement __get, consider adding a @property or @property-read.
Loading history...
832
        }
833
        $return .= '</div>';
834
        $return .= '</div>';
835
        $return .= '</div>';
836
        return $return;
837
    }
838
839
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
840
    /**
841
     *  Create a withdrawal request for a direct debit order or a credit transfer order.
842
     *  Use the remain to pay excluding all existing open direct debit requests.
843
     *
844
     *  @param      User    $fuser                      User asking the direct debit transfer
845
     *  @param      float   $amount                     Amount we request direct debit for
846
     *  @param      string  $type                       'direct-debit' or 'bank-transfer'
847
     *  @param      string  $sourcetype                 Source ('facture' or 'supplier_invoice')
848
     *  @param      int     $checkduplicateamongall     0=Default (check among open requests only to find if request already exists). 1=Check also among requests completely processed and cancel if at least 1 request exists whatever is its status.
849
     *  @return     int                                 Return integer <0 if KO, 0 if a request already exists, >0 if OK
850
     */
851
    public function demande_prelevement($fuser, $amount = 0, $type = 'direct-debit', $sourcetype = 'salaire', $checkduplicateamongall = 0)
852
    {
853
		// phpcs:enable
854
        global $conf, $mysoc;
855
856
        $error = 0;
857
858
        dol_syslog(get_class($this) . "::demande_prelevement", LOG_DEBUG);
859
        if ($this->paye == 0) {
860
            require_once constant('DOL_DOCUMENT_ROOT') . '/societe/class/companybankaccount.class.php';
861
            $bac = new CompanyBankAccount($this->db);
862
            // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
863
            $bac->fetch(0, '', $mysoc->id);
864
865
            $sql = "SELECT count(rowid) as nb";
866
            $sql .= " FROM " . $this->db->prefix() . "prelevement_demande";
867
            if ($type == 'salaire') {
868
                $sql .= " WHERE fk_salary = " . ((int) $this->id);
869
            } else {
870
                $sql .= " WHERE fk_facture = " . ((int) $this->id);
871
            }
872
            $sql .= " AND type = 'ban'"; // To exclude record done for some online payments
873
            if (empty($checkduplicateamongall)) {
874
                $sql .= " AND traite = 0";
875
            }
876
877
            dol_syslog(get_class($this) . "::demande_prelevement", LOG_DEBUG);
878
879
            $resql = $this->db->query($sql);
880
            if ($resql) {
881
                $obj = $this->db->fetch_object($resql);
882
                if ($obj && $obj->nb == 0) {    // If no request found yet
883
                    $now = dol_now();
884
885
                    $totalpaid = $this->getSommePaiement();
886
                    // $totalcreditnotes = $this->getSumCreditNotesUsed();
887
                    // $totaldeposits = $this->getSumDepositsUsed();
888
                    //print "totalpaid=".$totalpaid." totalcreditnotes=".$totalcreditnotes." totaldeposts=".$totaldeposits;
889
890
                    // We can also use bcadd to avoid pb with floating points
891
                    // For example print 239.2 - 229.3 - 9.9; does not return 0.
892
                    //$resteapayer=bcadd($this->total_ttc,$totalpaid,$conf->global->MAIN_MAX_DECIMALS_TOT);
893
                    //$resteapayer=bcadd($resteapayer,$totalavoir,$conf->global->MAIN_MAX_DECIMALS_TOT);
894
                    // if (empty($amount)) {
895
                    //  $amount = price2num($this->total_ttc - $totalpaid - $totalcreditnotes - $totaldeposits, 'MT');
896
                    // }
897
898
                    if (is_numeric($amount) && $amount != 0) {
899
                        $sql = 'INSERT INTO ' . $this->db->prefix() . 'prelevement_demande(';
900
                        if ($type == 'salaire') {
901
                            $sql .= 'fk_salary, ';
902
                        } else {
903
                            $sql .= 'fk_facture, ';
904
                        }
905
                        $sql .= ' amount, date_demande, fk_user_demande, code_banque, code_guichet, number, cle_rib, sourcetype, type, entity)';
906
                        $sql .= " VALUES (" . ((int) $this->id);
907
                        $sql .= ", " . ((float) price2num($amount));
908
                        $sql .= ", '" . $this->db->idate($now) . "'";
909
                        $sql .= ", " . ((int) $fuser->id);
910
                        $sql .= ", '" . $this->db->escape($bac->code_banque) . "'";
911
                        $sql .= ", '" . $this->db->escape($bac->code_guichet) . "'";
912
                        $sql .= ", '" . $this->db->escape($bac->number) . "'";
913
                        $sql .= ", '" . $this->db->escape($bac->cle_rib) . "'";
914
                        $sql .= ", '" . $this->db->escape($sourcetype) . "'";
915
                        $sql .= ", 'ban'";
916
                        $sql .= ", " . ((int) $conf->entity);
917
                        $sql .= ")";
918
919
                        dol_syslog(get_class($this) . "::demande_prelevement", LOG_DEBUG);
920
                        $resql = $this->db->query($sql);
921
                        if (!$resql) {
922
                            $this->error = $this->db->lasterror();
923
                            dol_syslog(get_class($this) . '::demandeprelevement Erreur');
924
                            $error++;
925
                        }
926
                    } else {
927
                        $this->error = 'WithdrawRequestErrorNilAmount';
928
                        dol_syslog(get_class($this) . '::demandeprelevement WithdrawRequestErrorNilAmount');
929
                        $error++;
930
                    }
931
932
                    if (!$error) {
933
                        // Force payment mode of invoice to withdraw
934
                        $payment_mode_id = dol_getIdFromCode($this->db, ($type == 'bank-transfer' ? 'VIR' : 'PRE'), 'c_paiement', 'code', 'id', 1);
935
                        if ($payment_mode_id > 0) {
936
                            $result = $this->setPaymentMethods($payment_mode_id);
937
                        }
938
                    }
939
940
                    if ($error) {
941
                        return -1;
942
                    }
943
                    return 1;
944
                } else {
945
                    $this->error = "A request already exists";
946
                    dol_syslog(get_class($this) . '::demandeprelevement Can t create a request to generate a direct debit, a request already exists.');
947
                    return 0;
948
                }
949
            } else {
950
                $this->error = $this->db->error();
951
                dol_syslog(get_class($this) . '::demandeprelevement Error -2');
952
                return -2;
953
            }
954
        } else {
955
            $this->error = "Status of invoice does not allow this";
956
            dol_syslog(get_class($this) . "::demandeprelevement " . $this->error . " $this->status, $this->paye, $this->mode_reglement_id");
957
            return -3;
958
        }
959
    }
960
961
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
962
    /**
963
     *  Remove a direct debit request or a credit transfer request
964
     *
965
     *  @param  User    $fuser      User making delete
966
     *  @param  int     $did        ID of request to delete
967
     *  @return int                 Return integer <0 if OK, >0 if KO
968
     */
969
    public function demande_prelevement_delete($fuser, $did)
970
    {
971
		// phpcs:enable
972
        $sql = 'DELETE FROM ' . $this->db->prefix() . 'prelevement_demande';
973
        $sql .= ' WHERE rowid = ' . ((int) $did);
974
        $sql .= ' AND traite = 0';
975
        if ($this->db->query($sql)) {
976
            return 0;
977
        } else {
978
            $this->error = $this->db->lasterror();
979
            dol_syslog(get_class($this) . '::demande_prelevement_delete Error ' . $this->error);
980
            return -1;
981
        }
982
    }
983
}
984