Passed
Branch develop (5cbde9)
by
unknown
26:38
created

SupplierProposal::addline()   F

Complexity

Conditions 37
Paths > 20000

Size

Total Lines 232
Code Lines 146

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 37
eloc 146
c 0
b 0
f 0
nc 820736
nop 24
dl 0
loc 232
rs 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/* Copyright (C) 2002-2004 Rodolphe Quiedeville		<[email protected]>
3
 * Copyright (C) 2004      Eric Seigne				<[email protected]>
4
 * Copyright (C) 2004-2011 Laurent Destailleur		<[email protected]>
5
 * Copyright (C) 2005      Marc Barilley			<[email protected]>
6
 * Copyright (C) 2005-2013 Regis Houssin			<[email protected]>
7
 * Copyright (C) 2006      Andre Cianfarani			<[email protected]>
8
 * Copyright (C) 2008      Raphael Bertrand			<[email protected]>
9
 * Copyright (C) 2010-2015 Juanjo Menent			<[email protected]>
10
 * Copyright (C) 2010-2018 Philippe Grand			<[email protected]>
11
 * Copyright (C) 2012-2014 Christophe Battarel  	<[email protected]>
12
 * Copyright (C) 2013      Florian Henry		  	<[email protected]>
13
 * Copyright (C) 2014      Marcos García            <[email protected]>
14
 * Copyright (C) 2016      Ferran Marcet            <[email protected]>
15
 * Copyright (C) 2018      Nicolas ZABOURI			<[email protected]>
16
 * Copyright (C) 2019       Frédéric France         <[email protected]>
17
 *
18
 * This program is free software; you can redistribute it and/or modify
19
 * it under the terms of the GNU General Public License as published by
20
 * the Free Software Foundation; either version 3 of the License, or
21
 * (at your option) any later version.
22
 *
23
 * This program is distributed in the hope that it will be useful,
24
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26
 * GNU General Public License for more details.
27
 *
28
 * You should have received a copy of the GNU General Public License
29
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
30
 */
31
32
/**
33
 *	\file       htdocs/supplier_proposal/class/supplier_proposal.class.php
34
 *	\brief      File of class to manage supplier proposals
35
 */
36
37
require_once DOL_DOCUMENT_ROOT .'/fourn/class/fournisseur.product.class.php';
38
require_once DOL_DOCUMENT_ROOT .'/core/class/commonobject.class.php';
39
require_once DOL_DOCUMENT_ROOT .'/product/class/product.class.php';
40
require_once DOL_DOCUMENT_ROOT .'/contact/class/contact.class.php';
41
require_once DOL_DOCUMENT_ROOT .'/margin/lib/margins.lib.php';
42
require_once DOL_DOCUMENT_ROOT .'/multicurrency/class/multicurrency.class.php';
43
44
/**
45
 *	Class to manage price ask supplier
46
 */
47
class SupplierProposal extends CommonObject
48
{
49
    /**
50
     * @var string ID to identify managed object
51
     */
52
    public $element='supplier_proposal';
53
54
    /**
55
     * @var string Name of table without prefix where object is stored
56
     */
57
    public $table_element='supplier_proposal';
58
59
    /**
60
     * @var int    Name of subtable line
61
     */
62
    public $table_element_line='supplier_proposaldet';
63
64
    /**
65
     * @var int Field with ID of parent key if this field has a parent
66
     */
67
    public $fk_element='fk_supplier_proposal';
68
69
    public $picto='propal';
70
71
    /**
72
     * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
73
     * @var int
74
     */
75
    public $ismultientitymanaged = 1;
76
77
    /**
78
     * 0=Default, 1=View may be restricted to sales representative only if no permission to see all or to company of external user if external user
79
     * @var integer
80
     */
81
    public $restrictiononfksoc = 1;
82
83
    /**
84
     * {@inheritdoc}
85
     */
86
    protected $table_ref_field = 'ref';
87
88
    public $socid;		// Id client
89
90
    /**
91
     * @deprecated
92
     * @see $user_author_id
93
     */
94
    public $author;
95
96
    public $ref_fourn;					//Reference saisie lors de l'ajout d'une ligne à la demande
97
    public $ref_supplier;				//Reference saisie lors de l'ajout d'une ligne à la demande
98
    public $statut;					// 0 (draft), 1 (validated), 2 (signed), 3 (not signed), 4 (processed/billed)
99
    public $date;						// Date of proposal
100
    public $date_livraison;
101
102
    /**
103
     * @deprecated
104
     * @see $date_creation
105
     */
106
    public $datec;
107
108
    /**
109
     * Creation date
110
     * @var int
111
     */
112
    public $date_creation;
113
114
    /**
115
     * @deprecated
116
     * @see $date_validation
117
     */
118
    public $datev;
119
120
    /**
121
     * Validation date
122
     * @var int
123
     */
124
    public $date_validation;
125
126
127
    public $user_author_id;
128
    public $user_valid_id;
129
    public $user_close_id;
130
131
    /**
132
     * @deprecated
133
     * @see $price_ht
134
     */
135
    public $price;
136
137
    /**
138
     * @deprecated
139
     * @see $total_tva
140
     */
141
    public $tva;
142
143
    /**
144
     * @deprecated
145
     * @see $total_ttc
146
     */
147
    public $total;
148
149
    public $cond_reglement_code;
150
    public $mode_reglement_code;
151
    public $remise = 0;
152
    public $remise_percent = 0;
153
    public $remise_absolue = 0;
154
155
    public $products=array();
156
    public $extraparams=array();
157
158
    public $lines = array();
159
    public $line;
160
161
    public $labelstatut=array();
162
    public $labelstatut_short=array();
163
164
    public $nbtodo;
165
    public $nbtodolate;
166
167
    public $specimen;
168
169
    // Multicurrency
170
    /**
171
     * @var int ID
172
     */
173
    public $fk_multicurrency;
174
175
    public $multicurrency_code;
176
    public $multicurrency_tx;
177
    public $multicurrency_total_ht;
178
    public $multicurrency_total_tva;
179
    public $multicurrency_total_ttc;
180
181
    /**
182
     * Draft status
183
     */
184
    const STATUS_DRAFT = 0;
185
186
    /**
187
     * Validated status
188
     */
189
    const STATUS_VALIDATED = 1;
190
191
    /**
192
     * Signed quote
193
     */
194
    const STATUS_SIGNED = 2;
195
196
    /**
197
     * Not signed quote, canceled
198
     */
199
    const STATUS_NOTSIGNED = 3;
200
201
    /**
202
     * Billed or closed/processed quote
203
     */
204
    const STATUS_CLOSE = 4;
205
206
207
208
    /**
209
     *	Constructor
210
     *
211
     *	@param      DoliDB	$db         Database handler
212
     *	@param      int		$socid		Id third party
213
     *	@param      int		$supplier_proposalid   Id supplier_proposal
214
     */
215
    public function __construct($db, $socid = "", $supplier_proposalid = 0)
216
    {
217
        global $conf,$langs;
218
219
        $this->db = $db;
220
221
        $this->socid = $socid;
222
        $this->id = $supplier_proposalid;
223
224
        $this->products = array();
225
    }
226
227
228
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
229
    /**
230
     * 	Add line into array products
231
     *  $this->client doit etre charge
232
     *
233
     * 	@param  int		$idproduct       	Product Id to add
234
     * 	@param  int		$qty             	Quantity
235
     * 	@param  int		$remise_percent  	Discount effected on Product
236
     *  @return	int							<0 if KO, >0 if OK
237
     *
238
     *	TODO	Remplacer les appels a cette fonction par generation objet Ligne
239
     *			insere dans tableau $this->products
240
     */
241
    public function add_product($idproduct, $qty, $remise_percent = 0)
242
    {
243
        // phpcs:enable
244
        global $conf, $mysoc;
245
246
        if (! $qty) $qty = 1;
247
248
        dol_syslog(get_class($this)."::add_product $idproduct, $qty, $remise_percent");
249
        if ($idproduct > 0)
250
        {
251
            $prod=new Product($this->db);
252
            $prod->fetch($idproduct);
253
254
            $productdesc = $prod->description;
255
256
            $tva_tx = get_default_tva($mysoc, $this->thirdparty, $prod->id);
257
            $tva_npr = get_default_npr($mysoc, $this->thirdparty, $prod->id);
258
            if (empty($tva_tx)) $tva_npr=0;
259
            $localtax1_tx = get_localtax($tva_tx, 1, $mysoc, $this->thirdparty, $tva_npr);
260
            $localtax2_tx = get_localtax($tva_tx, 2, $mysoc, $this->thirdparty, $tva_npr);
261
262
            // multiprix
263
            if($conf->global->PRODUIT_MULTIPRICES && $this->thirdparty->price_level)
264
            {
265
                $price = $prod->multiprices[$this->thirdparty->price_level];
266
            }
267
            else
268
            {
269
                $price = $prod->price;
270
            }
271
272
            $line = new SupplierProposalLine($this->db);
273
274
            $line->fk_product=$idproduct;
275
            $line->desc=$productdesc;
276
            $line->qty=$qty;
277
            $line->subprice=$price;
278
            $line->remise_percent=$remise_percent;
279
            $line->tva_tx=$tva_tx;
280
281
            $this->lines[]=$line;
282
        }
283
    }
284
285
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
286
    /**
287
     *	Adding line of fixed discount in the proposal in DB
288
     *
289
     *	@param     int		$idremise			Id of fixed discount
290
     *  @return    int          				>0 if OK, <0 if KO
291
     */
292
    public function insert_discount($idremise)
293
    {
294
        // phpcs:enable
295
        global $langs;
296
297
        include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
298
        include_once DOL_DOCUMENT_ROOT.'/core/class/discount.class.php';
299
300
        $this->db->begin();
301
302
        $remise=new DiscountAbsolute($this->db);
303
        $result=$remise->fetch($idremise);
304
305
        if ($result > 0)
306
        {
307
            if ($remise->fk_facture)	// Protection against multiple submission
308
            {
309
                $this->error=$langs->trans("ErrorDiscountAlreadyUsed");
310
                $this->db->rollback();
311
                return -5;
312
            }
313
314
            $supplier_proposalligne=new SupplierProposalLine($this->db);
315
            $supplier_proposalligne->fk_supplier_proposal=$this->id;
316
            $supplier_proposalligne->fk_remise_except=$remise->id;
317
            $supplier_proposalligne->desc=$remise->description;   	// Description ligne
318
            $supplier_proposalligne->tva_tx=$remise->tva_tx;
319
            $supplier_proposalligne->subprice=-$remise->amount_ht;
320
            $supplier_proposalligne->fk_product=0;					// Id produit predefini
321
            $supplier_proposalligne->qty=1;
322
            $supplier_proposalligne->remise=0;
1 ignored issue
show
Deprecated Code introduced by
The property SupplierProposalLine::$remise has been deprecated. ( Ignorable by Annotation )

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

322
            /** @scrutinizer ignore-deprecated */ $supplier_proposalligne->remise=0;
Loading history...
323
            $supplier_proposalligne->remise_percent=0;
324
            $supplier_proposalligne->rang=-1;
325
            $supplier_proposalligne->info_bits=2;
326
327
            // TODO deprecated
328
            $supplier_proposalligne->price=-$remise->amount_ht;
1 ignored issue
show
Deprecated Code introduced by
The property SupplierProposalLine::$price has been deprecated. ( Ignorable by Annotation )

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

328
            /** @scrutinizer ignore-deprecated */ $supplier_proposalligne->price=-$remise->amount_ht;
Loading history...
329
330
            $supplier_proposalligne->total_ht  = -$remise->amount_ht;
331
            $supplier_proposalligne->total_tva = -$remise->amount_tva;
332
            $supplier_proposalligne->total_ttc = -$remise->amount_ttc;
333
334
            $result=$supplier_proposalligne->insert();
335
            if ($result > 0)
336
            {
337
                $result=$this->update_price(1);
338
                if ($result > 0)
339
                {
340
                    $this->db->commit();
341
                    return 1;
342
                }
343
                else
344
                {
345
                    $this->db->rollback();
346
                    return -1;
347
                }
348
            }
349
            else
350
            {
351
                $this->error=$supplier_proposalligne->error;
352
                $this->db->rollback();
353
                return -2;
354
            }
355
        }
356
        else
357
        {
358
            $this->db->rollback();
359
            return -2;
360
        }
361
    }
362
363
    /**
364
     *    	Add a proposal line into database (linked to product/service or not)
365
     * 		Les parametres sont deja cense etre juste et avec valeurs finales a l'appel
366
     *		de cette methode. Aussi, pour le taux tva, il doit deja avoir ete defini
367
     *		par l'appelant par la methode get_default_tva(societe_vendeuse,societe_acheteuse,'',produit)
368
     *		et le desc doit deja avoir la bonne valeur (a l'appelant de gerer le multilangue)
369
     *
370
     * 		@param    	string		$desc				Description de la ligne
371
     * 		@param    	double		$pu_ht				Prix unitaire
372
     * 		@param    	double		$qty             	Quantite
373
     * 		@param    	double		$txtva           	Taux de tva
374
     * 		@param		double		$txlocaltax1		Local tax 1 rate
375
     *  	@param		double		$txlocaltax2		Local tax 2 rate
376
     *		@param    	int			$fk_product      	Product/Service ID predefined
377
     * 		@param    	double		$remise_percent  	Percentage discount of the line
378
     * 		@param    	string		$price_base_type	HT or TTC
379
     * 		@param    	double		$pu_ttc             Prix unitaire TTC
380
     * 		@param    	int			$info_bits			Bits of type of lines
381
     *      @param      int			$type               Type of line (product, service)
382
     *      @param      int			$rang               Position of line
383
     *      @param		int			$special_code		Special code (also used by externals modules!)
384
     *      @param		int			$fk_parent_line		Id of parent line
385
     *      @param		int			$fk_fournprice		Id supplier price
386
     *      @param		int			$pa_ht				Buying price without tax
387
     *      @param		string		$label				???
388
     *      @param		array		$array_option		extrafields array
389
     * 		@param		string		$ref_supplier			Supplier price reference
390
     * 		@param		int			$fk_unit			Id of the unit to use.
391
     * 		@param		string		$origin				'order', 'supplier_proposal', ...
392
     * 		@param		int			$origin_id			Id of origin line
393
     * 		@param		double		$pu_ht_devise		Amount in currency
394
     *    	@return    	int         	    			>0 if OK, <0 if KO
395
     *
396
     *    	@see       	add_product()
397
     */
398
    public function addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1 = 0, $txlocaltax2 = 0, $fk_product = 0, $remise_percent = 0, $price_base_type = 'HT', $pu_ttc = 0, $info_bits = 0, $type = 0, $rang = -1, $special_code = 0, $fk_parent_line = 0, $fk_fournprice = 0, $pa_ht = 0, $label = '', $array_option = 0, $ref_supplier = '', $fk_unit = '', $origin = '', $origin_id = 0, $pu_ht_devise = 0)
399
    {
400
        global $mysoc, $conf;
401
402
        dol_syslog(get_class($this)."::addline supplier_proposalid=$this->id, desc=$desc, pu_ht=$pu_ht, qty=$qty, txtva=$txtva, fk_product=$fk_product, remise_except=$remise_percent, price_base_type=$price_base_type, pu_ttc=$pu_ttc, info_bits=$info_bits, type=$type");
403
        include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
404
405
        // Clean parameters
406
        if (empty($remise_percent)) $remise_percent=0;
407
        if (empty($qty)) $qty=0;
408
        if (empty($info_bits)) $info_bits=0;
409
        if (empty($rang)) $rang=0;
410
        if (empty($fk_parent_line) || $fk_parent_line < 0) $fk_parent_line=0;
411
        if (empty($pu_ht)) $pu_ht=0;
412
413
        $remise_percent=price2num($remise_percent);
414
        $qty=price2num($qty);
415
        $pu_ht=price2num($pu_ht);
416
        $pu_ttc=price2num($pu_ttc);
417
        $txtva=price2num($txtva);
418
        $txlocaltax1=price2num($txlocaltax1);
419
        $txlocaltax2=price2num($txlocaltax2);
420
            $pa_ht=price2num($pa_ht);
421
        if ($price_base_type=='HT')
422
        {
423
            $pu=$pu_ht;
424
        }
425
        else
426
        {
427
            $pu=$pu_ttc;
428
        }
429
430
        // Check parameters
431
        if ($type < 0) return -1;
432
433
        if ($this->statut == self::STATUS_DRAFT)
434
        {
435
            $this->db->begin();
436
437
            if ($fk_product > 0)
438
            {
439
                if (! empty($conf->global->SUPPLIER_PROPOSAL_WITH_PREDEFINED_PRICES_ONLY))
440
                {
441
                    // Check quantity is enough
442
                    dol_syslog(get_class($this)."::addline we check supplier prices fk_product=".$fk_product." fk_fournprice=".$fk_fournprice." qty=".$qty." ref_supplier=".$ref_supplier);
443
                    $prod = new Product($this->db, $fk_product);
1 ignored issue
show
Unused Code introduced by
The call to Product::__construct() has too many arguments starting with $fk_product. ( Ignorable by Annotation )

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

443
                    $prod = /** @scrutinizer ignore-call */ new Product($this->db, $fk_product);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
444
                    if ($prod->fetch($fk_product) > 0)
445
                    {
446
                        $product_type = $prod->type;
447
                        $label = $prod->label;
448
                        $fk_prod_fourn_price = $fk_fournprice;
449
450
                        // We use 'none' instead of $ref_supplier, because fourn_ref may not exists anymore. So we will take the first supplier price ok.
451
                        // If we want a dedicated supplier price, we must provide $fk_prod_fourn_price.
452
                        $result=$prod->get_buyprice($fk_prod_fourn_price, $qty, $fk_product, 'none', ($this->fk_soc?$this->fk_soc:$this->socid));   // Search on couple $fk_prod_fourn_price/$qty first, then on triplet $qty/$fk_product/$ref_supplier/$this->fk_soc
453
                        if ($result > 0)
454
                        {
455
                            $pu = $prod->fourn_pu;       // Unit price supplier price set by get_buyprice
456
                            $ref_supplier = $prod->ref_supplier;   // Ref supplier price set by get_buyprice
457
                            // is remise percent not keyed but present for the product we add it
458
                            if ($remise_percent == 0 && $prod->remise_percent !=0)
459
                                $remise_percent =$prod->remise_percent;
460
                        }
461
                        if ($result == 0)                   // If result == 0, we failed to found the supplier reference price
462
                        {
463
                            $langs->load("errors");
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
464
                            $this->error = "Ref " . $prod->ref . " " . $langs->trans("ErrorQtyTooLowForThisSupplier");
465
                            $this->db->rollback();
466
                            dol_syslog(get_class($this)."::addline we did not found supplier price, so we can't guess unit price");
467
                            //$pu    = $prod->fourn_pu;     // We do not overwrite unit price
468
                            //$ref   = $prod->ref_fourn;    // We do not overwrite ref supplier price
469
                            return -1;
470
                        }
471
                        if ($result == -1)
472
                        {
473
                            $langs->load("errors");
474
                            $this->error = "Ref " . $prod->ref . " " . $langs->trans("ErrorQtyTooLowForThisSupplier");
475
                            $this->db->rollback();
476
                            dol_syslog(get_class($this)."::addline result=".$result." - ".$this->error, LOG_DEBUG);
477
                            return -1;
478
                        }
479
                        if ($result < -1)
480
                        {
481
                            $this->error=$prod->error;
482
                            $this->db->rollback();
483
                            dol_syslog(get_class($this)."::addline result=".$result." - ".$this->error, LOG_ERR);
484
                            return -1;
485
                        }
486
                    }
487
                    else
488
                    {
489
                        $this->error=$prod->error;
490
                        $this->db->rollback();
491
                        return -1;
492
                    }
493
                }
494
            }
495
            else
496
            {
497
                $product_type = $type;
498
            }
499
500
            // Calcul du total TTC et de la TVA pour la ligne a partir de
501
            // qty, pu, remise_percent et txtva
502
            // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
503
            // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
504
505
            $localtaxes_type=getLocalTaxesFromRate($txtva, 0, $this->thirdparty, $mysoc);
506
            $txtva = preg_replace('/\s*\(.*\)/', '', $txtva);  // Remove code into vatrate.
507
508
            if ($conf->multicurrency->enabled && $pu_ht_devise > 0) {
509
                $pu = 0;
510
            }
511
512
            $tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $this->thirdparty, $localtaxes_type, 100, $this->multicurrency_tx, $pu_ht_devise);
513
            $total_ht  = $tabprice[0];
514
            $total_tva = $tabprice[1];
515
            $total_ttc = $tabprice[2];
516
            $total_localtax1 = $tabprice[9];
517
            $total_localtax2 = $tabprice[10];
518
            $pu = $pu_ht = $tabprice[3];
519
520
            // MultiCurrency
521
            $multicurrency_total_ht  = $tabprice[16];
522
            $multicurrency_total_tva = $tabprice[17];
523
            $multicurrency_total_ttc = $tabprice[18];
524
            $pu_ht_devise = $tabprice[19];
525
526
            // Rang to use
527
            $rangtouse = $rang;
528
            if ($rangtouse == -1)
529
            {
530
                $rangmax = $this->line_max($fk_parent_line);
531
                $rangtouse = $rangmax + 1;
532
            }
533
534
            // TODO A virer
535
            // Anciens indicateurs: $price, $remise (a ne plus utiliser)
536
            $price = $pu;
537
            $remise = 0;
538
            if ($remise_percent > 0)
539
            {
540
                $remise = round(($pu * $remise_percent / 100), 2);
541
                $price = $pu - $remise;
542
            }
543
544
            // Insert line
545
            $this->line=new SupplierProposalLine($this->db);
546
547
            $this->line->fk_supplier_proposal=$this->id;
548
            $this->line->label=$label;
549
            $this->line->desc=$desc;
550
            $this->line->qty=$qty;
551
            $this->line->tva_tx=$txtva;
552
            $this->line->localtax1_tx=($total_localtax1?$localtaxes_type[1]:0);
553
            $this->line->localtax2_tx=($total_localtax2?$localtaxes_type[3]:0);
554
            $this->line->localtax1_type = $localtaxes_type[0];
555
            $this->line->localtax2_type = $localtaxes_type[2];
556
            $this->line->fk_product=$fk_product;
557
            $this->line->remise_percent=$remise_percent;
558
            $this->line->subprice=$pu_ht;
559
            $this->line->rang=$rangtouse;
560
            $this->line->info_bits=$info_bits;
561
            $this->line->total_ht=$total_ht;
562
            $this->line->total_tva=$total_tva;
563
            $this->line->total_localtax1=$total_localtax1;
564
            $this->line->total_localtax2=$total_localtax2;
565
            $this->line->total_ttc=$total_ttc;
566
            $this->line->product_type=$type;
567
            $this->line->special_code=$special_code;
568
            $this->line->fk_parent_line=$fk_parent_line;
569
            $this->line->fk_unit=$fk_unit;
570
            $this->line->origin=$origin;
571
            $this->line->origin_id=$origin_id;
572
            $this->line->ref_fourn = $this->db->escape($ref_supplier);
573
574
            // infos marge
575
            if (!empty($fk_product) && empty($fk_fournprice) && empty($pa_ht)) {
576
                // by external module, take lowest buying price
577
                include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
578
                $productFournisseur = new ProductFournisseur($this->db);
579
                $productFournisseur->find_min_price_product_fournisseur($fk_product);
580
                $this->line->fk_fournprice = $productFournisseur->product_fourn_price_id;
581
            } else {
582
                $this->line->fk_fournprice = $fk_fournprice;
583
            }
584
            $this->line->pa_ht = $pa_ht;
585
586
            // Multicurrency
587
            $this->line->fk_multicurrency			= $this->fk_multicurrency;
588
            $this->line->multicurrency_code			= $this->multicurrency_code;
589
            $this->line->multicurrency_subprice		= $pu_ht_devise;
590
            $this->line->multicurrency_total_ht 	= $multicurrency_total_ht;
591
            $this->line->multicurrency_total_tva 	= $multicurrency_total_tva;
592
            $this->line->multicurrency_total_ttc 	= $multicurrency_total_ttc;
593
594
            // Mise en option de la ligne
595
            if (empty($qty) && empty($special_code)) $this->line->special_code=3;
596
597
            // TODO deprecated
598
            $this->line->price=$price;
1 ignored issue
show
Deprecated Code introduced by
The property SupplierProposalLine::$price has been deprecated. ( Ignorable by Annotation )

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

598
            /** @scrutinizer ignore-deprecated */ $this->line->price=$price;
Loading history...
599
            $this->line->remise=$remise;
1 ignored issue
show
Deprecated Code introduced by
The property SupplierProposalLine::$remise has been deprecated. ( Ignorable by Annotation )

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

599
            /** @scrutinizer ignore-deprecated */ $this->line->remise=$remise;
Loading history...
600
601
            if (is_array($array_option) && count($array_option)>0) {
602
                $this->line->array_options=$array_option;
603
            }
604
605
            $result=$this->line->insert();
606
            if ($result > 0)
607
            {
608
                // Reorder if child line
609
                if (! empty($fk_parent_line)) $this->line_order(true, 'DESC');
610
611
                // Mise a jour informations denormalisees au niveau de la propale meme
612
                $result=$this->update_price(1, 'auto', 0, $this->thirdparty);	// This method is designed to add line from user input so total calculation must be done using 'auto' mode.
613
                if ($result > 0)
614
                {
615
                    $this->db->commit();
616
                    return $this->line->rowid;
617
                }
618
                else
619
                {
620
                    $this->error=$this->db->error();
621
                    $this->db->rollback();
622
                    return -1;
623
                }
624
            }
625
            else
626
            {
627
                $this->error=$this->line->error;
628
                $this->db->rollback();
629
                return -2;
630
            }
631
        }
632
    }
633
634
635
    /**
636
     *  Update a proposal line
637
     *
638
     *  @param      int			$rowid           	Id de la ligne
639
     *  @param      double		$pu		     	  	Prix unitaire (HT ou TTC selon price_base_type)
640
     *  @param      double		$qty            	Quantity
641
     *  @param      double		$remise_percent  	Remise effectuee sur le produit
642
     *  @param      double		$txtva	          	Taux de TVA
643
     * 	@param	  	double		$txlocaltax1		Local tax 1 rate
644
     *  @param	  	double		$txlocaltax2		Local tax 2 rate
645
     *  @param      string		$desc            	Description
646
     *	@param	  	double		$price_base_type	HT ou TTC
647
     *	@param      int			$info_bits        	Miscellaneous informations
648
     *	@param		int			$special_code		Special code (also used by externals modules!)
649
     * 	@param		int			$fk_parent_line		Id of parent line (0 in most cases, used by modules adding sublevels into lines).
650
     * 	@param		int			$skip_update_total	Keep fields total_xxx to 0 (used for special lines by some modules)
651
     *  @param		int			$fk_fournprice		Id of origin supplier price
652
     *  @param		int			$pa_ht				Price (without tax) of product when it was bought
653
     *  @param		string		$label				???
654
     *  @param		int			$type				0/1=Product/service
655
     *  @param		array		$array_option		extrafields array
656
     * 	@param		string		$ref_supplier			Supplier price reference
657
     *	@param		int			$fk_unit			Id of the unit to use.
658
	 * 	@param		double		$pu_ht_devise		Unit price in currency
659
     *  @return     int     		        		0 if OK, <0 if KO
660
     */
661
    public function updateline($rowid, $pu, $qty, $remise_percent, $txtva, $txlocaltax1 = 0, $txlocaltax2 = 0, $desc = '', $price_base_type = 'HT', $info_bits = 0, $special_code = 0, $fk_parent_line = 0, $skip_update_total = 0, $fk_fournprice = 0, $pa_ht = 0, $label = '', $type = 0, $array_option = 0, $ref_supplier = '', $fk_unit = '', $pu_ht_devise = 0)
662
    {
663
        global $conf,$user,$langs, $mysoc;
664
665
        dol_syslog(get_class($this)."::updateLine $rowid, $pu, $qty, $remise_percent, $txtva, $desc, $price_base_type, $info_bits");
666
        include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
667
668
        // Clean parameters
669
        $remise_percent=price2num($remise_percent);
670
        $qty=price2num($qty);
671
        $pu = price2num($pu);
672
        $txtva = price2num($txtva);
673
        $txlocaltax1=price2num($txlocaltax1);
674
        $txlocaltax2=price2num($txlocaltax2);
675
        $pa_ht=price2num($pa_ht);
676
        if (empty($qty) && empty($special_code)) $special_code=3;    // Set option tag
677
        if (! empty($qty) && $special_code == 3) $special_code=0;    // Remove option tag
678
679
        if ($this->statut == 0)
680
        {
681
            $this->db->begin();
682
683
            // Calcul du total TTC et de la TVA pour la ligne a partir de
684
            // qty, pu, remise_percent et txtva
685
            // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
686
            // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
687
688
            $localtaxes_type=getLocalTaxesFromRate($txtva, 0, $mysoc, $this->thirdparty);
689
690
            // Clean vat code
691
            $vat_src_code='';
692
            if (preg_match('/\((.*)\)/', $txtva, $reg))
693
            {
694
            	$vat_src_code = $reg[1];
695
            	$txtva = preg_replace('/\s*\(.*\)/', '', $txtva);    // Remove code into vatrate.
696
            }
697
698
            $tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $this->thirdparty, $localtaxes_type, 100, $this->multicurrency_tx, $pu_ht_devise);
699
            $total_ht  = $tabprice[0];
700
            $total_tva = $tabprice[1];
701
            $total_ttc = $tabprice[2];
702
            $total_localtax1 = $tabprice[9];
703
            $total_localtax2 = $tabprice[10];
704
705
            // MultiCurrency
706
            $multicurrency_total_ht  = $tabprice[16];
707
            $multicurrency_total_tva = $tabprice[17];
708
            $multicurrency_total_ttc = $tabprice[18];
709
710
            // Anciens indicateurs: $price, $remise (a ne plus utiliser)
711
            $price = $pu;
712
            if ($remise_percent > 0)
713
            {
714
                $remise = round(($pu * $remise_percent / 100), 2);
715
                $price = $pu - $remise;
716
            }
717
718
            // Update line
719
            $this->line=new SupplierProposalLine($this->db);
720
721
            // Stock previous line records
722
            $staticline=new SupplierProposalLine($this->db);
723
            $staticline->fetch($rowid);
724
            $this->line->oldline = $staticline;
725
726
            // Reorder if fk_parent_line change
727
            if (! empty($fk_parent_line) && ! empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line)
728
            {
729
                $rangmax = $this->line_max($fk_parent_line);
730
                $this->line->rang = $rangmax + 1;
731
            }
732
733
            $this->line->rowid				= $rowid;
734
            $this->line->label				= $label;
735
            $this->line->desc				= $desc;
736
            $this->line->qty				= $qty;
737
            $this->line->product_type		= $type;
738
739
            $this->line->vat_src_code       = $vat_src_code;
0 ignored issues
show
Bug introduced by
The property vat_src_code does not seem to exist on SupplierProposalLine.
Loading history...
740
            $this->line->tva_tx				= $txtva;
741
            $this->line->localtax1_tx		= $txlocaltax1;
742
            $this->line->localtax2_tx		= $txlocaltax2;
743
            $this->line->localtax1_type		= $localtaxes_type[0];
744
            $this->line->localtax2_type		= $localtaxes_type[2];
745
            $this->line->remise_percent		= $remise_percent;
746
            $this->line->subprice			= $pu;
747
            $this->line->info_bits			= $info_bits;
748
            $this->line->total_ht			= $total_ht;
749
            $this->line->total_tva			= $total_tva;
750
            $this->line->total_localtax1	= $total_localtax1;
751
            $this->line->total_localtax2	= $total_localtax2;
752
            $this->line->total_ttc			= $total_ttc;
753
            $this->line->special_code		= $special_code;
754
            $this->line->fk_parent_line		= $fk_parent_line;
755
            $this->line->skip_update_total	= $skip_update_total;
756
            $this->line->ref_fourn			= $ref_supplier;
757
            $this->line->fk_unit			= $fk_unit;
758
759
            // infos marge
760
            if (!empty($fk_product) && empty($fk_fournprice) && empty($pa_ht)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $fk_product seems to never exist and therefore empty should always be true.
Loading history...
761
                // by external module, take lowest buying price
762
                include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
763
                $productFournisseur = new ProductFournisseur($this->db);
764
                $productFournisseur->find_min_price_product_fournisseur($fk_product);
765
                $this->line->fk_fournprice = $productFournisseur->product_fourn_price_id;
766
            } else {
767
                $this->line->fk_fournprice = $fk_fournprice;
768
            }
769
            $this->line->pa_ht = $pa_ht;
770
771
            // TODO deprecated
772
            $this->line->price=$price;
1 ignored issue
show
Deprecated Code introduced by
The property SupplierProposalLine::$price has been deprecated. ( Ignorable by Annotation )

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

772
            /** @scrutinizer ignore-deprecated */ $this->line->price=$price;
Loading history...
773
            $this->line->remise=$remise;
1 ignored issue
show
Comprehensibility Best Practice introduced by
The variable $remise does not seem to be defined for all execution paths leading up to this point.
Loading history...
Deprecated Code introduced by
The property SupplierProposalLine::$remise has been deprecated. ( Ignorable by Annotation )

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

773
            /** @scrutinizer ignore-deprecated */ $this->line->remise=$remise;
Loading history...
774
775
            if (is_array($array_option) && count($array_option)>0) {
776
                $this->line->array_options=$array_option;
777
            }
778
779
            // Multicurrency
780
            $this->line->multicurrency_subprice		= price2num($pu * $this->multicurrency_tx);
781
            $this->line->multicurrency_total_ht 	= $multicurrency_total_ht;
782
            $this->line->multicurrency_total_tva 	= $multicurrency_total_tva;
783
            $this->line->multicurrency_total_ttc 	= $multicurrency_total_ttc;
784
785
            $result=$this->line->update();
786
            if ($result > 0)
787
            {
788
                // Reorder if child line
789
                if (! empty($fk_parent_line)) $this->line_order(true, 'DESC');
790
791
                $this->update_price(1);
792
793
                $this->fk_supplier_proposal = $this->id;
794
                $this->rowid = $rowid;
795
796
                $this->db->commit();
797
                return $result;
798
            }
799
            else
800
            {
801
                $this->error=$this->db->error();
802
                $this->db->rollback();
803
                return -1;
804
            }
805
        }
806
        else
807
        {
808
            dol_syslog(get_class($this)."::updateline Erreur -2 SupplierProposal en mode incompatible pour cette action");
809
            return -2;
810
        }
811
    }
812
813
814
    /**
815
     *  Delete detail line
816
     *
817
     *  @param		int		$lineid			Id of line to delete
818
     *  @return     int         			>0 if OK, <0 if KO
819
     */
820
    public function deleteline($lineid)
821
    {
822
        if ($this->statut == 0)
823
        {
824
            $line=new SupplierProposalLine($this->db);
825
826
            // For triggers
827
            $line->fetch($lineid);
828
829
            if ($line->delete() > 0)
830
            {
831
                $this->update_price(1);
832
833
                return 1;
834
            }
835
            else
836
            {
837
                return -1;
838
            }
839
        }
840
        else
841
        {
842
            return -2;
843
        }
844
    }
845
846
847
    /**
848
     *  Create commercial proposal into database
849
     * 	this->ref can be set or empty. If empty, we will use "(PROVid)"
850
     *
851
     * 	@param		User	$user		User that create
852
     * 	@param		int		$notrigger	1=Does not execute triggers, 0= execute triggers
853
     *  @return     int     			<0 if KO, >=0 if OK
854
     */
855
    public function create($user, $notrigger = 0)
856
    {
857
        global $langs, $conf, $mysoc, $hookmanager;
858
        $error=0;
859
860
        $now=dol_now();
861
862
        dol_syslog(get_class($this)."::create");
863
864
        // Check parameters
865
        $result=$this->fetch_thirdparty();
866
        if ($result < 0)
867
        {
868
            $this->error="Failed to fetch company";
869
            dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
870
            return -3;
871
        }
872
873
        // Check parameters
874
        if (! empty($this->ref))	// We check that ref is not already used
875
        {
876
            $result=self::isExistingObject($this->element, 0, $this->ref);	// Check ref is not yet used
877
            if ($result > 0)
878
            {
879
                $this->error='ErrorRefAlreadyExists';
880
                dol_syslog(get_class($this)."::create ".$this->error, LOG_WARNING);
881
                $this->db->rollback();
882
                return -1;
883
            }
884
        }
885
886
        // Multicurrency
887
        if (!empty($this->multicurrency_code)) list($this->fk_multicurrency,$this->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code);
888
        if (empty($this->fk_multicurrency))
889
        {
890
            $this->multicurrency_code = $conf->currency;
891
            $this->fk_multicurrency = 0;
892
            $this->multicurrency_tx = 1;
893
        }
894
895
        $this->db->begin();
896
897
        // Insert into database
898
        $sql = "INSERT INTO ".MAIN_DB_PREFIX."supplier_proposal (";
899
        $sql.= "fk_soc";
900
        $sql.= ", price";
901
        $sql.= ", remise";
902
        $sql.= ", remise_percent";
903
        $sql.= ", remise_absolue";
904
        $sql.= ", tva";
905
        $sql.= ", total";
906
        $sql.= ", datec";
907
        $sql.= ", ref";
908
        $sql.= ", fk_user_author";
909
        $sql.= ", note_private";
910
        $sql.= ", note_public";
911
        $sql.= ", model_pdf";
912
        $sql.= ", fk_cond_reglement";
913
        $sql.= ", fk_mode_reglement";
914
        $sql.= ", fk_account";
915
        $sql.= ", date_livraison";
916
        $sql.= ", fk_shipping_method";
917
        $sql.= ", fk_projet";
918
        $sql.= ", entity";
919
        $sql.= ", fk_multicurrency";
920
        $sql.= ", multicurrency_code";
921
        $sql.= ", multicurrency_tx";
922
        $sql.= ") ";
923
        $sql.= " VALUES (";
924
        $sql.= $this->socid;
925
        $sql.= ", 0";
926
        $sql.= ", ".$this->remise;
927
        $sql.= ", ".($this->remise_percent?$this->db->escape($this->remise_percent):'null');
928
        $sql.= ", ".($this->remise_absolue?$this->db->escape($this->remise_absolue):'null');
929
        $sql.= ", 0";
930
        $sql.= ", 0";
931
        $sql.= ", '".$this->db->idate($now)."'";
932
        $sql.= ", '(PROV)'";
933
        $sql.= ", ".($user->id > 0 ? "'".$user->id."'":"null");
934
        $sql.= ", '".$this->db->escape($this->note_private)."'";
935
        $sql.= ", '".$this->db->escape($this->note_public)."'";
936
        $sql.= ", '".$this->db->escape($this->modelpdf)."'";
937
        $sql.= ", ".($this->cond_reglement_id > 0 ? $this->cond_reglement_id : 'NULL');
938
        $sql.= ", ".($this->mode_reglement_id > 0 ? $this->mode_reglement_id : 'NULL');
939
        $sql.= ", ".($this->fk_account>0?$this->fk_account:'NULL');
940
        $sql.= ", ".($this->date_livraison!=''?"'".$this->db->idate($this->date_livraison)."'":"null");
941
        $sql.= ", ".($this->shipping_method_id>0?$this->shipping_method_id:'NULL');
942
        $sql.= ", ".($this->fk_project?$this->fk_project:"null");
943
        $sql.= ", ".$conf->entity;
944
        $sql.= ", ".(int) $this->fk_multicurrency;
945
        $sql.= ", '".$this->db->escape($this->multicurrency_code)."'";
946
        $sql.= ", ".(double) $this->multicurrency_tx;
947
        $sql.= ")";
948
949
        dol_syslog(get_class($this)."::create", LOG_DEBUG);
950
        $resql=$this->db->query($sql);
951
        if ($resql)
952
        {
953
            $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."supplier_proposal");
954
955
            if ($this->id)
956
            {
957
                $this->ref='(PROV'.$this->id.')';
958
                $sql = 'UPDATE '.MAIN_DB_PREFIX."supplier_proposal SET ref='".$this->db->escape($this->ref)."' WHERE rowid=".$this->id;
959
960
                dol_syslog(get_class($this)."::create", LOG_DEBUG);
961
                $resql=$this->db->query($sql);
962
                if (! $resql) $error++;
963
964
                if (! empty($this->linkedObjectsIds) && empty($this->linked_objects))	// To use new linkedObjectsIds instead of old linked_objects
965
                {
966
                    $this->linked_objects = $this->linkedObjectsIds;	// TODO Replace linked_objects with linkedObjectsIds
967
                }
968
969
                // Add object linked
970
                if (! $error && $this->id && is_array($this->linked_objects) && ! empty($this->linked_objects))
971
                {
972
                    foreach($this->linked_objects as $origin => $tmp_origin_id)
973
                    {
974
                        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, ...))
975
                        {
976
                            foreach($tmp_origin_id as $origin_id)
977
                            {
978
                                $ret = $this->add_object_linked($origin, $origin_id);
979
                                if (! $ret)
980
                                {
981
                                    dol_print_error($this->db);
982
                                    $error++;
983
                                }
984
                            }
985
                        }
986
                    }
987
                }
988
989
                // Add linked object (deprecated, use ->linkedObjectsIds instead)
990
                if (! $error && $this->origin && $this->origin_id)
991
                {
992
                    $ret = $this->add_object_linked();
993
                    if (! $ret)	dol_print_error($this->db);
994
                }
995
996
                /*
997
                 *  Insertion du detail des produits dans la base
998
                 */
999
                if (! $error)
1000
                {
1001
                    $fk_parent_line=0;
1002
                    $num=count($this->lines);
1003
1004
                    for ($i=0;$i<$num;$i++)
1005
                    {
1006
                        // Reset fk_parent_line for no child products and special product
1007
                        if (($this->lines[$i]->product_type != 9 && empty($this->lines[$i]->fk_parent_line)) || $this->lines[$i]->product_type == 9) {
1008
                            $fk_parent_line = 0;
1009
                        }
1010
1011
                        $result = $this->addline(
1012
                            $this->lines[$i]->desc,
1013
                            $this->lines[$i]->subprice,
1014
                            $this->lines[$i]->qty,
1015
                            $this->lines[$i]->tva_tx,
1016
                            $this->lines[$i]->localtax1_tx,
1017
                            $this->lines[$i]->localtax2_tx,
1018
                            $this->lines[$i]->fk_product,
1019
                            $this->lines[$i]->remise_percent,
1020
                            'HT',
1021
                            0,
1022
                            0,
1023
                            $this->lines[$i]->product_type,
1024
                            $this->lines[$i]->rang,
1025
                            $this->lines[$i]->special_code,
1026
                            $fk_parent_line,
1027
                            $this->lines[$i]->fk_fournprice,
1028
                            $this->lines[$i]->pa_ht,
1029
                            $this->lines[$i]->label,
1030
                            $this->lines[$i]->array_options,
1031
                            $this->lines[$i]->ref_fourn,
1032
                            $this->lines[$i]->fk_unit,
1033
                            'supplier_proposal',
1034
                            $this->lines[$i]->rowid
1035
                        );
1036
1037
                        if ($result < 0)
1038
                        {
1039
                            $error++;
1040
                            $this->error=$this->db->error;
1041
                            dol_print_error($this->db);
1042
                            break;
1043
                        }
1044
                        // Defined the new fk_parent_line
1045
                        if ($result > 0 && $this->lines[$i]->product_type == 9) {
1046
                            $fk_parent_line = $result;
1047
                        }
1048
                    }
1049
                }
1050
1051
                if (! $error)
1052
                {
1053
                    // Mise a jour infos denormalisees
1054
                    $resql=$this->update_price(1);
1055
                    if ($resql)
1056
                    {
1057
                        $action='update';
1058
1059
                        // Actions on extra fields
1060
                        if (! $error && empty($conf->global->MAIN_EXTRAFIELDS_DISABLED))
1061
                        {
1062
                            $result=$this->insertExtraFields();
1063
                            if ($result < 0)
1064
                            {
1065
                                $error++;
1066
                            }
1067
                        }
1068
1069
                        if (! $error && ! $notrigger)
1070
                        {
1071
                            // Call trigger
1072
                            $result=$this->call_trigger('PROPAL_SUPPLIER_CREATE', $user);
1073
                            if ($result < 0) { $error++; }
1074
                            // End call triggers
1075
                        }
1076
                    }
1077
                    else
1078
                    {
1079
                        $this->error=$this->db->lasterror();
1080
                        $error++;
1081
                    }
1082
                }
1083
            }
1084
            else
1085
            {
1086
                $this->error=$this->db->lasterror();
1087
                $error++;
1088
            }
1089
1090
            if (! $error)
1091
            {
1092
                $this->db->commit();
1093
                dol_syslog(get_class($this)."::create done id=".$this->id);
1094
                return $this->id;
1095
            }
1096
            else
1097
            {
1098
                $this->db->rollback();
1099
                return -2;
1100
            }
1101
        }
1102
        else
1103
        {
1104
            $this->error=$this->db->lasterror();
1105
            $this->db->rollback();
1106
            return -1;
1107
        }
1108
    }
1109
1110
1111
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1112
    /**
1113
     *	Insert into DB a supplier_proposal object completely defined by its data members (ex, results from copy).
1114
     *
1115
     *	@param 		User	$user	User that create
1116
     *	@return    	int				Id of the new object if ok, <0 if ko
1117
     *	@see       	create()
1118
     */
1119
    public function create_from($user)
1120
    {
1121
        // phpcs:enable
1122
        $this->products=$this->lines;
1123
1124
        return $this->create($user);
1125
    }
1126
1127
    /**
1128
     *		Load an object from its id and create a new one in database
1129
     *
1130
	 *      @param	    User	$user		    User making the clone
1131
     *		@param		int		$fromid			Id of thirdparty
1132
     * 	 	@return		int						New id of clone
1133
     */
1134
    public function createFromClone(User $user, $fromid = 0)
1135
    {
1136
        global $conf,$hookmanager;
1137
1138
        $error=0;
1139
        $now=dol_now();
1140
1141
        $this->db->begin();
1142
1143
        // get extrafields so they will be clone
1144
        foreach($this->lines as $line)
1145
            $line->fetch_optionals();
1146
1147
        // Load source object
1148
        $objFrom = clone $this;
1149
1150
        $objsoc=new Societe($this->db);
1151
1152
        // Change socid if needed
1153
        if (! empty($fromid) && $fromid != $this->socid)
1154
        {
1155
            if ($objsoc->fetch($fromid) > 0)
1156
            {
1157
                $this->socid 				= $objsoc->id;
1158
                $this->cond_reglement_id	= (! empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
1159
                $this->mode_reglement_id	= (! empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
1160
                $this->fk_project			= '';
1 ignored issue
show
Documentation Bug introduced by
The property $fk_project was declared of type integer, but '' is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
1161
            }
1162
1163
            // TODO Change product price if multi-prices
1164
        }
1165
        else
1166
        {
1167
            $objsoc->fetch($this->socid);
1168
        }
1169
1170
        $this->id=0;
1171
        $this->statut=0;
1172
1173
        if (empty($conf->global->SUPPLIER_PROPOSAL_ADDON) || ! is_readable(DOL_DOCUMENT_ROOT ."/core/modules/supplier_proposal/".$conf->global->SUPPLIER_PROPOSAL_ADDON.".php"))
1174
        {
1175
            $this->error='ErrorSetupNotComplete';
1176
            return -1;
1177
        }
1178
1179
        // Clear fields
1180
        $this->user_author	= $user->id;
1181
        $this->user_valid	= '';
1182
        $this->date			= $now;
1183
1184
        // Set ref
1185
        require_once DOL_DOCUMENT_ROOT ."/core/modules/supplier_proposal/".$conf->global->SUPPLIER_PROPOSAL_ADDON.'.php';
1186
        $obj = $conf->global->SUPPLIER_PROPOSAL_ADDON;
1187
        $modSupplierProposal = new $obj;
1188
        $this->ref = $modSupplierProposal->getNextValue($objsoc, $this);
1189
1190
        // Create clone
1191
        $this->context['createfromclone'] = 'createfromclone';
1192
        $result=$this->create($user);
1193
        if ($result < 0) $error++;
1194
1195
        if (! $error)
1196
        {
1197
            // Hook of thirdparty module
1198
            if (is_object($hookmanager))
1199
            {
1200
                $parameters=array('objFrom'=>$objFrom);
1201
                $action='';
1202
                $reshook=$hookmanager->executeHooks('createFrom', $parameters, $this, $action);    // Note that $action and $object may have been modified by some hooks
1203
                if ($reshook < 0) $error++;
1204
            }
1205
        }
1206
1207
        unset($this->context['createfromclone']);
1208
1209
        // End
1210
        if (! $error)
1211
        {
1212
            $this->db->commit();
1213
            return $this->id;
1214
        }
1215
        else
1216
        {
1217
            $this->db->rollback();
1218
            return -1;
1219
        }
1220
    }
1221
1222
    /**
1223
     *	Load a proposal from database and its ligne array
1224
     *
1225
     *	@param      int			$rowid		id of object to load
1226
     *	@param		string		$ref		Ref of proposal
1227
     *	@return     int         			>0 if OK, <0 if KO
1228
     */
1229
    public function fetch($rowid, $ref = '')
1230
    {
1231
        global $conf;
1232
1233
        $sql = "SELECT p.rowid, p.entity, p.ref, p.remise, p.remise_percent, p.remise_absolue, p.fk_soc";
1234
        $sql.= ", p.total, p.tva, p.localtax1, p.localtax2, p.total_ht";
1235
        $sql.= ", p.datec";
1236
        $sql.= ", p.date_valid as datev";
1237
        $sql.= ", p.date_livraison as date_livraison";
1238
        $sql.= ", p.model_pdf, p.extraparams";
1239
        $sql.= ", p.note_private, p.note_public";
1240
        $sql.= ", p.fk_projet as fk_project, p.fk_statut";
1241
        $sql.= ", p.fk_user_author, p.fk_user_valid, p.fk_user_cloture";
1242
        $sql.= ", p.fk_cond_reglement";
1243
        $sql.= ", p.fk_mode_reglement";
1244
        $sql.= ', p.fk_account';
1245
        $sql.= ", p.fk_shipping_method";
1246
        $sql.= ", p.fk_multicurrency, p.multicurrency_code, p.multicurrency_tx, p.multicurrency_total_ht, p.multicurrency_total_tva, p.multicurrency_total_ttc";
1247
        $sql.= ", c.label as statut_label";
1248
        $sql.= ", cr.code as cond_reglement_code, cr.libelle as cond_reglement, cr.libelle_facture as cond_reglement_libelle_doc";
1249
        $sql.= ", cp.code as mode_reglement_code, cp.libelle as mode_reglement";
1250
        $sql.= " FROM ".MAIN_DB_PREFIX."c_propalst as c, ".MAIN_DB_PREFIX."supplier_proposal as p";
1251
        $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as cp ON p.fk_mode_reglement = cp.id';
1252
        $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_payment_term as cr ON p.fk_cond_reglement = cr.rowid';
1253
        $sql.= " WHERE p.fk_statut = c.id";
1254
        $sql.= " AND p.entity IN (".getEntity('supplier_proposal').")";
1255
        if ($ref) $sql.= " AND p.ref='".$ref."'";
1256
        else $sql.= " AND p.rowid=".$rowid;
1257
1258
        dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
1259
        $resql=$this->db->query($sql);
1260
        if ($resql)
1261
        {
1262
            if ($this->db->num_rows($resql))
1263
            {
1264
                $obj = $this->db->fetch_object($resql);
1265
1266
                $this->id                   = $obj->rowid;
1267
                $this->entity               = $obj->entity;
1268
1269
                $this->ref                  = $obj->ref;
1270
                $this->remise               = $obj->remise;
1271
                $this->remise_percent       = $obj->remise_percent;
1272
                $this->remise_absolue       = $obj->remise_absolue;
1273
                $this->total                = $obj->total; // TODO deprecated
1274
                $this->total_ht             = $obj->total_ht;
1275
                $this->total_tva            = $obj->tva;
1276
                $this->total_localtax1		= $obj->localtax1;
1277
                $this->total_localtax2		= $obj->localtax2;
1278
                $this->total_ttc            = $obj->total;
1279
                $this->socid                = $obj->fk_soc;
1280
                $this->fk_project           = $obj->fk_project;
1281
                $this->modelpdf             = $obj->model_pdf;
1282
                $this->note                 = $obj->note_private; // TODO deprecated
1283
                $this->note_private         = $obj->note_private;
1284
                $this->note_public          = $obj->note_public;
1285
                $this->statut               = (int) $obj->fk_statut;
1286
                $this->statut_libelle       = $obj->statut_label;
1287
                $this->datec                = $this->db->jdate($obj->datec); // TODO deprecated
1288
                $this->datev                = $this->db->jdate($obj->datev); // TODO deprecated
1289
                $this->date_creation		= $this->db->jdate($obj->datec); //Creation date
1290
                $this->date_validation		= $this->db->jdate($obj->datev); //Validation date
1291
                $this->date_livraison       = $this->db->jdate($obj->date_livraison);
1292
                $this->shipping_method_id   = ($obj->fk_shipping_method>0)?$obj->fk_shipping_method:null;
1293
1294
                $this->mode_reglement_id    = $obj->fk_mode_reglement;
1295
                $this->mode_reglement_code  = $obj->mode_reglement_code;
1296
                $this->mode_reglement       = $obj->mode_reglement;
1297
                $this->fk_account           = ($obj->fk_account>0)?$obj->fk_account:null;
1298
                $this->cond_reglement_id    = $obj->fk_cond_reglement;
1299
                $this->cond_reglement_code  = $obj->cond_reglement_code;
1300
                $this->cond_reglement       = $obj->cond_reglement;
1301
                $this->cond_reglement_doc   = $obj->cond_reglement_libelle_doc;
1302
1303
                $this->extraparams			= (array) json_decode($obj->extraparams, true);
1304
1305
                $this->user_author_id = $obj->fk_user_author;
1306
                $this->user_valid_id  = $obj->fk_user_valid;
1307
                $this->user_close_id  = $obj->fk_user_cloture;
1308
1309
                // Multicurrency
1310
                $this->fk_multicurrency 		= $obj->fk_multicurrency;
1311
                $this->multicurrency_code 		= $obj->multicurrency_code;
1312
                $this->multicurrency_tx 		= $obj->multicurrency_tx;
1313
                $this->multicurrency_total_ht 	= $obj->multicurrency_total_ht;
1314
                $this->multicurrency_total_tva 	= $obj->multicurrency_total_tva;
1315
                $this->multicurrency_total_ttc 	= $obj->multicurrency_total_ttc;
1316
1317
                if ($obj->fk_statut == 0)
1318
                {
1319
                    $this->brouillon = 1;
1320
                }
1321
1322
                // Retreive all extrafield
1323
                // fetch optionals attributes and labels
1324
                $this->fetch_optionals();
1325
1326
                $this->db->free($resql);
1327
1328
                $this->lines = array();
1329
1330
                // Lines of supplier proposals
1331
                $sql = "SELECT d.rowid, d.fk_supplier_proposal, d.fk_parent_line, d.label as custom_label, d.description, d.price, d.tva_tx, d.localtax1_tx, d.localtax2_tx, d.qty, d.fk_remise_except, d.remise_percent, d.subprice, d.fk_product,";
1332
                $sql.= " d.info_bits, d.total_ht, d.total_tva, d.total_localtax1, d.total_localtax2, d.total_ttc, d.fk_product_fournisseur_price as fk_fournprice, d.buy_price_ht as pa_ht, d.special_code, d.rang, d.product_type,";
1333
                $sql.= ' p.ref as product_ref, p.description as product_desc, p.fk_product_type, p.label as product_label,';
1334
                $sql.= ' d.ref_fourn as ref_produit_fourn,';
1335
                $sql.= ' d.fk_multicurrency, d.multicurrency_code, d.multicurrency_subprice, d.multicurrency_total_ht, d.multicurrency_total_tva, d.multicurrency_total_ttc, d.fk_unit';
1336
                $sql.= " FROM ".MAIN_DB_PREFIX."supplier_proposaldet as d";
1337
                $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON d.fk_product = p.rowid";
1338
                $sql.= " WHERE d.fk_supplier_proposal = ".$this->id;
1339
                $sql.= " ORDER by d.rang";
1340
1341
                $result = $this->db->query($sql);
1342
                if ($result)
1343
                {
1344
                    $num = $this->db->num_rows($result);
1345
                    $i = 0;
1346
1347
                    while ($i < $num)
1348
                    {
1349
                        $objp                   = $this->db->fetch_object($result);
1350
1351
                        $line                   = new SupplierProposalLine($this->db);
1352
1353
                        $line->rowid			= $objp->rowid; // deprecated
1354
                        $line->id				= $objp->rowid;
1355
                        $line->fk_supplier_proposal		= $objp->fk_supplier_proposal;
1356
                        $line->fk_parent_line	= $objp->fk_parent_line;
1357
                        $line->product_type     = $objp->product_type;
1358
                        $line->label            = $objp->custom_label;
1359
                        $line->desc             = $objp->description;  // Description ligne
1360
                        $line->qty              = $objp->qty;
1361
                        $line->tva_tx           = $objp->tva_tx;
1362
                        $line->localtax1_tx		= $objp->localtax1_tx;
1363
                        $line->localtax2_tx		= $objp->localtax2_tx;
1364
                        $line->subprice         = $objp->subprice;
1365
                        $line->fk_remise_except = $objp->fk_remise_except;
1366
                        $line->remise_percent   = $objp->remise_percent;
1367
                        $line->price            = $objp->price;		// TODO deprecated
1368
1369
                        $line->info_bits        = $objp->info_bits;
1370
                        $line->total_ht         = $objp->total_ht;
1371
                        $line->total_tva        = $objp->total_tva;
1372
                        $line->total_localtax1	= $objp->total_localtax1;
1373
                        $line->total_localtax2	= $objp->total_localtax2;
1374
                        $line->total_ttc        = $objp->total_ttc;
1375
                          $line->fk_fournprice 	= $objp->fk_fournprice;
1376
                        $marginInfos			= getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $line->fk_fournprice, $objp->pa_ht);
1377
                        $line->pa_ht 			= $marginInfos[0];
1378
                        $line->marge_tx			= $marginInfos[1];
1379
                        $line->marque_tx		= $marginInfos[2];
1380
                        $line->special_code     = $objp->special_code;
1381
                        $line->rang             = $objp->rang;
1382
1383
                        $line->fk_product       = $objp->fk_product;
1384
1385
                        $line->ref				= $objp->product_ref;		// TODO deprecated
1386
                        $line->product_ref		= $objp->product_ref;
1387
                        $line->libelle			= $objp->product_label;		// TODO deprecated
1388
                        $line->product_label	= $objp->product_label;
1389
                        $line->product_desc     = $objp->product_desc; 		// Description produit
1390
                        $line->fk_product_type  = $objp->fk_product_type;
1391
1392
                        $line->ref_fourn		= $objp->ref_produit_fourn;
1393
1394
                        // Multicurrency
1395
                        $line->fk_multicurrency 		= $objp->fk_multicurrency;
1396
                        $line->multicurrency_code 		= $objp->multicurrency_code;
1397
                        $line->multicurrency_subprice 	= $objp->multicurrency_subprice;
1398
                        $line->multicurrency_total_ht 	= $objp->multicurrency_total_ht;
1399
                        $line->multicurrency_total_tva 	= $objp->multicurrency_total_tva;
1400
                        $line->multicurrency_total_ttc 	= $objp->multicurrency_total_ttc;
1401
                        $line->fk_unit					= $objp->fk_unit;
1402
1403
                        $this->lines[$i]        = $line;
1404
1405
                        $i++;
1406
                    }
1407
                    $this->db->free($result);
1408
                }
1409
                else
1410
                {
1411
                    $this->error=$this->db->error();
1412
                    return -1;
1413
                }
1414
1415
                // Retreive all extrafield
1416
                // fetch optionals attributes and labels
1417
                $this->fetch_optionals();
1418
1419
                return 1;
1420
            }
1421
1422
            $this->error="Record Not Found";
1423
            return 0;
1424
        }
1425
        else
1426
        {
1427
            $this->error=$this->db->error();
1428
            return -1;
1429
        }
1430
    }
1431
1432
    /**
1433
     *  Set status to validated
1434
     *
1435
     *  @param	User	$user       Object user that validate
1436
     *  @param	int		$notrigger	1=Does not execute triggers, 0= execute triggers
1437
     *  @return int         		<0 if KO, >=0 if OK
1438
     */
1439
    public function valid($user, $notrigger = 0)
1440
    {
1441
        require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1442
1443
        global $conf,$langs;
1444
1445
        $error=0;
1446
        $now=dol_now();
1447
1448
        if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->supplier_proposal->creer))
1449
           || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->supplier_proposal->validate_advance)))
1450
        {
1451
            $this->db->begin();
1452
1453
            // Numbering module definition
1454
            $soc = new Societe($this->db);
1455
            $soc->fetch($this->socid);
1456
1457
            // Define new ref
1458
            if (! $error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) // empty should not happened, but when it occurs, the test save life
1459
            {
1460
                $num = $this->getNextNumRef($soc);
1461
            }
1462
            else
1463
            {
1464
                $num = $this->ref;
1465
            }
1466
            $this->newref = $num;
1467
1468
            $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal";
1469
            $sql.= " SET ref = '".$this->db->escape($num)."',";
1470
            $sql.= " fk_statut = 1, date_valid='".$this->db->idate($now)."', fk_user_valid=".$user->id;
1471
            $sql.= " WHERE rowid = ".$this->id." AND fk_statut = 0";
1472
1473
            dol_syslog(get_class($this)."::valid", LOG_DEBUG);
1474
            $resql=$this->db->query($sql);
1475
            if (! $resql)
1476
            {
1477
                dol_print_error($this->db);
1478
                $error++;
1479
            }
1480
1481
               // Trigger calls
1482
            if (! $error && ! $notrigger)
1483
            {
1484
                // Call trigger
1485
                $result=$this->call_trigger('SUPPLIER_PROPOSAL_VALIDATE', $user);
1486
                if ($result < 0) { $error++; }
1487
                // End call triggers
1488
            }
1489
1490
            if (! $error)
1491
            {
1492
                $this->oldref = $this->ref;
1493
1494
                // Rename directory if dir was a temporary ref
1495
                if (preg_match('/^[\(]?PROV/i', $this->ref))
1496
                {
1497
                	// Now we rename also files into index
1498
                	$sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref)+1).")), filepath = 'supplier_proposal/".$this->db->escape($this->newref)."'";
1499
                	$sql.= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'supplier_proposal/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
1500
                	$resql = $this->db->query($sql);
1501
                	if (! $resql) { $error++; $this->error = $this->db->lasterror(); }
1502
1503
                	// We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
1504
                	$oldref = dol_sanitizeFileName($this->ref);
1505
                    $newref = dol_sanitizeFileName($num);
1506
                    $dirsource = $conf->supplier_proposal->dir_output.'/'.$oldref;
1507
                    $dirdest = $conf->supplier_proposal->dir_output.'/'.$newref;
1508
                    if (! $error && file_exists($dirsource))
1509
                    {
1510
                        dol_syslog(get_class($this)."::valid rename dir ".$dirsource." into ".$dirdest);
1511
                        if (@rename($dirsource, $dirdest))
1512
                        {
1513
                            dol_syslog("Rename ok");
1514
                            // Rename docs starting with $oldref with $newref
1515
                            $listoffiles=dol_dir_list($conf->supplier_proposal->dir_output.'/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
1516
                            foreach($listoffiles as $fileentry)
1517
                            {
1518
                                $dirsource=$fileentry['name'];
1519
                                $dirdest=preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
1520
                                $dirsource=$fileentry['path'].'/'.$dirsource;
1521
                                $dirdest=$fileentry['path'].'/'.$dirdest;
1522
                                @rename($dirsource, $dirdest);
1 ignored issue
show
Security Best Practice introduced by
It seems like you do not handle an error condition for rename(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

1522
                                /** @scrutinizer ignore-unhandled */ @rename($dirsource, $dirdest);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1523
                            }
1524
                        }
1525
                    }
1526
                }
1527
1528
                $this->ref=$num;
1529
                $this->brouillon=0;
1530
                $this->statut = 1;
1531
                $this->user_valid_id=$user->id;
1532
                $this->datev=$now;
1 ignored issue
show
Deprecated Code introduced by
The property SupplierProposal::$datev has been deprecated. ( Ignorable by Annotation )

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

1532
                /** @scrutinizer ignore-deprecated */ $this->datev=$now;
Loading history...
1533
1534
                $this->db->commit();
1535
                return 1;
1536
            }
1537
            else
1538
            {
1539
                $this->db->rollback();
1540
                return -1;
1541
            }
1542
        }
1543
        else
1544
        {
1545
            dol_syslog("You don't have permission to validate supplier proposal", LOG_WARNING);
1546
            return -2;
1547
        }
1548
    }
1549
1550
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1551
    /**
1552
     *	Set delivery date
1553
     *
1554
     *	@param      User 		$user        		Object user that modify
1555
     *	@param      int			$date_livraison     Delivery date
1556
     *	@return     int         					<0 if ko, >0 if ok
1557
     */
1558
    public function set_date_livraison($user, $date_livraison)
1559
    {
1560
        // phpcs:enable
1561
        if (! empty($user->rights->supplier_proposal->creer))
1562
        {
1563
            $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal ";
1564
            $sql.= " SET date_livraison = ".($date_livraison!=''?"'".$this->db->idate($date_livraison)."'":'null');
1565
            $sql.= " WHERE rowid = ".$this->id;
1566
1567
            if ($this->db->query($sql))
1568
            {
1569
                $this->date_livraison = $date_livraison;
1570
                return 1;
1571
            }
1572
            else
1573
            {
1574
                $this->error=$this->db->error();
1575
                dol_syslog(get_class($this)."::set_date_livraison Erreur SQL");
1576
                return -1;
1577
            }
1578
        }
1579
    }
1580
1581
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1582
    /**
1583
     *	Set an overall discount on the proposal
1584
     *
1585
     *	@param      User	$user       Object user that modify
1586
     *	@param      double	$remise      Amount discount
1587
     *	@return     int         		<0 if ko, >0 if ok
1588
     */
1589
    public function set_remise_percent($user, $remise)
1590
    {
1591
        // phpcs:enable
1592
        $remise=trim($remise)?trim($remise):0;
1593
1594
        if (! empty($user->rights->supplier_proposal->creer))
1595
        {
1596
            $remise = price2num($remise);
1597
1598
            $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal SET remise_percent = ".$remise;
1599
            $sql.= " WHERE rowid = ".$this->id." AND fk_statut = 0";
1600
1601
            if ($this->db->query($sql) )
1602
            {
1603
                $this->remise_percent = $remise;
1604
                $this->update_price(1);
1605
                return 1;
1606
            }
1607
            else
1608
            {
1609
                $this->error=$this->db->error();
1610
                return -1;
1611
            }
1612
        }
1613
    }
1614
1615
1616
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1617
    /**
1618
     *	Set an absolute overall discount on the proposal
1619
     *
1620
     *	@param      User	$user        Object user that modify
1621
     *	@param      double	$remise      Amount discount
1622
     *	@return     int         		<0 if ko, >0 if ok
1623
     */
1624
    public function set_remise_absolue($user, $remise)
1625
    {
1626
        // phpcs:enable
1627
        $remise=trim($remise)?trim($remise):0;
1628
1629
        if (! empty($user->rights->supplier_proposal->creer))
1630
        {
1631
            $remise = price2num($remise);
1632
1633
            $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal ";
1634
            $sql.= " SET remise_absolue = ".$remise;
1635
            $sql.= " WHERE rowid = ".$this->id." AND fk_statut = 0";
1636
1637
            if ($this->db->query($sql) )
1638
            {
1639
                $this->remise_absolue = $remise;
1640
                $this->update_price(1);
1641
                return 1;
1642
            }
1643
            else
1644
            {
1645
                $this->error=$this->db->error();
1646
                return -1;
1647
            }
1648
        }
1649
    }
1650
1651
1652
1653
    /**
1654
     *	Reopen the commercial proposal
1655
     *
1656
     *	@param      User	$user		Object user that close
1657
     *	@param      int		$statut		Statut
1658
     *	@param      string	$note		Comment
1659
     *  @param		int		$notrigger	1=Does not execute triggers, 0= execute triggers
1660
     *	@return     int         		<0 if KO, >0 if OK
1661
     */
1662
    public function reopen($user, $statut, $note = '', $notrigger = 0)
1663
    {
1664
        global $langs,$conf;
1665
1666
        $this->statut = $statut;
1667
        $error=0;
1668
1669
        $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal";
1670
        $sql.= " SET fk_statut = ".$this->statut.",";
1671
        if (! empty($note)) $sql.= " note_private = '".$this->db->escape($note)."',";
1672
        $sql.= " date_cloture=NULL, fk_user_cloture=NULL";
1673
        $sql.= " WHERE rowid = ".$this->id;
1674
1675
        $this->db->begin();
1676
1677
        dol_syslog(get_class($this)."::reopen", LOG_DEBUG);
1678
        $resql = $this->db->query($sql);
1679
        if (! $resql) {
1680
            $error++; $this->errors[]="Error ".$this->db->lasterror();
1681
        }
1682
        if (! $error)
1683
        {
1684
            if (! $notrigger)
1685
            {
1686
                // Call trigger
1687
                $result=$this->call_trigger('SUPPLIER_PROPOSAL_REOPEN', $user);
1688
                if ($result < 0) { $error++; }
1689
                // End call triggers
1690
            }
1691
        }
1692
1693
        // Commit or rollback
1694
        if ($error)
1695
        {
1696
            if (!empty($this->errors))
1697
            {
1698
                foreach($this->errors as $errmsg)
1699
                {
1700
                    dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
1701
                    $this->error.=($this->error?', '.$errmsg:$errmsg);
1702
                }
1703
            }
1704
            $this->db->rollback();
1705
            return -1*$error;
1706
        }
1707
        else
1708
        {
1709
            $this->db->commit();
1710
            return 1;
1711
        }
1712
    }
1713
1714
1715
    /**
1716
     *	Close the askprice
1717
     *
1718
     *	@param      User	$user		Object user that close
1719
     *	@param      int		$statut		Statut
1720
     *	@param      string	$note		Comment
1721
     *	@return     int         		<0 if KO, >0 if OK
1722
     */
1723
    public function cloture($user, $statut, $note)
1724
    {
1725
        global $langs,$conf;
1726
1727
        $this->statut = $statut;
1728
        $error=0;
1729
        $now=dol_now();
1730
1731
        $this->db->begin();
1732
1733
        $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal";
1734
        $sql.= " SET fk_statut = ".$statut.", note_private = '".$this->db->escape($note)."', date_cloture='".$this->db->idate($now)."', fk_user_cloture=".$user->id;
1735
        $sql.= " WHERE rowid = ".$this->id;
1736
1737
        $resql=$this->db->query($sql);
1738
        if ($resql)
1739
        {
1740
            $modelpdf=$conf->global->SUPPLIER_PROPOSAL_ADDON_PDF_ODT_CLOSED?$conf->global->SUPPLIER_PROPOSAL_ADDON_PDF_ODT_CLOSED:$this->modelpdf;
1741
            $trigger_name='SUPPLIER_PROPOSAL_CLOSE_REFUSED';
1742
1743
            if ($statut == 2)
1744
            {
1745
                $trigger_name='SUPPLIER_PROPOSAL_CLOSE_SIGNED';
1746
                $modelpdf=$conf->global->SUPPLIER_PROPOSAL_ADDON_PDF_ODT_TOBILL?$conf->global->SUPPLIER_PROPOSAL_ADDON_PDF_ODT_TOBILL:$this->modelpdf;
1747
1748
                if (! empty($conf->global->SUPPLIER_PROPOSAL_UPDATE_PRICE_ON_SUPPlIER_PROPOSAL))     // TODO This option was not tested correctly. Error if product ref does not exists
1749
                {
1750
                    $result = $this->updateOrCreatePriceFournisseur($user);
1751
                }
1752
            }
1753
            if ($statut == 4)
1754
            {
1755
                $trigger_name='SUPPLIER_PROPOSAL_CLASSIFY_BILLED';
1756
            }
1757
1758
            if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
1759
            {
1760
                 // Define output language
1761
                  $outputlangs = $langs;
1762
                   if (! empty($conf->global->MAIN_MULTILANGS))
1763
                   {
1764
                       $outputlangs = new Translate("", $conf);
1765
                       $newlang=(GETPOST('lang_id', 'aZ09') ? GETPOST('lang_id', 'aZ09') : $this->thirdparty->default_lang);
1766
                       $outputlangs->setDefaultLang($newlang);
1767
                   }
1768
                   //$ret=$object->fetch($id);    // Reload to get new records
1769
                   $this->generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $hidedetails seems to be never defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable $hidedesc seems to be never defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable $hideref seems to be never defined.
Loading history...
1770
            }
1771
1772
            // Call trigger
1773
            $result=$this->call_trigger($trigger_name, $user);
1774
            if ($result < 0) { $error++; }
1775
            // End call triggers
1776
1777
            if ( ! $error )
1778
            {
1779
                $this->db->commit();
1780
                return 1;
1781
            }
1782
            else
1783
            {
1784
                $this->db->rollback();
1785
                return -1;
1786
            }
1787
        }
1788
        else
1789
        {
1790
            $this->error=$this->db->lasterror();
1791
            $this->errors[]=$this->db->lasterror();
1792
            $this->db->rollback();
1793
            return -1;
1794
        }
1795
    }
1796
1797
    /**
1798
     *	Add or update supplier price according to result of proposal
1799
     *
1800
     *	@param     User	    $user       Object user
1801
     *  @return    int                  > 0 if OK
1802
     */
1803
    public function updateOrCreatePriceFournisseur($user)
1804
    {
1805
        $productsupplier = new ProductFournisseur($this->db);
1806
1807
        dol_syslog(get_class($this)."::updateOrCreatePriceFournisseur", LOG_DEBUG);
1808
        foreach ($this->lines as $product)
1809
        {
1810
            if ($product->subprice <= 0) continue;
1811
1812
            $idProductFourn = $productsupplier->find_min_price_product_fournisseur($product->fk_product, $product->qty);
1813
            $res = $productsupplier->fetch($idProductFourn);
1814
1815
            if ($productsupplier->id) {
1816
                if ($productsupplier->fourn_qty == $product->qty) {
1817
                    $this->updatePriceFournisseur($productsupplier->product_fourn_price_id, $product, $user);
1818
                } else {
1819
                    $this->createPriceFournisseur($product, $user);
1820
                }
1821
            } else {
1822
                $this->createPriceFournisseur($product, $user);
1823
            }
1824
        }
1825
1826
        return 1;
1827
    }
1828
1829
    /**
1830
     *	Upate ProductFournisseur
1831
     *
1832
     * 	@param		int 	$idProductFournPrice	id of llx_product_fournisseur_price
1833
     * 	@param		Product $product				contain informations to update
1834
     *	@param      User	$user					Object user
1835
     *	@return     int         					<0 if KO, >0 if OK
1836
     */
1837
    public function updatePriceFournisseur($idProductFournPrice, $product, $user)
1838
    {
1839
        $price=price2num($product->subprice*$product->qty, 'MU');
1840
        $unitPrice = price2num($product->subprice, 'MU');
1841
1842
        $sql = 'UPDATE '.MAIN_DB_PREFIX.'product_fournisseur_price SET '.(!empty($product->ref_fourn) ? 'ref_fourn = "'.$product->ref_fourn.'", ' : '').' price ='.$price.', unitprice ='.$unitPrice.' WHERE rowid = '.$idProductFournPrice;
1 ignored issue
show
Deprecated Code introduced by
The property Product::$ref_fourn has been deprecated. ( Ignorable by Annotation )

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

1842
        $sql = 'UPDATE '.MAIN_DB_PREFIX.'product_fournisseur_price SET '.(!empty(/** @scrutinizer ignore-deprecated */ $product->ref_fourn) ? 'ref_fourn = "'.$product->ref_fourn.'", ' : '').' price ='.$price.', unitprice ='.$unitPrice.' WHERE rowid = '.$idProductFournPrice;
Loading history...
1843
1844
        $resql = $this->db->query($sql);
1845
        if (!$resql) {
1846
            $this->error=$this->db->error();
1847
            $this->db->rollback();
1848
            return -1;
1849
        }
1850
    }
1851
1852
     /**
1853
     *	Create ProductFournisseur
1854
     *
1855
     *	@param		Product 	$product	Object Product
1856
     *	@param      User		$user		Object user
1857
     *	@return     int         			<0 if KO, >0 if OK
1858
     */
1859
    public function createPriceFournisseur($product, $user)
1860
    {
1861
        $price=price2num($product->subprice*$product->qty, 'MU');
1862
        $qty=price2num($product->qty);
1863
        $unitPrice = price2num($product->subprice, 'MU');
1864
        $now=dol_now();
1865
1866
        $values = array(
1867
            "'".$this->db->idate($now)."'",
1868
            $product->fk_product,
1869
            $this->thirdparty->id,
1870
            "'".$product->ref_fourn."'",
1 ignored issue
show
Deprecated Code introduced by
The property Product::$ref_fourn has been deprecated. ( Ignorable by Annotation )

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

1870
            "'"./** @scrutinizer ignore-deprecated */ $product->ref_fourn."'",
Loading history...
1871
            $price,
1872
            $qty,
1873
            $unitPrice,
1874
            $product->tva_tx,
1875
            $user->id
1876
        );
1877
1878
        $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'product_fournisseur_price ';
1879
        $sql .= '(datec, fk_product, fk_soc, ref_fourn, price, quantity, unitprice, tva_tx, fk_user) VALUES ('.implode(',', $values).')';
1880
1881
        $resql = $this->db->query($sql);
1882
        if (!$resql) {
1883
            $this->error=$this->db->error();
1884
            $this->db->rollback();
1885
            return -1;
1886
        }
1887
    }
1888
1889
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1890
    /**
1891
     *  Set draft status
1892
     *
1893
     *	@param		User	$user		Object user that modify
1894
     *	@return		int					<0 if KO, >0 if OK
1895
     */
1896
    public function setDraft($user)
1897
    {
1898
        // phpcs:enable
1899
        global $conf,$langs;
1900
1901
        $error = 0;
1902
1903
        if ($this->statut == self::STATUS_DRAFT)
1904
        {
1905
            dol_syslog(get_class($this)."::setDraft already draft status", LOG_WARNING);
1906
            return 0;
1907
        }
1908
1909
        $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal";
1910
        $sql.= " SET fk_statut = ".self::STATUS_DRAFT;
1911
        $sql.= " WHERE rowid = ".$this->id;
1912
1913
        if ($this->db->query($sql))
1914
        {
1915
            if (!$error) {
1916
                $this->oldcopy = clone $this;
1917
            }
1918
1919
            if (!$error) {
1920
                // Call trigger
1921
                $result=$this->call_trigger('SUPPLIER_PROPOSAL_UNVALIDATE', $user);
1922
                if ($result < 0) $error++;
1923
            }
1924
1925
            if (!$error) {
1926
                $this->statut=self::STATUS_DRAFT;
1927
                $this->brouillon = 1;
1928
                $this->db->commit();
1929
                return 1;
1930
            } else {
1931
                $this->db->rollback();
1932
                return -1;
1933
            }
1934
        }
1935
        else
1936
        {
1937
            return -1;
1938
        }
1939
    }
1940
1941
1942
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1943
    /**
1944
     *    Return list of askprice (eventually filtered on user) into an array
1945
     *
1946
     *    @param	int		$shortlist			0=Return array[id]=ref, 1=Return array[](id=>id,ref=>ref,name=>name)
1947
     *    @param	int		$draft				0=not draft, 1=draft
1948
     *    @param	int		$notcurrentuser		0=all user, 1=not current user
1949
     *    @param    int		$socid				Id third pary
1950
     *    @param    int		$limit				For pagination
1951
     *    @param    int		$offset				For pagination
1952
     *    @param    string	$sortfield			Sort criteria
1953
     *    @param    string	$sortorder			Sort order
1954
     *    @return	int		       				-1 if KO, array with result if OK
1955
     */
1956
    public function liste_array($shortlist = 0, $draft = 0, $notcurrentuser = 0, $socid = 0, $limit = 0, $offset = 0, $sortfield = 'p.datec', $sortorder = 'DESC')
1957
    {
1958
        // phpcs:enable
1959
        global $conf,$user;
1960
1961
        $ga = array();
1962
1963
        $sql = "SELECT s.rowid, s.nom as name, s.client,";
1964
        $sql.= " p.rowid as supplier_proposalid, p.fk_statut, p.total_ht, p.ref, p.remise, ";
1965
        $sql.= " p.datep as dp, p.fin_validite as datelimite";
1966
        if (! $user->rights->societe->client->voir && ! $socid) $sql .= ", sc.fk_soc, sc.fk_user";
1967
        $sql.= " FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."supplier_proposal as p, ".MAIN_DB_PREFIX."c_propalst as c";
1968
        if (! $user->rights->societe->client->voir && ! $socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
1969
        $sql.= " WHERE p.entity IN (".getEntity('supplier_proposal').")";
1970
        $sql.= " AND p.fk_soc = s.rowid";
1971
        $sql.= " AND p.fk_statut = c.id";
1972
        if (! $user->rights->societe->client->voir && ! $socid) //restriction
1973
        {
1974
            $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id;
1975
        }
1976
        if ($socid) $sql.= " AND s.rowid = ".$socid;
1977
        if ($draft)	$sql.= " AND p.fk_statut = 0";
1978
        if ($notcurrentuser > 0) $sql.= " AND p.fk_user_author <> ".$user->id;
1979
        $sql.= $this->db->order($sortfield, $sortorder);
1980
        $sql.= $this->db->plimit($limit, $offset);
1981
1982
        $result=$this->db->query($sql);
1983
        if ($result)
1984
        {
1985
            $num = $this->db->num_rows($result);
1986
            if ($num)
1987
            {
1988
                $i = 0;
1989
                while ($i < $num)
1990
                {
1991
                    $obj = $this->db->fetch_object($result);
1992
1993
                    if ($shortlist == 1)
1994
                    {
1995
                        $ga[$obj->supplier_proposalid] = $obj->ref;
1996
                    }
1997
                    elseif ($shortlist == 2)
1998
                    {
1999
                        $ga[$obj->supplier_proposalid] = $obj->ref.' ('.$obj->name.')';
2000
                    }
2001
                    else
2002
                    {
2003
                        $ga[$i]['id']	= $obj->supplier_proposalid;
2004
                        $ga[$i]['ref'] 	= $obj->ref;
2005
                        $ga[$i]['name'] = $obj->name;
2006
                    }
2007
2008
                    $i++;
2009
                }
2010
            }
2011
            return $ga;
2012
        }
2013
        else
2014
        {
2015
            dol_print_error($this->db);
2016
            return -1;
2017
        }
2018
    }
2019
2020
    /**
2021
     *	Delete askprice
2022
     *
2023
     *	@param	User	$user        	Object user that delete
2024
     *	@param	int		$notrigger		1=Does not execute triggers, 0= execute triggers
2025
     *	@return	int						1 if ok, otherwise if error
2026
     */
2027
    public function delete($user, $notrigger = 0)
2028
    {
2029
        global $conf,$langs;
2030
        require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
2031
2032
        $error=0;
2033
2034
        $this->db->begin();
2035
2036
        if (! $notrigger)
2037
        {
2038
            // Call trigger
2039
            $result=$this->call_trigger('SUPPLIER_PROPOSAL_DELETE', $user);
2040
            if ($result < 0) { $error++; }
2041
            // End call triggers
2042
        }
2043
2044
        if (! $error)
2045
        {
2046
            $sql = "DELETE FROM ".MAIN_DB_PREFIX."supplier_proposaldet WHERE fk_supplier_proposal = ".$this->id;
2047
            if ($this->db->query($sql))
2048
            {
2049
                $sql = "DELETE FROM ".MAIN_DB_PREFIX."supplier_proposal WHERE rowid = ".$this->id;
2050
                if ($this->db->query($sql))
2051
                {
2052
                    // Delete linked object
2053
                    $res = $this->deleteObjectLinked();
2054
                    if ($res < 0) $error++;
2055
2056
                    if (! $error)
2057
                    {
2058
                        // We remove directory
2059
                        $ref = dol_sanitizeFileName($this->ref);
2060
                        if ($conf->supplier_proposal->dir_output && !empty($this->ref))
2061
                        {
2062
                            $dir = $conf->supplier_proposal->dir_output . "/" . $ref ;
2063
                            $file = $dir . "/" . $ref . ".pdf";
2064
                            if (file_exists($file))
2065
                            {
2066
                                dol_delete_preview($this);
2067
2068
                                if (! dol_delete_file($file, 0, 0, 0, $this)) // For triggers
2069
                                {
2070
                                    $this->error='ErrorFailToDeleteFile';
2071
                                    $this->errors=array('ErrorFailToDeleteFile');
2072
                                    $this->db->rollback();
2073
                                    return 0;
2074
                                }
2075
                            }
2076
                            if (file_exists($dir))
2077
                            {
2078
                                $res=@dol_delete_dir_recursive($dir);
2079
                                if (! $res)
2080
                                {
2081
                                    $this->error='ErrorFailToDeleteDir';
2082
                                    $this->errors=array('ErrorFailToDeleteDir');
2083
                                    $this->db->rollback();
2084
                                    return 0;
2085
                                }
2086
                            }
2087
                        }
2088
                    }
2089
2090
                    // Removed extrafields
2091
                    if (! $error)
2092
                    {
2093
                        if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
2094
                        {
2095
                            $result=$this->deleteExtraFields();
2096
                            if ($result < 0)
2097
                            {
2098
                                $error++;
2099
                                $errorflag=-4;
2100
                                dol_syslog(get_class($this)."::delete erreur ".$errorflag." ".$this->error, LOG_ERR);
2101
                            }
2102
                        }
2103
                    }
2104
2105
                    if (! $error)
2106
                    {
2107
                        dol_syslog(get_class($this)."::delete ".$this->id." by ".$user->id, LOG_DEBUG);
2108
                        $this->db->commit();
2109
                        return 1;
2110
                    }
2111
                    else
2112
                    {
2113
                        $this->error=$this->db->lasterror();
2114
                        $this->db->rollback();
2115
                        return 0;
2116
                    }
2117
                }
2118
                else
2119
                {
2120
                    $this->error=$this->db->lasterror();
2121
                    $this->db->rollback();
2122
                    return -3;
2123
                }
2124
            }
2125
            else
2126
            {
2127
                $this->error=$this->db->lasterror();
2128
                $this->db->rollback();
2129
                return -2;
2130
            }
2131
        }
2132
        else
2133
        {
2134
            $this->db->rollback();
2135
            return -1;
2136
        }
2137
    }
2138
2139
    /**
2140
     *	Object SupplierProposal Information
2141
     *
2142
     * 	@param	int		$id		Proposal id
2143
     *  @return	void
2144
     */
2145
    public function info($id)
2146
    {
2147
        $sql = "SELECT c.rowid, ";
2148
        $sql.= " c.datec, c.date_valid as datev, c.date_cloture as dateo,";
2149
        $sql.= " c.fk_user_author, c.fk_user_valid, c.fk_user_cloture";
2150
        $sql.= " FROM ".MAIN_DB_PREFIX."supplier_proposal as c";
2151
        $sql.= " WHERE c.rowid = ".$id;
2152
2153
        $result = $this->db->query($sql);
2154
2155
        if ($result)
2156
        {
2157
            if ($this->db->num_rows($result))
2158
            {
2159
                $obj = $this->db->fetch_object($result);
2160
2161
                $this->id                = $obj->rowid;
2162
2163
                $this->date_creation     = $this->db->jdate($obj->datec);
2164
                $this->date_validation   = $this->db->jdate($obj->datev);
2165
                $this->date_cloture      = $this->db->jdate($obj->dateo);
2166
2167
                $cuser = new User($this->db);
2168
                $cuser->fetch($obj->fk_user_author);
2169
                $this->user_creation     = $cuser;
2170
2171
                if ($obj->fk_user_valid)
2172
                {
2173
                    $vuser = new User($this->db);
2174
                    $vuser->fetch($obj->fk_user_valid);
2175
                    $this->user_validation     = $vuser;
2176
                }
2177
2178
                if ($obj->fk_user_cloture)
2179
                {
2180
                    $cluser = new User($this->db);
2181
                    $cluser->fetch($obj->fk_user_cloture);
2182
                    $this->user_cloture     = $cluser;
2183
                }
2184
            }
2185
            $this->db->free($result);
2186
        }
2187
        else
2188
        {
2189
            dol_print_error($this->db);
2190
        }
2191
    }
2192
2193
2194
    /**
2195
     *    	Return label of status of proposal (draft, validated, ...)
2196
     *
2197
     *    	@param      int			$mode        0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto
2198
     *    	@return     string		Label
2199
     */
2200
    public function getLibStatut($mode = 0)
2201
    {
2202
        return $this->LibStatut($this->statut, $mode);
2203
    }
2204
2205
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2206
    /**
2207
     *  Return label of a status (draft, validated, ...)
2208
     *
2209
     *  @param      int			$statut		id statut
2210
     *  @param      int			$mode      	0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto
2211
     *  @return     string      Label
2212
     */
2213
    public function LibStatut($statut, $mode = 1)
2214
    {
2215
        // phpcs:enable
2216
        // Init/load array of translation of status
2217
        if (empty($this->labelstatut) || empty($this->labelstatut_short))
2218
        {
2219
            global $langs;
2220
            $langs->load("supplier_proposal");
2221
            $this->labelstatut[0]=$langs->trans("SupplierProposalStatusDraft");
2222
            $this->labelstatut[1]=$langs->trans("SupplierProposalStatusValidated");
2223
            $this->labelstatut[2]=$langs->trans("SupplierProposalStatusSigned");
2224
            $this->labelstatut[3]=$langs->trans("SupplierProposalStatusNotSigned");
2225
            $this->labelstatut[4]=$langs->trans("SupplierProposalStatusClosed");
2226
            $this->labelstatut_short[0]=$langs->trans("SupplierProposalStatusDraftShort");
2227
            $this->labelstatut_short[1]=$langs->trans("Opened");
2228
            $this->labelstatut_short[2]=$langs->trans("SupplierProposalStatusSignedShort");
2229
            $this->labelstatut_short[3]=$langs->trans("SupplierProposalStatusNotSignedShort");
2230
            $this->labelstatut_short[4]=$langs->trans("SupplierProposalStatusClosedShort");
2231
        }
2232
2233
        $statuttrans='';
2234
        if ($statut==0) $statuttrans='statut0';
2235
        elseif ($statut==1) $statuttrans='statut1';
2236
        elseif ($statut==2) $statuttrans='statut3';
2237
        elseif ($statut==3) $statuttrans='statut5';
2238
        elseif ($statut==4) $statuttrans='statut6';
2239
2240
        if ($mode == 0)	return $this->labelstatut[$statut];
2241
        elseif ($mode == 1)	return $this->labelstatut_short[$statut];
2242
        elseif ($mode == 2)	return img_picto($this->labelstatut[$statut], $statuttrans).' '.$this->labelstatut_short[$statut];
2243
        elseif ($mode == 3)	return img_picto($this->labelstatut[$statut], $statuttrans);
2244
        elseif ($mode == 4)	return img_picto($this->labelstatut[$statut], $statuttrans).' '.$this->labelstatut[$statut];
2245
        elseif ($mode == 5)	return '<span class="hideonsmartphone">'.$this->labelstatut_short[$statut].' </span>'.img_picto($this->labelstatut[$statut], $statuttrans);
2246
        elseif ($mode == 6)	return '<span class="hideonsmartphone">'.$this->labelstatut[$statut].' </span>'.img_picto($this->labelstatut[$statut], $statuttrans);
2247
    }
2248
2249
2250
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2251
    /**
2252
     *      Load indicators for dashboard (this->nbtodo and this->nbtodolate)
2253
     *
2254
     *      @param          User	$user   Object user
2255
     *      @param          int		$mode   "opened" for askprice to close, "signed" for proposal to invoice
2256
     *      @return         int             <0 if KO, >0 if OK
2257
     */
2258
    public function load_board($user, $mode)
2259
    {
2260
        // phpcs:enable
2261
        global $conf, $user, $langs;
2262
2263
        $now=dol_now();
2264
2265
        $this->nbtodo=$this->nbtodolate=0;
2266
        $clause = " WHERE";
2267
2268
        $sql = "SELECT p.rowid, p.ref, p.datec as datec";
2269
        $sql.= " FROM ".MAIN_DB_PREFIX."supplier_proposal as p";
2270
        if (!$user->rights->societe->client->voir && !$user->socid)
2271
        {
2272
            $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON p.fk_soc = sc.fk_soc";
2273
            $sql.= " WHERE sc.fk_user = " .$user->id;
2274
            $clause = " AND";
2275
        }
2276
        $sql.= $clause." p.entity IN (".getEntity('supplier_proposal').")";
2277
        if ($mode == 'opened') $sql.= " AND p.fk_statut = 1";
2278
        if ($mode == 'signed') $sql.= " AND p.fk_statut = 2";
2279
        if ($user->socid) $sql.= " AND p.fk_soc = ".$user->socid;
2280
2281
        $resql=$this->db->query($sql);
2282
        if ($resql)
2283
        {
2284
            if ($mode == 'opened') {
2285
                $delay_warning=$conf->supplier_proposal->cloture->warning_delay;
2286
                $statut = self::STATUS_VALIDATED;
2287
                $label = $langs->trans("SupplierProposalsToClose");
2288
            }
2289
            if ($mode == 'signed') {
2290
                $delay_warning=$conf->supplier_proposal->facturation->warning_delay;
2291
                $statut = self::STATUS_SIGNED;
2292
                $label = $langs->trans("SupplierProposalsToProcess");      // May be billed or ordered
2293
            }
2294
2295
            $response = new WorkboardResponse();
2296
            $response->warning_delay = $delay_warning/60/60/24;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $delay_warning does not seem to be defined for all execution paths leading up to this point.
Loading history...
2297
            $response->label = $label;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $label does not seem to be defined for all execution paths leading up to this point.
Loading history...
2298
            $response->url = DOL_URL_ROOT.'/supplier_proposal/list.php?viewstatut='.$statut;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $statut does not seem to be defined for all execution paths leading up to this point.
Loading history...
2299
            $response->img = img_object('', "propal");
2300
2301
            // This assignment in condition is not a bug. It allows walking the results.
2302
            while ($obj=$this->db->fetch_object($resql))
2303
            {
2304
                $response->nbtodo++;
2305
                if ($mode == 'opened')
2306
                {
2307
                    $datelimit = $this->db->jdate($obj->datefin);
2308
                    if ($datelimit < ($now - $delay_warning))
2309
                    {
2310
                        $response->nbtodolate++;
2311
                    }
2312
                }
2313
                // TODO Definir regle des propales a facturer en retard
2314
                // if ($mode == 'signed' && ! count($this->FactureListeArray($obj->rowid))) $this->nbtodolate++;
2315
            }
2316
            return $response;
2317
        }
2318
        else
2319
        {
2320
            $this->error=$this->db->lasterror();
2321
            return -1;
2322
        }
2323
    }
2324
2325
2326
    /**
2327
     *  Initialise an instance with random values.
2328
     *  Used to build previews or test instances.
2329
     *	id must be 0 if object instance is a specimen.
2330
     *
2331
     *  @return	void
2332
     */
2333
    public function initAsSpecimen()
2334
    {
2335
        global $user,$langs,$conf;
2336
2337
        // Load array of products prodids
2338
        $num_prods = 0;
2339
        $prodids = array();
2340
        $sql = "SELECT rowid";
2341
        $sql.= " FROM ".MAIN_DB_PREFIX."product";
2342
        $sql.= " WHERE entity IN (".getEntity('product').")";
2343
        $resql = $this->db->query($sql);
2344
        if ($resql)
2345
        {
2346
            $num_prods = $this->db->num_rows($resql);
2347
            $i = 0;
2348
            while ($i < $num_prods)
2349
            {
2350
                $i++;
2351
                $row = $this->db->fetch_row($resql);
2352
                $prodids[$i] = $row[0];
2353
            }
2354
        }
2355
2356
        // Initialise parametres
2357
        $this->id=0;
2358
        $this->ref = 'SPECIMEN';
2359
        $this->specimen=1;
2360
        $this->socid = 1;
2361
        $this->date = time();
2362
        $this->cond_reglement_id   = 1;
2363
        $this->cond_reglement_code = 'RECEP';
2364
        $this->mode_reglement_id   = 7;
2365
        $this->mode_reglement_code = 'CHQ';
2366
        $this->note_public='This is a comment (public)';
2367
        $this->note_private='This is a comment (private)';
2368
        // Lines
2369
        $nbp = 5;
2370
        $xnbp = 0;
2371
        while ($xnbp < $nbp)
2372
        {
2373
            $line=new SupplierProposalLine($this->db);
2374
            $line->desc=$langs->trans("Description")." ".$xnbp;
2375
            $line->qty=1;
2376
            $line->subprice=100;
2377
            $line->price=100;
1 ignored issue
show
Deprecated Code introduced by
The property SupplierProposalLine::$price has been deprecated. ( Ignorable by Annotation )

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

2377
            /** @scrutinizer ignore-deprecated */ $line->price=100;
Loading history...
2378
            $line->tva_tx=19.6;
2379
            $line->localtax1_tx=0;
2380
            $line->localtax2_tx=0;
2381
            if ($xnbp == 2)
2382
            {
2383
                $line->total_ht=50;
2384
                $line->total_ttc=59.8;
2385
                $line->total_tva=9.8;
2386
                $line->remise_percent=50;
2387
            }
2388
            else
2389
            {
2390
                $line->total_ht=100;
2391
                $line->total_ttc=119.6;
2392
                $line->total_tva=19.6;
2393
                $line->remise_percent=00;
2394
            }
2395
2396
            if ($num_prods > 0)
2397
            {
2398
                $prodid = mt_rand(1, $num_prods);
2399
                $line->fk_product=$prodids[$prodid];
2400
            }
2401
2402
            $this->lines[$xnbp]=$line;
2403
2404
            $this->total_ht       += $line->total_ht;
2405
            $this->total_tva      += $line->total_tva;
2406
            $this->total_ttc      += $line->total_ttc;
2407
2408
            $xnbp++;
2409
        }
2410
    }
2411
2412
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2413
    /**
2414
     *      Charge indicateurs this->nb de tableau de bord
2415
     *
2416
     *      @return     int         <0 if ko, >0 if ok
2417
     */
2418
    public function load_state_board()
2419
    {
2420
        // phpcs:enable
2421
        global $conf, $user;
2422
2423
        $this->nb=array();
2424
        $clause = "WHERE";
2425
2426
        $sql = "SELECT count(p.rowid) as nb";
2427
        $sql.= " FROM ".MAIN_DB_PREFIX."supplier_proposal as p";
2428
        $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON p.fk_soc = s.rowid";
2429
        if (!$user->rights->societe->client->voir && !$user->socid)
2430
        {
2431
            $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON s.rowid = sc.fk_soc";
2432
            $sql.= " WHERE sc.fk_user = " .$user->id;
2433
            $clause = "AND";
2434
        }
2435
        $sql.= " ".$clause." p.entity IN (".getEntity('supplier_proposal').")";
2436
2437
        $resql=$this->db->query($sql);
2438
        if ($resql)
2439
        {
2440
            // This assignment in condition is not a bug. It allows walking the results.
2441
            while ($obj=$this->db->fetch_object($resql))
2442
            {
2443
                $this->nb["askprice"]=$obj->nb;
2444
            }
2445
            $this->db->free($resql);
2446
            return 1;
2447
        }
2448
        else
2449
        {
2450
            dol_print_error($this->db);
2451
            $this->error=$this->db->lasterror();
2452
            return -1;
2453
        }
2454
    }
2455
2456
2457
    /**
2458
     *  Returns the reference to the following non used Proposal used depending on the active numbering module
2459
     *  defined into SUPPLIER_PROPOSAL_ADDON
2460
     *
2461
     *  @param	Societe		$soc  	Object thirdparty
2462
     *  @return string      		Reference libre pour la propale
2463
     */
2464
    public function getNextNumRef($soc)
2465
    {
2466
        global $conf, $db, $langs;
2467
        $langs->load("supplier_proposal");
2468
2469
        if (! empty($conf->global->SUPPLIER_PROPOSAL_ADDON))
2470
        {
2471
            $mybool=false;
2472
2473
            $file = $conf->global->SUPPLIER_PROPOSAL_ADDON.".php";
2474
            $classname = $conf->global->SUPPLIER_PROPOSAL_ADDON;
2475
2476
            // Include file with class
2477
            $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
2478
            foreach ($dirmodels as $reldir) {
2479
2480
                $dir = dol_buildpath($reldir."core/modules/supplier_proposal/");
2481
2482
                // Load file with numbering class (if found)
2483
                $mybool|=@include_once $dir.$file;
2484
            }
2485
2486
            if (! $mybool)
1 ignored issue
show
Bug Best Practice introduced by
The expression $mybool of type false|integer is loosely compared to false; this is ambiguous if the integer can be 0. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
2487
            {
2488
                dol_print_error('', "Failed to include file ".$file);
2489
                return '';
2490
            }
2491
2492
            $obj = new $classname();
2493
            $numref = "";
2494
            $numref = $obj->getNextValue($soc, $this);
2495
2496
            if ($numref != "")
2497
            {
2498
                return $numref;
2499
            }
2500
            else
2501
            {
2502
                $this->error=$obj->error;
2503
                return "";
2504
            }
2505
        }
2506
        else
2507
        {
2508
            $langs->load("errors");
2509
            print $langs->trans("Error")." ".$langs->trans("ErrorModuleSetupNotComplete");
2510
            return "";
2511
        }
2512
    }
2513
2514
    /**
2515
     *	Return clicable link of object (with eventually picto)
2516
     *
2517
     *	@param      int		$withpicto					Add picto into link
2518
     *	@param      string	$option						Where point the link ('compta', 'expedition', 'document', ...)
2519
     *	@param      string	$get_params    				Parametres added to url
2520
     *  @param	    int   	$notooltip					1=Disable tooltip
2521
     *  @param      int     $save_lastsearch_value		-1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
2522
     *	@return     string          					String with URL
2523
     */
2524
    public function getNomUrl($withpicto = 0, $option = '', $get_params = '', $notooltip = 0, $save_lastsearch_value = -1)
2525
    {
2526
        global $langs, $conf, $user;
2527
2528
        if (! empty($conf->dol_no_mouse_hover)) $notooltip=1;   // Force disable tooltips
2529
2530
        $url='';
2531
        $result='';
2532
2533
        $label='<u>'.$langs->trans("ShowSupplierProposal").'</u>';
2534
        if (! empty($this->ref))
2535
        $label.= '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
2536
        if (! empty($this->ref_fourn))
2537
            $label.= '<br><b>'.$langs->trans('RefSupplier').':</b> '.$this->ref_fourn;
2538
        if (! empty($this->total_ht))
2539
            $label.= '<br><b>' . $langs->trans('AmountHT') . ':</b> ' . price($this->total_ht, 0, $langs, 0, -1, -1, $conf->currency);
2540
        if (! empty($this->total_tva))
2541
            $label.= '<br><b>' . $langs->trans('VAT') . ':</b> ' . price($this->total_tva, 0, $langs, 0, -1, -1, $conf->currency);
2542
        if (! empty($this->total_ttc))
2543
            $label.= '<br><b>' . $langs->trans('AmountTTC') . ':</b> ' . price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency);
2544
        if ($option == '') {
2545
            $url = DOL_URL_ROOT.'/supplier_proposal/card.php?id='.$this->id. $get_params;
2546
        }
2547
        if ($option == 'document') {
2548
            $url = DOL_URL_ROOT.'/supplier_proposal/document.php?id='.$this->id. $get_params;
2549
        }
2550
2551
        if ($option !== 'nolink')
2552
        {
2553
            // Add param to save lastsearch_values or not
2554
            $add_save_lastsearch_values=($save_lastsearch_value == 1 ? 1 : 0);
2555
            if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) $add_save_lastsearch_values=1;
2556
            if ($add_save_lastsearch_values) $url.='&save_lastsearch_values=1';
2557
        }
2558
2559
        $linkclose='';
2560
        if (empty($notooltip) && $user->rights->propal->lire)
2561
        {
2562
            if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
2563
            {
2564
                $label=$langs->trans("ShowSupplierProposal");
2565
                $linkclose.=' alt="'.dol_escape_htmltag($label, 1).'"';
2566
            }
2567
            $linkclose.= ' title="'.dol_escape_htmltag($label, 1).'"';
2568
            $linkclose.=' class="classfortooltip"';
2569
        }
2570
2571
        $linkstart = '<a href="'.$url.'"';
2572
        $linkstart.=$linkclose.'>';
2573
        $linkend='</a>';
2574
2575
        $picto='supplier_proposal';
2576
2577
        $result .= $linkstart;
2578
        if ($withpicto) $result.=img_object(($notooltip?'':$label), $this->picto, ($notooltip?(($withpicto != 2) ? 'class="paddingright"' : ''):'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip?0:1);
2579
        if ($withpicto != 2) $result.= $this->ref;
2580
        $result .= $linkend;
2581
2582
        return $result;
2583
    }
2584
2585
    /**
2586
     * 	Retrieve an array of supplier proposal lines
2587
     *
2588
     * 	@return int		>0 if OK, <0 if KO
2589
     */
2590
    public function getLinesArray()
2591
    {
2592
        // For other object, here we call fetch_lines. But fetch_lines does not exists on supplier proposal
2593
2594
        $sql = 'SELECT pt.rowid, pt.label as custom_label, pt.description, pt.fk_product, pt.fk_remise_except,';
2595
        $sql.= ' pt.qty, pt.tva_tx, pt.remise_percent, pt.subprice, pt.info_bits,';
2596
        $sql.= ' pt.total_ht, pt.total_tva, pt.total_ttc, pt.fk_product_fournisseur_price as fk_fournprice, pt.buy_price_ht as pa_ht, pt.special_code, pt.localtax1_tx, pt.localtax2_tx,';
2597
        $sql.= ' pt.product_type, pt.rang, pt.fk_parent_line,';
2598
        $sql.= ' p.label as product_label, p.ref, p.fk_product_type, p.rowid as prodid,';
2599
        $sql.= ' p.description as product_desc, pt.ref_fourn as ref_supplier,';
2600
        $sql.= ' pt.fk_multicurrency, pt.multicurrency_code, pt.multicurrency_subprice, pt.multicurrency_total_ht, pt.multicurrency_total_tva, pt.multicurrency_total_ttc, pt.fk_unit';
2601
        $sql.= ' FROM '.MAIN_DB_PREFIX.'supplier_proposaldet as pt';
2602
        $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON pt.fk_product=p.rowid';
2603
        $sql.= ' WHERE pt.fk_supplier_proposal = '.$this->id;
2604
        $sql.= ' ORDER BY pt.rang ASC, pt.rowid';
2605
2606
        dol_syslog(get_class($this).'::getLinesArray', LOG_DEBUG);
2607
        $resql = $this->db->query($sql);
2608
        if ($resql)
2609
        {
2610
            $num = $this->db->num_rows($resql);
2611
            $i = 0;
2612
2613
            while ($i < $num)
2614
            {
2615
                $obj = $this->db->fetch_object($resql);
2616
2617
                $this->lines[$i]					= new SupplierProposalLine($this->db);
2618
                $this->lines[$i]->id				= $obj->rowid; // for backward compatibility
2619
                $this->lines[$i]->rowid				= $obj->rowid;
2620
                $this->lines[$i]->label 			= $obj->custom_label;
2621
                $this->lines[$i]->description 		= $obj->description;
2622
                $this->lines[$i]->fk_product		= $obj->fk_product;
2623
                $this->lines[$i]->ref				= $obj->ref;
2624
                $this->lines[$i]->product_label		= $obj->product_label;
2625
                $this->lines[$i]->product_desc		= $obj->product_desc;
2626
                $this->lines[$i]->fk_product_type	= $obj->fk_product_type;  // deprecated
2627
                $this->lines[$i]->product_type		= $obj->product_type;
2628
                $this->lines[$i]->qty				= $obj->qty;
2629
                $this->lines[$i]->subprice			= $obj->subprice;
2630
                $this->lines[$i]->fk_remise_except 	= $obj->fk_remise_except;
2631
                $this->lines[$i]->remise_percent	= $obj->remise_percent;
2632
                $this->lines[$i]->tva_tx			= $obj->tva_tx;
2633
                $this->lines[$i]->info_bits			= $obj->info_bits;
2634
                $this->lines[$i]->total_ht			= $obj->total_ht;
2635
                $this->lines[$i]->total_tva			= $obj->total_tva;
2636
                $this->lines[$i]->total_ttc			= $obj->total_ttc;
2637
                $this->lines[$i]->fk_fournprice		= $obj->fk_fournprice;
2638
                $marginInfos						= getMarginInfos($obj->subprice, $obj->remise_percent, $obj->tva_tx, $obj->localtax1_tx, $obj->localtax2_tx, $this->lines[$i]->fk_fournprice, $obj->pa_ht);
2639
                $this->lines[$i]->pa_ht				= $marginInfos[0];
2640
                $this->lines[$i]->marge_tx			= $marginInfos[1];
2641
                $this->lines[$i]->marque_tx			= $marginInfos[2];
2642
                $this->lines[$i]->fk_parent_line	= $obj->fk_parent_line;
2643
                $this->lines[$i]->special_code		= $obj->special_code;
2644
                $this->lines[$i]->rang				= $obj->rang;
2645
2646
                $this->lines[$i]->ref_fourn				= $obj->ref_supplier;	// deprecated
2647
                $this->lines[$i]->ref_supplier			= $obj->ref_supplier;
2648
2649
                // Multicurrency
2650
                $this->lines[$i]->fk_multicurrency 			= $obj->fk_multicurrency;
2651
                $this->lines[$i]->multicurrency_code 		= $obj->multicurrency_code;
2652
                $this->lines[$i]->multicurrency_subprice 	= $obj->multicurrency_subprice;
2653
                $this->lines[$i]->multicurrency_total_ht 	= $obj->multicurrency_total_ht;
2654
                $this->lines[$i]->multicurrency_total_tva 	= $obj->multicurrency_total_tva;
2655
                $this->lines[$i]->multicurrency_total_ttc 	= $obj->multicurrency_total_ttc;
2656
                $this->lines[$i]->fk_unit				 	= $obj->fk_unit;
2657
2658
                $i++;
2659
            }
2660
            $this->db->free($resql);
2661
2662
            return 1;
2663
        }
2664
        else
2665
        {
2666
            $this->error=$this->db->error();
2667
            return -1;
2668
        }
2669
    }
2670
2671
    /**
2672
     *  Create a document onto disk according to template module.
2673
     *
2674
     * 	@param	    string		$modele			Force model to use ('' to not force)
2675
     * 	@param		Translate	$outputlangs	Object langs to use for output
2676
     *  @param      int			$hidedetails    Hide details of lines
2677
     *  @param      int			$hidedesc       Hide description
2678
     *  @param      int			$hideref        Hide ref
2679
         *  @param   null|array  $moreparams     Array to provide more information
2680
     * 	@return     int         				0 if KO, 1 if OK
2681
     */
2682
    public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
2683
    {
2684
        global $conf, $langs;
2685
2686
        $langs->load("supplier_proposal");
2687
2688
        if (! dol_strlen($modele)) {
2689
2690
            $modele = 'aurore';
2691
2692
            if ($this->modelpdf) {
2693
                $modele = $this->modelpdf;
2694
            } elseif (! empty($conf->global->SUPPLIER_PROPOSAL_ADDON_PDF)) {
2695
                $modele = $conf->global->SUPPLIER_PROPOSAL_ADDON_PDF;
2696
            }
2697
        }
2698
2699
        $modelpath = "core/modules/supplier_proposal/doc/";
2700
2701
        return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
2702
    }
2703
2704
2705
    /**
2706
     * Function used to replace a thirdparty id with another one.
2707
     *
2708
     * @param DoliDB $db Database handler
2709
     * @param int $origin_id Old thirdparty id
2710
     * @param int $dest_id New thirdparty id
2711
     * @return bool
2712
     */
2713
    public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
2714
    {
2715
        $tables = array(
2716
            'supplier_proposal'
2717
        );
2718
2719
        return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
2720
    }
2721
}
2722
2723
2724
/**
2725
 *	Class to manage supplier_proposal lines
2726
 */
2727
class SupplierProposalLine extends CommonObjectLine
2728
{
2729
    /**
2730
     * @var DoliDB Database handler.
2731
     */
2732
    public $db;
2733
2734
    /**
2735
     * @var string Error code (or message)
2736
     */
2737
    public $error='';
2738
2739
    /**
2740
     * @var string ID to identify managed object
2741
     */
2742
    public $element='supplier_proposaldet';
2743
2744
    /**
2745
     * @var string Name of table without prefix where object is stored
2746
     */
2747
    public $table_element='supplier_proposaldet';
2748
2749
    public $oldline;
2750
2751
    // From llx_supplier_proposaldet
2752
    public $rowid; // deprecated
2753
2754
    /**
2755
     * @var int ID
2756
     */
2757
    public $id;
2758
2759
    /**
2760
     * @var int ID
2761
     */
2762
    public $fk_supplier_proposal;
2763
2764
    /**
2765
     * @var int ID
2766
     */
2767
    public $fk_parent_line;
2768
2769
    public $desc;          	// Description ligne
2770
2771
    /**
2772
     * @var int ID
2773
     */
2774
    public $fk_product;		// Id produit predefini
2775
2776
    /**
2777
     * @deprecated
2778
     * @see $product_type
2779
     */
2780
    public $fk_product_type;
2781
    /**
2782
     * Product type
2783
     * @var int
2784
     * @see Product::TYPE_PRODUCT, Product::TYPE_SERVICE
2785
     */
2786
    public $product_type = Product::TYPE_PRODUCT;
2787
2788
    public $qty;
2789
    public $tva_tx;
2790
    public $subprice;
2791
    public $remise_percent;
2792
2793
    /**
2794
     * @var int ID
2795
     */
2796
    public $fk_remise_except;
2797
2798
    public $rang = 0;
2799
2800
    /**
2801
     * @var int ID
2802
     */
2803
    public $fk_fournprice;
2804
2805
    public $pa_ht;
2806
    public $marge_tx;
2807
    public $marque_tx;
2808
2809
    public $special_code;	// Tag for special lines (exlusive tags)
2810
    // 1: frais de port
2811
    // 2: ecotaxe
2812
    // 3: option line (when qty = 0)
2813
2814
    public $info_bits = 0;	// Liste d'options cumulables:
2815
    // Bit 0: 	0 si TVA normal - 1 si TVA NPR
2816
    // Bit 1:	0 ligne normale - 1 si ligne de remise fixe
2817
2818
    public $total_ht;			// Total HT  de la ligne toute quantite et incluant la remise ligne
2819
    public $total_tva;			// Total TVA  de la ligne toute quantite et incluant la remise ligne
2820
    public $total_ttc;			// Total TTC de la ligne toute quantite et incluant la remise ligne
2821
2822
    /**
2823
     * @deprecated
2824
     * @see remise_percent, fk_remise_except
2825
     */
2826
    public $remise;
2827
2828
    /**
2829
     * @deprecated
2830
     * @see subprice
2831
     */
2832
    public $price;
2833
2834
    // From llx_product
2835
    /**
2836
     * @deprecated
2837
     * @see product_ref
2838
     */
2839
    public $ref;
2840
2841
    /**
2842
     * Product reference
2843
     * @var string
2844
     */
2845
    public $product_ref;
2846
2847
    /**
2848
     * @deprecated
2849
     * @see $product_label
2850
     */
2851
    public $libelle;
2852
2853
    /**
2854
     *  Product label
2855
     * @var string
2856
     */
2857
    public $product_label;
2858
2859
    /**
2860
     * Product description
2861
     * @var string
2862
     */
2863
    public $product_desc;
2864
2865
    public $localtax1_tx;		// Local tax 1
2866
    public $localtax2_tx;		// Local tax 2
2867
    public $localtax1_type;	// Local tax 1 type
2868
    public $localtax2_type;	// Local tax 2 type
2869
    public $total_localtax1;  	// Line total local tax 1
2870
    public $total_localtax2;	// Line total local tax 2
2871
2872
    public $skip_update_total; // Skip update price total for special lines
2873
2874
    public $ref_fourn;
2875
    public $ref_supplier;
2876
2877
    // Multicurrency
2878
    /**
2879
     * @var int ID
2880
     */
2881
    public $fk_multicurrency;
2882
2883
    public $multicurrency_code;
2884
    public $multicurrency_subprice;
2885
    public $multicurrency_total_ht;
2886
    public $multicurrency_total_tva;
2887
    public $multicurrency_total_ttc;
2888
2889
    /**
2890
     * 	Class line Contructor
2891
     *
2892
     * 	@param	DoliDB	$db	Database handler
2893
     */
2894
    public function __construct($db)
2895
    {
2896
        $this->db= $db;
2897
    }
2898
2899
    /**
2900
     *	Retrieve the propal line object
2901
     *
2902
     *	@param	int		$rowid		Propal line id
2903
     *	@return	int					<0 if KO, >0 if OK
2904
     */
2905
    public function fetch($rowid)
2906
    {
2907
        $sql = 'SELECT pd.rowid, pd.fk_supplier_proposal, pd.fk_parent_line, pd.fk_product, pd.label as custom_label, pd.description, pd.price, pd.qty, pd.tva_tx,';
2908
        $sql.= ' pd.remise, pd.remise_percent, pd.fk_remise_except, pd.subprice,';
2909
        $sql.= ' pd.info_bits, pd.total_ht, pd.total_tva, pd.total_ttc, pd.fk_product_fournisseur_price as fk_fournprice, pd.buy_price_ht as pa_ht, pd.special_code, pd.rang,';
2910
        $sql.= ' pd.localtax1_tx, pd.localtax2_tx, pd.total_localtax1, pd.total_localtax2,';
2911
        $sql.= ' p.ref as product_ref, p.label as product_label, p.description as product_desc,';
2912
        $sql.= ' pd.product_type, pd.ref_fourn as ref_produit_fourn,';
2913
        $sql.= ' pd.fk_multicurrency, pd.multicurrency_code, pd.multicurrency_subprice, pd.multicurrency_total_ht, pd.multicurrency_total_tva, pd.multicurrency_total_ttc, pd.fk_unit';
2914
        $sql.= ' FROM '.MAIN_DB_PREFIX.'supplier_proposaldet as pd';
2915
        $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON pd.fk_product = p.rowid';
2916
        $sql.= ' WHERE pd.rowid = '.$rowid;
2917
2918
        $result = $this->db->query($sql);
2919
        if ($result)
2920
        {
2921
            $objp = $this->db->fetch_object($result);
2922
2923
            $this->rowid			= $objp->rowid; // deprecated
2924
            $this->id				= $objp->rowid;
2925
            $this->fk_supplier_proposal		= $objp->fk_supplier_proposal;
2926
            $this->fk_parent_line	= $objp->fk_parent_line;
2927
            $this->label			= $objp->custom_label;
2928
            $this->desc				= $objp->description;
2929
            $this->qty				= $objp->qty;
2930
            $this->price			= $objp->price;		// deprecated
2931
            $this->subprice			= $objp->subprice;
2932
            $this->tva_tx			= $objp->tva_tx;
2933
            $this->remise			= $objp->remise;
2934
            $this->remise_percent	= $objp->remise_percent;
2935
            $this->fk_remise_except = $objp->fk_remise_except;
2936
            $this->fk_product		= $objp->fk_product;
2937
            $this->info_bits		= $objp->info_bits;
2938
2939
            $this->total_ht			= $objp->total_ht;
2940
            $this->total_tva		= $objp->total_tva;
2941
            $this->total_ttc		= $objp->total_ttc;
2942
2943
            $this->fk_fournprice	= $objp->fk_fournprice;
2944
2945
            $marginInfos			= getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $this->fk_fournprice, $objp->pa_ht);
2946
            $this->pa_ht			= $marginInfos[0];
2947
            $this->marge_tx			= $marginInfos[1];
2948
            $this->marque_tx		= $marginInfos[2];
2949
2950
            $this->special_code		= $objp->special_code;
2951
            $this->product_type		= $objp->product_type;
2952
            $this->rang				= $objp->rang;
2953
2954
            $this->ref				= $objp->product_ref;      // deprecated
2955
            $this->product_ref		= $objp->product_ref;
2956
            $this->libelle			= $objp->product_label;  // deprecated
2957
            $this->product_label	= $objp->product_label;
2958
            $this->product_desc		= $objp->product_desc;
2959
2960
            $this->ref_fourn		= $objp->ref_produit_forun;
2961
2962
            // Multicurrency
2963
            $this->fk_multicurrency 		= $objp->fk_multicurrency;
2964
            $this->multicurrency_code 		= $objp->multicurrency_code;
2965
            $this->multicurrency_subprice 	= $objp->multicurrency_subprice;
2966
            $this->multicurrency_total_ht 	= $objp->multicurrency_total_ht;
2967
            $this->multicurrency_total_tva 	= $objp->multicurrency_total_tva;
2968
            $this->multicurrency_total_ttc 	= $objp->multicurrency_total_ttc;
2969
            $this->fk_unit				 	= $objp->fk_unit;
2970
2971
            $this->db->free($result);
2972
        }
2973
        else
2974
        {
2975
            dol_print_error($this->db);
2976
        }
2977
    }
2978
2979
    /**
2980
     *  Insert object line propal in database
2981
     *
2982
     *	@param		int		$notrigger		1=Does not execute triggers, 0= execute triggers
2983
     *	@return		int						<0 if KO, >0 if OK
2984
     */
2985
    public function insert($notrigger = 0)
2986
    {
2987
        global $conf,$langs,$user;
2988
2989
        $error=0;
2990
2991
        dol_syslog(get_class($this)."::insert rang=".$this->rang);
2992
2993
        // Clean parameters
2994
        if (empty($this->tva_tx)) $this->tva_tx=0;
2995
        if (empty($this->localtax1_tx)) $this->localtax1_tx=0;
2996
        if (empty($this->localtax2_tx)) $this->localtax2_tx=0;
2997
        if (empty($this->localtax1_type)) $this->localtax1_type=0;
2998
        if (empty($this->localtax2_type)) $this->localtax2_type=0;
2999
        if (empty($this->total_localtax1)) $this->total_localtax1=0;
3000
        if (empty($this->total_localtax2)) $this->total_localtax2=0;
3001
        if (empty($this->rang)) $this->rang=0;
3002
        if (empty($this->remise)) $this->remise=0;
1 ignored issue
show
Deprecated Code introduced by
The property SupplierProposalLine::$remise has been deprecated. ( Ignorable by Annotation )

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

3002
        if (empty($this->remise)) /** @scrutinizer ignore-deprecated */ $this->remise=0;
Loading history...
3003
        if (empty($this->remise_percent)) $this->remise_percent=0;
3004
        if (empty($this->info_bits)) $this->info_bits=0;
3005
        if (empty($this->special_code)) $this->special_code=0;
3006
        if (empty($this->fk_parent_line)) $this->fk_parent_line=0;
3007
        if (empty($this->fk_fournprice)) $this->fk_fournprice=0;
3008
        if (empty($this->fk_unit)) $this->fk_unit=0;
3009
        if (empty($this->subprice)) $this->subprice=0;
3010
3011
        if (empty($this->pa_ht)) $this->pa_ht=0;
3012
3013
        // if buy price not defined, define buyprice as configured in margin admin
3014
        if ($this->pa_ht == 0)
3015
        {
3016
            if (($result = $this->defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product)) < 0)
3017
            {
3018
                return $result;
3019
            }
3020
            else
3021
            {
3022
                $this->pa_ht = $result;
3023
            }
3024
        }
3025
3026
        // Check parameters
3027
        if ($this->product_type < 0) return -1;
3028
3029
        $this->db->begin();
3030
3031
        // Insert line into database
3032
        $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'supplier_proposaldet';
3033
        $sql.= ' (fk_supplier_proposal, fk_parent_line, label, description, fk_product, product_type,';
3034
        $sql.= ' fk_remise_except, qty, tva_tx, localtax1_tx, localtax2_tx, localtax1_type, localtax2_type,';
3035
        $sql.= ' subprice, remise_percent, ';
3036
        $sql.= ' info_bits, ';
3037
        $sql.= ' total_ht, total_tva, total_localtax1, total_localtax2, total_ttc, fk_product_fournisseur_price, buy_price_ht, special_code, rang,';
3038
        $sql.= ' ref_fourn,';
3039
        $sql.= ' fk_multicurrency, multicurrency_code, multicurrency_subprice, multicurrency_total_ht, multicurrency_total_tva, multicurrency_total_ttc, fk_unit)';
3040
        $sql.= " VALUES (".$this->fk_supplier_proposal.",";
3041
        $sql.= " ".($this->fk_parent_line>0?"'".$this->db->escape($this->fk_parent_line)."'":"null").",";
3042
        $sql.= " ".(! empty($this->label)?"'".$this->db->escape($this->label)."'":"null").",";
3043
        $sql.= " '".$this->db->escape($this->desc)."',";
3044
        $sql.= " ".($this->fk_product?"'".$this->db->escape($this->fk_product)."'":"null").",";
3045
        $sql.= " '".$this->db->escape($this->product_type)."',";
3046
        $sql.= " ".($this->fk_remise_except?"'".$this->db->escape($this->fk_remise_except)."'":"null").",";
3047
        $sql.= " ".price2num($this->qty).",";
3048
        $sql.= " ".price2num($this->tva_tx).",";
3049
        $sql.= " ".price2num($this->localtax1_tx).",";
3050
        $sql.= " ".price2num($this->localtax2_tx).",";
3051
        $sql.= " '".$this->db->escape($this->localtax1_type)."',";
3052
        $sql.= " '".$this->db->escape($this->localtax2_type)."',";
3053
        $sql.= " ".(!empty($this->subprice)?price2num($this->subprice):"null").",";
3054
        $sql.= " ".price2num($this->remise_percent).",";
3055
        $sql.= " ".(isset($this->info_bits)?"'".$this->db->escape($this->info_bits)."'":"null").",";
3056
        $sql.= " ".price2num($this->total_ht).",";
3057
        $sql.= " ".price2num($this->total_tva).",";
3058
        $sql.= " ".price2num($this->total_localtax1).",";
3059
        $sql.= " ".price2num($this->total_localtax2).",";
3060
        $sql.= " ".price2num($this->total_ttc).",";
3061
        $sql.= " ".(!empty($this->fk_fournprice)?"'".$this->db->escape($this->fk_fournprice)."'":"null").",";
3062
        $sql.= " ".(isset($this->pa_ht)?"'".price2num($this->pa_ht)."'":"null").",";
3063
        $sql.= ' '.$this->special_code.',';
3064
        $sql.= ' '.$this->rang.',';
3065
        $sql.= " '".$this->db->escape($this->ref_fourn)."'";
3066
        $sql.= ", ".($this->fk_multicurrency > 0?$this->fk_multicurrency:'null');
3067
        $sql.= ", '".$this->db->escape($this->multicurrency_code)."'";
3068
        $sql.= ", ".$this->multicurrency_subprice;
3069
        $sql.= ", ".$this->multicurrency_total_ht;
3070
        $sql.= ", ".$this->multicurrency_total_tva;
3071
        $sql.= ", ".$this->multicurrency_total_ttc;
3072
        $sql.= ", ".($this->fk_unit?$this->fk_unit:'null');
3073
        $sql.= ')';
3074
3075
        dol_syslog(get_class($this).'::insert', LOG_DEBUG);
3076
        $resql=$this->db->query($sql);
3077
        if ($resql)
3078
        {
3079
            $this->rowid=$this->db->last_insert_id(MAIN_DB_PREFIX.'supplier_proposaldet');
3080
            $this->id=$this->rowid;
3081
3082
            if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
3083
            {
3084
                $result=$this->insertExtraFields();
3085
                if ($result < 0)
3086
                {
3087
                    $error++;
3088
                }
3089
            }
3090
3091
            if (! $error && ! $notrigger)
3092
            {
3093
                // Call trigger
3094
                $result=$this->call_trigger('LINESUPPLIER_PROPOSAL_INSERT', $user);
3095
                if ($result < 0)
3096
                {
3097
                    $this->db->rollback();
3098
                    return -1;
3099
                }
3100
                // End call triggers
3101
            }
3102
3103
            $this->db->commit();
3104
            return 1;
3105
        }
3106
        else
3107
        {
3108
            $this->error=$this->db->error()." sql=".$sql;
3109
            $this->db->rollback();
3110
            return -1;
3111
        }
3112
    }
3113
3114
    /**
3115
     * 	Delete line in database
3116
     *
3117
     *	@return	 int  <0 if ko, >0 if ok
3118
     */
3119
    public function delete()
3120
    {
3121
        global $conf,$langs,$user;
3122
3123
        $error=0;
3124
        $this->db->begin();
3125
3126
        $sql = "DELETE FROM ".MAIN_DB_PREFIX."supplier_proposaldet WHERE rowid = ".$this->rowid;
3127
        dol_syslog("SupplierProposalLine::delete", LOG_DEBUG);
3128
        if ($this->db->query($sql) )
3129
        {
3130
3131
            // Remove extrafields
3132
            if ((! $error) && (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED))) // For avoid conflicts if trigger used
3133
            {
3134
                $this->id=$this->rowid;
3135
                $result=$this->deleteExtraFields();
3136
                if ($result < 0)
3137
                {
3138
                    $error++;
3139
                    dol_syslog(get_class($this)."::delete error -4 ".$this->error, LOG_ERR);
3140
                }
3141
            }
3142
3143
            // Call trigger
3144
            $result=$this->call_trigger('LINESUPPLIER_PROPOSAL_DELETE', $user);
3145
            if ($result < 0)
3146
            {
3147
                $this->db->rollback();
3148
                return -1;
3149
            }
3150
            // End call triggers
3151
3152
            $this->db->commit();
3153
3154
            return 1;
3155
        }
3156
        else
3157
        {
3158
            $this->error=$this->db->error()." sql=".$sql;
3159
            $this->db->rollback();
3160
            return -1;
3161
        }
3162
    }
3163
3164
    /**
3165
     *	Update propal line object into DB
3166
     *
3167
     *	@param 	int		$notrigger	1=Does not execute triggers, 0= execute triggers
3168
     *	@return	int					<0 if ko, >0 if ok
3169
     */
3170
    public function update($notrigger = 0)
3171
    {
3172
        global $conf,$langs,$user;
3173
3174
        $error=0;
3175
3176
        // Clean parameters
3177
        if (empty($this->tva_tx)) $this->tva_tx=0;
3178
        if (empty($this->localtax1_tx)) $this->localtax1_tx=0;
3179
        if (empty($this->localtax2_tx)) $this->localtax2_tx=0;
3180
        if (empty($this->total_localtax1)) $this->total_localtax1=0;
3181
        if (empty($this->total_localtax2)) $this->total_localtax2=0;
3182
        if (empty($this->localtax1_type)) $this->localtax1_type=0;
3183
        if (empty($this->localtax2_type)) $this->localtax2_type=0;
3184
        if (empty($this->marque_tx)) $this->marque_tx=0;
3185
        if (empty($this->marge_tx)) $this->marge_tx=0;
3186
        if (empty($this->price)) $this->price=0;	// TODO A virer
1 ignored issue
show
Deprecated Code introduced by
The property SupplierProposalLine::$price has been deprecated. ( Ignorable by Annotation )

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

3186
        if (empty($this->price)) /** @scrutinizer ignore-deprecated */ $this->price=0;	// TODO A virer
Loading history...
3187
        if (empty($this->remise)) $this->remise=0;	// TODO A virer
1 ignored issue
show
Deprecated Code introduced by
The property SupplierProposalLine::$remise has been deprecated. ( Ignorable by Annotation )

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

3187
        if (empty(/** @scrutinizer ignore-deprecated */ $this->remise)) $this->remise=0;	// TODO A virer
Loading history...
3188
        if (empty($this->remise_percent)) $this->remise_percent=0;
3189
        if (empty($this->info_bits)) $this->info_bits=0;
3190
        if (empty($this->special_code)) $this->special_code=0;
3191
        if (empty($this->fk_parent_line)) $this->fk_parent_line=0;
3192
        if (empty($this->fk_fournprice)) $this->fk_fournprice=0;
3193
        if (empty($this->fk_unit)) $this->fk_unit=0;
3194
        if (empty($this->subprice)) $this->subprice=0;
3195
3196
        if (empty($this->pa_ht)) $this->pa_ht=0;
3197
3198
        // if buy price not defined, define buyprice as configured in margin admin
3199
        if ($this->pa_ht == 0)
3200
        {
3201
            if (($result = $this->defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product)) < 0)
3202
            {
3203
                return $result;
3204
            }
3205
            else
3206
            {
3207
                $this->pa_ht = $result;
3208
            }
3209
        }
3210
3211
        $this->db->begin();
3212
3213
        // Mise a jour ligne en base
3214
        $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposaldet SET";
3215
        $sql.= " description='".$this->db->escape($this->desc)."'";
3216
        $sql.= " , label=".(! empty($this->label)?"'".$this->db->escape($this->label)."'":"null");
3217
        $sql.= " , product_type=".$this->product_type;
3218
        $sql.= " , tva_tx='".price2num($this->tva_tx)."'";
3219
        $sql.= " , localtax1_tx=".price2num($this->localtax1_tx);
3220
        $sql.= " , localtax2_tx=".price2num($this->localtax2_tx);
3221
        $sql.= " , localtax1_type='".$this->db->escape($this->localtax1_type)."'";
3222
        $sql.= " , localtax2_type='".$this->db->escape($this->localtax2_type)."'";
3223
        $sql.= " , qty='".price2num($this->qty)."'";
3224
        $sql.= " , subprice=".price2num($this->subprice)."";
3225
        $sql.= " , remise_percent=".price2num($this->remise_percent)."";
3226
        $sql.= " , price=".price2num($this->price)."";					// TODO A virer
1 ignored issue
show
Deprecated Code introduced by
The property SupplierProposalLine::$price has been deprecated. ( Ignorable by Annotation )

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

3226
        $sql.= " , price=".price2num(/** @scrutinizer ignore-deprecated */ $this->price)."";					// TODO A virer
Loading history...
3227
        $sql.= " , remise=".price2num($this->remise)."";				// TODO A virer
1 ignored issue
show
Deprecated Code introduced by
The property SupplierProposalLine::$remise has been deprecated. ( Ignorable by Annotation )

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

3227
        $sql.= " , remise=".price2num(/** @scrutinizer ignore-deprecated */ $this->remise)."";				// TODO A virer
Loading history...
3228
        $sql.= " , info_bits='".$this->db->escape($this->info_bits)."'";
3229
        if (empty($this->skip_update_total))
3230
        {
3231
            $sql.= " , total_ht=".price2num($this->total_ht)."";
3232
            $sql.= " , total_tva=".price2num($this->total_tva)."";
3233
            $sql.= " , total_ttc=".price2num($this->total_ttc)."";
3234
            $sql.= " , total_localtax1=".price2num($this->total_localtax1)."";
3235
            $sql.= " , total_localtax2=".price2num($this->total_localtax2)."";
3236
        }
3237
        $sql.= " , fk_product_fournisseur_price=".(! empty($this->fk_fournprice)?"'".$this->db->escape($this->fk_fournprice)."'":"null");
3238
        $sql.= " , buy_price_ht=".price2num($this->pa_ht);
3239
        if (strlen($this->special_code)) $sql.= " , special_code=".$this->special_code;
3240
        $sql.= " , fk_parent_line=".($this->fk_parent_line>0?$this->fk_parent_line:"null");
3241
        if (! empty($this->rang)) $sql.= ", rang=".$this->rang;
3242
        $sql.= " , ref_fourn=".(! empty($this->ref_fourn)?"'".$this->db->escape($this->ref_fourn)."'":"null");
3243
        $sql.= " , fk_unit=".($this->fk_unit?$this->fk_unit:'null');
3244
3245
        // Multicurrency
3246
        $sql.= " , multicurrency_subprice=".price2num($this->multicurrency_subprice)."";
3247
        $sql.= " , multicurrency_total_ht=".price2num($this->multicurrency_total_ht)."";
3248
        $sql.= " , multicurrency_total_tva=".price2num($this->multicurrency_total_tva)."";
3249
        $sql.= " , multicurrency_total_ttc=".price2num($this->multicurrency_total_ttc)."";
3250
3251
        $sql.= " WHERE rowid = ".$this->rowid;
3252
3253
        dol_syslog(get_class($this)."::update", LOG_DEBUG);
3254
        $resql=$this->db->query($sql);
3255
        if ($resql)
3256
        {
3257
            if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
3258
            {
3259
                $this->id=$this->rowid;
3260
                $result=$this->insertExtraFields();
3261
                if ($result < 0)
3262
                {
3263
                    $error++;
3264
                }
3265
            }
3266
3267
            if (! $error && ! $notrigger)
3268
            {
3269
                // Call trigger
3270
                $result=$this->call_trigger('LINESUPPLIER_PROPOSAL_UPDATE', $user);
3271
                if ($result < 0)
3272
                {
3273
                    $this->db->rollback();
3274
                    return -1;
3275
                }
3276
                // End call triggers
3277
            }
3278
3279
            $this->db->commit();
3280
            return 1;
3281
        }
3282
        else
3283
        {
3284
            $this->error=$this->db->error();
3285
            $this->db->rollback();
3286
            return -2;
3287
        }
3288
    }
3289
3290
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3291
    /**
3292
     *	Update DB line fields total_xxx
3293
     *	Used by migration
3294
     *
3295
     *	@return		int		<0 if ko, >0 if ok
3296
     */
3297
    public function update_total()
3298
    {
3299
        // phpcs:enable
3300
        $this->db->begin();
3301
3302
        // Mise a jour ligne en base
3303
        $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposaldet SET";
3304
        $sql.= " total_ht=".price2num($this->total_ht, 'MT')."";
3305
        $sql.= ",total_tva=".price2num($this->total_tva, 'MT')."";
3306
        $sql.= ",total_ttc=".price2num($this->total_ttc, 'MT')."";
3307
        $sql.= " WHERE rowid = ".$this->rowid;
3308
3309
        dol_syslog("SupplierProposalLine::update_total", LOG_DEBUG);
3310
3311
        $resql=$this->db->query($sql);
3312
        if ($resql)
3313
        {
3314
            $this->db->commit();
3315
            return 1;
3316
        }
3317
        else
3318
        {
3319
            $this->error=$this->db->error();
3320
            $this->db->rollback();
3321
            return -2;
3322
        }
3323
    }
3324
}
3325