Completed
Branch develop (15a4cd)
by
unknown
46:28
created

FactureLigneRec::update()   D

Complexity

Conditions 12
Paths 320

Size

Total Lines 74
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 51
nc 320
nop 2
dl 0
loc 74
rs 4.0382
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/* Copyright (C) 2003-2005	Rodolphe Quiedeville	<[email protected]>
3
 * Copyright (C) 2004-2015	Laurent Destailleur		<[email protected]>
4
 * Copyright (C) 2009-2012	Regis Houssin			<[email protected]>
5
 * Copyright (C) 2010-2011	Juanjo Menent			<[email protected]>
6
 * Copyright (C) 2012       Cedric Salvador      <[email protected]>
7
 * Copyright (C) 2013       Florian Henry		  	<[email protected]>
8
 * Copyright (C) 2015       Marcos García           <[email protected]>
9
 * Copyright (C) 2017       Frédéric France         <[email protected]>
10
 *
11
 * This program is free software; you can redistribute it and/or modify
12
 * it under the terms of the GNU General Public License as published by
13
 * the Free Software Foundation; either version 3 of the License, or
14
 * (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23
 */
24
25
/**
26
 *	\file       htdocs/compta/facture/class/facture-rec.class.php
27
 *	\ingroup    facture
28
 *	\brief      Fichier de la classe des factures recurentes
29
 */
30
31
require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
32
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
33
require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
34
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
35
36
37
/**
38
 *	Class to manage invoice templates
39
 */
40
class FactureRec extends CommonInvoice
41
{
42
	public $element='facturerec';
43
	public $table_element='facture_rec';
44
	public $table_element_line='facturedet_rec';
45
	public $fk_element='fk_facture';
46
	public $picto='bill';
47
48
	var $entity;
49
	var $number;
50
	var $date;
51
	var $amount;
52
	var $remise;
53
	var $tva;
54
	var $total;
55
	var $db_table;
56
	var $propalid;
57
58
	var $date_last_gen;
59
	var $date_when;
60
	var $nb_gen_done;
61
	var $nb_gen_max;
62
63
	var $frequency;
64
	var $unit_frequency;
65
66
	var $rang;
67
	var $special_code;
68
69
	var $usenewprice=0;
70
71
	var $suspended;			// status
72
73
	const STATUS_NOTSUSPENDED = 0;
74
	const STATUS_SUSPENDED = 1;
75
76
77
78
	/**
79
	 *	Constructor
80
	 *
81
	 * 	@param		DoliDB		$db		Database handler
82
	 */
83
	function __construct($db)
84
	{
85
		$this->db = $db;
86
	}
87
88
	/**
89
	 * 	Create a predefined invoice
90
	 *
91
	 * 	@param		User	$user		User object
92
	 * 	@param		int		$facid		Id of source invoice
93
	 *	@return		int					<0 if KO, id of invoice created if OK
94
	 */
95
	function create($user, $facid)
96
	{
97
		global $conf;
98
99
		$error=0;
100
		$now=dol_now();
101
102
		// Clean parameters
103
		$this->titre=trim($this->titre);
104
		$this->usenewprice=empty($this->usenewprice)?0:$this->usenewprice;
105
		if (empty($this->suspended)) $this->suspended=0;
106
107
		// No frequency defined then no next date to execution
108
		if (empty($this->frequency))
109
		{
110
			$this->frequency=0;
111
			$this->date_when=null;
112
		}
113
114
115
		$this->frequency=abs($this->frequency);
116
		$this->nb_gen_done=0;
117
		$this->nb_gen_max=empty($this->nb_gen_max)?0:$this->nb_gen_max;
118
		$this->auto_validate=empty($this->auto_validate)?0:$this->auto_validate;
119
		$this->generate_pdf = empty($this->generate_pdf)?0:$this->generate_pdf;
120
121
		$this->db->begin();
122
123
		// Charge facture modele
124
		$facsrc=new Facture($this->db);
125
		$result=$facsrc->fetch($facid);
126
		if ($result > 0)
127
		{
128
			// On positionne en mode brouillon la facture
129
			$this->brouillon = 1;
130
131
			$sql = "INSERT INTO ".MAIN_DB_PREFIX."facture_rec (";
132
			$sql.= "titre";
133
			$sql.= ", fk_soc";
134
			$sql.= ", entity";
135
			$sql.= ", datec";
136
			$sql.= ", amount";
137
			$sql.= ", remise";
138
			$sql.= ", note_private";
139
			$sql.= ", note_public";
140
			$sql.= ", modelpdf";
141
			$sql.= ", fk_user_author";
142
			$sql.= ", fk_projet";
143
			$sql.= ", fk_account";
144
			$sql.= ", fk_cond_reglement";
145
			$sql.= ", fk_mode_reglement";
146
			$sql.= ", usenewprice";
147
			$sql.= ", frequency";
148
			$sql.= ", unit_frequency";
149
			$sql.= ", date_when";
150
			$sql.= ", date_last_gen";
151
			$sql.= ", nb_gen_done";
152
			$sql.= ", nb_gen_max";
153
			$sql.= ", auto_validate";
154
			$sql.= ", generate_pdf";
155
			$sql.= ", fk_multicurrency";
156
			$sql.= ", multicurrency_code";
157
			$sql.= ", multicurrency_tx";
158
			$sql.= ", suspended";
159
			$sql.= ") VALUES (";
160
			$sql.= "'".$this->db->escape($this->titre)."'";
161
			$sql.= ", ".$facsrc->socid;
162
			$sql.= ", ".$conf->entity;
163
			$sql.= ", '".$this->db->idate($now)."'";
164
			$sql.= ", ".(!empty($facsrc->amount)?$facsrc->amount:'0');
165
			$sql.= ", ".(!empty($facsrc->remise)?$this->remise:'0');
166
			$sql.= ", ".(!empty($this->note_private)?("'".$this->db->escape($this->note_private)."'"):"NULL");
167
			$sql.= ", ".(!empty($this->note_public)?("'".$this->db->escape($this->note_public)."'"):"NULL");
168
			$sql.= ", ".(!empty($this->modelpdf)?("'".$this->db->escape($this->modelpdf)."'"):"NULL");
169
			$sql.= ", '".$this->db->escape($user->id)."'";
170
			$sql.= ", ".(! empty($facsrc->fk_project)?"'".$facsrc->fk_project."'":"null");
171
			$sql.= ", ".(! empty($facsrc->fk_account)?"'".$facsrc->fk_account."'":"null");
172
			$sql.= ", ".($facsrc->cond_reglement_id > 0 ? $this->db->escape($facsrc->cond_reglement_id) : "null");
173
			$sql.= ", ".($facsrc->mode_reglement_id > 0 ? $this->db->escape($facsrc->mode_reglement_id) : "null");
174
			$sql.= ", ".$this->usenewprice;
175
			$sql.= ", ".$this->frequency;
176
			$sql.= ", '".$this->db->escape($this->unit_frequency)."'";
177
			$sql.= ", ".(!empty($this->date_when)?"'".$this->db->idate($this->date_when)."'":'NULL');
178
			$sql.= ", ".(!empty($this->date_last_gen)?"'".$this->db->idate($this->date_last_gen)."'":'NULL');
179
			$sql.= ", ".$this->db->escape($this->nb_gen_done);
180
			$sql.= ", ".$this->db->escape($this->nb_gen_max);
181
			$sql.= ", ".$this->db->escape($this->auto_validate);
182
			$sql.= ", ".$this->db->escape($this->generate_pdf);
183
			$sql.= ", ".$this->db->escape($facsrc->fk_multicurrency);
184
			$sql.= ", '".$this->db->escape($facsrc->multicurrency_code)."'";
185
			$sql.= ", ".$this->db->escape($facsrc->multicurrency_tx);
186
			$sql.= ", ".$this->db->escape($this->suspended);
187
			$sql.= ")";
188
189
			if ($this->db->query($sql))
190
			{
191
				$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."facture_rec");
192
193
				// Fields used into addline later
194
				$this->fk_multicurrency = $facsrc->fk_multicurrency;
195
				$this->multicurrency_code = $facsrc->multicurrency_code;
196
				$this->multicurrency_tx = $facsrc->multicurrency_tx;
197
198
				// Add lines
199
				$num=count($facsrc->lines);
200
				for ($i = 0; $i < $num; $i++)
201
				{
202
					$tva_tx = $facsrc->lines[$i]->tva_tx;
203
					if (! empty($facsrc->lines[$i]->vat_src_code) && ! preg_match('/\(/', $tva_tx)) $tva_tx .= ' ('.$facsrc->lines[$i]->vat_src_code.')';
204
205
					$result_insert = $this->addline(
206
                        $facsrc->lines[$i]->desc,
207
                        $facsrc->lines[$i]->subprice,
208
                        $facsrc->lines[$i]->qty,
209
						$tva_tx,
210
                        $facsrc->lines[$i]->localtax1_tx,
211
                        $facsrc->lines[$i]->localtax2_tx,
212
                        $facsrc->lines[$i]->fk_product,
213
                        $facsrc->lines[$i]->remise_percent,
214
                        'HT',
215
						$facsrc->lines[$i]->info_bits,
216
                        '',
217
                        0,
218
                        $facsrc->lines[$i]->product_type,
219
                        $facsrc->lines[$i]->rang,
220
                        $facsrc->lines[$i]->special_code,
221
                    	$facsrc->lines[$i]->label,
222
						$facsrc->lines[$i]->fk_unit,
223
						$facsrc->lines[$i]->multicurrency_subprice
224
                    );
225
226
					if ($result_insert < 0)
227
					{
228
						$error++;
229
					}
230
				}
231
232
				if (! empty($this->linkedObjectsIds) && empty($this->linked_objects))	// To use new linkedObjectsIds instead of old linked_objects
233
				{
234
					$this->linked_objects = $this->linkedObjectsIds;	// TODO Replace linked_objects with linkedObjectsIds
235
				}
236
237
				// Add object linked
238
				if (! $error && $this->id && is_array($this->linked_objects) && ! empty($this->linked_objects))
239
				{
240
					foreach($this->linked_objects as $origin => $tmp_origin_id)
241
					{
242
					    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, ...))
243
					    {
244
					        foreach($tmp_origin_id as $origin_id)
245
					        {
246
					            $ret = $this->add_object_linked($origin, $origin_id);
247
					            if (! $ret)
248
					            {
249
					                $this->error=$this->db->lasterror();
250
					                $error++;
251
					            }
252
					        }
253
					    }
254
					    else                                // Old behaviour, if linked_object has only one link per type, so is something like array('contract'=>id1))
255
					    {
256
					        $origin_id = $tmp_origin_id;
257
	    					$ret = $this->add_object_linked($origin, $origin_id);
258
	    					if (! $ret)
259
	    					{
260
	    						$this->error=$this->db->lasterror();
261
	    						$error++;
262
	    					}
263
					    }
264
					}
265
				}
266
267
				if ($error)
268
				{
269
					$this->db->rollback();
270
				}
271
				else
272
				{
273
					$this->db->commit();
274
					return $this->id;
275
				}
276
			}
277
			else
278
			{
279
			    $this->error=$this->db->lasterror();
280
				$this->db->rollback();
281
				return -2;
282
			}
283
		}
284
		else
285
		{
286
			$this->db->rollback();
287
			return -1;
288
		}
289
	}
290
291
292
	/**
293
	 *	Load object and lines
294
	 *
295
	 *	@param      int		$rowid       	Id of object to load
296
	 * 	@param		string	$ref			Reference of recurring invoice
297
	 * 	@param		string	$ref_ext		External reference of invoice
298
	 * 	@param		int		$ref_int		Internal reference of other object
299
	 *	@return     int         			>0 if OK, <0 if KO, 0 if not found
300
	 */
301
	function fetch($rowid, $ref='', $ref_ext='', $ref_int='')
302
	{
303
		$sql = 'SELECT f.rowid, f.entity, f.titre, f.suspended, f.fk_soc, f.amount, f.tva, f.localtax1, f.localtax2, f.total, f.total_ttc';
304
		$sql.= ', f.remise_percent, f.remise_absolue, f.remise';
305
		$sql.= ', f.date_lim_reglement as dlr';
306
		$sql.= ', f.note_private, f.note_public, f.fk_user_author';
307
        $sql.= ', f.modelpdf';
308
		$sql.= ', f.fk_mode_reglement, f.fk_cond_reglement, f.fk_projet';
309
		$sql.= ', f.fk_account';
310
		$sql.= ', f.frequency, f.unit_frequency, f.date_when, f.date_last_gen, f.nb_gen_done, f.nb_gen_max, f.usenewprice, f.auto_validate';
311
        $sql.= ', f.generate_pdf';
312
        $sql.= ", f.fk_multicurrency, f.multicurrency_code, f.multicurrency_tx, f.multicurrency_total_ht, f.multicurrency_total_tva, f.multicurrency_total_ttc";
313
        $sql.= ', p.code as mode_reglement_code, p.libelle as mode_reglement_libelle';
314
		$sql.= ', c.code as cond_reglement_code, c.libelle as cond_reglement_libelle, c.libelle_facture as cond_reglement_libelle_doc';
315
		//$sql.= ', el.fk_source';
316
		$sql.= ' FROM '.MAIN_DB_PREFIX.'facture_rec as f';
317
		$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_payment_term as c ON f.fk_cond_reglement = c.rowid';
318
		$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as p ON f.fk_mode_reglement = p.id';
319
		//$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."element_element as el ON el.fk_target = f.rowid AND el.targettype = 'facture'";
320
		$sql.= ' WHERE f.entity IN ('.getEntity('facture').')';
321
		if ($rowid) $sql.= ' AND f.rowid='.$rowid;
322
		elseif ($ref) $sql.= " AND f.titre='".$this->db->escape($ref)."'";
323
		/* This field are not used for template invoice
324
		if ($ref_ext) $sql.= " AND f.ref_ext='".$this->db->escape($ref_ext)."'";
325
		if ($ref_int) $sql.= " AND f.ref_int='".$this->db->escape($ref_int)."'";
326
		*/
327
328
		$result = $this->db->query($sql);
329
		if ($result)
330
		{
331
			if ($this->db->num_rows($result))
332
			{
333
				$obj = $this->db->fetch_object($result);
334
335
				$this->id                     = $obj->rowid;
336
				$this->entity                 = $obj->entity;
337
				$this->titre                  = $obj->titre;
338
				$this->ref                    = $obj->titre;
339
				$this->ref_client             = $obj->ref_client;
340
				$this->suspended              = $obj->suspended;
341
				$this->type                   = $obj->type;
342
				$this->datep                  = $obj->dp;
343
				$this->date                   = $obj->df;
344
				$this->amount                 = $obj->amount;
345
				$this->remise_percent         = $obj->remise_percent;
346
				$this->remise_absolue         = $obj->remise_absolue;
347
				$this->remise                 = $obj->remise;
348
				$this->total_ht               = $obj->total;
349
				$this->total_tva              = $obj->tva;
350
				$this->total_localtax1        = $obj->localtax1;
351
				$this->total_localtax2        = $obj->localtax2;
352
				$this->total_ttc              = $obj->total_ttc;
353
				$this->paye                   = $obj->paye;
354
				$this->close_code             = $obj->close_code;
355
				$this->close_note             = $obj->close_note;
356
				$this->socid                  = $obj->fk_soc;
357
				$this->date_lim_reglement     = $this->db->jdate($obj->dlr);
358
				$this->mode_reglement_id      = $obj->fk_mode_reglement;
359
				$this->mode_reglement_code    = $obj->mode_reglement_code;
360
				$this->mode_reglement         = $obj->mode_reglement_libelle;
361
				$this->cond_reglement_id      = $obj->fk_cond_reglement;
362
				$this->cond_reglement_code    = $obj->cond_reglement_code;
363
				$this->cond_reglement         = $obj->cond_reglement_libelle;
364
				$this->cond_reglement_doc     = $obj->cond_reglement_libelle_doc;
365
				$this->fk_project             = $obj->fk_projet;
366
				$this->fk_account             = $obj->fk_account;
367
				$this->fk_facture_source      = $obj->fk_facture_source;
368
				$this->note_private           = $obj->note_private;
369
				$this->note_public            = $obj->note_public;
370
				$this->user_author            = $obj->fk_user_author;
371
				$this->modelpdf               = $obj->modelpdf;
372
				$this->rang					  = $obj->rang;
373
				$this->special_code			  = $obj->special_code;
374
				$this->frequency			  = $obj->frequency;
375
				$this->unit_frequency		  = $obj->unit_frequency;
376
				$this->date_when			  = $this->db->jdate($obj->date_when);
377
				$this->date_last_gen		  = $this->db->jdate($obj->date_last_gen);
378
				$this->nb_gen_done			  = $obj->nb_gen_done;
379
				$this->nb_gen_max			  = $obj->nb_gen_max;
380
				$this->usenewprice			  = $obj->usenewprice;
381
				$this->auto_validate		  = $obj->auto_validate;
382
				$this->generate_pdf           = $obj->generate_pdf;
383
384
				// Multicurrency
385
				$this->fk_multicurrency 		= $obj->fk_multicurrency;
386
				$this->multicurrency_code 		= $obj->multicurrency_code;
387
				$this->multicurrency_tx 		= $obj->multicurrency_tx;
388
				$this->multicurrency_total_ht 	= $obj->multicurrency_total_ht;
389
				$this->multicurrency_total_tva 	= $obj->multicurrency_total_tva;
390
				$this->multicurrency_total_ttc 	= $obj->multicurrency_total_ttc;
391
392
				if ($this->statut == self::STATUS_DRAFT)	$this->brouillon = 1;
393
394
				// Retreive all extrafield
395
				// fetch optionals attributes and labels
396
				$this->fetch_optionals();
397
398
				/*
399
				 * Lines
400
				 */
401
				$result=$this->fetch_lines();
402
				if ($result < 0)
403
				{
404
					$this->error=$this->db->lasterror();
405
					return -3;
406
				}
407
				return 1;
408
			}
409
			else
410
			{
411
				$this->error='Bill with id '.$rowid.' or ref '.$ref.' not found sql='.$sql;
412
				dol_syslog('Facture::Fetch Error '.$this->error, LOG_ERR);
413
				return -2;
414
			}
415
		}
416
		else
417
		{
418
			$this->error=$this->db->error();
419
			return -1;
420
		}
421
	}
422
423
424
	/**
425
	 * 	Create an array of invoice lines
426
	 *
427
	 * 	@return int		>0 if OK, <0 if KO
428
	 */
429
	function getLinesArray()
430
	{
431
	    return $this->fetch_lines();
432
	}
433
434
435
	/**
436
	 *	Recupere les lignes de factures predefinies dans this->lines
437
	 *
438
	 *	@return     int         1 if OK, < 0 if KO
439
 	 */
440
	function fetch_lines()
441
	{
442
		$this->lines=array();
443
444
		// Retreive all extrafield for line
445
		// fetch optionals attributes and labels
446
		require_once(DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php');
447
		$extrafieldsline=new ExtraFields($this->db);
448
		$extrafieldsline=$extrafieldsline->fetch_name_optionals_label('facturedet_rec',true);
449
450
		$sql = 'SELECT l.rowid, l.fk_product, l.product_type, l.label as custom_label, l.description, l.product_type, l.price, l.qty, l.vat_src_code, l.tva_tx, ';
451
		$sql.= ' l.localtax1_tx, l.localtax2_tx, l.localtax1_type, l.localtax2_type, l.remise, l.remise_percent, l.subprice,';
452
		$sql.= ' l.info_bits, l.date_start_fill, l.date_end_fill, l.total_ht, l.total_tva, l.total_ttc,';
453
		//$sql.= ' l.situation_percent, l.fk_prev_id,';
454
		//$sql.= ' l.localtax1_tx, l.localtax2_tx, l.localtax1_type, l.localtax2_type, l.remise_percent, l.fk_remise_except, l.subprice,';
455
		$sql.= ' l.rang, l.special_code,';
456
		//$sql.= ' l.info_bits, l.total_ht, l.total_tva, l.total_localtax1, l.total_localtax2, l.total_ttc, l.fk_code_ventilation, l.fk_product_fournisseur_price as fk_fournprice, l.buy_price_ht as pa_ht,';
457
		$sql.= ' l.fk_unit, l.fk_contract_line,';
458
		$sql.= ' l.fk_multicurrency, l.multicurrency_code, l.multicurrency_subprice, l.multicurrency_total_ht, l.multicurrency_total_tva, l.multicurrency_total_ttc,';
459
		$sql.= ' p.ref as product_ref, p.fk_product_type as fk_product_type, p.label as product_label, p.description as product_desc';
460
		$sql.= ' FROM '.MAIN_DB_PREFIX.'facturedet_rec as l';
461
		$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON l.fk_product = p.rowid';
462
		$sql.= ' WHERE l.fk_facture = '.$this->id;
463
		$sql.= ' ORDER BY l.rang';
464
465
		dol_syslog('FactureRec::fetch_lines', LOG_DEBUG);
466
		$result = $this->db->query($sql);
467
		if ($result)
468
		{
469
			$num = $this->db->num_rows($result);
470
			$i = 0;
471
			while ($i < $num)
472
			{
473
				$objp = $this->db->fetch_object($result);
474
				$line = new FactureLigneRec($this->db);
475
476
				$line->id	            = $objp->rowid;
477
				$line->rowid	        = $objp->rowid;
478
				$line->desc             = $objp->description;		// Description line
479
				$line->description      = $objp->description;		// Description line
480
				$line->product_type     = $objp->product_type;		// Type of line
481
				$line->ref              = $objp->product_ref;		// Ref product
482
				$line->product_ref      = $objp->product_ref;		// Ref product
483
				$line->libelle          = $objp->product_label;		// deprecated
484
				$line->product_label	= $objp->product_label;		// Label product
485
				$line->product_desc     = $objp->product_desc;		// Description product
486
				$line->fk_product_type  = $objp->fk_product_type;	// Type of product
487
				$line->qty              = $objp->qty;
488
				$line->subprice         = $objp->subprice;
489
490
				$line->label            = $objp->custom_label;		// @deprecated
491
492
				$line->vat_src_code     = $objp->vat_src_code;
493
				$line->tva_tx           = $objp->tva_tx;
494
				$line->localtax1_tx     = $objp->localtax1_tx;
495
				$line->localtax2_tx     = $objp->localtax2_tx;
496
				$line->localtax1_type   = $objp->localtax1_type;
497
				$line->localtax2_type   = $objp->localtax2_type;
498
				$line->remise_percent   = $objp->remise_percent;
499
				$line->fk_remise_except = $objp->fk_remise_except;
500
				$line->fk_product       = $objp->fk_product;
501
				$line->date_start_fill  = $objp->date_start_fill;
502
				$line->date_end_fill    = $objp->date_end_fill;
503
				$line->info_bits        = $objp->info_bits;
504
				$line->total_ht         = $objp->total_ht;
505
				$line->total_tva        = $objp->total_tva;
506
				$line->total_ttc        = $objp->total_ttc;
507
				$line->code_ventilation = $objp->fk_code_ventilation;
508
				$line->rang 			= $objp->rang;
509
				$line->special_code 	= $objp->special_code;
510
				$line->fk_unit          = $objp->fk_unit;
511
                $line->fk_contract_line = $objp->fk_contract_line;
512
513
				// Ne plus utiliser
514
				$line->price            = $objp->price;
515
				$line->remise           = $objp->remise;
516
517
				$extralabelsline = $line->fetch_optionals($line->id);
518
519
				// Multicurrency
520
				$line->fk_multicurrency 		= $objp->fk_multicurrency;
521
				$line->multicurrency_code 		= $objp->multicurrency_code;
522
				$line->multicurrency_subprice 	= $objp->multicurrency_subprice;
523
				$line->multicurrency_total_ht 	= $objp->multicurrency_total_ht;
524
				$line->multicurrency_total_tva 	= $objp->multicurrency_total_tva;
525
				$line->multicurrency_total_ttc 	= $objp->multicurrency_total_ttc;
526
527
				$this->lines[$i] = $line;
528
529
				$i++;
530
			}
531
532
			$this->db->free($result);
533
			return 1;
534
		}
535
		else
536
		{
537
			$this->error=$this->db->lasterror();
538
			return -3;
539
		}
540
	}
541
542
543
	/**
544
	 * 	Delete template invoice
545
	 *
546
	 *	@param     	User	$user          	User that delete.
547
	 *	@param		int		$notrigger		1=Does not execute triggers, 0= execute triggers
548
	 *	@param		int		$idwarehouse	Id warehouse to use for stock change.
549
	 *	@return		int						<0 if KO, >0 if OK
550
	 */
551
	function delete(User $user, $notrigger=0, $idwarehouse=-1)
552
	{
553
	    $rowid=$this->id;
554
555
	    dol_syslog(get_class($this)."::delete rowid=".$rowid, LOG_DEBUG);
556
557
        $error=0;
558
		$this->db->begin();
559
560
		$sql = "DELETE FROM ".MAIN_DB_PREFIX."facturedet_rec WHERE fk_facture = ".$rowid;
561
		dol_syslog($sql);
562
		if ($this->db->query($sql))
563
		{
564
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."facture_rec WHERE rowid = ".$rowid;
565
			dol_syslog($sql);
566
			if ($this->db->query($sql))
567
			{
568
				// Delete linked object
569
				$res = $this->deleteObjectLinked();
570
				if ($res < 0) $error=-3;
571
			}
572
			else
573
			{
574
				$this->error=$this->db->lasterror();
575
				$error=-1;
576
			}
577
		}
578
		else
579
		{
580
			$this->error=$this->db->lasterror();
581
			$error=-2;
582
		}
583
584
		if (! $error)
585
		{
586
		    $this->db->commit();
587
		    return 1;
588
		}
589
		else
590
		{
591
	        $this->db->rollback();
592
	        return $error;
593
		}
594
	}
595
596
597
	/**
598
	 * 	Add a line to invoice
599
	 *
600
     *	@param    	string		$desc            	Description de la ligne
601
     *	@param    	double		$pu_ht              Prix unitaire HT (> 0 even for credit note)
602
     *	@param    	double		$qty             	Quantite
603
     *	@param    	double		$txtva           	Taux de tva force, sinon -1
604
	 * 	@param		double		$txlocaltax1		Local tax 1 rate (deprecated)
605
	 *  @param		double		$txlocaltax2		Local tax 2 rate (deprecated)
606
     *	@param    	int			$fk_product      	Id du produit/service predefini
607
     *	@param    	double		$remise_percent  	Pourcentage de remise de la ligne
608
     *	@param		string		$price_base_type	HT or TTC
609
     *	@param    	int			$info_bits			VAT npr or not ?
610
     *	@param    	int			$fk_remise_except	Id remise
611
     *	@param    	double		$pu_ttc             Prix unitaire TTC (> 0 even for credit note)
612
     *	@param		int			$type				Type of line (0=product, 1=service)
613
     *	@param      int			$rang               Position of line
614
     *	@param		int			$special_code		Special code
615
     *	@param		string		$label				Label of the line
616
     *	@param		string		$fk_unit			Unit
617
	 * 	@param		double		$pu_ht_devise		Unit price in currency
618
	 *  @param		int			$date_start_fill	1=Flag to fill start date when generating invoice
619
	 *  @param		int			$date_end_fill		1=Flag to fill end date when generating invoice
620
     *	@return    	int             				<0 if KO, Id of line if OK
621
	 */
622
	function addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1=0, $txlocaltax2=0, $fk_product=0, $remise_percent=0, $price_base_type='HT', $info_bits=0, $fk_remise_except='', $pu_ttc=0, $type=0, $rang=-1, $special_code=0, $label='', $fk_unit=null, $pu_ht_devise=0, $date_start_fill=0, $date_end_fill=0)
623
	{
624
	    global $mysoc;
625
626
		$facid=$this->id;
627
628
		dol_syslog(get_class($this)."::addline facid=$facid,desc=$desc,pu_ht=$pu_ht,qty=$qty,txtva=$txtva,txlocaltax1=$txlocaltax1,txlocaltax2=$txlocaltax2,fk_product=$fk_product,remise_percent=$remise_percent,info_bits=$info_bits,fk_remise_except=$fk_remise_except,price_base_type=$price_base_type,pu_ttc=$pu_ttc,type=$type,fk_unit=$fk_unit,pu_ht_devise=$pu_ht_devise,date_start_fill=$date_start_fill,date_end_fill=$date_end_fill", LOG_DEBUG);
629
		include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
630
631
		// Check parameters
632
		if ($type < 0) return -1;
633
634
		$localtaxes_type=getLocalTaxesFromRate($txtva, 0, $this->thirdparty, $mysoc);
635
636
		// Clean vat code
637
		$vat_src_code='';
638
		if (preg_match('/\((.*)\)/', $txtva, $reg))
639
		{
640
			$vat_src_code = $reg[1];
641
			$txtva = preg_replace('/\s*\(.*\)/', '', $txtva);    // Remove code into vatrate.
642
		}
643
644
		if ($this->brouillon)
645
		{
646
			// Clean parameters
647
			$remise_percent=price2num($remise_percent);
648
			if (empty($remise_percent)) $remise_percent=0;
649
			$qty=price2num($qty);
650
			$pu_ht = price2num($pu_ht);
651
			$pu_ttc = price2num($pu_ttc);
652
			$txtva = price2num($txtva);
653
			$txlocaltax1 = price2num($txlocaltax1);
654
			$txlocaltax2 = price2num($txlocaltax2);
655
			if (empty($txtva)) $txtva=0;
656
			if (empty($txlocaltax1)) $txlocaltax1=0;
657
			if (empty($txlocaltax2)) $txlocaltax2=0;
658
			if (empty($info_bits)) $info_bits=0;
659
660
			if ($price_base_type=='HT')
661
			{
662
				$pu=$pu_ht;
663
			}
664
			else
665
			{
666
				$pu=$pu_ttc;
667
			}
668
669
			// Calcul du total TTC et de la TVA pour la ligne a partir de
670
			// qty, pu, remise_percent et txtva
671
			// TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
672
			// la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
673
674
			$tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx, $pu_ht_devise);
675
			$total_ht  = $tabprice[0];
676
			$total_tva = $tabprice[1];
677
			$total_ttc = $tabprice[2];
678
			$total_localtax1=$tabprice[9];
679
			$total_localtax2=$tabprice[10];
680
			$pu_ht = $tabprice[3];
681
682
			// MultiCurrency
683
			$multicurrency_total_ht  = $tabprice[16];
684
			$multicurrency_total_tva = $tabprice[17];
685
			$multicurrency_total_ttc = $tabprice[18];
686
			$pu_ht_devise = $tabprice[19];
687
688
			$product_type=$type;
689
			if ($fk_product)
690
			{
691
				$product=new Product($this->db);
692
				$result=$product->fetch($fk_product);
693
				$product_type=$product->type;
694
			}
695
696
			$sql = "INSERT INTO ".MAIN_DB_PREFIX."facturedet_rec (";
697
			$sql.= "fk_facture";
698
			$sql.= ", label";
699
			$sql.= ", description";
700
			$sql.= ", price";
701
			$sql.= ", qty";
702
			$sql.= ", tva_tx";
703
			$sql.= ", vat_src_code";
704
			$sql.= ", localtax1_tx";
705
			$sql.= ", localtax1_type";
706
			$sql.= ", localtax2_tx";
707
			$sql.= ", localtax2_type";
708
			$sql.= ", fk_product";
709
			$sql.= ", product_type";
710
			$sql.= ", remise_percent";
711
			$sql.= ", subprice";
712
			$sql.= ", remise";
713
			$sql.= ", total_ht";
714
			$sql.= ", total_tva";
715
			$sql.= ", total_localtax1";
716
			$sql.= ", total_localtax2";
717
			$sql.= ", total_ttc";
718
			$sql.= ", date_start_fill";
719
			$sql.= ", date_end_fill";
720
			$sql.= ", info_bits";
721
			$sql.= ", rang";
722
			$sql.= ", special_code";
723
			$sql.= ", fk_unit";
724
			$sql.= ', fk_multicurrency, multicurrency_code, multicurrency_subprice, multicurrency_total_ht, multicurrency_total_tva, multicurrency_total_ttc';
725
			$sql.= ") VALUES (";
726
			$sql.= "'".$facid."'";
727
			$sql.= ", ".(! empty($label)?"'".$this->db->escape($label)."'":"null");
728
			$sql.= ", '".$this->db->escape($desc)."'";
729
			$sql.= ", ".price2num($pu_ht);
730
			$sql.= ", ".price2num($qty);
731
			$sql.= ", ".price2num($txtva);
732
			$sql.= ", '".$this->db->escape($vat_src_code)."'";
733
			$sql.= ", ".price2num($txlocaltax1);
734
			$sql.= ", '".$this->db->escape($localtaxes_type[0])."'";
735
			$sql.= ", ".price2num($txlocaltax2);
736
			$sql.= ", '".$this->db->escape($localtaxes_type[2])."'";
737
			$sql.= ", ".(! empty($fk_product)?"'".$fk_product."'":"null");
738
			$sql.= ", ".$product_type;
739
			$sql.= ", ".price2num($remise_percent);
740
			$sql.= ", ".price2num($pu_ht);
741
			$sql.= ", null";
742
			$sql.= ", ".price2num($total_ht);
743
			$sql.= ", ".price2num($total_tva);
744
			$sql.= ", ".price2num($total_localtax1);
745
			$sql.= ", ".price2num($total_localtax2);
746
			$sql.= ", ".price2num($total_ttc);
747
			$sql.= ", ".(int) $date_start_fill;
748
			$sql.= ", ".(int) $date_end_fill;
749
			$sql.= ", ".$info_bits;
750
			$sql.= ", ".$rang;
751
			$sql.= ", ".$special_code;
752
			$sql.= ", ".($fk_unit?"'".$this->db->escape($fk_unit)."'":"null");
753
			$sql.= ", ".(int) $this->fk_multicurrency;
754
			$sql.= ", '".$this->db->escape($this->multicurrency_code)."'";
755
			$sql.= ", ".price2num($pu_ht_devise);
756
			$sql.= ", ".price2num($multicurrency_total_ht);
757
			$sql.= ", ".price2num($multicurrency_total_tva);
758
			$sql.= ", ".price2num($multicurrency_total_ttc);
759
			$sql.= ")";
760
761
			dol_syslog(get_class($this)."::addline", LOG_DEBUG);
762
			if ($this->db->query($sql))
763
			{
764
				$lineId = $this->db->last_insert_id(MAIN_DB_PREFIX."facturedet_rec");
765
				$this->id=$facid;
766
				$this->update_price();
767
				return $lineId;
768
			}
769
			else
770
			{
771
				$this->error=$this->db->lasterror();
772
				return -1;
773
			}
774
		}
775
	}
776
777
	/**
778
	 * 	Update a line to invoice
779
	 *
780
	 *  @param     	int			$rowid           	Id of line to update
781
	 *	@param    	string		$desc            	Description de la ligne
782
	 *	@param    	double		$pu_ht              Prix unitaire HT (> 0 even for credit note)
783
	 *	@param    	double		$qty             	Quantite
784
	 *	@param    	double		$txtva           	Taux de tva force, sinon -1
785
	 * 	@param		double		$txlocaltax1		Local tax 1 rate (deprecated)
786
	 *  @param		double		$txlocaltax2		Local tax 2 rate (deprecated)
787
	 *	@param    	int			$fk_product      	Id du produit/service predefini
788
	 *	@param    	double		$remise_percent  	Pourcentage de remise de la ligne
789
	 *	@param		string		$price_base_type	HT or TTC
790
	 *	@param    	int			$info_bits			Bits de type de lignes
791
	 *	@param    	int			$fk_remise_except	Id remise
792
	 *	@param    	double		$pu_ttc             Prix unitaire TTC (> 0 even for credit note)
793
	 *	@param		int			$type				Type of line (0=product, 1=service)
794
	 *	@param      int			$rang               Position of line
795
	 *	@param		int			$special_code		Special code
796
	 *	@param		string		$label				Label of the line
797
	 *	@param		string		$fk_unit			Unit
798
	 * 	@param		double		$pu_ht_devise		Unit price in currency
799
	 * 	@param		int			$notrigger			disable line update trigger
800
	 *  @param		int			$date_start_fill	1=Flag to fill start date when generating invoice
801
	 *  @param		int			$date_end_fill		1=Flag to fill end date when generating invoice
802
	 *	@return    	int             				<0 if KO, Id of line if OK
803
	 */
804
	function updateline($rowid, $desc, $pu_ht, $qty, $txtva, $txlocaltax1=0, $txlocaltax2=0, $fk_product=0, $remise_percent=0, $price_base_type='HT', $info_bits=0, $fk_remise_except='', $pu_ttc=0, $type=0, $rang=-1, $special_code=0, $label='', $fk_unit=null, $pu_ht_devise = 0, $notrigger=0, $date_start_fill=0, $date_end_fill=0)
805
	{
806
	    global $mysoc;
807
808
	    $facid=$this->id;
809
810
	    dol_syslog(get_class($this)."::updateline facid=".$facid." rowid=$rowid, desc=$desc, pu_ht=$pu_ht, qty=$qty, txtva=$txtva, txlocaltax1=$txlocaltax1, txlocaltax2=$txlocaltax2, fk_product=$fk_product, remise_percent=$remise_percent, info_bits=$info_bits, fk_remise_except=$fk_remise_except, price_base_type=$price_base_type, pu_ttc=$pu_ttc, type=$type, fk_unit=$fk_unit, pu_ht_devise=$pu_ht_devise", LOG_DEBUG);
811
	    include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
812
813
	    // Clean parameters
814
	    if (empty($remise_percent)) $remise_percent = 0;
815
816
	    // Check parameters
817
	    if ($type < 0) return -1;
818
819
		$localtaxes_type=getLocalTaxesFromRate($txtva, 0, $this->thirdparty, $mysoc);
820
821
		// Clean vat code
822
		$vat_src_code='';
823
		if (preg_match('/\((.*)\)/', $txtva, $reg))
824
		{
825
			$vat_src_code = $reg[1];
826
			$txtva = preg_replace('/\s*\(.*\)/', '', $txtva);    // Remove code into vatrate.
827
		}
828
829
	    if ($this->brouillon)
830
	    {
831
	        // Clean parameters
832
	        $remise_percent=price2num($remise_percent);
833
	        $qty=price2num($qty);
834
	        if (empty($info_bits)) $info_bits=0;
835
	        $pu_ht=price2num($pu_ht);
836
	        $pu_ttc=price2num($pu_ttc);
837
	        $txtva=price2num($txtva);
838
		    $txlocaltax1	= price2num($txlocaltax1);
839
		    $txlocaltax2	= price2num($txlocaltax2);
840
		    if (empty($txlocaltax1)) $txlocaltax1=0;
841
		    if (empty($txlocaltax2)) $txlocaltax2=0;
842
843
		    if (empty($this->multicurrency_subprice)) $this->multicurrency_subprice=0;
844
		    if (empty($this->multicurrency_total_ht)) $this->multicurrency_total_ht=0;
845
		    if (empty($this->multicurrency_total_tva)) $this->multicurrency_total_tva=0;
846
		    if (empty($this->multicurrency_total_ttc)) $this->multicurrency_total_ttc=0;
847
848
	        if ($price_base_type=='HT')
849
	        {
850
	            $pu=$pu_ht;
851
	        }
852
	        else
853
	        {
854
	            $pu=$pu_ttc;
855
	        }
856
857
	        // Calcul du total TTC et de la TVA pour la ligne a partir de
858
	        // qty, pu, remise_percent et txtva
859
	        // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
860
	        // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
861
	        $tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx, $pu_ht_devise);
862
863
	        $total_ht  = $tabprice[0];
864
	        $total_tva = $tabprice[1];
865
	        $total_ttc = $tabprice[2];
866
		    $total_localtax1=$tabprice[9];
867
		    $total_localtax2=$tabprice[10];
868
		    $pu_ht  = $tabprice[3];
869
		    $pu_tva = $tabprice[4];
870
		    $pu_ttc = $tabprice[5];
871
872
		    // MultiCurrency
873
		    $multicurrency_total_ht  = $tabprice[16];
874
		    $multicurrency_total_tva = $tabprice[17];
875
		    $multicurrency_total_ttc = $tabprice[18];
876
		    $pu_ht_devise = $tabprice[19];
877
878
	        $product_type=$type;
879
	        if ($fk_product)
880
	        {
881
	            $product=new Product($this->db);
882
	            $result=$product->fetch($fk_product);
883
	            $product_type=$product->type;
884
	        }
885
886
	        $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet_rec SET ";
887
	        $sql.= "fk_facture = '".$facid."'";
888
	        $sql.= ", label=".(! empty($label)?"'".$this->db->escape($label)."'":"null");
889
	        $sql.= ", description='".$this->db->escape($desc)."'";
890
	        $sql.= ", price=".price2num($pu_ht);
891
	        $sql.= ", qty=".price2num($qty);
892
	        $sql.= ", tva_tx=".price2num($txtva);
893
	        $sql.= ", vat_src_code='".$this->db->escape($vat_src_code)."'";
894
		    $sql.= ", localtax1_tx=".$txlocaltax1;
895
		    $sql.= ", localtax1_type='".$this->db->escape($localtaxes_type[0])."'";
896
		    $sql.= ", localtax2_tx=".$txlocaltax2;
897
		    $sql.= ", localtax2_type='".$this->db->escape($localtaxes_type[2])."'";
898
	        $sql.= ", fk_product=".(! empty($fk_product)?"'".$fk_product."'":"null");
899
	        $sql.= ", product_type=".$product_type;
900
	        $sql.= ", remise_percent='".price2num($remise_percent)."'";
901
	        $sql.= ", subprice='".price2num($pu_ht)."'";
902
	        $sql.= ", total_ht='".price2num($total_ht)."'";
903
	        $sql.= ", total_tva='".price2num($total_tva)."'";
904
	        $sql.= ", total_localtax1='".price2num($total_localtax1)."'";
905
	        $sql.= ", total_localtax2='".price2num($total_localtax2)."'";
906
	        $sql.= ", total_ttc='".price2num($total_ttc)."'";
907
	        $sql.= ", date_start_fill=".((int) $date_start_fill);
908
	        $sql.= ", date_end_fill=".((int) $date_end_fill);
909
	        $sql.= ", info_bits=".$info_bits;
910
	        $sql.= ", rang=".$rang;
911
	        $sql.= ", special_code=".$special_code;
912
	        $sql.= ", fk_unit=".($fk_unit?"'".$this->db->escape($fk_unit)."'":"null");
913
	        $sql.= ', multicurrency_subprice = '.$pu_ht_devise;
914
	        $sql.= ', multicurrency_total_ht = '.$multicurrency_total_ht;
915
	        $sql.= ', multicurrency_total_tva = '.$multicurrency_total_tva;
916
	        $sql.= ', multicurrency_total_ttc = '.$multicurrency_total_ttc;
917
	        $sql.= " WHERE rowid = ".$rowid;
918
919
	        dol_syslog(get_class($this)."::updateline", LOG_DEBUG);
920
	        if ($this->db->query($sql))
921
	        {
922
	            $this->id=$facid;
923
	            $this->update_price();
924
	            return 1;
925
	        }
926
	        else
927
	        {
928
	            $this->error=$this->db->lasterror();
929
	            return -1;
930
	        }
931
	    }
932
	}
933
934
935
	/**
936
	 * Return the next date of
937
	 *
938
	 * @return	timestamp	false if KO, timestamp if OK
939
	 */
940
	function getNextDate()
941
	{
942
		if (empty($this->date_when)) return false;
943
		return dol_time_plus_duree($this->date_when, $this->frequency, $this->unit_frequency);
944
	}
945
946
	/**
947
	 * Return if maximum number of generation is reached
948
	 *
949
	 * @return	boolean			False by default, True if maximum number of generation is reached
950
	 */
951
	function isMaxNbGenReached()
952
	{
953
		$ret = false;
954
		if ($this->nb_gen_max > 0 && ($this->nb_gen_done >= $this->nb_gen_max)) $ret = true;
955
		return $ret;
956
	}
957
958
	/**
959
	 * Format string to output with by striking the string if max number of generation was reached
960
	 *
961
	 * @param	string		$ret	Default value to output
962
	 * @return	boolean				False by default, True if maximum number of generation is reached
963
	 */
964
	function strikeIfMaxNbGenReached($ret)
965
	{
966
		// Special case to strike the date
967
		return ($this->isMaxNbGenReached()?'<strike>':'').$ret.($this->isMaxNbGenReached()?'</strike>':'');
968
	}
969
970
	/**
971
	 *  Create all recurrents invoices (for all entities if multicompany is used).
972
	 *  A result may also be provided into this->output.
973
	 *
974
	 *  WARNING: This method change temporarly context $conf->entity to be in correct context for each recurring invoice found.
975
	 *
976
	 *  @param	int		$restictoninvoiceid		0=All qualified template invoices found. > 0 = restrict action on invoice ID
977
	 *  @param	int		$forcevalidation		1=Force validation of invoice whatever is template auto_validate flag.
978
	 *  @return	int								0 if OK, < 0 if KO (this function is used also by cron so only 0 is OK)
979
	 */
980
	function createRecurringInvoices($restictoninvoiceid=0, $forcevalidation=0)
981
	{
982
		global $conf, $langs, $db, $user;
983
984
		$error=0;
985
986
		$langs->load("bills");
987
988
		$nb_create=0;
989
990
		$now = dol_now();
991
		$tmparray=dol_getdate($now);
992
		$today = dol_mktime(23,59,59,$tmparray['mon'],$tmparray['mday'],$tmparray['year']);   // Today is last second of current day
993
994
		dol_syslog("createRecurringInvoices restictoninvoiceid=".$restictoninvoiceid." forcevalidation=".$forcevalidation);
995
996
		$sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'facture_rec';
997
		$sql.= ' WHERE frequency > 0';      // A recurring invoice is an invoice with a frequency
998
		$sql.= " AND (date_when IS NULL OR date_when <= '".$db->idate($today)."')";
999
		$sql.= ' AND (nb_gen_done < nb_gen_max OR nb_gen_max = 0)';
1000
		$sql.= ' AND suspended = 0';
1001
		$sql.= ' AND entity = '.$conf->entity;	// MUST STAY = $conf->entity here
1002
		if ($restictoninvoiceid > 0) $sql.=' AND rowid = '.$restictoninvoiceid;
1003
		$sql.= $db->order('entity', 'ASC');
1004
		//print $sql;exit;
1005
1006
		$resql = $db->query($sql);
1007
		if ($resql)
1008
		{
1009
		    $i=0;
1010
		    $num = $db->num_rows($resql);
1011
1012
		    if ($num) $this->output.=$langs->trans("FoundXQualifiedRecurringInvoiceTemplate", $num)."\n";
1013
		    else $this->output.=$langs->trans("NoQualifiedRecurringInvoiceTemplateFound");
1014
1015
		    $saventity = $conf->entity;
1016
1017
		    while ($i < $num)     // Loop on each template invoice. If $num = 0, test is false at first pass.
1018
			{
1019
				$line = $db->fetch_object($resql);
1020
1021
			    $db->begin();
1022
1023
			    $invoiceidgenerated = 0;
1024
1025
			    $facturerec = new FactureRec($db);
1026
				$facturerec->fetch($line->rowid);
1027
1028
				if ($facturerec->id > 0)
1029
				{
1030
					// Set entity context
1031
					$conf->entity = $facturerec->entity;
1032
1033
					dol_syslog("createRecurringInvoices Process invoice template id=".$facturerec->id.", ref=".$facturerec->ref.", entity=".$facturerec->entity);
1034
1035
				    $facture = new Facture($db);
1036
					$facture->fac_rec = $facturerec->id;    // We will create $facture from this recurring invoice
1037
					$facture->fk_fac_rec_source = $facturerec->id;    // We will create $facture from this recurring invoice
1038
1039
				    $facture->type = self::TYPE_STANDARD;
1040
				    $facture->brouillon = 1;
1041
				    $facture->date = (empty($facturerec->date_when)?$now:$facturerec->date_when);	// We could also use dol_now here but we prefer date_when so invoice has real date when we would like even if we generate later.
1042
				    $facture->socid = $facturerec->socid;
1043
1044
				    $invoiceidgenerated = $facture->create($user);
1045
				    if ($invoiceidgenerated <= 0)
1046
				    {
1047
				        $this->errors = $facture->errors;
1048
				        $this->error = $facture->error;
1049
				        $error++;
1050
				    }
1051
				    if (! $error && ($facturerec->auto_validate || $forcevalidation))
1052
				    {
1053
				        $result = $facture->validate($user);
1054
				        if ($result <= 0)
1055
				        {
1056
	    			        $this->errors = $facture->errors;
1057
	    			        $this->error = $facture->error;
1058
				            $error++;
1059
	                    }
1060
				    }
1061
	                if (! $error && $facturerec->generate_pdf)
1062
	                {
1063
	                    $result = $facture->generateDocument($facturerec->modelpdf, $langs);
1064
	                    if ($result <= 0)
1065
	                    {
1066
	                        $this->errors = $facture->errors;
1067
	                        $this->error = $facture->error;
1068
	                        $error++;
1069
	                    }
1070
	                }
1071
				}
1072
				else
1073
				{
1074
					$error++;
1075
					$this->error="Failed to load invoice template with id=".$line->rowid.", entity=".$conf->entity."\n";
1076
					$this->errors[]="Failed to load invoice template with id=".$line->rowid.", entity=".$conf->entity;
1077
					dol_syslog("createRecurringInvoices Failed to load invoice template with id=".$line->rowid.", entity=".$conf->entity);
1078
				}
1079
1080
				if (! $error && $invoiceidgenerated >= 0)
1081
				{
1082
					$db->commit("createRecurringInvoices Process invoice template id=".$facturerec->id.", ref=".$facturerec->ref);
1083
					dol_syslog("createRecurringInvoices Process invoice template ".$facturerec->ref." is finished with a success generation");
1084
					$nb_create++;
1085
					$this->output.=$langs->trans("InvoiceGeneratedFromTemplate", $facture->ref, $facturerec->ref)."\n";
0 ignored issues
show
Bug introduced by
The variable $facture 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...
1086
				}
1087
				else
1088
				{
1089
				    $db->rollback("createRecurringInvoices Process invoice template id=".$facturerec->id.", ref=".$facturerec->ref);
1090
				}
1091
1092
				$i++;
1093
			}
1094
1095
			$conf->entity = $saventity;      // Restore entity context
1096
		}
1097
		else dol_print_error($db);
1098
1099
		$this->output=trim($this->output);
1100
1101
		return $error?$error:0;
1102
	}
1103
1104
	/**
1105
	 *	Return clicable name (with picto eventually)
1106
	 *
1107
	 * @param	int		$withpicto       			Add picto into link
1108
	 * @param  string	$option          			Where point the link
1109
	 * @param  int		$max             			Maxlength of ref
1110
	 * @param  int		$short           			1=Return just URL
1111
	 * @param  string   $moretitle       			Add more text to title tooltip
1112
     * @param	int  	$notooltip		 			1=Disable tooltip
1113
     * @param  int		$save_lastsearch_value    	-1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
1114
	 * @return string 			         			String with URL
1115
	 */
1116
	function getNomUrl($withpicto=0,$option='',$max=0,$short=0,$moretitle='',$notooltip='',$save_lastsearch_value=-1)
1117
	{
1118
		global $langs;
1119
1120
		$result='';
1121
        $label=$langs->trans("ShowInvoice").': '.$this->ref;
1122
1123
        $url = DOL_URL_ROOT.'/compta/facture/fiche-rec.php?facid='.$this->id;
1124
1125
        if ($short) return $url;
1126
1127
        if ($option != 'nolink')
1128
        {
1129
        	// Add param to save lastsearch_values or not
1130
        	$add_save_lastsearch_values=($save_lastsearch_value == 1 ? 1 : 0);
1131
        	if ($save_lastsearch_value == -1 && preg_match('/list\.php/',$_SERVER["PHP_SELF"])) $add_save_lastsearch_values=1;
1132
        	if ($add_save_lastsearch_values) $url.='&save_lastsearch_values=1';
1133
        }
1134
1135
		$linkstart = '<a href="'.$url.'" title="'.dol_escape_htmltag($label, 1).'" class="classfortooltip">';
1136
		$linkend='</a>';
1137
1138
		$result .= $linkstart;
1139
		if ($withpicto) $result.=img_object(($notooltip?'':$label), ($this->picto?$this->picto:'generic'), ($notooltip?(($withpicto != 2) ? 'class="paddingright"' : ''):'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip?0:1);
1140
		if ($withpicto != 2) $result.= $this->ref;
1141
		$result .= $linkend;
1142
1143
		return $result;
1144
	}
1145
1146
	/**
1147
	 *  Return label of object status
1148
	 *
1149
	 *  @param      int		$mode			0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=short label + picto, 6=Long label + picto
1150
	 *  @param      integer	$alreadypaid    Not used on recurring invoices
1151
	 *  @return     string			        Label of status
1152
	 */
1153
	function getLibStatut($mode=0, $alreadypaid=-1)
1154
	{
1155
1156
		return $this->LibStatut($this->frequency?1:0, $this->suspended, $mode, $alreadypaid, empty($this->type)?0:$this->type);
1157
	}
1158
1159
	/**
1160
	 *	Return label of a status
1161
	 *
1162
	 *	@param    	int  	$recur         	Is it a recurring invoice ?
1163
	 *	@param      int		$status        	Id status (suspended or not)
1164
	 *	@param      int		$mode          	0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=short label + picto, 6=long label + picto
1165
	 *	@param		integer	$alreadypaid	Not used for recurring invoices
1166
	 *	@param		int		$type			Type invoice
1167
	 *	@return     string        			Label of status
1168
	 */
1169
	function LibStatut($recur, $status, $mode=0, $alreadypaid=-1, $type=0)
1170
	{
1171
		global $langs;
1172
		$langs->load('bills');
1173
1174
		//print "$recur,$status,$mode,$alreadypaid,$type";
1175
		if ($mode == 0)
1176
		{
1177
			$prefix='';
1178
			if ($recur)
1179
			{
1180
				if ($status == self::STATUS_SUSPENDED) return $langs->trans('Disabled');
1181
				else return $langs->trans('Active');
1182
			}
1183
			else
1184
			{
1185
				if ($status == self::STATUS_SUSPENDED) return $langs->trans('Disabled');
1186
				else return $langs->trans("Draft");
1187
			}
1188
		}
1189
		if ($mode == 1)
1190
		{
1191
			$prefix='Short';
1192
			if ($recur)
1193
			{
1194
				if ($status == self::STATUS_SUSPENDED) return $langs->trans('Disabled');
1195
				else return $langs->trans('Active');
1196
			}
1197
			else
1198
			{
1199
				if ($status == self::STATUS_SUSPENDED) return $langs->trans('Disabled');
1200
				else return $langs->trans("Draft");
1201
			}
1202
		}
1203
		if ($mode == 2)
1204
		{
1205
			if ($recur)
1206
			{
1207
				if ($status == self::STATUS_SUSPENDED) return img_picto($langs->trans('Disabled'),'statut6').' '.$langs->trans('Disabled');
1208
				else return img_picto($langs->trans('Active'),'statut4').' '.$langs->trans('Active');
1209
			}
1210
			else
1211
			{
1212
				if ($status == self::STATUS_SUSPENDED) return img_picto($langs->trans('Disabled'),'statut6').' '.$langs->trans('Disabled');
1213
				else return img_picto($langs->trans('Draft'),'statut0').' '.$langs->trans('Draft');
1214
			}
1215
		}
1216
		if ($mode == 3)
1217
		{
1218
			if ($recur)
1219
			{
1220
				$prefix='Short';
1221
				if ($status == self::STATUS_SUSPENDED) return img_picto($langs->trans('Disabled'),'statut6');
1222
				else return img_picto($langs->trans('Active'),'statut4');
1223
			}
1224
			else
1225
			{
1226
				if ($status == self::STATUS_SUSPENDED) return img_picto($langs->trans('Disabled'),'statut6');
1227
				else return img_picto($langs->trans('Draft'),'statut0');
1228
			}
1229
		}
1230
		if ($mode == 4)
1231
		{
1232
			$prefix='';
1233
			if ($recur)
1234
			{
1235
				if ($status == self::STATUS_SUSPENDED) return img_picto($langs->trans('Disabled'),'statut6').' '.$langs->trans('Disabled');
1236
				else return img_picto($langs->trans('Active'),'statut4').' '.$langs->trans('Active');
1237
			}
1238
			else
1239
			{
1240
				if ($status == self::STATUS_SUSPENDED) return img_picto($langs->trans('Disabled'),'statut6').' '.$langs->trans('Disabled');
1241
				else return img_picto($langs->trans('Draft'),'statut0').' '.$langs->trans('Draft');
1242
			}
1243
		}
1244
		if ($mode == 5 || $mode == 6)
1245
		{
1246
			$prefix='';
1247
			if ($mode == 5) $prefix='Short';
1248
			if ($recur)
1249
			{
1250
				if ($status == self::STATUS_SUSPENDED) return '<span class="xhideonsmartphone">'.$langs->trans('Disabled').' </span>'.img_picto($langs->trans('Disabled'),'statut6');
1251
				else return '<span class="xhideonsmartphone">'.$langs->trans('Active').' </span>'.img_picto($langs->trans('Active'),'statut4');
1252
			}
1253
			else
1254
			{
1255
				if ($status == self::STATUS_SUSPENDED) return '<span class="xhideonsmartphone">'.$langs->trans('Disabled').' </span>'.img_picto($langs->trans('Disabled'),'statut6');
1256
				else return $langs->trans('Draft').' '.img_picto($langs->trans('Active'),'statut0');
1257
			}
1258
		}
1259
	}
1260
1261
	/**
1262
	 *  Initialise an instance with random values.
1263
	 *  Used to build previews or test instances.
1264
	 *	id must be 0 if object instance is a specimen.
1265
	 *
1266
	 *	@param	string		$option		''=Create a specimen invoice with lines, 'nolines'=No lines
1267
	 *  @return	void
1268
	 */
1269
	function initAsSpecimen($option='')
1270
	{
1271
		global $user,$langs,$conf;
1272
1273
		$now=dol_now();
1274
		$arraynow=dol_getdate($now);
1275
		$nownotime=dol_mktime(0, 0, 0, $arraynow['mon'], $arraynow['mday'], $arraynow['year']);
1276
1277
        // Load array of products prodids
1278
		$num_prods = 0;
1279
		$prodids = array();
1280
1281
		$sql = "SELECT rowid";
1282
		$sql.= " FROM ".MAIN_DB_PREFIX."product";
1283
		$sql.= " WHERE entity IN (".getEntity('product').")";
1284
		$resql = $this->db->query($sql);
1285
		if ($resql)
1286
		{
1287
			$num_prods = $this->db->num_rows($resql);
1288
			$i = 0;
1289
			while ($i < $num_prods)
1290
			{
1291
				$i++;
1292
				$row = $this->db->fetch_row($resql);
1293
				$prodids[$i] = $row[0];
1294
			}
1295
		}
1296
1297
		// Initialize parameters
1298
		$this->id=0;
1299
		$this->ref = 'SPECIMEN';
1300
		$this->specimen=1;
1301
		$this->socid = 1;
1302
		$this->date = $nownotime;
1303
		$this->date_lim_reglement = $nownotime + 3600 * 24 *30;
1304
		$this->cond_reglement_id   = 1;
1305
		$this->cond_reglement_code = 'RECEP';
1306
		$this->date_lim_reglement=$this->calculate_date_lim_reglement();
1307
		$this->mode_reglement_id   = 0;		// Not forced to show payment mode CHQ + VIR
1308
		$this->mode_reglement_code = '';	// Not forced to show payment mode CHQ + VIR
1309
		$this->note_public='This is a comment (public)';
1310
		$this->note_private='This is a comment (private)';
1311
		$this->note='This is a comment (private)';
1312
		$this->fk_incoterms=0;
1313
		$this->location_incoterms='';
1314
1315
		if (empty($option) || $option != 'nolines')
1316
		{
1317
			// Lines
1318
			$nbp = 5;
1319
			$xnbp = 0;
1320
			while ($xnbp < $nbp)
1321
			{
1322
				$line=new FactureLigne($this->db);
1323
				$line->desc=$langs->trans("Description")." ".$xnbp;
1324
				$line->qty=1;
1325
				$line->subprice=100;
1326
				$line->tva_tx=19.6;
1327
				$line->localtax1_tx=0;
1328
				$line->localtax2_tx=0;
1329
				$line->remise_percent=0;
1330
				if ($xnbp == 1)        // Qty is negative (product line)
1331
				{
1332
					$prodid = mt_rand(1, $num_prods);
1333
					$line->fk_product=$prodids[$prodid];
1334
					$line->qty=-1;
1335
					$line->total_ht=-100;
1336
					$line->total_ttc=-119.6;
1337
					$line->total_tva=-19.6;
1338
				}
1339
				else if ($xnbp == 2)    // UP is negative (free line)
1340
				{
1341
					$line->subprice=-100;
1342
					$line->total_ht=-100;
1343
					$line->total_ttc=-119.6;
1344
					$line->total_tva=-19.6;
1345
					$line->remise_percent=0;
1346
				}
1347
				else if ($xnbp == 3)    // Discount is 50% (product line)
1348
				{
1349
					$prodid = mt_rand(1, $num_prods);
1350
					$line->fk_product=$prodids[$prodid];
1351
					$line->total_ht=50;
1352
					$line->total_ttc=59.8;
1353
					$line->total_tva=9.8;
1354
					$line->remise_percent=50;
1355
				}
1356
				else    // (product line)
1357
				{
1358
					$prodid = mt_rand(1, $num_prods);
1359
					$line->fk_product=$prodids[$prodid];
1360
					$line->total_ht=100;
1361
					$line->total_ttc=119.6;
1362
					$line->total_tva=19.6;
1363
					$line->remise_percent=00;
1364
				}
1365
1366
				$this->lines[$xnbp]=$line;
1367
				$xnbp++;
1368
1369
				$this->total_ht       += $line->total_ht;
1370
				$this->total_tva      += $line->total_tva;
1371
				$this->total_ttc      += $line->total_ttc;
1372
			}
1373
			$this->revenuestamp = 0;
1374
1375
			// Add a line "offered"
1376
			$line=new FactureLigne($this->db);
1377
			$line->desc=$langs->trans("Description")." (offered line)";
1378
			$line->qty=1;
1379
			$line->subprice=100;
1380
			$line->tva_tx=19.6;
1381
			$line->localtax1_tx=0;
1382
			$line->localtax2_tx=0;
1383
			$line->remise_percent=100;
1384
			$line->total_ht=0;
1385
			$line->total_ttc=0;    // 90 * 1.196
1386
			$line->total_tva=0;
1387
			$prodid = mt_rand(1, $num_prods);
1388
			$line->fk_product=$prodids[$prodid];
1389
1390
			$this->lines[$xnbp]=$line;
1391
			$xnbp++;
1392
		}
1393
1394
		$this->usenewprice = 1;
1395
	}
1396
1397
	/**
1398
	 * Function used to replace a thirdparty id with another one.
1399
	 *
1400
	 * @param DoliDB $db Database handler
1401
	 * @param int $origin_id Old thirdparty id
1402
	 * @param int $dest_id New thirdparty id
1403
	 * @return bool
1404
	 */
1405
	public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
1406
	{
1407
		$tables = array(
1408
			'facture_rec'
1409
		);
1410
1411
		return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
1412
	}
1413
1414
	/**
1415
     *	Update frequency and unit
1416
     *
1417
     *	@param     	int		$frequency		value of frequency
1418
	 *	@param     	string	$unit 			unit of frequency  (d, m, y)
1419
     *	@return		int						<0 if KO, >0 if OK
1420
     */
1421
    function setFrequencyAndUnit($frequency,$unit)
1422
    {
1423
        if (! $this->table_element)
1424
        {
1425
            dol_syslog(get_class($this)."::setFrequencyAndUnit was called on objet with property table_element not defined",LOG_ERR);
1426
            return -1;
1427
        }
1428
1429
		if (!empty($frequency) && empty($unit))
1430
        {
1431
            dol_syslog(get_class($this)."::setFrequencyAndUnit was called on objet with params frequency defined but unit not defined",LOG_ERR);
1432
            return -2;
1433
        }
1434
1435
        $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
1436
        $sql.= ' SET frequency = '.($frequency?$this->db->escape($frequency):'null');
1437
        if (!empty($unit))
1438
        {
1439
        	$sql.= ', unit_frequency = \''.$this->db->escape($unit).'\'';
1440
		}
1441
        $sql.= ' WHERE rowid = '.$this->id;
1442
1443
        dol_syslog(get_class($this)."::setFrequencyAndUnit", LOG_DEBUG);
1444
        if ($this->db->query($sql))
1445
        {
1446
            $this->frequency = $frequency;
1447
			if (!empty($unit)) $this->unit_frequency = $unit;
1448
            return 1;
1449
        }
1450
        else
1451
        {
1452
            dol_print_error($this->db);
1453
            return -1;
1454
        }
1455
    }
1456
1457
	/**
1458
     *	Update the next date of execution
1459
     *
1460
     *	@param     	datetime	$date					date of execution
1461
     *	@param     	int			$increment_nb_gen_done	0 do nothing more, >0 increment nb_gen_done
1462
     *	@return		int									<0 if KO, >0 if OK
1463
     */
1464
    function setNextDate($date, $increment_nb_gen_done=0)
1465
    {
1466
        if (! $this->table_element)
1467
        {
1468
            dol_syslog(get_class($this)."::setNextDate was called on objet with property table_element not defined",LOG_ERR);
1469
            return -1;
1470
        }
1471
        $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
1472
        $sql.= " SET date_when = ".($date ? "'".$this->db->idate($date)."'" : "null");
1473
        if ($increment_nb_gen_done>0) $sql.= ', nb_gen_done = nb_gen_done + 1';
1474
        $sql.= ' WHERE rowid = '.$this->id;
1475
1476
        dol_syslog(get_class($this)."::setNextDate", LOG_DEBUG);
1477
        if ($this->db->query($sql))
1478
        {
1479
            $this->date_when = $date;
1480
            if ($increment_nb_gen_done>0) $this->nb_gen_done++;
1481
            return 1;
1482
        }
1483
        else
1484
        {
1485
            dol_print_error($this->db);
1486
            return -1;
1487
        }
1488
    }
1489
1490
	/**
1491
     *	Update the maximum period
1492
     *
1493
     *	@param     	int		$nb		number of maximum period
1494
     *	@return		int				<0 if KO, >0 if OK
1495
     */
1496
    function setMaxPeriod($nb)
1497
    {
1498
        if (! $this->table_element)
1499
        {
1500
            dol_syslog(get_class($this)."::setMaxPeriod was called on objet with property table_element not defined",LOG_ERR);
1501
            return -1;
1502
        }
1503
1504
        if (empty($nb)) $nb=0;
1505
1506
        $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
1507
        $sql.= ' SET nb_gen_max = '.$nb;
1508
        $sql.= ' WHERE rowid = '.$this->id;
1509
1510
        dol_syslog(get_class($this)."::setMaxPeriod", LOG_DEBUG);
1511
        if ($this->db->query($sql))
1512
        {
1513
            $this->nb_gen_max = $nb;
1514
            return 1;
1515
        }
1516
        else
1517
        {
1518
            dol_print_error($this->db);
1519
            return -1;
1520
        }
1521
    }
1522
1523
	/**
1524
     *	Update the auto validate flag of invoice
1525
     *
1526
     *	@param     	int		$validate		0 to create in draft, 1 to create and validate invoice
1527
     *	@return		int						<0 if KO, >0 if OK
1528
     */
1529
    function setAutoValidate($validate)
1530
    {
1531
        if (! $this->table_element)
1532
        {
1533
            dol_syslog(get_class($this)."::setAutoValidate was called on objet with property table_element not defined",LOG_ERR);
1534
            return -1;
1535
        }
1536
1537
        $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
1538
        $sql.= ' SET auto_validate = '.$validate;
1539
        $sql.= ' WHERE rowid = '.$this->id;
1540
1541
        dol_syslog(get_class($this)."::setAutoValidate", LOG_DEBUG);
1542
        if ($this->db->query($sql))
1543
        {
1544
            $this->auto_validate = $validate;
1545
            return 1;
1546
        }
1547
        else
1548
        {
1549
            dol_print_error($this->db);
1550
            return -1;
1551
        }
1552
    }
1553
1554
    /**
1555
     *	Update the auto generate documents
1556
     *
1557
     *	@param     	int		$validate		0 no document, 1 to generate document
1558
     *	@return		int						<0 if KO, >0 if OK
1559
     */
1560
    function setGeneratePdf($validate)
1561
    {
1562
        if (! $this->table_element)
1563
        {
1564
            dol_syslog(get_class($this)."::setGeneratePdf was called on objet with property table_element not defined",LOG_ERR);
1565
            return -1;
1566
        }
1567
1568
        $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
1569
        $sql.= ' SET generate_pdf = '.$validate;
1570
        $sql.= ' WHERE rowid = '.$this->id;
1571
1572
        dol_syslog(get_class($this)."::setGeneratePdf", LOG_DEBUG);
1573
        if ($this->db->query($sql))
1574
        {
1575
            $this->generate_pdf = $validate;
1576
            return 1;
1577
        }
1578
        else
1579
        {
1580
            dol_print_error($this->db);
1581
            return -1;
1582
        }
1583
    }
1584
1585
    /**
1586
     *	Update the model for documents
1587
     *
1588
     *	@param     	string		$model		model of document generator
1589
     *	@return		int						<0 if KO, >0 if OK
1590
     */
1591
    function setModelPdf($model)
1592
    {
1593
        if (! $this->table_element)
1594
        {
1595
            dol_syslog(get_class($this)."::setModelPdf was called on objet with property table_element not defined",LOG_ERR);
1596
            return -1;
1597
        }
1598
1599
        $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
1600
        $sql.= ' SET modelpdf = "' . $model . '"';
1601
        $sql.= ' WHERE rowid = '.$this->id;
1602
1603
        dol_syslog(get_class($this)."::setModelPdf", LOG_DEBUG);
1604
        if ($this->db->query($sql))
1605
        {
1606
            $this->modelpdf = $model;
1607
            return 1;
1608
        }
1609
        else
1610
        {
1611
            dol_print_error($this->db);
1612
            return -1;
1613
        }
1614
    }
1615
}
1616
1617
1618
1619
/**
1620
 *	Class to manage invoice lines of templates.
1621
 *  Saved into database table llx_facturedet_rec
1622
 */
1623
class FactureLigneRec extends CommonInvoiceLine
1624
{
1625
	public $element='facturedetrec';
1626
	public $table_element='facturedet_rec';
1627
1628
	var $date_start_fill;
1629
	var $date_end_fill;
1630
1631
1632
    /**
1633
     * 	Delete line in database
1634
     *
1635
     *  @param		User	$user		Object user
1636
     *  @param		int		$notrigger	Disable triggers
1637
     *	@return		int					<0 if KO, >0 if OK
1638
     */
1639
    function delete(User $user, $notrigger = false)
1640
    {
1641
    	$error=0;
1642
1643
	    $this->db->begin();
1644
1645
	    if (! $error) {
1646
	        if (! $notrigger) {
1647
	            // Call triggers
1648
	            $result=$this->call_trigger('LINEBILLREC_DELETE', $user);
1649
	            if ($result < 0) { $error++; } // Do also here what you must do to rollback action if trigger fail
1650
	            // End call triggers
1651
	        }
1652
	    }
1653
1654
	    if (! $error)
1655
	    {
1656
    		$sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.' WHERE rowid='.$this->id;
1657
1658
    		$res = $this->db->query($sql);
1659
    		if($res===false) {
1660
    		    $error++;
1661
    		    $this->errors[] = $this->db->lasterror();
1662
    		}
1663
	    }
1664
1665
    	// Commit or rollback
1666
		if ($error) {
1667
		    $this->db->rollback();
1668
		    return -1;
1669
		} else {
1670
		    $this->db->commit();
1671
		    return 1;
1672
		}
1673
    }
1674
1675
1676
    /**
1677
     *	Recupere les lignes de factures predefinies dans this->lines
1678
     *
1679
     *	@param		int 	$rowid		Id of invoice
1680
     *	@return     int         		1 if OK, < 0 if KO
1681
     */
1682
    function fetch($rowid)
1683
    {
1684
    	$sql = 'SELECT l.rowid, l.fk_facture ,l.fk_product, l.product_type, l.label as custom_label, l.description, l.product_type, l.price, l.qty, l.vat_src_code, l.tva_tx,';
1685
    	$sql.= ' l.localtax1_tx, l.localtax2_tx, l.localtax1_type, l.localtax2_type, l.remise, l.remise_percent, l.subprice,';
1686
    	$sql.= ' l.date_start_fill, l.date_end_fill, l.info_bits, l.total_ht, l.total_tva, l.total_ttc,';
1687
    	$sql.= ' l.rang, l.special_code,';
1688
    	$sql.= ' l.fk_unit, l.fk_contract_line,';
1689
    	$sql.= ' p.ref as product_ref, p.fk_product_type as fk_product_type, p.label as product_label, p.description as product_desc';
1690
    	$sql.= ' FROM '.MAIN_DB_PREFIX.'facturedet_rec as l';
1691
    	$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON l.fk_product = p.rowid';
1692
    	$sql.= ' WHERE l.rowid = '.$rowid;
1693
    	$sql.= ' ORDER BY l.rang';
1694
1695
    	dol_syslog('FactureRec::fetch', LOG_DEBUG);
1696
    	$result = $this->db->query($sql);
1697
    	if ($result)
1698
    	{
1699
1700
    		$objp = $this->db->fetch_object($result);
1701
1702
    		$this->id	            = $objp->rowid;
1703
    		$this->label            = $objp->custom_label;		// Label line
1704
    		$this->desc             = $objp->description;		// Description line
1705
    		$this->description      = $objp->description;		// Description line
1706
    		$this->product_type     = $objp->product_type;		// Type of line
1707
    		$this->ref              = $objp->product_ref;		// Ref product
1708
    		$this->product_ref      = $objp->product_ref;		// Ref product
1709
    		$this->libelle          = $objp->product_label;		// deprecated
1710
    		$this->product_label	= $objp->product_label;		// Label product
1711
    		$this->product_desc     = $objp->product_desc;		// Description product
1712
    		$this->fk_product_type  = $objp->fk_product_type;	// Type of product
1713
    		$this->qty              = $objp->qty;
1714
    		$this->price			= $objp->price;
1715
    		$this->subprice         = $objp->subprice;
1716
    		$this->fk_facture		= $objp->fk_facture;
1717
    		$this->vat_src_code     = $objp->vat_src_code;
1718
    		$this->tva_tx           = $objp->tva_tx;
1719
    		$this->localtax1_tx     = $objp->localtax1_tx;
1720
    		$this->localtax2_tx     = $objp->localtax2_tx;
1721
    		$this->localtax1_type   = $objp->localtax1_type;
1722
    		$this->localtax2_type   = $objp->localtax2_type;
1723
    		$this->remise_percent   = $objp->remise_percent;
1724
    		$this->fk_remise_except = $objp->fk_remise_except;
1725
    		$this->fk_product       = $objp->fk_product;
1726
    		$this->date_start_fill  = $objp->date_start_fill;
1727
    		$this->date_end_fill    = $objp->date_end_fill;
1728
    		$this->info_bits        = $objp->info_bits;
1729
    		$this->total_ht         = $objp->total_ht;
1730
    		$this->total_tva        = $objp->total_tva;
1731
    		$this->total_ttc        = $objp->total_ttc;
1732
    		$this->code_ventilation = $objp->fk_code_ventilation;
1733
    		$this->rang 			= $objp->rang;
1734
    		$this->special_code 	= $objp->special_code;
1735
    		$this->fk_unit          = $objp->fk_unit;
1736
    		$this->fk_contract_line = $objp->fk_contract_line;
1737
1738
1739
    		$this->db->free($result);
1740
    		return 1;
1741
    	}
1742
    	else
1743
    	{
1744
    		$this->error=$this->db->lasterror();
1745
    		return -3;
1746
    	}
1747
    }
1748
1749
1750
    /**
1751
     * 	Update a line to invoice_rec.
1752
     *
1753
     *  @param		User	$user					User
1754
     *  @param		int		$notrigger				No trigger
1755
     *	@return    	int             				<0 if KO, Id of line if OK
1756
     */
1757
    function update(User $user, $notrigger=0)
1758
    {
1759
    	global $conf;
1760
1761
    	include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
1762
1763
    	$sql = "UPDATE ".MAIN_DB_PREFIX."facturedet_rec SET";
1764
    	$sql.= " fk_facture = ".$this->fk_facture;
1765
    	$sql.= ", label=".(! empty($this->label)?"'".$this->db->escape($this->label)."'":"null");
1766
    	$sql.= ", description='".$this->db->escape($this->desc)."'";
1767
    	$sql.= ", price=".price2num($this->price);
1768
    	$sql.= ", qty=".price2num($this->qty);
1769
    	$sql.= ", tva_tx=".price2num($this->tva_tx);
1770
    	$sql.= ", vat_src_code='".$this->db->escape($this->vat_src_code)."'";
1771
    	$sql.= ", localtax1_tx=".price2num($this->localtax1_tx);
1772
    	$sql.= ", localtax1_type='".$this->db->escape($this->localtax1_type)."'";
1773
    	$sql.= ", localtax2_tx=".price2num($this->localtax2_tx);
1774
    	$sql.= ", localtax2_type='".$this->db->escape($this->localtax2_type)."'";
1775
    	$sql.= ", fk_product=".($this->fk_product > 0 ? $this->fk_product :"null");
1776
    	$sql.= ", product_type=".$this->product_type;
1777
    	$sql.= ", remise_percent='".price2num($this->remise_percent)."'";
1778
    	$sql.= ", subprice='".price2num($this->subprice)."'";
1779
    	$sql.= ", info_bits='".price2num($this->info_bits)."'";
1780
    	$sql.= ", date_start_fill=".(int) $this->date_start_fill;
1781
    	$sql.= ", date_end_fill=".(int) $this->date_end_fill;
1782
    	if (empty($this->skip_update_total))
1783
    	{
1784
    		$sql.= ", total_ht=".price2num($this->total_ht);
1785
	    	$sql.= ", total_tva=".price2num($this->total_tva);
1786
	    	$sql.= ", total_localtax1=".price2num($this->total_localtax1);
1787
	    	$sql.= ", total_localtax2=".price2num($this->total_localtax2);
1788
	    	$sql.= ", total_ttc=".price2num($this->total_ttc);
1789
    	}
1790
    	$sql.= ", rang=".$this->rang;
1791
    	$sql.= ", special_code=".$this->special_code;
1792
    	$sql.= ", fk_unit=".($this->fk_unit ?"'".$this->db->escape($this->fk_unit )."'":"null");
1793
    	$sql.= ", fk_contract_line=".($this->fk_contract_line?$this->fk_contract_line:"null");
1794
    	$sql.= " WHERE rowid = ".$this->id;
1795
1796
    	dol_syslog(get_class($this)."::updateline", LOG_DEBUG);
1797
    	$resql=$this->db->query($sql);
1798
    	if ($resql)
1799
    	{
1800
    		if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
1801
    		{
1802
    			$result=$this->insertExtraFields();
1803
    			if ($result < 0)
1804
    			{
1805
    				$error++;
0 ignored issues
show
Bug introduced by
The variable $error 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...
1806
    			}
1807
    		}
1808
1809
    		if (! $error && ! $notrigger)
1810
    		{
1811
    			// Call trigger
1812
    			$result=$this->call_trigger('LINEBILL_REC_UPDATE', $user);
1813
    			if ($result < 0)
1814
    			{
1815
    				$this->db->rollback();
1816
    				return -2;
1817
    			}
1818
    			// End call triggers
1819
    		}
1820
    		$this->db->commit();
1821
    		return 1;
1822
    	}
1823
    	else
1824
    	{
1825
    		$this->error=$this->db->lasterror();
1826
    		$this->db->rollback();
1827
    		return -2;
1828
    	}
1829
1830
    }
1831
1832
}
1833