Completed
Branch develop (2959dc)
by
unknown
32:39
created

CommandeFournisseur::fetch()   C

Complexity

Conditions 8
Paths 13

Size

Total Lines 126
Code Lines 93

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 93
nc 13
nop 2
dl 0
loc 126
rs 5.2676
c 0
b 0
f 0

How to fix   Long Method   

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) 2003-2006	Rodolphe Quiedeville	<[email protected]>
3
 * Copyright (C) 2004-2017	Laurent Destailleur		<[email protected]>
4
 * Copyright (C) 2005-2012	Regis Houssin			<[email protected]>
5
 * Copyright (C) 2007		Franky Van Liedekerke	<[email protected]>
6
 * Copyright (C) 2010-2014	Juanjo Menent			<[email protected]>
7
 * Copyright (C) 2010-2016	Philippe Grand			<[email protected]>
8
 * Copyright (C) 2012-2015  Marcos García           <[email protected]>
9
 * Copyright (C) 2013       Florian Henry		  	<[email protected]>
10
 * Copyright (C) 2013       Cédric Salvador         <[email protected]>
11
 *
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 3 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
 */
25
26
/**
27
 *	\file       htdocs/fourn/class/fournisseur.commande.class.php
28
 *	\ingroup    fournisseur,commande
29
 *	\brief      File of class to manage suppliers orders
30
 */
31
32
include_once DOL_DOCUMENT_ROOT.'/core/class/commonorder.class.php';
33
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
34
if (! empty($conf->productbatch->enabled)) require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
35
require_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
36
37
/**
38
 *	Class to manage predefined suppliers products
39
 */
40
class CommandeFournisseur extends CommonOrder
41
{
42
    public $element='order_supplier';
43
    public $table_element='commande_fournisseur';
44
    public $table_element_line = 'commande_fournisseurdet';
45
    public $fk_element = 'fk_commande';
46
    public $picto='order';
47
    /**
48
     * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
49
     * @var int
50
     */
51
    public $ismultientitymanaged = 1;
52
    /**
53
     * 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
54
     * @var integer
55
     */
56
    public $restrictiononfksoc = 1;
57
58
    /**
59
     * {@inheritdoc}
60
     */
61
    protected $table_ref_field = 'ref';
62
63
    public $id;
64
65
	/**
66
	 * Supplier order reference
67
	 * @var string
68
	 */
69
    public $ref;
70
    public $ref_supplier;
71
    public $brouillon;
72
    public $statut;			// 0=Draft -> 1=Validated -> 2=Approved -> 3=Ordered/Process runing -> 4=Received partially -> 5=Received totally -> (reopen) 4=Received partially
73
    //                                                                                          -> 7=Canceled/Never received -> (reopen) 3=Process runing
74
    //									                            -> 6=Canceled -> (reopen) 2=Approved
75
    //  		                                      -> 9=Refused  -> (reopen) 1=Validated
76
    //  Note: billed or not is on another field "billed"
77
    public $statuts;           // List of status
78
79
    public $socid;
80
    public $fourn_id;
81
    public $date;
82
    public $date_valid;
83
    public $date_approve;
84
    public $date_approve2;		// Used when SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED is set
85
    public $date_commande;
86
87
    /**
88
     * Delivery date
89
     */
90
    public $date_livraison;
91
    public $total_ht;
92
    public $total_tva;
93
    public $total_localtax1;   // Total Local tax 1
94
    public $total_localtax2;   // Total Local tax 2
95
    public $total_ttc;
96
    public $source;
97
	/**
98
	 * @deprecated
99
	 * @see note_private, note_public
100
	 */
101
    public $note;
102
	public $note_private;
103
    public $note_public;
104
    public $model_pdf;
105
    public $fk_project;
106
    public $cond_reglement_id;
107
    public $cond_reglement_code;
108
    public $fk_account;
109
    public $mode_reglement_id;
110
    public $mode_reglement_code;
111
    public $user_author_id;
112
    public $user_valid_id;
113
    public $user_approve_id;
114
    public $user_approve_id2;	// Used when SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED is set
115
116
	//Incoterms
117
    public $fk_incoterms;
118
    public $location_incoterms;
119
    public $libelle_incoterms;  //Used into tooltip
120
121
    public $extraparams=array();
122
123
	/**
124
	 * @var CommandeFournisseurLigne[]
125
	 */
126
	public $lines = array();
127
	//Add for supplier_proposal
128
    public $origin;
129
    public $origin_id;
130
    public $linked_objects=array();
131
132
	// Multicurrency
133
    public $fk_multicurrency;
134
    public $multicurrency_code;
135
    public $multicurrency_tx;
136
    public $multicurrency_total_ht;
137
    public $multicurrency_total_tva;
138
    public $multicurrency_total_ttc;
139
140
	/**
141
	 * Draft status
142
	 */
143
	const STATUS_DRAFT = 0;
144
	/**
145
	 * Validated status
146
	 */
147
	const STATUS_VALIDATED = 1;
148
	/**
149
	 * Accepted
150
	 */
151
	const STATUS_ACCEPTED = 2;
152
	/**
153
	 * Order sent, shipment on process
154
	 */
155
	const STATUS_ORDERSENT = 3;
156
	/**
157
	 * Received partially
158
	 */
159
	const STATUS_RECEIVED_PARTIALLY = 4;
160
	/**
161
	 * Received completely
162
	 */
163
	const STATUS_RECEIVED_COMPLETELY = 5;
164
	/**
165
	 * Order canceled
166
	 */
167
	const STATUS_CANCELED = 6;
168
	/**
169
	 * Order canceled/never received
170
	 */
171
	const STATUS_CANCELED_AFTER_ORDER = 7;
172
	/**
173
	 * Refused
174
	 */
175
	const STATUS_REFUSED = 9;
176
177
178
179
180
	/**
181
     * 	Constructor
182
     *
183
     *  @param      DoliDB		$db      Database handler
184
     */
185
    public function __construct($db)
186
    {
187
    	global $conf;
188
189
        $this->db = $db;
190
        $this->products = array();
191
192
        // List of language codes for status
193
        $this->statuts[0] = 'StatusOrderDraft';
194
        $this->statuts[1] = 'StatusOrderValidated';
195
        $this->statuts[2] = 'StatusOrderApproved';
196
        if (empty($conf->global->SUPPLIER_ORDER_USE_DISPATCH_STATUS)) $this->statuts[3] = 'StatusOrderOnProcess';
197
        else $this->statuts[3] = 'StatusOrderOnProcessWithValidation';
198
        $this->statuts[4] = 'StatusOrderReceivedPartially';
199
        $this->statuts[5] = 'StatusOrderReceivedAll';
200
        $this->statuts[6] = 'StatusOrderCanceled';	// Approved->Canceled
201
        $this->statuts[7] = 'StatusOrderCanceled';	// Process running->canceled
202
        //$this->statuts[8] = 'StatusOrderBilled';	// Everything is finished, order received totally and bill received
203
        $this->statuts[9] = 'StatusOrderRefused';
204
    }
205
206
207
    /**
208
     *	Get object and lines from database
209
     *
210
     * 	@param	int		$id			Id of order to load
211
     * 	@param	string	$ref		Ref of object
212
     *	@return int 		        >0 if OK, <0 if KO, 0 if not found
213
     */
214
    public function fetch($id,$ref='')
215
    {
216
        global $conf;
217
218
        // Check parameters
219
        if (empty($id) && empty($ref)) return -1;
220
221
        $sql = "SELECT c.rowid, c.entity, c.ref, ref_supplier, c.fk_soc, c.fk_statut, c.amount_ht, c.total_ht, c.total_ttc, c.tva as total_vat,";
222
        $sql.= " c.localtax1, c.localtax2, ";
223
        $sql.= " c.date_creation, c.date_valid, c.date_approve, c.date_approve2,";
224
        $sql.= " c.fk_user_author, c.fk_user_valid, c.fk_user_approve, c.fk_user_approve2,";
225
        $sql.= " c.date_commande as date_commande, c.date_livraison as date_livraison, c.fk_cond_reglement, c.fk_mode_reglement, c.fk_projet as fk_project, c.remise_percent, c.source, c.fk_input_method,";
226
        $sql.= " c.fk_account,";
227
        $sql.= " c.note_private, c.note_public, c.model_pdf, c.extraparams, c.billed,";
228
		$sql.= " c.fk_multicurrency, c.multicurrency_code, c.multicurrency_tx, c.multicurrency_total_ht, c.multicurrency_total_tva, c.multicurrency_total_ttc,";
229
        $sql.= " cm.libelle as methode_commande,";
230
        $sql.= " cr.code as cond_reglement_code, cr.libelle as cond_reglement_libelle,";
231
        $sql.= " p.code as mode_reglement_code, p.libelle as mode_reglement_libelle";
232
        $sql.= ', c.fk_incoterms, c.location_incoterms';
233
        $sql.= ', i.libelle as libelle_incoterms';
234
        $sql.= " FROM ".MAIN_DB_PREFIX."commande_fournisseur as c";
235
        $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_payment_term as cr ON c.fk_cond_reglement = cr.rowid";
236
        $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_paiement as p ON c.fk_mode_reglement = p.id";
237
        $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_input_method as cm ON cm.rowid = c.fk_input_method";
238
		$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_incoterms as i ON c.fk_incoterms = i.rowid';
239
        $sql.= " WHERE c.entity = ".$conf->entity;
240
        if ($ref) $sql.= " AND c.ref='".$this->db->escape($ref)."'";
241
        else $sql.= " AND c.rowid=".$id;
242
243
        dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
244
        $resql = $this->db->query($sql);
245
        if ($resql)
246
        {
247
            $obj = $this->db->fetch_object($resql);
248
            if (! $obj)
249
            {
250
                $this->error='Bill with id '.$id.' not found';
251
                dol_syslog(get_class($this).'::fetch '.$this->error);
252
                return 0;
253
            }
254
255
            $this->id					= $obj->rowid;
256
            $this->entity				= $obj->entity;
257
258
            $this->ref					= $obj->ref;
259
            $this->ref_supplier			= $obj->ref_supplier;
260
            $this->socid				= $obj->fk_soc;
261
            $this->fourn_id				= $obj->fk_soc;
262
            $this->statut				= $obj->fk_statut;
263
            $this->billed				= $obj->billed;
264
            $this->user_author_id		= $obj->fk_user_author;
265
            $this->user_valid_id		= $obj->fk_user_valid;
266
            $this->user_approve_id		= $obj->fk_user_approve;
267
            $this->user_approve_id2		= $obj->fk_user_approve2;
268
            $this->total_ht				= $obj->total_ht;
269
            $this->total_tva			= $obj->total_vat;
270
            $this->total_localtax1		= $obj->localtax1;
271
            $this->total_localtax2		= $obj->localtax2;
272
            $this->total_ttc			= $obj->total_ttc;
273
            $this->date					= $this->db->jdate($obj->date_creation);
274
            $this->date_valid			= $this->db->jdate($obj->date_valid);
275
            $this->date_approve			= $this->db->jdate($obj->date_approve);
276
            $this->date_approve2		= $this->db->jdate($obj->date_approve2);
277
            $this->date_commande		= $this->db->jdate($obj->date_commande); // date we make the order to supplier
278
			$this->date_livraison       = $this->db->jdate($obj->date_livraison);
279
            $this->remise_percent		= $obj->remise_percent;
280
            $this->methode_commande_id	= $obj->fk_input_method;
281
            $this->methode_commande		= $obj->methode_commande;
282
283
            $this->source				= $obj->source;
284
            $this->fk_project			= $obj->fk_project;
285
            $this->cond_reglement_id	= $obj->fk_cond_reglement;
286
            $this->cond_reglement_code	= $obj->cond_reglement_code;
287
            $this->cond_reglement		= $obj->cond_reglement_libelle;
288
            $this->cond_reglement_doc	= $obj->cond_reglement_libelle;
289
            $this->fk_account           = $obj->fk_account;
290
            $this->mode_reglement_id	= $obj->fk_mode_reglement;
291
            $this->mode_reglement_code	= $obj->mode_reglement_code;
292
            $this->mode_reglement		= $obj->mode_reglement_libelle;
293
            $this->note					= $obj->note_private;    // deprecated
294
            $this->note_private			= $obj->note_private;
295
            $this->note_public			= $obj->note_public;
296
            $this->modelpdf				= $obj->model_pdf;
297
298
			//Incoterms
299
			$this->fk_incoterms = $obj->fk_incoterms;
300
			$this->location_incoterms = $obj->location_incoterms;
301
			$this->libelle_incoterms = $obj->libelle_incoterms;
302
303
			// Multicurrency
304
			$this->fk_multicurrency 		= $obj->fk_multicurrency;
305
			$this->multicurrency_code 		= $obj->multicurrency_code;
306
			$this->multicurrency_tx 		= $obj->multicurrency_tx;
307
			$this->multicurrency_total_ht 	= $obj->multicurrency_total_ht;
308
			$this->multicurrency_total_tva 	= $obj->multicurrency_total_tva;
309
			$this->multicurrency_total_ttc 	= $obj->multicurrency_total_ttc;
310
311
            $this->extraparams			= (array) json_decode($obj->extraparams, true);
312
313
            $this->db->free($resql);
314
315
            // Retreive all extrafield
316
            // fetch optionals attributes and labels
317
            $this->fetch_optionals();
318
319
            if ($this->statut == 0) $this->brouillon = 1;
320
321
            /*
322
             * Lines
323
             */
324
            $result=$this->fetch_lines();
325
            if ($result < 0)
326
            {
327
            	return -1;
328
            }
329
            else
330
            {
331
            	return 1;
332
            }
333
        }
334
        else
335
        {
336
            $this->error=$this->db->error()." sql=".$sql;
337
            return -1;
338
        }
339
    }
340
341
    /**
342
     * Load array lines
343
     *
344
     * @param		int		$only_product	Return only physical products
345
     * @return		int						<0 if KO, >0 if OK
346
     */
347
    function fetch_lines($only_product=0)
348
    {
349
    	//$result=$this->fetch_lines();
350
    	$this->lines=array();
351
352
    	$sql = "SELECT l.rowid, l.ref as ref_supplier, l.fk_product, l.product_type, l.label, l.description, l.qty,";
353
    	$sql.= " l.vat_src_code, l.tva_tx, l.remise_percent, l.subprice,";
354
    	$sql.= " l.localtax1_tx, l. localtax2_tx, l.localtax1_type, l. localtax2_type, l.total_localtax1, l.total_localtax2,";
355
    	$sql.= " l.total_ht, l.total_tva, l.total_ttc, l.special_code, l.fk_parent_line, l.rang,";
356
    	$sql.= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.description as product_desc,";
357
    	$sql.= " l.fk_unit,";
358
    	$sql.= " l.date_start, l.date_end,";
359
    	$sql.= ' l.fk_multicurrency, l.multicurrency_code, l.multicurrency_subprice, l.multicurrency_total_ht, l.multicurrency_total_tva, l.multicurrency_total_ttc';
360
    	$sql.= " FROM ".MAIN_DB_PREFIX."commande_fournisseurdet	as l";
361
    	$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON l.fk_product = p.rowid';
362
    	$sql.= " WHERE l.fk_commande = ".$this->id;
363
    	if ($only_product) $sql .= ' AND p.fk_product_type = 0';
364
    	$sql.= " ORDER BY l.rang, l.rowid";
365
    	//print $sql;
366
367
    	dol_syslog(get_class($this)."::fetch get lines", LOG_DEBUG);
368
    	$result = $this->db->query($sql);
369
    	if ($result)
370
    	{
371
    		$num = $this->db->num_rows($result);
372
    		$i = 0;
373
374
    		while ($i < $num)
375
    		{
376
    			$objp                  = $this->db->fetch_object($result);
377
378
    			$line                 = new CommandeFournisseurLigne($this->db);
379
380
    			$line->id                  = $objp->rowid;
381
    			$line->desc                = $objp->description;
382
    			$line->description         = $objp->description;
383
    			$line->qty                 = $objp->qty;
384
    			$line->tva_tx              = $objp->tva_tx;
385
    			$line->localtax1_tx		   = $objp->localtax1_tx;
386
    			$line->localtax2_tx		   = $objp->localtax2_tx;
387
    			$line->localtax1_type	   = $objp->localtax1_type;
388
    			$line->localtax2_type	   = $objp->localtax2_type;
389
    			$line->subprice            = $objp->subprice;
390
    			$line->pu_ht	           = $objp->subprice;
391
    			$line->remise_percent      = $objp->remise_percent;
392
393
    			$line->vat_src_code        = $objp->vat_src_code;
394
    			$line->total_ht            = $objp->total_ht;
395
    			$line->total_tva           = $objp->total_tva;
396
    			$line->total_localtax1	   = $objp->total_localtax1;
397
    			$line->total_localtax2	   = $objp->total_localtax2;
398
    			$line->total_ttc           = $objp->total_ttc;
399
    			$line->product_type        = $objp->product_type;
400
401
    			$line->fk_product          = $objp->fk_product;
402
403
    			$line->libelle             = $objp->product_label;
404
    			$line->product_label       = $objp->product_label;
405
    			$line->product_desc        = $objp->product_desc;
406
407
    			$line->ref                 = $objp->product_ref;    // Ref of product
408
    			$line->product_ref         = $objp->product_ref;    // Ref of product
409
    			$line->ref_fourn           = $objp->ref_supplier;   // The supplier ref of price when product was added. May have change since
410
    			$line->ref_supplier        = $objp->ref_supplier;   // The supplier ref of price when product was added. May have change since
411
412
    			$line->date_start          = $this->db->jdate($objp->date_start);
413
    			$line->date_end            = $this->db->jdate($objp->date_end);
414
    			$line->fk_unit             = $objp->fk_unit;
415
416
    			// Multicurrency
417
    			$line->fk_multicurrency 		= $objp->fk_multicurrency;
418
    			$line->multicurrency_code 		= $objp->multicurrency_code;
419
    			$line->multicurrency_subprice 	= $objp->multicurrency_subprice;
420
    			$line->multicurrency_total_ht 	= $objp->multicurrency_total_ht;
421
    			$line->multicurrency_total_tva 	= $objp->multicurrency_total_tva;
422
    			$line->multicurrency_total_ttc 	= $objp->multicurrency_total_ttc;
423
424
    			$line->special_code        = $objp->special_code;
425
    			$line->fk_parent_line      = $objp->fk_parent_line;
426
427
    			$line->rang                = $objp->rang;
428
429
    			// Retreive all extrafield
430
    			// fetch optionals attributes and labels
431
    			$line->fetch_optionals();
432
433
    			$this->lines[$i]      = $line;
434
435
    			$i++;
436
    		}
437
    		$this->db->free($result);
438
439
    		return $num;
440
    	}
441
    	else
442
    	{
443
    		$this->error=$this->db->error()." sql=".$sql;
444
    		return -1;
445
    	}
446
    }
447
448
    /**
449
     *	Validate an order
450
     *
451
     *	@param	User	$user			Validator User
452
     *	@param	int		$idwarehouse	Id of warehouse to use for stock decrease
453
     *  @param	int		$notrigger		1=Does not execute triggers, 0= execute triggers
454
     *	@return	int						<0 if KO, >0 if OK
455
     */
456
    public function valid($user,$idwarehouse=0,$notrigger=0)
457
    {
458
        global $langs,$conf;
459
        require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
460
461
        $error=0;
462
463
        dol_syslog(get_class($this)."::valid");
464
        $result = 0;
465
        if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->fournisseur->commande->creer))
466
       	|| (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->fournisseur->supplier_order_advance->validate)))
467
        {
468
            $this->db->begin();
469
470
            // Definition of supplier order numbering model name
471
            $soc = new Societe($this->db);
472
            $soc->fetch($this->fourn_id);
473
474
            // Check if object has a temporary ref
475
            if (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref)) // empty should not happened, but when it occurs, the test save life
476
            {
477
                $num = $this->getNextNumRef($soc);
478
            }
479
            else
480
			{
481
                $num = $this->ref;
482
            }
483
            $this->newref = $num;
484
485
            $sql = 'UPDATE '.MAIN_DB_PREFIX."commande_fournisseur";
486
            $sql.= " SET ref='".$this->db->escape($num)."',";
487
            $sql.= " fk_statut = ".self::STATUS_VALIDATED.",";
488
            $sql.= " date_valid='".$this->db->idate(dol_now())."',";
489
            $sql.= " fk_user_valid = ".$user->id;
490
            $sql.= " WHERE rowid = ".$this->id;
491
            $sql.= " AND fk_statut = ".self::STATUS_DRAFT;
492
493
            $resql=$this->db->query($sql);
494
            if (! $resql)
495
            {
496
                dol_print_error($this->db);
497
                $error++;
498
            }
499
500
            if (! $error && ! $notrigger)
501
            {
502
				// Call trigger
503
				$result=$this->call_trigger('ORDER_SUPPLIER_VALIDATE',$user);
504
				if ($result < 0) $error++;
505
				// End call triggers
506
            }
507
508
            if (! $error)
509
            {
510
	            $this->oldref = $this->ref;
511
512
                // Rename directory if dir was a temporary ref
513
                if (preg_match('/^[\(]?PROV/i', $this->ref))
514
                {
515
                    // We rename directory ($this->ref = ancienne ref, $num = nouvelle ref)
516
                    // in order not to lose the attached files
517
                    $oldref = dol_sanitizeFileName($this->ref);
518
                    $newref = dol_sanitizeFileName($num);
519
                    $dirsource = $conf->fournisseur->commande->dir_output.'/'.$oldref;
520
                    $dirdest = $conf->fournisseur->commande->dir_output.'/'.$newref;
521
                    if (file_exists($dirsource))
522
                    {
523
                        dol_syslog(get_class($this)."::valid rename dir ".$dirsource." into ".$dirdest);
524
525
                        if (@rename($dirsource, $dirdest))
526
                        {
527
                            dol_syslog("Rename ok");
528
                            // Rename docs starting with $oldref with $newref
529
	                        $listoffiles=dol_dir_list($conf->fournisseur->commande->dir_output.'/'.$newref, 'files', 1, '^'.preg_quote($oldref,'/'));
530
	                        foreach($listoffiles as $fileentry)
531
	                        {
532
	                        	$dirsource=$fileentry['name'];
533
	                        	$dirdest=preg_replace('/^'.preg_quote($oldref,'/').'/',$newref, $dirsource);
534
	                        	$dirsource=$fileentry['path'].'/'.$dirsource;
535
	                        	$dirdest=$fileentry['path'].'/'.$dirdest;
536
	                        	@rename($dirsource, $dirdest);
537
	                        }
538
                        }
539
                    }
540
                }
541
            }
542
543
            if (! $error)
544
            {
545
                $result = 1;
546
                $this->statut = self::STATUS_VALIDATED;
547
                $this->ref = $num;
548
            }
549
550
            if (! $error)
551
            {
552
                $this->db->commit();
553
                return 1;
554
            }
555
            else
556
            {
557
                $this->db->rollback();
558
                return -1;
559
            }
560
        }
561
        else
562
        {
563
            $this->error='NotAuthorized';
564
            dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
565
            return -1;
566
        }
567
    }
568
569
    /**
570
     *  Return label of the status of object
571
     *
572
	 *  @param      int		$mode			0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=short label + picto
573
     *  @return 	string        			Label
574
     */
575
    public function getLibStatut($mode=0)
576
    {
577
        return $this->LibStatut($this->statut,$mode,$this->billed);
578
    }
579
580
    /**
581
     *  Return label of a status
582
     *
583
     * 	@param  int		$statut		Id statut
584
     *  @param  int		$mode       0=Long label, 1=Short label, 2=Picto + Short label, 3=Picto, 4=Picto + Long label, 5=Short label + Picto
585
     *  @param  int     $billed     1=Billed
586
     *  @return string				Label of status
587
     */
588
    function LibStatut($statut,$mode=0,$billed=0)
589
    {
590
        global $langs;
591
        $langs->load('orders');
592
593
        $billedtext='';
594
		//if ($statut==5 && $this->billed == 1) $statut = 8;
595
        if ($billed == 1) $billedtext=$langs->trans("Billed");
596
597
        // List of language codes for status
598
        $statutshort[0] = 'StatusOrderDraftShort';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$statutshort was never initialized. Although not strictly required by PHP, it is generally a good practice to add $statutshort = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
599
        $statutshort[1] = 'StatusOrderValidatedShort';
600
        $statutshort[2] = 'StatusOrderApprovedShort';
601
        $statutshort[3] = 'StatusOrderOnProcessShort';
602
        $statutshort[4] = 'StatusOrderReceivedPartiallyShort';
603
        $statutshort[5] = 'StatusOrderReceivedAllShort';
604
        $statutshort[6] = 'StatusOrderCanceledShort';
605
        $statutshort[7] = 'StatusOrderCanceledShort';
606
        $statutshort[9] = 'StatusOrderRefusedShort';
607
608
        if ($mode == 0)
609
        {
610
            return $langs->trans($this->statuts[$statut]);
611
        }
612
        if ($mode == 1)
613
        {
614
            return $langs->trans($statutshort[$statut]);
615
        }
616
        if ($mode == 2)
617
        {
618
            return $langs->trans($this->statuts[$statut]);
619
        }
620
        if ($mode == 3)
621
        {
622
            if ($statut==0) return img_picto($langs->trans($this->statuts[$statut]),'statut0');
623
            if ($statut==1) return img_picto($langs->trans($this->statuts[$statut]),'statut1');
624
            if ($statut==2) return img_picto($langs->trans($this->statuts[$statut]),'statut3');
625
            if ($statut==3) return img_picto($langs->trans($this->statuts[$statut]),'statut3');
626
            if ($statut==4) return img_picto($langs->trans($this->statuts[$statut]),'statut3');
627
            if ($statut==5) return img_picto($langs->trans($this->statuts[$statut]),'statut6');
628
            if ($statut==6 || $statut==7) return img_picto($langs->trans($this->statuts[$statut]),'statut5');
629
            if ($statut==9) return img_picto($langs->trans($this->statuts[$statut]),'statut5');
630
        }
631
        if ($mode == 4)
632
        {
633
            if ($statut==0) return img_picto($langs->trans($this->statuts[$statut]),'statut0').' '.$langs->trans($this->statuts[$statut]).($billedtext?' - '.$billedtext:'');
634
            if ($statut==1) return img_picto($langs->trans($this->statuts[$statut]),'statut1').' '.$langs->trans($this->statuts[$statut]).($billedtext?' - '.$billedtext:'');
635
            if ($statut==2) return img_picto($langs->trans($this->statuts[$statut]),'statut3').' '.$langs->trans($this->statuts[$statut]).($billedtext?' - '.$billedtext:'');
636
            if ($statut==3) return img_picto($langs->trans($this->statuts[$statut]),'statut3').' '.$langs->trans($this->statuts[$statut]).($billedtext?' - '.$billedtext:'');
637
            if ($statut==4) return img_picto($langs->trans($this->statuts[$statut]),'statut3').' '.$langs->trans($this->statuts[$statut]).($billedtext?' - '.$billedtext:'');
638
            if ($statut==5) return img_picto($langs->trans($this->statuts[$statut]),'statut6').' '.$langs->trans($this->statuts[$statut]).($billedtext?' - '.$billedtext:'');
639
            if ($statut==6 || $statut==7) return img_picto($langs->trans($this->statuts[$statut]),'statut5').' '.$langs->trans($this->statuts[$statut]).($billedtext?' - '.$billedtext:'');
640
            if ($statut==9) return img_picto($langs->trans($this->statuts[$statut]),'statut5').' '.$langs->trans($this->statuts[$statut]).($billedtext?' - '.$billedtext:'');
641
        }
642
        if ($mode == 5)
643
        {
644
            if ($statut==0) return '<span class="hideonsmartphone">'.$langs->trans($statutshort[$statut]).' </span>'.img_picto($langs->trans($this->statuts[$statut]),'statut0');
645
            if ($statut==1) return '<span class="hideonsmartphone">'.$langs->trans($statutshort[$statut]).' </span>'.img_picto($langs->trans($this->statuts[$statut]),'statut1');
646
            if ($statut==2) return '<span class="hideonsmartphone">'.$langs->trans($statutshort[$statut]).' </span>'.img_picto($langs->trans($this->statuts[$statut]),'statut3');
647
            if ($statut==3) return '<span class="hideonsmartphone">'.$langs->trans($statutshort[$statut]).' </span>'.img_picto($langs->trans($this->statuts[$statut]),'statut3');
648
            if ($statut==4) return '<span class="hideonsmartphone">'.$langs->trans($statutshort[$statut]).' </span>'.img_picto($langs->trans($this->statuts[$statut]),'statut3');
649
            if ($statut==5) return '<span class="hideonsmartphone">'.$langs->trans($statutshort[$statut]).' </span>'.img_picto($langs->trans($this->statuts[$statut]),'statut6');
650
            if ($statut==6 || $statut==7) return '<span class="hideonsmartphone">'.$langs->trans($statutshort[$statut]).' </span>'.img_picto($langs->trans($this->statuts[$statut]),'statut5');
651
            if ($statut==9) return '<span class="hideonsmartphone">'.$langs->trans($statutshort[$statut]).' </span>'.img_picto($langs->trans($this->statuts[$statut]),'statut5');
652
        }
653
    }
654
655
656
    /**
657
     *	Return clicable name (with picto eventually)
658
     *
659
     *	@param		int		$withpicto					0=No picto, 1=Include picto into link, 2=Only picto
660
     *	@param		string	$option						On what the link points
661
     *  @param	    int   	$notooltip					1=Disable tooltip
662
     *  @param      int     $save_lastsearch_value		-1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
663
     *	@return		string								Chain with URL
664
     */
665
    public function getNomUrl($withpicto=0, $option='', $notooltip=0, $save_lastsearch_value=-1)
666
    {
667
        global $langs, $conf;
668
669
        $result='';
670
        $label = '<u>' . $langs->trans("ShowOrder") . '</u>';
671
        if (! empty($this->ref))
672
            $label .= '<br><b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
673
        if (! empty($this->ref_supplier))
674
            $label.= '<br><b>' . $langs->trans('RefSupplier') . ':</b> ' . $this->ref_supplier;
675
        if (! empty($this->total_ht))
676
            $label.= '<br><b>' . $langs->trans('AmountHT') . ':</b> ' . price($this->total_ht, 0, $langs, 0, -1, -1, $conf->currency);
677
        if (! empty($this->total_tva))
678
            $label.= '<br><b>' . $langs->trans('VAT') . ':</b> ' . price($this->total_tva, 0, $langs, 0, -1, -1, $conf->currency);
679
        if (! empty($this->total_ttc))
680
            $label.= '<br><b>' . $langs->trans('AmountTTC') . ':</b> ' . price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency);
681
682
        $picto='order';
683
        $url = DOL_URL_ROOT.'/fourn/commande/card.php?id='.$this->id;
684
685
        if ($option !== 'nolink')
686
        {
687
        	// Add param to save lastsearch_values or not
688
        	$add_save_lastsearch_values=($save_lastsearch_value == 1 ? 1 : 0);
689
        	if ($save_lastsearch_value == -1 && preg_match('/list\.php/',$_SERVER["PHP_SELF"])) $add_save_lastsearch_values=1;
690
        	if ($add_save_lastsearch_values) $url.='&save_lastsearch_values=1';
691
        }
692
693
        $linkclose='';
694
        if (empty($notooltip))
695
        {
696
            if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
697
            {
698
                $label=$langs->trans("ShowOrder");
699
                $linkclose.=' alt="'.dol_escape_htmltag($label, 1).'"';
700
            }
701
            $linkclose.= ' title="'.dol_escape_htmltag($label, 1).'"';
702
            $linkclose.=' class="classfortooltip"';
703
        }
704
705
        $linkstart = '<a href="'.$url.'"';
706
        $linkstart.=$linkclose.'>';
707
        $linkend='</a>';
708
709
        $result .= $linkstart;
710
        if ($withpicto) $result.=img_object(($notooltip?'':$label), $this->picto, ($notooltip?(($withpicto != 2) ? 'class="paddingright"' : ''):'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip?0:1);
711
        if ($withpicto != 2) $result.= $this->ref;
712
        $result .= $linkend;
713
714
        return $result;
715
    }
716
717
718
    /**
719
     *  Returns the following order reference not used depending on the numbering model activated
720
     *                  defined within COMMANDE_SUPPLIER_ADDON_NUMBER
721
     *
722
     *  @param	    Company		$soc  		company object
723
     *  @return     string                  free reference for the invoice
724
     */
725
    public function getNextNumRef($soc)
726
    {
727
        global $db, $langs, $conf;
728
        $langs->load("orders");
729
730
        if (! empty($conf->global->COMMANDE_SUPPLIER_ADDON_NUMBER))
731
        {
732
            $mybool = false;
733
734
            $file = $conf->global->COMMANDE_SUPPLIER_ADDON_NUMBER.'.php';
735
            $classname=$conf->global->COMMANDE_SUPPLIER_ADDON_NUMBER;
736
737
            // Include file with class
738
            $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
739
740
            foreach ($dirmodels as $reldir) {
741
742
                $dir = dol_buildpath($reldir."core/modules/supplier_order/");
743
744
                // Load file with numbering class (if found)
745
                $mybool|=@include_once $dir.$file;
746
            }
747
748
            if (! $mybool)
749
            {
750
                dol_print_error('',"Failed to include file ".$file);
751
                return '';
752
            }
753
754
            $obj = new $classname();
755
            $numref = $obj->getNextValue($soc,$this);
756
757
            if ( $numref != "")
758
            {
759
                return $numref;
760
            }
761
            else
762
			{
763
                $this->error = $obj->error;
764
                return -1;
765
            }
766
        }
767
        else
768
		{
769
            $this->error = "Error_COMMANDE_SUPPLIER_ADDON_NotDefined";
770
            return -2;
771
        }
772
    }
773
	/**
774
     *	Class invoiced the supplier order
775
     *
776
     *  @param      User        $user       Object user making the change
777
     *	@return     int     	            <0 if KO, >0 if KO
778
     */
779
    public function classifyBilled(User $user)
780
    {
781
        $error=0;
782
        $this->db->begin();
783
784
        $sql = 'UPDATE '.MAIN_DB_PREFIX.'commande_fournisseur SET billed = 1';
785
        $sql .= ' WHERE rowid = '.$this->id.' AND fk_statut > '.self::STATUS_DRAFT;
786
        if ($this->db->query($sql))
787
        {
788
        	if (! $error)
789
        	{
790
        	    // Call trigger
791
        	    $result=$this->call_trigger('ORDER_SUPPLIER_CLASSIFY_BILLED',$user);
792
        	    if ($result < 0) $error++;
793
        	    // End call triggers
794
        	}
795
796
        	if (! $error)
797
        	{
798
        	    $this->billed=1;
799
800
        	    $this->db->commit();
801
        	    return 1;
802
        	}
803
        	else
804
        	{
805
        	    $this->db->rollback();
806
                return -1;
807
        	}
808
        }
809
        else
810
        {
811
        	dol_print_error($this->db);
812
813
        	$this->db->rollback();
814
			return -1;
815
        }
816
    }
817
818
    /**
819
     * 	Approve a supplier order
820
     *
821
     *	@param	User	$user			Object user
822
     *	@param	int		$idwarehouse	Id of warhouse for stock change
823
     *  @param	int		$secondlevel	0=Standard approval, 1=Second level approval (used when option SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED is set)
824
     *	@return	int						<0 if KO, >0 if OK
825
     */
826
    public function approve($user, $idwarehouse=0, $secondlevel=0)
827
    {
828
        global $langs,$conf;
829
		require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
830
831
        $error=0;
832
833
        dol_syslog(get_class($this)."::approve");
834
835
        if ($user->rights->fournisseur->commande->approuver)
836
        {
837
        	$now = dol_now();
838
839
            $this->db->begin();
840
841
			// Definition of order numbering model name
842
            $soc = new Societe($this->db);
843
            $soc->fetch($this->fourn_id);
844
845
            // Check if object has a temporary ref
846
            if (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref)) // empty should not happened, but when it occurs, the test save life
847
            {
848
                $num = $this->getNextNumRef($soc);
849
            }
850
            else
851
			{
852
                $num = $this->ref;
853
            }
854
            $this->newref = $num;
855
856
            // Do we have to change status now ? (If double approval is required and first approval, we keep status to 1 = validated)
857
			$movetoapprovestatus=true;
858
			$comment='';
859
860
            $sql = "UPDATE ".MAIN_DB_PREFIX."commande_fournisseur";
861
			$sql.= " SET ref='".$this->db->escape($num)."',";
862
			if (empty($secondlevel))	// standard or first level approval
863
			{
864
	            $sql.= " date_approve='".$this->db->idate($now)."',";
865
    	        $sql.= " fk_user_approve = ".$user->id;
866
    	        if (! empty($conf->global->SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED) && $conf->global->MAIN_FEATURES_LEVEL > 0 && $this->total_ht >= $conf->global->SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED)
867
    	        {
868
    	        	if (empty($this->user_approve_id2))
869
    	        	{
870
    	        	    $movetoapprovestatus=false;		// second level approval not done
871
    	        	    $comment=' (first level)';
872
    	        	}
873
    	        }
874
			}
875
			else	// request a second level approval
876
			{
877
            	$sql.= " date_approve2='".$this->db->idate($now)."',";
878
            	$sql.= " fk_user_approve2 = ".$user->id;
879
    	        if (empty($this->user_approve_id)) $movetoapprovestatus=false;		// first level approval not done
880
    	        $comment=' (second level)';
881
			}
882
			// If double approval is required and first approval, we keep status to 1 = validated
883
			if ($movetoapprovestatus) $sql.= ", fk_statut = ".self::STATUS_ACCEPTED;
884
			else $sql.= ", fk_statut = ".self::STATUS_VALIDATED;
885
            $sql.= " WHERE rowid = ".$this->id;
886
            $sql.= " AND fk_statut = ".self::STATUS_VALIDATED;
887
888
            if ($this->db->query($sql))
889
            {
890
            	if (! empty($conf->global->SUPPLIER_ORDER_AUTOADD_USER_CONTACT))
891
	            {
892
					$result=$this->add_contact($user->id, 'SALESREPFOLL', 'internal', 1);
893
					if ($result < 0 && $result != -2)	// -2 means already exists
894
					{
895
						$error++;
896
					}
897
	            }
898
899
                // If stock is incremented on validate order, we must increment it
900
                if (! $error && $movetoapprovestatus && ! empty($conf->stock->enabled) && ! empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER))
901
                {
902
                    require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
903
                    $langs->load("agenda");
904
905
                    $cpt=count($this->lines);
906
                    for ($i = 0; $i < $cpt; $i++)
907
                    {
908
                        // Product with reference
909
                        if ($this->lines[$i]->fk_product > 0)
910
                        {
911
                            $this->line = $this->lines[$i];
912
                            $mouvP = new MouvementStock($this->db);
913
                            $mouvP->origin = &$this;
914
                            // We decrement stock of product (and sub-products)
915
	                        $up_ht_disc=$this->lines[$i]->subprice;
916
    	                    if (! empty($this->lines[$i]->remise_percent) && empty($conf->global->STOCK_EXCLUDE_DISCOUNT_FOR_PMP)) $up_ht_disc=price2num($up_ht_disc * (100 - $this->lines[$i]->remise_percent) / 100, 'MU');
917
                            $result=$mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $up_ht_disc, $langs->trans("OrderApprovedInDolibarr",$this->ref));
918
                            if ($result < 0) { $error++; }
919
                            unset($this->line);
920
                        }
921
                    }
922
                }
923
924
                if (! $error)
925
                {
926
					// Call trigger
927
					$result=$this->call_trigger('ORDER_SUPPLIER_APPROVE',$user);
928
					if ($result < 0) $error++;
929
					// End call triggers
930
                }
931
932
                if (! $error)
933
                {
934
                	$this->ref = $this->newref;
935
936
                	if ($movetoapprovestatus) $this->statut = self::STATUS_ACCEPTED;
937
					else $this->statut = self::STATUS_VALIDATED;
938
           			if (empty($secondlevel))	// standard or first level approval
939
					{
940
			            $this->date_approve = $now;
941
		    	        $this->user_approve_id = $user->id;
942
					}
943
					else	// request a second level approval
944
					{
945
			            $this->date_approve2 = $now;
946
		    	        $this->user_approve_id2 = $user->id;
947
					}
948
949
                    $this->db->commit();
950
                    return 1;
951
                }
952
                else
953
                {
954
                    $this->db->rollback();
955
                    return -1;
956
                }
957
            }
958
            else
959
            {
960
                $this->db->rollback();
961
                $this->error=$this->db->lasterror();
962
                return -1;
963
            }
964
        }
965
        else
966
        {
967
            dol_syslog(get_class($this)."::approve Not Authorized", LOG_ERR);
968
        }
969
        return -1;
970
    }
971
972
    /**
973
     * 	Refuse an order
974
     *
975
     * 	@param		User	$user		User making action
976
     *	@return		int					0 if Ok, <0 if Ko
977
     */
978
    public function refuse($user)
979
    {
980
        global $conf, $langs;
981
982
		$error=0;
983
984
        dol_syslog(get_class($this)."::refuse");
985
        $result = 0;
986
        if ($user->rights->fournisseur->commande->approuver)
987
        {
988
            $this->db->begin();
989
990
            $sql = "UPDATE ".MAIN_DB_PREFIX."commande_fournisseur SET fk_statut = ".self::STATUS_REFUSED;
991
            $sql .= " WHERE rowid = ".$this->id;
992
993
            if ($this->db->query($sql))
994
            {
995
                $result = 0;
996
997
                if ($error == 0)
998
                {
999
					// Call trigger
1000
					$result=$this->call_trigger('ORDER_SUPPLIER_REFUSE',$user);
1001
					if ($result < 0)
1002
                    {
1003
                        $error++;
1004
                        $this->db->rollback();
1005
                    }
1006
                    else
1007
                    	$this->db->commit();
1008
					// End call triggers
1009
                }
1010
            }
1011
            else
1012
            {
1013
                $this->db->rollback();
1014
                $this->error=$this->db->lasterror();
1015
                dol_syslog(get_class($this)."::refuse Error -1");
1016
                $result = -1;
1017
            }
1018
        }
1019
        else
1020
        {
1021
            dol_syslog(get_class($this)."::refuse Not Authorized");
1022
        }
1023
        return $result ;
1024
    }
1025
1026
    /**
1027
     * 	Cancel an approved order.
1028
     *	The cancellation is done after approval
1029
     *
1030
     * 	@param	User	$user			User making action
1031
     *	@param	int		$idwarehouse	Id warehouse to use for stock change (not used for supplier orders).
1032
     * 	@return	int						>0 if Ok, <0 if Ko
1033
     */
1034
    function Cancel($user, $idwarehouse=-1)
1035
    {
1036
        global $langs,$conf;
1037
1038
		$error=0;
1039
1040
        //dol_syslog("CommandeFournisseur::Cancel");
1041
        $result = 0;
1042
        if ($user->rights->fournisseur->commande->commander)
1043
        {
1044
            $statut = self::STATUS_CANCELED;
1045
1046
            $this->db->begin();
1047
1048
            $sql = "UPDATE ".MAIN_DB_PREFIX."commande_fournisseur SET fk_statut = ".$statut;
1049
            $sql .= " WHERE rowid = ".$this->id;
1050
            dol_syslog(get_class($this)."::cancel", LOG_DEBUG);
1051
            if ($this->db->query($sql))
1052
            {
1053
                $result = 0;
1054
1055
				// Call trigger
1056
				$result=$this->call_trigger('ORDER_SUPPLIER_CANCEL',$user);
1057
				if ($result < 0) $error++;
1058
				// End call triggers
1059
1060
                if ($error == 0)
1061
                {
1062
                    $this->db->commit();
1063
                    return 1;
1064
                }
1065
                else
1066
                {
1067
                    $this->db->rollback();
1068
                    return -1;
1069
                }
1070
            }
1071
            else
1072
            {
1073
                $this->db->rollback();
1074
                $this->error=$this->db->lasterror();
1075
                dol_syslog(get_class($this)."::cancel ".$this->error);
1076
                return -1;
1077
            }
1078
        }
1079
        else
1080
        {
1081
            dol_syslog(get_class($this)."::cancel Not Authorized");
1082
            return -1;
1083
        }
1084
    }
1085
1086
1087
    /**
1088
     * 	Submit a supplier order to supplier
1089
     *
1090
     * 	@param		User	$user		User making change
1091
     * 	@param		date	$date		Date
1092
     * 	@param		int		$methode	Method
1093
     * 	@param		string	$comment	Comment
1094
     * 	@return		int			        <0 if KO, >0 if OK
1095
     */
1096
    public function commande($user, $date, $methode, $comment='')
1097
    {
1098
        global $langs;
1099
        dol_syslog(get_class($this)."::commande");
1100
        $error = 0;
1101
        if ($user->rights->fournisseur->commande->commander)
1102
        {
1103
            $this->db->begin();
1104
1105
            $sql = "UPDATE ".MAIN_DB_PREFIX."commande_fournisseur SET fk_statut = ".self::STATUS_ORDERSENT.", fk_input_method=".$methode.", date_commande='".$this->db->idate($date)."'";
1106
            $sql .= " WHERE rowid = ".$this->id;
1107
1108
            dol_syslog(get_class($this)."::commande", LOG_DEBUG);
1109
            if ($this->db->query($sql))
1110
            {
1111
                $this->statut = self::STATUS_ORDERSENT;
1112
                $this->methode_commande_id = $methode;
1113
                $this->date_commande = $date;
1114
1115
                // Call trigger
1116
                $result=$this->call_trigger('ORDER_SUPPLIER_SUBMIT',$user);
1117
                if ($result < 0) $error++;
1118
                // End call triggers
1119
            }
1120
            else
1121
            {
1122
                $error++;
1123
                $this->error = $this->db->lasterror();
1124
                $this->errors[] = $this->db->lasterror();
1125
            }
1126
1127
            if (! $error)
1128
            {
1129
                $this->db->commit();
1130
            }
1131
            else
1132
            {
1133
                $this->db->rollback();
1134
            }
1135
        }
1136
        else
1137
        {
1138
            $error++;
1139
            $this->error = $langs->trans('NotAuthorized');
1140
            $this->errors[] = $langs->trans('NotAuthorized');
1141
            dol_syslog(get_class($this)."::commande User not Authorized", LOG_WARNING);
1142
        }
1143
1144
        return ($error ? -1 : 1);
1145
    }
1146
1147
    /**
1148
     *  Create order with draft status
1149
     *
1150
     *  @param      User	$user       User making creation
1151
     *	@param		int		$notrigger	Disable all triggers
1152
     *  @return     int         		<0 if KO, Id of supplier order if OK
1153
     */
1154
    public function create($user, $notrigger=0)
1155
    {
1156
        global $langs,$conf,$hookmanager;
1157
1158
        $this->db->begin();
1159
1160
		$error=0;
1161
        $now=dol_now();
1162
1163
        // Clean parameters
1164
        if (empty($this->source)) $this->source = 0;
1165
1166
		// Multicurrency (test on $this->multicurrency_tx because we should take the default rate only if not using origin rate)
1167
		if (!empty($this->multicurrency_code) && empty($this->multicurrency_tx)) list($this->fk_multicurrency,$this->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code);
1168
		else $this->fk_multicurrency = MultiCurrency::getIdFromCode($this->db, $this->multicurrency_code);
1169
		if (empty($this->fk_multicurrency))
1170
		{
1171
			$this->multicurrency_code = $conf->currency;
1172
			$this->fk_multicurrency = 0;
1173
			$this->multicurrency_tx = 1;
1174
		}
1175
1176
        // We set order into draft status
1177
        $this->brouillon = 1;
1178
1179
        $sql = "INSERT INTO ".MAIN_DB_PREFIX."commande_fournisseur (";
1180
        $sql.= "ref";
1181
        $sql.= ", ref_supplier";
1182
        $sql.= ", note_private";
1183
        $sql.= ", note_public";
1184
        $sql.= ", entity";
1185
        $sql.= ", fk_soc";
1186
        $sql.= ", fk_projet";
1187
        $sql.= ", date_creation";
1188
		$sql.= ", date_livraison";
1189
        $sql.= ", fk_user_author";
1190
        $sql.= ", fk_statut";
1191
        $sql.= ", source";
1192
        $sql.= ", model_pdf";
1193
        $sql.= ", fk_mode_reglement";
1194
		$sql.= ", fk_cond_reglement";
1195
        $sql.= ", fk_account";
1196
		$sql.= ", fk_incoterms, location_incoterms";
1197
        $sql.= ", fk_multicurrency";
1198
        $sql.= ", multicurrency_code";
1199
        $sql.= ", multicurrency_tx";
1200
        $sql.= ") ";
1201
        $sql.= " VALUES (";
1202
        $sql.= "''";
1203
        $sql.= ", '".$this->db->escape($this->ref_supplier)."'";
1204
        $sql.= ", '".$this->db->escape($this->note_private)."'";
1205
        $sql.= ", '".$this->db->escape($this->note_public)."'";
1206
        $sql.= ", ".$conf->entity;
1207
        $sql.= ", ".$this->socid;
1208
        $sql.= ", ".($this->fk_project > 0 ? $this->fk_project : "null");
1209
        $sql.= ", '".$this->db->idate($now)."'";
1210
		$sql.= ", ".($this->date_livraison?"'".$this->db->idate($this->date_livraison)."'":"null");
1211
        $sql.= ", ".$user->id;
1212
        $sql.= ", ".self::STATUS_DRAFT;
1213
        $sql.= ", ".$this->db->escape($this->source);
1214
        $sql.= ", '".$conf->global->COMMANDE_SUPPLIER_ADDON_PDF."'";
1215
        $sql.= ", ".($this->mode_reglement_id > 0 ? $this->mode_reglement_id : 'null');
1216
        $sql.= ", ".($this->cond_reglement_id > 0 ? $this->cond_reglement_id : 'null');
1217
        $sql.= ", ".($this->fk_account>0?$this->fk_account:'NULL');
1218
        $sql.= ", ".(int) $this->fk_incoterms;
1219
        $sql.= ", '".$this->db->escape($this->location_incoterms)."'";
1220
		$sql.= ", ".(int) $this->fk_multicurrency;
1221
		$sql.= ", '".$this->db->escape($this->multicurrency_code)."'";
1222
		$sql.= ", ".(double) $this->multicurrency_tx;
1223
        $sql.= ")";
1224
1225
        dol_syslog(get_class($this)."::create", LOG_DEBUG);
1226
        if ($this->db->query($sql))
1227
        {
1228
            $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."commande_fournisseur");
1229
1230
			if ($this->id) {
1231
				$num=count($this->lines);
1232
1233
	            // insert products details into database
1234
	            for ($i=0;$i<$num;$i++)
1235
	            {
1236
	                $result = $this->addline(              // This include test on qty if option SUPPLIER_ORDER_WITH_NOPRICEDEFINED is not set
1237
	                    $this->lines[$i]->desc,
1238
	                    $this->lines[$i]->subprice,
1239
	                    $this->lines[$i]->qty,
1240
	                    $this->lines[$i]->tva_tx,
1241
	                    $this->lines[$i]->localtax1_tx,
1242
	                    $this->lines[$i]->localtax2_tx,
1243
	                    $this->lines[$i]->fk_product,
1244
	                    0,
1245
	                    $this->lines[$i]->ref_fourn,   // $this->lines[$i]->ref_fourn comes from field ref into table of lines. Value may ba a ref that does not exists anymore, so we first try with value of product
1246
	                    $this->lines[$i]->remise_percent,
1247
	                    'HT',
1248
	                    0,
1249
	                    $this->lines[$i]->product_type,
1250
	                    $this->lines[$i]->info_bits,
1251
                        false,
1252
	                    $this->lines[$i]->date_start,
1253
                        $this->lines[$i]->date_end,
1254
                        0,
1255
                        $this->lines[$i]->fk_unit
1256
	                );
1257
	                if ($result < 0)
1258
	                {
1259
	                    dol_syslog(get_class($this)."::create ".$this->error, LOG_WARNING);	// do not use dol_print_error here as it may be a functionnal error
1260
	                    $this->db->rollback();
1261
	                    return -1;
1262
	                }
1263
	            }
1264
1265
	            $sql = "UPDATE ".MAIN_DB_PREFIX."commande_fournisseur";
1266
	            $sql.= " SET ref='(PROV".$this->id.")'";
1267
	            $sql.= " WHERE rowid=".$this->id;
1268
	            dol_syslog(get_class($this)."::create", LOG_DEBUG);
1269
	            if ($this->db->query($sql))
1270
	            {
1271
					// Add link with price request and supplier order
1272
					if ($this->id)
1273
					{
1274
						$this->ref="(PROV".$this->id.")";
1275
1276
						if (! empty($this->linkedObjectsIds) && empty($this->linked_objects))	// To use new linkedObjectsIds instead of old linked_objects
1277
						{
1278
							$this->linked_objects = $this->linkedObjectsIds;	// TODO Replace linked_objects with linkedObjectsIds
1279
						}
1280
1281
						// Add object linked
1282
						if (! $error && $this->id && is_array($this->linked_objects) && ! empty($this->linked_objects))
1283
						{
1284
							foreach($this->linked_objects as $origin => $tmp_origin_id)
1285
							{
1286
							    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, ...))
1287
							    {
1288
							        foreach($tmp_origin_id as $origin_id)
1289
							        {
1290
							            $ret = $this->add_object_linked($origin, $origin_id);
1291
							            if (! $ret)
1292
							            {
1293
							                dol_print_error($this->db);
1294
							                $error++;
1295
							            }
1296
							        }
1297
							    }
1298
							    else                                // Old behaviour, if linked_object has only one link per type, so is something like array('contract'=>id1))
1299
							    {
1300
							        $origin_id = $tmp_origin_id;
1301
									$ret = $this->add_object_linked($origin, $origin_id);
1302
									if (! $ret)
1303
									{
1304
										dol_print_error($this->db);
1305
										$error++;
1306
									}
1307
							    }
1308
							}
1309
						}
1310
					}
1311
1312
	                if (! $error)
1313
                    {
1314
                    	$result=$this->insertExtraFields();
1315
	                    if ($result < 0) $error++;
1316
                    }
1317
1318
					if (! $error && ! $notrigger)
1319
	                {
1320
						// Call trigger
1321
						$result=$this->call_trigger('ORDER_SUPPLIER_CREATE',$user);
1322
						if ($result < 0)
1323
	                    {
1324
	                        $this->db->rollback();
1325
	                        return -1;
1326
	                    }
1327
						// End call triggers
1328
	                }
1329
1330
	                $this->db->commit();
1331
	                return $this->id;
1332
	            }
1333
	            else
1334
	            {
1335
	                $this->error=$this->db->lasterror();
1336
	                $this->db->rollback();
1337
	                return -2;
1338
	            }
1339
            }
1340
        }
1341
        else
1342
        {
1343
            $this->error=$this->db->lasterror();
1344
            $this->db->rollback();
1345
            return -1;
1346
        }
1347
    }
1348
1349
    /**
1350
     *	Load an object from its id and create a new one in database
1351
     *
1352
     *	@return		int							New id of clone
1353
     */
1354
    public function createFromClone()
1355
    {
1356
        global $conf,$user,$langs,$hookmanager;
1357
1358
        $error=0;
1359
1360
		$this->context['createfromclone'] = 'createfromclone';
1361
1362
		$this->db->begin();
1363
1364
		// Load source object
1365
		$objFrom = clone $this;
1366
1367
        $this->id=0;
1368
        $this->statut=self::STATUS_DRAFT;
1369
1370
        // Clear fields
1371
        $this->user_author_id     = $user->id;
1372
        $this->user_valid         = '';
1373
        $this->date_creation      = '';
1374
        $this->date_validation    = '';
1375
        $this->ref_supplier       = '';
1376
        $this->user_approve_id    = '';
1377
        $this->user_approve_id2   = '';
1378
        $this->date_approve       = '';
1379
        $this->date_approve2      = '';
1380
1381
        // Create clone
1382
        $result=$this->create($user);
1383
        if ($result < 0) $error++;
1384
1385
        if (! $error)
1386
        {
1387
            // Hook of thirdparty module
1388
            if (is_object($hookmanager))
1389
            {
1390
                $parameters=array('objFrom'=>$objFrom);
1391
                $action='';
1392
                $reshook=$hookmanager->executeHooks('createFrom',$parameters,$this,$action);    // Note that $action and $object may have been modified by some hooks
1393
                if ($reshook < 0) $error++;
1394
            }
1395
        }
1396
1397
		unset($this->context['createfromclone']);
1398
1399
		// End
1400
        if (! $error)
1401
        {
1402
            $this->db->commit();
1403
            return $this->id;
1404
        }
1405
        else
1406
        {
1407
            $this->db->rollback();
1408
            return -1;
1409
        }
1410
    }
1411
1412
    /**
1413
     *	Add order line
1414
     *
1415
     *	@param      string	$desc            		Description
1416
     *	@param      float	$pu_ht              	Unit price
1417
     *	@param      float	$qty             		Quantity
1418
     *	@param      float	$txtva           		Taux tva
1419
     *	@param      float	$txlocaltax1        	Localtax1 tax
1420
     *  @param      float	$txlocaltax2        	Localtax2 tax
1421
     *	@param      int		$fk_product      		Id product
1422
     *  @param      int		$fk_prod_fourn_price	Id supplier price
1423
     *  @param      string	$ref_supplier			Supplier reference price
1424
     *	@param      float	$remise_percent  		Remise
1425
     *	@param      string	$price_base_type		HT or TTC
1426
     *	@param		float	$pu_ttc					Unit price TTC
1427
     *	@param		int		$type					Type of line (0=product, 1=service)
1428
     *	@param		int		$info_bits				More information
1429
     *  @param		bool	$notrigger				Disable triggers
1430
     *  @param		int		$date_start				Date start of service
1431
     *  @param		int		$date_end				Date end of service
1432
	 *  @param		array	$array_options			extrafields array
1433
     *  @param 		string	$fk_unit 				Code of the unit to use. Null to use the default one
1434
	 *  @param 		string	$pu_ht_devise			Amount in currency
1435
	 *  @param		string	$origin					'order', ...
1436
	 *  @param		int		$origin_id				Id of origin object
1437
     *	@return     int             				<=0 if KO, >0 if OK
1438
     */
1439
	public function addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1=0.0, $txlocaltax2=0.0, $fk_product=0, $fk_prod_fourn_price=0, $ref_supplier='', $remise_percent=0.0, $price_base_type='HT', $pu_ttc=0.0, $type=0, $info_bits=0, $notrigger=false, $date_start=null, $date_end=null, $array_options=0, $fk_unit=null, $pu_ht_devise=0, $origin='', $origin_id=0)
1440
    {
1441
        global $langs,$mysoc,$conf;
1442
1443
        $error = 0;
1444
1445
        dol_syslog(get_class($this)."::addline $desc, $pu_ht, $qty, $txtva, $txlocaltax1, $txlocaltax2, $fk_product, $fk_prod_fourn_price, $ref_supplier, $remise_percent, $price_base_type, $pu_ttc, $type, $fk_unit");
1446
        include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
1447
1448
        // Clean parameters
1449
        if (! $qty) $qty=1;
1450
        if (! $info_bits) $info_bits=0;
1451
        if (empty($txtva)) $txtva=0;
1452
        if (empty($txlocaltax1)) $txlocaltax1=0;
1453
        if (empty($txlocaltax2)) $txlocaltax2=0;
1454
		if (empty($remise_percent)) $remise_percent=0;
1455
1456
        $remise_percent=price2num($remise_percent);
1457
        $qty=price2num($qty);
1458
        $pu_ht=price2num($pu_ht);
1459
        $pu_ttc=price2num($pu_ttc);
1460
        $txtva = price2num($txtva);
1461
        $txlocaltax1 = price2num($txlocaltax1);
1462
        $txlocaltax2 = price2num($txlocaltax2);
1463
        if ($price_base_type=='HT')
1464
        {
1465
            $pu=$pu_ht;
1466
        }
1467
        else
1468
        {
1469
            $pu=$pu_ttc;
1470
        }
1471
        $desc=trim($desc);
1472
1473
        // Check parameters
1474
        if ($qty < 1 && ! $fk_product)
1475
        {
1476
            $this->error=$langs->trans("ErrorFieldRequired",$langs->trans("Product"));
1477
            return -1;
1478
        }
1479
        if ($type < 0) return -1;
1480
1481
        if ($this->statut == 0)
1482
        {
1483
            $this->db->begin();
1484
1485
            if ($fk_product > 0)
1486
            {
1487
                if (empty($conf->global->SUPPLIER_ORDER_WITH_NOPRICEDEFINED))
1488
                {
1489
                    // Check quantity is enough
1490
                    dol_syslog(get_class($this)."::addline we check supplier prices fk_product=".$fk_product." fk_prod_fourn_price=".$fk_prod_fourn_price." qty=".$qty." ref_supplier=".$ref_supplier);
1491
                    $prod = new Product($this->db, $fk_product);
1492
                    if ($prod->fetch($fk_product) > 0)
1493
                    {
1494
                        $product_type = $prod->type;
1495
                        $label = $prod->label;
1496
1497
                        // We use 'none' instead of $ref_supplier, because fourn_ref may not exists anymore. So we will take the first supplier price ok.
1498
                        // If we want a dedicated supplier price, we must provide $fk_prod_fourn_price.
1499
                        $result=$prod->get_buyprice($fk_prod_fourn_price, $qty, $fk_product, 'none', ($this->fk_soc?$this->fk_soc:$this->socid));   // Search on couple $fk_prod_fourn_price/$qty first, then on triplet $qty/$fk_product/$ref_supplier/$this->fk_soc
1500
                        if ($result > 0)
1501
                        {
1502
			    $pu           = $prod->fourn_pu;       // Unit price supplier price set by get_buyprice
1503
                            $ref_supplier = $prod->ref_supplier;   // Ref supplier price set by get_buyprice
1504
			    // is remise percent not keyed but present for the product we add it
1505
                            if ($remise_percent == 0 && $prod->remise_percent !=0)
1506
                            	$remise_percent =$prod->remise_percent;
1507
1508
1509
                        }
1510
                        if ($result == 0)                   // If result == 0, we failed to found the supplier reference price
1511
                        {
1512
                            $langs->load("errors");
1513
                            $this->error = "Ref " . $prod->ref . " " . $langs->trans("ErrorQtyTooLowForThisSupplier");
1514
                            $this->db->rollback();
1515
                            dol_syslog(get_class($this)."::addline we did not found supplier price, so we can't guess unit price");
1516
                            //$pu    = $prod->fourn_pu;     // We do not overwrite unit price
1517
                            //$ref   = $prod->ref_fourn;    // We do not overwrite ref supplier price
1518
                            return -1;
1519
                        }
1520
                        if ($result == -1)
1521
                        {
1522
                            $langs->load("errors");
1523
                            $this->error = "Ref " . $prod->ref . " " . $langs->trans("ErrorQtyTooLowForThisSupplier");
1524
                            $this->db->rollback();
1525
                            dol_syslog(get_class($this)."::addline result=".$result." - ".$this->error, LOG_DEBUG);
1526
                            return -1;
1527
                        }
1528
                        if ($result < -1)
1529
                        {
1530
                            $this->error=$prod->error;
1531
                            $this->db->rollback();
1532
                            dol_syslog(get_class($this)."::addline result=".$result." - ".$this->error, LOG_ERR);
1533
                            return -1;
1534
                        }
1535
                    }
1536
                    else
1537
    				{
1538
                        $this->error=$prod->error;
1539
                        return -1;
1540
                    }
1541
                }
1542
            }
1543
            else
1544
            {
1545
                $product_type = $type;
1546
            }
1547
1548
            // Calcul du total TTC et de la TVA pour la ligne a partir de
1549
            // qty, pu, remise_percent et txtva
1550
            // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
1551
            // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
1552
1553
            $localtaxes_type=getLocalTaxesFromRate($txtva,0,$mysoc,$this->thirdparty);
1554
1555
            // Clean vat code
1556
            $vat_src_code='';
1557
            if (preg_match('/\((.*)\)/', $txtva, $reg))
1558
            {
1559
                $vat_src_code = $reg[1];
1560
                $txtva = preg_replace('/\s*\(.*\)/', '', $txtva);    // Remove code into vatrate.
1561
            }
1562
1563
            if ($conf->multicurrency->enabled && $pu_ht_devise > 0) {
1564
                $pu = 0;
1565
            }
1566
1567
            $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $product_type, $this->thirdparty, $localtaxes_type, 100, $this->multicurrency_tx,$pu_ht_devise);
0 ignored issues
show
Bug introduced by
The variable $product_type 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...
1568
            $total_ht  = $tabprice[0];
1569
            $total_tva = $tabprice[1];
1570
            $total_ttc = $tabprice[2];
1571
            $total_localtax1 = $tabprice[9];
1572
            $total_localtax2 = $tabprice[10];
1573
            $pu = $pu_ht = $tabprice[3];
1574
1575
			// MultiCurrency
1576
			$multicurrency_total_ht  = $tabprice[16];
1577
            $multicurrency_total_tva = $tabprice[17];
1578
            $multicurrency_total_ttc = $tabprice[18];
1579
			$pu_ht_devise = $tabprice[19];
1580
1581
            $localtax1_type=$localtaxes_type[0];
1582
			$localtax2_type=$localtaxes_type[2];
1583
1584
            $subprice = price2num($pu,'MU');
1585
1586
            $rangmax = $this->line_max();
1587
            $rang = $rangmax + 1;
1588
1589
            // Insert line
1590
            $this->line=new CommandeFournisseurLigne($this->db);
1591
1592
            $this->line->context = $this->context;
1593
1594
            $this->line->fk_commande=$this->id;
1595
            $this->line->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...
1596
            $this->line->ref_fourn = $ref_supplier;
1597
            $this->line->ref_supplier = $ref_supplier;
1598
            $this->line->desc=$desc;
1599
            $this->line->qty=$qty;
1600
            $this->line->tva_tx=$txtva;
1601
            $this->line->localtax1_tx=($total_localtax1?$localtaxes_type[1]:0);
1602
            $this->line->localtax2_tx=($total_localtax2?$localtaxes_type[3]:0);
1603
            $this->line->localtax1_type = $localtaxes_type[0];
1604
            $this->line->localtax2_type = $localtaxes_type[2];
1605
            $this->line->fk_product=$fk_product;
1606
            $this->line->product_type=$product_type;
1607
            $this->line->remise_percent=$remise_percent;
1608
            $this->line->subprice=$pu_ht;
1609
            $this->line->rang=$rang;
1610
            $this->line->info_bits=$info_bits;
1611
1612
            $this->line->vat_src_code=$vat_src_code;
1613
            $this->line->total_ht=$total_ht;
1614
            $this->line->total_tva=$total_tva;
1615
            $this->line->total_localtax1=$total_localtax1;
1616
            $this->line->total_localtax2=$total_localtax2;
1617
            $this->line->total_ttc=$total_ttc;
1618
            $this->line->product_type=$type;
1619
            $this->line->special_code=$this->special_code;
1620
            $this->line->origin=$origin;
1621
            $this->line->origin_id=$origin_id;
1622
            $this->line->fk_unit=$fk_unit;
1623
1624
            $this->line->date_start=$date_start;
1625
            $this->line->date_end=$date_end;
1626
1627
            // Multicurrency
1628
            $this->line->fk_multicurrency			= $this->fk_multicurrency;
1629
            $this->line->multicurrency_code			= $this->multicurrency_code;
1630
            $this->line->multicurrency_subprice		= $pu_ht_devise;
1631
            $this->line->multicurrency_total_ht 	= $multicurrency_total_ht;
1632
            $this->line->multicurrency_total_tva 	= $multicurrency_total_tva;
1633
            $this->line->multicurrency_total_ttc 	= $multicurrency_total_ttc;
1634
1635
            $this->line->subprice=$pu_ht;
1636
            $this->line->price=$this->line->subprice;
1637
1638
            $this->line->remise_percent=$remise_percent;
1639
1640
            if (is_array($array_options) && count($array_options)>0) {
1641
                $this->line->array_options=$array_options;
1642
            }
1643
1644
            $result=$this->line->insert($notrigger);
1645
            if ($result > 0)
1646
            {
1647
                // Reorder if child line
1648
                if (! empty($fk_parent_line)) $this->line_order(true,'DESC');
0 ignored issues
show
Bug introduced by
The variable $fk_parent_line 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...
1649
1650
                // Mise a jour informations denormalisees au niveau de la commande meme
1651
                $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.
1652
                if ($result > 0)
1653
                {
1654
                    $this->db->commit();
1655
                    return $this->line->id;
1656
                }
1657
                else
1658
                {
1659
                    $this->db->rollback();
1660
                    return -1;
1661
                }
1662
            }
1663
            else
1664
            {
1665
                $this->error=$this->line->error;
1666
                $this->errors=$this->line->errors;
1667
                dol_syslog(get_class($this)."::addline error=".$this->error, LOG_ERR);
1668
                $this->db->rollback();
1669
                return -1;
1670
            }
1671
        }
1672
    }
1673
1674
1675
    /**
1676
     * Save a receiving into the tracking table of receiving (commande_fournisseur_dispatch) and add product into stock warehouse.
1677
     *
1678
     * @param 	User		$user					User object making change
1679
     * @param 	int			$product				Id of product to dispatch
1680
     * @param 	double		$qty					Qty to dispatch
1681
     * @param 	int			$entrepot				Id of warehouse to add product
1682
     * @param 	double		$price					Unit Price for PMP value calculation (Unit price without Tax and taking into account discount)
1683
     * @param	string		$comment				Comment for stock movement
1684
	 * @param	date		$eatby					eat-by date
1685
	 * @param	date		$sellby					sell-by date
1686
	 * @param	string		$batch					Lot number
1687
	 * @param	int			$fk_commandefourndet	Id of supplier order line
1688
     * @param	int			$notrigger          	1 = notrigger
1689
     * @return 	int						<0 if KO, >0 if OK
1690
     */
1691
    public function dispatchProduct($user, $product, $qty, $entrepot, $price=0, $comment='', $eatby='', $sellby='', $batch='', $fk_commandefourndet=0, $notrigger=0)
1692
    {
1693
        global $conf, $langs;
1694
1695
        $error = 0;
1696
        require_once DOL_DOCUMENT_ROOT .'/product/stock/class/mouvementstock.class.php';
1697
1698
        // Check parameters (if test are wrong here, there is bug into caller)
1699
        if ($entrepot <= 0)
1700
        {
1701
            $this->error='ErrorBadValueForParameterWarehouse';
1702
            return -1;
1703
        }
1704
        if ($qty <= 0)
1705
        {
1706
            $this->error='ErrorBadValueForParameterQty';
1707
            return -1;
1708
        }
1709
1710
        $dispatchstatus = 1;
1711
        if (! empty($conf->global->SUPPLIER_ORDER_USE_DISPATCH_STATUS)) $dispatchstatus = 0;	// Setting dispatch status (a validation step after receiving products) will be done manually to 1 or 2 if this option is on
1712
1713
        $now=dol_now();
1714
1715
        if (($this->statut == self::STATUS_ORDERSENT || $this->statut == self::STATUS_RECEIVED_PARTIALLY || $this->statut == self::STATUS_RECEIVED_COMPLETELY))
1716
        {
1717
            $this->db->begin();
1718
1719
            $sql = "INSERT INTO ".MAIN_DB_PREFIX."commande_fournisseur_dispatch";
1720
            $sql.= " (fk_commande, fk_product, qty, fk_entrepot, fk_user, datec, fk_commandefourndet, status, comment, eatby, sellby, batch) VALUES";
1721
            $sql.= " ('".$this->id."','".$product."','".$qty."',".($entrepot>0?"'".$entrepot."'":"null").",'".$user->id."','".$this->db->idate($now)."','".$fk_commandefourndet."', ".$dispatchstatus.", '".$this->db->escape($comment)."', ";
1722
            $sql.= ($eatby?"'".$this->db->idate($eatby)."'":"null").", ".($sellby?"'".$this->db->idate($sellby)."'":"null").", ".($batch?"'".$batch."'":"null");
1723
            $sql.= ")";
1724
1725
            dol_syslog(get_class($this)."::dispatchProduct", LOG_DEBUG);
1726
            $resql = $this->db->query($sql);
1727
            if ($resql)
1728
            {
1729
                if (! $notrigger)
1730
                {
1731
                    global $conf, $langs, $user;
1732
					// Call trigger
1733
					$result=$this->call_trigger('LINEORDER_SUPPLIER_DISPATCH',$user);
1734
					if ($result < 0)
1735
                    {
1736
                        $error++;
1737
                        return -1;
1738
                    }
1739
					// End call triggers
1740
                }
1741
            }
1742
            else
1743
			{
1744
                $this->error=$this->db->lasterror();
1745
                $error++;
1746
            }
1747
1748
            // Si module stock gere et que incrementation faite depuis un dispatching en stock
1749
            if (! $error && $entrepot > 0 && ! empty($conf->stock->enabled) && ! empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER))
1750
            {
1751
1752
                $mouv = new MouvementStock($this->db);
1753
                if ($product > 0)
1754
                {
1755
                	// $price should take into account discount (except if option STOCK_EXCLUDE_DISCOUNT_FOR_PMP is on)
1756
                	$mouv->origin = &$this;
1757
					$result=$mouv->reception($user, $product, $entrepot, $qty, $price, $comment, $eatby, $sellby, $batch);
1758
                    if ($result < 0)
1759
                    {
1760
                        $this->error=$mouv->error;
1761
                        $this->errors=$mouv->errors;
1762
                        dol_syslog(get_class($this)."::dispatchProduct ".$this->error." ".join(',',$this->errors), LOG_ERR);
1763
                        $error++;
1764
                    }
1765
                }
1766
            }
1767
1768
            if ($error == 0)
1769
            {
1770
                $this->db->commit();
1771
                return 1;
1772
            }
1773
            else
1774
            {
1775
                $this->db->rollback();
1776
                return -1;
1777
            }
1778
        }
1779
        else
1780
		{
1781
            $this->error='BadStatusForObject';
1782
            return -2;
1783
        }
1784
    }
1785
1786
    /**
1787
     * 	Delete line
1788
     *
1789
     *	@param	int		$idline		Id of line to delete
1790
     *	@param	int		$notrigger	1=Disable call to triggers
1791
     *	@return	int					<0 if KO, >0 if OK
1792
     */
1793
    public function deleteline($idline, $notrigger=0)
1794
    {
1795
        if ($this->statut == 0)
1796
        {
1797
            $line = new CommandeFournisseurLigne($this->db);
1798
1799
            if ($line->fetch($idline) <= 0)
1800
            {
1801
                return 0;
1802
            }
1803
1804
            if ($line->delete($notrigger) > 0)
1805
            {
1806
                $this->update_price();
1807
                return 1;
1808
            }
1809
            else
1810
            {
1811
                $this->error = $line->error;
1812
                $this->errors = $line->errors;
1813
                return -1;
1814
            }
1815
        }
1816
        else
1817
        {
1818
            return -2;
1819
        }
1820
    }
1821
1822
    /**
1823
     *  Delete an order
1824
     *
1825
     *	@param	User	$user		Object user
1826
     *	@param	int		$notrigger	1=Does not execute triggers, 0= execute triggers
1827
     *	@return	int					<0 if KO, >0 if OK
1828
     */
1829
    public function delete(User $user, $notrigger=0)
1830
    {
1831
        global $langs,$conf;
1832
        require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1833
1834
        $error = 0;
1835
1836
        $this->db->begin();
1837
1838
        if (empty($notrigger))
1839
        {
1840
            // Call trigger
1841
            $result=$this->call_trigger('ORDER_SUPPLIER_DELETE',$user);
1842
            if ($result < 0)
1843
            {
1844
            	$this->errors[]='ErrorWhenRunningTrigger';
1845
            	dol_syslog(get_class($this)."::delete ".$this->error, LOG_ERR);
1846
            	return -1;
1847
            }
1848
            // End call triggers
1849
        }
1850
1851
        $sql = "DELETE FROM ".MAIN_DB_PREFIX."commande_fournisseurdet WHERE fk_commande =". $this->id ;
1852
        dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1853
        if (! $this->db->query($sql) )
1854
        {
1855
            $this->error=$this->db->lasterror();
1856
            $this->errors[]=$this->db->lasterror();
1857
            $error++;
1858
        }
1859
1860
        $sql = "DELETE FROM ".MAIN_DB_PREFIX."commande_fournisseur WHERE rowid =".$this->id;
1861
        dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1862
        if ($resql = $this->db->query($sql) )
1863
        {
1864
            if ($this->db->affected_rows($resql) < 1)
1865
            {
1866
                $this->error=$this->db->lasterror();
1867
                $this->errors[]=$this->db->lasterror();
1868
                $error++;
1869
            }
1870
        }
1871
        else
1872
        {
1873
            $this->error=$this->db->lasterror();
1874
            $this->errors[]=$this->db->lasterror();
1875
            $error++;
1876
        }
1877
1878
        // Remove extrafields
1879
        if ((! $error) && (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED))) // For avoid conflicts if trigger used
1880
        {
1881
        	$result=$this->deleteExtraFields();
1882
        	if ($result < 0)
1883
        	{
1884
        		$this->error='FailToDeleteExtraFields';
1885
        		$this->errors[]='FailToDeleteExtraFields';
1886
        		$error++;
1887
        		dol_syslog(get_class($this)."::delete error -4 ".$this->error, LOG_ERR);
1888
        	}
1889
        }
1890
1891
		// Delete linked object
1892
    	$res = $this->deleteObjectLinked();
1893
    	if ($res < 0) {
1894
    		$this->error='FailToDeleteObjectLinked';
1895
    		$this->errors[]='FailToDeleteObjectLinked';
1896
    		$error++;
1897
    	}
1898
1899
        if (! $error)
1900
        {
1901
        	// We remove directory
1902
        	$ref = dol_sanitizeFileName($this->ref);
1903
        	if ($conf->fournisseur->commande->dir_output)
1904
        	{
1905
        		$dir = $conf->fournisseur->commande->dir_output . "/" . $ref ;
1906
        		$file = $dir . "/" . $ref . ".pdf";
1907
        		if (file_exists($file))
1908
        		{
1909
        			if (! dol_delete_file($file,0,0,0,$this)) // For triggers
1910
        			{
1911
        				$this->error='ErrorFailToDeleteFile';
1912
        				$this->errors[]='ErrorFailToDeleteFile';
1913
        				$error++;
1914
        			}
1915
        		}
1916
        		if (file_exists($dir))
1917
        		{
1918
        			$res=@dol_delete_dir_recursive($dir);
1919
        			if (! $res)
1920
        			{
1921
        				$this->error='ErrorFailToDeleteDir';
1922
        				$this->errors[]='ErrorFailToDeleteDir';
1923
        				$error++;
1924
        			}
1925
        		}
1926
        	}
1927
        }
1928
1929
		if (! $error)
1930
		{
1931
			dol_syslog(get_class($this)."::delete $this->id by $user->id", LOG_DEBUG);
1932
			$this->db->commit();
1933
			return 1;
1934
		}
1935
		else
1936
		{
1937
			dol_syslog(get_class($this)."::delete ".$this->error, LOG_ERR);
1938
			$this->db->rollback();
1939
			return -$error;
1940
		}
1941
    }
1942
1943
    /**
1944
     *	Get list of order methods
1945
     *
1946
     *	@return 0 if Ok, <0 if Ko
1947
     */
1948
    function get_methodes_commande()
1949
    {
1950
        $sql = "SELECT rowid, libelle";
1951
        $sql.= " FROM ".MAIN_DB_PREFIX."c_input_method";
1952
        $sql.= " WHERE active = 1";
1953
1954
        $resql=$this->db->query($sql);
1955
        if ($resql)
1956
        {
1957
            $i = 0;
1958
            $num = $this->db->num_rows($resql);
1959
            $this->methodes_commande = array();
1960
            while ($i < $num)
1961
            {
1962
                $row = $this->db->fetch_row($resql);
1963
1964
                $this->methodes_commande[$row[0]] = $row[1];
1965
1966
                $i++;
1967
            }
1968
            return 0;
1969
        }
1970
        else
1971
        {
1972
            return -1;
1973
        }
1974
    }
1975
1976
    /**
1977
	 * Return array of dispathed lines waiting to be approved for this order
1978
     *
1979
     * @since 8.0 Return dispatched quantity (qty).
1980
	 *
1981
	 * @param	int		$status		Filter on stats (-1 = no filter, 0 = lines draft to be approved, 1 = approved lines)
1982
	 * @return	array				Array of lines
1983
     */
1984
    public function getDispachedLines($status=-1)
1985
    {
1986
    	$ret = array();
1987
1988
    	// List of already dispatched lines
1989
		$sql = "SELECT p.ref, p.label,";
1990
		$sql.= " e.rowid as warehouse_id, e.ref as entrepot,";
1991
		$sql.= " cfd.rowid as dispatchedlineid, cfd.fk_product, cfd.qty, cfd.eatby, cfd.sellby, cfd.batch, cfd.comment, cfd.status";
1992
		$sql.= " FROM ".MAIN_DB_PREFIX."product as p,";
1993
		$sql.= " ".MAIN_DB_PREFIX."commande_fournisseur_dispatch as cfd";
1994
		$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."entrepot as e ON cfd.fk_entrepot = e.rowid";
1995
		$sql.= " WHERE cfd.fk_commande = ".$this->id;
1996
		$sql.= " AND cfd.fk_product = p.rowid";
1997
		if ($status >= 0) $sql.=" AND cfd.status = ".$status;
1998
		$sql.= " ORDER BY cfd.rowid ASC";
1999
2000
		$resql = $this->db->query($sql);
2001
		if ($resql)
2002
		{
2003
			$num = $this->db->num_rows($resql);
2004
			$i = 0;
2005
2006
			while ($i < $num)
2007
			{
2008
				$objp = $this->db->fetch_object($resql);
2009
				if ($objp)
2010
				{
2011
					$ret[] = array(
2012
						'id' => $objp->dispatchedlineid,
2013
						'productid' => $objp->fk_product,
2014
						'warehouseid' => $objp->warehouse_id,
2015
						'qty' => $objp->qty,
2016
					);
2017
				}
2018
2019
				$i++;
2020
			}
2021
		}
2022
		else dol_print_error($this->db, 'Failed to execute request to get dispatched lines');
2023
2024
		return $ret;
2025
    }
2026
2027
2028
    /**
2029
     * 	Set a delivery in database for this supplier order
2030
     *
2031
     *	@param	User	$user		User that input data
2032
     *	@param	date	$date		Date of reception
2033
     *	@param	string	$type		Type of receipt ('tot' = total/done, 'par' = partial, 'nev' = never, 'can' = cancel)
2034
     *	@param	string	$comment	Comment
2035
     *	@return	int					<0 if KO, >0 if OK
2036
     */
2037
    function Livraison($user, $date, $type, $comment)
2038
    {
2039
    	global $conf, $langs;
2040
2041
        $result = 0;
2042
		$error = 0;
2043
2044
        dol_syslog(get_class($this)."::Livraison");
2045
2046
        if ($user->rights->fournisseur->commande->receptionner)
2047
        {
2048
        	// Define the new status
2049
            if ($type == 'par') $statut = self::STATUS_RECEIVED_PARTIALLY;
2050
            elseif ($type == 'tot')	$statut = self::STATUS_RECEIVED_COMPLETELY;
2051
            elseif ($type == 'nev') $statut = self::STATUS_CANCELED_AFTER_ORDER;
2052
            elseif ($type == 'can') $statut = self::STATUS_CANCELED_AFTER_ORDER;
2053
			else {
2054
            	$error++;
2055
                dol_syslog(get_class($this)."::Livraison Error -2", LOG_ERR);
2056
                return -2;
2057
			}
2058
2059
            // Some checks to accept the record
2060
            if (! empty($conf->global->SUPPLIER_ORDER_USE_DISPATCH_STATUS))
2061
            {
2062
				// If option SUPPLIER_ORDER_USE_DISPATCH_STATUS is on, we check all reception are approved to allow status "total/done"
2063
	        	if (! $error && ($type == 'tot'))
2064
		    	{
2065
		    		$dispatchedlinearray=$this->getDispachedLines(0);
2066
		    		if (count($dispatchedlinearray) > 0)
2067
		    		{
2068
		    			$result=-1;
2069
		    			$error++;
2070
		    			$this->errors[]='ErrorCantSetReceptionToTotalDoneWithReceptionToApprove';
2071
		    			dol_syslog('ErrorCantSetReceptionToTotalDoneWithReceptionToApprove', LOG_DEBUG);
2072
		    		}
2073
2074
		    	}
2075
	    		if (! $error && ! empty($conf->global->SUPPLIER_ORDER_USE_DISPATCH_STATUS_NEED_APPROVE) && ($type == 'tot'))	// Accept to move to reception done, only if status of all line are ok (refuse denied)
2076
	    		{
2077
	    			$dispatcheddenied=$this->getDispachedLines(2);
2078
	    			if (count($dispatchedlinearray) > 0)
0 ignored issues
show
Bug introduced by
The variable $dispatchedlinearray 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...
2079
	    			{
2080
		    			$result=-1;
2081
		    			$error++;
2082
		    			$this->errors[]='ErrorCantSetReceptionToTotalDoneWithReceptionDenied';
2083
		    			dol_syslog('ErrorCantSetReceptionToTotalDoneWithReceptionDenied', LOG_DEBUG);
2084
	    			}
2085
	    		}
2086
            }
2087
2088
            // TODO LDR01 Add a control test to accept only if ALL predefined products are received (same qty).
2089
2090
2091
            if (! $error)
2092
            {
2093
                $this->db->begin();
2094
2095
                $sql = "UPDATE ".MAIN_DB_PREFIX."commande_fournisseur";
2096
                $sql.= " SET fk_statut = ".$statut;
2097
                $sql.= " WHERE rowid = ".$this->id;
2098
                $sql.= " AND fk_statut IN (".self::STATUS_ORDERSENT.",".self::STATUS_RECEIVED_PARTIALLY.")";	// Process running or Partially received
2099
2100
                dol_syslog(get_class($this)."::Livraison", LOG_DEBUG);
2101
                $resql=$this->db->query($sql);
2102
                if ($resql)
2103
                {
2104
                    $result = 0;
2105
                    $old_statut = $this->statut;
2106
                    $this->statut = $statut;
2107
					$this->actionmsg2 = $comment;
2108
2109
                    // Call trigger
2110
                    $result=$this->call_trigger('ORDER_SUPPLIER_RECEIVE',$user);
2111
                    if ($result < 0) $error++;
2112
                    // End call triggers
2113
2114
                    if (! $error)
2115
                    {
2116
                        $this->db->commit();
2117
                    }
2118
                    else
2119
                    {
2120
                        $this->statut = $old_statut;
2121
                        $this->db->rollback();
2122
                        $this->error=$this->db->lasterror();
2123
                        $result = -1;
2124
                    }
2125
                }
2126
                else
2127
                {
2128
                    $this->db->rollback();
2129
                    $this->error=$this->db->lasterror();
2130
                    $result = -1;
2131
                }
2132
            }
2133
        }
2134
        else
2135
        {
2136
            $this->error = $langs->trans('NotAuthorized');
2137
            $this->errors[] = $langs->trans('NotAuthorized');
2138
            dol_syslog(get_class($this)."::Livraison Not Authorized");
2139
            $result = -3;
2140
        }
2141
        return $result ;
2142
    }
2143
2144
	/**
2145
     *	Set the planned delivery date
2146
     *
2147
     *	@param      User			$user        		Objet user making change
2148
     *	@param      timestamp		$date_livraison     Planned delivery date
2149
     *  @param     	int				$notrigger			1=Does not execute triggers, 0= execute triggers
2150
     *	@return     int         						<0 if KO, >0 if OK
2151
     */
2152
    function set_date_livraison($user, $date_livraison, $notrigger=0)
2153
    {
2154
        if ($user->rights->fournisseur->commande->creer)
2155
        {
2156
        	$error=0;
2157
2158
        	$this->db->begin();
2159
2160
        	$sql = "UPDATE ".MAIN_DB_PREFIX."commande_fournisseur";
2161
            $sql.= " SET date_livraison = ".($date_livraison ? "'".$this->db->idate($date_livraison)."'" : 'null');
2162
            $sql.= " WHERE rowid = ".$this->id;
2163
2164
        	dol_syslog(__METHOD__, LOG_DEBUG);
2165
        	$resql=$this->db->query($sql);
2166
        	if (!$resql)
2167
        	{
2168
        		$this->errors[]=$this->db->error();
2169
        		$error++;
2170
        	}
2171
2172
        	if (! $error)
2173
        	{
2174
        		$this->oldcopy= clone $this;
2175
        		$this->date_livraison = $date_livraison;
2176
        	}
2177
2178
        	if (! $notrigger && empty($error))
2179
        	{
2180
        		// Call trigger
2181
        		$result=$this->call_trigger('ORDER_SUPPLIER_MODIFY',$user);
2182
        		if ($result < 0) $error++;
2183
        		// End call triggers
2184
        	}
2185
2186
        	if (! $error)
2187
        	{
2188
        		$this->db->commit();
2189
        		return 1;
2190
        	}
2191
        	else
2192
        	{
2193
        		foreach($this->errors as $errmsg)
2194
        		{
2195
        			dol_syslog(__METHOD__.' Error: '.$errmsg, LOG_ERR);
2196
        			$this->error.=($this->error?', '.$errmsg:$errmsg);
2197
        		}
2198
        		$this->db->rollback();
2199
        		return -1*$error;
2200
        	}
2201
        }
2202
        else
2203
        {
2204
            return -2;
2205
        }
2206
    }
2207
2208
	/**
2209
     *	Set the id projet
2210
     *
2211
     *	@param      User			$user        		Objet utilisateur qui modifie
2212
     *	@param      int				$id_projet    	 	Date de livraison
2213
     *  @param     	int				$notrigger			1=Does not execute triggers, 0= execute triggers
2214
     *	@return     int         						<0 si ko, >0 si ok
2215
     */
2216
    function set_id_projet($user, $id_projet, $notrigger=0)
2217
    {
2218
        if ($user->rights->fournisseur->commande->creer)
2219
        {
2220
        	$error=0;
2221
2222
        	$this->db->begin();
2223
2224
            $sql = "UPDATE ".MAIN_DB_PREFIX."commande_fournisseur";
2225
            $sql.= " SET fk_projet = ".($id_projet > 0 ? (int) $id_projet : 'null');
2226
            $sql.= " WHERE rowid = ".$this->id;
2227
2228
            dol_syslog(__METHOD__, LOG_DEBUG);
2229
            $resql=$this->db->query($sql);
2230
            if (!$resql)
2231
            {
2232
            	$this->errors[]=$this->db->error();
2233
            	$error++;
2234
            }
2235
2236
            if (! $error)
2237
            {
2238
            	$this->oldcopy= clone $this;
2239
            	$this->fk_projet = $id_projet;
2240
            }
2241
2242
            if (! $notrigger && empty($error))
2243
            {
2244
            	// Call trigger
2245
            	$result=$this->call_trigger('ORDER_SUPPLIER_MODIFY',$user);
2246
            	if ($result < 0) $error++;
2247
            	// End call triggers
2248
            }
2249
2250
            if (! $error)
2251
            {
2252
            	$this->db->commit();
2253
            	return 1;
2254
            }
2255
            else
2256
            {
2257
            	foreach($this->errors as $errmsg)
2258
            	{
2259
            		dol_syslog(__METHOD__.' Error: '.$errmsg, LOG_ERR);
2260
            		$this->error.=($this->error?', '.$errmsg:$errmsg);
2261
            	}
2262
            	$this->db->rollback();
2263
            	return -1*$error;
2264
            }
2265
        }
2266
        else
2267
        {
2268
            return -2;
2269
        }
2270
    }
2271
2272
    /**
2273
     *  Update a supplier order from a customer order
2274
     *
2275
     *  @param  User	$user           User that create
2276
     *  @param  int		$idc			Id of supplier order to update
2277
     *  @param	int		$comclientid	Id of customer order to use as template
2278
     *	@return	int						<0 if KO, >0 if OK
2279
     */
2280
    public function updateFromCommandeClient($user, $idc, $comclientid)
2281
    {
2282
        $comclient = new Commande($this->db);
2283
        $comclient->fetch($comclientid);
2284
2285
        $this->id = $idc;
2286
2287
        $this->lines = array();
2288
2289
        $num=count($comclient->lines);
2290
        for ($i = 0; $i < $num; $i++)
2291
        {
2292
            $prod = new Product($this->db);
2293
            if ($prod->fetch($comclient->lines[$i]->fk_product) > 0)
2294
            {
2295
                $libelle  = $prod->libelle;
2296
                $ref      = $prod->ref;
2297
            }
2298
2299
            $sql = "INSERT INTO ".MAIN_DB_PREFIX."commande_fournisseurdet";
2300
            $sql .= " (fk_commande,label,description,fk_product, price, qty, tva_tx, localtax1_tx, localtax2_tx, remise_percent, subprice, remise, ref)";
2301
            $sql .= " VALUES (".$idc.", '" . $this->db->escape($libelle) . "','" . $this->db->escape($comclient->lines[$i]->desc) . "'";
0 ignored issues
show
Bug introduced by
The variable $libelle 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...
2302
            $sql .= ",".$comclient->lines[$i]->fk_product.",'".price2num($comclient->lines[$i]->price)."'";
2303
            $sql .= ", '".$comclient->lines[$i]->qty."', ".$comclient->lines[$i]->tva_tx.", ".$comclient->lines[$i]->localtax1_tx.", ".$comclient->lines[$i]->localtax2_tx.", ".$comclient->lines[$i]->remise_percent;
2304
            $sql .= ", '".price2num($comclient->lines[$i]->subprice)."','0','".$ref."');";
0 ignored issues
show
Bug introduced by
The variable $ref 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...
2305
            if ($this->db->query($sql))
2306
            {
2307
                $this->update_price();
2308
            }
2309
        }
2310
2311
        return 1;
2312
    }
2313
2314
    /**
2315
     *  Tag order with a particular status
2316
     *
2317
     *  @param      User	$user       Object user that change status
2318
     *  @param      int		$status		New status
2319
     *  @return     int         		<0 if KO, >0 if OK
2320
     */
2321
    public function setStatus($user, $status)
2322
    {
2323
        global $conf,$langs;
2324
        $error=0;
2325
2326
        $this->db->begin();
2327
2328
        $sql = 'UPDATE '.MAIN_DB_PREFIX.'commande_fournisseur';
2329
        $sql.= ' SET fk_statut='.$status;
2330
        $sql.= ' WHERE rowid = '.$this->id;
2331
2332
        dol_syslog(get_class($this)."::setStatus", LOG_DEBUG);
2333
        $resql = $this->db->query($sql);
2334
        if ($resql)
2335
        {
2336
            // Trigger names for each status
2337
            $trigger_name[0] = 'DRAFT';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$trigger_name was never initialized. Although not strictly required by PHP, it is generally a good practice to add $trigger_name = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
2338
            $trigger_name[1] = 'VALIDATED';
2339
            $trigger_name[2] = 'APPROVED';
2340
            $trigger_name[3] = 'ORDERED';				// Ordered
2341
            $trigger_name[4] = 'RECEIVED_PARTIALLY';
2342
            $trigger_name[5] = 'RECEIVED_COMPLETELY';
2343
            $trigger_name[6] = 'CANCELED';
2344
            $trigger_name[7] = 'CANCELED';
2345
            $trigger_name[9] = 'REFUSED';
2346
2347
            // Call trigger
2348
            $result=$this->call_trigger("ORDER_SUPPLIER_STATUS_".$trigger_name[$status],$user);
2349
            if ($result < 0) { $error++; }
2350
            // End call triggers
2351
        }
2352
        else
2353
        {
2354
            $error++;
2355
            $this->error=$this->db->lasterror();
2356
            dol_syslog(get_class($this)."::setStatus ".$this->error);
2357
        }
2358
2359
        if (! $error)
2360
        {
2361
            $this->statut = $status;
2362
            $this->db->commit();
2363
            return 1;
2364
        }
2365
        else
2366
        {
2367
            $this->db->rollback();
2368
            return -1;
2369
        }
2370
    }
2371
2372
    /**
2373
     *	Update line
2374
     *
2375
     *	@param     	int			$rowid           	Id de la ligne de facture
2376
     *	@param     	string		$desc            	Description de la ligne
2377
     *	@param     	double		$pu              	Prix unitaire
2378
     *	@param     	double		$qty             	Quantity
2379
     *	@param     	double		$remise_percent  	Percent discount on line
2380
     *	@param     	double		$txtva          	VAT rate
2381
     *  @param     	double		$txlocaltax1	    Localtax1 tax
2382
     *  @param     	double		$txlocaltax2   		Localtax2 tax
2383
     *  @param     	double		$price_base_type 	Type of price base
2384
     *	@param		int			$info_bits			Miscellaneous informations
2385
     *	@param		int			$type				Type of line (0=product, 1=service)
2386
     *  @param		int			$notrigger			Disable triggers
2387
     *  @param      timestamp   $date_start     	Date start of service
2388
     *  @param      timestamp   $date_end       	Date end of service
2389
	 *  @param		array		$array_options		Extrafields array
2390
     * 	@param 		string		$fk_unit 			Code of the unit to use. Null to use the default one
2391
	 * 	@param		double		$pu_ht_devise		Unit price in currency
2392
	 *  @param		string		$ref_supplier		Supplier ref
2393
     *	@return    	int         	    			< 0 if error, > 0 if ok
2394
     */
2395
    public function updateline($rowid, $desc, $pu, $qty, $remise_percent, $txtva, $txlocaltax1=0, $txlocaltax2=0, $price_base_type='HT', $info_bits=0, $type=0, $notrigger=0, $date_start='', $date_end='', $array_options=0, $fk_unit=null, $pu_ht_devise=0, $ref_supplier='')
2396
    {
2397
    	global $mysoc, $conf;
2398
        dol_syslog(get_class($this)."::updateline $rowid, $desc, $pu, $qty, $remise_percent, $txtva, $price_base_type, $info_bits, $type, $fk_unit");
2399
        include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
2400
2401
        $error = 0;
2402
2403
        if ($this->brouillon)
2404
        {
2405
            $this->db->begin();
2406
2407
            // Clean parameters
2408
            if (empty($qty)) $qty=0;
2409
            if (empty($info_bits)) $info_bits=0;
2410
            if (empty($txtva)) $txtva=0;
2411
            if (empty($txlocaltax1)) $txlocaltax1=0;
2412
            if (empty($txlocaltax2)) $txlocaltax2=0;
2413
            if (empty($remise)) $remise=0;
0 ignored issues
show
Bug introduced by
The variable $remise seems only to be defined at a later point. As such the call to empty() seems to always evaluate to true.

This check marks calls to isset(...) or empty(...) that are found before the variable itself is defined. These will always have the same result.

This is likely the result of code being shifted around. Consider removing these calls.

Loading history...
2414
            if (empty($remise_percent)) $remise_percent=0;
2415
2416
            $remise_percent=price2num($remise_percent);
2417
            $qty=price2num($qty);
2418
            if (! $qty) $qty=1;
2419
            $pu = price2num($pu);
2420
            $txtva=price2num($txtva);
2421
            $txlocaltax1=price2num($txlocaltax1);
2422
            $txlocaltax2=price2num($txlocaltax2);
2423
2424
            // Check parameters
2425
            if ($type < 0) return -1;
2426
2427
            // Calcul du total TTC et de la TVA pour la ligne a partir de
2428
            // qty, pu, remise_percent et txtva
2429
            // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
2430
            // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
2431
2432
            $localtaxes_type=getLocalTaxesFromRate($txtva,0,$mysoc, $this->thirdparty);
2433
2434
            // Clean vat code
2435
            $vat_src_code='';
2436
            if (preg_match('/\((.*)\)/', $txtva, $reg))
2437
            {
2438
                $vat_src_code = $reg[1];
2439
                $txtva = preg_replace('/\s*\(.*\)/', '', $txtva);    // Remove code into vatrate.
2440
            }
2441
2442
            $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);
2443
            $total_ht  = $tabprice[0];
2444
            $total_tva = $tabprice[1];
2445
            $total_ttc = $tabprice[2];
2446
            $total_localtax1 = $tabprice[9];
2447
            $total_localtax2 = $tabprice[10];
2448
			$pu_ht  = $tabprice[3];
2449
			$pu_tva = $tabprice[4];
2450
			$pu_ttc = $tabprice[5];
2451
2452
			// MultiCurrency
2453
			$multicurrency_total_ht  = $tabprice[16];
2454
            $multicurrency_total_tva = $tabprice[17];
2455
            $multicurrency_total_ttc = $tabprice[18];
2456
			$pu_ht_devise = $tabprice[19];
2457
2458
            $localtax1_type=$localtaxes_type[0];
2459
			$localtax2_type=$localtaxes_type[2];
2460
2461
            $subprice = price2num($pu_ht,'MU');
2462
2463
            //Fetch current line from the database and then clone the object and set it in $oldline property
2464
            $this->line=new CommandeFournisseurLigne($this->db);
2465
            $this->line->fetch($rowid);
2466
            $oldline = clone $this->line;
2467
            $this->line->oldline = $oldline;
2468
2469
            $this->line->context = $this->context;
2470
2471
            $this->line->fk_commande=$this->id;
2472
            //$this->line->label=$label;
2473
            $this->line->desc=$desc;
2474
            $this->line->qty=$qty;
0 ignored issues
show
Documentation Bug introduced by
It seems like $qty can also be of type string or integer. However, the property $qty is declared as type double. Maybe add an additional type check?

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

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

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

class Id
{
    public $id;

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

}

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

$account_id = false;

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

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
2475
			$this->line->ref_supplier=$ref_supplier;
2476
2477
	        $this->line->vat_src_code   = $vat_src_code;
2478
            $this->line->tva_tx         = $txtva;
2479
            $this->line->localtax1_tx   = $txlocaltax1;
2480
            $this->line->localtax2_tx   = $txlocaltax2;
2481
            $this->line->localtax1_type = $localtaxes_type[0];
2482
            $this->line->localtax2_type = $localtaxes_type[2];
2483
            $this->line->remise_percent = $remise_percent;
2484
            $this->line->subprice       = $pu_ht;
2485
            $this->line->rang           = $this->rang;
2486
            $this->line->info_bits      = $info_bits;
2487
            $this->line->total_ht       = $total_ht;
2488
            $this->line->total_tva      = $total_tva;
2489
            $this->line->total_localtax1= $total_localtax1;
2490
            $this->line->total_localtax2= $total_localtax2;
2491
            $this->line->total_ttc      = $total_ttc;
2492
            $this->line->product_type   = $type;
2493
            $this->line->special_code   = $this->special_code;
2494
            $this->line->origin         = $this->origin;
2495
            $this->line->fk_unit        = $fk_unit;
2496
2497
            $this->line->date_start     = $date_start;
2498
            $this->line->date_end       = $date_end;
2499
2500
            // Multicurrency
2501
            $this->line->fk_multicurrency			= $this->fk_multicurrency;
2502
            $this->line->multicurrency_code			= $this->multicurrency_code;
2503
            $this->line->multicurrency_subprice		= $pu_ht_devise;
2504
            $this->line->multicurrency_total_ht 	= $multicurrency_total_ht;
2505
            $this->line->multicurrency_total_tva 	= $multicurrency_total_tva;
2506
            $this->line->multicurrency_total_ttc 	= $multicurrency_total_ttc;
2507
2508
            $this->line->subprice=$pu_ht;
2509
            $this->line->price=$this->line->subprice;
2510
2511
            $this->line->remise_percent=$remise_percent;
2512
2513
            if (is_array($array_options) && count($array_options)>0) {
2514
                $this->line->array_options=$array_options;
2515
            }
2516
2517
            $result=$this->line->update($notrigger);
2518
2519
2520
            // Mise a jour info denormalisees au niveau facture
2521
            if ($result >= 0)
2522
            {
2523
                $this->update_price('','auto');
2524
				$this->db->commit();
2525
				return $result;
2526
            }
2527
            else
2528
            {
2529
                $this->error=$this->db->lasterror();
2530
                $this->db->rollback();
2531
                return -1;
2532
            }
2533
        }
2534
        else
2535
        {
2536
            $this->error="Order status makes operation forbidden";
2537
            dol_syslog(get_class($this)."::updateline ".$this->error, LOG_ERR);
2538
            return -2;
2539
        }
2540
    }
2541
2542
2543
    /**
2544
     *  Initialise an instance with random values.
2545
     *  Used to build previews or test instances.
2546
     *	id must be 0 if object instance is a specimen.
2547
     *
2548
     *  @return	void
2549
     */
2550
    public function initAsSpecimen()
2551
    {
2552
        global $user,$langs,$conf;
2553
2554
        dol_syslog(get_class($this)."::initAsSpecimen");
2555
2556
        $now=dol_now();
2557
2558
        // Find first product
2559
        $prodid=0;
2560
        $product=new ProductFournisseur($this->db);
2561
        $sql = "SELECT rowid";
2562
        $sql.= " FROM ".MAIN_DB_PREFIX."product";
2563
        $sql.= " WHERE entity IN (".getEntity('product').")";
2564
        $sql.=$this->db->order("rowid","ASC");
2565
        $sql.=$this->db->plimit(1);
2566
        $resql = $this->db->query($sql);
2567
        if ($resql)
2568
        {
2569
            $obj = $this->db->fetch_object($resql);
2570
            $prodid = $obj->rowid;
2571
        }
2572
2573
        // Initialise parametres
2574
        $this->id=0;
2575
        $this->ref = 'SPECIMEN';
2576
        $this->specimen=1;
2577
        $this->socid = 1;
2578
        $this->date = $now;
2579
        $this->date_commande = $now;
2580
        $this->date_lim_reglement=$this->date+3600*24*30;
2581
        $this->cond_reglement_code = 'RECEP';
2582
        $this->mode_reglement_code = 'CHQ';
2583
        $this->note_public='This is a comment (public)';
2584
        $this->note_private='This is a comment (private)';
2585
        $this->statut=0;
2586
2587
        // Lines
2588
        $nbp = 5;
2589
        $xnbp = 0;
2590
        while ($xnbp < $nbp)
2591
        {
2592
            $line=new CommandeFournisseurLigne($this->db);
2593
            $line->desc=$langs->trans("Description")." ".$xnbp;
2594
            $line->qty=1;
2595
            $line->subprice=100;
2596
            $line->price=100;
2597
            $line->tva_tx=19.6;
2598
            $line->localtax1_tx=0;
2599
            $line->localtax2_tx=0;
2600
            if ($xnbp == 2)
2601
            {
2602
                $line->total_ht=50;
2603
                $line->total_ttc=59.8;
2604
                $line->total_tva=9.8;
2605
                $line->remise_percent=50;
2606
            }
2607
            else
2608
            {
2609
                $line->total_ht=100;
2610
                $line->total_ttc=119.6;
2611
                $line->total_tva=19.6;
2612
                $line->remise_percent=00;
2613
            }
2614
            $line->fk_product=$prodid;
2615
2616
            $this->lines[$xnbp]=$line;
2617
2618
            $this->total_ht       += $line->total_ht;
2619
            $this->total_tva      += $line->total_tva;
2620
            $this->total_ttc      += $line->total_ttc;
2621
2622
            $xnbp++;
2623
        }
2624
    }
2625
2626
    /**
2627
     *	Charge les informations d'ordre info dans l'objet facture
2628
     *
2629
     *	@param  int		$id       	Id de la facture a charger
2630
     *	@return	void
2631
     */
2632
    public function info($id)
2633
    {
2634
        $sql = 'SELECT c.rowid, date_creation as datec, tms as datem, date_valid as date_validation, date_approve as datea, date_approve2 as datea2,';
2635
        $sql.= ' fk_user_author, fk_user_modif, fk_user_valid, fk_user_approve, fk_user_approve2';
2636
        $sql.= ' FROM '.MAIN_DB_PREFIX.'commande_fournisseur as c';
2637
        $sql.= ' WHERE c.rowid = '.$id;
2638
2639
        $result=$this->db->query($sql);
2640
        if ($result)
2641
        {
2642
            if ($this->db->num_rows($result))
2643
            {
2644
                $obj = $this->db->fetch_object($result);
2645
                $this->id = $obj->rowid;
2646
                if ($obj->fk_user_author)   $this->user_creation_id = $obj->fk_user_author;
2647
                if ($obj->fk_user_valid)    $this->user_validation_id = $obj->fk_user_valid;
2648
                if ($obj->fk_user_modif)    $this->user_modification_id =$obj->fk_user_modif;
2649
                if ($obj->fk_user_approve)  $this->user_approve_id = $obj->fk_user_approve;
2650
                if ($obj->fk_user_approve2) $this->user_approve_id2 = $obj->fk_user_approve2;
2651
2652
                $this->date_creation     = $this->db->idate($obj->datec);
2653
                $this->date_modification = $this->db->idate($obj->datem);
2654
                $this->date_approve      = $this->db->idate($obj->datea);
2655
                $this->date_approve2     = $this->db->idate($obj->datea2);
2656
                $this->date_validation   = $this->db->idate($obj->date_validation);
2657
            }
2658
            $this->db->free($result);
2659
        }
2660
        else
2661
        {
2662
            dol_print_error($this->db);
2663
        }
2664
    }
2665
2666
    /**
2667
     *	Charge indicateurs this->nb de tableau de bord
2668
     *
2669
     *	@return     int         <0 si ko, >0 si ok
2670
     */
2671
    function load_state_board()
2672
    {
2673
        global $conf, $user;
2674
2675
        $this->nb=array();
2676
        $clause = "WHERE";
2677
2678
        $sql = "SELECT count(co.rowid) as nb";
2679
        $sql.= " FROM ".MAIN_DB_PREFIX."commande_fournisseur as co";
2680
        $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON co.fk_soc = s.rowid";
2681
        if (!$user->rights->societe->client->voir && !$user->societe_id)
2682
        {
2683
            $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON s.rowid = sc.fk_soc";
2684
            $sql.= " WHERE sc.fk_user = " .$user->id;
2685
            $clause = "AND";
2686
        }
2687
        $sql.= " ".$clause." co.entity = ".$conf->entity;
2688
2689
        $resql=$this->db->query($sql);
2690
        if ($resql)
2691
        {
2692
            while ($obj=$this->db->fetch_object($resql))
2693
            {
2694
                $this->nb["supplier_orders"]=$obj->nb;
2695
            }
2696
            $this->db->free($resql);
2697
            return 1;
2698
        }
2699
        else
2700
        {
2701
            dol_print_error($this->db);
2702
            $this->error=$this->db->error();
2703
            return -1;
2704
        }
2705
    }
2706
2707
    /**
2708
     *	Load indicators for dashboard (this->nbtodo and this->nbtodolate)
2709
     *
2710
     *	@param          User	$user   Objet user
2711
     *	@return WorkboardResponse|int 	<0 if KO, WorkboardResponse if OK
2712
     */
2713
    function load_board($user)
2714
    {
2715
        global $conf, $langs;
2716
2717
        $clause = " WHERE";
2718
2719
        $sql = "SELECT c.rowid, c.date_creation as datec, c.date_commande, c.fk_statut, c.date_livraison as delivery_date";
2720
        $sql.= " FROM ".MAIN_DB_PREFIX."commande_fournisseur as c";
2721
        if (!$user->rights->societe->client->voir && !$user->societe_id)
2722
        {
2723
            $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON c.fk_soc = sc.fk_soc";
2724
            $sql.= " WHERE sc.fk_user = " .$user->id;
2725
            $clause = " AND";
2726
        }
2727
        $sql.= $clause." c.entity = ".$conf->entity;
2728
        $sql.= " AND c.fk_statut IN (".self::STATUS_VALIDATED.", ".self::STATUS_ACCEPTED.")";
2729
        if ($user->societe_id) $sql.=" AND c.fk_soc = ".$user->societe_id;
2730
2731
        $resql=$this->db->query($sql);
2732
        if ($resql)
2733
        {
2734
            $commandestatic = new CommandeFournisseur($this->db);
2735
2736
	        $response = new WorkboardResponse();
2737
	        $response->warning_delay=$conf->commande->fournisseur->warning_delay/60/60/24;
2738
	        $response->label=$langs->trans("SuppliersOrdersToProcess");
2739
	        $response->url=DOL_URL_ROOT.'/fourn/commande/list.php?statut=1,2,3&mainmenu=commercial&leftmenu=orders_suppliers';
2740
	        $response->img=img_object('',"order");
2741
2742
            while ($obj=$this->db->fetch_object($resql))
2743
            {
2744
                $response->nbtodo++;
2745
2746
                $commandestatic->date_livraison = $this->db->jdate($obj->delivery_date);
2747
                $commandestatic->date_commande = $this->db->jdate($obj->date_commande);
2748
                $commandestatic->statut = $obj->fk_statut;
2749
2750
                if ($commandestatic->hasDelay()) {
2751
	                $response->nbtodolate++;
2752
                }
2753
            }
2754
2755
            return $response;
2756
        }
2757
        else
2758
        {
2759
            $this->error=$this->db->error();
2760
            return -1;
2761
        }
2762
    }
2763
2764
    /**
2765
     * Returns the translated input method of object (defined if $this->methode_commande_id > 0).
2766
     * This function make a sql request to get translation. No cache yet, try to not use it inside a loop.
2767
     *
2768
     * @return string
2769
     */
2770
    public function getInputMethod()
2771
    {
2772
        global $db, $langs;
2773
2774
        if ($this->methode_commande_id > 0)
2775
        {
2776
            $sql = "SELECT rowid, code, libelle as label";
2777
            $sql.= " FROM ".MAIN_DB_PREFIX.'c_input_method';
2778
            $sql.= " WHERE active=1 AND rowid = ".$db->escape($this->methode_commande_id);
2779
2780
            $resql = $db->query($sql);
2781
            if ($resql)
2782
            {
2783
                if ($db->num_rows($query))
2784
                {
2785
                    $obj = $db->fetch_object($query);
0 ignored issues
show
Bug introduced by
The variable $query 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...
2786
2787
                    $string = $langs->trans($obj->code);
2788
                    if ($string == $obj->code)
2789
                    {
2790
                        $string = $obj->label != '-' ? $obj->label : '';
2791
                    }
2792
                    return $string;
2793
                }
2794
            }
2795
            else dol_print_error($db);
2796
        }
2797
2798
        return '';
2799
    }
2800
2801
	/**
2802
	 *  Create a document onto disk according to template model.
2803
	 *
2804
	 *  @param	    string		$modele			Force template to use ('' to not force)
2805
	 *  @param		Translate	$outputlangs	Object lang to use for traduction
2806
	 *  @param      int			$hidedetails    Hide details of lines
2807
	 *  @param      int			$hidedesc       Hide description
2808
	 *  @param      int			$hideref        Hide ref
2809
	 *  @return     int          				0 if KO, 1 if OK
2810
	 */
2811
	public function generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
2812
	{
2813
		global $conf, $langs;
2814
2815
		$langs->load("suppliers");
2816
2817
		if (! dol_strlen($modele)) {
2818
2819
			$modele = 'muscadet';
2820
2821
			if ($this->modelpdf) {
2822
				$modele = $this->modelpdf;
2823
			} elseif (! empty($conf->global->COMMANDE_SUPPLIER_ADDON_PDF)) {
2824
				$modele = $conf->global->COMMANDE_SUPPLIER_ADDON_PDF;
2825
			}
2826
		}
2827
2828
		$modelpath = "core/modules/supplier_order/pdf/";
2829
2830
		return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref);
2831
	}
2832
2833
	/**
2834
     * Return the max number delivery delay in day
2835
     *
2836
     * @param	Translate	$langs		Language object
2837
     * @return 							Translated string
2838
     */
2839
    public function getMaxDeliveryTimeDay($langs)
2840
	{
2841
		if (empty($this->lines)) return '';
2842
2843
		$obj = new ProductFournisseur($this->db);
2844
2845
		$nb = 0;
2846
		foreach ($this->lines as $line)
2847
		{
2848
			if ($line->fk_product > 0)
2849
			{
2850
				$idp = $obj->find_min_price_product_fournisseur($line->fk_product, $line->qty);
2851
				if ($idp)
2852
				{
2853
					$obj->fetch($idp);
2854
					if ($obj->delivery_time_days > $nb) $nb = $obj->delivery_time_days;
2855
				}
2856
			}
2857
		}
2858
2859
		if ($nb === 0) return '';
2860
		else return $nb.' '.$langs->trans('Days');
2861
	}
2862
2863
	/**
2864
	 * Returns the rights used for this class
2865
	 * @return stdClass
2866
	 */
2867
	public function getRights()
2868
	{
2869
		global $user;
2870
2871
		return $user->rights->fournisseur->commande;
2872
	}
2873
2874
2875
	/**
2876
	 * Function used to replace a thirdparty id with another one.
2877
	 *
2878
	 * @param DoliDB $db Database handler
2879
	 * @param int $origin_id Old thirdparty id
2880
	 * @param int $dest_id New thirdparty id
2881
	 * @return bool
2882
	 */
2883
	public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
2884
	{
2885
		$tables = array(
2886
			'commande_fournisseur'
2887
		);
2888
2889
		return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
2890
	}
2891
2892
    /**
2893
     * Is the supplier order delayed?
2894
     *
2895
     * @return bool
2896
     */
2897
    public function hasDelay()
2898
    {
2899
        global $conf;
2900
2901
        if (empty($this->date_delivery) && ! empty($this->date_livraison)) $this->date_delivery = $this->date_livraison;    // For backward compatibility
2902
2903
        $now = dol_now();
2904
        $date_to_test = empty($this->date_delivery) ? $this->date_commande : $this->date_delivery;
2905
2906
        return ($this->statut > 0 && $this->statut < 4) && $date_to_test && $date_to_test < ($now - $conf->commande->fournisseur->warning_delay);
2907
    }
2908
2909
    /**
2910
     * Show the customer delayed info
2911
     *
2912
     * @return string       Show delayed information
2913
     */
2914
    public function showDelay()
2915
    {
2916
        global $conf, $langs;
2917
2918
        if (empty($this->date_delivery) && ! empty($this->date_livraison)) $this->date_delivery = $this->date_livraison;    // For backward compatibility
2919
2920
        if (empty($this->date_delivery)) $text=$langs->trans("OrderDate").' '.dol_print_date($this->date_commande, 'day');
2921
        else $text=$text=$langs->trans("DeliveryDate").' '.dol_print_date($this->date_delivery, 'day');
2922
        $text.=' '.($conf->commande->fournisseur->warning_delay>0?'+':'-').' '.round(abs($conf->commande->fournisseur->warning_delay)/3600/24,1).' '.$langs->trans("days").' < '.$langs->trans("Today");
2923
2924
        return $text;
2925
    }
2926
2927
2928
    /**
2929
     * Calc status regarding to dispatched stock
2930
     *
2931
     * @param 		User 	$user                   User action
2932
     * @param       int     $closeopenorder         Close if received
2933
     * @param		string	$comment				Comment
2934
     * @return		int		                        <0 if KO, 0 if not applicable, >0 if OK
2935
     */
2936
    public function calcAndSetStatusDispatch(User $user, $closeopenorder=1, $comment='')
2937
    {
2938
    	global $conf, $langs;
2939
2940
    	if (! empty($conf->fournisseur->enabled))
2941
    	{
2942
    		require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.dispatch.class.php';
2943
2944
    		$qtydelivered=array();
2945
    		$qtywished=array();
2946
2947
    		$supplierorderdispatch = new CommandeFournisseurDispatch($this->db);
2948
    		$filter=array('t.fk_commande'=>$this->id);
2949
    		if (! empty($conf->global->SUPPLIER_ORDER_USE_DISPATCH_STATUS)) {
2950
    			$filter['t.status']=1;	// Restrict to lines with status validated
2951
    		}
2952
2953
    		$ret=$supplierorderdispatch->fetchAll('','',0,0,$filter);
2954
    		if ($ret<0)
2955
    		{
2956
    			$this->error=$supplierorderdispatch->error; $this->errors=$supplierorderdispatch->errors;
2957
    			return $ret;
2958
    		}
2959
    		else
2960
    		{
2961
    			if (is_array($supplierorderdispatch->lines) && count($supplierorderdispatch->lines)>0)
2962
    			{
2963
    				$date_liv = dol_now();
2964
2965
    				// Build array with quantity deliverd by product
2966
    				foreach($supplierorderdispatch->lines as $line) {
2967
    					$qtydelivered[$line->fk_product]+=$line->qty;
2968
    				}
2969
    				foreach($this->lines as $line) {
2970
    					$qtywished[$line->fk_product]+=$line->qty;
2971
    				}
2972
    				//Compare array
2973
    				$diff_array=array_diff_assoc($qtydelivered,$qtywished);		// Warning: $diff_array is done only on common keys.
2974
    				$keysinwishednotindelivered=array_diff(array_keys($qtywished),array_keys($qtydelivered));		// To check we also have same number of keys
2975
    				$keysindeliverednotinwished=array_diff(array_keys($qtydelivered),array_keys($qtywished));		// To check we also have same number of keys
2976
    				/*var_dump(array_keys($qtydelivered));
2977
    				var_dump(array_keys($qtywished));
2978
    				var_dump($diff_array);
2979
    				var_dump($keysinwishednotindelivered);
2980
    				var_dump($keysindeliverednotinwished);
2981
    				exit;*/
2982
2983
    				if (count($diff_array)==0 && count($keysinwishednotindelivered)==0 && count($keysindeliverednotinwished)==0) //No diff => mean everythings is received
2984
    				{
2985
    					if ($closeopenorder)
2986
    					{
2987
        					//$ret=$this->setStatus($user,5);
2988
    						$ret = $this->Livraison($user, $date_liv, 'tot', $comment);   // GETPOST("type") is 'tot', 'par', 'nev', 'can'
2989
        					if ($ret<0) {
2990
        						return -1;
2991
        					}
2992
    					    return 5;
2993
    					}
2994
    					else
2995
    					{
2996
    					    //Diff => received partially
2997
    					    //$ret=$this->setStatus($user,4);
2998
    						$ret = $this->Livraison($user, $date_liv, 'par', $comment);   // GETPOST("type") is 'tot', 'par', 'nev', 'can'
2999
    					    if ($ret<0) {
3000
    					        return -1;
3001
    					    }
3002
    					    return 4;
3003
    					}
3004
    				}elseif(! empty($conf->global->SUPPLIER_ORDER_MORE_THAN_WISHED) )
3005
				{//set livraison to 'tot' if more products received than wished. (and if $closeopenorder is set to 1 of course...)
3006
3007
					$close=0;
3008
3009
					if( count($diff_array) > 0 )
3010
					{//there are some difference between  the two arrays
3011
3012
						//scan the array of results
3013
						foreach($diff_array as $key => $value)
3014
						{//if the quantity delivered is greater or equal to wish quantity
3015
							if($qtydelivered[$key] >= $qtywished[$key] )
3016
							{
3017
								$close++;
3018
							}
3019
3020
						}
3021
					}
3022
3023
3024
					if($close == count($diff_array))
3025
					{//all the products are received equal or more than the wished quantity
3026
						if ($closeopenorder)
3027
    						{
3028
    							$ret = $this->Livraison($user, $date_liv, 'tot', $comment);   // GETPOST("type") is 'tot', 'par', 'nev', 'can'
3029
        						if ($ret<0) {
3030
        							return -1;
3031
        						}
3032
    					    		return 5;
3033
    						}
3034
    						else
3035
    						{
3036
    					   	 	//Diff => received partially
3037
    					  		$ret = $this->Livraison($user, $date_liv, 'par', $comment);   // GETPOST("type") is 'tot', 'par', 'nev', 'can'
3038
							if ($ret<0) {
3039
								return -1;
3040
							}
3041
							return 4;
3042
						}
3043
3044
3045
					}
3046
					else
3047
					{//all the products are not received
3048
						$ret = $this->Livraison($user, $date_liv, 'par', $comment);   // GETPOST("type") is 'tot', 'par', 'nev', 'can'
3049
						if ($ret<0) {
3050
							return -1;
3051
						}
3052
						return 4;
3053
					}
3054
3055
				}
3056
    				else
3057
    				{
3058
    					//Diff => received partially
3059
    					$ret = $this->Livraison($user, $date_liv, 'par', $comment);   // GETPOST("type") is 'tot', 'par', 'nev', 'can'
3060
    					if ($ret<0) {
3061
    						return -1;
3062
    					}
3063
    					return 4;
3064
    				}
3065
    			}
3066
    			return 1;
3067
    		}
3068
    	}
3069
    	return 0;
3070
    }
3071
}
3072
3073
3074
3075
/**
3076
 *  Class to manage line orders
3077
 */
3078
class CommandeFournisseurLigne extends CommonOrderLine
3079
{
3080
    public $element='commande_fournisseurdet';
3081
	public $table_element='commande_fournisseurdet';
3082
3083
    public $oldline;
3084
3085
    /**
3086
     * Id of parent order
3087
     * @var int
3088
     */
3089
    public $fk_commande;
3090
3091
    // From llx_commande_fournisseurdet
3092
    public $fk_parent_line;
3093
    public $fk_facture;
3094
    public $label;
3095
    public $rang = 0;
3096
    public $special_code = 0;
3097
3098
	/**
3099
	 * Unit price without taxes
3100
	 * @var float
3101
	 */
3102
	public $pu_ht;
3103
3104
    public $date_start;
3105
    public $date_end;
3106
3107
    // From llx_product_fournisseur_price
3108
3109
	/**
3110
	 * Supplier reference of price when we added the line. May have been changed after line was added.
3111
	 * @var string
3112
	 */
3113
    public $ref_supplier;
3114
    public $remise;
3115
    public $product_libelle;
3116
3117
3118
    /**
3119
     *	Constructor
3120
     *
3121
     *  @param		DoliDB		$db      Database handler
3122
     */
3123
    public function __construct($db)
3124
    {
3125
        $this->db= $db;
3126
    }
3127
3128
    /**
3129
     *  Load line order
3130
     *
3131
     *  @param  int		$rowid      Id line order
3132
     *	@return	int					<0 if KO, >0 if OK
3133
     */
3134
    public function fetch($rowid)
3135
    {
3136
        $sql = 'SELECT cd.rowid, cd.fk_commande, cd.fk_product, cd.product_type, cd.description, cd.qty, cd.tva_tx, cd.special_code,';
3137
        $sql.= ' cd.localtax1_tx, cd.localtax2_tx, cd.localtax1_type, cd.localtax2_type, cd.ref,';
3138
        $sql.= ' cd.remise, cd.remise_percent, cd.subprice,';
3139
        $sql.= ' cd.info_bits, cd.total_ht, cd.total_tva, cd.total_ttc,';
3140
        $sql.= ' cd.total_localtax1, cd.total_localtax2,';
3141
        $sql.= ' p.ref as product_ref, p.label as product_libelle, p.description as product_desc,';
3142
        $sql.= ' cd.date_start, cd.date_end, cd.fk_unit,';
3143
		$sql.= ' cd.multicurrency_subprice, cd.multicurrency_total_ht, cd.multicurrency_total_tva, cd.multicurrency_total_ttc';
3144
        $sql.= ' FROM '.MAIN_DB_PREFIX.'commande_fournisseurdet as cd';
3145
        $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON cd.fk_product = p.rowid';
3146
        $sql.= ' WHERE cd.rowid = '.$rowid;
3147
        $result = $this->db->query($sql);
3148
        if ($result)
3149
        {
3150
            $objp = $this->db->fetch_object($result);
3151
3152
            $this->rowid            = $objp->rowid;
3153
            $this->id               = $objp->rowid;
3154
            $this->fk_commande      = $objp->fk_commande;
3155
            $this->desc             = $objp->description;
3156
            $this->qty              = $objp->qty;
3157
            $this->ref_fourn        = $objp->ref;
3158
            $this->ref_supplier     = $objp->ref;
3159
            $this->subprice         = $objp->subprice;
3160
            $this->tva_tx           = $objp->tva_tx;
3161
            $this->localtax1_tx		= $objp->localtax1_tx;
3162
            $this->localtax2_tx		= $objp->localtax2_tx;
3163
            $this->localtax1_type	= $objp->localtax1_type;
3164
            $this->localtax2_type	= $objp->localtax2_type;
3165
            $this->remise           = $objp->remise;
3166
            $this->remise_percent   = $objp->remise_percent;
3167
            $this->fk_product       = $objp->fk_product;
3168
            $this->info_bits        = $objp->info_bits;
3169
            $this->total_ht         = $objp->total_ht;
3170
            $this->total_tva        = $objp->total_tva;
3171
            $this->total_localtax1	= $objp->total_localtax1;
3172
            $this->total_localtax2	= $objp->total_localtax2;
3173
            $this->total_ttc        = $objp->total_ttc;
3174
            $this->product_type     = $objp->product_type;
3175
            $this->special_code     = $objp->special_code;
3176
3177
            $this->ref	            = $objp->product_ref;
3178
            $this->product_ref      = $objp->product_ref;
3179
            $this->product_libelle  = $objp->product_libelle;
3180
            $this->product_desc     = $objp->product_desc;
3181
3182
            $this->date_start       		= $this->db->jdate($objp->date_start);
3183
            $this->date_end         		= $this->db->jdate($objp->date_end);
3184
	        $this->fk_unit          		= $objp->fk_unit;
3185
3186
			$this->multicurrency_subprice	= $objp->multicurrency_subprice;
3187
			$this->multicurrency_total_ht	= $objp->multicurrency_total_ht;
3188
			$this->multicurrency_total_tva	= $objp->multicurrency_total_tva;
3189
			$this->multicurrency_total_ttc	= $objp->multicurrency_total_ttc;
3190
3191
			$this->fetch_optionals();
3192
3193
            $this->db->free($result);
3194
            return 1;
3195
        }
3196
        else
3197
        {
3198
            dol_print_error($this->db);
3199
            return -1;
3200
        }
3201
    }
3202
3203
    /**
3204
     *	Insert line into database
3205
     *
3206
     *	@param      int		$notrigger		1 = disable triggers
3207
     *	@return		int						<0 if KO, >0 if OK
3208
     */
3209
    public function insert($notrigger=0)
3210
    {
3211
        global $conf, $user;
3212
3213
        $error=0;
3214
3215
        dol_syslog(get_class($this)."::insert rang=".$this->rang);
3216
3217
        // Clean parameters
3218
        if (empty($this->tva_tx)) $this->tva_tx=0;
3219
        if (empty($this->localtax1_tx)) $this->localtax1_tx=0;
3220
        if (empty($this->localtax2_tx)) $this->localtax2_tx=0;
3221
        if (empty($this->localtax1_type)) $this->localtax1_type='0';
3222
        if (empty($this->localtax2_type)) $this->localtax2_type='0';
3223
        if (empty($this->total_localtax1)) $this->total_localtax1=0;
3224
        if (empty($this->total_localtax2)) $this->total_localtax2=0;
3225
        if (empty($this->rang)) $this->rang=0;
3226
        if (empty($this->remise)) $this->remise=0;
3227
        if (empty($this->remise_percent)) $this->remise_percent=0;
3228
        if (empty($this->info_bits)) $this->info_bits=0;
3229
        if (empty($this->special_code)) $this->special_code=0;
3230
        if (empty($this->fk_parent_line)) $this->fk_parent_line=0;
3231
        if (empty($this->pa_ht)) $this->pa_ht=0;
3232
3233
        // Multicurrency
3234
        if (!empty($this->multicurrency_code)) list($this->fk_multicurrency,$this->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code);
3235
        if (empty($this->fk_multicurrency))
3236
        {
3237
            $this->multicurrency_code = $conf->currency;
3238
            $this->fk_multicurrency = 0;
3239
            $this->multicurrency_tx = 1;
3240
        }
3241
3242
        // Check parameters
3243
        if ($this->product_type < 0) return -1;
3244
3245
        $this->db->begin();
3246
3247
        // Insertion dans base de la ligne
3248
        $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element;
3249
        $sql.= " (fk_commande, label, description, date_start, date_end,";
3250
        $sql.= " fk_product, product_type, special_code, rang,";
3251
        $sql.= " qty, vat_src_code, tva_tx, localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, remise_percent, subprice, ref,";
3252
        $sql.= " total_ht, total_tva, total_localtax1, total_localtax2, total_ttc, fk_unit,";
3253
        $sql.= " fk_multicurrency, multicurrency_code, multicurrency_subprice, multicurrency_total_ht, multicurrency_total_tva, multicurrency_total_ttc";
3254
        $sql.= ")";
3255
        $sql.= " VALUES (".$this->fk_commande.", '" . $this->db->escape($this->label) . "','" . $this->db->escape($this->desc) . "',";
3256
        $sql.= " ".($this->date_start?"'".$this->db->idate($this->date_start)."'":"null").",";
3257
        $sql.= " ".($this->date_end?"'".$this->db->idate($this->date_end)."'":"null").",";
3258
        if ($this->fk_product) { $sql.= $this->fk_product.","; }
3259
        else { $sql.= "null,"; }
3260
        $sql.= "'".$this->db->escape($this->product_type)."',";
3261
        $sql.= "'".$this->db->escape($this->special_code)."',";
3262
        $sql.= "'".$this->db->escape($this->rang)."',";
3263
        $sql.= "'".$this->db->escape($this->qty)."', ";
3264
        $sql.= " ".(empty($this->vat_src_code)?"''":"'".$this->db->escape($this->vat_src_code)."'").",";
3265
        $sql.= " ".$this->tva_tx.", ";
3266
        $sql.= " ".$this->localtax1_tx.",";
3267
        $sql.= " ".$this->localtax2_tx.",";
3268
        $sql.= " '".$this->db->escape($this->localtax1_type)."',";
3269
        $sql.= " '".$this->db->escape($this->localtax2_type)."',";
3270
        $sql.= " ".$this->remise_percent.", ".price2num($this->subprice,'MU').", '".$this->db->escape($this->ref_supplier)."',";
3271
        $sql.= " ".price2num($this->total_ht).",";
3272
        $sql.= " ".price2num($this->total_tva).",";
3273
        $sql.= " ".price2num($this->total_localtax1).",";
3274
        $sql.= " ".price2num($this->total_localtax2).",";
3275
        $sql.= " ".price2num($this->total_ttc).",";
3276
        $sql.= ($this->fk_unit ? "'".$this->db->escape($this->fk_unit)."'":"null");
3277
        $sql.= ", ".($this->fk_multicurrency ? $this->fk_multicurrency : "null");
3278
        $sql.= ", '".$this->db->escape($this->multicurrency_code)."'";
3279
        $sql.= ", ".price2num($this->multicurrency_subprice);
3280
        $sql.= ", ".price2num($this->multicurrency_total_ht);
3281
        $sql.= ", ".price2num($this->multicurrency_total_tva);
3282
        $sql.= ", ".price2num($this->multicurrency_total_ttc);
3283
        $sql.= ")";
3284
3285
        dol_syslog(get_class($this)."::insert", LOG_DEBUG);
3286
        $resql=$this->db->query($sql);
3287
        if ($resql)
3288
        {
3289
            $this->id=$this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
3290
            $this->rowid =$this->id;
3291
3292
            if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
3293
            {
3294
                $result=$this->insertExtraFields();
3295
                if ($result < 0)
3296
                {
3297
                    $error++;
3298
                }
3299
            }
3300
3301
            if (! $error && ! $notrigger)
3302
            {
3303
                // Call trigger
3304
                $result=$this->call_trigger('LINEORDER_SUPPLIER_CREATE',$user);
3305
                if ($result < 0) $error++;
3306
                // End call triggers
3307
            }
3308
3309
            if (!$error) {
3310
                $this->db->commit();
3311
                return 1;
3312
            }
3313
3314
            foreach($this->errors as $errmsg)
3315
            {
3316
                dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
3317
                $this->errors[]=($this->errors?', '.$errmsg:$errmsg);
3318
            }
3319
            $this->db->rollback();
3320
            return -1*$error;
3321
        }
3322
        else
3323
        {
3324
            $this->errors[]=$this->db->error();
3325
            $this->db->rollback();
3326
            return -2;
3327
        }
3328
    }
3329
    /**
3330
     *	Update the line object into db
3331
     *
3332
     *	@param      int		$notrigger		1 = disable triggers
3333
     *	@return		int		<0 si ko, >0 si ok
3334
     */
3335
    public function update($notrigger=0)
3336
    {
3337
        global $conf,$user;
3338
3339
        $error=0;
3340
3341
        // Mise a jour ligne en base
3342
        $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET";
3343
        $sql.= "  description='".$this->db->escape($this->desc)."'";
3344
        $sql.= ", ref='".$this->db->escape($this->ref_supplier)."'";
3345
        $sql.= ", subprice='".price2num($this->subprice)."'";
3346
        //$sql.= ",remise='".price2num($remise)."'";
3347
        $sql.= ", remise_percent='".price2num($this->remise_percent)."'";
3348
3349
		$sql.= ", vat_src_code = '".(empty($this->vat_src_code)?'':$this->vat_src_code)."'";
3350
        $sql.= ", tva_tx='".price2num($this->tva_tx)."'";
3351
        $sql.= ", localtax1_tx='".price2num($this->total_localtax1)."'";
3352
        $sql.= ", localtax2_tx='".price2num($this->total_localtax2)."'";
3353
        $sql.= ", localtax1_type='".$this->db->escape($this->localtax1_type)."'";
3354
        $sql.= ", localtax2_type='".$this->db->escape($this->localtax2_type)."'";
3355
        $sql.= ", qty='".price2num($this->qty)."'";
3356
        $sql.= ", date_start=".(! empty($this->date_start)?"'".$this->db->idate($this->date_start)."'":"null");
3357
        $sql.= ", date_end=".(! empty($this->date_end)?"'".$this->db->idate($this->date_end)."'":"null");
3358
        $sql.= ", info_bits='".$this->db->escape($this->info_bits)."'";
3359
        $sql.= ", total_ht='".price2num($this->total_ht)."'";
3360
        $sql.= ", total_tva='".price2num($this->total_tva)."'";
3361
        $sql.= ", total_localtax1='".price2num($this->total_localtax1)."'";
3362
        $sql.= ", total_localtax2='".price2num($this->total_localtax2)."'";
3363
        $sql.= ", total_ttc='".price2num($this->total_ttc)."'";
3364
        $sql.= ", product_type=".$this->product_type;
3365
        $sql.= ", special_code=".(!empty($this->special_code) ? $this->special_code : 0);
3366
        $sql.= ($this->fk_unit ? ", fk_unit='".$this->db->escape($this->fk_unit)."'":", fk_unit=null");
3367
3368
        // Multicurrency
3369
        $sql.= ", multicurrency_subprice=".price2num($this->multicurrency_subprice)."";
3370
        $sql.= ", multicurrency_total_ht=".price2num($this->multicurrency_total_ht)."";
3371
        $sql.= ", multicurrency_total_tva=".price2num($this->multicurrency_total_tva)."";
3372
        $sql.= ", multicurrency_total_ttc=".price2num($this->multicurrency_total_ttc)."";
3373
3374
        $sql.= " WHERE rowid = ".$this->id;
3375
3376
        dol_syslog(get_class($this)."::updateline", LOG_DEBUG);
3377
        $result = $this->db->query($sql);
3378
        if ($result > 0)
3379
        {
3380
            if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
3381
            {
3382
                $result=$this->insertExtraFields();
3383
                if ($result < 0)
3384
                {
3385
                    $error++;
3386
                }
3387
            }
3388
3389
            if (! $error && ! $notrigger)
3390
            {
3391
                global $user;
3392
                // Call trigger
3393
                $result=$this->call_trigger('LINEORDER_SUPPLIER_UPDATE',$user);
3394
                if ($result < 0)
3395
                {
3396
                    $this->db->rollback();
3397
                    return -1;
3398
                }
3399
                // End call triggers
3400
            }
3401
3402
            if (! $error)
3403
            {
3404
                $this->db->commit();
3405
                return $result;
3406
            }
3407
            else
3408
            {
3409
                $this->db->rollback();
3410
                return -1;
3411
            }
3412
        }
3413
        else
3414
        {
3415
            $this->error=$this->db->lasterror();
3416
            $this->db->rollback();
3417
            return -1;
3418
        }
3419
    }
3420
3421
    /**
3422
     * 	Delete line in database
3423
     *
3424
     *	@param      int     $notrigger  1=Disable call to triggers
3425
     *	@return     int                 <0 if KO, >0 if OK
3426
     */
3427
    function delete($notrigger)
3428
    {
3429
        global $user;
3430
3431
        $error=0;
3432
3433
        $this->db->begin();
3434
3435
        $sql = 'DELETE FROM '.MAIN_DB_PREFIX."commande_fournisseurdet WHERE rowid=".$this->rowid;
3436
3437
        dol_syslog(__METHOD__, LOG_DEBUG);
3438
        $resql=$this->db->query($sql);
3439
        if ($resql)
3440
        {
3441
3442
            if (!$notrigger)
3443
            {
3444
                // Call trigger
3445
                $result=$this->call_trigger('LINEORDER_SUPPLIER_DELETE',$user);
3446
                if ($result < 0) $error++;
3447
                // End call triggers
3448
            }
3449
3450
            if (!$error)
3451
            {
3452
                $this->db->commit();
3453
                return 1;
3454
            }
3455
3456
            foreach($this->errors as $errmsg)
3457
            {
3458
                dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
3459
                $this->error.=($this->error?', '.$errmsg:$errmsg);
3460
            }
3461
            $this->db->rollback();
3462
            return -1*$error;
3463
        }
3464
        else
3465
        {
3466
            $this->error=$this->db->lasterror();
3467
            return -1;
3468
        }
3469
    }
3470
}
3471
3472