Completed
Branch develop (a0152f)
by
unknown
34:49
created

SupplierProposal::delete()   F

Complexity

Conditions 18
Paths 315

Size

Total Lines 111
Code Lines 60

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 18
eloc 60
nc 315
nop 2
dl 0
loc 111
rs 3.6714
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/* 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-2011 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
 *
16
 * This program is free software; you can redistribute it and/or modify
17
 * it under the terms of the GNU General Public License as published by
18
 * the Free Software Foundation; either version 3 of the License, or
19
 * (at your option) any later version.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24
 * GNU General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU General Public License
27
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28
 */
29
30
/**
31
 *	\file       htdocs/supplier_proposal/class/supplier_proposal.class.php
32
 *	\brief      File of class to manage supplier proposals
33
 */
34
35
require_once DOL_DOCUMENT_ROOT .'/fourn/class/fournisseur.product.class.php';
36
require_once DOL_DOCUMENT_ROOT .'/core/class/commonobject.class.php';
37
require_once DOL_DOCUMENT_ROOT .'/product/class/product.class.php';
38
require_once DOL_DOCUMENT_ROOT .'/contact/class/contact.class.php';
39
require_once DOL_DOCUMENT_ROOT .'/margin/lib/margins.lib.php';
40
require_once DOL_DOCUMENT_ROOT .'/multicurrency/class/multicurrency.class.php';
41
42
/**
43
 *	Class to manage price ask supplier
44
 */
45
class SupplierProposal extends CommonObject
46
{
47
    public $element='supplier_proposal';
48
    public $table_element='supplier_proposal';
49
    public $table_element_line='supplier_proposaldet';
50
    public $fk_element='fk_supplier_proposal';
51
    public $picto='propal';
52
    /**
53
     * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
54
     * @var int
55
     */
56
    public $ismultientitymanaged = 1;
57
    /**
58
     * 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
59
     * @var integer
60
     */
61
    public $restrictiononfksoc = 1;
62
63
    /**
64
     * {@inheritdoc}
65
     */
66
    protected $table_ref_field = 'ref';
67
68
    var $socid;		// Id client
69
70
	/**
71
	 * @deprecated
72
	 * @see user_author_id
73
	 */
74
    var $author;
75
	var $ref_fourn;  //Reference saisie lors de l'ajout d'une ligne à la demande
76
    var $statut;					// 0 (draft), 1 (validated), 2 (signed), 3 (not signed), 4 (processed/billed)
77
    var $date;						// Date of proposal
78
    var $date_livraison;
79
80
	/**
81
	 * @deprecated
82
	 * @see date_creation
83
	 */
84
	var $datec;
85
86
	/**
87
	 * Creation date
88
	 * @var int
89
	 */
90
	public $date_creation;
91
92
	/**
93
	 * @deprecated
94
	 * @see date_validation
95
	 */
96
	var $datev;
97
98
	/**
99
	 * Validation date
100
	 * @var int
101
	 */
102
	public $date_validation;
103
104
105
    var $user_author_id;
106
    var $user_valid_id;
107
    var $user_close_id;
108
109
	/**
110
	 * @deprecated
111
	 * @see price_ht
112
	 */
113
    var $price;
114
	/**
115
	 * @deprecated
116
	 * @see total_tva
117
	 */
118
    var $tva;
119
	/**
120
	 * @deprecated
121
	 * @see total_ttc
122
	 */
123
    var $total;
124
125
    var $cond_reglement_code;
126
    var $mode_reglement_code;
127
    var $remise = 0;
128
    var $remise_percent = 0;
129
    var $remise_absolue = 0;
130
131
    var $products=array();
132
    var $extraparams=array();
133
134
    var $lines = array();
135
    var $line;
136
137
    var $labelstatut=array();
138
    var $labelstatut_short=array();
139
140
    var $nbtodo;
141
    var $nbtodolate;
142
143
    var $specimen;
144
145
	// Multicurrency
146
	var $fk_multicurrency;
147
	var $multicurrency_code;
148
	var $multicurrency_tx;
149
	var $multicurrency_total_ht;
150
	var $multicurrency_total_tva;
151
	var $multicurrency_total_ttc;
152
153
	/**
154
	 * Draft status
155
	 */
156
	const STATUS_DRAFT = 0;
157
	/**
158
	 * Validated status
159
	 */
160
	const STATUS_VALIDATED = 1;
161
	/**
162
	 * Signed quote
163
	 */
164
	const STATUS_SIGNED = 2;
165
	/**
166
	 * Not signed quote, canceled
167
	 */
168
	const STATUS_NOTSIGNED = 3;
169
	/**
170
	 * Billed or closed/processed quote
171
	 */
172
	const STATUS_CLOSE = 4;
173
174
175
176
    /**
177
     *	Constructor
178
     *
179
     *	@param      DoliDB	$db         Database handler
180
     *	@param      int		$socid		Id third party
181
     *	@param      int		$supplier_proposalid   Id supplier_proposal
182
     */
183
    function __construct($db, $socid="", $supplier_proposalid=0)
184
    {
185
        global $conf,$langs;
186
187
        $this->db = $db;
188
189
        $this->socid = $socid;
190
        $this->id = $supplier_proposalid;
191
192
        $this->products = array();
193
    }
194
195
196
    /**
197
     * 	Add line into array products
198
     *	$this->client doit etre charge
199
     *
200
     * 	@param  int		$idproduct       	Product Id to add
201
     * 	@param  int		$qty             	Quantity
202
     * 	@param  int		$remise_percent  	Discount effected on Product
203
     *  @return	int							<0 if KO, >0 if OK
204
     *
205
     *	TODO	Remplacer les appels a cette fonction par generation objet Ligne
206
     *			insere dans tableau $this->products
207
     */
208
    function add_product($idproduct, $qty, $remise_percent=0)
209
    {
210
        global $conf, $mysoc;
211
212
        if (! $qty) $qty = 1;
213
214
        dol_syslog(get_class($this)."::add_product $idproduct, $qty, $remise_percent");
215
        if ($idproduct > 0)
216
        {
217
            $prod=new Product($this->db);
218
            $prod->fetch($idproduct);
219
220
            $productdesc = $prod->description;
221
222
            $tva_tx = get_default_tva($mysoc,$this->thirdparty,$prod->id);
223
            $tva_npr = get_default_npr($mysoc,$this->thirdparty,$prod->id);
224
            if (empty($tva_tx)) $tva_npr=0;
225
            $localtax1_tx = get_localtax($tva_tx,1,$mysoc,$this->thirdparty,$tva_npr);
226
            $localtax2_tx = get_localtax($tva_tx,2,$mysoc,$this->thirdparty,$tva_npr);
227
228
            // multiprix
229
            if($conf->global->PRODUIT_MULTIPRICES && $this->thirdparty->price_level)
230
            {
231
                $price = $prod->multiprices[$this->thirdparty->price_level];
232
            }
233
            else
234
            {
235
                $price = $prod->price;
236
            }
237
238
            $line = new SupplierProposalLine($this->db);
239
240
            $line->fk_product=$idproduct;
241
            $line->desc=$productdesc;
242
            $line->qty=$qty;
243
            $line->subprice=$price;
244
            $line->remise_percent=$remise_percent;
245
            $line->tva_tx=$tva_tx;
246
247
            $this->lines[]=$line;
248
        }
249
    }
250
251
    /**
252
     *	Adding line of fixed discount in the proposal in DB
253
     *
254
     *	@param     int		$idremise			Id of fixed discount
255
     *  @return    int          				>0 if OK, <0 if KO
256
     */
257
    function insert_discount($idremise)
258
    {
259
        global $langs;
260
261
        include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
262
        include_once DOL_DOCUMENT_ROOT.'/core/class/discount.class.php';
263
264
        $this->db->begin();
265
266
        $remise=new DiscountAbsolute($this->db);
267
        $result=$remise->fetch($idremise);
268
269
        if ($result > 0)
270
        {
271
            if ($remise->fk_facture)	// Protection against multiple submission
272
            {
273
                $this->error=$langs->trans("ErrorDiscountAlreadyUsed");
274
                $this->db->rollback();
275
                return -5;
276
            }
277
278
            $supplier_proposalligne=new SupplierProposalLine($this->db);
279
            $supplier_proposalligne->fk_supplier_proposal=$this->id;
280
            $supplier_proposalligne->fk_remise_except=$remise->id;
281
            $supplier_proposalligne->desc=$remise->description;   	// Description ligne
282
            $supplier_proposalligne->tva_tx=$remise->tva_tx;
283
            $supplier_proposalligne->subprice=-$remise->amount_ht;
284
            $supplier_proposalligne->fk_product=0;					// Id produit predefini
285
            $supplier_proposalligne->qty=1;
286
            $supplier_proposalligne->remise=0;
287
            $supplier_proposalligne->remise_percent=0;
288
            $supplier_proposalligne->rang=-1;
289
            $supplier_proposalligne->info_bits=2;
290
291
            // TODO deprecated
292
            $supplier_proposalligne->price=-$remise->amount_ht;
293
294
            $supplier_proposalligne->total_ht  = -$remise->amount_ht;
295
            $supplier_proposalligne->total_tva = -$remise->amount_tva;
296
            $supplier_proposalligne->total_ttc = -$remise->amount_ttc;
297
298
            $result=$supplier_proposalligne->insert();
299
            if ($result > 0)
300
            {
301
                $result=$this->update_price(1);
302
                if ($result > 0)
303
                {
304
                    $this->db->commit();
305
                    return 1;
306
                }
307
                else
308
                {
309
                    $this->db->rollback();
310
                    return -1;
311
                }
312
            }
313
            else
314
            {
315
                $this->error=$supplier_proposalligne->error;
316
                $this->db->rollback();
317
                return -2;
318
            }
319
        }
320
        else
321
        {
322
            $this->db->rollback();
323
            return -2;
324
        }
325
    }
326
327
    /**
328
     *    	Add a proposal line into database (linked to product/service or not)
329
     * 		Les parametres sont deja cense etre juste et avec valeurs finales a l'appel
330
     *		de cette methode. Aussi, pour le taux tva, il doit deja avoir ete defini
331
     *		par l'appelant par la methode get_default_tva(societe_vendeuse,societe_acheteuse,'',produit)
332
     *		et le desc doit deja avoir la bonne valeur (a l'appelant de gerer le multilangue)
333
     *
334
     * 		@param    	string		$desc				Description de la ligne
335
     * 		@param    	double		$pu_ht				Prix unitaire
336
     * 		@param    	double		$qty             	Quantite
337
     * 		@param    	double		$txtva           	Taux de tva
338
     * 		@param		double		$txlocaltax1		Local tax 1 rate
339
     *  	@param		double		$txlocaltax2		Local tax 2 rate
340
     *		@param    	int			$fk_product      	Id du produit/service predefini
341
     * 		@param    	double		$remise_percent  	Pourcentage de remise de la ligne
342
     * 		@param    	string		$price_base_type	HT or TTC
343
     * 		@param    	double		$pu_ttc             Prix unitaire TTC
344
     * 		@param    	int			$info_bits			Bits de type de lignes
345
     *      @param      int			$type               Type of line (product, service)
346
     *      @param      int			$rang               Position of line
347
     *      @param		int			$special_code		Special code (also used by externals modules!)
348
     *      @param		int			$fk_parent_line		Id of parent line
349
     *      @param		int			$fk_fournprice		Id supplier price
350
     *      @param		int			$pa_ht				Buying price without tax
351
     *      @param		string		$label				???
352
     *      @param		array		$array_option		extrafields array
353
	 * 		@param		string		$ref_fourn			Supplier price reference
354
	 * 		@param		int			$fk_unit			Id of the unit to use.
355
	 * 		@param		string		$origin				'order', 'supplier_proposal', ...
356
	 * 		@param		int			$origin_id			Id of origin line
357
     * 		@param		double		$pu_ht_devise		Amount in currency
358
     *    	@return    	int         	    			>0 if OK, <0 if KO
359
     *
360
     *    	@see       	add_product
361
     */
362
    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_fourn='', $fk_unit='', $origin='', $origin_id=0, $pu_ht_devise=0)
363
    {
364
    	global $mysoc, $conf;
365
366
        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");
367
        include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
368
369
        // Clean parameters
370
        if (empty($remise_percent)) $remise_percent=0;
371
        if (empty($qty)) $qty=0;
372
        if (empty($info_bits)) $info_bits=0;
373
        if (empty($rang)) $rang=0;
374
        if (empty($fk_parent_line) || $fk_parent_line < 0) $fk_parent_line=0;
375
        if (empty($pu_ht)) $pu_ht=0;
376
377
        $remise_percent=price2num($remise_percent);
378
        $qty=price2num($qty);
379
        $pu_ht=price2num($pu_ht);
380
        $pu_ttc=price2num($pu_ttc);
381
        $txtva=price2num($txtva);
382
        $txlocaltax1=price2num($txlocaltax1);
383
        $txlocaltax2=price2num($txlocaltax2);
384
    		$pa_ht=price2num($pa_ht);
385
        if ($price_base_type=='HT')
386
        {
387
            $pu=$pu_ht;
388
        }
389
        else
390
        {
391
            $pu=$pu_ttc;
392
        }
393
394
        // Check parameters
395
        if ($type < 0) return -1;
396
397
        if ($this->statut == 0)
398
        {
399
            $this->db->begin();
400
401
            // Calcul du total TTC et de la TVA pour la ligne a partir de
402
            // qty, pu, remise_percent et txtva
403
            // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
404
            // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
405
406
            $localtaxes_type=getLocalTaxesFromRate($txtva,0,$this->thirdparty,$mysoc);
407
            $txtva = preg_replace('/\s*\(.*\)/','',$txtva);  // Remove code into vatrate.
408
409
            if ($conf->multicurrency->enabled && $pu_ht_devise > 0) {
410
                $pu = 0;
411
            }
412
413
            $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);
414
            $total_ht  = $tabprice[0];
415
            $total_tva = $tabprice[1];
416
            $total_ttc = $tabprice[2];
417
            $total_localtax1 = $tabprice[9];
418
            $total_localtax2 = $tabprice[10];
419
            $pu = $pu_ht = $tabprice[3];
420
421
			// MultiCurrency
422
			$multicurrency_total_ht  = $tabprice[16];
423
            $multicurrency_total_tva = $tabprice[17];
424
            $multicurrency_total_ttc = $tabprice[18];
425
            $pu_ht_devise = $tabprice[19];
426
427
            // Rang to use
428
            $rangtouse = $rang;
429
            if ($rangtouse == -1)
430
            {
431
                $rangmax = $this->line_max($fk_parent_line);
432
                $rangtouse = $rangmax + 1;
433
            }
434
435
            // TODO A virer
436
            // Anciens indicateurs: $price, $remise (a ne plus utiliser)
437
            $price = $pu;
438
            $remise = 0;
439
            if ($remise_percent > 0)
440
            {
441
                $remise = round(($pu * $remise_percent / 100), 2);
442
                $price = $pu - $remise;
443
            }
444
445
            // Insert line
446
            $this->line=new SupplierProposalLine($this->db);
447
448
            $this->line->fk_supplier_proposal=$this->id;
449
            $this->line->label=$label;
450
            $this->line->desc=$desc;
451
            $this->line->qty=$qty;
452
            $this->line->tva_tx=$txtva;
453
            $this->line->localtax1_tx=($total_localtax1?$localtaxes_type[1]:0);
454
            $this->line->localtax2_tx=($total_localtax2?$localtaxes_type[3]:0);
455
            $this->line->localtax1_type = $localtaxes_type[0];
456
			$this->line->localtax2_type = $localtaxes_type[2];
457
            $this->line->fk_product=$fk_product;
458
            $this->line->remise_percent=$remise_percent;
459
            $this->line->subprice=$pu_ht;
460
            $this->line->rang=$rangtouse;
461
            $this->line->info_bits=$info_bits;
462
            $this->line->total_ht=$total_ht;
463
            $this->line->total_tva=$total_tva;
464
            $this->line->total_localtax1=$total_localtax1;
465
            $this->line->total_localtax2=$total_localtax2;
466
            $this->line->total_ttc=$total_ttc;
467
            $this->line->product_type=$type;
468
            $this->line->special_code=$special_code;
469
            $this->line->fk_parent_line=$fk_parent_line;
470
            $this->line->fk_unit=$fk_unit;
471
            $this->line->origin=$origin;
472
            $this->line->origin_id=$origin_id;
473
			$this->line->ref_fourn = $this->db->escape($ref_fourn);
474
475
			// infos marge
476
			if (!empty($fk_product) && empty($fk_fournprice) && empty($pa_ht)) {
477
			    // by external module, take lowest buying price
478
			    include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
479
			    $productFournisseur = new ProductFournisseur($this->db);
480
			    $productFournisseur->find_min_price_product_fournisseur($fk_product);
481
			    $this->line->fk_fournprice = $productFournisseur->product_fourn_price_id;
482
			} else {
483
			    $this->line->fk_fournprice = $fk_fournprice;
484
			}
485
			$this->line->pa_ht = $pa_ht;
486
487
			// Multicurrency
488
			$this->line->fk_multicurrency			= $this->fk_multicurrency;
489
			$this->line->multicurrency_code			= $this->multicurrency_code;
490
            $this->line->multicurrency_subprice		= $pu_ht_devise;
491
			$this->line->multicurrency_total_ht 	= $multicurrency_total_ht;
492
            $this->line->multicurrency_total_tva 	= $multicurrency_total_tva;
493
            $this->line->multicurrency_total_ttc 	= $multicurrency_total_ttc;
494
495
            // Mise en option de la ligne
496
            if (empty($qty) && empty($special_code)) $this->line->special_code=3;
497
498
            // TODO deprecated
499
            $this->line->price=$price;
500
            $this->line->remise=$remise;
501
502
            if (is_array($array_option) && count($array_option)>0) {
503
            	$this->line->array_options=$array_option;
504
            }
505
506
            $result=$this->line->insert();
507
            if ($result > 0)
508
            {
509
                // Reorder if child line
510
                if (! empty($fk_parent_line)) $this->line_order(true,'DESC');
511
512
                // Mise a jour informations denormalisees au niveau de la propale meme
513
                $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.
514
                if ($result > 0)
515
                {
516
                    $this->db->commit();
517
                    return $this->line->rowid;
518
                }
519
                else
520
                {
521
                    $this->error=$this->db->error();
522
                    $this->db->rollback();
523
                    return -1;
524
                }
525
            }
526
            else
527
            {
528
                $this->error=$this->line->error;
529
                $this->db->rollback();
530
                return -2;
531
            }
532
        }
533
    }
534
535
536
    /**
537
     *  Update a proposal line
538
     *
539
     *  @param      int			$rowid           	Id de la ligne
540
     *  @param      double		$pu		     	  	Prix unitaire (HT ou TTC selon price_base_type)
541
     *  @param      double		$qty            	Quantity
542
     *  @param      double		$remise_percent  	Remise effectuee sur le produit
543
     *  @param      double		$txtva	          	Taux de TVA
544
     * 	@param	  	double		$txlocaltax1		Local tax 1 rate
545
     *  @param	  	double		$txlocaltax2		Local tax 2 rate
546
     *  @param      string		$desc            	Description
547
     *	@param	  	double		$price_base_type	HT ou TTC
548
     *	@param      int			$info_bits        	Miscellaneous informations
549
     *	@param		int			$special_code		Special code (also used by externals modules!)
550
     * 	@param		int			$fk_parent_line		Id of parent line (0 in most cases, used by modules adding sublevels into lines).
551
     * 	@param		int			$skip_update_total	Keep fields total_xxx to 0 (used for special lines by some modules)
552
     *  @param		int			$fk_fournprice		Id of origin supplier price
553
     *  @param		int			$pa_ht				Price (without tax) of product when it was bought
554
     *  @param		string		$label				???
555
     *  @param		int			$type				0/1=Product/service
556
	 *  @param		array		$array_option		extrafields array
557
	 * 	@param		string		$ref_fourn			Supplier price reference
558
	 *	@param		int			$fk_unit			Id of the unit to use.
559
     *  @return     int     		        		0 if OK, <0 if KO
560
     */
561
	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_fourn='', $fk_unit='')
562
    {
563
        global $conf,$user,$langs, $mysoc;
564
565
        dol_syslog(get_class($this)."::updateLine $rowid, $pu, $qty, $remise_percent, $txtva, $desc, $price_base_type, $info_bits");
566
        include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
567
568
        // Clean parameters
569
        $remise_percent=price2num($remise_percent);
570
        $qty=price2num($qty);
571
        $pu = price2num($pu);
572
        $txtva = price2num($txtva);
573
        $txlocaltax1=price2num($txlocaltax1);
574
        $txlocaltax2=price2num($txlocaltax2);
575
    	$pa_ht=price2num($pa_ht);
576
        if (empty($qty) && empty($special_code)) $special_code=3;    // Set option tag
577
        if (! empty($qty) && $special_code == 3) $special_code=0;    // Remove option tag
578
579
        if ($this->statut == 0)
580
        {
581
            $this->db->begin();
582
583
            // Calcul du total TTC et de la TVA pour la ligne a partir de
584
            // qty, pu, remise_percent et txtva
585
            // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
586
            // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
587
588
            $localtaxes_type=getLocalTaxesFromRate($txtva,0,$this->thirdparty,$mysoc);
589
            $txtva = preg_replace('/\s*\(.*\)/','',$txtva);  // Remove code into vatrate.
590
591
            $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);
592
            $total_ht  = $tabprice[0];
593
            $total_tva = $tabprice[1];
594
            $total_ttc = $tabprice[2];
595
            $total_localtax1 = $tabprice[9];
596
            $total_localtax2 = $tabprice[10];
597
598
			// MultiCurrency
599
			$multicurrency_total_ht  = $tabprice[16];
600
            $multicurrency_total_tva = $tabprice[17];
601
            $multicurrency_total_ttc = $tabprice[18];
602
603
            // Anciens indicateurs: $price, $remise (a ne plus utiliser)
604
            $price = $pu;
605
            if ($remise_percent > 0)
606
            {
607
                $remise = round(($pu * $remise_percent / 100), 2);
608
                $price = $pu - $remise;
609
            }
610
611
            // Update line
612
            $this->line=new SupplierProposalLine($this->db);
613
614
            // Stock previous line records
615
            $staticline=new SupplierProposalLine($this->db);
616
            $staticline->fetch($rowid);
617
            $this->line->oldline = $staticline;
618
619
            // Reorder if fk_parent_line change
620
            if (! empty($fk_parent_line) && ! empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line)
621
            {
622
                $rangmax = $this->line_max($fk_parent_line);
623
                $this->line->rang = $rangmax + 1;
624
            }
625
626
            $this->line->rowid				= $rowid;
627
            $this->line->label				= $label;
628
            $this->line->desc				= $desc;
629
            $this->line->qty				= $qty;
630
            $this->line->product_type			= $type;
631
            $this->line->tva_tx				= $txtva;
632
            $this->line->localtax1_tx		= $txlocaltax1;
633
            $this->line->localtax2_tx		= $txlocaltax2;
634
			$this->line->localtax1_type		= $localtaxes_type[0];
635
			$this->line->localtax2_type		= $localtaxes_type[2];
636
            $this->line->remise_percent		= $remise_percent;
637
            $this->line->subprice			= $pu;
638
            $this->line->info_bits			= $info_bits;
639
            $this->line->total_ht			= $total_ht;
640
            $this->line->total_tva			= $total_tva;
641
            $this->line->total_localtax1	= $total_localtax1;
642
            $this->line->total_localtax2	= $total_localtax2;
643
            $this->line->total_ttc			= $total_ttc;
644
            $this->line->special_code		= $special_code;
645
            $this->line->fk_parent_line		= $fk_parent_line;
646
            $this->line->skip_update_total	= $skip_update_total;
647
            $this->line->ref_fourn			= $ref_fourn;
648
			$this->line->fk_unit			= $fk_unit;
649
650
            // infos marge
651
            if (!empty($fk_product) && empty($fk_fournprice) && empty($pa_ht)) {
0 ignored issues
show
Bug introduced by
The variable $fk_product seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
652
                // by external module, take lowest buying price
653
                include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
654
			    $productFournisseur = new ProductFournisseur($this->db);
655
			    $productFournisseur->find_min_price_product_fournisseur($fk_product);
656
			    $this->line->fk_fournprice = $productFournisseur->product_fourn_price_id;
657
			} else {
658
			    $this->line->fk_fournprice = $fk_fournprice;
659
			}
660
            $this->line->pa_ht = $pa_ht;
661
662
            // TODO deprecated
663
            $this->line->price=$price;
664
            $this->line->remise=$remise;
0 ignored issues
show
Bug introduced by
The variable $remise does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
665
666
            if (is_array($array_option) && count($array_option)>0) {
667
            	$this->line->array_options=$array_option;
668
            }
669
670
			// Multicurrency
671
			$this->line->multicurrency_subprice		= price2num($pu * $this->multicurrency_tx);
672
			$this->line->multicurrency_total_ht 	= $multicurrency_total_ht;
673
            $this->line->multicurrency_total_tva 	= $multicurrency_total_tva;
674
            $this->line->multicurrency_total_ttc 	= $multicurrency_total_ttc;
675
676
            $result=$this->line->update();
677
            if ($result > 0)
678
            {
679
                // Reorder if child line
680
                if (! empty($fk_parent_line)) $this->line_order(true,'DESC');
681
682
                $this->update_price(1);
683
684
                $this->fk_supplier_proposal = $this->id;
685
                $this->rowid = $rowid;
686
687
                $this->db->commit();
688
                return $result;
689
            }
690
            else
691
            {
692
                $this->error=$this->db->error();
693
                $this->db->rollback();
694
                return -1;
695
            }
696
        }
697
        else
698
        {
699
            dol_syslog(get_class($this)."::updateline Erreur -2 SupplierProposal en mode incompatible pour cette action");
700
            return -2;
701
        }
702
    }
703
704
705
    /**
706
     *  Delete detail line
707
     *
708
     *  @param		int		$lineid			Id of line to delete
709
     *  @return     int         			>0 if OK, <0 if KO
710
     */
711
    function deleteline($lineid)
712
    {
713
        if ($this->statut == 0)
714
        {
715
            $line=new SupplierProposalLine($this->db);
716
717
            // For triggers
718
            $line->fetch($lineid);
719
720
            if ($line->delete() > 0)
721
            {
722
                $this->update_price(1);
723
724
                return 1;
725
            }
726
            else
727
            {
728
                return -1;
729
            }
730
        }
731
        else
732
        {
733
            return -2;
734
        }
735
    }
736
737
738
    /**
739
     *  Create commercial proposal into database
740
     * 	this->ref can be set or empty. If empty, we will use "(PROVid)"
741
     *
742
     * 	@param		User	$user		User that create
743
     * 	@param		int		$notrigger	1=Does not execute triggers, 0= execute triggers
744
     *  @return     int     			<0 if KO, >=0 if OK
745
     */
746
    function create($user, $notrigger=0)
747
    {
748
        global $langs,$conf,$mysoc,$hookmanager;
749
        $error=0;
750
751
        $now=dol_now();
752
753
        dol_syslog(get_class($this)."::create");
754
755
        // Check parameters
756
        $result=$this->fetch_thirdparty();
757
        if ($result < 0)
758
        {
759
            $this->error="Failed to fetch company";
760
            dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
761
            return -3;
762
        }
763
764
        // Check parameters
765
		if (! empty($this->ref))	// We check that ref is not already used
766
		{
767
			$result=self::isExistingObject($this->element, 0, $this->ref);	// Check ref is not yet used
768
			if ($result > 0)
769
			{
770
				$this->error='ErrorRefAlreadyExists';
771
				dol_syslog(get_class($this)."::create ".$this->error,LOG_WARNING);
772
				$this->db->rollback();
773
				return -1;
774
			}
775
		}
776
777
		// Multicurrency
778
		if (!empty($this->multicurrency_code)) list($this->fk_multicurrency,$this->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code);
779
		if (empty($this->fk_multicurrency))
780
		{
781
			$this->multicurrency_code = $conf->currency;
782
			$this->fk_multicurrency = 0;
783
			$this->multicurrency_tx = 1;
784
		}
785
786
        $this->db->begin();
787
788
        // Insert into database
789
        $sql = "INSERT INTO ".MAIN_DB_PREFIX."supplier_proposal (";
790
        $sql.= "fk_soc";
791
        $sql.= ", price";
792
        $sql.= ", remise";
793
        $sql.= ", remise_percent";
794
        $sql.= ", remise_absolue";
795
        $sql.= ", tva";
796
        $sql.= ", total";
797
        $sql.= ", datec";
798
        $sql.= ", ref";
799
        $sql.= ", fk_user_author";
800
        $sql.= ", note_private";
801
        $sql.= ", note_public";
802
        $sql.= ", model_pdf";
803
        $sql.= ", fk_cond_reglement";
804
        $sql.= ", fk_mode_reglement";
805
        $sql.= ", fk_account";
806
        $sql.= ", date_livraison";
807
        $sql.= ", fk_shipping_method";
808
        $sql.= ", fk_projet";
809
        $sql.= ", entity";
810
        $sql.= ", fk_multicurrency";
811
        $sql.= ", multicurrency_code";
812
        $sql.= ", multicurrency_tx";
813
        $sql.= ") ";
814
        $sql.= " VALUES (";
815
        $sql.= $this->socid;
816
        $sql.= ", 0";
817
        $sql.= ", ".$this->remise;
818
        $sql.= ", ".($this->remise_percent?$this->db->escape($this->remise_percent):'null');
819
        $sql.= ", ".($this->remise_absolue?$this->db->escape($this->remise_absolue):'null');
820
        $sql.= ", 0";
821
        $sql.= ", 0";
822
        $sql.= ", '".$this->db->idate($now)."'";
823
        $sql.= ", '(PROV)'";
824
        $sql.= ", ".($user->id > 0 ? "'".$user->id."'":"null");
825
        $sql.= ", '".$this->db->escape($this->note_private)."'";
826
        $sql.= ", '".$this->db->escape($this->note_public)."'";
827
        $sql.= ", '".$this->db->escape($this->modelpdf)."'";
828
        $sql.= ", ".($this->cond_reglement_id > 0 ? $this->cond_reglement_id : 'NULL');
829
        $sql.= ", ".($this->mode_reglement_id > 0 ? $this->mode_reglement_id : 'NULL');
830
        $sql.= ", ".($this->fk_account>0?$this->fk_account:'NULL');
831
        $sql.= ", ".($this->date_livraison!=''?"'".$this->db->idate($this->date_livraison)."'":"null");
832
        $sql.= ", ".($this->shipping_method_id>0?$this->shipping_method_id:'NULL');
833
        $sql.= ", ".($this->fk_project?$this->fk_project:"null");
834
        $sql.= ", ".$conf->entity;
835
		$sql.= ", ".(int) $this->fk_multicurrency;
836
		$sql.= ", '".$this->db->escape($this->multicurrency_code)."'";
837
		$sql.= ", ".(double) $this->multicurrency_tx;
838
        $sql.= ")";
839
840
        dol_syslog(get_class($this)."::create", LOG_DEBUG);
841
        $resql=$this->db->query($sql);
842
        if ($resql)
843
        {
844
            $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."supplier_proposal");
845
846
            if ($this->id)
847
            {
848
                $this->ref='(PROV'.$this->id.')';
849
                $sql = 'UPDATE '.MAIN_DB_PREFIX."supplier_proposal SET ref='".$this->db->escape($this->ref)."' WHERE rowid=".$this->id;
850
851
                dol_syslog(get_class($this)."::create", LOG_DEBUG);
852
                $resql=$this->db->query($sql);
853
                if (! $resql) $error++;
854
855
                if (! empty($this->linkedObjectsIds) && empty($this->linked_objects))	// To use new linkedObjectsIds instead of old linked_objects
856
                {
857
                	$this->linked_objects = $this->linkedObjectsIds;	// TODO Replace linked_objects with linkedObjectsIds
858
                }
859
860
                // Add object linked
861
                if (! $error && $this->id && is_array($this->linked_objects) && ! empty($this->linked_objects))
862
                {
863
                	foreach($this->linked_objects as $origin => $tmp_origin_id)
864
                	{
865
                		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, ...))
866
                		{
867
                			foreach($tmp_origin_id as $origin_id)
868
                			{
869
                				$ret = $this->add_object_linked($origin, $origin_id);
870
                				if (! $ret)
871
                				{
872
                					dol_print_error($this->db);
873
                					$error++;
874
                				}
875
                			}
876
                		}
877
                	}
878
                }
879
880
                // Add linked object (deprecated, use ->linkedObjectsIds instead)
881
                if (! $error && $this->origin && $this->origin_id)
882
                {
883
                	$ret = $this->add_object_linked();
884
                	if (! $ret)	dol_print_error($this->db);
885
                }
886
887
                /*
888
                 *  Insertion du detail des produits dans la base
889
                 */
890
                if (! $error)
891
                {
892
                    $fk_parent_line=0;
893
                    $num=count($this->lines);
894
895
                    for ($i=0;$i<$num;$i++)
896
                    {
897
                        // Reset fk_parent_line for no child products and special product
898
                        if (($this->lines[$i]->product_type != 9 && empty($this->lines[$i]->fk_parent_line)) || $this->lines[$i]->product_type == 9) {
899
                            $fk_parent_line = 0;
900
                        }
901
902
						$result = $this->addline(
903
							$this->lines[$i]->desc,
904
							$this->lines[$i]->subprice,
905
							$this->lines[$i]->qty,
906
							$this->lines[$i]->tva_tx,
907
							$this->lines[$i]->localtax1_tx,
908
							$this->lines[$i]->localtax2_tx,
909
							$this->lines[$i]->fk_product,
910
							$this->lines[$i]->remise_percent,
911
							'HT',
912
							0,
913
							0,
914
							$this->lines[$i]->product_type,
915
							$this->lines[$i]->rang,
916
							$this->lines[$i]->special_code,
917
							$fk_parent_line,
918
							$this->lines[$i]->fk_fournprice,
919
							$this->lines[$i]->pa_ht,
920
							$this->lines[$i]->label,
921
							$this->lines[$i]->array_options,
922
							$this->lines[$i]->ref_fourn,
923
							$this->lines[$i]->fk_unit,
924
							'supplier_proposal',
925
							$this->lines[$i]->rowid
926
						);
927
928
                        if ($result < 0)
929
                        {
930
                            $error++;
931
                            $this->error=$this->db->error;
932
                            dol_print_error($this->db);
933
                            break;
934
                        }
935
                        // Defined the new fk_parent_line
936
                        if ($result > 0 && $this->lines[$i]->product_type == 9) {
937
                            $fk_parent_line = $result;
938
                        }
939
                    }
940
                }
941
942
                if (! $error)
943
                {
944
                    // Mise a jour infos denormalisees
945
                    $resql=$this->update_price(1);
946
                    if ($resql)
947
                    {
948
                    	$action='update';
949
950
                    	// Actions on extra fields
951
                   		if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
952
                   		{
953
                   			$result=$this->insertExtraFields();
954
                   			if ($result < 0)
955
                   			{
956
                   				$error++;
957
                   			}
958
                    	}
959
960
                        if (! $erro && ! $notrigger)
0 ignored issues
show
Bug introduced by
The variable $erro does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
961
                        {
962
                            // Call trigger
963
                            $result=$this->call_trigger('PROPAL_SUPPLIER_CREATE',$user);
964
                            if ($result < 0) { $error++; }
965
                            // End call triggers
966
                        }
967
                    }
968
                    else
969
					{
970
                        $this->error=$this->db->lasterror();
971
                        $error++;
972
                    }
973
                }
974
            }
975
            else
976
			{
977
                $this->error=$this->db->lasterror();
978
                $error++;
979
            }
980
981
            if (! $error)
982
            {
983
                $this->db->commit();
984
                dol_syslog(get_class($this)."::create done id=".$this->id);
985
                return $this->id;
986
            }
987
            else
988
            {
989
                $this->db->rollback();
990
                return -2;
991
            }
992
        }
993
        else
994
        {
995
            $this->error=$this->db->lasterror();
996
            $this->db->rollback();
997
            return -1;
998
        }
999
    }
1000
1001
1002
    /**
1003
     *	Insert into DB a supplier_proposal object completely defined by its data members (ex, results from copy).
1004
     *
1005
     *	@param 		User	$user	User that create
1006
     *	@return    	int				Id of the new object if ok, <0 if ko
1007
     *	@see       	create
1008
     */
1009
    function create_from($user)
1010
    {
1011
        $this->products=$this->lines;
1012
1013
        return $this->create($user);
1014
    }
1015
1016
    /**
1017
     *		Load an object from its id and create a new one in database
1018
     *
1019
     *		@param		int				$socid			Id of thirdparty
1020
     * 	 	@return		int								New id of clone
1021
     */
1022
    function createFromClone($socid=0)
1023
    {
1024
        global $user,$langs,$conf,$hookmanager;
1025
1026
        $error=0;
1027
        $now=dol_now();
1028
1029
        $this->db->begin();
1030
1031
		// get extrafields so they will be clone
1032
		foreach($this->lines as $line)
1033
			$line->fetch_optionals();
1034
1035
		// Load source object
1036
		$objFrom = clone $this;
1037
1038
        $objsoc=new Societe($this->db);
1039
1040
        // Change socid if needed
1041
        if (! empty($socid) && $socid != $this->socid)
1042
        {
1043
            if ($objsoc->fetch($socid) > 0)
1044
            {
1045
                $this->socid 				= $objsoc->id;
1046
                $this->cond_reglement_id	= (! empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
1047
                $this->mode_reglement_id	= (! empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
1048
                $this->fk_project			= '';
1049
            }
1050
1051
            // TODO Change product price if multi-prices
1052
        }
1053
        else
1054
        {
1055
            $objsoc->fetch($this->socid);
1056
        }
1057
1058
        $this->id=0;
1059
        $this->statut=0;
1060
1061
        if (empty($conf->global->SUPPLIER_PROPOSAL_ADDON) || ! is_readable(DOL_DOCUMENT_ROOT ."/core/modules/supplier_proposal/".$conf->global->SUPPLIER_PROPOSAL_ADDON.".php"))
1062
        {
1063
            $this->error='ErrorSetupNotComplete';
1064
            return -1;
1065
        }
1066
1067
        // Clear fields
1068
        $this->user_author	= $user->id;
1069
        $this->user_valid	= '';
1070
        $this->date			= $now;
1071
1072
        // Set ref
1073
        require_once DOL_DOCUMENT_ROOT ."/core/modules/supplier_proposal/".$conf->global->SUPPLIER_PROPOSAL_ADDON.'.php';
1074
        $obj = $conf->global->SUPPLIER_PROPOSAL_ADDON;
1075
        $modSupplierProposal = new $obj;
1076
        $this->ref = $modSupplierProposal->getNextValue($objsoc,$this);
1077
1078
        // Create clone
1079
        $result=$this->create($user);
1080
        if ($result < 0) $error++;
1081
1082
        if (! $error)
1083
        {
1084
            // Hook of thirdparty module
1085
            if (is_object($hookmanager))
1086
            {
1087
                $parameters=array('objFrom'=>$objFrom);
1088
                $action='';
1089
                $reshook=$hookmanager->executeHooks('createFrom',$parameters,$this,$action);    // Note that $action and $object may have been modified by some hooks
1090
                if ($reshook < 0) $error++;
1091
            }
1092
        }
1093
1094
        // End
1095
        if (! $error)
1096
        {
1097
            $this->db->commit();
1098
            return $this->id;
1099
        }
1100
        else
1101
        {
1102
            $this->db->rollback();
1103
            return -1;
1104
        }
1105
    }
1106
1107
    /**
1108
     *	Load a proposal from database and its ligne array
1109
     *
1110
     *	@param      int			$rowid		id of object to load
1111
     *	@param		string		$ref		Ref of proposal
1112
     *	@return     int         			>0 if OK, <0 if KO
1113
     */
1114
    function fetch($rowid,$ref='')
1115
    {
1116
        global $conf;
1117
1118
        $sql = "SELECT p.rowid, p.entity, p.ref, p.remise, p.remise_percent, p.remise_absolue, p.fk_soc";
1119
        $sql.= ", p.total, p.tva, p.localtax1, p.localtax2, p.total_ht";
1120
        $sql.= ", p.datec";
1121
        $sql.= ", p.date_valid as datev";
1122
        $sql.= ", p.date_livraison as date_livraison";
1123
        $sql.= ", p.model_pdf, p.extraparams";
1124
        $sql.= ", p.note_private, p.note_public";
1125
        $sql.= ", p.fk_projet, p.fk_statut";
1126
        $sql.= ", p.fk_user_author, p.fk_user_valid, p.fk_user_cloture";
1127
        $sql.= ", p.fk_cond_reglement";
1128
        $sql.= ", p.fk_mode_reglement";
1129
        $sql.= ', p.fk_account';
1130
        $sql.= ", p.fk_shipping_method";
1131
		$sql.= ", p.fk_multicurrency, p.multicurrency_code, p.multicurrency_tx, p.multicurrency_total_ht, p.multicurrency_total_tva, p.multicurrency_total_ttc";
1132
        $sql.= ", c.label as statut_label";
1133
        $sql.= ", cr.code as cond_reglement_code, cr.libelle as cond_reglement, cr.libelle_facture as cond_reglement_libelle_doc";
1134
        $sql.= ", cp.code as mode_reglement_code, cp.libelle as mode_reglement";
1135
        $sql.= " FROM ".MAIN_DB_PREFIX."c_propalst as c, ".MAIN_DB_PREFIX."supplier_proposal as p";
1136
        $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as cp ON p.fk_mode_reglement = cp.id';
1137
        $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_payment_term as cr ON p.fk_cond_reglement = cr.rowid';
1138
        $sql.= " WHERE p.fk_statut = c.id";
1139
        $sql.= " AND p.entity IN (".getEntity('supplier_proposal').")";
1140
        if ($ref) $sql.= " AND p.ref='".$ref."'";
1141
        else $sql.= " AND p.rowid=".$rowid;
1142
1143
        dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
1144
        $resql=$this->db->query($sql);
1145
        if ($resql)
1146
        {
1147
            if ($this->db->num_rows($resql))
1148
            {
1149
                $obj = $this->db->fetch_object($resql);
1150
1151
                $this->id                   = $obj->rowid;
1152
                $this->entity               = $obj->entity;
1153
1154
                $this->ref                  = $obj->ref;
1155
                $this->remise               = $obj->remise;
1156
                $this->remise_percent       = $obj->remise_percent;
1157
                $this->remise_absolue       = $obj->remise_absolue;
1158
                $this->total                = $obj->total; // TODO deprecated
1159
                $this->total_ht             = $obj->total_ht;
1160
                $this->total_tva            = $obj->tva;
1161
                $this->total_localtax1		= $obj->localtax1;
1162
                $this->total_localtax2		= $obj->localtax2;
1163
                $this->total_ttc            = $obj->total;
1164
                $this->socid                = $obj->fk_soc;
1165
                $this->fk_project           = $obj->fk_projet;
1166
                $this->modelpdf             = $obj->model_pdf;
1167
                $this->note                 = $obj->note_private; // TODO deprecated
1168
                $this->note_private         = $obj->note_private;
1169
                $this->note_public          = $obj->note_public;
1170
                $this->statut               = (int) $obj->fk_statut;
1171
                $this->statut_libelle       = $obj->statut_label;
1172
                $this->datec                = $this->db->jdate($obj->datec); // TODO deprecated
1173
                $this->datev                = $this->db->jdate($obj->datev); // TODO deprecated
1174
                $this->date_creation		= $this->db->jdate($obj->datec); //Creation date
1175
                $this->date_validation		= $this->db->jdate($obj->datev); //Validation date
1176
                $this->date_livraison       = $this->db->jdate($obj->date_livraison);
1177
                $this->shipping_method_id   = ($obj->fk_shipping_method>0)?$obj->fk_shipping_method:null;
1178
1179
                $this->mode_reglement_id    = $obj->fk_mode_reglement;
1180
                $this->mode_reglement_code  = $obj->mode_reglement_code;
1181
                $this->mode_reglement       = $obj->mode_reglement;
1182
                $this->fk_account           = ($obj->fk_account>0)?$obj->fk_account:null;
1183
                $this->cond_reglement_id    = $obj->fk_cond_reglement;
1184
                $this->cond_reglement_code  = $obj->cond_reglement_code;
1185
                $this->cond_reglement       = $obj->cond_reglement;
1186
                $this->cond_reglement_doc   = $obj->cond_reglement_libelle_doc;
1187
1188
                $this->extraparams			= (array) json_decode($obj->extraparams, true);
1189
1190
                $this->user_author_id = $obj->fk_user_author;
1191
                $this->user_valid_id  = $obj->fk_user_valid;
1192
                $this->user_close_id  = $obj->fk_user_cloture;
1193
1194
				// Multicurrency
1195
				$this->fk_multicurrency 		= $obj->fk_multicurrency;
1196
				$this->multicurrency_code 		= $obj->multicurrency_code;
1197
				$this->multicurrency_tx 		= $obj->multicurrency_tx;
1198
				$this->multicurrency_total_ht 	= $obj->multicurrency_total_ht;
1199
				$this->multicurrency_total_tva 	= $obj->multicurrency_total_tva;
1200
				$this->multicurrency_total_ttc 	= $obj->multicurrency_total_ttc;
1201
1202
                if ($obj->fk_statut == 0)
1203
                {
1204
                    $this->brouillon = 1;
1205
                }
1206
1207
                // Retreive all extrafield
1208
                // fetch optionals attributes and labels
1209
                $this->fetch_optionals();
1210
1211
                $this->db->free($resql);
1212
1213
                $this->lines = array();
1214
1215
                // Lines of supplier proposals
1216
                $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,";
1217
				$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,";
1218
                $sql.= ' p.ref as product_ref, p.description as product_desc, p.fk_product_type, p.label as product_label,';
1219
                $sql.= ' d.ref_fourn as ref_produit_fourn,';
1220
				$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';
1221
                $sql.= " FROM ".MAIN_DB_PREFIX."supplier_proposaldet as d";
1222
                $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON d.fk_product = p.rowid";
1223
                $sql.= " WHERE d.fk_supplier_proposal = ".$this->id;
1224
                $sql.= " ORDER by d.rang";
1225
1226
                $result = $this->db->query($sql);
1227
                if ($result)
1228
                {
1229
                    $num = $this->db->num_rows($result);
1230
                    $i = 0;
1231
1232
                    while ($i < $num)
1233
                    {
1234
                        $objp                   = $this->db->fetch_object($result);
1235
1236
                        $line                   = new SupplierProposalLine($this->db);
1237
1238
                        $line->rowid			= $objp->rowid; // deprecated
1239
                        $line->id				= $objp->rowid;
1240
                        $line->fk_supplier_proposal		= $objp->fk_supplier_proposal;
1241
                        $line->fk_parent_line	= $objp->fk_parent_line;
1242
                        $line->product_type     = $objp->product_type;
1243
                        $line->label            = $objp->custom_label;
1244
                        $line->desc             = $objp->description;  // Description ligne
1245
                        $line->qty              = $objp->qty;
1246
                        $line->tva_tx           = $objp->tva_tx;
1247
                        $line->localtax1_tx		= $objp->localtax1_tx;
1248
                        $line->localtax2_tx		= $objp->localtax2_tx;
1249
                        $line->subprice         = $objp->subprice;
1250
                        $line->fk_remise_except = $objp->fk_remise_except;
1251
                        $line->remise_percent   = $objp->remise_percent;
1252
                        $line->price            = $objp->price;		// TODO deprecated
1253
1254
                        $line->info_bits        = $objp->info_bits;
1255
                        $line->total_ht         = $objp->total_ht;
1256
                        $line->total_tva        = $objp->total_tva;
1257
                        $line->total_localtax1	= $objp->total_localtax1;
1258
                        $line->total_localtax2	= $objp->total_localtax2;
1259
                        $line->total_ttc        = $objp->total_ttc;
1260
      					$line->fk_fournprice 	= $objp->fk_fournprice;
1261
						$marginInfos			= getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $line->fk_fournprice, $objp->pa_ht);
1262
						$line->pa_ht 			= $marginInfos[0];
1263
						$line->marge_tx			= $marginInfos[1];
1264
						$line->marque_tx		= $marginInfos[2];
1265
                        $line->special_code     = $objp->special_code;
1266
                        $line->rang             = $objp->rang;
1267
1268
                        $line->fk_product       = $objp->fk_product;
1269
1270
                        $line->ref				= $objp->product_ref;		// TODO deprecated
1271
                        $line->product_ref		= $objp->product_ref;
1272
                        $line->libelle			= $objp->product_label;		// TODO deprecated
1273
                        $line->product_label	= $objp->product_label;
1274
                        $line->product_desc     = $objp->product_desc; 		// Description produit
1275
                        $line->fk_product_type  = $objp->fk_product_type;
1276
1277
						$line->ref_fourn		= $objp->ref_produit_fourn;
1278
1279
						// Multicurrency
1280
						$line->fk_multicurrency 		= $objp->fk_multicurrency;
1281
						$line->multicurrency_code 		= $objp->multicurrency_code;
1282
						$line->multicurrency_subprice 	= $objp->multicurrency_subprice;
1283
						$line->multicurrency_total_ht 	= $objp->multicurrency_total_ht;
1284
						$line->multicurrency_total_tva 	= $objp->multicurrency_total_tva;
1285
						$line->multicurrency_total_ttc 	= $objp->multicurrency_total_ttc;
1286
						$line->fk_unit					= $objp->fk_unit;
1287
1288
                        $this->lines[$i]        = $line;
1289
1290
                        $i++;
1291
                    }
1292
                    $this->db->free($result);
1293
                }
1294
                else
1295
                {
1296
                    $this->error=$this->db->error();
1297
                    return -1;
1298
                }
1299
1300
                // Retreive all extrafield
1301
                // fetch optionals attributes and labels
1302
                $this->fetch_optionals();
1303
1304
                return 1;
1305
            }
1306
1307
            $this->error="Record Not Found";
1308
            return 0;
1309
        }
1310
        else
1311
        {
1312
            $this->error=$this->db->error();
1313
            return -1;
1314
        }
1315
    }
1316
1317
    /**
1318
     *  Set status to validated
1319
     *
1320
     *  @param	User	$user       Object user that validate
1321
     *  @param	int		$notrigger	1=Does not execute triggers, 0= execute triggers
1322
     *  @return int         		<0 if KO, >=0 if OK
1323
     */
1324
    function valid($user, $notrigger=0)
1325
    {
1326
    	require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1327
1328
    	global $conf,$langs;
1329
1330
        $error=0;
1331
        $now=dol_now();
1332
1333
        if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->supplier_proposal->creer))
1334
       	|| (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->supplier_proposal->validate_advance)))
1335
        {
1336
            $this->db->begin();
1337
1338
            // Numbering module definition
1339
            $soc = new Societe($this->db);
1340
            $soc->fetch($this->socid);
1341
1342
            // Define new ref
1343
            if (! $error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) // empty should not happened, but when it occurs, the test save life
1344
            {
1345
            	$num = $this->getNextNumRef($soc);
1346
            }
1347
            else
1348
            {
1349
            	$num = $this->ref;
1350
            }
1351
            $this->newref = $num;
1352
1353
            $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal";
1354
            $sql.= " SET ref = '".$this->db->escape($num)."',";
1355
            $sql.= " fk_statut = 1, date_valid='".$this->db->idate($now)."', fk_user_valid=".$user->id;
1356
            $sql.= " WHERE rowid = ".$this->id." AND fk_statut = 0";
1357
1358
            dol_syslog(get_class($this)."::valid", LOG_DEBUG);
1359
			$resql=$this->db->query($sql);
1360
			if (! $resql)
1361
			{
1362
				dol_print_error($this->db);
1363
				$error++;
1364
			}
1365
1366
   			// Trigger calls
1367
			if (! $error && ! $notrigger)
1368
			{
1369
                // Call trigger
1370
                $result=$this->call_trigger('SUPPLIER_PROPOSAL_VALIDATE',$user);
1371
                if ($result < 0) { $error++; }
1372
                // End call triggers
1373
            }
1374
1375
            if (! $error)
1376
            {
1377
            	$this->oldref = $this->ref;
1378
1379
            	// Rename directory if dir was a temporary ref
1380
            	if (preg_match('/^[\(]?PROV/i', $this->ref))
1381
            	{
1382
            		// Rename of propal directory ($this->ref = old ref, $num = new ref)
1383
            		// to  not lose the linked files
1384
            		$oldref = dol_sanitizeFileName($this->ref);
1385
            		$newref = dol_sanitizeFileName($num);
1386
            		$dirsource = $conf->supplier_proposal->dir_output.'/'.$oldref;
1387
            		$dirdest = $conf->supplier_proposal->dir_output.'/'.$newref;
1388
1389
            		if (file_exists($dirsource))
1390
            		{
1391
            			dol_syslog(get_class($this)."::validate rename dir ".$dirsource." into ".$dirdest);
1392
            			if (@rename($dirsource, $dirdest))
1393
            			{
1394
            				dol_syslog("Rename ok");
1395
            				// Rename docs starting with $oldref with $newref
1396
            				$listoffiles=dol_dir_list($conf->supplier_proposal->dir_output.'/'.$newref, 'files', 1, '^'.preg_quote($oldref,'/'));
1397
            				foreach($listoffiles as $fileentry)
1398
            				{
1399
            					$dirsource=$fileentry['name'];
1400
            					$dirdest=preg_replace('/^'.preg_quote($oldref,'/').'/',$newref, $dirsource);
1401
            					$dirsource=$fileentry['path'].'/'.$dirsource;
1402
            					$dirdest=$fileentry['path'].'/'.$dirdest;
1403
            					@rename($dirsource, $dirdest);
1404
            				}
1405
            			}
1406
            		}
1407
            	}
1408
1409
            	$this->ref=$num;
1410
            	$this->brouillon=0;
1411
            	$this->statut = 1;
1412
            	$this->user_valid_id=$user->id;
1413
            	$this->datev=$now;
1414
1415
            	$this->db->commit();
1416
            	return 1;
1417
            }
1418
            else
1419
			{
1420
            	$this->db->rollback();
1421
            	return -1;
1422
            }
1423
        }
1424
        else
1425
        {
1426
        	dol_syslog("You don't have permission to validate supplier proposal", LOG_WARNING);
1427
        	return -2;
1428
        }
1429
    }
1430
1431
    /**
1432
     *	Set delivery date
1433
     *
1434
     *	@param      User 		$user        		Object user that modify
1435
     *	@param      int			$date_livraison     Delivery date
1436
     *	@return     int         					<0 if ko, >0 if ok
1437
     */
1438
    function set_date_livraison($user, $date_livraison)
1439
    {
1440
        if (! empty($user->rights->supplier_proposal->creer))
1441
        {
1442
            $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal ";
1443
            $sql.= " SET date_livraison = ".($date_livraison!=''?"'".$this->db->idate($date_livraison)."'":'null');
1444
            $sql.= " WHERE rowid = ".$this->id;
1445
1446
            if ($this->db->query($sql))
1447
            {
1448
                $this->date_livraison = $date_livraison;
1449
                return 1;
1450
            }
1451
            else
1452
            {
1453
                $this->error=$this->db->error();
1454
                dol_syslog(get_class($this)."::set_date_livraison Erreur SQL");
1455
                return -1;
1456
            }
1457
        }
1458
    }
1459
1460
    /**
1461
     *	Set an overall discount on the proposal
1462
     *
1463
     *	@param      User	$user       Object user that modify
1464
     *	@param      double	$remise      Amount discount
1465
     *	@return     int         		<0 if ko, >0 if ok
1466
     */
1467
    function set_remise_percent($user, $remise)
1468
    {
1469
        $remise=trim($remise)?trim($remise):0;
1470
1471
        if (! empty($user->rights->supplier_proposal->creer))
1472
        {
1473
            $remise = price2num($remise);
1474
1475
            $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal SET remise_percent = ".$remise;
1476
            $sql.= " WHERE rowid = ".$this->id." AND fk_statut = 0";
1477
1478
            if ($this->db->query($sql) )
1479
            {
1480
                $this->remise_percent = $remise;
1 ignored issue
show
Documentation Bug introduced by
It seems like $remise of type string or double is incompatible with the declared type integer of property $remise_percent.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
1481
                $this->update_price(1);
1482
                return 1;
1483
            }
1484
            else
1485
            {
1486
                $this->error=$this->db->error();
1487
                return -1;
1488
            }
1489
        }
1490
    }
1491
1492
1493
    /**
1494
     *	Set an absolute overall discount on the proposal
1495
     *
1496
     *	@param      User	$user        Object user that modify
1497
     *	@param      double	$remise      Amount discount
1498
     *	@return     int         		<0 if ko, >0 if ok
1499
     */
1500
    function set_remise_absolue($user, $remise)
1501
    {
1502
        $remise=trim($remise)?trim($remise):0;
1503
1504
        if (! empty($user->rights->supplier_proposal->creer))
1505
        {
1506
            $remise = price2num($remise);
1507
1508
            $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal ";
1509
            $sql.= " SET remise_absolue = ".$remise;
1510
            $sql.= " WHERE rowid = ".$this->id." AND fk_statut = 0";
1511
1512
            if ($this->db->query($sql) )
1513
            {
1514
                $this->remise_absolue = $remise;
0 ignored issues
show
Documentation Bug introduced by
It seems like $remise of type string or double is incompatible with the declared type integer of property $remise_absolue.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
1515
                $this->update_price(1);
1516
                return 1;
1517
            }
1518
            else
1519
            {
1520
                $this->error=$this->db->error();
1521
                return -1;
1522
            }
1523
        }
1524
    }
1525
1526
1527
1528
    /**
1529
     *	Reopen the commercial proposal
1530
     *
1531
     *	@param      User	$user		Object user that close
1532
     *	@param      int		$statut		Statut
1533
     *	@param      string	$note		Comment
1534
     *  @param		int		$notrigger	1=Does not execute triggers, 0= execute triggers
1535
     *	@return     int         		<0 if KO, >0 if OK
1536
     */
1537
    function reopen($user, $statut, $note='', $notrigger=0)
1538
    {
1539
        global $langs,$conf;
1540
1541
        $this->statut = $statut;
1542
        $error=0;
1543
1544
        $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal";
1545
        $sql.= " SET fk_statut = ".$this->statut.",";
1546
		if (! empty($note)) $sql.= " note_private = '".$this->db->escape($note)."',";
1547
        $sql.= " date_cloture=NULL, fk_user_cloture=NULL";
1548
        $sql.= " WHERE rowid = ".$this->id;
1549
1550
    	$this->db->begin();
1551
1552
		dol_syslog(get_class($this)."::reopen", LOG_DEBUG);
1553
		$resql = $this->db->query($sql);
1554
		if (! $resql) {
1555
			$error++; $this->errors[]="Error ".$this->db->lasterror();
1556
		}
1557
		if (! $error)
1558
		{
1559
			if (! $notrigger)
1560
			{
1561
                // Call trigger
1562
                $result=$this->call_trigger('SUPPLIER_PROPOSAL_REOPEN',$user);
1563
                if ($result < 0) { $error++; }
1564
                // End call triggers
1565
			}
1566
		}
1567
1568
		// Commit or rollback
1569
		if ($error)
1570
		{
1571
		    if (!empty($this->errors))
1572
		    {
1573
    			foreach($this->errors as $errmsg)
1574
    			{
1575
    				dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
1576
    				$this->error.=($this->error?', '.$errmsg:$errmsg);
1577
    			}
1578
		    }
1579
			$this->db->rollback();
1580
			return -1*$error;
1581
		}
1582
		else
1583
		{
1584
			$this->db->commit();
1585
			return 1;
1586
		}
1587
    }
1588
1589
1590
    /**
1591
     *	Close the askprice
1592
     *
1593
     *	@param      User	$user		Object user that close
1594
     *	@param      int		$statut		Statut
1595
     *	@param      string	$note		Comment
1596
     *	@return     int         		<0 if KO, >0 if OK
1597
     */
1598
    function cloture($user, $statut, $note)
1599
    {
1600
        global $langs,$conf;
1601
1602
        $this->statut = $statut;
1603
        $error=0;
1604
        $now=dol_now();
1605
1606
        $this->db->begin();
1607
1608
        $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal";
1609
        $sql.= " SET fk_statut = ".$statut.", note_private = '".$this->db->escape($note)."', date_cloture='".$this->db->idate($now)."', fk_user_cloture=".$user->id;
1610
        $sql.= " WHERE rowid = ".$this->id;
1611
1612
        $resql=$this->db->query($sql);
1613
        if ($resql)
1614
        {
1615
        	$modelpdf=$conf->global->SUPPLIER_PROPOSAL_ADDON_PDF_ODT_CLOSED?$conf->global->SUPPLIER_PROPOSAL_ADDON_PDF_ODT_CLOSED:$this->modelpdf;
1616
        	$trigger_name='SUPPLIER_PROPOSAL_CLOSE_REFUSED';
1617
1618
            if ($statut == 2)
1619
            {
1620
            	$trigger_name='SUPPLIER_PROPOSAL_CLOSE_SIGNED';
1621
				$modelpdf=$conf->global->SUPPLIER_PROPOSAL_ADDON_PDF_ODT_TOBILL?$conf->global->SUPPLIER_PROPOSAL_ADDON_PDF_ODT_TOBILL:$this->modelpdf;
1622
1623
                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
1624
                {
1625
                    $result = $this->updateOrCreatePriceFournisseur($user);
1626
                }
1627
1628
            }
1629
            if ($statut == 4)
1630
            {
1631
            	$trigger_name='SUPPLIER_PROPOSAL_CLASSIFY_BILLED';
1632
            }
1633
1634
            if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
1635
            {
1636
             	// Define output language
1637
              	$outputlangs = $langs;
1638
               	if (! empty($conf->global->MAIN_MULTILANGS))
1639
               	{
1640
               		$outputlangs = new Translate("",$conf);
1641
               		$newlang=(GETPOST('lang_id','aZ09') ? GETPOST('lang_id','aZ09') : $this->thirdparty->default_lang);
1642
               		$outputlangs->setDefaultLang($newlang);
1643
               	}
1644
               	//$ret=$object->fetch($id);    // Reload to get new records
1645
	               $this->generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
0 ignored issues
show
Bug introduced by
The variable $hidedetails does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $hidedesc does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $hideref does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
1646
            }
1647
1648
            // Call trigger
1649
            $result=$this->call_trigger($trigger_name,$user);
1650
            if ($result < 0) { $error++; }
1651
            // End call triggers
1652
1653
            if ( ! $error )
1654
            {
1655
                $this->db->commit();
1656
                return 1;
1657
            }
1658
            else
1659
            {
1660
                $this->db->rollback();
1661
                return -1;
1662
            }
1663
        }
1664
        else
1665
        {
1666
            $this->error=$this->db->lasterror();
1667
            $this->errors[]=$this->db->lasterror();
1668
            $this->db->rollback();
1669
            return -1;
1670
        }
1671
    }
1672
1673
	/**
1674
     *	Add or update supplier price according to result of proposal
1675
     *
1676
	 *	@param     User	    $user       Object user
1677
	 *  @return    int                  > 0 if OK
1678
     */
1679
	function updateOrCreatePriceFournisseur($user)
1680
	{
1681
		$productsupplier = new ProductFournisseur($this->db);
1682
1683
		dol_syslog(get_class($this)."::updateOrCreatePriceFournisseur", LOG_DEBUG);
1684
		foreach ($this->lines as $product)
1685
		{
1686
			if ($product->subprice <= 0) continue;
1687
1688
			$idProductFourn = $productsupplier->find_min_price_product_fournisseur($product->fk_product, $product->qty);
1689
			$res = $productsupplier->fetch($idProductFourn);
1690
1691
			if ($productsupplier->id) {
1692
				if ($productsupplier->fourn_qty == $product->qty) {
1693
					$this->updatePriceFournisseur($productsupplier->product_fourn_price_id, $product, $user);
1694
				} else {
1695
					$this->createPriceFournisseur($product, $user);
1696
				}
1697
			} else {
1698
				$this->createPriceFournisseur($product, $user);
1699
			}
1700
		}
1701
1702
		return 1;
1703
	}
1704
1705
	/**
1706
     *	Upate ProductFournisseur
1707
     *
1708
	 * 	@param		int 	$idProductFournPrice	id of llx_product_fournisseur_price
1709
	 * 	@param		int 	$product				contain informations to update
1710
	 *	@param      User	$user					Object user
1711
     *	@return     int         					<0 if KO, >0 if OK
1712
     */
1713
     function updatePriceFournisseur($idProductFournPrice, $product, $user) {
1714
		$price=price2num($product->subprice*$product->qty,'MU');
1715
		$unitPrice = price2num($product->subprice,'MU');
1716
1717
		$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;
1718
1719
		$resql = $this->db->query($sql);
1720
		if (!$resql) {
1721
			$this->error=$this->db->error();
1722
            $this->db->rollback();
1723
            return -1;
1724
		}
1725
	 }
1726
1727
	 /**
1728
     *	Create ProductFournisseur
1729
	 *
1730
     *	@param		Product 	$product	Object Product
1731
	 *	@param      User		$user		Object user
1732
     *	@return     int         			<0 if KO, >0 if OK
1733
     */
1734
	 function createPriceFournisseur($product, $user) {
1735
	 	$price=price2num($product->subprice*$product->qty,'MU');
1736
	    $qty=price2num($product->qty);
1737
		$unitPrice = price2num($product->subprice,'MU');
1738
		$now=dol_now();
1739
1740
		$values = array(
1741
			"'".$this->db->idate($now)."'",
1742
			$product->fk_product,
1743
			$this->thirdparty->id,
1744
			"'".$product->ref_fourn."'",
1745
			$price,
1746
			$qty,
1747
			$unitPrice,
1748
			$product->tva_tx,
1749
			$user->id
1750
		);
1751
1752
		$sql = 'INSERT INTO '.MAIN_DB_PREFIX.'product_fournisseur_price ';
1753
		$sql .= '(datec, fk_product, fk_soc, ref_fourn, price, quantity, unitprice, tva_tx, fk_user) VALUES ('.implode(',', $values).')';
1754
1755
		$resql = $this->db->query($sql);
1756
		if (!$resql) {
1757
			$this->error=$this->db->error();
1758
            $this->db->rollback();
1759
            return -1;
1760
		}
1761
	 }
1762
1763
    /**
1764
     *	Set draft status
1765
     *
1766
     *	@param		User	$user		Object user that modify
1767
     *	@return		int					<0 if KO, >0 if OK
1768
     */
1769
    function set_draft($user)
1770
    {
1771
        global $conf,$langs;
1772
1773
        $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal SET fk_statut = 0";
1774
        $sql.= " WHERE rowid = ".$this->id;
1775
1776
        if ($this->db->query($sql))
1777
        {
1778
            $this->statut = 0;
1779
            $this->brouillon = 1;
1780
            return 1;
1781
        }
1782
        else
1783
        {
1784
            return -1;
1785
        }
1786
    }
1787
1788
1789
    /**
1790
     *    Return list of askprice (eventually filtered on user) into an array
1791
     *
1792
     *    @param	int		$shortlist			0=Return array[id]=ref, 1=Return array[](id=>id,ref=>ref,name=>name)
1793
     *    @param	int		$draft				0=not draft, 1=draft
1794
     *    @param	int		$notcurrentuser		0=all user, 1=not current user
1795
     *    @param    int		$socid				Id third pary
1796
     *    @param    int		$limit				For pagination
1797
     *    @param    int		$offset				For pagination
1798
     *    @param    string	$sortfield			Sort criteria
1799
     *    @param    string	$sortorder			Sort order
1800
     *    @return	int		       				-1 if KO, array with result if OK
1801
     */
1802
    function liste_array($shortlist=0, $draft=0, $notcurrentuser=0, $socid=0, $limit=0, $offset=0, $sortfield='p.datec', $sortorder='DESC')
1803
    {
1804
        global $conf,$user;
1805
1806
        $ga = array();
1807
1808
        $sql = "SELECT s.rowid, s.nom as name, s.client,";
1809
        $sql.= " p.rowid as supplier_proposalid, p.fk_statut, p.total_ht, p.ref, p.remise, ";
1810
        $sql.= " p.datep as dp, p.fin_validite as datelimite";
1811
        if (! $user->rights->societe->client->voir && ! $socid) $sql .= ", sc.fk_soc, sc.fk_user";
1812
        $sql.= " FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."supplier_proposal as p, ".MAIN_DB_PREFIX."c_propalst as c";
1813
		if (! $user->rights->societe->client->voir && ! $socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
1814
        $sql.= " WHERE p.entity IN (".getEntity('supplier_proposal').")";
1815
        $sql.= " AND p.fk_soc = s.rowid";
1816
        $sql.= " AND p.fk_statut = c.id";
1817
        if (! $user->rights->societe->client->voir && ! $socid) //restriction
1818
        {
1819
        	$sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id;
1820
        }
1821
        if ($socid) $sql.= " AND s.rowid = ".$socid;
1822
        if ($draft)	$sql.= " AND p.fk_statut = 0";
1823
        if ($notcurrentuser > 0) $sql.= " AND p.fk_user_author <> ".$user->id;
1824
        $sql.= $this->db->order($sortfield,$sortorder);
1825
        $sql.= $this->db->plimit($limit,$offset);
1826
1827
        $result=$this->db->query($sql);
1828
        if ($result)
1829
        {
1830
            $num = $this->db->num_rows($result);
1831
            if ($num)
1832
            {
1833
                $i = 0;
1834
                while ($i < $num)
1835
                {
1836
                    $obj = $this->db->fetch_object($result);
1837
1838
                    if ($shortlist == 1)
1839
                    {
1840
                        $ga[$obj->supplier_proposalid] = $obj->ref;
1841
                    }
1842
                    else if ($shortlist == 2)
1843
                    {
1844
                        $ga[$obj->supplier_proposalid] = $obj->ref.' ('.$obj->name.')';
1845
                    }
1846
                    else
1847
					{
1848
                        $ga[$i]['id']	= $obj->supplier_proposalid;
1849
                        $ga[$i]['ref'] 	= $obj->ref;
1850
                        $ga[$i]['name'] = $obj->name;
1851
                    }
1852
1853
                    $i++;
1854
                }
1855
            }
1856
            return $ga;
1857
        }
1858
        else
1859
        {
1860
            dol_print_error($this->db);
1861
            return -1;
1862
        }
1863
    }
1864
1865
    /**
1866
     *	Delete askprice
1867
     *
1868
     *	@param	User	$user        	Object user that delete
1869
     *	@param	int		$notrigger		1=Does not execute triggers, 0= execute triggers
1870
     *	@return	int						1 if ok, otherwise if error
1871
     */
1872
    function delete($user, $notrigger=0)
1873
    {
1874
        global $conf,$langs;
1875
        require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1876
1877
        $error=0;
1878
1879
        $this->db->begin();
1880
1881
        if (! $notrigger)
1882
        {
1883
            // Call trigger
1884
            $result=$this->call_trigger('SUPPLIER_PROPOSAL_DELETE',$user);
1885
            if ($result < 0) { $error++; }
1886
            // End call triggers
1887
        }
1888
1889
        if (! $error)
1890
        {
1891
            $sql = "DELETE FROM ".MAIN_DB_PREFIX."supplier_proposaldet WHERE fk_supplier_proposal = ".$this->id;
1892
            if ($this->db->query($sql))
1893
            {
1894
                $sql = "DELETE FROM ".MAIN_DB_PREFIX."supplier_proposal WHERE rowid = ".$this->id;
1895
                if ($this->db->query($sql))
1896
                {
1897
                    // Delete linked object
1898
                    $res = $this->deleteObjectLinked();
1899
                    if ($res < 0) $error++;
1900
1901
                    if (! $error)
1902
                    {
1903
                        // We remove directory
1904
                        $ref = dol_sanitizeFileName($this->ref);
1905
                        if ($conf->supplier_proposal->dir_output && !empty($this->ref))
1906
                        {
1907
                            $dir = $conf->supplier_proposal->dir_output . "/" . $ref ;
1908
                            $file = $dir . "/" . $ref . ".pdf";
1909
                            if (file_exists($file))
1910
                            {
1911
                                dol_delete_preview($this);
1912
1913
                                if (! dol_delete_file($file,0,0,0,$this)) // For triggers
1914
                                {
1915
                                    $this->error='ErrorFailToDeleteFile';
1916
                                    $this->errors=array('ErrorFailToDeleteFile');
1917
                                	$this->db->rollback();
1918
                                    return 0;
1919
                                }
1920
                            }
1921
                            if (file_exists($dir))
1922
                            {
1923
                                $res=@dol_delete_dir_recursive($dir);
1924
                                if (! $res)
1925
                                {
1926
                                    $this->error='ErrorFailToDeleteDir';
1927
                                    $this->errors=array('ErrorFailToDeleteDir');
1928
                                    $this->db->rollback();
1929
                                    return 0;
1930
                                }
1931
                            }
1932
                        }
1933
                    }
1934
1935
                    // Removed extrafields
1936
                    if (! $error)
1937
                    {
1938
                    	if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
1939
                    	{
1940
                    		$result=$this->deleteExtraFields();
1941
                    		if ($result < 0)
1942
                    		{
1943
                    			$error++;
1944
                    			$errorflag=-4;
1945
                    			dol_syslog(get_class($this)."::delete erreur ".$errorflag." ".$this->error, LOG_ERR);
1946
                    		}
1947
                    	}
1948
                    }
1949
1950
                    if (! $error)
1951
                    {
1952
                        dol_syslog(get_class($this)."::delete ".$this->id." by ".$user->id, LOG_DEBUG);
1953
                        $this->db->commit();
1954
                        return 1;
1955
                    }
1956
                    else
1957
                    {
1958
                        $this->error=$this->db->lasterror();
1959
                        $this->db->rollback();
1960
                        return 0;
1961
                    }
1962
                }
1963
                else
1964
                {
1965
                    $this->error=$this->db->lasterror();
1966
                    $this->db->rollback();
1967
                    return -3;
1968
                }
1969
            }
1970
            else
1971
            {
1972
                $this->error=$this->db->lasterror();
1973
                $this->db->rollback();
1974
                return -2;
1975
            }
1976
        }
1977
        else
1978
        {
1979
            $this->db->rollback();
1980
            return -1;
1981
        }
1982
    }
1983
1984
    /**
1985
     *	Object SupplierProposal Information
1986
     *
1987
     * 	@param	int		$id		Proposal id
1988
     *  @return	void
1989
     */
1990
    function info($id)
1991
    {
1992
        $sql = "SELECT c.rowid, ";
1993
        $sql.= " c.datec, c.date_valid as datev, c.date_cloture as dateo,";
1994
        $sql.= " c.fk_user_author, c.fk_user_valid, c.fk_user_cloture";
1995
        $sql.= " FROM ".MAIN_DB_PREFIX."supplier_proposal as c";
1996
        $sql.= " WHERE c.rowid = ".$id;
1997
1998
        $result = $this->db->query($sql);
1999
2000
        if ($result)
2001
        {
2002
            if ($this->db->num_rows($result))
2003
            {
2004
                $obj = $this->db->fetch_object($result);
2005
2006
                $this->id                = $obj->rowid;
2007
2008
                $this->date_creation     = $this->db->jdate($obj->datec);
2009
                $this->date_validation   = $this->db->jdate($obj->datev);
2010
                $this->date_cloture      = $this->db->jdate($obj->dateo);
2011
2012
                $cuser = new User($this->db);
2013
                $cuser->fetch($obj->fk_user_author);
2014
                $this->user_creation     = $cuser;
2015
2016
                if ($obj->fk_user_valid)
2017
                {
2018
                    $vuser = new User($this->db);
2019
                    $vuser->fetch($obj->fk_user_valid);
2020
                    $this->user_validation     = $vuser;
2021
                }
2022
2023
                if ($obj->fk_user_cloture)
2024
                {
2025
                    $cluser = new User($this->db);
2026
                    $cluser->fetch($obj->fk_user_cloture);
2027
                    $this->user_cloture     = $cluser;
2028
                }
2029
2030
2031
            }
2032
            $this->db->free($result);
2033
2034
        }
2035
        else
2036
        {
2037
            dol_print_error($this->db);
2038
        }
2039
    }
2040
2041
2042
    /**
2043
     *    	Return label of status of proposal (draft, validated, ...)
2044
     *
2045
     *    	@param      int			$mode        0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto
2046
     *    	@return     string		Label
2047
     */
2048
    function getLibStatut($mode=0)
2049
    {
2050
        return $this->LibStatut($this->statut,$mode);
2051
    }
2052
2053
    /**
2054
     *    	Return label of a status (draft, validated, ...)
2055
     *
2056
     *    	@param      int			$statut		id statut
2057
     *    	@param      int			$mode      	0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto
2058
     *    	@return     string		Label
2059
     */
2060
	function LibStatut($statut,$mode=1)
2061
    {
2062
    	// Init/load array of translation of status
2063
    	if (empty($this->labelstatut) || empty($this->labelstatut_short))
2064
    	{
2065
    		global $langs;
2066
    		$langs->load("supplier_proposal");
2067
    		$this->labelstatut[0]=$langs->trans("SupplierProposalStatusDraft");
2068
    		$this->labelstatut[1]=$langs->trans("SupplierProposalStatusValidated");
2069
    		$this->labelstatut[2]=$langs->trans("SupplierProposalStatusSigned");
2070
    		$this->labelstatut[3]=$langs->trans("SupplierProposalStatusNotSigned");
2071
    		$this->labelstatut[4]=$langs->trans("SupplierProposalStatusClosed");
2072
    		$this->labelstatut_short[0]=$langs->trans("SupplierProposalStatusDraftShort");
2073
    		$this->labelstatut_short[1]=$langs->trans("Opened");
2074
    		$this->labelstatut_short[2]=$langs->trans("SupplierProposalStatusSignedShort");
2075
    		$this->labelstatut_short[3]=$langs->trans("SupplierProposalStatusNotSignedShort");
2076
    		$this->labelstatut_short[4]=$langs->trans("SupplierProposalStatusClosedShort");
2077
    	}
2078
2079
    	$statuttrans='';
2080
		if ($statut==0) $statuttrans='statut0';
2081
		if ($statut==1) $statuttrans='statut1';
2082
		if ($statut==2) $statuttrans='statut3';
2083
		if ($statut==3) $statuttrans='statut5';
2084
		if ($statut==4) $statuttrans='statut6';
2085
2086
		if ($mode == 0)	return $this->labelstatut[$statut];
2087
		if ($mode == 1)	return $this->labelstatut_short[$statut];
2088
		if ($mode == 2)	return img_picto($this->labelstatut[$statut], $statuttrans).' '.$this->labelstatut_short[$statut];
2089
		if ($mode == 3)	return img_picto($this->labelstatut[$statut], $statuttrans);
2090
		if ($mode == 4)	return img_picto($this->labelstatut[$statut],$statuttrans).' '.$this->labelstatut[$statut];
2091
		if ($mode == 5)	return '<span class="hideonsmartphone">'.$this->labelstatut_short[$statut].' </span>'.img_picto($this->labelstatut[$statut],$statuttrans);
2092
		if ($mode == 6)	return '<span class="hideonsmartphone">'.$this->labelstatut[$statut].' </span>'.img_picto($this->labelstatut[$statut],$statuttrans);
2093
	}
2094
2095
2096
    /**
2097
     *      Load indicators for dashboard (this->nbtodo and this->nbtodolate)
2098
     *
2099
     *      @param          User	$user   Object user
2100
     *      @param          int		$mode   "opened" for askprice to close, "signed" for proposal to invoice
2101
     *      @return         int     		<0 if KO, >0 if OK
2102
     */
2103
    function load_board($user,$mode)
2104
    {
2105
        global $conf, $user, $langs;
2106
2107
        $now=dol_now();
2108
2109
        $this->nbtodo=$this->nbtodolate=0;
2110
        $clause = " WHERE";
2111
2112
        $sql = "SELECT p.rowid, p.ref, p.datec as datec";
2113
        $sql.= " FROM ".MAIN_DB_PREFIX."supplier_proposal as p";
2114
        if (!$user->rights->societe->client->voir && !$user->socid)
2115
        {
2116
            $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON p.fk_soc = sc.fk_soc";
2117
            $sql.= " WHERE sc.fk_user = " .$user->id;
2118
            $clause = " AND";
2119
        }
2120
        $sql.= $clause." p.entity IN (".getEntity('supplier_proposal').")";
2121
        if ($mode == 'opened') $sql.= " AND p.fk_statut = 1";
2122
        if ($mode == 'signed') $sql.= " AND p.fk_statut = 2";
2123
        if ($user->socid) $sql.= " AND p.fk_soc = ".$user->socid;
2124
2125
        $resql=$this->db->query($sql);
2126
        if ($resql)
2127
        {
2128
            if ($mode == 'opened') {
2129
	            $delay_warning=$conf->supplier_proposal->cloture->warning_delay;
2130
	            $statut = self::STATUS_VALIDATED;
2131
	            $label = $langs->trans("SupplierProposalsToClose");
2132
            }
2133
            if ($mode == 'signed') {
2134
	            $delay_warning=$conf->supplier_proposal->facturation->warning_delay;
2135
	            $statut = self::STATUS_SIGNED;
2136
	            $label = $langs->trans("SupplierProposalsToProcess");      // May be billed or ordered
2137
            }
2138
2139
	        $response = new WorkboardResponse();
2140
	        $response->warning_delay = $delay_warning/60/60/24;
0 ignored issues
show
Bug introduced by
The variable $delay_warning does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2141
	        $response->label = $label;
0 ignored issues
show
Bug introduced by
The variable $label does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2142
	        $response->url = DOL_URL_ROOT.'/supplier_proposal/list.php?viewstatut='.$statut;
0 ignored issues
show
Bug introduced by
The variable $statut does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2143
	        $response->img = img_object('',"propal");
2144
2145
            // This assignment in condition is not a bug. It allows walking the results.
2146
            while ($obj=$this->db->fetch_object($resql))
2147
            {
2148
                $response->nbtodo++;
2149
                if ($mode == 'opened')
2150
                {
2151
                    $datelimit = $this->db->jdate($obj->datefin);
2152
                    if ($datelimit < ($now - $delay_warning))
2153
                    {
2154
                        $response->nbtodolate++;
2155
                    }
2156
                }
2157
                // TODO Definir regle des propales a facturer en retard
2158
                // if ($mode == 'signed' && ! count($this->FactureListeArray($obj->rowid))) $this->nbtodolate++;
2159
            }
2160
            return $response;
2161
        }
2162
        else
2163
        {
2164
            $this->error=$this->db->lasterror();
2165
            return -1;
2166
        }
2167
    }
2168
2169
2170
    /**
2171
     *  Initialise an instance with random values.
2172
     *  Used to build previews or test instances.
2173
     *	id must be 0 if object instance is a specimen.
2174
     *
2175
     *  @return	void
2176
     */
2177
    function initAsSpecimen()
2178
    {
2179
        global $user,$langs,$conf;
2180
2181
        // Load array of products prodids
2182
        $num_prods = 0;
2183
        $prodids = array();
2184
        $sql = "SELECT rowid";
2185
        $sql.= " FROM ".MAIN_DB_PREFIX."product";
2186
        $sql.= " WHERE entity IN (".getEntity('product').")";
2187
        $resql = $this->db->query($sql);
2188
        if ($resql)
2189
        {
2190
            $num_prods = $this->db->num_rows($resql);
2191
            $i = 0;
2192
            while ($i < $num_prods)
2193
            {
2194
                $i++;
2195
                $row = $this->db->fetch_row($resql);
2196
                $prodids[$i] = $row[0];
2197
            }
2198
        }
2199
2200
        // Initialise parametres
2201
        $this->id=0;
2202
        $this->ref = 'SPECIMEN';
2203
        $this->specimen=1;
2204
        $this->socid = 1;
2205
        $this->date = time();
2206
        $this->cond_reglement_id   = 1;
2207
        $this->cond_reglement_code = 'RECEP';
2208
        $this->mode_reglement_id   = 7;
2209
        $this->mode_reglement_code = 'CHQ';
2210
        $this->note_public='This is a comment (public)';
2211
        $this->note_private='This is a comment (private)';
2212
        // Lines
2213
        $nbp = 5;
2214
        $xnbp = 0;
2215
        while ($xnbp < $nbp)
2216
        {
2217
            $line=new SupplierProposalLine($this->db);
2218
            $line->desc=$langs->trans("Description")." ".$xnbp;
2219
            $line->qty=1;
2220
            $line->subprice=100;
2221
            $line->price=100;
2222
            $line->tva_tx=19.6;
2223
            $line->localtax1_tx=0;
2224
            $line->localtax2_tx=0;
2225
            if ($xnbp == 2)
2226
            {
2227
                $line->total_ht=50;
2228
                $line->total_ttc=59.8;
2229
                $line->total_tva=9.8;
2230
                $line->remise_percent=50;
2231
            }
2232
            else
2233
            {
2234
                $line->total_ht=100;
2235
                $line->total_ttc=119.6;
2236
                $line->total_tva=19.6;
2237
                $line->remise_percent=00;
2238
            }
2239
2240
            if ($num_prods > 0)
2241
            {
2242
            	$prodid = mt_rand(1, $num_prods);
2243
            	$line->fk_product=$prodids[$prodid];
2244
            }
2245
2246
            $this->lines[$xnbp]=$line;
2247
2248
            $this->total_ht       += $line->total_ht;
2249
            $this->total_tva      += $line->total_tva;
2250
            $this->total_ttc      += $line->total_ttc;
2251
2252
            $xnbp++;
2253
        }
2254
    }
2255
2256
    /**
2257
     *      Charge indicateurs this->nb de tableau de bord
2258
     *
2259
     *      @return     int         <0 if ko, >0 if ok
2260
     */
2261
    function load_state_board()
2262
    {
2263
        global $conf, $user;
2264
2265
        $this->nb=array();
2266
        $clause = "WHERE";
2267
2268
        $sql = "SELECT count(p.rowid) as nb";
2269
        $sql.= " FROM ".MAIN_DB_PREFIX."supplier_proposal as p";
2270
        $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON p.fk_soc = s.rowid";
2271
        if (!$user->rights->societe->client->voir && !$user->socid)
2272
        {
2273
            $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON s.rowid = sc.fk_soc";
2274
            $sql.= " WHERE sc.fk_user = " .$user->id;
2275
            $clause = "AND";
2276
        }
2277
        $sql.= " ".$clause." p.entity IN (".getEntity('supplier_proposal').")";
2278
2279
        $resql=$this->db->query($sql);
2280
        if ($resql)
2281
        {
2282
            // This assignment in condition is not a bug. It allows walking the results.
2283
            while ($obj=$this->db->fetch_object($resql))
2284
            {
2285
                $this->nb["askprice"]=$obj->nb;
2286
            }
2287
            $this->db->free($resql);
2288
            return 1;
2289
        }
2290
        else
2291
        {
2292
            dol_print_error($this->db);
2293
            $this->error=$this->db->lasterror();
2294
            return -1;
2295
        }
2296
    }
2297
2298
2299
    /**
2300
     *  Returns the reference to the following non used Proposal used depending on the active numbering module
2301
     *  defined into SUPPLIER_PROPOSAL_ADDON
2302
     *
2303
     *  @param	Societe		$soc  	Object thirdparty
2304
     *  @return string      		Reference libre pour la propale
2305
     */
2306
    function getNextNumRef($soc)
2307
    {
2308
        global $conf, $db, $langs;
2309
        $langs->load("supplier_proposal");
2310
2311
        if (! empty($conf->global->SUPPLIER_PROPOSAL_ADDON))
2312
        {
2313
        	$mybool=false;
2314
2315
            $file = $conf->global->SUPPLIER_PROPOSAL_ADDON.".php";
2316
            $classname = $conf->global->SUPPLIER_PROPOSAL_ADDON;
2317
2318
            // Include file with class
2319
            $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
2320
            foreach ($dirmodels as $reldir) {
2321
2322
                $dir = dol_buildpath($reldir."core/modules/supplier_proposal/");
2323
2324
                // Load file with numbering class (if found)
2325
                $mybool|=@include_once $dir.$file;
2326
            }
2327
2328
            if (! $mybool)
2329
            {
2330
            	dol_print_error('',"Failed to include file ".$file);
2331
            	return '';
2332
            }
2333
2334
            $obj = new $classname();
2335
            $numref = "";
2336
            $numref = $obj->getNextValue($soc,$this);
2337
2338
            if ($numref != "")
2339
            {
2340
                return $numref;
2341
            }
2342
            else
2343
			{
2344
                $this->error=$obj->error;
2345
                return "";
2346
            }
2347
        }
2348
        else
2349
		{
2350
            $langs->load("errors");
2351
            print $langs->trans("Error")." ".$langs->trans("ErrorModuleSetupNotComplete");
2352
            return "";
2353
        }
2354
    }
2355
2356
    /**
2357
     *	Return clicable link of object (with eventually picto)
2358
     *
2359
     *	@param      int		$withpicto					Add picto into link
2360
     *	@param      string	$option						Where point the link ('compta', 'expedition', 'document', ...)
2361
     *	@param      string	$get_params    				Parametres added to url
2362
     *  @param	    int   	$notooltip					1=Disable tooltip
2363
     *  @param      int     $save_lastsearch_value		-1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
2364
     *	@return     string          					String with URL
2365
     */
2366
    function getNomUrl($withpicto=0, $option='', $get_params='', $notooltip=0, $save_lastsearch_value=-1)
2367
    {
2368
        global $langs, $conf, $user;
2369
2370
        if (! empty($conf->dol_no_mouse_hover)) $notooltip=1;   // Force disable tooltips
2371
2372
        $url='';
2373
        $result='';
2374
2375
        $label='<u>'.$langs->trans("ShowSupplierProposal").'</u>';
2376
        if (! empty($this->ref))
2377
        $label.= '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
2378
        if (! empty($this->ref_fourn))
2379
            $label.= '<br><b>'.$langs->trans('RefSupplier').':</b> '.$this->ref_fourn;
2380
        if (! empty($this->total_ht))
2381
            $label.= '<br><b>' . $langs->trans('AmountHT') . ':</b> ' . price($this->total_ht, 0, $langs, 0, -1, -1, $conf->currency);
2382
        if (! empty($this->total_tva))
2383
            $label.= '<br><b>' . $langs->trans('VAT') . ':</b> ' . price($this->total_tva, 0, $langs, 0, -1, -1, $conf->currency);
2384
        if (! empty($this->total_ttc))
2385
            $label.= '<br><b>' . $langs->trans('AmountTTC') . ':</b> ' . price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency);
2386
        if ($option == '') {
2387
            $url = DOL_URL_ROOT.'/supplier_proposal/card.php?id='.$this->id. $get_params;
2388
        }
2389
        if ($option == 'document') {
2390
            $url = DOL_URL_ROOT.'/supplier_proposal/document.php?id='.$this->id. $get_params;
2391
        }
2392
2393
        if ($option !== 'nolink')
2394
        {
2395
        	// Add param to save lastsearch_values or not
2396
        	$add_save_lastsearch_values=($save_lastsearch_value == 1 ? 1 : 0);
2397
        	if ($save_lastsearch_value == -1 && preg_match('/list\.php/',$_SERVER["PHP_SELF"])) $add_save_lastsearch_values=1;
2398
        	if ($add_save_lastsearch_values) $url.='&save_lastsearch_values=1';
2399
        }
2400
2401
        $linkclose='';
2402
        if (empty($notooltip) && $user->rights->propal->lire)
2403
        {
2404
            if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
2405
            {
2406
                $label=$langs->trans("ShowSupplierProposal");
2407
                $linkclose.=' alt="'.dol_escape_htmltag($label, 1).'"';
2408
            }
2409
            $linkclose.= ' title="'.dol_escape_htmltag($label, 1).'"';
2410
            $linkclose.=' class="classfortooltip"';
2411
        }
2412
2413
        $linkstart = '<a href="'.$url.'"';
2414
        $linkstart.=$linkclose.'>';
2415
        $linkend='</a>';
2416
2417
        $picto='supplier_proposal';
2418
2419
        $result .= $linkstart;
2420
        if ($withpicto) $result.=img_object(($notooltip?'':$label), $this->picto, ($notooltip?(($withpicto != 2) ? 'class="paddingright"' : ''):'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip?0:1);
2421
        if ($withpicto != 2) $result.= $this->ref;
2422
        $result .= $linkend;
2423
2424
        return $result;
2425
    }
2426
2427
    /**
2428
     * 	Retrieve an array of supplier proposal lines
2429
	 *
2430
	 * 	@return int		>0 if OK, <0 if KO
2431
     */
2432
    function getLinesArray()
2433
    {
2434
        // For other object, here we call fetch_lines. But fetch_lines does not exists on supplier proposal
2435
2436
        $sql = 'SELECT pt.rowid, pt.label as custom_label, pt.description, pt.fk_product, pt.fk_remise_except,';
2437
        $sql.= ' pt.qty, pt.tva_tx, pt.remise_percent, pt.subprice, pt.info_bits,';
2438
        $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,';
2439
        $sql.= ' pt.product_type, pt.rang, pt.fk_parent_line,';
2440
        $sql.= ' p.label as product_label, p.ref, p.fk_product_type, p.rowid as prodid,';
2441
        $sql.= ' p.description as product_desc, pt.ref_fourn as ref_supplier,';
2442
		$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';
2443
        $sql.= ' FROM '.MAIN_DB_PREFIX.'supplier_proposaldet as pt';
2444
        $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON pt.fk_product=p.rowid';
2445
        $sql.= ' WHERE pt.fk_supplier_proposal = '.$this->id;
2446
        $sql.= ' ORDER BY pt.rang ASC, pt.rowid';
2447
2448
        dol_syslog(get_class($this).'::getLinesArray', LOG_DEBUG);
2449
        $resql = $this->db->query($sql);
2450
        if ($resql)
2451
        {
2452
            $num = $this->db->num_rows($resql);
2453
            $i = 0;
2454
2455
            while ($i < $num)
2456
            {
2457
                $obj = $this->db->fetch_object($resql);
2458
2459
                $this->lines[$i]					= new SupplierProposalLine($this->db);
2460
                $this->lines[$i]->id				= $obj->rowid; // for backward compatibility
2461
                $this->lines[$i]->rowid				= $obj->rowid;
2462
                $this->lines[$i]->label 			= $obj->custom_label;
2463
                $this->lines[$i]->description 		= $obj->description;
2464
                $this->lines[$i]->fk_product		= $obj->fk_product;
2465
                $this->lines[$i]->ref				= $obj->ref;
2466
                $this->lines[$i]->product_label		= $obj->product_label;
2467
                $this->lines[$i]->product_desc		= $obj->product_desc;
2468
                $this->lines[$i]->fk_product_type	= $obj->fk_product_type;  // deprecated
2469
                $this->lines[$i]->product_type		= $obj->product_type;
2470
                $this->lines[$i]->qty				= $obj->qty;
2471
                $this->lines[$i]->subprice			= $obj->subprice;
2472
                $this->lines[$i]->fk_remise_except 	= $obj->fk_remise_except;
2473
                $this->lines[$i]->remise_percent	= $obj->remise_percent;
2474
                $this->lines[$i]->tva_tx			= $obj->tva_tx;
2475
                $this->lines[$i]->info_bits			= $obj->info_bits;
2476
                $this->lines[$i]->total_ht			= $obj->total_ht;
2477
                $this->lines[$i]->total_tva			= $obj->total_tva;
2478
                $this->lines[$i]->total_ttc			= $obj->total_ttc;
2479
				$this->lines[$i]->fk_fournprice		= $obj->fk_fournprice;
2480
				$marginInfos						= getMarginInfos($obj->subprice, $obj->remise_percent, $obj->tva_tx, $obj->localtax1_tx, $obj->localtax2_tx, $this->lines[$i]->fk_fournprice, $obj->pa_ht);
2481
				$this->lines[$i]->pa_ht				= $marginInfos[0];
2482
				$this->lines[$i]->marge_tx			= $marginInfos[1];
2483
				$this->lines[$i]->marque_tx			= $marginInfos[2];
2484
				$this->lines[$i]->fk_parent_line	= $obj->fk_parent_line;
2485
                $this->lines[$i]->special_code		= $obj->special_code;
2486
                $this->lines[$i]->rang				= $obj->rang;
2487
2488
                $this->lines[$i]->ref_fourn				= $obj->ref_supplier;	// deprecated
2489
                $this->lines[$i]->ref_supplier			= $obj->ref_supplier;
2490
2491
				// Multicurrency
2492
				$this->lines[$i]->fk_multicurrency 			= $obj->fk_multicurrency;
2493
				$this->lines[$i]->multicurrency_code 		= $obj->multicurrency_code;
2494
				$this->lines[$i]->multicurrency_subprice 	= $obj->multicurrency_subprice;
2495
				$this->lines[$i]->multicurrency_total_ht 	= $obj->multicurrency_total_ht;
2496
				$this->lines[$i]->multicurrency_total_tva 	= $obj->multicurrency_total_tva;
2497
				$this->lines[$i]->multicurrency_total_ttc 	= $obj->multicurrency_total_ttc;
2498
				$this->lines[$i]->fk_unit				 	= $obj->fk_unit;
2499
2500
                $i++;
2501
            }
2502
            $this->db->free($resql);
2503
2504
            return 1;
2505
        }
2506
        else
2507
        {
2508
            $this->error=$this->db->error();
2509
            return -1;
2510
        }
2511
    }
2512
2513
	/**
2514
	 *  Create a document onto disk according to template module.
2515
	 *
2516
	 * 	@param	    string		$modele			Force model to use ('' to not force)
2517
	 * 	@param		Translate	$outputlangs	Object langs to use for output
2518
	 *  @param      int			$hidedetails    Hide details of lines
2519
	 *  @param      int			$hidedesc       Hide description
2520
	 *  @param      int			$hideref        Hide ref
2521
	 * 	@return     int         				0 if KO, 1 if OK
2522
	 */
2523
	public function generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
2524
	{
2525
		global $conf, $langs;
2526
2527
		$langs->load("supplier_proposal");
2528
2529
		if (! dol_strlen($modele)) {
2530
2531
			$modele = 'aurore';
2532
2533
			if ($this->modelpdf) {
2534
				$modele = $this->modelpdf;
2535
			} elseif (! empty($conf->global->SUPPLIER_PROPOSAL_ADDON_PDF)) {
2536
				$modele = $conf->global->SUPPLIER_PROPOSAL_ADDON_PDF;
2537
			}
2538
		}
2539
2540
		$modelpath = "core/modules/supplier_proposal/doc/";
2541
2542
		return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref);
2543
	}
2544
2545
2546
	/**
2547
	 * Function used to replace a thirdparty id with another one.
2548
	 *
2549
	 * @param DoliDB $db Database handler
2550
	 * @param int $origin_id Old thirdparty id
2551
	 * @param int $dest_id New thirdparty id
2552
	 * @return bool
2553
	 */
2554
	public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
2555
	{
2556
	    $tables = array(
2557
	        'supplier_proposal'
2558
	    );
2559
2560
	    return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
2561
	}
2562
2563
}
2564
2565
2566
/**
2567
 *	Class to manage supplier_proposal lines
2568
 */
2569
class SupplierProposalLine extends CommonObjectLine
2570
{
2571
    var $db;
2572
    var $error;
2573
2574
    public $element='supplier_proposaldet';
2575
    public $table_element='supplier_proposaldet';
2576
2577
    var $oldline;
2578
2579
    // From llx_supplier_proposaldet
2580
    var $rowid; // deprecated
2581
    var $id;
2582
    var $fk_supplier_proposal;
2583
    var $fk_parent_line;
2584
    var $desc;          	// Description ligne
2585
    var $fk_product;		// Id produit predefini
2586
	/**
2587
	 * @deprecated
2588
	 * @see product_type
2589
	 */
2590
	var $fk_product_type;
2591
	/**
2592
	 * Product type
2593
	 * @var int
2594
	 * @see Product::TYPE_PRODUCT, Product::TYPE_SERVICE
2595
	 */
2596
    public $product_type = Product::TYPE_PRODUCT;
2597
2598
    var $qty;
2599
    var $tva_tx;
2600
    var $subprice;
2601
    var $remise_percent;
2602
    var $fk_remise_except;
2603
2604
    var $rang = 0;
2605
2606
	var $fk_fournprice;
2607
	var $pa_ht;
2608
	var $marge_tx;
2609
	var $marque_tx;
2610
2611
    var $special_code;	// Tag for special lines (exlusive tags)
2612
    // 1: frais de port
2613
    // 2: ecotaxe
2614
    // 3: option line (when qty = 0)
2615
2616
    var $info_bits = 0;	// Liste d'options cumulables:
2617
    // Bit 0: 	0 si TVA normal - 1 si TVA NPR
2618
    // Bit 1:	0 ligne normale - 1 si ligne de remise fixe
2619
2620
    var $total_ht;			// Total HT  de la ligne toute quantite et incluant la remise ligne
2621
    var $total_tva;			// Total TVA  de la ligne toute quantite et incluant la remise ligne
2622
    var $total_ttc;			// Total TTC de la ligne toute quantite et incluant la remise ligne
2623
2624
	/**
2625
	 * @deprecated
2626
	 * @see remise_percent, fk_remise_except
2627
	 */
2628
    var $remise;
2629
	/**
2630
	 * @deprecated
2631
	 * @see subprice
2632
	 */
2633
    var $price;
2634
2635
    // From llx_product
2636
	/**
2637
	 * @deprecated
2638
	 * @see product_ref
2639
	 */
2640
	var $ref;
2641
	/**
2642
	 * Product reference
2643
	 * @var string
2644
	 */
2645
	public $product_ref;
2646
	/**
2647
	 * @deprecated
2648
	 * @see product_label
2649
	 */
2650
	var $libelle;
2651
	/**
2652
	 *  Product label
2653
	 * @var string
2654
	 */
2655
	public $product_label;
2656
	/**
2657
	 * Product description
2658
	 * @var string
2659
	 */
2660
	public $product_desc;
2661
2662
    var $localtax1_tx;		// Local tax 1
2663
    var $localtax2_tx;		// Local tax 2
2664
    var $localtax1_type;	// Local tax 1 type
2665
	var $localtax2_type;	// Local tax 2 type
2666
    var $total_localtax1;  	// Line total local tax 1
2667
    var $total_localtax2;	// Line total local tax 2
2668
2669
    var $skip_update_total; // Skip update price total for special lines
2670
2671
	var $ref_fourn;
2672
2673
	// Multicurrency
2674
	var $fk_multicurrency;
2675
	var $multicurrency_code;
2676
	var $multicurrency_subprice;
2677
	var $multicurrency_total_ht;
2678
	var $multicurrency_total_tva;
2679
	var $multicurrency_total_ttc;
2680
2681
    /**
2682
     * 	Class line Contructor
2683
     *
2684
     * 	@param	DoliDB	$db	Database handler
2685
     */
2686
    function __construct($db)
2687
    {
2688
        $this->db= $db;
2689
    }
2690
2691
    /**
2692
     *	Retrieve the propal line object
2693
     *
2694
     *	@param	int		$rowid		Propal line id
2695
     *	@return	int					<0 if KO, >0 if OK
2696
     */
2697
	function fetch($rowid)
2698
	{
2699
		$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,';
2700
		$sql.= ' pd.remise, pd.remise_percent, pd.fk_remise_except, pd.subprice,';
2701
		$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,';
2702
		$sql.= ' pd.localtax1_tx, pd.localtax2_tx, pd.total_localtax1, pd.total_localtax2,';
2703
		$sql.= ' p.ref as product_ref, p.label as product_label, p.description as product_desc,';
2704
		$sql.= ' pd.product_type, pd.ref_fourn as ref_produit_fourn,';
2705
		$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';
2706
		$sql.= ' FROM '.MAIN_DB_PREFIX.'supplier_proposaldet as pd';
2707
		$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON pd.fk_product = p.rowid';
2708
		$sql.= ' WHERE pd.rowid = '.$rowid;
2709
2710
		$result = $this->db->query($sql);
2711
		if ($result)
2712
		{
2713
			$objp = $this->db->fetch_object($result);
2714
2715
			$this->rowid			= $objp->rowid; // deprecated
2716
			$this->id				= $objp->rowid;
2717
			$this->fk_supplier_proposal		= $objp->fk_supplier_proposal;
2718
			$this->fk_parent_line	= $objp->fk_parent_line;
2719
			$this->label			= $objp->custom_label;
2720
			$this->desc				= $objp->description;
2721
			$this->qty				= $objp->qty;
2722
			$this->price			= $objp->price;		// deprecated
2723
			$this->subprice			= $objp->subprice;
2724
			$this->tva_tx			= $objp->tva_tx;
2725
			$this->remise			= $objp->remise;
2726
			$this->remise_percent	= $objp->remise_percent;
2727
			$this->fk_remise_except = $objp->fk_remise_except;
2728
			$this->fk_product		= $objp->fk_product;
2729
			$this->info_bits		= $objp->info_bits;
2730
2731
			$this->total_ht			= $objp->total_ht;
2732
			$this->total_tva		= $objp->total_tva;
2733
			$this->total_ttc		= $objp->total_ttc;
2734
2735
			$this->fk_fournprice	= $objp->fk_fournprice;
2736
2737
			$marginInfos			= getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $this->fk_fournprice, $objp->pa_ht);
2738
			$this->pa_ht			= $marginInfos[0];
2739
			$this->marge_tx			= $marginInfos[1];
2740
			$this->marque_tx		= $marginInfos[2];
2741
2742
			$this->special_code		= $objp->special_code;
2743
			$this->product_type		= $objp->product_type;
2744
			$this->rang				= $objp->rang;
2745
2746
			$this->ref				= $objp->product_ref;      // deprecated
2747
			$this->product_ref		= $objp->product_ref;
2748
			$this->libelle			= $objp->product_label;  // deprecated
2749
			$this->product_label	= $objp->product_label;
2750
			$this->product_desc		= $objp->product_desc;
2751
2752
			$this->ref_fourn		= $objp->ref_produit_forun;
2753
2754
			// Multicurrency
2755
			$this->fk_multicurrency 		= $objp->fk_multicurrency;
2756
			$this->multicurrency_code 		= $objp->multicurrency_code;
2757
			$this->multicurrency_subprice 	= $objp->multicurrency_subprice;
2758
			$this->multicurrency_total_ht 	= $objp->multicurrency_total_ht;
2759
			$this->multicurrency_total_tva 	= $objp->multicurrency_total_tva;
2760
			$this->multicurrency_total_ttc 	= $objp->multicurrency_total_ttc;
2761
			$this->fk_unit				 	= $objp->fk_unit;
2762
2763
			$this->db->free($result);
2764
		}
2765
		else
2766
		{
2767
			dol_print_error($this->db);
2768
		}
2769
	}
2770
2771
    /**
2772
     *  Insert object line propal in database
2773
     *
2774
     *	@param		int		$notrigger		1=Does not execute triggers, 0= execute triggers
2775
     *	@return		int						<0 if KO, >0 if OK
2776
     */
2777
    function insert($notrigger=0)
2778
    {
2779
        global $conf,$langs,$user;
2780
2781
        $error=0;
2782
2783
        dol_syslog(get_class($this)."::insert rang=".$this->rang);
2784
2785
        // Clean parameters
2786
        if (empty($this->tva_tx)) $this->tva_tx=0;
2787
        if (empty($this->localtax1_tx)) $this->localtax1_tx=0;
2788
        if (empty($this->localtax2_tx)) $this->localtax2_tx=0;
2789
        if (empty($this->localtax1_type)) $this->localtax1_type=0;
2790
		if (empty($this->localtax2_type)) $this->localtax2_type=0;
2791
        if (empty($this->total_localtax1)) $this->total_localtax1=0;
2792
        if (empty($this->total_localtax2)) $this->total_localtax2=0;
2793
        if (empty($this->rang)) $this->rang=0;
2794
        if (empty($this->remise)) $this->remise=0;
2795
        if (empty($this->remise_percent)) $this->remise_percent=0;
2796
        if (empty($this->info_bits)) $this->info_bits=0;
2797
        if (empty($this->special_code)) $this->special_code=0;
2798
        if (empty($this->fk_parent_line)) $this->fk_parent_line=0;
2799
        if (empty($this->fk_fournprice)) $this->fk_fournprice=0;
2800
        if (empty($this->fk_unit)) $this->fk_unit=0;
0 ignored issues
show
Documentation Bug introduced by
The property $fk_unit was declared of type string, but 0 is of type integer. 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...
2801
        if (empty($this->subprice)) $this->subprice=0;
2802
2803
        if (empty($this->pa_ht)) $this->pa_ht=0;
2804
2805
		// if buy price not defined, define buyprice as configured in margin admin
2806
		if ($this->pa_ht == 0)
2807
		{
2808
			if (($result = $this->defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product)) < 0)
2809
			{
2810
				return $result;
2811
			}
2812
			else
2813
			{
2814
				$this->pa_ht = $result;
2815
			}
2816
		}
2817
2818
        // Check parameters
2819
        if ($this->product_type < 0) return -1;
2820
2821
        $this->db->begin();
2822
2823
        // Insert line into database
2824
        $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'supplier_proposaldet';
2825
        $sql.= ' (fk_supplier_proposal, fk_parent_line, label, description, fk_product, product_type,';
2826
		$sql.= ' fk_remise_except, qty, tva_tx, localtax1_tx, localtax2_tx, localtax1_type, localtax2_type,';
2827
        $sql.= ' subprice, remise_percent, ';
2828
        $sql.= ' info_bits, ';
2829
        $sql.= ' total_ht, total_tva, total_localtax1, total_localtax2, total_ttc, fk_product_fournisseur_price, buy_price_ht, special_code, rang,';
2830
        $sql.= ' ref_fourn,';
2831
		$sql.= ' fk_multicurrency, multicurrency_code, multicurrency_subprice, multicurrency_total_ht, multicurrency_total_tva, multicurrency_total_ttc, fk_unit)';
2832
        $sql.= " VALUES (".$this->fk_supplier_proposal.",";
2833
        $sql.= " ".($this->fk_parent_line>0?"'".$this->db->escape($this->fk_parent_line)."'":"null").",";
2834
        $sql.= " ".(! empty($this->label)?"'".$this->db->escape($this->label)."'":"null").",";
2835
        $sql.= " '".$this->db->escape($this->desc)."',";
2836
        $sql.= " ".($this->fk_product?"'".$this->db->escape($this->fk_product)."'":"null").",";
2837
        $sql.= " '".$this->db->escape($this->product_type)."',";
2838
        $sql.= " ".($this->fk_remise_except?"'".$this->db->escape($this->fk_remise_except)."'":"null").",";
2839
        $sql.= " ".price2num($this->qty).",";
2840
        $sql.= " ".price2num($this->tva_tx).",";
2841
        $sql.= " ".price2num($this->localtax1_tx).",";
2842
        $sql.= " ".price2num($this->localtax2_tx).",";
2843
		$sql.= " '".$this->db->escape($this->localtax1_type)."',";
2844
		$sql.= " '".$this->db->escape($this->localtax2_type)."',";
2845
        $sql.= " ".(!empty($this->subprice)?price2num($this->subprice):"null").",";
2846
        $sql.= " ".price2num($this->remise_percent).",";
2847
        $sql.= " ".(isset($this->info_bits)?"'".$this->db->escape($this->info_bits)."'":"null").",";
2848
        $sql.= " ".price2num($this->total_ht).",";
2849
        $sql.= " ".price2num($this->total_tva).",";
2850
        $sql.= " ".price2num($this->total_localtax1).",";
2851
        $sql.= " ".price2num($this->total_localtax2).",";
2852
        $sql.= " ".price2num($this->total_ttc).",";
2853
        $sql.= " ".(!empty($this->fk_fournprice)?"'".$this->db->escape($this->fk_fournprice)."'":"null").",";
2854
        $sql.= " ".(isset($this->pa_ht)?"'".price2num($this->pa_ht)."'":"null").",";
2855
        $sql.= ' '.$this->special_code.',';
2856
        $sql.= ' '.$this->rang.',';
2857
        $sql.= " '".$this->db->escape($this->ref_fourn)."'";
2858
		$sql.= ", ".($this->fk_multicurrency > 0?$this->fk_multicurrency:'null');
2859
		$sql.= ", '".$this->db->escape($this->multicurrency_code)."'";
2860
		$sql.= ", ".$this->multicurrency_subprice;
2861
		$sql.= ", ".$this->multicurrency_total_ht;
2862
		$sql.= ", ".$this->multicurrency_total_tva;
2863
		$sql.= ", ".$this->multicurrency_total_ttc;
2864
        $sql.= ", ".($this->fk_unit?$this->fk_unit:'null');
2865
		$sql.= ')';
2866
2867
        dol_syslog(get_class($this).'::insert', LOG_DEBUG);
2868
        $resql=$this->db->query($sql);
2869
        if ($resql)
2870
        {
2871
            $this->rowid=$this->db->last_insert_id(MAIN_DB_PREFIX.'supplier_proposaldet');
2872
			$this->id=$this->rowid;
2873
2874
            if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
2875
            {
2876
            	$result=$this->insertExtraFields();
2877
            	if ($result < 0)
2878
            	{
2879
            		$error++;
2880
            	}
2881
            }
2882
2883
            if (! $error && ! $notrigger)
2884
            {
2885
                // Call trigger
2886
                $result=$this->call_trigger('LINESUPPLIER_PROPOSAL_INSERT',$user);
2887
                if ($result < 0)
2888
                {
2889
                    $this->db->rollback();
2890
                    return -1;
2891
                }
2892
                // End call triggers
2893
            }
2894
2895
            $this->db->commit();
2896
            return 1;
2897
        }
2898
        else
2899
        {
2900
            $this->error=$this->db->error()." sql=".$sql;
2901
            $this->db->rollback();
2902
            return -1;
2903
        }
2904
    }
2905
2906
    /**
2907
     * 	Delete line in database
2908
     *
2909
     *	@return	 int  <0 if ko, >0 if ok
2910
     */
2911
    function delete()
2912
    {
2913
        global $conf,$langs,$user;
2914
2915
        $error=0;
2916
        $this->db->begin();
2917
2918
        $sql = "DELETE FROM ".MAIN_DB_PREFIX."supplier_proposaldet WHERE rowid = ".$this->rowid;
2919
        dol_syslog("SupplierProposalLine::delete", LOG_DEBUG);
2920
        if ($this->db->query($sql) )
2921
        {
2922
2923
        	// Remove extrafields
2924
        	if ((! $error) && (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED))) // For avoid conflicts if trigger used
2925
        	{
2926
        		$this->id=$this->rowid;
2927
        		$result=$this->deleteExtraFields();
2928
        		if ($result < 0)
2929
        		{
2930
        			$error++;
2931
        			dol_syslog(get_class($this)."::delete error -4 ".$this->error, LOG_ERR);
2932
        		}
2933
        	}
2934
2935
            // Call trigger
2936
            $result=$this->call_trigger('LINESUPPLIER_PROPOSAL_DELETE',$user);
2937
            if ($result < 0)
2938
            {
2939
                $this->db->rollback();
2940
                return -1;
2941
            }
2942
            // End call triggers
2943
2944
            $this->db->commit();
2945
2946
            return 1;
2947
        }
2948
        else
2949
        {
2950
            $this->error=$this->db->error()." sql=".$sql;
2951
            $this->db->rollback();
2952
            return -1;
2953
        }
2954
    }
2955
2956
    /**
2957
     *	Update propal line object into DB
2958
     *
2959
     *	@param 	int		$notrigger	1=Does not execute triggers, 0= execute triggers
2960
     *	@return	int					<0 if ko, >0 if ok
2961
     */
2962
    function update($notrigger=0)
2963
    {
2964
        global $conf,$langs,$user;
2965
2966
        $error=0;
2967
2968
        // Clean parameters
2969
        if (empty($this->tva_tx)) $this->tva_tx=0;
2970
        if (empty($this->localtax1_tx)) $this->localtax1_tx=0;
2971
        if (empty($this->localtax2_tx)) $this->localtax2_tx=0;
2972
        if (empty($this->total_localtax1)) $this->total_localtax1=0;
2973
        if (empty($this->total_localtax2)) $this->total_localtax2=0;
2974
		if (empty($this->localtax1_type)) $this->localtax1_type=0;
2975
		if (empty($this->localtax2_type)) $this->localtax2_type=0;
2976
        if (empty($this->marque_tx)) $this->marque_tx=0;
2977
        if (empty($this->marge_tx)) $this->marge_tx=0;
2978
        if (empty($this->price)) $this->price=0;	// TODO A virer
2979
        if (empty($this->remise)) $this->remise=0;	// TODO A virer
2980
        if (empty($this->remise_percent)) $this->remise_percent=0;
2981
        if (empty($this->info_bits)) $this->info_bits=0;
2982
        if (empty($this->special_code)) $this->special_code=0;
2983
        if (empty($this->fk_parent_line)) $this->fk_parent_line=0;
2984
        if (empty($this->fk_fournprice)) $this->fk_fournprice=0;
2985
        if (empty($this->fk_unit)) $this->fk_unit=0;
0 ignored issues
show
Documentation Bug introduced by
The property $fk_unit was declared of type string, but 0 is of type integer. 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...
2986
        if (empty($this->subprice)) $this->subprice=0;
2987
2988
		if (empty($this->pa_ht)) $this->pa_ht=0;
2989
2990
		// if buy price not defined, define buyprice as configured in margin admin
2991
		if ($this->pa_ht == 0)
2992
		{
2993
			if (($result = $this->defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product)) < 0)
2994
			{
2995
				return $result;
2996
			}
2997
			else
2998
			{
2999
				$this->pa_ht = $result;
3000
			}
3001
		}
3002
3003
        $this->db->begin();
3004
3005
        // Mise a jour ligne en base
3006
        $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposaldet SET";
3007
        $sql.= " description='".$this->db->escape($this->desc)."'";
3008
        $sql.= " , label=".(! empty($this->label)?"'".$this->db->escape($this->label)."'":"null");
3009
        $sql.= " , product_type=".$this->product_type;
3010
        $sql.= " , tva_tx='".price2num($this->tva_tx)."'";
3011
        $sql.= " , localtax1_tx=".price2num($this->localtax1_tx);
3012
        $sql.= " , localtax2_tx=".price2num($this->localtax2_tx);
3013
		$sql.= " , localtax1_type='".$this->db->escape($this->localtax1_type)."'";
3014
		$sql.= " , localtax2_type='".$this->db->escape($this->localtax2_type)."'";
3015
        $sql.= " , qty='".price2num($this->qty)."'";
3016
        $sql.= " , subprice=".price2num($this->subprice)."";
3017
        $sql.= " , remise_percent=".price2num($this->remise_percent)."";
3018
        $sql.= " , price=".price2num($this->price)."";					// TODO A virer
3019
        $sql.= " , remise=".price2num($this->remise)."";				// TODO A virer
3020
        $sql.= " , info_bits='".$this->db->escape($this->info_bits)."'";
3021
        if (empty($this->skip_update_total))
3022
        {
3023
            $sql.= " , total_ht=".price2num($this->total_ht)."";
3024
            $sql.= " , total_tva=".price2num($this->total_tva)."";
3025
            $sql.= " , total_ttc=".price2num($this->total_ttc)."";
3026
            $sql.= " , total_localtax1=".price2num($this->total_localtax1)."";
3027
            $sql.= " , total_localtax2=".price2num($this->total_localtax2)."";
3028
        }
3029
		$sql.= " , fk_product_fournisseur_price=".(! empty($this->fk_fournprice)?"'".$this->db->escape($this->fk_fournprice)."'":"null");
3030
		$sql.= " , buy_price_ht=".price2num($this->pa_ht);
3031
        if (strlen($this->special_code)) $sql.= " , special_code=".$this->special_code;
3032
        $sql.= " , fk_parent_line=".($this->fk_parent_line>0?$this->fk_parent_line:"null");
3033
        if (! empty($this->rang)) $sql.= ", rang=".$this->rang;
3034
        $sql.= " , ref_fourn=".(! empty($this->ref_fourn)?"'".$this->db->escape($this->ref_fourn)."'":"null");
3035
        $sql.= " , fk_unit=".($this->fk_unit?$this->fk_unit:'null');
3036
3037
		// Multicurrency
3038
		$sql.= " , multicurrency_subprice=".price2num($this->multicurrency_subprice)."";
3039
        $sql.= " , multicurrency_total_ht=".price2num($this->multicurrency_total_ht)."";
3040
        $sql.= " , multicurrency_total_tva=".price2num($this->multicurrency_total_tva)."";
3041
        $sql.= " , multicurrency_total_ttc=".price2num($this->multicurrency_total_ttc)."";
3042
3043
		$sql.= " WHERE rowid = ".$this->rowid;
3044
3045
        dol_syslog(get_class($this)."::update", LOG_DEBUG);
3046
        $resql=$this->db->query($sql);
3047
        if ($resql)
3048
        {
3049
        	if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
3050
        	{
3051
        		$this->id=$this->rowid;
3052
        		$result=$this->insertExtraFields();
3053
        		if ($result < 0)
3054
        		{
3055
        			$error++;
3056
        		}
3057
        	}
3058
3059
            if (! $error && ! $notrigger)
3060
            {
3061
                // Call trigger
3062
                $result=$this->call_trigger('LINESUPPLIER_PROPOSAL_UPDATE',$user);
3063
                if ($result < 0)
3064
                {
3065
                    $this->db->rollback();
3066
                    return -1;
3067
                }
3068
                // End call triggers
3069
            }
3070
3071
            $this->db->commit();
3072
            return 1;
3073
        }
3074
        else
3075
        {
3076
            $this->error=$this->db->error();
3077
            $this->db->rollback();
3078
            return -2;
3079
        }
3080
    }
3081
3082
    /**
3083
     *	Update DB line fields total_xxx
3084
     *	Used by migration
3085
     *
3086
     *	@return		int		<0 if ko, >0 if ok
3087
     */
3088
    function update_total()
3089
    {
3090
        $this->db->begin();
3091
3092
        // Mise a jour ligne en base
3093
        $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposaldet SET";
3094
        $sql.= " total_ht=".price2num($this->total_ht,'MT')."";
3095
        $sql.= ",total_tva=".price2num($this->total_tva,'MT')."";
3096
        $sql.= ",total_ttc=".price2num($this->total_ttc,'MT')."";
3097
        $sql.= " WHERE rowid = ".$this->rowid;
3098
3099
        dol_syslog("SupplierProposalLine::update_total", LOG_DEBUG);
3100
3101
        $resql=$this->db->query($sql);
3102
        if ($resql)
3103
        {
3104
            $this->db->commit();
3105
            return 1;
3106
        }
3107
        else
3108
        {
3109
            $this->error=$this->db->error();
3110
            $this->db->rollback();
3111
            return -2;
3112
        }
3113
    }
3114
3115
}
3116
3117