Passed
Pull Request — dev (#6)
by Rafael
79:24 queued 24:08
created

FichinterRec   F

Complexity

Total Complexity 93

Size/Duplication

Total Lines 849
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 440
dl 0
loc 849
rs 2
c 0
b 0
f 0
wmc 93

17 Methods

Rating   Name   Duplication   Size   Complexity  
A setAutoValidate() 0 18 3
A setMaxPeriod() 0 22 4
B fetch_lines() 0 60 5
A updateNbGenDone() 0 25 4
A getLibStatut() 0 3 1
A delete() 0 29 4
F addLineRec() 0 102 15
B fetch() 0 62 9
A replaceThirdparty() 0 5 1
A setNextDate() 0 23 6
A set_auto() 0 21 3
A replaceProduct() 0 7 1
B setFrequencyAndUnit() 0 29 8
A __construct() 0 10 1
F create() 0 122 20
A initAsSpecimen() 0 11 1
B getNomUrl() 0 37 7

How to fix   Complexity   

Complex Class

Complex classes like FichinterRec 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 FichinterRec, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/* Copyright (C) 2003-2005  Rodolphe Quiedeville        <[email protected]>
4
 * Copyright (C) 2004-2015  Laurent Destailleur		    <[email protected]>
5
 * Copyright (C) 2009-2012  Regis Houssin			    <[email protected]>
6
 * Copyright (C) 2010-2011  Juanjo Menent			    <[email protected]>
7
 * Copyright (C) 2012       Cedric Salvador			    <[email protected]>
8
 * Copyright (C) 2013       Florian Henry			    <[email protected]>
9
 * Copyright (C) 2015       Marcos García			    <[email protected]>
10
 * Copyright (C) 2016-2018  Charlie Benke			    <[email protected]>
11
 * Copyright (C) 2024		William Mead			    <[email protected]>
12
 * Copyright (C) 2024       Frédéric France             <[email protected]>
13
 * Copyright (C) 2024		MDW							<[email protected]>
14
 * Copyright (C) 2024       Rafael San José             <[email protected]>
15
 *
16
 * This program is free software; you can redistribute it and/or modify
17
 * it under the terms of the GNU General Public License as published by
18
 * the Free Software Foundation; either version 3 of the License, or
19
 * (at your option) any later version.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24
 * GNU General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU General Public License
27
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
28
 */
29
30
namespace Dolibarr\Code\FichInter\Classes;
31
32
/**
33
 *  \file       htdocs/fichinter/class/fichinterrec.class.php
34
 *  \ingroup    fichinter
35
 *  \brief      File for class to manage recurring interventions
36
 */
37
38
39
40
/**
41
 * Class to manage recurring interventions
42
 */
43
class FichinterRec extends Fichinter
44
{
45
    public $element = 'fichinterrec';
46
    public $table_element = 'fichinter_rec';
47
    public $table_element_line = 'fichinterdet_rec';
48
49
    /**
50
     * @var string Fieldname with ID of parent key if this field has a parent
51
     */
52
    public $fk_element = 'fk_fichinter';
53
54
    /**
55
     * {@inheritdoc}
56
     */
57
    protected $table_ref_field = 'title';
58
59
    /**
60
     * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
61
     */
62
    public $picto = 'intervention';
63
64
65
    /**
66
     * @var string title
67
     */
68
    public $title;
69
    public $number;
70
    public $date;
71
    public $amount;
72
    public $tva;
73
    public $total;
74
75
    /**
76
     * @var int
77
     */
78
    public $auto_validate;
79
80
    /**
81
     * @var int Frequency
82
     */
83
    public $frequency;
84
85
    public $id_origin;
86
87
    /**
88
     * @var string Unit frequency
89
     */
90
    public $unit_frequency;
91
92
    /**
93
     * @var int Proposal Id
94
     */
95
    public $propalid;
96
97
    public $date_last_gen;
98
    public $date_when;
99
100
    /**
101
     * @var int number of generation done
102
     */
103
    public $nb_gen_done;
104
105
    /**
106
     * @var int number of maximum generation
107
     */
108
    public $nb_gen_max;
109
110
    /**
111
     * int rank
112
     */
113
    public $rang;
114
115
    /**
116
     * @var int special code
117
     */
118
    public $special_code;
119
120
    public $usenewprice = 0;
121
122
    /**
123
     *  Constructor
124
     *
125
     *  @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...
126
     */
127
    public function __construct($db)
128
    {
129
        $this->db = $db;
130
131
        //status dans l'ordre de l'intervention
132
        $this->labelStatus[0] = 'Draft';
133
        $this->labelStatus[1] = 'Closed';
134
135
        $this->labelStatusShort[0] = 'Draft';
136
        $this->labelStatusShort[1] = 'Closed';
137
    }
138
139
    /**
140
     *  Returns the label status
141
     *
142
     *  @param      int     $mode       0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto
143
     *  @return     string              Label
144
     */
145
    public function getLibStatut($mode = 0)
146
    {
147
        return $this->LibStatut($this->status, $mode);
148
    }
149
150
151
    /**
152
     *  Create a predefined fichinter
153
     *
154
     *  @param      User    $user       User object
155
     *  @param      int     $notrigger  no trigger
156
     *  @return     int                 Return integer <0 if KO, id of fichinter if OK
157
     */
158
    public function create($user, $notrigger = 0)
159
    {
160
        global $conf;
161
162
        $error = 0;
163
        $now = dol_now();
164
165
        // Clean parameters
166
        $this->title = trim($this->title);
167
        $this->description = trim($this->description);
168
169
170
        $this->db->begin();
171
172
        // Load fichinter model
173
        $fichintsrc = new Fichinter($this->db);
174
175
        $result = $fichintsrc->fetch($this->id_origin);
176
        if ($result > 0) {
177
            $result = $fichintsrc->fetch_lines(); // to get all lines
178
        }
179
180
        if ($result > 0) {
181
            $sql = "INSERT INTO " . MAIN_DB_PREFIX . "fichinter_rec (";
182
            $sql .= "title";
183
            $sql .= ", fk_soc";
184
            $sql .= ", entity";
185
            $sql .= ", datec";
186
            $sql .= ", duree";
187
            $sql .= ", description";
188
            $sql .= ", note_private";
189
            $sql .= ", note_public";
190
            $sql .= ", fk_user_author";
191
            $sql .= ", fk_projet";
192
            $sql .= ", fk_contrat";
193
            $sql .= ", modelpdf";
194
            $sql .= ", frequency";
195
            $sql .= ", unit_frequency";
196
            $sql .= ", date_when";
197
            $sql .= ", date_last_gen";
198
            $sql .= ", nb_gen_done";
199
            $sql .= ", nb_gen_max";
200
            // $sql.= ", auto_validate";
201
            $sql .= ") VALUES (";
202
            $sql .= "'" . $this->db->escape($this->title) . "'";
203
            $sql .= ", " . ($this->socid > 0 ? ((int) $this->socid) : 'null');
204
            $sql .= ", " . ((int) $conf->entity);
205
            $sql .= ", '" . $this->db->idate($now) . "'";
206
            $sql .= ", " . (!empty($fichintsrc->duration) ? ((int) $fichintsrc->duration) : '0');
207
            $sql .= ", " . (!empty($this->description) ? ("'" . $this->db->escape($this->description) . "'") : "null");
208
            $sql .= ", " . (!empty($fichintsrc->note_private) ? ("'" . $this->db->escape($fichintsrc->note_private) . "'") : "null");
209
            $sql .= ", " . (!empty($fichintsrc->note_public) ? ("'" . $this->db->escape($fichintsrc->note_public) . "'") : "null");
210
            $sql .= ", " . ((int) $user->id);
211
            // si c'est la même société on conserve les liens vers le projet et le contrat
212
            if ($this->socid == $fichintsrc->socid) {
213
                $sql .= ", " . (!empty($fichintsrc->fk_project) ? ((int) $fichintsrc->fk_project) : "null");
214
                $sql .= ", " . (!empty($fichintsrc->fk_contrat) ? ((int) $fichintsrc->fk_contrat) : "null");
215
            } else {
216
                $sql .= ", null, null";
217
            }
218
219
            $sql .= ", " . (!empty($fichintsrc->model_pdf) ? "'" . $this->db->escape($fichintsrc->model_pdf) . "'" : "''");
220
221
            // Frequency
222
            $sql .= ", " . (!empty($this->frequency) ? ((int) $this->frequency) : "null");
223
            $sql .= ", '" . $this->db->escape($this->unit_frequency) . "'";
224
            $sql .= ", " . (!empty($this->date_when) ? "'" . $this->db->idate($this->date_when) . "'" : 'null');
225
            $sql .= ", " . (!empty($this->date_last_gen) ? "'" . $this->db->idate($this->date_last_gen) . "'" : 'null');
226
            $sql .= ", 0"; // we start at 0
227
            $sql .= ", " . ((int) $this->nb_gen_max);
228
            // $sql.= ", ".$this->auto_validate;
229
            $sql .= ")";
230
231
            if ($this->db->query($sql)) {
232
                $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . $this->table_element);
233
234
                /*
235
                 * Lines
236
                 */
237
                $num = count($fichintsrc->lines);
238
                for ($i = 0; $i < $num; $i++) {
239
                    //var_dump($fichintsrc->lines[$i]);
240
                    $result_insert = $this->addLineRec(
241
                        $fichintsrc->lines[$i]->desc,
242
                        $fichintsrc->lines[$i]->duration,
243
                        $fichintsrc->lines[$i]->date,
244
                        $fichintsrc->lines[$i]->rang,
245
                        $fichintsrc->lines[$i]->subprice,
246
                        $fichintsrc->lines[$i]->qty,
247
                        $fichintsrc->lines[$i]->tva_tx,
248
                        $fichintsrc->lines[$i]->fk_product,
249
                        $fichintsrc->lines[$i]->remise_percent,
250
                        'HT',
251
                        0,
252
                        '',
253
                        0,
254
                        $fichintsrc->lines[$i]->product_type,
255
                        $fichintsrc->lines[$i]->special_code,
256
                        !empty($fichintsrc->lines[$i]->label) ? $fichintsrc->lines[$i]->label : "",
257
                        $fichintsrc->lines[$i]->fk_unit
258
                    );
259
260
                    if ($result_insert < 0) {
261
                        $error++;
262
                    }
263
                }
264
265
                if ($error) {
266
                    $this->db->rollback();
267
                    return -1;
268
                } else {
269
                    $this->db->commit();
270
                    return $this->id;
271
                }
272
            } else {
273
                $this->error = $this->db->error() . ' sql=' . $sql;
274
                $this->db->rollback();
275
                return -2;
276
            }
277
        } else {
278
            $this->db->rollback();
279
            return -1;
280
        }
281
    }
282
283
284
    /**
285
     *  Get the template of intervention object and lines
286
     *
287
     *  @param    int       $rowid      Id of object to load
288
     *  @param      string  $ref            Reference of fichinter
289
     *  @param      string  $ref_ext        External reference of fichinter
290
     *  @return  int                    >0 if OK, <0 if KO, 0 if not found
291
     */
292
    public function fetch($rowid = 0, $ref = '', $ref_ext = '')
293
    {
294
        $sql = 'SELECT f.title, f.fk_soc';
295
        $sql .= ', f.datec, f.duree, f.fk_projet, f.fk_contrat, f.description';
296
        $sql .= ', f.note_private, f.note_public, f.fk_user_author';
297
        $sql .= ', f.frequency, f.unit_frequency, f.date_when, f.date_last_gen, f.nb_gen_done, f.nb_gen_max, f.auto_validate';
298
        $sql .= ', f.note_private, f.note_public, f.fk_user_author';
299
        $sql .= ', f.status';
300
        $sql .= ' FROM ' . MAIN_DB_PREFIX . 'fichinter_rec as f';
301
        if ($rowid > 0) {
302
            $sql .= " WHERE f.rowid = " . ((int) $rowid);
303
        } elseif ($ref) {
304
            $sql .= " WHERE f.title = '" . $this->db->escape($ref) . "'";
305
        }
306
307
        dol_syslog(get_class($this) . "::fetch rowid=" . $rowid, LOG_DEBUG);
308
309
        $result = $this->db->query($sql);
310
        if ($result) {
311
            if ($this->db->num_rows($result)) {
312
                $obj = $this->db->fetch_object($result);
313
314
                $this->id = $rowid;
315
                $this->title = $obj->title;
316
                $this->ref = $obj->title;
317
                $this->description = $obj->description;
318
                $this->datec = $obj->datec;
319
                $this->duration = $obj->duree;
320
                $this->socid = $obj->fk_soc;
321
                $this->status = $obj->status;
322
                $this->statut = $obj->status;   // deprecated
323
                $this->fk_project = $obj->fk_projet;
324
                $this->fk_contrat = $obj->fk_contrat;
325
                $this->note_private = $obj->note_private;
326
                $this->note_public = $obj->note_public;
327
                $this->user_author = $obj->fk_user_author;
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$user_author has been deprecated: Store only id in user_creation_id ( 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->user_author = $obj->fk_user_author;

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->model_pdf = empty($obj->model_pdf) ? "" : $obj->model_pdf;
329
                $this->rang = !empty($obj->rang) ? $obj->rang : "";
330
                $this->special_code = !empty($obj->special_code) ? $obj->special_code : "";
0 ignored issues
show
Documentation Bug introduced by
It seems like ! empty($obj->special_co...$obj->special_code : '' can also be of type string. However, the property $special_code is declared as type integer. Maybe add an additional type check?

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

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

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

class Id
{
    public $id;

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

}

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

$account_id = false;

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

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
331
                $this->frequency = $obj->frequency;
332
                $this->unit_frequency = $obj->unit_frequency;
333
                $this->date_when = $this->db->jdate($obj->date_when);
334
                $this->date_last_gen = $this->db->jdate($obj->date_last_gen);
335
                $this->nb_gen_done = $obj->nb_gen_done;
336
                $this->nb_gen_max = $obj->nb_gen_max;
337
                $this->auto_validate = $obj->auto_validate;
338
339
                // Lines
340
                $result = $this->fetch_lines();
341
                if ($result < 0) {
342
                    $this->error = $this->db->error();
343
                    return -3;
344
                }
345
                return 1;
346
            } else {
347
                $this->error = 'Interventional with id ' . $rowid . ' not found sql=' . $sql;
348
                dol_syslog(get_class($this) . '::Fetch Error ' . $this->error, LOG_ERR);
349
                return -2;
350
            }
351
        } else {
352
            $this->error = $this->db->error();
353
            return -1;
354
        }
355
    }
356
357
358
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
359
    /**
360
     *  Load all lines of template of intervention into this->lines
361
     *
362
     *  @param   int    $sall   sall
363
     *  @return  int            1 if OK, < 0 if KO
364
     */
365
    public function fetch_lines($sall = 0)
366
    {
367
		// phpcs:enable
368
        $this->lines = array();
369
370
        $sql = 'SELECT l.rowid, l.fk_product, l.product_type as product_type, l.label as custom_label, l.description,';
371
        $sql .= ' l.price, l.qty, l.tva_tx, l.remise_percent, l.subprice, l.duree, l.date,';
372
        $sql .= ' l.total_ht, l.total_tva, l.total_ttc,';
373
        $sql .= ' l.rang, l.special_code,';
374
        $sql .= ' l.fk_unit, p.ref as product_ref, p.fk_product_type as fk_product_type,';
375
        $sql .= ' p.label as product_label, p.description as product_desc';
376
        $sql .= ' FROM ' . MAIN_DB_PREFIX . 'fichinterdet_rec as l';
377
        $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'product as p ON l.fk_product = p.rowid';
378
        $sql .= ' WHERE l.fk_fichinter = ' . ((int) $this->id);
379
380
        dol_syslog('FichinterRec::fetch_lines', LOG_DEBUG);
381
382
        $result = $this->db->query($sql);
383
        if ($result) {
384
            $num = $this->db->num_rows($result);
385
            $i = 0;
386
            while ($i < $num) {
387
                $objp = $this->db->fetch_object($result);
388
389
                $line = new FichinterLigne($this->db);
390
                $line->id = $objp->rowid;
391
                $line->label = $objp->custom_label; // Label line
392
                $line->desc = $objp->description; // Description line
393
                $line->product_type = $objp->product_type; // Type of line
394
                $line->product_ref = $objp->product_ref; // Ref product
395
                $line->product_label = $objp->product_label; // Label product
396
                $line->product_desc = $objp->product_desc; // Description product
397
                $line->fk_product_type = $objp->fk_product_type; // Type in product
398
                $line->qty = $objp->qty;
399
                $line->duree = $objp->duree;
400
                $line->duration = $objp->duree;
401
                $line->date = $objp->date;
402
                $line->subprice = $objp->subprice;
403
                $line->tva_tx = $objp->tva_tx;
404
                $line->remise_percent = $objp->remise_percent;
405
                $line->fk_remise_except = !empty($objp->fk_remise_except) ? $objp->fk_remise_except : "";
0 ignored issues
show
Bug Best Practice introduced by
The property fk_remise_except does not exist on Dolibarr\Code\FichInter\Classes\FichinterLigne. Since you implemented __set, consider adding a @property annotation.
Loading history...
406
                $line->fk_product = $objp->fk_product;
407
                $line->info_bits = !empty($objp->info_bits) ? $objp->info_bits : "";
0 ignored issues
show
Documentation Bug introduced by
It seems like ! empty($objp->info_bits) ? $objp->info_bits : '' can also be of type string. However, the property $info_bits is declared as type integer. Maybe add an additional type check?

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

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

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

class Id
{
    public $id;

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

}

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

$account_id = false;

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

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
408
                $line->total_ht = $objp->total_ht;
409
                $line->total_tva = $objp->total_tva;
410
                $line->total_ttc = $objp->total_ttc;
411
                $line->rang = $objp->rang;
412
                $line->special_code = $objp->special_code;
413
                $line->fk_unit = $objp->fk_unit;
414
415
                $this->lines[$i] = $line;
416
417
                $i++;
418
            }
419
420
            $this->db->free($result);
421
            return 1;
422
        } else {
423
            $this->error = $this->db->error();
424
            return -3;
425
        }
426
    }
427
428
429
    /**
430
     *  Delete template fichinter rec
431
     *
432
     *  @param      User    $user           Object user who delete
433
     *  @param      int     $notrigger      Disable trigger
434
     *  @return     int                     Return integer <0 if KO, >0 if OK
435
     */
436
    public function delete(User $user, $notrigger = 0)
437
    {
438
        $rowid = $this->id;
439
440
        dol_syslog(get_class($this) . "::delete rowid=" . $rowid, LOG_DEBUG);
441
442
        $error = 0;
443
        $this->db->begin();
444
445
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "fichinterdet_rec WHERE fk_fichinter = " . ((int) $rowid);
446
        dol_syslog($sql);
447
        if ($this->db->query($sql)) {
448
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "fichinter_rec WHERE rowid = " . ((int) $rowid);
449
            dol_syslog($sql);
450
            if (!$this->db->query($sql)) {
451
                $this->error = $this->db->lasterror();
452
                $error = -1;
453
            }
454
        } else {
455
            $this->error = $this->db->lasterror();
456
            $error = -2;
457
        }
458
459
        if (!$error) {
460
            $this->db->commit();
461
            return 1;
462
        } else {
463
            $this->db->rollback();
464
            return $error;
465
        }
466
    }
467
468
469
    /**
470
     *  Add line to a recurring intervention
471
     *
472
     *  @param      string      $desc               Line description
473
     *  @param      integer     $duration           Duration
474
     *  @param      string      $date               Date
475
     *  @param      int         $rang               Position of line
476
     *  @param      double      $pu_ht              Unit price without tax (> 0 even for credit note)
477
     *  @param      double      $qty                Quantity
478
     *  @param      double      $txtva              Forced VAT rate, otherwise -1
479
     *  @param      int         $fk_product         Id of predefined product/service
480
     *  @param      double      $remise_percent     Percentage of discount for line
481
     *  @param      string      $price_base_type    HT or TTC
482
     *  @param      int         $info_bits          Bits for type of lines
483
     *  @param      int         $fk_remise_except   Id discount (not used)
484
     *  @param      double      $pu_ttc             Unit price with tax (> 0 even for credit note)
485
     *  @param      int         $type               Type of line (0=product, 1=service)
486
     *  @param      int         $special_code       Special code
487
     *  @param      string      $label              Label of the line
488
     *  @param      string      $fk_unit            Unit
489
     *  @return     int                             if KO: <0 || if OK: Id of line
490
     */
491
    public function addLineRec($desc, $duration, $date, $rang = -1, $pu_ht = 0, $qty = 0, $txtva = 0, $fk_product = 0, $remise_percent = 0, $price_base_type = 'HT', $info_bits = 0, $fk_remise_except = 0, $pu_ttc = 0, $type = 0, $special_code = 0, $label = '', $fk_unit = null)
492
    {
493
        global $mysoc;
494
495
        include_once DOL_DOCUMENT_ROOT . '/core/lib/price.lib.php';
496
497
        // Check parameters
498
        if ($type < 0) {
499
            $this->error = 'Bad value for parameter type';
500
            return -1;
501
        }
502
503
        if ($this->status == self::STATUS_DRAFT) {
504
            // Clean parameters
505
            $remise_percent = price2num($remise_percent);
506
            $qty = price2num($qty);
507
            if (!$qty) {
508
                $qty = 1;
509
            }
510
            if (!$info_bits) {
511
                $info_bits = 0;
512
            }
513
            $pu_ht = price2num($pu_ht);
514
            $pu_ttc = price2num($pu_ttc);
515
            if (!preg_match('/\((.*)\)/', (string) $txtva)) {
516
                $txtva = price2num($txtva); // $txtva can have format '5.0(XXX)' or '5'
517
            }
518
519
            if ($price_base_type == 'HT') {
520
                $pu = $pu_ht;
521
            } else {
522
                $pu = $pu_ttc;
523
            }
524
525
            // Calcul du total TTC et de la TVA pour la ligne a partir de
526
            // qty, pu, remise_percent et txtva
527
            // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
528
            // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
529
            $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, 0, 0, 0, $price_base_type, $info_bits, $type, $mysoc);
530
531
            $total_ht  = $tabprice[0];
532
            $total_tva = $tabprice[1];
533
            $total_ttc = $tabprice[2];
534
535
            $pu_ht = $tabprice[3];
536
537
            $product_type = $type;
538
            if ($fk_product) {
539
                $product = new Product($this->db);
540
                $result = $product->fetch($fk_product);
541
                $product_type = $product->type;
542
            }
543
544
            $sql = "INSERT INTO " . MAIN_DB_PREFIX . "fichinterdet_rec (";
545
            $sql .= "fk_fichinter";
546
            $sql .= ", label";
547
            $sql .= ", description";
548
            $sql .= ", date";
549
            $sql .= ", duree";
550
            //$sql.= ", price";
551
            //$sql.= ", qty";
552
            //$sql.= ", tva_tx";
553
            $sql .= ", fk_product";
554
            $sql .= ", product_type";
555
            $sql .= ", remise_percent";
556
            $sql .= ", subprice";
557
            $sql .= ", total_ht";
558
            $sql .= ", total_tva";
559
            $sql .= ", total_ttc";
560
            $sql .= ", rang";
561
            //$sql.= ", special_code";
562
            $sql .= ", fk_unit";
563
            $sql .= ") VALUES (";
564
            $sql .= (int) $this->id;
565
            $sql .= ", " . (!empty($label) ? "'" . $this->db->escape($label) . "'" : "null");
566
            $sql .= ", " . (!empty($desc) ? "'" . $this->db->escape($desc) . "'" : "null");
567
            $sql .= ", " . (!empty($date) ? "'" . $this->db->idate($date) . "'" : "null");
568
            $sql .= ", " . $duration;
569
            //$sql.= ", ".(!empty($qty)? $qty :(!empty($duration)? $duration :"null"));
570
            //$sql.= ", ".price2num($txtva);
571
            $sql .= ", " . (!empty($fk_product) ? $fk_product : "null");
572
            $sql .= ", " . $product_type;
573
            $sql .= ", " . (!empty($remise_percent) ? $remise_percent : "null");
574
            $sql .= ", '" . price2num($pu_ht) . "'";
575
            $sql .= ", '" . price2num($total_ht) . "'";
576
            $sql .= ", '" . price2num($total_tva) . "'";
577
            $sql .= ", '" . price2num($total_ttc) . "'";
578
            $sql .= ", " . (int) $rang;
579
            //$sql.= ", ".$special_code;
580
            $sql .= ", " . (!empty($fk_unit) ? $fk_unit : "null");
581
            $sql .= ")";
582
583
            dol_syslog(get_class($this) . "::addLineRec", LOG_DEBUG);
584
            if ($this->db->query($sql)) {
585
                return 1;
586
            } else {
587
                $this->error = $this->db->lasterror();
588
                return -1;
589
            }
590
        } else {
591
            $this->error = 'Bad status of recurring intervention. Must be draft status to allow addition of lines';
592
            return -1;
593
        }
594
    }
595
596
597
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
598
    /**
599
     *  Rend la fichinter automatique
600
     *
601
     *  @param      User    $user       User object
602
     *  @param      int     $freq       Freq
603
     *  @param      string  $courant    Courant
604
     *  @return     int                 0 if OK, <0 if KO
605
     */
606
    public function set_auto($user, $freq, $courant)
607
    {
608
		// phpcs:enable
609
        if ($user->hasRight('fichinter', 'creer')) {
610
            $sql = "UPDATE " . MAIN_DB_PREFIX . "fichinter_rec ";
611
            $sql .= " SET frequency='" . $this->db->escape($freq) . "'";
612
            $sql .= ", date_last_gen='" . $this->db->escape($courant) . "'";
613
            $sql .= " WHERE rowid = " . ((int) $this->id);
614
615
            $resql = $this->db->query($sql);
616
617
            if ($resql) {
618
                $this->frequency = $freq;
619
                $this->date_last_gen = $courant;
620
                return 0;
621
            } else {
622
                dol_print_error($this->db);
623
                return -1;
624
            }
625
        } else {
626
            return -2;
627
        }
628
    }
629
630
    /**
631
     *  Return clicable name (with picto eventually)
632
     *
633
     *  @param  int     $withpicto      Add picto into link
634
     *  @param  string  $option         Where point the link
635
     *  @param  int     $max            Maxlength of ref
636
     *  @param  int     $short          1=Return just URL
637
     *  @param  string   $moretitle     Add more text to title tooltip
638
     *  @return string                  String with URL
639
     */
640
    public function getNomUrl($withpicto = 0, $option = '', $max = 0, $short = 0, $moretitle = '')
641
    {
642
        global $langs, $hookmanager;
643
644
        $result = '';
645
        $label = $langs->trans("ShowInterventionModel") . ': ' . $this->ref;
646
647
        $url = constant('BASE_URL') . '/fichinter/card-rec.php?id=' . $this->id;
648
649
        if ($short) {
650
            return $url;
651
        }
652
653
        $picto = 'intervention';
654
655
        $link = '<a href="' . $url . '" title="' . dol_escape_htmltag($label, 1) . '" class="classfortooltip">';
656
        $linkend = '</a>';
657
658
        if ($withpicto) {
659
            $result .= $link . img_object($label, $picto, 'class="classfortooltip"') . $linkend;
660
        }
661
        if ($withpicto && $withpicto != 2) {
662
            $result .= ' ';
663
        }
664
        if ($withpicto != 2) {
665
            $result .= $link . $this->ref . $linkend;
666
        }
667
        global $action;
668
        $hookmanager->initHooks(array($this->element . 'dao'));
669
        $parameters = array('id' => $this->id, 'getnomurl' => &$result);
670
        $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
671
        if ($reshook > 0) {
672
            $result = $hookmanager->resPrint;
673
        } else {
674
            $result .= $hookmanager->resPrint;
675
        }
676
        return $result;
677
    }
678
679
680
    /**
681
     *  Initialise an instance with random values.
682
     *  Used to build previews or test instances.
683
     *  id must be 0 if object instance is a specimen.
684
     *
685
     *  @return int
686
     */
687
    public function initAsSpecimen()
688
    {
689
        //$now = dol_now();
690
        //$arraynow = dol_getdate($now);
691
        //$nownotime = dol_mktime(0, 0, 0, $arraynow['mon'], $arraynow['mday'], $arraynow['year']);
692
693
        parent::initAsSpecimen();
694
695
        $this->usenewprice = 1;
696
697
        return 1;
698
    }
699
700
    /**
701
     * Function used to replace a thirdparty id with another one.
702
     *
703
     * @param   DoliDB  $dbs        Database handler, because function is static we name it $dbs not $db to avoid breaking coding test
704
     * @param   int     $origin_id  Old thirdparty id
705
     * @param   int     $dest_id    New thirdparty id
706
     * @return  bool
707
     */
708
    public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
709
    {
710
        $tables = array('fichinter_rec');
711
712
        return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables);
713
    }
714
715
    /**
716
     * Function used to replace a product id with another one.
717
     *
718
     * @param DoliDB $db Database handler
719
     * @param int $origin_id Old product id
720
     * @param int $dest_id New product id
721
     * @return bool
722
     */
723
    public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
724
    {
725
        $tables = array(
726
            'fichinterdet_rec'
727
        );
728
729
        return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables);
730
    }
731
732
    /**
733
     *  Update frequency and unit
734
     *
735
     *  @param      int     $frequency      value of frequency
736
     *  @param      string  $unit           unit of frequency  (d, m, y)
737
     *  @return     int                     Return integer <0 if KO, >0 if OK
738
     */
739
    public function setFrequencyAndUnit($frequency, $unit)
740
    {
741
        if (!$this->table_element) {
742
            dol_syslog(get_class($this) . "::setFrequencyAndUnit called with table_element not defined", LOG_ERR);
743
            return -1;
744
        }
745
746
        if (!empty($frequency) && empty($unit)) {
747
            dol_syslog(get_class($this) . "::setFrequencyAndUnit called with frequency defined but unit not ", LOG_ERR);
748
            return -2;
749
        }
750
751
        $sql = 'UPDATE ' . MAIN_DB_PREFIX . $this->table_element;
752
        $sql .= ' SET frequency = ' . ($frequency ? $this->db->escape($frequency) : 'null');
753
        if (!empty($unit)) {
754
            $sql .= ', unit_frequency = "' . $this->db->escape($unit) . '"';
755
        }
756
        $sql .= " WHERE rowid = " . ((int) $this->id);
757
758
        dol_syslog(get_class($this) . "::setFrequencyAndUnit", LOG_DEBUG);
759
        if ($this->db->query($sql)) {
760
            $this->frequency = $frequency;
761
            if (!empty($unit)) {
762
                $this->unit_frequency = $unit;
763
            }
764
            return 1;
765
        } else {
766
            dol_print_error($this->db);
767
            return -1;
768
        }
769
    }
770
771
    /**
772
     *  Update the next date of execution
773
     *
774
     *  @param      datetime    $date                   date of execution
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\FichInter\Classes\datetime was not found. Did you mean datetime? If so, make sure to prefix the type with \.
Loading history...
775
     *  @param      int         $increment_nb_gen_done  0 do nothing more, >0 increment nb_gen_done
776
     *  @return     int                                 Return integer <0 if KO, >0 if OK
777
     */
778
    public function setNextDate($date, $increment_nb_gen_done = 0)
779
    {
780
        if (!$this->table_element) {
781
            dol_syslog(get_class($this) . "::setNextDate was called on object with property table_element not defined", LOG_ERR);
782
            return -1;
783
        }
784
        $sql = 'UPDATE ' . MAIN_DB_PREFIX . $this->table_element;
785
        $sql .= " SET date_when = " . ($date ? "'" . $this->db->idate($date) . "'" : "null");
786
        if ($increment_nb_gen_done > 0) {
787
            $sql .= ', nb_gen_done = nb_gen_done + 1';
788
        }
789
        $sql .= " WHERE rowid = " . ((int) $this->id);
790
791
        dol_syslog(get_class($this) . "::setNextDate", LOG_DEBUG);
792
        if ($this->db->query($sql)) {
793
            $this->date_when = $date;
794
            if ($increment_nb_gen_done > 0) {
795
                $this->nb_gen_done++;
796
            }
797
            return 1;
798
        } else {
799
            dol_print_error($this->db);
800
            return -1;
801
        }
802
    }
803
804
    /**
805
     *  Update the maximum period
806
     *
807
     *  @param      int     $nb     number of maximum period
808
     *  @return     int             Return integer <0 if KO, >0 if OK
809
     */
810
    public function setMaxPeriod($nb)
811
    {
812
        if (!$this->table_element) {
813
            dol_syslog(get_class($this) . "::setMaxPeriod was called on object with property table_element not defined", LOG_ERR);
814
            return -1;
815
        }
816
817
        if (empty($nb)) {
818
            $nb = 0;
819
        }
820
821
        $sql = 'UPDATE ' . MAIN_DB_PREFIX . $this->table_element;
822
        $sql .= ' SET nb_gen_max = ' . ((int) $nb);
823
        $sql .= ' WHERE rowid = ' . ((int) $this->id);
824
825
        dol_syslog(get_class($this) . "::setMaxPeriod", LOG_DEBUG);
826
        if ($this->db->query($sql)) {
827
            $this->nb_gen_max = $nb;
828
            return 1;
829
        } else {
830
            dol_print_error($this->db);
831
            return -1;
832
        }
833
    }
834
835
    /**
836
     *  Update the auto validate fichinter
837
     *
838
     *  @param      int     $validate       0 to create in draft, 1 to create and validate fichinter
839
     *  @return     int                     Return integer <0 if KO, >0 if OK
840
     */
841
    public function setAutoValidate($validate)
842
    {
843
        if (!$this->table_element) {
844
            dol_syslog(get_class($this) . "::setAutoValidate called with property table_element not defined", LOG_ERR);
845
            return -1;
846
        }
847
848
        $sql = 'UPDATE ' . MAIN_DB_PREFIX . $this->table_element;
849
        $sql .= ' SET auto_validate = ' . ((int) $validate);
850
        $sql .= ' WHERE rowid = ' . ((int) $this->id);
851
852
        dol_syslog(get_class($this) . "::setAutoValidate", LOG_DEBUG);
853
        if ($this->db->query($sql)) {
854
            $this->auto_validate = $validate;
855
            return 1;
856
        } else {
857
            dol_print_error($this->db);
858
            return -1;
859
        }
860
    }
861
862
    /**
863
     *  Update the Number of Generation Done
864
     *
865
     *  @return     int                     Return integer <0 if KO, >0 if OK
866
     */
867
    public function updateNbGenDone()
868
    {
869
        if (!$this->table_element) {
870
            dol_syslog(get_class($this) . "::updateNbGenDone called with property table_element not defined", LOG_ERR);
871
            return -1;
872
        }
873
874
        $sql = 'UPDATE ' . MAIN_DB_PREFIX . $this->table_element;
875
        $sql .= ' SET nb_gen_done = nb_gen_done + 1';
876
        $sql .= ' , date_last_gen = now()';
877
        // si on et arrivé à la fin des génération
878
        if ($this->nb_gen_max <= $this->nb_gen_done + 1) {
879
            $sql .= ' , status = 1';
880
        }
881
882
        $sql .= " WHERE rowid = " . ((int) $this->id);
883
884
        dol_syslog(get_class($this) . "::setAutoValidate", LOG_DEBUG);
885
        if ($this->db->query($sql)) {
886
            $this->nb_gen_done = $this->nb_gen_done + 1;
887
            $this->nb_gen_done = dol_now();
888
            return 1;
889
        } else {
890
            dol_print_error($this->db);
891
            return -1;
892
        }
893
    }
894
}
895