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

Fichinter::getNomUrl()   F

Complexity

Conditions 27
Paths 11520

Size

Total Lines 83
Code Lines 56

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 27
eloc 56
nc 11520
nop 5
dl 0
loc 83
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
/* Copyright (C) 2002-2003  Rodolphe Quiedeville        <[email protected]>
4
 * Copyright (C) 2004-2014  Laurent Destailleur         <[email protected]>
5
 * Copyright (C) 2005-2012  Regis Houssin               <[email protected]>
6
 * Copyright (C) 2011-2020  Juanjo Menent               <[email protected]>
7
 * Copyright (C) 2015       Marcos García               <[email protected]>
8
 * Copyright (C) 2015-2020  Charlene Benke              <[email protected]>
9
 * Copyright (C) 2018       Nicolas ZABOURI	            <[email protected]>
10
 * Copyright (C) 2018-2024  Frédéric France             <[email protected]>
11
 * Copyright (C) 2023-2024  William Mead                <[email protected]>
12
 * Copyright (C) 2024		MDW							<[email protected]>
13
 * Copyright (C) 2024       Rafael San José             <[email protected]>
14
 *
15
 * This program is free software; you can redistribute it and/or modify
16
 * it under the terms of the GNU General Public License as published by
17
 * the Free Software Foundation; either version 3 of the License, or
18
 * (at your option) any later version.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 * GNU General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU General Public License
26
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
27
 */
28
29
namespace Dolibarr\Code\FichInter\Classes;
30
31
use Dolibarr\Core\Base\CommonObject;
32
33
/**
34
 *  \file       htdocs/fichinter/class/fichinter.class.php
35
 *  \ingroup    fichinter
36
 *  \brief      File for class to manage interventions
37
 */
38
39
/**
40
 *  Class to manage interventions
41
 */
42
class Fichinter extends CommonObject
43
{
44
    public $fields = array(
45
        'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 10),
46
        'fk_soc' => array('type' => 'integer:Societe:societe/class/societe.class.php', 'label' => 'ThirdParty', 'enabled' => 'isModEnabled("societe")', 'visible' => -1, 'notnull' => 1, 'position' => 15),
47
        'fk_projet' => array('type' => 'integer:Project:projet/class/project.class.php:1:(fk_statut:=:1)', 'label' => 'Fk projet', 'enabled' => 'isModEnabled("project")', 'visible' => -1, 'position' => 20),
48
        'fk_contrat' => array('type' => 'integer', 'label' => 'Fk contrat', 'enabled' => '$conf->contrat->enabled', 'visible' => -1, 'position' => 25),
49
        'ref' => array('type' => 'varchar(30)', 'label' => 'Ref', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'showoncombobox' => 1, 'position' => 30),
50
        'ref_ext' => array('type' => 'varchar(255)', 'label' => 'Ref ext', 'enabled' => 1, 'visible' => 0, 'position' => 35),
51
        'ref_client' => array('type' => 'varchar(255)', 'label' => 'RefCustomer', 'enabled' => 1, 'visible' => -1, 'position' => 36),
52
        'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => '1', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 40, 'index' => 1),
53
        'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 45),
54
        'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -1, 'position' => 50),
55
        'date_valid' => array('type' => 'datetime', 'label' => 'DateValidation', 'enabled' => 1, 'visible' => -1, 'position' => 55),
56
        'datei' => array('type' => 'date', 'label' => 'Datei', 'enabled' => 1, 'visible' => -1, 'position' => 60),
57
        'fk_user_author' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'Fk user author', 'enabled' => 1, 'visible' => -1, 'position' => 65),
58
        'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'position' => 70),
59
        'fk_user_valid' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserValidation', 'enabled' => 1, 'visible' => -1, 'position' => 75),
60
        'dateo' => array('type' => 'date', 'label' => 'Dateo', 'enabled' => 1, 'visible' => -1, 'position' => 85),
61
        'datee' => array('type' => 'date', 'label' => 'Datee', 'enabled' => 1, 'visible' => -1, 'position' => 90),
62
        'datet' => array('type' => 'date', 'label' => 'Datet', 'enabled' => 1, 'visible' => -1, 'position' => 95),
63
        'duree' => array('type' => 'double', 'label' => 'Duree', 'enabled' => 1, 'visible' => -1, 'position' => 100),
64
        'signed_status' => array('type' => 'smallint(6)', 'label' => 'SignedStatus', 'enabled' => 1, 'visible' => -1, 'position' => 101, 'arrayofkeyval' => array(0 => 'NoSignature', 1 => 'SignedSender', 2 => 'SignedReceiver', 9 => 'SignedAll')),
65
        'description' => array('type' => 'html', 'label' => 'Description', 'enabled' => 1, 'visible' => -1, 'position' => 105, 'showoncombobox' => 2),
66
        'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 110),
67
        'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 115),
68
        'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'visible' => 0, 'position' => 120),
69
        'last_main_doc' => array('type' => 'varchar(255)', 'label' => 'Last main doc', 'enabled' => 1, 'visible' => -1, 'position' => 125),
70
        'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'position' => 130),
71
        'extraparams' => array('type' => 'varchar(255)', 'label' => 'Extraparams', 'enabled' => 1, 'visible' => -1, 'position' => 135),
72
        'fk_statut' => array('type' => 'integer', 'label' => 'Fk statut', 'enabled' => 1, 'visible' => -1, 'position' => 500),
73
    );
74
75
    /**
76
     * @var string ID to identify managed object
77
     */
78
    public $element = 'fichinter';
79
80
    /**
81
     * @var string Name of table without prefix where object is stored
82
     */
83
    public $table_element = 'fichinter';
84
85
    /**
86
     * @var string Field with ID of parent key if this field has a parent
87
     */
88
    public $fk_element = 'fk_fichinter';
89
90
    /**
91
     * @var string    Name of subtable line
92
     */
93
    public $table_element_line = 'fichinterdet';
94
95
    /**
96
     * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
97
     */
98
    public $picto = 'intervention';
99
100
    /**
101
     * {@inheritdoc}
102
     */
103
    protected $table_ref_field = 'ref';
104
105
    /**
106
     * @var int Thirdparty Id
107
     */
108
    public $socid;
109
110
    public $author;
111
112
    /**
113
     * Date creation record (datec)
114
     *
115
     * @var integer
116
     */
117
    public $datec;
118
119
    public $datev;
120
    public $dateo;
121
    public $datee;
122
    public $datet;
123
124
    /**
125
     * Date modification record (tms)
126
     *
127
     * @var integer
128
     */
129
    public $datem;
130
131
    /**
132
     * @var int duration
133
     */
134
    public $duration;
135
136
    /**
137
     * @var int status
138
     */
139
    public $statut = 0; // 0=draft, 1=validated, 2=invoiced, 3=Terminate
140
141
    /**
142
     * Signed Status of the intervention (0=NoSignature, 1=SignedBySender, 2=SignedByReceiver, 9=SignedByAll)
143
     * @var int
144
     */
145
    public $signed_status = 0;
146
147
    /**
148
     * @var string description
149
     */
150
    public $description;
151
152
    /**
153
     * @var int Contract ID
154
     */
155
    public $fk_contrat = 0;
156
157
    /**
158
     * @var int Project ID
159
     */
160
    public $fk_project = 0;
161
162
    /**
163
     * Customer Ref
164
     * @var string
165
     */
166
    public $ref_client;
167
168
    /**
169
     * @var array extraparams
170
     */
171
    public $extraparams = array();
172
173
    /**
174
     * @var FichinterLigne[] lines
175
     */
176
    public $lines = array();
177
178
    /**
179
     * Draft status
180
     */
181
    const STATUS_DRAFT = 0;
182
183
    /**
184
     * Validated status
185
     */
186
    const STATUS_VALIDATED = 1;
187
188
    /**
189
     * Billed
190
     */
191
    const STATUS_BILLED = 2;
192
193
    /**
194
     * Closed
195
     */
196
    const STATUS_CLOSED = 3;
197
198
199
    /**
200
     * No signature
201
     */
202
    const STATUS_NO_SIGNATURE    = 0;
203
204
    /**
205
     * Signed by sender
206
     */
207
    const STATUS_SIGNED_SENDER   = 1;
208
209
    /**
210
     * Signed by receiver
211
     */
212
    const STATUS_SIGNED_RECEIVER = 2;
213
214
    /**
215
     * Signed by all
216
     */
217
    const STATUS_SIGNED_ALL      = 9; // To handle future kind of signature (ex: tripartite contract)
218
219
220
    /**
221
     * Date delivery
222
     * @var string|int      Delivery int
223
     */
224
    public $date_delivery;
225
226
    /**
227
     * Author Id
228
     * @var int
229
     */
230
    public $user_author_id;
231
232
233
    /**
234
     *  Constructor
235
     *
236
     *  @param  DoliDB  $db     Database handler
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\FichInter\Classes\DoliDB was not found. Did you mean DoliDB? If so, make sure to prefix the type with \.
Loading history...
237
     */
238
    public function __construct($db)
239
    {
240
        $this->db = $db;
241
    }
242
243
    /**
244
     *  Load indicators into this->nb for board
245
     *
246
     *  @return     int         Return integer <0 if KO, >0 if OK
247
     */
248
    public function loadStateBoard()
249
    {
250
        global $user;
251
252
        $this->nb = array();
253
        $clause = "WHERE";
254
255
        $sql = "SELECT count(fi.rowid) as nb";
256
        $sql .= " FROM " . MAIN_DB_PREFIX . "fichinter as fi";
257
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe as s ON fi.fk_soc = s.rowid";
258
        if (!$user->hasRight('societe', 'client', 'voir')) {
259
            $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as sc ON s.rowid = sc.fk_soc";
260
            $sql .= " WHERE sc.fk_user = " . ((int) $user->id);
261
            $clause = "AND";
262
        }
263
        $sql .= " " . $clause . " fi.entity IN (" . getEntity('intervention') . ")";
264
265
        $resql = $this->db->query($sql);
266
        if ($resql) {
267
            while ($obj = $this->db->fetch_object($resql)) {
268
                $this->nb["interventions"] = $obj->nb;
269
            }
270
            $this->db->free($resql);
271
            return 1;
272
        } else {
273
            dol_print_error($this->db);
274
            $this->error = $this->db->error();
275
            return -1;
276
        }
277
    }
278
279
    /**
280
     *  Create an intervention into data base
281
     *
282
     *  @param      User    $user       Object user that make creation
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\FichInter\Classes\User was not found. Did you mean User? If so, make sure to prefix the type with \.
Loading history...
283
     *  @param      int     $notrigger  Disable all triggers
284
     *  @return     int     Return integer <0 if KO, >0 if OK
285
     */
286
    public function create($user, $notrigger = 0)
287
    {
288
        global $conf, $langs;
289
290
        $error = 0;
291
292
        dol_syslog(get_class($this) . "::create ref=" . $this->ref);
293
294
        // Check parameters
295
        if (!empty($this->ref)) {   // We check that ref is not already used
296
            $result = self::isExistingObject($this->element, 0, $this->ref); // Check ref is not yet used
297
            if ($result > 0) {
298
                $this->error = 'ErrorRefAlreadyExists';
299
                dol_syslog(get_class($this) . "::create " . $this->error, LOG_WARNING);
300
                $this->db->rollback();
301
                return -1;
302
            }
303
        }
304
        if (!is_numeric($this->duration)) {
305
            $this->duration = 0;
306
        }
307
        if (isset($this->ref_client)) {
308
            $this->ref_client = trim($this->ref_client);
309
        }
310
311
        if ($this->socid <= 0) {
312
            $this->error = 'ErrorFicheinterCompanyDoesNotExist';
313
            dol_syslog(get_class($this) . "::create " . $this->error, LOG_ERR);
314
            return -1;
315
        }
316
317
        $soc = new Societe($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\FichInter\Classes\Societe was not found. Did you mean Societe? If so, make sure to prefix the type with \.
Loading history...
318
        $result = $soc->fetch($this->socid);
319
320
        $now = dol_now();
321
322
        $this->db->begin();
323
324
        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "fichinter (";
325
        $sql .= "fk_soc";
326
        $sql .= ", datec";
327
        $sql .= ", ref";
328
        $sql .= ", ref_client";
329
        $sql .= ", entity";
330
        $sql .= ", fk_user_author";
331
        $sql .= ", fk_user_modif";
332
        $sql .= ", description";
333
        $sql .= ", model_pdf";
334
        $sql .= ", fk_projet";
335
        $sql .= ", fk_contrat";
336
        $sql .= ", fk_statut";
337
        $sql .= ", note_private";
338
        $sql .= ", note_public";
339
        $sql .= ") ";
340
        $sql .= " VALUES (";
341
        $sql .= $this->socid;
342
        $sql .= ", '" . $this->db->idate($now) . "'";
343
        $sql .= ", '" . $this->db->escape($this->ref) . "'";
344
        $sql .= ", " . ($this->ref_client ? "'" . $this->db->escape($this->ref_client) . "'" : "null");
345
        $sql .= ", " . ((int) $conf->entity);
346
        $sql .= ", " . ((int) $user->id);
347
        $sql .= ", " . ((int) $user->id);
348
        $sql .= ", " . ($this->description ? "'" . $this->db->escape($this->description) . "'" : "null");
349
        $sql .= ", '" . $this->db->escape($this->model_pdf) . "'";
350
        $sql .= ", " . ($this->fk_project ? ((int) $this->fk_project) : 0);
351
        $sql .= ", " . ($this->fk_contrat ? ((int) $this->fk_contrat) : 0);
352
        $sql .= ", " . ((int) $this->statut);
353
        $sql .= ", " . ($this->note_private ? "'" . $this->db->escape($this->note_private) . "'" : "null");
354
        $sql .= ", " . ($this->note_public ? "'" . $this->db->escape($this->note_public) . "'" : "null");
355
        $sql .= ")";
356
357
        dol_syslog(get_class($this) . "::create", LOG_DEBUG);
358
        $result = $this->db->query($sql);
359
        if ($result) {
360
            $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . "fichinter");
361
362
            if ($this->id) {
363
                $this->ref = '(PROV' . $this->id . ')';
364
                $sql = 'UPDATE ' . MAIN_DB_PREFIX . "fichinter SET ref='" . $this->db->escape($this->ref) . "' WHERE rowid=" . ((int) $this->id);
365
366
                dol_syslog(get_class($this) . "::create", LOG_DEBUG);
367
                $resql = $this->db->query($sql);
368
                if (!$resql) {
369
                    $error++;
370
                }
371
            }
372
373
            if (!$error) {
374
                $result = $this->insertExtraFields();
375
                if ($result < 0) {
376
                    $error++;
377
                }
378
            }
379
380
            // Add linked object
381
            if (!$error && $this->origin && $this->origin_id) {
382
                $ret = $this->add_object_linked();
383
                if (!$ret) {
384
                    dol_print_error($this->db);
385
                }
386
            }
387
388
389
            if (!$error && !$notrigger) {
390
                // Call trigger
391
                $result = $this->call_trigger('FICHINTER_CREATE', $user);
392
                if ($result < 0) {
393
                    $error++;
394
                }
395
                // End call triggers
396
            }
397
398
            if (!$error) {
399
                $this->db->commit();
400
                return $this->id;
401
            } else {
402
                $this->db->rollback();
403
                $this->error = implode(',', $this->errors);
404
                dol_syslog(get_class($this) . "::create " . $this->error, LOG_ERR);
405
                return -1;
406
            }
407
        } else {
408
            $this->error = $this->db->error();
409
            $this->db->rollback();
410
            return -1;
411
        }
412
    }
413
414
    /**
415
     *  Update an intervention
416
     *
417
     *  @param      User    $user       Object user that make creation
418
     *  @param      int     $notrigger  Disable all triggers
419
     *  @return     int     Return integer <0 if KO, >0 if OK
420
     */
421
    public function update($user, $notrigger = 0)
422
    {
423
        global $conf;
424
425
        if (!is_numeric($this->duration)) {
426
            $this->duration = 0;
427
        }
428
        if (!dol_strlen($this->fk_project)) {
429
            $this->fk_project = 0;
430
        }
431
        if (isset($this->ref_client)) {
432
            $this->ref_client = trim($this->ref_client);
433
        }
434
435
        $error = 0;
436
437
        $this->db->begin();
438
439
        $sql = "UPDATE " . MAIN_DB_PREFIX . "fichinter SET ";
440
        $sql .= "description  = '" . $this->db->escape($this->description) . "'";
441
        $sql .= ", duree = " . ((int) $this->duration);
442
        $sql .= ", ref_client = " . ($this->ref_client ? "'" . $this->db->escape($this->ref_client) . "'" : "null");
443
        $sql .= ", fk_projet = " . ((int) $this->fk_project);
444
        $sql .= ", note_private = " . ($this->note_private ? "'" . $this->db->escape($this->note_private) . "'" : "null");
445
        $sql .= ", note_public = " . ($this->note_public ? "'" . $this->db->escape($this->note_public) . "'" : "null");
446
        $sql .= ", fk_user_modif = " . ((int) $user->id);
447
        $sql .= " WHERE rowid = " . ((int) $this->id);
448
449
        dol_syslog(get_class($this) . "::update", LOG_DEBUG);
450
        if ($this->db->query($sql)) {
451
            if (!$error) {
452
                $result = $this->insertExtraFields();
453
                if ($result < 0) {
454
                    $error++;
455
                }
456
            }
457
458
            if (!$error && !$notrigger) {
459
                // Call trigger
460
                $result = $this->call_trigger('FICHINTER_MODIFY', $user);
461
                if ($result < 0) {
462
                    $error++;
463
                    $this->db->rollback();
464
                    return -1;
465
                }
466
                // End call triggers
467
            }
468
469
            $this->db->commit();
470
            return 1;
471
        } else {
472
            $this->error = $this->db->error();
473
            $this->db->rollback();
474
            return -1;
475
        }
476
    }
477
478
    /**
479
     *  Fetch a intervention
480
     *
481
     *  @param      int     $rowid      Id of intervention
482
     *  @param      string  $ref        Ref of intervention
483
     *  @return     int                 Return integer <0 if KO, >0 if OK
484
     */
485
    public function fetch($rowid, $ref = '')
486
    {
487
        $sql = "SELECT f.rowid, f.ref, f.ref_client, f.description, f.fk_soc, f.fk_statut as status,";
488
        $sql .= " f.datec, f.dateo, f.datee, f.datet, f.fk_user_author,";
489
        $sql .= " f.date_valid as datev,";
490
        $sql .= " f.tms as datem,";
491
        $sql .= " f.duree, f.fk_projet as fk_project, f.note_public, f.note_private, f.model_pdf, f.last_main_doc, f.extraparams, fk_contrat, f.entity as entity";
492
        $sql .= " FROM " . MAIN_DB_PREFIX . "fichinter as f";
493
        if ($ref) {
494
            $sql .= " WHERE f.entity IN (" . getEntity('intervention') . ")";
495
            $sql .= " AND f.ref = '" . $this->db->escape($ref) . "'";
496
        } else {
497
            $sql .= " WHERE f.rowid = " . ((int) $rowid);
498
        }
499
500
        dol_syslog(get_class($this) . "::fetch", LOG_DEBUG);
501
        $resql = $this->db->query($sql);
502
        if ($resql) {
503
            if ($this->db->num_rows($resql)) {
504
                $obj = $this->db->fetch_object($resql);
505
506
                $this->id           = $obj->rowid;
507
                $this->ref          = $obj->ref;
508
                $this->ref_client   = $obj->ref_client;
509
                $this->description  = $obj->description;
510
                $this->socid        = $obj->fk_soc;
511
                $this->status       = $obj->status;
512
                $this->statut       = $obj->status; // deprecated
513
                $this->duration     = $obj->duree;
514
                $this->datec        = $this->db->jdate($obj->datec);
515
                $this->dateo        = $this->db->jdate($obj->dateo);
516
                $this->datee        = $this->db->jdate($obj->datee);
517
                $this->datet        = $this->db->jdate($obj->datet);
518
                $this->datev        = $this->db->jdate($obj->datev);
519
                $this->datem        = $this->db->jdate($obj->datem);
520
                $this->fk_project   = $obj->fk_project;
521
                $this->note_public  = $obj->note_public;
522
                $this->note_private = $obj->note_private;
523
                $this->model_pdf    = $obj->model_pdf;
524
                $this->fk_contrat = $obj->fk_contrat;
525
                $this->entity = $obj->entity;
526
527
                $this->user_creation_id = $obj->fk_user_author;
528
529
                $this->extraparams = (array) json_decode($obj->extraparams, true);
530
531
                $this->last_main_doc = $obj->last_main_doc;
532
533
                // Retrieve extrafields
534
                $this->fetch_optionals();
535
536
                /*
537
                 * Lines
538
                 */
539
                $result = $this->fetch_lines();
540
                if ($result < 0) {
541
                    return -3;
542
                }
543
                $this->db->free($resql);
544
                return 1;
545
            }
546
547
            return 0;
548
        } else {
549
            $this->error = $this->db->lasterror();
550
            return -1;
551
        }
552
    }
553
554
    /**
555
     *  Set status to draft
556
     *
557
     *  @param      User    $user   User that set draft
558
     *  @return     int             Return integer <0 if KO, >0 if OK
559
     */
560
    public function setDraft($user)
561
    {
562
        $error = 0;
563
564
        // Protection
565
        if ($this->statut <= self::STATUS_DRAFT) {
566
            return 0;
567
        }
568
569
        dol_syslog(get_class($this) . "::setDraft", LOG_DEBUG);
570
571
        $this->oldcopy = dol_clone($this, 2);
572
573
        $this->db->begin();
574
575
        $sql = "UPDATE " . MAIN_DB_PREFIX . "fichinter";
576
        $sql .= " SET fk_statut = " . self::STATUS_DRAFT;
577
        $sql .= " WHERE rowid = " . ((int) $this->id);
578
579
        $resql = $this->db->query($sql);
580
        if ($resql) {
581
            if (!$error) {
582
                // Call trigger
583
                $result = $this->call_trigger('FICHINTER_UNVALIDATE', $user);
584
                if ($result < 0) {
585
                    $error++;
586
                }
587
            }
588
589
            if (!$error) {
590
                $this->statut = self::STATUS_DRAFT;
591
                $this->db->commit();
592
                return 1;
593
            } else {
594
                $this->db->rollback();
595
                return -1;
596
            }
597
        } else {
598
            $this->db->rollback();
599
            $this->error = $this->db->lasterror();
600
            return -1;
601
        }
602
    }
603
604
    /**
605
     *  Validate a intervention
606
     *
607
     *  @param      User        $user       User that validate
608
     *  @param      int         $notrigger  1=Does not execute triggers, 0= execute triggers
609
     *  @return     int                     Return integer <0 if KO, >0 if OK
610
     */
611
    public function setValid($user, $notrigger = 0)
612
    {
613
        global $conf;
614
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
615
616
        $error = 0;
617
618
        if ($this->status != self::STATUS_VALIDATED) {
619
            $this->db->begin();
620
621
            $now = dol_now();
622
623
            // Define new ref
624
            if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
625
                $num = $this->getNextNumRef($this->thirdparty);
626
            } else {
627
                $num = $this->ref;
628
            }
629
            $this->newref = dol_sanitizeFileName($num);
630
631
            $sql = "UPDATE " . MAIN_DB_PREFIX . "fichinter";
632
            $sql .= " SET fk_statut = 1";
633
            $sql .= ", ref = '" . $this->db->escape($num) . "'";
634
            $sql .= ", date_valid = '" . $this->db->idate($now) . "'";
635
            $sql .= ", fk_user_valid = " . ($user->id > 0 ? (int) $user->id : "null");
636
            $sql .= " WHERE rowid = " . ((int) $this->id);
637
            $sql .= " AND entity = " . ((int) $this->entity);
638
639
            $sql .= " AND fk_statut = 0";
640
641
            dol_syslog(get_class($this) . "::setValid", LOG_DEBUG);
642
            $resql = $this->db->query($sql);
643
            if (!$resql) {
644
                dol_print_error($this->db);
645
                $error++;
646
            }
647
648
            if (!$error && !$notrigger) {
649
                // Call trigger
650
                $result = $this->call_trigger('FICHINTER_VALIDATE', $user);
651
                if ($result < 0) {
652
                    $error++;
653
                }
654
                // End call triggers
655
            }
656
657
            if (!$error) {
658
                $this->oldref = $this->ref;
659
660
                // Rename directory if dir was a temporary ref
661
                if (preg_match('/^[\(]?PROV/i', $this->ref)) {
662
                    require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
663
664
                    // Now we rename also files into index
665
                    $sql = 'UPDATE ' . MAIN_DB_PREFIX . "ecm_files set filename = CONCAT('" . $this->db->escape($this->newref) . "', SUBSTR(filename, " . (strlen($this->ref) + 1) . ")), filepath = 'ficheinter/" . $this->db->escape($this->newref) . "'";
666
                    $sql .= " WHERE filename LIKE '" . $this->db->escape($this->ref) . "%' AND filepath = 'ficheinter/" . $this->db->escape($this->ref) . "' and entity = " . ((int) $this->entity);
667
                    $resql = $this->db->query($sql);
668
                    if (!$resql) {
669
                        $error++;
670
                        $this->error = $this->db->lasterror();
671
                    }
672
                    $sql = 'UPDATE ' . MAIN_DB_PREFIX . "ecm_files set filepath = 'ficheinter/" . $this->db->escape($this->newref) . "'";
673
                    $sql .= " WHERE filepath = 'ficheinter/" . $this->db->escape($this->ref) . "' and entity = " . $conf->entity;
674
                    $resql = $this->db->query($sql);
675
                    if (!$resql) {
676
                        $error++;
677
                        $this->error = $this->db->lasterror();
678
                    }
679
680
                    // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
681
                    $oldref = dol_sanitizeFileName($this->ref);
682
                    $newref = dol_sanitizeFileName($num);
683
                    $dirsource = $conf->ficheinter->dir_output . '/' . $oldref;
684
                    $dirdest = $conf->ficheinter->dir_output . '/' . $newref;
685
                    if (!$error && file_exists($dirsource)) {
686
                        dol_syslog(get_class($this) . "::setValid rename dir " . $dirsource . " into " . $dirdest);
687
688
                        if (@rename($dirsource, $dirdest)) {
689
                            dol_syslog("Rename ok");
690
                            // Rename docs starting with $oldref with $newref
691
                            $listoffiles = dol_dir_list($conf->ficheinter->dir_output . '/' . $newref, 'files', 1, '^' . preg_quote($oldref, '/'));
692
                            foreach ($listoffiles as $fileentry) {
693
                                $dirsource = $fileentry['name'];
694
                                $dirdest = preg_replace('/^' . preg_quote($oldref, '/') . '/', $newref, $dirsource);
695
                                $dirsource = $fileentry['path'] . '/' . $dirsource;
696
                                $dirdest = $fileentry['path'] . '/' . $dirdest;
697
                                @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

697
                                /** @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...
698
                            }
699
                        }
700
                    }
701
                }
702
            }
703
704
            // Set new ref and define current statut
705
            if (!$error) {
706
                $this->ref = $num;
707
                $this->status = self::STATUS_VALIDATED;
708
                $this->statut = self::STATUS_VALIDATED; // deprecated
709
                $this->date_validation = $now;
710
                $this->db->commit();
711
                return 1;
712
            } else {
713
                $this->db->rollback();
714
                dol_syslog(get_class($this) . "::setValid " . $this->error, LOG_ERR);
715
                return -1;
716
            }
717
        }
718
719
        return 0;
720
    }
721
722
    /**
723
     *  Close intervention
724
     *
725
     *  @param      User    $user       Object user that close
726
     *  @param      int     $notrigger  1=Does not execute triggers, 0=Execute triggers
727
     *  @return     int                 Return integer <0 if KO, >0 if OK
728
     */
729
    public function setClose($user, $notrigger = 0)
730
    {
731
        global $conf;
732
733
        $error = 0;
734
735
        if ($this->statut == self::STATUS_CLOSED) {
736
            return 0;
737
        } else {
738
            $this->db->begin();
739
740
            $now = dol_now();
741
742
            $sql = 'UPDATE ' . MAIN_DB_PREFIX . $this->table_element;
743
            $sql .= ' SET fk_statut = ' . self::STATUS_CLOSED . ',';
744
            $sql .= " datet = '" . $this->db->idate($now) . "',";
745
            $sql .= " fk_user_modif = " . ((int) $user->id);
746
            $sql .= " WHERE rowid = " . ((int) $this->id);
747
            $sql .= " AND fk_statut > " . self::STATUS_DRAFT;
748
            $sql .= " AND entity = " . ((int) $conf->entity);
749
750
            if ($this->db->query($sql)) {
751
                if (!$notrigger) {
752
                    // Call trigger
753
                    $result = $this->call_trigger('FICHINTER_CLOSE', $user);
754
                    if ($result < 0) {
755
                        $error++;
756
                    }
757
                    // End call triggers
758
                }
759
760
                if (!$error) {
761
                    $this->statut = self::STATUS_CLOSED;
762
                    $this->db->commit();
763
                    return 1;
764
                } else {
765
                    $this->db->rollback();
766
                    return -1;
767
                }
768
            } else {
769
                $this->error = $this->db->lasterror();
770
                $this->db->rollback();
771
                return -1;
772
            }
773
        }
774
    }
775
776
    /**
777
     *  Returns amount based on user thm
778
     *
779
     *  @return     float       Amount
780
     */
781
    public function getAmount()
782
    {
783
        $amount = 0;
784
785
        $this->author = new User($this->db);
786
        $this->author->fetch($this->user_creation_id);
787
788
        $thm = $this->author->thm;
789
790
        foreach ($this->lines as $line) {
791
            $amount += ($line->duration / 60 / 60 * (float) $thm);
792
        }
793
794
        return (float) price2num($amount, 'MT');
795
    }
796
797
798
    /**
799
     *  Create a document onto disk according to template module.
800
     *
801
     *  @param      string                  $modele         Force model to use ('' to not force)
802
     *  @param      Translate               $outputlangs    Object langs to use for output
803
     *  @param      int                     $hidedetails    Hide details of lines
804
     *  @param      int                     $hidedesc       Hide description
805
     *  @param      int                     $hideref        Hide ref
806
     *  @param   null|array  $moreparams     Array to provide more information
807
     *  @return     int                                     0 if KO, 1 if OK
808
     */
809
    public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
810
    {
811
        global $conf;
812
813
        $outputlangs->load("interventions");
814
815
        if (!dol_strlen($modele)) {
816
            $modele = 'soleil';
817
818
            if (!empty($this->model_pdf)) {
819
                $modele = $this->model_pdf;
820
            } elseif (getDolGlobalString('FICHEINTER_ADDON_PDF')) {
821
                $modele = getDolGlobalString('FICHEINTER_ADDON_PDF');
822
            }
823
        }
824
825
        $modelpath = "core/modules/fichinter/doc/";
826
827
        return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
828
    }
829
830
    /**
831
     *  Returns the label status
832
     *
833
     *  @param      int     $mode       0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto
834
     *  @return     string              Label
835
     */
836
    public function getLibStatut($mode = 0)
837
    {
838
        return $this->LibStatut((isset($this->statut) ? $this->statut : $this->status), $mode);
839
    }
840
841
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
842
    /**
843
     *  Returns the label of a status
844
     *
845
     *  @param      int     $status     Id status
846
     *  @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
847
     *  @return     string              Label
848
     */
849
    public function LibStatut($status, $mode = 0)
850
    {
851
		// phpcs:enable
852
        // Init/load array of translation of status
853
        if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
854
            global $langs;
855
            $langs->load("fichinter");
856
857
            $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
858
            $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
859
            $this->labelStatus[self::STATUS_BILLED] = $langs->transnoentitiesnoconv('StatusInterInvoiced');
860
            $this->labelStatus[self::STATUS_CLOSED] = $langs->transnoentitiesnoconv('Done');
861
            $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
862
            $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
863
            $this->labelStatusShort[self::STATUS_BILLED] = $langs->transnoentitiesnoconv('StatusInterInvoiced');
864
            $this->labelStatusShort[self::STATUS_CLOSED] = $langs->transnoentitiesnoconv('Done');
865
        }
866
867
        $statuscode = 'status' . $status;
868
        if ($status == self::STATUS_BILLED || $status == self::STATUS_CLOSED) {
869
            $statuscode = 'status6';
870
        }
871
        return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statuscode, $mode);
872
    }
873
874
    /**
875
     * getTooltipContentArray
876
     *
877
     * @param array $params ex option, infologin
878
     * @since v18
879
     * @return array
880
     */
881
    public function getTooltipContentArray($params)
882
    {
883
        global $conf, $langs;
884
885
        $langs->load('fichinter');
886
887
        $datas = [];
888
        $datas['picto'] = img_picto('', $this->picto) . ' <u class="paddingrightonly">' . $langs->trans("Intervention") . '</u>';
889
        if (isset($this->status)) {
890
            $datas['picto'] .= ' ' . $this->getLibStatut(5);
891
        }
892
        $datas['ref'] = '<br><b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
893
894
        return $datas;
895
    }
896
897
    /**
898
     *  Return clicable name (with picto eventually)
899
     *
900
     *  @param      int     $withpicto                  0=_No picto, 1=Includes the picto in the linkn, 2=Picto only
901
     *  @param      string  $option                     Options
902
     *  @param      int     $notooltip                  1=Disable tooltip
903
     *  @param      int     $save_lastsearch_value      -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
904
     *  @param      string  $morecss                    Add more css on link
905
     *  @return     string                              String with URL
906
     */
907
    public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $save_lastsearch_value = -1, $morecss = '')
908
    {
909
        global $conf, $langs, $hookmanager;
910
911
        if (!empty($conf->dol_no_mouse_hover)) {
912
            $notooltip = 1; // Force disable tooltips
913
        }
914
915
        $result = '';
916
        $params = [
917
            'id' => $this->id,
918
            'objecttype' => $this->element,
919
            'option' => $option,
920
        ];
921
        $classfortooltip = 'classfortooltip';
922
        $dataparams = '';
923
        if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
924
            $classfortooltip = 'classforajaxtooltip';
925
            $dataparams = ' data-params="' . dol_escape_htmltag(json_encode($params)) . '"';
926
            $label = '';
927
        } else {
928
            $label = implode($this->getTooltipContentArray($params));
929
        }
930
931
        $url = constant('BASE_URL') . '/fichinter/card.php?id=' . $this->id;
932
933
        if ($option !== 'nolink') {
934
            // Add param to save lastsearch_values or not
935
            $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
936
            if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
937
                $add_save_lastsearch_values = 1;
938
            }
939
            if ($add_save_lastsearch_values) {
940
                $url .= '&save_lastsearch_values=1';
941
            }
942
        }
943
944
        $linkclose = '';
945
        if (empty($notooltip)) {
946
            if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
947
                $label = $langs->trans("ShowIntervention");
948
                $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
949
            }
950
            $linkclose .= ($label ? ' title="' . dol_escape_htmltag($label, 1) . '"' : ' title="tocomplete"');
951
            $linkclose .= $dataparams . ' class="' . $classfortooltip . ($morecss ? ' ' . $morecss : '') . '"';
952
        } else {
953
            $linkclose = ($morecss ? ' class="' . $morecss . '"' : '');
954
        }
955
956
        if ($option == 'nolink' || empty($url)) {
957
            $linkstart = '<span';
958
        } else {
959
            $linkstart = '<a href="' . $url . '"';
960
        }
961
        $linkstart .= $linkclose . '>';
962
        if ($option == 'nolink' || empty($url)) {
963
            $linkend = '</span>';
964
        } else {
965
            $linkend = '</a>';
966
        }
967
968
        $result .= $linkstart;
969
        if ($withpicto) {
970
            $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="' . (($withpicto != 2) ? 'paddingright ' : '') . '"'), 0, 0, $notooltip ? 0 : 1);
971
        }
972
973
        if ($withpicto != 2) {
974
            $result .= $this->ref;
975
        }
976
977
        $result .= $linkend;
978
979
        global $action;
980
        $hookmanager->initHooks(array('interventiondao'));
981
        $parameters = array('id' => $this->id, 'getnomurl' => &$result);
982
        $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
983
        if ($reshook > 0) {
984
            $result = $hookmanager->resPrint;
985
        } else {
986
            $result .= $hookmanager->resPrint;
987
        }
988
989
        return $result;
990
    }
991
992
993
    /**
994
     *  Returns the next non used reference of intervention
995
     *  depending on the module numbering assets within FICHEINTER_ADDON
996
     *
997
     *  @param      Societe     $soc        Thirdparty object
998
     *  @return     string                  Free reference for intervention
999
     */
1000
    public function getNextNumRef($soc)
1001
    {
1002
        global $conf, $db, $langs;
1003
        $langs->load("interventions");
1004
1005
        if (getDolGlobalString('FICHEINTER_ADDON')) {
1006
            $mybool = false;
1007
1008
            $file = "mod_" . getDolGlobalString('FICHEINTER_ADDON') . ".php";
1009
            $classname = "mod_" . getDolGlobalString('FICHEINTER_ADDON');
1010
1011
            // Include file with class
1012
            $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1013
1014
            foreach ($dirmodels as $reldir) {
1015
                $dir = dol_buildpath($reldir . "core/modules/fichinter/");
1016
1017
                // Load file with numbering class (if found)
1018
                $mybool = ((bool) @include_once $dir . $file) || $mybool;
1019
            }
1020
1021
            if ($mybool === false) {
1022
                dol_print_error(null, "Failed to include file " . $file);
1023
                return '';
1024
            }
1025
1026
            $obj = new $classname();
1027
            $numref = "";
1028
            $numref = $obj->getNextValue($soc, $this);
1029
1030
            if ($numref != "") {
1031
                return $numref;
1032
            } else {
1033
                dol_print_error($db, "Fichinter::getNextNumRef " . $obj->error);
1034
                return "";
1035
            }
1036
        } else {
1037
            $langs->load("errors");
1038
            print $langs->trans("Error") . " " . $langs->trans("Error_FICHEINTER_ADDON_NotDefined");
1039
            return "";
1040
        }
1041
    }
1042
1043
    /**
1044
     *  Load information on object
1045
     *
1046
     *  @param  int     $id      Id of object
1047
     *  @return void
1048
     */
1049
    public function info($id)
1050
    {
1051
        $sql = "SELECT f.rowid,";
1052
        $sql .= " f.datec,";
1053
        $sql .= " f.tms as date_modification,";
1054
        $sql .= " f.date_valid as datev,";
1055
        $sql .= " f.fk_user_author,";
1056
        $sql .= " f.fk_user_modif as fk_user_modification,";
1057
        $sql .= " f.fk_user_valid";
1058
        $sql .= " FROM " . MAIN_DB_PREFIX . "fichinter as f";
1059
        $sql .= " WHERE f.rowid = " . ((int) $id);
1060
1061
        $resql = $this->db->query($sql);
1062
        if ($resql) {
1063
            if ($this->db->num_rows($resql)) {
1064
                $obj = $this->db->fetch_object($resql);
1065
1066
                $this->id                = $obj->rowid;
1067
1068
                $this->date_creation     = $this->db->jdate($obj->datec);
1069
                $this->date_modification = $this->db->jdate($obj->date_modification);
1070
                $this->date_validation   = $this->db->jdate($obj->datev);
1071
1072
                $this->user_creation_id = $obj->fk_user_author;
1073
                $this->user_validation_id = $obj->fk_user_valid;
1074
                $this->user_modification_id = $obj->fk_user_modification;
1075
            }
1076
            $this->db->free($resql);
1077
        } else {
1078
            dol_print_error($this->db);
1079
        }
1080
    }
1081
1082
    /**
1083
     *  Delete intervetnion
1084
     *
1085
     *  @param      User    $user           Object user who delete
1086
     *  @param      int     $notrigger      Disable trigger
1087
     *  @return     int                     Return integer <0 if KO, >0 if OK
1088
     */
1089
    public function delete(User $user, $notrigger = 0)
1090
    {
1091
        global $conf, $langs;
1092
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
1093
1094
        $error = 0;
1095
1096
        $this->db->begin();
1097
1098
        if (!$error && !$notrigger) {
1099
            // Call trigger
1100
            $result = $this->call_trigger('FICHINTER_DELETE', $user);
1101
            if ($result < 0) {
1102
                $error++;
1103
                $this->db->rollback();
1104
                return -1;
1105
            }
1106
            // End call triggers
1107
        }
1108
1109
        // Delete linked object
1110
        if (!$error) {
1111
            $res = $this->deleteObjectLinked();
1112
            if ($res < 0) {
1113
                $error++;
1114
            }
1115
        }
1116
1117
        // Delete linked contacts
1118
        if (!$error) {
1119
            $res = $this->delete_linked_contact();
1120
            if ($res < 0) {
1121
                $this->error = 'ErrorFailToDeleteLinkedContact';
1122
                $error++;
1123
            }
1124
        }
1125
1126
        if (!$error) {
1127
            $main = MAIN_DB_PREFIX . 'fichinterdet';
1128
            $ef = $main . "_extrafields";
1129
            $sql = "DELETE FROM $ef WHERE fk_object IN (SELECT rowid FROM $main WHERE fk_fichinter = " . ((int) $this->id) . ")";
1130
1131
            $resql = $this->db->query($sql);
1132
            if (!$resql) {
1133
                $error++;
1134
            }
1135
        }
1136
1137
        if (!$error) {
1138
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "fichinterdet";
1139
            $sql .= " WHERE fk_fichinter = " . ((int) $this->id);
1140
1141
            $resql = $this->db->query($sql);
1142
            if (!$resql) {
1143
                $error++;
1144
            }
1145
        }
1146
1147
        if (!$error) {
1148
            // Remove extrafields
1149
            $res = $this->deleteExtraFields();
1150
            if ($res < 0) {
1151
                $error++;
1152
            }
1153
        }
1154
1155
        if (!$error) {
1156
            // Delete object
1157
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "fichinter";
1158
            $sql .= " WHERE rowid = " . ((int) $this->id);
1159
1160
            dol_syslog("Fichinter::delete", LOG_DEBUG);
1161
            $resql = $this->db->query($sql);
1162
            if (!$resql) {
1163
                $error++;
1164
            }
1165
        }
1166
1167
        if (!$error) {
1168
            // Delete record into ECM index (Note that delete is also done when deleting files with the dol_delete_dir_recursive
1169
            $this->deleteEcmFiles(0); // Deleting files physically is done later with the dol_delete_dir_recursive
1170
            $this->deleteEcmFiles(1); // Deleting files physically is done later with the dol_delete_dir_recursive
1171
1172
            // Remove directory with files
1173
            $fichinterref = dol_sanitizeFileName($this->ref);
1174
            if ($conf->ficheinter->dir_output) {
1175
                $dir = $conf->ficheinter->dir_output . "/" . $fichinterref;
1176
                $file = $conf->ficheinter->dir_output . "/" . $fichinterref . "/" . $fichinterref . ".pdf";
1177
                if (file_exists($file)) {
1178
                    dol_delete_preview($this);
1179
1180
                    if (!dol_delete_file($file, 0, 0, 0, $this)) { // For triggers
1181
                        $langs->load("errors");
1182
                        $this->error = $langs->trans("ErrorFailToDeleteFile", $file);
1183
                        return 0;
1184
                    }
1185
                }
1186
                if (file_exists($dir)) {
1187
                    if (!dol_delete_dir_recursive($dir)) {
1188
                        $langs->load("errors");
1189
                        $this->error = $langs->trans("ErrorFailToDeleteDir", $dir);
1190
                        return 0;
1191
                    }
1192
                }
1193
            }
1194
        }
1195
1196
        if (!$error) {
1197
            $this->db->commit();
1198
            return 1;
1199
        } else {
1200
            $this->db->rollback();
1201
            return -1;
1202
        }
1203
    }
1204
1205
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1206
    /**
1207
     *  Defines a delivery date of intervention
1208
     *
1209
     *  @param      User    $user               Object user who define
1210
     *  @param      integer $date_delivery      date of delivery
1211
     *  @return     int                         Return integer <0 if KO, >0 if OK
1212
     */
1213
    public function set_date_delivery($user, $date_delivery)
1214
    {
1215
		// phpcs:enable
1216
        if ($user->hasRight('ficheinter', 'creer')) {
1217
            $sql = "UPDATE " . MAIN_DB_PREFIX . "fichinter ";
1218
            $sql .= " SET datei = '" . $this->db->idate($date_delivery) . "'";
1219
            $sql .= " WHERE rowid = " . ((int) $this->id);
1220
            $sql .= " AND fk_statut = 0";
1221
1222
            if ($this->db->query($sql)) {
1223
                $this->date_delivery = $date_delivery;
1224
                return 1;
1225
            } else {
1226
                $this->error = $this->db->error();
1227
                dol_syslog("Fichinter::set_date_delivery Erreur SQL");
1228
                return -1;
1229
            }
1230
        }
1231
1232
        return 0;
1233
    }
1234
1235
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1236
    /**
1237
     *  Define the label of the intervention
1238
     *
1239
     *  @param      User    $user           Object user who modify
1240
     *  @param      string  $description    description
1241
     *  @return     int                     Return integer <0 if KO, >0 if OK
1242
     */
1243
    public function set_description($user, $description)
1244
    {
1245
		// phpcs:enable
1246
        if ($user->hasRight('ficheinter', 'creer')) {
1247
            $sql = "UPDATE " . MAIN_DB_PREFIX . "fichinter ";
1248
            $sql .= " SET description = '" . $this->db->escape($description) . "',";
1249
            $sql .= " fk_user_modif = " . $user->id;
1250
            $sql .= " WHERE rowid = " . ((int) $this->id);
1251
1252
            if ($this->db->query($sql)) {
1253
                $this->description = $description;
1254
                return 1;
1255
            } else {
1256
                $this->error = $this->db->error();
1257
                dol_syslog("Fichinter::set_description Erreur SQL");
1258
                return -1;
1259
            }
1260
        }
1261
1262
        return 0;
1263
    }
1264
1265
1266
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1267
    /**
1268
     *  Link intervention to a contract
1269
     *
1270
     *  @param      User    $user           Object user who modify
1271
     *  @param      int     $contractid     Description
1272
     *  @return     int                     Return integer <0 if KO, >0 if OK
1273
     */
1274
    public function set_contrat($user, $contractid)
1275
    {
1276
		// phpcs:enable
1277
        if ($user->hasRight('ficheinter', 'creer')) {
1278
            $sql = "UPDATE " . MAIN_DB_PREFIX . "fichinter ";
1279
            $sql .= " SET fk_contrat = " . ((int) $contractid);
1280
            $sql .= " WHERE rowid = " . ((int) $this->id);
1281
1282
            if ($this->db->query($sql)) {
1283
                $this->fk_contrat = $contractid;
1284
                return 1;
1285
            } else {
1286
                $this->error = $this->db->error();
1287
                return -1;
1288
            }
1289
        }
1290
1291
        return -2;
1292
    }
1293
1294
1295
1296
    /**
1297
     *  Load an object from its id and create a new one in database
1298
     *
1299
     *  @param      User    $user           User making the clone
1300
     *  @param      int     $socid          Id of thirdparty
1301
     *  @return     int                     New id of clone
1302
     */
1303
    public function createFromClone(User $user, $socid = 0)
1304
    {
1305
        global $hookmanager;
1306
1307
        $error = 0;
1308
1309
        $this->db->begin();
1310
1311
        // get extrafields so they will be clone
1312
        foreach ($this->lines as $line) {
1313
            $line->fetch_optionals();
1314
        }
1315
1316
        // Load source object
1317
        $objFrom = clone $this;
1318
1319
        // Change socid if needed
1320
        if (!empty($socid) && $socid != $this->socid) {
1321
            $objsoc = new Societe($this->db);
1322
1323
            if ($objsoc->fetch($socid) > 0) {
1324
                $this->socid = $objsoc->id;
1325
                //$this->cond_reglement_id  = (!empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
1326
                //$this->mode_reglement_id  = (!empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
1327
                $this->fk_project = 0;
1328
                $this->fk_delivery_address = 0;
1329
            }
1330
1331
            // TODO Change product price if multi-prices
1332
        }
1333
1334
        $this->id = 0;
1335
        $this->ref = '';
1336
        $this->status = self::STATUS_DRAFT;
1337
        $this->statut = self::STATUS_DRAFT; //  deprecated
1338
1339
        // Clear fields
1340
        $this->user_author_id     = $user->id;
1341
        $this->user_validation_id = 0;
1342
        $this->date_creation      = '';
1343
        $this->date_validation    = '';
1344
1345
        $this->ref_client         = '';
1346
1347
        // Create clone
1348
        $this->context['createfromclone'] = 'createfromclone';
1349
        $result = $this->create($user);
1350
        if ($result < 0) {
1351
            $error++;
1352
        }
1353
1354
        if (!$error) {
1355
            // Add lines because it is not included into create function
1356
            foreach ($this->lines as $line) {
1357
                $this->addline($user, $this->id, $line->desc, $line->datei, $line->duration, $line->array_options);
1358
            }
1359
1360
            // Hook of thirdparty module
1361
            if (is_object($hookmanager)) {
1362
                $parameters = array('objFrom' => $objFrom);
1363
                $action = '';
1364
                $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1365
                if ($reshook < 0) {
1366
                    $this->setErrorsFromObject($hookmanager);
1367
                    $error++;
1368
                }
1369
            }
1370
        }
1371
1372
        unset($this->context['createfromclone']);
1373
1374
        // End
1375
        if (!$error) {
1376
            $this->db->commit();
1377
            return $this->id;
1378
        } else {
1379
            $this->db->rollback();
1380
            return -1;
1381
        }
1382
    }
1383
1384
1385
    /**
1386
     *  Adding a line of intervention into data base
1387
     *
1388
     *  @param      user    $user                   User that do the action
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\FichInter\Classes\user was not found. Did you mean user? If so, make sure to prefix the type with \.
Loading history...
1389
     *  @param      int     $fichinterid            Id of intervention
1390
     *  @param      string  $desc                   Line description
1391
     *  @param      integer $date_intervention      Intervention date
1392
     *  @param      int     $duration               Intervention duration
1393
     *  @param      array   $array_options          Array option
1394
     *  @return     int                             >0 if ok, <0 if ko
1395
     */
1396
    public function addline($user, $fichinterid, $desc, $date_intervention, $duration, $array_options = [])
1397
    {
1398
        dol_syslog(get_class($this) . "::addline $fichinterid, $desc, $date_intervention, $duration");
1399
1400
        if ($this->status == self::STATUS_DRAFT) {
1401
            $this->db->begin();
1402
1403
            // Insertion ligne
1404
            $line = new FichinterLigne($this->db);
1405
1406
            $line->fk_fichinter = $fichinterid;
1407
            $line->desc         = $desc;
1408
            $line->date         = $date_intervention;
1409
            $line->datei        = $date_intervention;   // For backward compatibility
1410
            $line->duration     = $duration;
1411
1412
            if (is_array($array_options) && count($array_options) > 0) {
1413
                $line->array_options = $array_options;
1414
            }
1415
1416
            $result = $line->insert($user);
1417
1418
            if ($result >= 0) {
1419
                $this->db->commit();
1420
                return 1;
1421
            } else {
1422
                $this->error = $this->db->error();
1423
                $this->db->rollback();
1424
                return -1;
1425
            }
1426
        }
1427
1428
        return 0;
1429
    }
1430
1431
1432
    /**
1433
     *  Initialise an instance with random values.
1434
     *  Used to build previews or test instances.
1435
     *  id must be 0 if object instance is a specimen.
1436
     *
1437
     *  @return int
1438
     */
1439
    public function initAsSpecimen()
1440
    {
1441
        global $langs;
1442
1443
        $now = dol_now();
1444
1445
        // Initialise parameters
1446
        $this->id = 0;
1447
        $this->ref = 'SPECIMEN';
1448
        $this->ref_client = 'SPECIMEN CLIENT';
1449
        $this->specimen = 1;
1450
        $this->socid = 1;
1451
        $this->datec = $now;
1452
        $this->note_private = 'Private note';
1453
        $this->note_public = 'SPECIMEN';
1454
        $this->duration = 0;
1455
        $nbp = 25;
1456
        $xnbp = 0;
1457
        while ($xnbp < $nbp) {
1458
            $line = new FichinterLigne($this->db);
1459
            $line->desc = $langs->trans("Description") . " " . $xnbp;
1460
            $line->date = ($now - 3600 * (1 + $xnbp));
1461
            $line->datei = ($now - 3600 * (1 + $xnbp)); // For backward compatibility
1462
            $line->duration = 600;
1463
            $line->fk_fichinter = 0;
1464
            $this->lines[$xnbp] = $line;
1465
            $xnbp++;
1466
1467
            $this->duration += $line->duration;
1468
        }
1469
1470
        return 1;
1471
    }
1472
1473
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1474
    /**
1475
     *  Load array lines ->lines
1476
     *
1477
     *  @return     int     Return integer <0 if KO, >0 if OK
1478
     */
1479
    public function fetch_lines()
1480
    {
1481
		// phpcs:enable
1482
        $this->lines = array();
1483
1484
        $sql = "SELECT rowid, fk_fichinter, description, duree, date, rang";
1485
        $sql .= " FROM " . MAIN_DB_PREFIX . "fichinterdet";
1486
        $sql .= " WHERE fk_fichinter = " . ((int) $this->id);
1487
        $sql .= " ORDER BY rang ASC, date ASC";
1488
1489
        dol_syslog(get_class($this) . "::fetch_lines", LOG_DEBUG);
1490
1491
        $resql = $this->db->query($sql);
1492
        if ($resql) {
1493
            $num = $this->db->num_rows($resql);
1494
            $i = 0;
1495
            while ($i < $num) {
1496
                $objp = $this->db->fetch_object($resql);
1497
1498
                $line = new FichinterLigne($this->db);
1499
                $line->id = $objp->rowid;
1500
                $line->fk_fichinter = $objp->fk_fichinter;
1501
                $line->desc = $objp->description;
1502
                $line->duration = $objp->duree;
1503
                //For invoicing we calculing hours
1504
                $line->qty = round($objp->duree / 3600, 2);
1505
                $line->date = $this->db->jdate($objp->date);
1506
                $line->datei = $this->db->jdate($objp->date);   // For backward compatibility
1507
                $line->rang = $objp->rang;
1508
                $line->product_type = 1;
1509
                $line->fetch_optionals();
1510
1511
                $this->lines[$i] = $line;
1512
                $i++;
1513
            }
1514
            $this->db->free($resql);
1515
1516
            return 1;
1517
        } else {
1518
            $this->error = $this->db->error();
1519
            return -1;
1520
        }
1521
    }
1522
1523
    /**
1524
     * Function used to replace a thirdparty id with another one.
1525
     *
1526
     * @param   DoliDB  $dbs        Database handler, because function is static we name it $dbs not $db to avoid breaking coding test
1527
     * @param   int     $origin_id  Old thirdparty id
1528
     * @param   int     $dest_id    New thirdparty id
1529
     * @return  bool
1530
     */
1531
    public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
1532
    {
1533
        $tables = array(
1534
            'fichinter'
1535
        );
1536
1537
        return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables);
1538
    }
1539
1540
    /**
1541
     * Set customer reference number
1542
     *
1543
     *  @param      User    $user           Object user that modify
1544
     *  @param      string  $ref_client     Customer reference
1545
     *  @param      int     $notrigger      1=Does not execute triggers, 0= execute triggers
1546
     *  @return     int                     Return integer <0 if ko, >0 if ok
1547
     */
1548
    public function setRefClient($user, $ref_client, $notrigger = 0)
1549
    {
1550
        // phpcs:enable
1551
        if ($user->hasRight('ficheinter', 'creer')) {
1552
            $error = 0;
1553
1554
            $this->db->begin();
1555
1556
            $this->oldcopy = dol_clone($this, 2);
1557
1558
            $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element . " SET ref_client = " . (empty($ref_client) ? 'NULL' : "'" . $this->db->escape($ref_client) . "'");
1559
            $sql .= " WHERE rowid = " . ((int) $this->id);
1560
1561
            dol_syslog(__METHOD__ . ' $this->id=' . $this->id . ', ref_client=' . $ref_client, LOG_DEBUG);
1562
            $resql = $this->db->query($sql);
1563
            if (!$resql) {
1564
                $this->errors[] = $this->db->error();
1565
                $error++;
1566
            }
1567
1568
            if (!$error) {
1569
                $this->ref_client = $ref_client;
1570
            }
1571
1572
            if (!$notrigger && empty($error)) {
1573
                // Call trigger
1574
                $result = $this->call_trigger('FICHINTER_MODIFY', $user);
1575
                if ($result < 0) {
1576
                    $error++;
1577
                }
1578
                // End call triggers
1579
            }
1580
1581
            if (!$error) {
1582
                $this->db->commit();
1583
                return 1;
1584
            } else {
1585
                foreach ($this->errors as $errmsg) {
1586
                    dol_syslog(__METHOD__ . ' Error: ' . $errmsg, LOG_ERR);
1587
                    $this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
1588
                }
1589
                $this->db->rollback();
1590
                return -1 * $error;
1591
            }
1592
        } else {
1593
            return -1;
1594
        }
1595
    }
1596
1597
    /**
1598
     *  Return clicable link of object (with eventually picto)
1599
     *
1600
     *  @param      string      $option                 Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link)
1601
     *  @param      array       $arraydata              Array of data
1602
     *  @return     string                              HTML Code for Kanban thumb.
1603
     */
1604
    public function getKanbanView($option = '', $arraydata = null)
1605
    {
1606
        global $langs;
1607
1608
        $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
1609
1610
        $return = '<div class="box-flex-item box-flex-grow-zero">';
1611
        $return .= '<div class="info-box info-box-sm">';
1612
        $return .= '<span class="info-box-icon bg-infobox-action">';
1613
        $return .= img_picto('', $this->picto);
1614
        $return .= '</span>';
1615
        $return .= '<div class="info-box-content">';
1616
        $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . (method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref) . '</span>';
1617
        if ($selected >= 0) {
1618
            $return .= '<input id="cb' . $this->id . '" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="' . $this->id . '"' . ($selected ? ' checked="checked"' : '') . '>';
1619
        }
1620
        if (!empty($arraydata['thirdparty'])) {
1621
            $tmpthirdparty = $arraydata['thirdparty'];
1622
            $return .= '<br><span class="info-box-label">' . $tmpthirdparty->getNomUrl(1) . '</span>';
1623
        }
1624
        if (property_exists($this, 'duration')) {
1625
            $return .= '<br><span class="info-box-label ">' . $langs->trans("Duration") . ' : ' . convertSecondToTime($this->duration, 'allhourmin') . '</span>';
1626
        }
1627
        if (method_exists($this, 'getLibStatut')) {
1628
            $return .= '<br><div class="info-box-status">' . $this->getLibStatut(3) . '</div>';
1629
        }
1630
        $return .= '</div>';
1631
        $return .= '</div>';
1632
        $return .= '</div>';
1633
        return $return;
1634
    }
1635
1636
    /**
1637
     * Set signed status
1638
     *
1639
     * @param  User   $user        Object user that modify
1640
     * @param  int    $status      Newsigned  status to set (often a constant like self::STATUS_XXX)
1641
     * @param  int    $notrigger   1 = Does not execute triggers, 0 = Execute triggers
1642
     * @param  string $triggercode Trigger code to use
1643
     * @return int                 0 < if KO, > 0 if OK
1644
     */
1645
    public function setSignedStatus(User $user, int $status = 0, int $notrigger = 0, $triggercode = ''): int
1646
    {
1647
        return $this->setSignedStatusCommon($user, $status, $notrigger, $triggercode);
1648
    }
1649
}
1650