Passed
Pull Request — dev (#8)
by Rafael
58:47
created

FactureFournisseurRec   F

Complexity

Total Complexity 281

Size/Duplication

Total Lines 1957
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1176
dl 0
loc 1957
rs 0.896
c 1
b 0
f 0
wmc 281

25 Methods

Rating   Name   Duplication   Size   Complexity  
A setGeneratePdf() 0 19 3
B delete() 0 51 10
B fetch() 0 109 6
A strikeIfMaxNbGenReached() 0 4 3
D update() 0 74 45
A __construct() 0 3 1
F updateline() 0 121 21
A setMaxPeriod() 0 23 4
B fetch_lines() 0 93 3
F getNomUrl() 0 64 24
A getLinesArray() 0 3 1
A getNextDate() 0 6 2
F createRecurringInvoices() 0 152 18
A getLibStatut() 0 3 3
A getNextNumRef() 0 4 1
F create() 0 217 50
B setFrequencyAndUnit() 0 30 8
F addline() 0 163 26
A replaceThirdparty() 0 7 1
D LibStatut() 0 122 27
A setModelPdf() 0 19 3
A isMaxNbGenReached() 0 7 3
A setNextDate() 0 24 6
A setAutoValidate() 0 19 3
C initAsSpecimen() 0 120 9

How to fix   Complexity   

Complex Class

Complex classes like FactureFournisseurRec 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 FactureFournisseurRec, 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-2019	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) 2017-2024  Frédéric France             <[email protected]>
11
 * Copyright (C) 2024		MDW					        <[email protected]>
12
 * Copyright (C) 2023-2024  Nick Fragoulis
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\Fourn\Classes;
30
31
use Dolibarr\Code\Core\Classes\CommonInvoice;
32
33
/**
34
 *  \file       htdocs/fourn/facture/class/fournisseur.facture-rec.class.php
35
 *  \ingroup    invoice
36
 *  \brief      File for class to manage invoice templates
37
 */
38
39
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/date.lib.php';
40
41
42
/**
43
 *  Class to manage invoice templates
44
 */
45
class FactureFournisseurRec extends CommonInvoice
46
{
47
    const TRIGGER_PREFIX = 'SUPPLIERBILLREC';
48
    /**
49
     * @var string ID to identify managed object
50
     */
51
    public $element = 'invoice_supplier_rec';
52
53
    /**
54
     * @var string Name of table without prefix where object is stored
55
     */
56
    public $table_element = 'facture_fourn_rec';
57
58
    /**
59
     * @var string    Name of subtable line
60
     */
61
    public $table_element_line = 'facture_fourn_det_rec';
62
63
    /**
64
     * @var string Field with ID of parent key if this field has a parent
65
     */
66
    public $fk_element = 'fk_facture_fourn';
67
68
    /**
69
     * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
70
     */
71
    public $picto = 'bill';
72
73
    /**
74
     * {@inheritdoc}
75
     */
76
    protected $table_ref_field = 'titre';
77
78
    /**
79
     * @var string  The label of recurring invoice
80
     * @deprecated  Use $title
81
     */
82
    public $titre;
83
    /**
84
     * @var string The label of recurring invoice
85
     */
86
    public $title;
87
88
    public $ref_supplier;
89
    public $socid;
90
91
    /**
92
     * @var int
93
     * @deprecated
94
     */
95
    public $fk_soc;
96
97
    public $suspended; // status
98
99
    /**
100
     * @var string      Label of invoice
101
     * @deprecated      Use $label
102
     */
103
    public $libelle;
104
    /**
105
     * @var string      Label of invoice
106
     */
107
    public $label;
108
109
    /**
110
     * @var double $amount
111
     * @deprecated
112
     */
113
    public $amount;
114
    /**
115
     * @var double $remise
116
     * @deprecated
117
     */
118
    public $remise;
119
120
    public $vat_src_code;
121
    public $localtax1;
122
    public $localtax2;
123
124
    public $user_author;
125
    public $user_modif;
126
    public $fk_project;
127
128
    public $mode_reglement_id;
129
    public $mode_reglement_code;
130
    public $cond_reglement_code;
131
    public $cond_reglement_doc;
132
    public $cond_reglement_id;
133
134
    /**
135
     * @var int Deadline for payment
136
     */
137
    public $date_lim_reglement;
138
139
    public $usenewprice = 0;
140
    public $frequency;
141
    public $unit_frequency;
142
    public $date_when;
143
    public $date_last_gen;
144
145
    /**
146
     * @var int nb generation done
147
     */
148
    public $nb_gen_done;
149
150
    /**
151
     * @var int nb generation max
152
     */
153
    public $nb_gen_max;
154
155
    /**
156
     * @var int<0,1> auto validate 0 to create in draft, 1 to create and validate the new invoice
157
     */
158
    public $auto_validate; //
159
    public $generate_pdf; // 1 to generate PDF on invoice generation (default)
160
161
    /**
162
     * Invoice lines
163
     * @var CommonInvoiceLine[]
164
     */
165
    public $lines = array();
166
167
168
    /* Override fields in CommonObject
169
    public $entity;
170
    public $date_creation;
171
    public $date_modification;
172
    public $total_ht;
173
    public $total_tva;
174
    public $total_ttc;
175
    public $fk_account;
176
    public $mode_reglement;
177
    public $cond_reglement;
178
    public $note_public;
179
    public $note_private;
180
    */
181
182
    /**
183
     *  'type' if the field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password')
184
     *         Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)"
185
     *  'label' the translation key.
186
     *  'enabled' is a condition when the field must be managed.
187
     *  'position' is the sort order of field.
188
     *  'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0).
189
     *  'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing)
190
     *  'noteditable' says if field is not editable (1 or 0)
191
     *  'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created.
192
     *  'index' if we want an index in database.
193
     *  'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommended to name the field fk_...).
194
     *  'searchall' is 1 if we want to search in this field when making a search from the quick search button.
195
     *  'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8).
196
     *  'css' is the CSS style to use on field. For example: 'maxwidth200'
197
     *  'help' is a string visible as a tooltip on field
198
     *  'showoncombobox' if value of the field must be visible into the label of the combobox that list record
199
     *  'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code.
200
     *  'arrayofkeyval' to set list of value if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel")
201
     *  'comment' is not used. You can store here any text of your choice. It is not used by application.
202
     *
203
     *  Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor.
204
     */
205
206
    // BEGIN MODULEBUILDER PROPERTIES
207
    /**
208
     * @var array<string,array{type:string,label:string,enabled:int<0,2>|string,position:int,notnull?:int,visible:int,noteditable?:int,default?:string,index?:int,foreignkey?:string,searchall?:int,isameasure?:int,css?:string,csslist?:string,help?:string,showoncombobox?:int,disabled?:int,arrayofkeyval?:array<int,string>,comment?:string}>  Array with all fields and their property. Do not use it as a static var. It may be modified by constructor.
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string,array{type:...ring>,comment?:string}> at position 16 could not be parsed: Expected '}' at position 16, but found 'int'.
Loading history...
209
     */
210
    public $fields = array(
211
        'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 10),
212
        'titre' => array('type' => 'varchar(100)', 'label' => 'Titre', 'enabled' => 1, 'showoncombobox' => 1, 'visible' => -1, 'position' => 15),
213
        'ref_supplier' => array('type' => 'varchar(180)', 'label' => 'RefSupplier', 'enabled' => 1, 'showoncombobox' => 1, 'visible' => -1, 'position' => 20),
214
        'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => '1', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 25, 'index' => 1),
215
        'fk_soc' => array('type' => 'integer:Societe:societe/class/societe.class.php', 'label' => 'ThirdParty', 'enabled' => 'isModEnabled("societe")', 'visible' => -1, 'notnull' => 1, 'position' => 30),
216
        'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -1, 'position' => 35),
217
        'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 40),
218
        'suspended' => array('type' => 'integer', 'label' => 'Suspended', 'enabled' => 1, 'visible' => -1, 'position' => 225),
219
        'libelle' => array('type' => 'varchar(100)', 'label' => 'Libelle', 'enabled' => 1, 'showoncombobox' => 0, 'visible' => -1, 'position' => 15),
220
221
        'localtax1' => array('type' => 'double(24,8)', 'label' => 'Localtax1', 'enabled' => 1, 'visible' => -1, 'position' => 60, 'isameasure' => 1),
222
        'localtax2' => array('type' => 'double(24,8)', 'label' => 'Localtax2', 'enabled' => 1, 'visible' => -1, 'position' => 65, 'isameasure' => 1),
223
        'total_ht' => array('type' => 'double(24,8)', 'label' => 'Total', 'enabled' => 1, 'visible' => -1, 'position' => 70, 'isameasure' => 1),
224
        'total_tva' => array('type' => 'double(24,8)', 'label' => 'Tva', 'enabled' => 1, 'visible' => -1, 'position' => 55, 'isameasure' => 1),
225
        'total_ttc' => array('type' => 'double(24,8)', 'label' => 'Total ttc', 'enabled' => 1, 'visible' => -1, 'position' => 75, 'isameasure' => 1),
226
227
        'fk_user_author' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'Fk user author', 'enabled' => 1, 'visible' => -1, 'position' => 80),
228
        'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'position' => 210),
229
        'fk_projet' => array('type' => 'integer:Project:projet/class/project.class.php:1:fk_statut=1', 'label' => 'Fk projet', 'enabled' => "isModEnabled('project')", 'visible' => -1, 'position' => 85),
230
        'fk_account' => array('type' => 'integer', 'label' => 'Fk account', 'enabled' => 'isModEnabled("bank")', 'visible' => -1, 'position' => 175),
231
        'fk_cond_reglement' => array('type' => 'integer', 'label' => 'Fk cond reglement', 'enabled' => 1, 'visible' => -1, 'position' => 90),
232
        'fk_mode_reglement' => array('type' => 'integer', 'label' => 'Fk mode reglement', 'enabled' => 1, 'visible' => -1, 'position' => 95),
233
        'date_lim_reglement' => array('type' => 'date', 'label' => 'Date lim reglement', 'enabled' => 1, 'visible' => -1, 'position' => 100),
234
235
        'note_private' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 105),
236
        'note_public' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 110),
237
        'modelpdf' => array('type' => 'varchar(255)', 'label' => 'Modelpdf', 'enabled' => 1, 'visible' => -1, 'position' => 115),
238
239
        'fk_multicurrency' => array('type' => 'integer', 'label' => 'Fk multicurrency', 'enabled' => 1, 'visible' => -1, 'position' => 180),
240
        'multicurrency_code' => array('type' => 'varchar(255)', 'label' => 'Multicurrency code', 'enabled' => 1, 'visible' => -1, 'position' => 185),
241
        'multicurrency_tx' => array('type' => 'double(24,8)', 'label' => 'Multicurrency tx', 'enabled' => 1, 'visible' => -1, 'position' => 190, 'isameasure' => 1),
242
        'multicurrency_total_ht' => array('type' => 'double(24,8)', 'label' => 'Multicurrency total ht', 'enabled' => 1, 'visible' => -1, 'position' => 195, 'isameasure' => 1),
243
        'multicurrency_total_tva' => array('type' => 'double(24,8)', 'label' => 'Multicurrency total tva', 'enabled' => 1, 'visible' => -1, 'position' => 200, 'isameasure' => 1),
244
        'multicurrency_total_ttc' => array('type' => 'double(24,8)', 'label' => 'Multicurrency total ttc', 'enabled' => 1, 'visible' => -1, 'position' => 205, 'isameasure' => 1),
245
246
        'usenewprice' => array('type' => 'integer', 'label' => 'UseNewPrice', 'enabled' => 1, 'visible' => 0, 'position' => 155),
247
        'frequency' => array('type' => 'integer', 'label' => 'Frequency', 'enabled' => 1, 'visible' => -1, 'position' => 150),
248
        'unit_frequency' => array('type' => 'varchar(2)', 'label' => 'Unit frequency', 'enabled' => 1, 'visible' => -1, 'position' => 125),
249
250
        'date_when' => array('type' => 'datetime', 'label' => 'Date when', 'enabled' => 1, 'visible' => -1, 'position' => 130),
251
        'date_last_gen' => array('type' => 'datetime', 'label' => 'Date last gen', 'enabled' => 1, 'visible' => -1, 'position' => 135),
252
        'nb_gen_done' => array('type' => 'integer', 'label' => 'Nb gen done', 'enabled' => 1, 'visible' => -1, 'position' => 140),
253
        'nb_gen_max' => array('type' => 'integer', 'label' => 'Nb gen max', 'enabled' => 1, 'visible' => -1, 'position' => 145),
254
        'revenuestamp' => array('type' => 'double(24,8)', 'label' => 'RevenueStamp', 'enabled' => 1, 'visible' => -1, 'position' => 160, 'isameasure' => 1),
255
        'auto_validate' => array('type' => 'integer', 'label' => 'Auto validate', 'enabled' => 1, 'visible' => -1, 'position' => 165),
256
        'generate_pdf' => array('type' => 'integer', 'label' => 'Generate pdf', 'enabled' => 1, 'visible' => -1, 'position' => 170),
257
    );
258
    // END MODULEBUILDER PROPERTIES
259
260
    const STATUS_NOTSUSPENDED = 0;
261
    const STATUS_SUSPENDED = 1;
262
263
264
265
    /**
266
     *  Constructor
267
     *
268
     *  @param      DoliDB      $db     Database handler
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Fourn\Classes\DoliDB was not found. Did you mean DoliDB? If so, make sure to prefix the type with \.
Loading history...
269
     */
270
    public function __construct($db)
271
    {
272
        $this->db = $db;
273
    }
274
275
    /**
276
     *    Create a predefined supplier invoice
277
     *
278
     * @param   User    $user           User object
279
     * @param   int     $facFournId     Id invoice
280
     * @param   int     $notrigger      No trigger
281
     * @return  int                     Return integer <0 if KO, id of invoice created if OK
282
     */
283
    public function create($user, $facFournId, $notrigger = 0)
284
    {
285
        global $conf;
286
287
        $error = 0;
288
        $now = dol_now();
289
290
        // Clean parameters
291
        $this->titre = empty($this->titre) ? '' : $this->titre; // deprecated
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Code\Fourn\Clas...eFournisseurRec::$titre has been deprecated: Use $title ( Ignorable by Annotation )

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

291
        $this->titre = empty(/** @scrutinizer ignore-deprecated */ $this->titre) ? '' : $this->titre; // deprecated

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...
292
        $this->title = empty($this->title) ? '' : $this->title;
293
        $keyforref = $this->table_ref_field;
294
        $this->ref = $this->$keyforref;
295
        $this->ref_supplier = empty($this->ref_supplier) ? '' : $this->ref_supplier;
296
        $this->usenewprice = empty($this->usenewprice) ? 0 : $this->usenewprice;
297
        $this->suspended = empty($this->suspended) ? 0 : $this->suspended;
298
        // No frequency defined then no next date to execution
299
        if (empty($this->frequency)) {
300
            $this->frequency = 0;
301
            $this->date_when = null;
302
        }
303
        $this->frequency = abs($this->frequency);
304
        $this->nb_gen_done = 0;
305
        $this->nb_gen_max = empty($this->nb_gen_max) ? 0 : $this->nb_gen_max;
306
        $this->auto_validate = empty($this->auto_validate) ? 0 : $this->auto_validate;
307
        $this->generate_pdf = empty($this->generate_pdf) ? 0 : $this->generate_pdf;
308
309
        $this->db->begin();
310
311
        // On charge la facture fournisseur depuis laquelle on crée la facture fournisseur modèle
312
        $facfourn_src = new FactureFournisseur($this->db);
313
        $result = $facfourn_src->fetch($facFournId);
314
        if ($result > 0) {
315
            $sql = 'INSERT INTO ' . MAIN_DB_PREFIX . 'facture_fourn_rec (';
316
            $sql .= 'titre';
317
            $sql .= ", subtype";
318
            $sql .= ', ref_supplier';
319
            $sql .= ', entity';
320
            $sql .= ', fk_soc';
321
            $sql .= ', datec';
322
            $sql .= ', suspended';
323
            $sql .= ', libelle';
324
            $sql .= ', total_ttc';
325
            $sql .= ', fk_user_author';
326
            $sql .= ', fk_projet';
327
            $sql .= ', fk_account';
328
            $sql .= ', fk_cond_reglement';
329
            $sql .= ', fk_mode_reglement';
330
            $sql .= ', date_lim_reglement';
331
            $sql .= ', note_private';
332
            $sql .= ', note_public';
333
            $sql .= ', modelpdf';
334
            $sql .= ', fk_multicurrency';
335
            $sql .= ', multicurrency_code';
336
            $sql .= ', multicurrency_tx';
337
            $sql .= ', usenewprice';
338
            $sql .= ', frequency';
339
            $sql .= ', unit_frequency';
340
            $sql .= ', date_when';
341
            $sql .= ', date_last_gen';
342
            $sql .= ', nb_gen_done';
343
            $sql .= ', nb_gen_max';
344
            $sql .= ', auto_validate';
345
            $sql .= ', generate_pdf';
346
            $sql .= ') VALUES (';
347
            $sql .= "'" . $this->db->escape($this->title) . "'";
348
            $sql .= ", " . ($this->subtype ? "'" . $this->db->escape($this->subtype) . "'" : "null");
349
            $sql .= ", '" . $this->db->escape($this->ref_supplier) . "'";
350
            $sql .= ", " . ((int) $conf->entity);
351
            $sql .= ", " . ((int) $facfourn_src->socid);
352
            $sql .= ", '" . $this->db->idate($now) . "'";
353
            $sql .= ", " . ((int) $this->suspended);
354
            $sql .= ", '" . $this->db->escape($this->libelle) . "'";
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Code\Fourn\Clas...ournisseurRec::$libelle has been deprecated: Use $label ( Ignorable by Annotation )

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

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

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...
355
            $sql .= ", " . (!empty($facfourn_src->total_ttc) ? (float) $facfourn_src->total_ttc : '0');                              // amount
356
            $sql .= ", " . ((int) $user->id);
357
            $sql .= ", " . (!empty($this->fk_project) ? ((int) $this->fk_project) : 'NULL');
358
            $sql .= ", " . (!empty($facfourn_src->fk_account) ? ((int) $facfourn_src->fk_account) : 'NULL');
359
            $sql .= ", " . ($this->cond_reglement_id > 0 ? (int) $this->cond_reglement_id : 'NULL');
360
            $sql .= ", " . ($this->mode_reglement_id > 0 ? (int) $this->mode_reglement_id : 'NULL');
361
            $sql .= ", " . ($facfourn_src->date_echeance > 0 ? "'" . $this->db->idate($facfourn_src->date_echeance) . "'" : 'NULL');      // date_lim_reglement
362
            $sql .= ", " . (!empty($this->note_private) ? "'" . $this->db->escape($this->note_private) . "'" : 'NULL');
363
            $sql .= ", " . (!empty($this->note_public) ? "'" . $this->db->escape($this->note_public) . "'" : 'NULL');
364
            $sql .= ", " . (!empty($this->model_pdf) ? "'" . $this->db->escape($this->model_pdf) . "'" : 'NULL');
365
            $sql .= ", " . (int) $facfourn_src->fk_multicurrency;
366
            $sql .= ", '" . $this->db->escape($facfourn_src->multicurrency_code) . "'";
367
            $sql .= ", " . (float) $facfourn_src->multicurrency_tx;
368
            $sql .= ", " . (int) $this->usenewprice;
369
            $sql .= ", " . (int) $this->frequency;
370
            $sql .= ", '" . $this->db->escape($this->unit_frequency) . "'";
371
            $sql .= ", " . (!empty($this->date_when) ? "'" . $this->db->idate($this->date_when) . "'" : 'NULL');
372
            $sql .= ", " . (!empty($this->date_last_gen) ? "'" . $this->db->idate($this->date_last_gen) . "'" : 'NULL');
373
            $sql .= ", " . (int) $this->nb_gen_done;
374
            $sql .= ", " . (int) $this->nb_gen_max;
375
            $sql .= ", " . (int) $this->auto_validate;
376
            $sql .= ", " . (int) $this->generate_pdf;
377
            $sql .= ')';
378
379
            if ($this->db->query($sql)) {
380
                $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . 'facture_fourn_rec');
381
382
                // Fields used into addline later
383
                $this->fk_multicurrency = $facfourn_src->fk_multicurrency;
384
385
                $this->multicurrency_code = $facfourn_src->multicurrency_code;
386
                $this->multicurrency_tx = $facfourn_src->multicurrency_tx;
387
388
                // Add lines
389
                $num = count($facfourn_src->lines);
390
                for ($i = 0; $i < $num; $i++) {
391
                    $tva_tx = $facfourn_src->lines[$i]->tva_tx;
392
                    if (!empty($facfourn_src->lines[$i]->vat_src_code) && !preg_match('/\(/', (string) $tva_tx)) {
393
                        $tva_tx .= ' (' . $facfourn_src->lines[$i]->vat_src_code . ')';
394
                    }
395
396
                    $result_insert = $this->addline(
397
                        $facfourn_src->lines[$i]->fk_product,
398
                        $facfourn_src->lines[$i]->ref_supplier,
0 ignored issues
show
Bug Best Practice introduced by
The property ref_supplier does not exist on Dolibarr\Code\Core\Classes\CommonInvoiceLine. Since you implemented __get, consider adding a @property annotation.
Loading history...
399
                        $facfourn_src->lines[$i]->product_label,
400
                        $facfourn_src->lines[$i]->desc ? $facfourn_src->lines[$i]->desc : $facfourn_src->lines[$i]->description,
401
                        $facfourn_src->lines[$i]->pu_ht,
0 ignored issues
show
Bug Best Practice introduced by
The property pu_ht does not exist on Dolibarr\Code\Core\Classes\CommonInvoiceLine. Since you implemented __get, consider adding a @property annotation.
Loading history...
402
                        $facfourn_src->lines[$i]->pu_ttc,
403
                        $facfourn_src->lines[$i]->qty,
404
                        $facfourn_src->lines[$i]->remise_percent,
405
                        $tva_tx,
406
                        $facfourn_src->lines[$i]->localtax1_tx,
407
                        $facfourn_src->lines[$i]->localtax2_tx,
408
                        'HT',
409
                        $facfourn_src->lines[$i]->product_type,
410
                        $facfourn_src->lines[$i]->date_start,
0 ignored issues
show
Bug Best Practice introduced by
The property date_start does not exist on Dolibarr\Code\Core\Classes\CommonInvoiceLine. Since you implemented __get, consider adding a @property annotation.
Loading history...
411
                        $facfourn_src->lines[$i]->date_end,
0 ignored issues
show
Bug Best Practice introduced by
The property date_end does not exist on Dolibarr\Code\Core\Classes\CommonInvoiceLine. Since you implemented __get, consider adding a @property annotation.
Loading history...
412
                        $facfourn_src->lines[$i]->info_bits,
413
                        $facfourn_src->lines[$i]->special_code,
414
                        $facfourn_src->lines[$i]->rang,
0 ignored issues
show
Bug Best Practice introduced by
The property rang does not exist on Dolibarr\Code\Core\Classes\CommonInvoiceLine. Since you implemented __get, consider adding a @property annotation.
Loading history...
415
                        $facfourn_src->lines[$i]->fk_unit
416
                    );
417
418
                    if ($result_insert < 0) {
419
                        $error++;
420
                    } else {
421
                        $objectline = new FactureFournisseurLigneRec($this->db);
422
423
                        $result2 = $objectline->fetch($result_insert);
424
                        if ($result2 > 0) {
425
                            // Extrafields
426
                            if (method_exists($facfourn_src->lines[$i], 'fetch_optionals')) {
427
                                $facfourn_src->lines[$i]->fetch_optionals($facfourn_src->lines[$i]->id);
428
                                $objectline->array_options = $facfourn_src->lines[$i]->array_options;
429
                            }
430
431
                            $result = $objectline->insertExtraFields();
432
                            if ($result < 0) {
433
                                $error++;
434
                            }
435
                        } elseif ($result2 < 0) {
436
                            $this->errors[] = $objectline->error;
437
                            $error++;
438
                        }
439
                    }
440
                }
441
442
                if (!empty($this->linkedObjectsIds) && empty($this->linked_objects)) {  // To use new linkedObjectsIds instead of old linked_objects
443
                    $this->linked_objects = $this->linkedObjectsIds; // TODO Replace linked_objects with linkedObjectsIds
444
                }
445
446
                // Add object linked
447
                if (!$error && $this->id && !empty($this->linked_objects) && is_array($this->linked_objects)) {
448
                    foreach ($this->linked_objects as $origin => $tmp_origin_id) {
449
                        if (is_array($tmp_origin_id)) {       // New behaviour, if linked_object can have several links per type, so is something like array('contract'=>array(id1, id2, ...))
450
                            foreach ($tmp_origin_id as $origin_id) {
451
                                $ret = $this->add_object_linked($origin, $origin_id);
452
                                if (!$ret) {
453
                                    $this->error = $this->db->lasterror();
454
                                    $error++;
455
                                }
456
                            }
457
                        } else { // Old behaviour, if linked_object has only one link per type, so is something like array('contract'=>id1))
458
                            $origin_id = $tmp_origin_id;
459
                            $ret = $this->add_object_linked($origin, $origin_id);
460
                            if (!$ret) {
461
                                $this->error = $this->db->lasterror();
462
                                $error++;
463
                            }
464
                        }
465
                    }
466
                }
467
468
                if (!$error) {
469
                    $result = $this->insertExtraFields();
470
                    if ($result < 0) {
471
                        $error++;
472
                    }
473
                }
474
475
                if (!$error && !$notrigger) {
476
                    // Call trigger
477
                    $result = $this->call_trigger('SUPPLIERBILLREC_CREATE', $user);
478
                    if ($result < 0) {
479
                        $this->db->rollback();
480
                        return -2;
481
                    }
482
                    // End call triggers
483
                }
484
485
                if ($error) {
486
                    $this->db->rollback();
487
                    return -3;
488
                } else {
489
                    $this->db->commit();
490
                    return $this->id;
491
                }
492
            } else {
493
                $this->error = $this->db->lasterror();
494
                $this->db->rollback();
495
                return -2;
496
            }
497
        } else {
498
            $this->db->rollback();
499
            return -1;
500
        }
501
    }
502
503
504
    /**
505
     *  Update fourn_invoice_rec.
506
     *
507
     *  @param      User    $user                   User
508
     *  @param      int     $notrigger              No trigger
509
     *  @return     int                             Return integer <0 if KO, Id of line if OK
510
     */
511
    public function update(User $user, $notrigger = 0)
512
    {
513
        $error = 0;
514
515
        $sql = "UPDATE " . MAIN_DB_PREFIX . "facture_fourn_rec SET";
516
        $sql .= " titre = '" . (!empty($this->title) ? $this->db->escape($this->title) : "") . "'," ;
517
        $sql .= " subtype=" . (isset($this->subtype) ? $this->db->escape($this->subtype) : "null") . ",";
518
        $sql .= " ref_supplier = '" . (!empty($this->ref_supplier) ? $this->db->escape($this->ref_supplier) : "") . "',";
519
        $sql .= " entity = " . (!empty($this->entity) ? ((int) $this->entity) : 1) . ',';
520
        if (!empty($this->socid) && $this->socid > 0) {
521
            $sql .= " fk_soc = " . ((int) $this->socid) . ',';
522
        } elseif (!empty($this->fk_soc) && $this->fk_soc > 0) { // For backward compatibility
523
            $sql .= " fk_soc = " . ((int) $this->fk_soc) . ',';
524
        }
525
        $sql .= " suspended = " . (!empty($this->suspended) ? ((int) $this->suspended) : 0) . ',';
526
        $sql .= " libelle = " . (!empty($this->libelle) ? "'" . $this->db->escape($this->libelle) . "'" : 'NULL') . ",";
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Code\Fourn\Clas...ournisseurRec::$libelle has been deprecated: Use $label ( Ignorable by Annotation )

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

526
        $sql .= " libelle = " . (!empty(/** @scrutinizer ignore-deprecated */ $this->libelle) ? "'" . $this->db->escape($this->libelle) . "'" : 'NULL') . ",";

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...
527
        $sql .= " vat_src_code = " . (!empty($this->vat_src_code) ? "'" . $this->db->escape($this->vat_src_code) . "'" : 'NULL') . ',';
528
        $sql .= " localtax1 = " . (!empty($this->localtax1) ? ((float) $this->localtax1) : 0.00) . ',';
529
        $sql .= " localtax2 = " . (!empty($this->localtax2) ? ((float) $this->localtax2) : 0.00) . ',';
530
        $sql .= " total_ht = " . (!empty($this->total_ht) ? ((float) $this->total_ht) : 0.00) . ',';
531
        $sql .= " total_tva = " . (!empty($this->total_tva) ? ((float) $this->total_tva) : 0.00) . ',';
532
        $sql .= " total_ttc = " . (!empty($this->total_ttc) ? ((float) $this->total_ttc) : 0.00) . ',';
533
        $sql .= " fk_user_modif = " . ((int) $user->id) . ',';
534
        $sql .= " fk_projet = " . (!empty($this->fk_project) ? ((int) $this->fk_project) : 'NULL') . ',';
535
        $sql .= " fk_account = " . (!empty($this->fk_account) ? ((int) $this->fk_account) : 'NULL') . ',';
536
        $sql .= " fk_mode_reglement = " . (!empty($this->mode_reglement_id) ? ((int) $this->mode_reglement_id) : 'NULL') . ',';
537
        $sql .= " fk_cond_reglement = " . (!empty($this->cond_reglement_id) ? ((int) $this->cond_reglement_id) : 'NULL') . ',';
538
        $sql .= " date_lim_reglement = " . (!empty($this->date_lim_reglement) ? "'" . $this->db->idate($this->date_lim_reglement) . "'" : 'NULL') . ',';
539
        $sql .= " note_private = '" . (!empty($this->note_private) ? $this->db->escape($this->note_private) : '') . "',";
540
        $sql .= " note_public = '" . (!empty($this->note_public) ? $this->db->escape($this->note_public) : '') . "',";
541
        $sql .= " modelpdf = " . (!empty($this->model_pdf) ? "'" . $this->db->escape($this->model_pdf) . "'" : 'NULL') . ",";
542
        $sql .= " fk_multicurrency = " . (!empty($this->fk_multicurrency) ? ((int) $this->fk_multicurrency) : 'NULL') . ',';
543
        $sql .= " multicurrency_code = " . (!empty($this->multicurrency_code) ? "'" . $this->db->escape($this->multicurrency_code) . "'" : 'NULL') . ",";
544
        $sql .= " multicurrency_tx = " . (!empty($this->multicurrency_tx) ? ((float) $this->multicurrency_tx) : 1) . ',';
545
        $sql .= " multicurrency_total_ht = " . (!empty($this->multicurrency_total_ht) ? ((float) $this->multicurrency_total_ht) : 0.00) . ',';
546
        $sql .= " multicurrency_total_tva = " . (!empty($this->multicurrency_total_tva) ? ((float) $this->multicurrency_total_tva) : 0.00) . ',';
547
        $sql .= " multicurrency_total_ttc = " . (!empty($this->multicurrency_total_ttc) ? ((float) $this->multicurrency_total_ttc) : 0.00) . ',';
548
        $sql .= " usenewprice = " . (!empty($this->usenewprice) ? ((int) $this->usenewprice) : 0) . ',';
549
        $sql .= " frequency = " . (!empty($this->frequency) ? ((int) $this->frequency) : 0) . ',';
550
        $sql .= " unit_frequency = '" . (!empty($this->unit_frequency) ? $this->db->escape($this->unit_frequency) : '') . "',";
551
        $sql .= " date_when = " . (!empty($this->date_when) ? "'" . $this->db->idate($this->date_when) . "'" : 'NULL') . ',';
552
        $sql .= " date_last_gen = " . (!empty($this->date_last_gen) ? "'" . $this->db->idate($this->date_last_gen) . "'" : 'NULL') . ',';
553
        $sql .= " nb_gen_done = " . (!empty($this->nb_gen_done) ? ((int) $this->nb_gen_done) : 0) . ',';
554
        $sql .= " nb_gen_max = " . (!empty($this->nb_gen_max) ? ((int) $this->nb_gen_max) : 0) . ',';
555
        $sql .= " auto_validate = " . (!empty($this->auto_validate) ? ((int) $this->auto_validate) : 0);
556
        $sql .= " WHERE rowid = " . (int) $this->id;
557
558
        $this->db->begin();
559
560
        dol_syslog(get_class($this) . "::update", LOG_DEBUG);
561
        $resql = $this->db->query($sql);
562
        if ($resql) {
563
            if (!$error) {
564
                $result = $this->insertExtraFields();
565
                if ($result < 0) {
566
                    $error++;
567
                }
568
            }
569
570
            if (!$error && !$notrigger) {
571
                // Call trigger
572
                $result = $this->call_trigger('SUPPLIERBILLREC_MODIFY', $user);
573
                if ($result < 0) {
574
                    $this->db->rollback();
575
                    return -2;
576
                }
577
                // End call triggers
578
            }
579
            $this->db->commit();
580
            return 1;
581
        } else {
582
            $this->error = $this->db->lasterror();
583
            $this->db->rollback();
584
            return -2;
585
        }
586
    }
587
588
    /**
589
     *  Load object and lines
590
     *
591
     *  @param      int     $rowid          Id of object to load
592
     *  @param      string  $ref            Reference of recurring invoice
593
     *  @param      string  $ref_ext        External reference of invoice
594
     *  @return     int                     >0 if OK, <0 if KO, 0 if not found
595
     */
596
    public function fetch($rowid, $ref = '', $ref_ext = '')
597
    {
598
        $sql = 'SELECT f.rowid, f.titre as title, f.subtype, f.ref_supplier, f.entity, f.fk_soc';
599
        $sql .= ', f.datec, f.tms, f.suspended';
600
        $sql .= ', f.libelle as label';
601
        $sql .= ', f.vat_src_code, f.localtax1, f.localtax2';
602
        $sql .= ', f.total_tva, f.total_ht, f.total_ttc';
603
        $sql .= ', f.fk_user_author, f.fk_user_modif';
604
        $sql .= ', f.fk_projet as fk_project, f.fk_account';
605
        $sql .= ', f.fk_mode_reglement, p.code as mode_reglement_code, p.libelle as mode_reglement_libelle';
606
        $sql .= ', f.fk_cond_reglement, c.code as cond_reglement_code, c.libelle as cond_reglement_libelle, c.libelle_facture as cond_reglement_libelle_doc';
607
        $sql .= ', f.date_lim_reglement';
608
        $sql .= ', f.note_private, f.note_public, f.modelpdf as model_pdf';
609
        $sql .= ', f.fk_multicurrency, f.multicurrency_code, f.multicurrency_tx, f.multicurrency_total_ht, f.multicurrency_total_tva, f.multicurrency_total_ttc';
610
        $sql .= ', f.usenewprice, f.frequency, f.unit_frequency, f.date_when, f.date_last_gen, f.nb_gen_done, f.nb_gen_max, f.auto_validate';
611
        $sql .= ', f.generate_pdf';
612
        $sql .= ' FROM ' . MAIN_DB_PREFIX . 'facture_fourn_rec as f';
613
        $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'c_payment_term as c ON f.fk_cond_reglement = c.rowid';
614
        $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'c_paiement as p ON f.fk_mode_reglement = p.id';
615
        $sql .= ' WHERE f.entity IN (' . getEntity('invoice') . ')';
616
        if ($rowid) {
617
            $sql .= ' AND f.rowid=' . (int) $rowid;
618
        } elseif ($ref) {
619
            $sql .= " AND f.titre='" . $this->db->escape($ref) . "'";
620
        } else {
621
            $sql .= ' AND f.rowid = 0';
622
        }
623
624
        $result = $this->db->query($sql);
625
        if ($result) {
626
            if ($this->db->num_rows($result)) {
627
                $obj = $this->db->fetch_object($result);
628
629
                $keyforref = $this->table_ref_field;
630
631
                $this->id                       = $obj->rowid;
632
                $this->titre                    = $obj->title;
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Code\Fourn\Clas...eFournisseurRec::$titre has been deprecated: Use $title ( Ignorable by Annotation )

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

632
                /** @scrutinizer ignore-deprecated */ $this->titre                    = $obj->title;

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...
633
                $this->title                    = $obj->title;
634
                $this->subtype                        = $obj->subtype;
635
                $this->ref                      = $obj->title;
636
                $this->ref_supplier             = $obj->ref_supplier;
637
                $this->entity                   = $obj->entity;
638
                $this->socid                    = $obj->fk_soc;
639
                $this->date_creation            = $obj->datec;
640
                $this->date_modification        = $obj->tms;
641
                $this->suspended                = $obj->suspended;
642
                $this->libelle                  = $obj->label;
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Code\Fourn\Clas...ournisseurRec::$libelle has been deprecated: Use $label ( Ignorable by Annotation )

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

642
                /** @scrutinizer ignore-deprecated */ $this->libelle                  = $obj->label;

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...
643
                $this->label                    = $obj->label;
644
                $this->vat_src_code             = $obj->vat_src_code;
645
                $this->total_localtax1          = $obj->localtax1;
646
                $this->total_localtax2          = $obj->localtax2;
647
                $this->total_ht                 = $obj->total_ht;
648
                $this->total_tva                = $obj->total_tva;
649
                $this->total_ttc                = $obj->total_ttc;
650
                $this->user_author              = $obj->fk_user_author;
651
                $this->user_modif               = $obj->fk_user_modif;
652
                $this->fk_project               = $obj->fk_project;
653
                $this->fk_account               = $obj->fk_account;
654
                $this->mode_reglement_id        = $obj->fk_mode_reglement;
655
                $this->mode_reglement_code      = $obj->mode_reglement_code;
656
                $this->mode_reglement           = $obj->mode_reglement_libelle;
657
                $this->cond_reglement_id        = $obj->fk_cond_reglement;
658
                $this->cond_reglement_code      = $obj->cond_reglement_code;
659
                $this->cond_reglement           = $obj->cond_reglement_libelle;
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$cond_reglement has been deprecated: Use $cond_reglement_id instead - Kept for compatibility ( Ignorable by Annotation )

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

659
                /** @scrutinizer ignore-deprecated */ $this->cond_reglement           = $obj->cond_reglement_libelle;

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

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

Loading history...
Bug Best Practice introduced by
The property $cond_reglement is declared private in Dolibarr\Core\Base\CommonObject. Since you implement __set, consider adding a @property or @property-write.
Loading history...
660
                $this->cond_reglement_doc       = $obj->cond_reglement_libelle_doc;
661
                $this->date_lim_reglement       = $this->db->jdate($obj->date_lim_reglement);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->db->jdate($obj->date_lim_reglement) can also be of type string. However, the property $date_lim_reglement 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...
662
                $this->note_private             = $obj->note_private;
663
                $this->note_public              = $obj->note_public;
664
                $this->model_pdf                = $obj->model_pdf;
665
666
                // Multicurrency
667
                $this->fk_multicurrency         = $obj->fk_multicurrency;
668
                $this->multicurrency_code       = $obj->multicurrency_code;
669
                $this->multicurrency_tx         = $obj->multicurrency_tx;
670
                $this->multicurrency_total_ht   = $obj->multicurrency_total_ht;
671
                $this->multicurrency_total_tva  = $obj->multicurrency_total_tva;
672
                $this->multicurrency_total_ttc  = $obj->multicurrency_total_ttc;
673
674
                $this->usenewprice              = $obj->usenewprice;
675
                $this->frequency                = $obj->frequency;
676
                $this->unit_frequency           = $obj->unit_frequency;
677
                $this->date_when                = $this->db->jdate($obj->date_when);
678
                $this->date_last_gen            = $this->db->jdate($obj->date_last_gen);
679
                $this->nb_gen_done              = $obj->nb_gen_done;
680
                $this->nb_gen_max               = $obj->nb_gen_max;
681
                $this->auto_validate            = $obj->auto_validate;
682
                $this->generate_pdf             = $obj->generate_pdf;
683
684
                // Retrieve all extrafield
685
                // fetch optionals attributes and labels
686
                $this->fetch_optionals();
687
688
                /*
689
                 * Lines
690
                 */
691
                $result = $this->fetch_lines();
692
                if ($result < 0) {
693
                    $this->error = $this->db->lasterror();
694
                    return -3;
695
                }
696
                return 1;
697
            } else {
698
                $this->error = 'Bill with id ' . $rowid . ' or ref ' . $ref . ' not found';
699
                dol_syslog('Facture::Fetch Error ' . $this->error, LOG_ERR);
700
                return -2;
701
            }
702
        } else {
703
            $this->error = $this->db->error();
704
            return -1;
705
        }
706
    }
707
708
709
    /**
710
     *  Create an array of invoice lines
711
     *
712
     *  @return int     >0 if OK, <0 if KO
713
     */
714
    public function getLinesArray()
715
    {
716
        return $this->fetch_lines();
717
    }
718
719
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
720
    /**
721
     *  Get lines of template invoices into this->lines
722
     *
723
     *  @return     int         1 if OK, < 0 if KO
724
     */
725
    public function fetch_lines()
726
    {
727
		// phpcs:enable
728
        $this->lines = array();
729
730
        // Retrieve all extrafield for line
731
        // fetch optionals attributes and labels
732
        /*if (!is_object($extrafields)) {
733
            require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
734
            $extrafields = new ExtraFields($this->db);
735
        }
736
        $extrafields->fetch_name_optionals_label($this->table_element_line, true);
737
        */
738
739
        $sql = 'SELECT l.rowid,';
740
        $sql .= ' l.fk_facture_fourn, l.fk_parent_line, l.fk_product, l.ref, l.label, l.description as line_desc,';
741
        $sql .= ' l.pu_ht, l.pu_ttc, l.qty, l.remise_percent, l.fk_remise_except, l.vat_src_code, l.tva_tx,';
742
        $sql .= ' l.localtax1_tx, l.localtax2_tx, l.localtax1_type, l.localtax2_type,';
743
        $sql .= ' l.total_ht, l.total_tva, l.total_ttc, total_localtax1, total_localtax2,';
744
        $sql .= ' l.product_type, l.date_start, l.date_end,';
745
        $sql .= ' l.info_bits, l.special_code, l.rang,';
746
        $sql .= ' l.fk_unit, l.import_key, l.fk_user_author, l.fk_user_modif,';
747
        $sql .= ' l.fk_multicurrency, l.multicurrency_code, l.multicurrency_subprice, l.multicurrency_total_ht, l.multicurrency_total_tva, l.multicurrency_total_ttc,';
748
        $sql .= ' p.ref as product_ref, p.fk_product_type as fk_product_type, p.label as product_label, p.description as product_desc';
749
        $sql .= ' FROM ' . MAIN_DB_PREFIX . 'facture_fourn_det_rec as l';
750
        $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'product as p ON l.fk_product = p.rowid';
751
        $sql .= ' WHERE l.fk_facture_fourn = ' . (int) $this->id;
752
        $sql .= ' ORDER BY l.rang';
753
754
        dol_syslog('FactureFournisseurRec::fetch_lines', LOG_DEBUG);
755
756
        $result = $this->db->query($sql);
757
        if ($result) {
758
            $num = $this->db->num_rows($result);
759
            $i = 0;
760
            while ($i < $num) {
761
                $objp = $this->db->fetch_object($result);
762
763
                $line = new FactureFournisseurLigneRec($this->db);
764
765
                $line->id                       = $objp->rowid;
766
                $line->fk_facture_fourn         = $objp->fk_facture_fourn;
767
                $line->fk_parent                = $objp->fk_parent_line;
768
                $line->fk_product               = $objp->fk_product;
769
                $line->ref_supplier             = $objp->ref;
770
                $line->label                    = $objp->label;
771
                $line->description              = $objp->line_desc;
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Code\Fourn\Clas...rLigneRec::$description has been deprecated: Use desc ( Ignorable by Annotation )

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

771
                /** @scrutinizer ignore-deprecated */ $line->description              = $objp->line_desc;

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...
772
                $line->desc                     = $objp->line_desc;
773
                $line->pu_ht                    = $objp->pu_ht;
774
                $line->pu_ttc                   = $objp->pu_ttc;
775
                $line->qty                      = $objp->qty;
776
                $line->remise_percent           = $objp->remise_percent;
777
                $line->fk_remise_except         = $objp->fk_remise_except;
778
                $line->vat_src_code             = $objp->vat_src_code;
779
                $line->tva_tx                   = $objp->tva_tx;
780
                $line->localtax1_tx             = $objp->localtax1_tx;
781
                $line->localtax1_type           = $objp->localtax1_type;
782
                $line->localtax2_tx             = $objp->localtax2_tx;
783
                $line->localtax2_type           = $objp->localtax2_type;
784
                $line->total_ht                 = $objp->total_ht;
785
                $line->total_tva                = $objp->total_tva;
786
                $line->total_localtax1          = $objp->total_localtax1;
787
                $line->total_localtax2          = $objp->total_localtax2;
788
                $line->total_ttc                = $objp->total_ttc;
789
                $line->product_type             = $objp->product_type;
790
                $line->date_start               = $objp->date_start;
791
                $line->date_end                 = $objp->date_end;
792
                $line->info_bits                = $objp->info_bits  ;
793
                $line->special_code             = $objp->special_code;
794
                $line->rang                     = $objp->rang;
795
                $line->fk_unit                  = $objp->fk_unit;
796
                $line->import_key               = $objp->import_key;
797
                $line->fk_user_author           = $objp->fk_user_author;
798
                $line->fk_user_modif            = $objp->fk_user_modif;
799
                $line->fk_multicurrency         = $objp->fk_multicurrency;
800
                $line->multicurrency_code       = $objp->multicurrency_code;
801
                $line->multicurrency_subprice   = $objp->multicurrency_subprice;
802
                $line->multicurrency_total_ht   = $objp->multicurrency_total_ht;
803
                $line->multicurrency_total_tva  = $objp->multicurrency_total_tva;
804
                $line->multicurrency_total_ttc  = $objp->multicurrency_total_ttc;
805
806
                $line->fetch_optionals();
807
808
                $this->lines[$i] = $line;
809
810
                $i++;
811
            }
812
813
            $this->db->free($result);
814
            return 1;
815
        } else {
816
            $this->error = $this->db->lasterror();
817
            return -3;
818
        }
819
    }
820
821
822
    /**
823
     *  Delete template invoice
824
     *
825
     *  @param      User    $user           User that delete.
826
     *  @param      int     $notrigger      1=Does not execute triggers, 0= execute triggers
827
     *  @param      int     $idwarehouse    Id warehouse to use for stock change.
828
     *  @return     int                     Return integer <0 if KO, >0 if OK
829
     */
830
    public function delete(User $user, $notrigger = 0, $idwarehouse = -1)
831
    {
832
        $rowid = $this->id;
833
834
        dol_syslog(get_class($this) . "::delete rowid=" . ((int) $rowid), LOG_DEBUG);
835
836
        $error = 0;
837
        $this->db->begin();
838
839
        $main = MAIN_DB_PREFIX . 'facture_fourn_det_rec';
840
        $ef = $main . "_extrafields";
841
842
        $sqlef = "DELETE FROM " . $ef . " WHERE fk_object IN (SELECT rowid FROM " . $main . " WHERE fk_facture_fourn = " . (int) $rowid . ")";
843
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "facture_fourn_det_rec WHERE fk_facture_fourn = " . (int) $rowid;
844
845
        if ($this->db->query($sqlef) && $this->db->query($sql)) {
846
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "facture_fourn_rec WHERE rowid = " . (int) $rowid;
847
            dol_syslog($sql);
848
            if ($this->db->query($sql)) {
849
                // Delete linked object
850
                $res = $this->deleteObjectLinked();
851
                if ($res < 0) {
852
                    $error = -3;
853
                }
854
                // Delete extrafields
855
                $res = $this->deleteExtraFields();
856
                if ($res < 0) {
857
                    $error = -4;
858
                }
859
            } else {
860
                $this->error = $this->db->lasterror();
861
                $error = -1;
862
            }
863
        } else {
864
            $this->error = $this->db->lasterror();
865
            $error = -2;
866
        }
867
        if (!$error && !$notrigger) {
868
            // Call trigger
869
            $result = $this->call_trigger('SUPPLIERBILLREC_DELETE', $user);
870
            if ($result < 0) {
871
                $error++;
872
            }
873
            // End call triggers
874
        }
875
        if (! $error) {
876
            $this->db->commit();
877
            return 1;
878
        } else {
879
            $this->db->rollback();
880
            return $error;
881
        }
882
    }
883
884
    /**
885
     * Add a line to recursive supplier invoice
886
     *
887
     * @param int       $fk_product     Product/Service ID predefined
888
     * @param string    $ref            Ref
889
     * @param string    $label          Label
890
     * @param string    $desc           Description de la ligne
891
     * @param double    $pu_ht          Unit price
892
     * @param double    $pu_ttc         Unit price with tax
893
     * @param double    $qty            Quantity
894
     * @param int       $remise_percent Percentage discount of the line
895
     * @param double    $txtva          Taux de tva force, sinon -1
896
     * @param int       $txlocaltax1    Local tax 1 rate (deprecated)
897
     * @param int       $txlocaltax2    Local tax 2 rate (deprecated)
898
     * @param string    $price_base_type HT or TTC
899
     * @param int       $type           Type of line (0=product, 1=service)
900
     * @param int       $date_start     Date start
901
     * @param int       $date_end       Date end
902
     * @param int       $info_bits      VAT npr or not ?
903
     * @param int       $special_code   Special code
904
     * @param int       $rang           Position of line
905
     * @param string    $fk_unit        Unit
906
     * @param int       $pu_ht_devise   Unit price in currency
907
     * @return int                      Return integer <0 if KO, Id of line if OK
908
     * @throws Exception
909
     */
910
    public function addline($fk_product, $ref, $label, $desc, $pu_ht, $pu_ttc, $qty, $remise_percent, $txtva, $txlocaltax1 = 0, $txlocaltax2 = 0, $price_base_type = 'HT', $type = 0, $date_start = 0, $date_end = 0, $info_bits = 0, $special_code = 0, $rang = -1, $fk_unit = null, $pu_ht_devise = 0)
911
    {
912
        global $mysoc, $user;
913
914
        include_once DOL_DOCUMENT_ROOT . '/core/lib/price.lib.php';
915
916
        $facid = $this->id; //Supplier invoice template ID linked to
917
918
        dol_syslog(get_class($this) . "::addline facid=$facid,desc=$desc,pu_ht=$pu_ht,qty=$qty,txtva=$txtva,txlocaltax1=$txlocaltax1,txlocaltax2=$txlocaltax2,fk_product=$fk_product,remise_percent=$remise_percent,info_bits=$info_bits,price_base_type=$price_base_type,pu_ttc=$pu_ttc,type=$type,fk_unit=$fk_unit,pu_ht_devise=$pu_ht_devise,date_start_fill=$date_start,date_end_fill=$date_end", LOG_DEBUG);
919
920
        // Check if object of the line is product or service
921
        if ($type < 0) {
922
            return -1;
923
        }
924
925
        if ($this->suspended == self::STATUS_NOTSUSPENDED) {
926
            $localtaxes_type = getLocalTaxesFromRate($txtva, 0, $this->thirdparty, $mysoc);
927
928
            // Clean vat code
929
            $reg = array();
930
            $vat_src_code = '';
931
            if (preg_match('/\((.*)\)/', (string) $txtva, $reg)) {
932
                $vat_src_code = $reg[1];
933
                $txtva = preg_replace('/\s*\(.*\)/', '', (string) $txtva); // Remove code into vatrate.
934
            }
935
936
            // Clean parameters
937
            $fk_product = empty($fk_product) ? 0 : $fk_product;
938
            $label = empty($label) ? '' : $label;
939
            $remise_percent = empty($remise_percent) ? 0 : price2num($remise_percent);
940
            $qty = price2num($qty);
941
            $pu_ht = price2num($pu_ht);
942
            $pu_ttc = price2num($pu_ttc);
943
            if (!preg_match('/\((.*)\)/', $txtva)) {
944
                $txtva = price2num($txtva); // $txtva can have format '5.0(XXX)' or '5'
945
            }
946
            $txlocaltax1 = price2num($txlocaltax1);
947
            $txlocaltax2 = price2num($txlocaltax2);
948
            $txtva = !empty($txtva) ? $txtva : 0;
949
            $txlocaltax1 = !empty($txlocaltax1) ? $txlocaltax1 : 0;
950
            $txlocaltax2 = !empty($txlocaltax2) ? $txlocaltax2 : 0;
951
            $info_bits = !empty($info_bits) ? $info_bits : 0;
952
            $info_bits = !empty($info_bits) ? $info_bits : 0;
953
            $pu = $price_base_type == 'HT' ? $pu_ht : $pu_ttc;
954
955
            // Calcul du total TTC et de la TVA pour la ligne a partir de qty, pu, remise_percent et txtva
956
            // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
957
            // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
958
959
            $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx, $pu_ht_devise);
960
            $total_ht  = $tabprice[0];
961
            $total_tva = $tabprice[1];
962
            $total_ttc = $tabprice[2];
963
            $total_localtax1 = $tabprice[9];
964
            $total_localtax2 = $tabprice[10];
965
            $pu_ht = $tabprice[3];
966
967
            // MultiCurrency
968
            $multicurrency_total_ht  = $tabprice[16];
969
            $multicurrency_total_tva = $tabprice[17];
970
            $multicurrency_total_ttc = $tabprice[18];
971
            $pu_ht_devise = $tabprice[19];
972
973
            $this->db->begin();
974
            $product_type = $type;
975
            if ($fk_product) {
976
                $product = new Product($this->db);
977
                $result = $product->fetch($fk_product);
978
                if ($result < 0) {
979
                    return -1;
980
                }
981
                $product_type = $product->type;
982
                if (empty($label)) {
983
                    $label = $product->label;
984
                }
985
            }
986
987
            $sql = 'INSERT INTO ' . MAIN_DB_PREFIX . 'facture_fourn_det_rec (';
988
            $sql .= 'fk_facture_fourn';
989
            $sql .= ', fk_product';
990
            $sql .= ', ref';
991
            $sql .= ', label';
992
            $sql .= ', description';
993
            $sql .= ', pu_ht';
994
            $sql .= ', pu_ttc';
995
            $sql .= ', qty';
996
            $sql .= ', remise_percent';
997
            $sql .= ', fk_remise_except';
998
            $sql .= ', vat_src_code';
999
            $sql .= ', tva_tx';
1000
            $sql .= ', localtax1_tx';
1001
            $sql .= ', localtax1_type';
1002
            $sql .= ', localtax2_tx';
1003
            $sql .= ', localtax2_type';
1004
            $sql .= ', total_ht';
1005
            $sql .= ', total_tva';
1006
            $sql .= ', total_localtax1';
1007
            $sql .= ', total_localtax2';
1008
            $sql .= ', total_ttc';
1009
            $sql .= ', product_type';
1010
            $sql .= ', date_start';
1011
            $sql .= ', date_end';
1012
            $sql .= ', info_bits';
1013
            $sql .= ', special_code';
1014
            $sql .= ', rang';
1015
            $sql .= ', fk_unit';
1016
            $sql .= ', fk_user_author';
1017
            $sql .= ', fk_multicurrency, multicurrency_code, multicurrency_subprice, multicurrency_total_ht, multicurrency_total_tva, multicurrency_total_ttc';
1018
            $sql .= ') VALUES (';
1019
            $sql .= ' ' . (int) $facid;   // source supplier invoice id
1020
            $sql .= ', ' . (!empty($fk_product) ? "'" . $this->db->escape($fk_product) . "'" : 'null');
1021
            $sql .= ', ' . (!empty($ref) ? "'" . $this->db->escape($ref) . "'" : 'null');
1022
            $sql .= ', ' . (!empty($label) ? "'" . $this->db->escape($label) . "'" : 'null');
1023
            $sql .= ", '" . $this->db->escape($desc) . "'";
1024
            $sql .= ', ' . price2num($pu_ht);
1025
            $sql .= ', ' . price2num($pu_ttc);
1026
            $sql .= ', ' . price2num($qty);
1027
            $sql .= ', ' . price2num($remise_percent);
1028
            $sql .= ', null';
1029
            $sql .= ", '" . $this->db->escape($vat_src_code) . "'";
1030
            $sql .= ', ' . price2num($txtva);
1031
            $sql .= ', ' . price2num($txlocaltax1);
1032
            $sql .= ", '" . $this->db->escape(isset($localtaxes_type[0]) ? $localtaxes_type[0] : '') . "'";
1033
            $sql .= ', ' . price2num($txlocaltax2);
1034
            $sql .= ", '" . $this->db->escape(isset($localtaxes_type[2]) ? $localtaxes_type[2] : '') . "'";
1035
            $sql .= ', ' . price2num($total_ht);
1036
            $sql .= ', ' . price2num($total_tva);
1037
            $sql .= ', ' . price2num($total_localtax1);
1038
            $sql .= ', ' . price2num($total_localtax2);
1039
            $sql .= ', ' . price2num($total_ttc);
1040
            $sql .= ', ' . (int) $product_type;
1041
            $sql .= ', ' . ($date_start > 0 ? (int) $date_start : 'NULL');
1042
            $sql .= ', ' . ($date_end > 0 ? (int) $date_end : 'NULL');
1043
            $sql .= ', ' . (int) $info_bits;
1044
            $sql .= ', ' . (int) $special_code;
1045
            $sql .= ', ' . (int) $rang;
1046
            $sql .= ', ' . ($fk_unit ? (int) $fk_unit : 'NULL');
1047
            $sql .= ', ' . (int) $user->id;
1048
            $sql .= ', ' . (int) $this->fk_multicurrency;
1049
            $sql .= ", '" . $this->db->escape($this->multicurrency_code) . "'";
1050
            $sql .= ', ' . price2num($pu_ht_devise, 'CU');
1051
            $sql .= ', ' . price2num($multicurrency_total_ht, 'CT');
1052
            $sql .= ', ' . price2num($multicurrency_total_tva, 'CT');
1053
            $sql .= ', ' . price2num($multicurrency_total_ttc, 'CT');
1054
            $sql .= ')';
1055
1056
            dol_syslog(get_class($this) . '::addline', LOG_DEBUG);
1057
            if ($this->db->query($sql)) {
1058
                $lineId = $this->db->last_insert_id(MAIN_DB_PREFIX . 'facture_fourn_det_rec');
1059
                $this->update_price();
1060
                $this->id = $facid;
1061
                $this->db->commit();
1062
                return $lineId;
1063
            } else {
1064
                $this->db->rollback();
1065
                $this->error = $this->db->lasterror();
1066
1067
                return -1;
1068
            }
1069
        } else {
1070
            $this->error = 'Recurring Invoice is suspended. adding lines not allowed.';
1071
1072
            return -1;
1073
        }
1074
    }
1075
1076
    /**
1077
     * Update a line to supplier invoice template
1078
     *
1079
     * @param int       $rowid              ID
1080
     * @param int       $fk_product         Product/Service ID predefined
1081
     * @param string    $ref                Ref
1082
     * @param string    $label              Label of the line
1083
     * @param string    $desc               Description de la ligne
1084
     * @param double    $pu_ht              Unit price HT (> 0 even for credit note)
1085
     * @param double    $qty                Quantity
1086
     * @param int       $remise_percent     Percentage discount of the line
1087
     * @param double    $txtva              VAT rate forced with format '5.0 (XXX)', or -1
1088
     * @param int       $txlocaltax1        Local tax 1 rate (deprecated)
1089
     * @param int       $txlocaltax2        Local tax 2 rate (deprecated)
1090
     * @param string    $price_base_type    HT or TTC
1091
     * @param int       $type               Type of line (0=product, 1=service)
1092
     * @param int       $date_start         Date start
1093
     * @param int       $date_end           Date end
1094
     * @param int       $info_bits          Bits of type of lines
1095
     * @param int       $special_code       Special code
1096
     * @param int       $rang               Position of line
1097
     * @param string    $fk_unit            Unit
1098
     * @param double    $pu_ht_devise       Unit price in currency
1099
     * @param double    $pu_ttc             Unit price TTC (> 0 even for credit note)
1100
     * @return int                          Return integer <0 if KO, Id of line if OK
1101
     * @throws Exception
1102
     */
1103
    public function updateline($rowid, $fk_product, $ref, $label, $desc, $pu_ht, $qty, $remise_percent, $txtva, $txlocaltax1 = 0, $txlocaltax2 = 0, $price_base_type = 'HT', $type = 0, $date_start = 0, $date_end = 0, $info_bits = 0, $special_code = 0, $rang = -1, $fk_unit = null, $pu_ht_devise = 0, $pu_ttc = 0)
1104
    {
1105
        global $mysoc, $user;
1106
1107
        $facid = $this->id;
1108
1109
        dol_syslog(get_class($this) . '::updateline facid=' . $facid . " rowid=$rowid, desc=$desc, pu_ht=$pu_ht, qty=$qty, txtva=$txtva, txlocaltax1=$txlocaltax1, txlocaltax2=$txlocaltax2, fk_product=$fk_product, remise_percent=$remise_percent, info_bits=$info_bits, price_base_type=$price_base_type, pu_ttc=$pu_ttc, type=$type, fk_unit=$fk_unit, pu_ht_devise=$pu_ht_devise", LOG_DEBUG);
1110
        include_once DOL_DOCUMENT_ROOT . '/core/lib/price.lib.php';
1111
1112
        // Check parameters
1113
        if ($type < 0) {
1114
            return -1;
1115
        }
1116
1117
        if ($this->status == self::STATUS_SUSPENDED) {
1118
            // Clean parameters
1119
            $fk_product = empty($fk_product) ? 0 : $fk_product;
1120
            $label = empty($label) ? '' : $label;
1121
            $remise_percent = empty($remise_percent) ? 0 : price2num($remise_percent);
1122
            $qty = price2num($qty);
1123
            $info_bits = empty($info_bits) ? 0 : $info_bits;
1124
            $pu_ht          = price2num($pu_ht);
1125
            $pu_ttc         = price2num($pu_ttc);
1126
            $pu_ht_devise = price2num($pu_ht_devise);
1127
1128
            if (!preg_match('/\((.*)\)/', (string) $txtva)) {
1129
                $txtva = price2num($txtva); // $txtva can have format '5.0(XXX)' or '5'
1130
            }
1131
1132
            $txlocaltax1 = empty($txlocaltax1) ? 0 : price2num($txlocaltax1);
1133
            $txlocaltax2 = empty($txlocaltax2) ? 0 : price2num($txlocaltax2);
1134
            $this->multicurrency_total_ht = empty($this->multicurrency_total_ht) ? 0 : $this->multicurrency_total_ht;
1135
            $this->multicurrency_total_tva = empty($this->multicurrency_total_tva) ? 0 : $this->multicurrency_total_tva;
1136
            $this->multicurrency_total_ttc = empty($this->multicurrency_total_ttc) ? 0 : $this->multicurrency_total_ttc;
1137
1138
            $pu = $price_base_type == 'HT' ? $pu_ht : $pu_ttc;
1139
1140
1141
            // Calculate total with, without tax and tax from qty, pu, remise_percent and txtva
1142
            // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
1143
            // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
1144
1145
            $localtaxes_type = getLocalTaxesFromRate($txtva, 0, $this->thirdparty, $mysoc);
1146
1147
            // Clean vat code
1148
            $vat_src_code = '';
1149
            $reg = array();
1150
            if (preg_match('/\((.*)\)/', $txtva, $reg)) {
1151
                $vat_src_code = $reg[1];
1152
                $txtva = preg_replace('/\s*\(.*\)/', '', $txtva); // Remove code into vatrate.
1153
            }
1154
1155
            $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx, $pu_ht_devise);
1156
1157
            $total_ht  = $tabprice[0];
1158
            $total_tva = $tabprice[1];
1159
            $total_ttc = $tabprice[2];
1160
            $total_localtax1 = $tabprice[9];
1161
            $total_localtax2 = $tabprice[10];
1162
            $pu_ht  = $tabprice[3];
1163
            $pu_tva = $tabprice[4];
1164
            $pu_ttc = $tabprice[5];
1165
1166
            // MultiCurrency
1167
            $multicurrency_total_ht  = $tabprice[16];
1168
            $multicurrency_total_tva = $tabprice[17];
1169
            $multicurrency_total_ttc = $tabprice[18];
1170
            $pu_ht_devise = $tabprice[19];
1171
1172
            $product_type = $type;
1173
            if ($fk_product) {
1174
                $product = new Product($this->db);
1175
                $result = $product->fetch($fk_product);
1176
                $product_type = $product->type;
1177
            }
1178
1179
            $sql = 'UPDATE ' . MAIN_DB_PREFIX . 'facture_fourn_det_rec SET';
1180
            $sql .= ' fk_facture_fourn = ' . ((int) $facid);
1181
            $sql .= ', fk_product = ' . ($fk_product > 0 ? ((int) $fk_product) : 'null');
1182
            $sql .= ", ref = '" . $this->db->escape($ref) . "'";
1183
            $sql .= ", label = '" . $this->db->escape($label) . "'";
1184
            $sql .= ", description = '" . $this->db->escape($desc) . "'";
1185
            $sql .= ', pu_ht = ' . price2num($pu_ht);
1186
            $sql .= ', qty = ' . price2num($qty);
1187
            $sql .= ", remise_percent = '" . price2num($remise_percent) . "'";
1188
            $sql .= ", vat_src_code = '" . $this->db->escape($vat_src_code) . "'";
1189
            $sql .= ', tva_tx = ' . price2num($txtva);
1190
            $sql .= ', localtax1_tx = ' . (float) $txlocaltax1;
1191
            $sql .= ", localtax1_type = '" . $this->db->escape($localtaxes_type[0]) . "'";
1192
            $sql .= ', localtax2_tx = ' . (float) $txlocaltax2;
1193
            $sql .= ", localtax2_type = '" . $this->db->escape($localtaxes_type[2]) . "'";
1194
            $sql .= ", total_ht = '" . price2num($total_ht) . "'";
1195
            $sql .= ", total_tva = '" . price2num($total_tva) . "'";
1196
            $sql .= ", total_localtax1 = '" . price2num($total_localtax1) . "'";
1197
            $sql .= ", total_localtax2 = '" . price2num($total_localtax2) . "'";
1198
            $sql .= ", total_ttc = '" . price2num($total_ttc) . "'";
1199
            $sql .= ', product_type = ' . (int) $product_type;
1200
            $sql .= ', date_start = ' . (empty($date_start) ? 'NULL' : (int) $date_start);
1201
            $sql .= ', date_end = ' . (empty($date_end) ? 'NULL' : (int) $date_end);
1202
            $sql .= ', info_bits = ' . (int) $info_bits;
1203
            $sql .= ', special_code = ' . (int) $special_code;
1204
            $sql .= ', rang = ' . (int) $rang;
1205
            $sql .= ', fk_unit = ' . ($fk_unit ? "'" . $this->db->escape($fk_unit) . "'" : 'null');
1206
            $sql .= ', fk_user_modif = ' . (int) $user;
1207
            $sql .= ', multicurrency_subprice = ' . price2num($pu_ht_devise);
1208
            $sql .= ', multicurrency_total_ht = ' . price2num($multicurrency_total_ht);
1209
            $sql .= ', multicurrency_total_tva = ' . price2num($multicurrency_total_tva);
1210
            $sql .= ', multicurrency_total_ttc = ' . price2num($multicurrency_total_ttc);
1211
            $sql .= ' WHERE rowid = ' . (int) $rowid;
1212
1213
            dol_syslog(get_class($this) . '::updateline', LOG_DEBUG);
1214
            if ($this->db->query($sql)) {
1215
                $this->id = $facid;
1216
                $this->update_price();
1217
                return 1;
1218
            } else {
1219
                $this->error = $this->db->lasterror();
1220
                return -1;
1221
            }
1222
        }
1223
        return 0;
1224
    }
1225
1226
1227
    /**
1228
     * Return next reference of invoice not already used (or last reference)
1229
     *
1230
     * @param    Societe    $soc        Thirdparty object
1231
     * @param    string     $mode       'next' for next value or 'last' for last value
1232
     * @return   string                 free ref or last ref
1233
     */
1234
    public function getNextNumRef($soc, $mode = 'next')
1235
    {
1236
        // Not used for recurring invoices
1237
        return '';
1238
    }
1239
1240
    /**
1241
     * Return the next date of
1242
     *
1243
     * @return  int|false   false if KO, timestamp if OK
1244
     */
1245
    public function getNextDate()
1246
    {
1247
        if (empty($this->date_when)) {
1248
            return false;
1249
        }
1250
        return dol_time_plus_duree($this->date_when, $this->frequency, $this->unit_frequency);
1251
    }
1252
1253
    /**
1254
     * Return if maximum number of generation is reached
1255
     *
1256
     * @return  boolean         False by default, True if maximum number of generation is reached
1257
     */
1258
    public function isMaxNbGenReached()
1259
    {
1260
        $ret = false;
1261
        if ($this->nb_gen_max > 0 && ($this->nb_gen_done >= $this->nb_gen_max)) {
1262
            $ret = true;
1263
        }
1264
        return $ret;
1265
    }
1266
1267
    /**
1268
     * Format string to output with by striking the string if max number of generation was reached
1269
     *
1270
     * @param   string      $ret    Default value to output
1271
     * @return  string              False by default, True if maximum number of generation is reached
1272
     */
1273
    public function strikeIfMaxNbGenReached($ret)
1274
    {
1275
        // Special case to strike the date
1276
        return ($this->isMaxNbGenReached() ? '<strike>' : '') . $ret . ($this->isMaxNbGenReached() ? '</strike>' : '');
1277
    }
1278
1279
    /**
1280
     *  Create all recurrents supplier invoices (for all entities if multicompany is used).
1281
     *  A result may also be provided into this->output.
1282
     *
1283
     *  WARNING: This method changes temporarily the context $conf->entity to be in correct context for each recurring invoice found.
1284
     *
1285
     *  @param  int     $restrictioninvoiceid       0=All qualified template invoices found. > 0 = restrict action on invoice ID
1286
     *  @param  int     $forcevalidation        1=Force validation of invoice whatever is template auto_validate flag.
1287
     *  @return int                             0 if OK, < 0 if KO (this function is used also by cron so only 0 is OK)
1288
     */
1289
    public function createRecurringInvoices($restrictioninvoiceid = 0, $forcevalidation = 0)
1290
    {
1291
        global $conf, $langs, $db, $user, $hookmanager;
1292
1293
        $error = 0;
1294
        $nb_create = 0;
1295
1296
        // Load translation files required by the page
1297
        $langs->loadLangs(array('main', 'bills'));
1298
1299
        $now = dol_now();
1300
        $tmparray = dol_getdate($now);
1301
        $today = dol_mktime(23, 59, 59, $tmparray['mon'], $tmparray['mday'], $tmparray['year']); // Today is last second of current day
1302
1303
        dol_syslog('createRecurringInvoices restrictioninvoiceid=' . $restrictioninvoiceid . ' forcevalidation=' . $forcevalidation);
1304
1305
        $sql = 'SELECT rowid FROM ' . MAIN_DB_PREFIX . 'facture_fourn_rec';
1306
        $sql .= ' WHERE frequency > 0'; // A recurring supplier invoice is an invoice with a frequency
1307
        $sql .= " AND (date_when IS NULL OR date_when <= '" . $this->db->idate($today) . "')";
1308
        $sql .= ' AND (nb_gen_done < nb_gen_max OR nb_gen_max = 0)';
1309
        $sql .= ' AND suspended = 0';
1310
        $sql .= ' AND entity = ' . (int) $conf->entity; // MUST STAY = $conf->entity here
1311
        if ($restrictioninvoiceid > 0) {
1312
            $sql .= ' AND rowid = ' . (int) $restrictioninvoiceid;
1313
        }
1314
        $sql .= $this->db->order('entity', 'ASC');
1315
        //print $sql;exit;
1316
        $parameters = array(
1317
            'restrictioninvoiceid' => $restrictioninvoiceid,
1318
            'forcevalidation' => $forcevalidation,
1319
        );
1320
        $reshook = $hookmanager->executeHooks('beforeCreationOfRecurringInvoices', $parameters, $sql); // note that $sql might be modified by hooks
1321
1322
        $resql = $this->db->query($sql);
1323
        if ($resql) {
1324
            $i = 0;
1325
            $num = $this->db->num_rows($resql);
1326
1327
            if ($num) {
1328
                $this->output .= $langs->trans('FoundXQualifiedRecurringInvoiceTemplate', $num) . "\n";
1329
            } else {
1330
                $this->output .= $langs->trans('NoQualifiedRecurringInvoiceTemplateFound');
1331
            }
1332
1333
            $saventity = $conf->entity;
1334
            $laststep = "None";
1335
1336
            while ($i < $num) {     // Loop on each template invoice. If $num = 0, test is false at first pass.
1337
                $line = $this->db->fetch_object($resql);
1338
1339
                $this->db->begin();
1340
1341
                $invoiceidgenerated = 0;
1342
1343
                $new_fac_fourn = null;
1344
                $facturerec = new FactureFournisseurRec($this->db);
1345
                $laststep = "Fetch {$line->rowid}";
1346
                $facturerec->fetch($line->rowid);
1347
1348
                if ($facturerec->id > 0) {
1349
                    // Set entity context
1350
                    $conf->entity = $facturerec->entity;
1351
1352
                    dol_syslog('createRecurringInvoices Process invoice template id=' . $facturerec->id . ', ref=' . $facturerec->ref . ', entity=' . $facturerec->entity);
1353
1354
                    $new_fac_fourn = new FactureFournisseur($this->db);
1355
                    $new_fac_fourn->fac_rec = $facturerec->id; // We will create $facture from this recurring invoice
1356
                    $new_fac_fourn->fk_fac_rec_source = $facturerec->id; // We will create $facture from this recurring invoice
1357
1358
                    $new_fac_fourn->type = self::TYPE_STANDARD;
1359
                    $new_fac_fourn->subtype = $facturerec->subtype;
1360
                    $new_fac_fourn->statut = self::STATUS_DRAFT;    // deprecated
1361
                    $new_fac_fourn->status = self::STATUS_DRAFT;
1362
                    $new_fac_fourn->date = empty($facturerec->date_when) ? $now : $facturerec->date_when; // We could also use dol_now here but we prefer date_when so invoice has real date when we would like even if we generate later.
1363
                    $new_fac_fourn->socid = $facturerec->socid;
1364
                    $new_fac_fourn->lines = $facturerec->lines;
1365
                    $new_fac_fourn->ref_supplier = $facturerec->ref_supplier;
1366
                    $new_fac_fourn->model_pdf = $facturerec->model_pdf;
1367
                    $new_fac_fourn->fk_project = $facturerec->fk_project;
1368
                    $new_fac_fourn->label = $facturerec->label;
1369
                    $new_fac_fourn->libelle = $facturerec->label;   // deprecated
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Code\Fourn\Clas...reFournisseur::$libelle has been deprecated: Use $label ( Ignorable by Annotation )

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

1369
                    /** @scrutinizer ignore-deprecated */ $new_fac_fourn->libelle = $facturerec->label;   // deprecated

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...
1370
1371
                    $invoiceidgenerated = $new_fac_fourn->create($user);
1372
                    $laststep = "Create invoiceidgenerated $invoiceidgenerated";
1373
                    if ($invoiceidgenerated <= 0) {
1374
                        $this->errors = $new_fac_fourn->errors;
1375
                        $this->error = $new_fac_fourn->error;
1376
                        $error++;
1377
                    }
1378
                    if (!$error && ($facturerec->auto_validate || $forcevalidation)) {
1379
                        $result = $new_fac_fourn->validate($user);
1380
                        $laststep = "Validate by user {$user->login}";
1381
                        if ($result <= 0) {
1382
                            $this->errors = $new_fac_fourn->errors;
1383
                            $this->error = $new_fac_fourn->error;
1384
                            $error++;
1385
                        }
1386
                    }
1387
1388
                    if (!$error && $facturerec->generate_pdf) {
1389
                        // We refresh the object in order to have all necessary data (like date_lim_reglement)
1390
                        $laststep = "Refresh " . $new_fac_fourn->id;
1391
                        $new_fac_fourn->fetch($new_fac_fourn->id);
1392
                        $laststep = "GenerateDocument " . $new_fac_fourn->id;
1393
                        $result = $new_fac_fourn->generateDocument($facturerec->model_pdf, $langs);
1394
                        if ($result < 0) {
1395
                            $this->errors = $new_fac_fourn->errors;
1396
                            $this->error = $new_fac_fourn->error;
1397
                            $error++;
1398
                        }
1399
                    }
1400
                } else {
1401
                    $error++;
1402
                    $this->error = 'Failed to load invoice template with id=' . $line->rowid . ', entity=' . $conf->entity . "\n";
1403
                    $this->errors[] = 'Failed to load invoice template with id=' . $line->rowid . ', entity=' . $conf->entity;
1404
                    dol_syslog('createRecurringInvoices Failed to load invoice template with id=' . $line->rowid . ', entity=' . $conf->entity);
1405
                }
1406
1407
                if (!$error && $invoiceidgenerated >= 0) {
1408
                    $facturerec->nb_gen_done++;
1409
                    $facturerec->date_last_gen = dol_now();
1410
                    $facturerec->date_when = $facturerec->getNextDate();
1411
                    $facturerec->update($user);
1412
                    $this->db->commit('createRecurringInvoices Process invoice template id=' . $facturerec->id . ', title=' . $facturerec->title);
1413
                    dol_syslog('createRecurringInvoices Process invoice template ' . $facturerec->title . ' is finished with a success generation');
1414
                    $nb_create++;
1415
                    $this->output .= $langs->trans('InvoiceGeneratedFromTemplate', $new_fac_fourn->ref, $facturerec->title) . "\n";
1416
                } else {
1417
                    $this->db->rollback('createRecurringInvoices Process invoice template error=' . $error . ' invoiceidgenerated=' . $invoiceidgenerated . ' LastStep=' . $laststep . ' id=' . $facturerec->id . ', title=' . $facturerec->title);
1418
                }
1419
1420
                $parameters = array(
1421
                    'cpt'        => $i,
1422
                    'total'      => $num,
1423
                    'errorCount' => $error,
1424
                    'invoiceidgenerated' => $invoiceidgenerated,
1425
                    'facturerec' => $facturerec, // it's an object which PHP passes by "reference", so modifiable by hooks.
1426
                    'this'       => $this, // it's an object which PHP passes by "reference", so modifiable by hooks.
1427
                );
1428
                $reshook = $hookmanager->executeHooks('afterCreationOfRecurringInvoice', $parameters, $new_fac_fourn); // note: $facture can be modified by hooks (warning: $facture can be null)
1429
1430
                $i++;
1431
            }
1432
1433
            $conf->entity = $saventity; // Restore entity context
1434
        } else {
1435
            dol_print_error($this->db);
1436
        }
1437
1438
        $this->output = trim($this->output);
1439
1440
        return $error ? $error : 0;
1441
    }
1442
1443
    /**
1444
     *  Return clicable name (with picto eventually)
1445
     *
1446
     * @param   int     $withpicto                  Add picto into link
1447
     * @param  string   $option                     Where point the link
1448
     * @param  int      $max                        Maxlength of ref
1449
     * @param  int      $short                      1=Return just URL
1450
     * @param  string   $moretitle                  Add more text to title tooltip
1451
     * @param   int     $notooltip                  1=Disable tooltip
1452
     * @param  int      $save_lastsearch_value      -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
1453
     * @return string                               String with URL
1454
     */
1455
    public function getNomUrl($withpicto = 0, $option = '', $max = 0, $short = 0, $moretitle = '', $notooltip = 0, $save_lastsearch_value = -1)
1456
    {
1457
        global $langs, $hookmanager;
1458
1459
        $result = '';
1460
1461
        $label = '<u>' . $langs->trans('RepeatableInvoice') . '</u>';
1462
        if (!empty($this->ref)) {
1463
            $label .= '<br><b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
1464
        }
1465
        if ($this->frequency > 0) {
1466
            $label .= '<br><b>' . $langs->trans('Frequency') . ':</b> ' . $langs->trans('FrequencyPer_' . $this->unit_frequency, $this->frequency);
1467
        }
1468
        if (!empty($this->date_last_gen)) {
1469
            $label .= '<br><b>' . $langs->trans('DateLastGeneration') . ':</b> ' . dol_print_date($this->date_last_gen, 'dayhour');
1470
        }
1471
        if ($this->frequency > 0) {
1472
            if (!empty($this->date_when)) {
1473
                $label .= '<br><b>' . $langs->trans('NextDateToExecution') . ':</b> ';
1474
                $label .= (empty($this->suspended) ? '' : '<strike>') . dol_print_date($this->date_when, 'day') . (empty($this->suspended) ? '' : '</strike>'); // No hour for this property
1475
                if (!empty($this->suspended)) {
1476
                    $label .= ' (' . $langs->trans('Disabled') . ')';
1477
                }
1478
            }
1479
        }
1480
1481
        $url = constant('BASE_URL') . '/fourn/facture/card-rec.php?facid=' . $this->id;
1482
1483
        if ($short) {
1484
            return $url;
1485
        }
1486
1487
        if ($option != 'nolink') {
1488
            // Add param to save lastsearch_values or not
1489
            $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1490
            if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER['PHP_SELF'])) {
1491
                $add_save_lastsearch_values = 1;
1492
            }
1493
            if ($add_save_lastsearch_values) {
1494
                $url .= '&save_lastsearch_values=1';
1495
            }
1496
        }
1497
1498
        $linkstart = '<a href="' . $url . '" title="' . dol_escape_htmltag($label, 1) . '" class="classfortooltip">';
1499
        $linkend = '</a>';
1500
1501
        $result .= $linkstart;
1502
        if ($withpicto) {
1503
            $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="' . (($withpicto != 2) ? 'paddingright ' : '') . 'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
1504
        }
1505
        if ($withpicto != 2) {
1506
            $result .= $this->ref;
1507
        }
1508
        $result .= $linkend;
1509
        global $action;
1510
        $hookmanager->initHooks(array($this->element . 'dao'));
1511
        $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1512
        $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1513
        if ($reshook > 0) {
1514
            $result = $hookmanager->resPrint;
1515
        } else {
1516
            $result .= $hookmanager->resPrint;
1517
        }
1518
        return $result;
1519
    }
1520
1521
    /**
1522
     *  Return label of object status
1523
     *
1524
     *  @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
1525
     *  @param      integer $alreadypaid    Not used on recurring invoices
1526
     *  @return     string                  Label of status
1527
     */
1528
    public function getLibStatut($mode = 0, $alreadypaid = -1)
1529
    {
1530
        return $this->LibStatut($this->frequency ? 1 : 0, $this->suspended, $mode, $alreadypaid, empty($this->type) ? 0 : $this->type);
1531
    }
1532
1533
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1534
    /**
1535
     *  Return label of a status
1536
     *
1537
     *  @param      int     $recur          Is it a recurring invoice ?
1538
     *  @param      int     $status         Id status (suspended or not)
1539
     *  @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
1540
     *  @param      integer $alreadypaid    Not used for recurring invoices
1541
     *  @param      int     $type           Type invoice
1542
     *  @return     string                  Label of status
1543
     */
1544
    public function LibStatut($recur, $status, $mode = 0, $alreadypaid = -1, $type = 0)
1545
    {
1546
		// phpcs:enable
1547
        global $langs;
1548
        $langs->load('bills');
1549
1550
        $labelStatus = $langs->transnoentitiesnoconv('Active');
1551
        $statusType = 'status0';
1552
1553
        //print "$recur,$status,$mode,$alreadypaid,$type";
1554
        if ($mode == 0) {
1555
            if ($recur) {
1556
                if ($status == self::STATUS_SUSPENDED) {
1557
                    $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1558
                } else {
1559
                    $labelStatus = $langs->transnoentitiesnoconv('Active');
1560
                }
1561
            } else {
1562
                if ($status == self::STATUS_SUSPENDED) {
1563
                    $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1564
                } else {
1565
                    $labelStatus = $langs->transnoentitiesnoconv('Draft');
1566
                }
1567
            }
1568
        } elseif ($mode == 1) {
1569
            $prefix = 'Short';
1570
            if ($recur) {
1571
                if ($status == self::STATUS_SUSPENDED) {
1572
                    $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1573
                } else {
1574
                    $labelStatus = $langs->transnoentitiesnoconv('Active');
1575
                }
1576
            } else {
1577
                if ($status == self::STATUS_SUSPENDED) {
1578
                    $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1579
                } else {
1580
                    $labelStatus = $langs->transnoentitiesnoconv('Draft');
1581
                }
1582
            }
1583
        } elseif ($mode == 2) {
1584
            if ($recur) {
1585
                if ($status == self::STATUS_SUSPENDED) {
1586
                    $statusType = 'status6';
1587
                    $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1588
                } else {
1589
                    $statusType = 'status4';
1590
                    $labelStatus = $langs->transnoentitiesnoconv('Active');
1591
                }
1592
            } else {
1593
                if ($status == self::STATUS_SUSPENDED) {
1594
                    $statusType = 'status6';
1595
                    $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1596
                } else {
1597
                    $statusType = 'status0';
1598
                    $labelStatus = $langs->transnoentitiesnoconv('Draft');
1599
                }
1600
            }
1601
        } elseif ($mode == 3) {
1602
            if ($recur) {
1603
                $prefix = 'Short';
1604
                if ($status == self::STATUS_SUSPENDED) {
1605
                    $statusType = 'status6';
1606
                    $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1607
                } else {
1608
                    $statusType = 'status4';
1609
                    $labelStatus = $langs->transnoentitiesnoconv('Active');
1610
                }
1611
            } else {
1612
                if ($status == self::STATUS_SUSPENDED) {
1613
                    $statusType = 'status6';
1614
                    $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1615
                } else {
1616
                    $statusType = 'status0';
1617
                    $labelStatus = $langs->transnoentitiesnoconv('Draft');
1618
                }
1619
            }
1620
        } elseif ($mode == 4) {
1621
            $prefix = '';
1622
            if ($recur) {
1623
                if ($status == self::STATUS_SUSPENDED) {
1624
                    $statusType = 'status6';
1625
                    $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1626
                } else {
1627
                    $statusType = 'status4';
1628
                    $labelStatus = $langs->transnoentitiesnoconv('Active');
1629
                }
1630
            } else {
1631
                if ($status == self::STATUS_SUSPENDED) {
1632
                    $statusType = 'status6';
1633
                    $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1634
                } else {
1635
                    $statusType = 'status0';
1636
                    $labelStatus = $langs->transnoentitiesnoconv('Draft');
1637
                }
1638
            }
1639
        } elseif ($mode == 5 || $mode == 6) {
1640
            $prefix = '';
1641
            if ($mode == 5) {
1642
                $prefix = 'Short';
1643
            }
1644
            if ($recur) {
1645
                if ($status == self::STATUS_SUSPENDED) {
1646
                    $statusType = 'status6';
1647
                    $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1648
                } else {
1649
                    $statusType = 'status4';
1650
                    $labelStatus = $langs->transnoentitiesnoconv('Active');
1651
                }
1652
            } else {
1653
                if ($status == self::STATUS_SUSPENDED) {
1654
                    $statusType = 'status6';
1655
                    $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1656
                } else {
1657
                    $statusType = 'status0';
1658
                    $labelStatus = $langs->transnoentitiesnoconv('Draft');
1659
                }
1660
            }
1661
        }
1662
1663
        $labelStatusShort = $labelStatus;
1664
1665
        return dolGetStatus($labelStatus, $labelStatusShort, '', $statusType, $mode);
1666
    }
1667
1668
    /**
1669
     *  Initialise an instance with random values.
1670
     *  Used to build previews or test instances.
1671
     *  id must be 0 if object instance is a specimen.
1672
     *
1673
     *  @param  string      $option     ''=Create a specimen invoice with lines, 'nolines'=No lines
1674
     *  @return int
1675
     */
1676
    public function initAsSpecimen($option = '')
1677
    {
1678
        global $user, $langs, $conf;
1679
1680
        $now = dol_now();
1681
        $arraynow = dol_getdate($now);
1682
        $nownotime = dol_mktime(0, 0, 0, $arraynow['mon'], $arraynow['mday'], $arraynow['year']);
1683
1684
        // Load array of products prodids
1685
        $num_prods = 0;
1686
        $prodids = array();
1687
1688
        $sql = 'SELECT rowid';
1689
        $sql .= ' FROM ' . MAIN_DB_PREFIX . 'product';
1690
        $sql .= ' WHERE entity IN (' . getEntity('product') . ')';
1691
        $sql .= $this->db->plimit(100);
1692
1693
        $resql = $this->db->query($sql);
1694
        if ($resql) {
1695
            $num_prods = $this->db->num_rows($resql);
1696
            $i = 0;
1697
            while ($i < $num_prods) {
1698
                $i++;
1699
                $row = $this->db->fetch_row($resql);
1700
                $prodids[$i] = $row[0];
1701
            }
1702
        }
1703
1704
        // Initialize parameters
1705
        $this->id = 0;
1706
        $this->ref = 'SPECIMEN';
1707
        $this->title = 'SPECIMEN';
1708
        $this->specimen = 1;
1709
        $this->socid = 1;
1710
        $this->date = $nownotime;
0 ignored issues
show
Documentation Bug introduced by
It seems like $nownotime can also be of type string. However, the property $date 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...
1711
        $this->date_lim_reglement = $nownotime + 3600 * 24 * 30;
1712
        $this->cond_reglement_id   = 1;
1713
        $this->cond_reglement_code = 'RECEP';
1714
        $this->date_lim_reglement = $this->calculate_date_lim_reglement();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->calculate_date_lim_reglement() can also be of type string. However, the property $date_lim_reglement 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...
1715
        $this->mode_reglement_id   = 0; // Not forced to show payment mode CHQ + VIR
1716
        $this->mode_reglement_code = ''; // Not forced to show payment mode CHQ + VIR
1717
        $this->note_public = 'This is a comment (public)';
1718
        $this->note_private = 'This is a comment (private)';
1719
        $this->note = 'This is a comment (private)';
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$note has been deprecated: Use $note_private instead. ( Ignorable by Annotation )

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

1719
        /** @scrutinizer ignore-deprecated */ $this->note = 'This is a comment (private)';

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...
1720
        $this->fk_incoterms = 0;
1721
        $this->location_incoterms = '';
1722
1723
        if (empty($option) || $option != 'nolines') {
1724
            // Lines
1725
            $nbp = 5;
1726
            $xnbp = 0;
1727
            while ($xnbp < $nbp) {
1728
                $line = new FactureLigne($this->db);
1729
                $line->desc = $langs->trans('Description') . ' ' . $xnbp;
1730
                $line->qty = 1;
1731
                $line->subprice = 100;
1732
                $line->tva_tx = 19.6;
1733
                $line->localtax1_tx = 0;
1734
                $line->localtax2_tx = 0;
1735
                $line->remise_percent = 0;
1736
                if ($xnbp == 1) {        // Qty is negative (product line)
1737
                    $prodid = mt_rand(1, $num_prods);
1738
                    $line->fk_product = $prodids[$prodid];
1739
                    $line->qty = -1;
1740
                    $line->total_ht = -100;
1741
                    $line->total_ttc = -119.6;
1742
                    $line->total_tva = -19.6;
1743
                } elseif ($xnbp == 2) {    // UP is negative (free line)
1744
                    $line->subprice = -100;
1745
                    $line->total_ht = -100;
1746
                    $line->total_ttc = -119.6;
1747
                    $line->total_tva = -19.6;
1748
                    $line->remise_percent = 0;
1749
                } elseif ($xnbp == 3) {    // Discount is 50% (product line)
1750
                    $prodid = mt_rand(1, $num_prods);
1751
                    $line->fk_product = $prodids[$prodid];
1752
                    $line->total_ht = 50;
1753
                    $line->total_ttc = 59.8;
1754
                    $line->total_tva = 9.8;
1755
                    $line->remise_percent = 50;
1756
                } else { // (product line)
1757
                    $prodid = mt_rand(1, $num_prods);
1758
                    $line->fk_product = $prodids[$prodid];
1759
                    $line->total_ht = 100;
1760
                    $line->total_ttc = 119.6;
1761
                    $line->total_tva = 19.6;
1762
                    $line->remise_percent = 0;
1763
                }
1764
1765
                $this->lines[$xnbp] = $line;
1766
                $xnbp++;
1767
1768
                $this->total_ht       += $line->total_ht;
1769
                $this->total_tva      += $line->total_tva;
1770
                $this->total_ttc      += $line->total_ttc;
1771
            }
1772
            $this->revenuestamp = 0;
1773
1774
            // Add a line "offered"
1775
            $line = new FactureLigne($this->db);
1776
            $line->desc = $langs->trans('Description') . ' (offered line)';
1777
            $line->qty = 1;
1778
            $line->subprice = 100;
1779
            $line->tva_tx = 19.6;
1780
            $line->localtax1_tx = 0;
1781
            $line->localtax2_tx = 0;
1782
            $line->remise_percent = 100;
1783
            $line->total_ht = 0;
1784
            $line->total_ttc = 0; // 90 * 1.196
1785
            $line->total_tva = 0;
1786
            $prodid = mt_rand(1, $num_prods);
1787
            $line->fk_product = $prodids[$prodid];
1788
1789
            $this->lines[$xnbp] = $line;
1790
            $xnbp++;
1791
        }
1792
1793
        $this->usenewprice = 0;
1794
1795
        return 1;
1796
    }
1797
1798
    /**
1799
     * Function used to replace a thirdparty id with another one.
1800
     *
1801
     * @param   DoliDB  $dbs        Database handler, because function is static we name it $dbs not $db to avoid breaking coding test
1802
     * @param   int     $origin_id  Old thirdparty id
1803
     * @param   int     $dest_id    New thirdparty id
1804
     * @return  bool
1805
     */
1806
    public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
1807
    {
1808
        $tables = array(
1809
            'facture_fourn_rec'
1810
        );
1811
1812
        return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables);
1813
    }
1814
1815
    /**
1816
     *  Update frequency and unit
1817
     *
1818
     *  @param      int     $frequency      value of frequency
1819
     *  @param      string  $unit           unit of frequency  (d, m, y)
1820
     *  @return     int                     Return integer <0 if KO, >0 if OK
1821
     */
1822
    public function setFrequencyAndUnit($frequency, $unit)
1823
    {
1824
        if (!$this->table_element) {
1825
            dol_syslog(get_class($this) . '::setFrequencyAndUnit was called on object with property table_element not defined', LOG_ERR);
1826
            return -1;
1827
        }
1828
1829
        if (!empty($frequency) && empty($unit)) {
1830
            dol_syslog(get_class($this) . '::setFrequencyAndUnit was called on object with params frequency defined but unit not defined', LOG_ERR);
1831
            return -2;
1832
        }
1833
1834
        $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element;
1835
        $sql .= " SET frequency = " . ($frequency ? ((int) $frequency) : "NULL");
1836
        if (!empty($unit)) {
1837
            $sql .= ", unit_frequency = '" . $this->db->escape($unit) . "'";
1838
        }
1839
        $sql .= " WHERE rowid = " . ((int) $this->id);
1840
1841
        dol_syslog(get_class($this) . '::setFrequencyAndUnit', LOG_DEBUG);
1842
1843
        if ($this->db->query($sql)) {
1844
            $this->frequency = $frequency;
1845
            if (!empty($unit)) {
1846
                $this->unit_frequency = $unit;
1847
            }
1848
            return 1;
1849
        } else {
1850
            $this->error = $this->db->lasterror();
1851
            return -1;
1852
        }
1853
    }
1854
1855
    /**
1856
     *  Update the next date of execution
1857
     *
1858
     *  @param      datetime    $date                   date of execution
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Fourn\Classes\datetime was not found. Did you mean datetime? If so, make sure to prefix the type with \.
Loading history...
1859
     *  @param      int         $increment_nb_gen_done  0 do nothing more, >0 increment nb_gen_done
1860
     *  @return     int                                 Return integer <0 if KO, >0 if OK
1861
     */
1862
    public function setNextDate($date, $increment_nb_gen_done = 0)
1863
    {
1864
        if (!$this->table_element) {
1865
            dol_syslog(get_class($this) . '::setNextDate was called on object with property table_element not defined', LOG_ERR);
1866
            return -1;
1867
        }
1868
        $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element;
1869
        $sql .= " SET date_when = " . ($date ? "'" . $this->db->idate($date) . "'" : "NULL");
1870
        if ($increment_nb_gen_done > 0) {
1871
            $sql .= ", nb_gen_done = nb_gen_done + 1";
1872
        }
1873
        $sql .= " WHERE rowid = " . (int) $this->id;
1874
1875
        dol_syslog(get_class($this) . '::setNextDate', LOG_DEBUG);
1876
1877
        if ($this->db->query($sql)) {
1878
            $this->date_when = $date;
1879
            if ($increment_nb_gen_done > 0) {
1880
                $this->nb_gen_done++;
1881
            }
1882
            return 1;
1883
        } else {
1884
            $this->error = $this->db->lasterror();
1885
            return -1;
1886
        }
1887
    }
1888
1889
    /**
1890
     *  Update the maximum period
1891
     *
1892
     *  @param      int     $nb     number of maximum period
1893
     *  @return     int             Return integer <0 if KO, >0 if OK
1894
     */
1895
    public function setMaxPeriod($nb)
1896
    {
1897
        if (!$this->table_element) {
1898
            dol_syslog(get_class($this) . '::setMaxPeriod was called on object with property table_element not defined', LOG_ERR);
1899
            return -1;
1900
        }
1901
1902
        if (empty($nb)) {
1903
            $nb = 0;
1904
        }
1905
1906
        $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element;
1907
        $sql .= " SET nb_gen_max = " . (int) $nb;
1908
        $sql .= " WHERE rowid = " . (int) $this->id;
1909
1910
        dol_syslog(get_class($this) . '::setMaxPeriod', LOG_DEBUG);
1911
1912
        if ($this->db->query($sql)) {
1913
            $this->nb_gen_max = $nb;
1914
            return 1;
1915
        } else {
1916
            dol_print_error($this->db);
1917
            return -1;
1918
        }
1919
    }
1920
1921
    /**
1922
     *  Update the auto validate flag of invoice
1923
     *
1924
     *  @param      int     $validate       0 to create in draft, 1 to create and validate invoice
1925
     *  @return     int                     Return integer <0 if KO, >0 if OK
1926
     */
1927
    public function setAutoValidate($validate)
1928
    {
1929
        if (!$this->table_element) {
1930
            dol_syslog(get_class($this) . '::setAutoValidate was called on object with property table_element not defined', LOG_ERR);
1931
            return -1;
1932
        }
1933
1934
        $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element;
1935
        $sql .= " SET auto_validate = " . ((int) $validate);
1936
        $sql .= " WHERE rowid = " . (int) $this->id;
1937
1938
        dol_syslog(get_class($this) . '::setAutoValidate', LOG_DEBUG);
1939
1940
        if ($this->db->query($sql)) {
1941
            $this->auto_validate = $validate;
1942
            return 1;
1943
        } else {
1944
            dol_print_error($this->db);
1945
            return -1;
1946
        }
1947
    }
1948
1949
    /**
1950
     *  Update the auto generate documents
1951
     *
1952
     *  @param      int     $validate       0 no document, 1 to generate document
1953
     *  @return     int                     Return integer <0 if KO, >0 if OK
1954
     */
1955
    public function setGeneratePdf($validate)
1956
    {
1957
        if (!$this->table_element) {
1958
            dol_syslog(get_class($this) . '::setGeneratePdf was called on object with property table_element not defined', LOG_ERR);
1959
            return -1;
1960
        }
1961
1962
        $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element;
1963
        $sql .= " SET generate_pdf = " . (int) $validate;
1964
        $sql .= " WHERE rowid = " . (int) $this->id;
1965
1966
        dol_syslog(get_class($this) . '::setGeneratePdf', LOG_DEBUG);
1967
1968
        if ($this->db->query($sql)) {
1969
            $this->generate_pdf = $validate;
1970
            return 1;
1971
        } else {
1972
            dol_print_error($this->db);
1973
            return -1;
1974
        }
1975
    }
1976
1977
    /**
1978
     *  Update the model for documents
1979
     *
1980
     *  @param      string      $model      model of document generator
1981
     *  @return     int                     Return integer <0 if KO, >0 if OK
1982
     */
1983
    public function setModelPdf($model)
1984
    {
1985
        if (!$this->table_element) {
1986
            dol_syslog(get_class($this) . '::setModelPdf was called on object with property table_element not defined', LOG_ERR);
1987
            return -1;
1988
        }
1989
1990
        $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element;
1991
        $sql .= " SET modelpdf = '" . $this->db->escape($model) . "'";
1992
        $sql .= " WHERE rowid = " . (int) $this->id;
1993
1994
        dol_syslog(get_class($this) . '::setModelPdf', LOG_DEBUG);
1995
1996
        if ($this->db->query($sql)) {
1997
            $this->model_pdf = $model;
1998
            return 1;
1999
        } else {
2000
            dol_print_error($this->db);
2001
            return -1;
2002
        }
2003
    }
2004
}
2005