Completed
Branch develop (59ab9a)
by
unknown
27:43
created

ExpenseReport::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 10
nc 1
nop 1
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/* Copyright (C) 2011 Dimitri Mouillard   <[email protected]>
3
 * Copyright (C) 2015 Laurent Destailleur <[email protected]>
4
 * Copyright (C) 2015 Alexandre Spangaro  <[email protected]>
5
 * Copyright (C) 2016 Ferran Marcet       <[email protected]>
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19
 */
20
21
/**
22
 *       \file       htdocs/expensereport/class/expensereport.class.php
23
 *       \ingroup    expensereport
24
 *       \brief      File to manage Expense Reports
25
 */
26
require_once DOL_DOCUMENT_ROOT .'/core/class/commonobject.class.php';
27
28
/**
29
 * Class to manage Trips and Expenses
30
 */
31
class ExpenseReport extends CommonObject
32
{
33
    var $element='expensereport';
34
    var $table_element='expensereport';
35
    var $table_element_line = 'expensereport_det';
36
    var $fk_element = 'fk_expensereport';
37
    var $picto = 'trip';
38
39
    var $lignes=array();
40
    
41
    public $date_debut;
42
    
43
    public $date_fin;
44
45
    var $fk_user_validator;
46
    var $status;
47
    var $fk_statut;     // -- 0=draft, 2=validated (attente approb), 4=canceled, 5=approved, 6=payed, 99=denied
48
    var $fk_c_paiement;
49
    var $paid;
50
51
    var $user_author_infos;
52
    var $user_validator_infos;
53
54
    var $fk_typepayment;
55
	var $num_payment;
56
    var $code_paiement;
57
    var $code_statut;
58
59
    // ACTIONS
60
61
    // Create
62
    var $date_create;
63
    var $fk_user_author;    // Note fk_user_author is not the 'author' but the guy the expense report is for.
64
65
    // Update
66
	var $date_modif;
67
    var $fk_user_modif;
68
    
69
    // Refus
70
    var $date_refuse;
71
    var $detail_refuse;
72
    var $fk_user_refuse;
73
74
    // Annulation
75
    var $date_cancel;
76
    var $detail_cancel;
77
    var $fk_user_cancel;
78
79
    // Validation
80
    var $date_valid;
81
    var $fk_user_valid;
82
    var $user_valid_infos;
83
84
    // Approve
85
    var $date_approve;
86
    var $fk_user_approve;
87
88
    // Paiement
89
    var $user_paid_infos;
90
91
    /*
92
        END ACTIONS
93
    */
94
95
96
    /**
97
     *  Constructor
98
     *
99
     *  @param  DoliDB  $db     Handler acces base de donnees
100
     */
101
    function __construct($db)
102
    {
103
        $this->db = $db;
104
        $this->total_ht = 0;
105
        $this->total_ttc = 0;
106
        $this->total_tva = 0;
107
        $this->modepaymentid = 0;
108
109
        // List of language codes for status
110
        $this->statuts_short = array(0 => 'Draft', 2 => 'Validated', 4 => 'Canceled', 5 => 'Approved', 6 => 'Paid', 99 => 'Refused');
111
        $this->statuts = array(0 => 'Draft', 2 => 'ValidatedWaitingApproval', 4 => 'Canceled', 5 => 'Approved', 6 => 'Paid', 99 => 'Refused');
112
        $this->statuts_logo = array(0 => 'statut0', 2 => 'statut1', 4 => 'statut5', 5 => 'statut3', 6 => 'statut6', 99 => 'statut8');
113
114
        return 1;
0 ignored issues
show
Bug introduced by
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
115
    }
116
117
    /**
118
     * Create object in database
119
     *
120
     * @param   User    $user   User that create
121
	 * @param   int     $notrigger   Disable triggers
122
     * @return  int             <0 if KO, >0 if OK
123
     */
124
    function create($user, $notrigger=0)
125
    {
126
        global $conf;
127
128
        $now = dol_now();
129
130
        $error = 0;
131
		
132
        // Check parameters
133
        if (empty($this->date_debut) || empty($this->date_fin)) 
134
        {
135
            $this->error='ErrorFieldRequired';
136
            return -1;
137
        }
138
        
139
        $fuserid = $this->fk_user_author;       // Note fk_user_author is not the 'author' but the guy the expense report is for.
140
        if (empty($fuserid)) $fuserid = $user->id;
141
        
142
        $this->db->begin();
143
144
        $sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." (";
145
        $sql.= "ref";
146
        $sql.= ",total_ht";
147
        $sql.= ",total_ttc";
148
        $sql.= ",total_tva";
149
        $sql.= ",date_debut";
150
        $sql.= ",date_fin";
151
        $sql.= ",date_create";
152
        $sql.= ",fk_user_author";
153
        $sql.= ",fk_user_validator";
154
        $sql.= ",fk_user_modif";
155
        $sql.= ",fk_statut";
156
        $sql.= ",fk_c_paiement";
157
        $sql.= ",paid";
158
        $sql.= ",note_public";
159
        $sql.= ",note_private";
160
        $sql.= ",entity";
161
        $sql.= ") VALUES(";
162
        $sql.= "'(PROV)'";
163
        $sql.= ", ".$this->total_ht;
164
        $sql.= ", ".$this->total_ttc;
165
        $sql.= ", ".$this->total_tva;
166
        $sql.= ", '".$this->db->idate($this->date_debut)."'";
167
        $sql.= ", '".$this->db->idate($this->date_fin)."'";
168
        $sql.= ", '".$this->db->idate($now)."'";
169
        $sql.= ", ".$fuserid;
170
        $sql.= ", ".($this->fk_user_validator > 0 ? $this->fk_user_validator:"null");
171
        $sql.= ", ".($this->fk_user_modif > 0 ? $this->fk_user_modif:"null");
172
        $sql.= ", ".($this->fk_statut > 1 ? $this->fk_statut:0);
173
        $sql.= ", ".($this->modepaymentid?$this->modepaymentid:"null");
174
        $sql.= ", 0";
175
        $sql.= ", ".($this->note_public?"'".$this->db->escape($this->note_public)."'":"null");
176
        $sql.= ", ".($this->note_private?"'".$this->db->escape($this->note_private)."'":"null");
177
        $sql.= ", ".$conf->entity;
178
        $sql.= ")";
179
180
        $result = $this->db->query($sql);
181
        if ($result)
182
        {
183
            $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
184
            $this->ref='(PROV'.$this->id.')';
185
186
            $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element." SET ref='".$this->db->escape($this->ref)."' WHERE rowid=".$this->id;
187
            $resql=$this->db->query($sql);
188
            if (!$resql) $error++;
189
190
            foreach ($this->lines as $i => $val)
191
            {
192
                $newndfline=new ExpenseReportLine($this->db);
193
                $newndfline=$this->lines[$i];
194
                $newndfline->fk_expensereport=$this->id;
195
                if ($result >= 0)
196
                {
197
                    $result=$newndfline->insert();
0 ignored issues
show
Bug introduced by
The method insert() does not exist on CommonObjectLine. Did you maybe mean insertExtraFields()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
198
                }
199
                if ($result < 0)
200
                {
201
                    $error++;
202
                    break;
203
                }
204
            }
205
206
            if (! $error)
207
            {
208
                $result=$this->update_price();
209
                if ($result > 0)
210
                {
211
					
212
					if (!$notrigger)
213
					{
214
						// Call trigger
215
						$result=$this->call_trigger('EXPENSE_REPORT_CREATE',$user);
216
217
						if ($result < 0) {
218
							$error++;
219
						}
220
						// End call triggers
221
					}
222
223
					if (empty($error))
224
					{
225
						$this->db->commit();
226
						return $this->id;
227
					}
228
					else
229
					{
230
						$this->db->rollback();
231
						return -4;
232
					}
233
                }
234
                else
235
                {
236
                    $this->db->rollback();
237
                    return -3;
238
                }
239
            }
240
            else
241
            {
242
                dol_syslog(get_class($this)."::create error ".$this->error, LOG_ERR);
243
                $this->db->rollback();
244
                return -2;
245
            }
246
        }
247
        else
248
        {
249
            $this->error=$this->db->lasterror()." sql=".$sql;
250
            $this->db->rollback();
251
            return -1;
252
        }
253
    }
254
255
256
    /**
257
     *	Load an object from its id and create a new one in database
258
     *
259
     *	@param		int			$fk_user_author		  Id of new user
260
     *	@return		int							      New id of clone
261
     */
262
    function createFromClone($fk_user_author)
263
    {
264
        global $user,$hookmanager;
265
    
266
        $error=0;
267
    
268
        if (empty($fk_user_author)) $fk_user_author = $user->id;
269
        
270
        $this->context['createfromclone'] = 'createfromclone';
271
        
272
        $this->db->begin();
273
    
274
        // get extrafields so they will be clone
275
        //foreach($this->lines as $line)
276
            //$line->fetch_optionals($line->rowid);
277
    
278
        // Load source object
279
        $objFrom = clone $this;
280
281
        $this->id=0;
282
        $this->ref = '';
283
        $this->status=0;
284
        $this->fk_statut=0;
285
286
        // Clear fields
287
        $this->fk_user_author     = $fk_user_author;     // Note fk_user_author is not the 'author' but the guy the expense report is for.
288
        $this->fk_user_valid      = '';
289
        $this->date_create  	  = '';
290
        $this->date_creation      = '';
291
        $this->date_validation    = '';
292
293
        // Create clone
294
        $result=$this->create($user);
295
        if ($result < 0) $error++;
296
297
        if (! $error)
298
        {
299
            // Hook of thirdparty module
300
            if (is_object($hookmanager))
301
            {
302
                $parameters=array('objFrom'=>$objFrom);
303
                $action='';
304
                $reshook=$hookmanager->executeHooks('createFrom',$parameters,$this,$action);    // Note that $action and $object may have been modified by some hooks
305
                if ($reshook < 0) $error++;
306
            }
307
308
            // Call trigger
309
            $result=$this->call_trigger('EXPENSEREPORT_CLONE',$user);
310
            if ($result < 0) $error++;
311
            // End call triggers
312
        }
313
314
        unset($this->context['createfromclone']);
315
316
        // End
317
        if (! $error)
318
        {
319
            $this->db->commit();
320
            return $this->id;
321
        }
322
        else
323
        {
324
            $this->db->rollback();
325
            return -1;
326
        }
327
    }
328
    
329
    
330
    /**
331
     * update
332
     *
333
     * @param   User    $user                   User making change
334
	 * @param   int     $notrigger              Disable triggers
335
     * @param   User    $userofexpensereport    New user we want to have the expense report on.
336
     * @return  int                             <0 if KO, >0 if OK
337
     */
338
    function update($user, $notrigger = 0, $userofexpensereport=null)
339
    {
340
        global $langs;
341
342
		$error = 0;
343
		$this->db->begin();
344
		
345
        $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET";
346
        $sql.= " total_ht = ".$this->total_ht;
347
        $sql.= " , total_ttc = ".$this->total_ttc;
348
        $sql.= " , total_tva = ".$this->total_tva;
349
        $sql.= " , date_debut = '".$this->db->idate($this->date_debut)."'";
350
        $sql.= " , date_fin = '".$this->db->idate($this->date_fin)."'";
351
        if ($userofexpensereport && is_object($userofexpensereport))
352
        {
353
            $sql.= " , fk_user_author = ".($userofexpensereport->id > 0 ? "'".$userofexpensereport->id."'":"null");     // Note fk_user_author is not the 'author' but the guy the expense report is for.
354
        }
355
        $sql.= " , fk_user_validator = ".($this->fk_user_validator > 0 ? $this->fk_user_validator:"null");
356
        $sql.= " , fk_user_valid = ".($this->fk_user_valid > 0 ? $this->fk_user_valid:"null");
357
        $sql.= " , fk_user_modif = ".$user->id;
358
        $sql.= " , fk_statut = ".($this->fk_statut >= 0 ? $this->fk_statut:'0');
359
        $sql.= " , fk_c_paiement = ".($this->fk_c_paiement > 0 ? $this->fk_c_paiement:"null");
360
        $sql.= " , note_public = ".(!empty($this->note_public)?"'".$this->db->escape($this->note_public)."'":"''");
361
        $sql.= " , note_private = ".(!empty($this->note_private)?"'".$this->db->escape($this->note_private)."'":"''");
362
        $sql.= " , detail_refuse = ".(!empty($this->detail_refuse)?"'".$this->db->escape($this->detail_refuse)."'":"''");
363
        $sql.= " WHERE rowid = ".$this->id;
364
365
        dol_syslog(get_class($this)."::update sql=".$sql, LOG_DEBUG);
366
        $result = $this->db->query($sql);
367
        if ($result)
368
        {
369
            if (!$notrigger)
370
			{
371
				// Call trigger
372
				$result=$this->call_trigger('EXPENSE_REPORT_UPDATE',$user);
373
374
				if ($result < 0) {
375
					$error++;
376
				}
377
				// End call triggers
378
			}
379
380
			if (empty($error))
381
			{
382
				$this->db->commit();
383
				return 1;
384
			}
385
			else
386
			{
387
				$this->db->rollback();
388
				$this->error=$this->db->error();
389
				return -2;
390
			}
391
        }
392
        else
393
        {
394
			$this->db->rollback();
395
            $this->error=$this->db->error();
396
            return -1;
397
        }
398
    }
399
400
    /**
401
     *  Load an object from database
402
     *
403
     *  @param  int     $id     Id                      {@min 1}
404
     *  @param  string  $ref    Ref                     {@name ref}
405
     *  @return int             <0 if KO, >0 if OK
406
     */
407
    function fetch($id, $ref='')
408
    {
409
        global $conf;
410
411
        $sql = "SELECT d.rowid, d.ref, d.note_public, d.note_private,";                                 // DEFAULT
412
        $sql.= " d.detail_refuse, d.detail_cancel, d.fk_user_refuse, d.fk_user_cancel,";                // ACTIONS
413
        $sql.= " d.date_refuse, d.date_cancel,";                                                        // ACTIONS
414
        $sql.= " d.total_ht, d.total_ttc, d.total_tva,";                                                // TOTAUX (int)
415
        $sql.= " d.date_debut, d.date_fin, d.date_create, d.tms as date_modif, d.date_valid, d.date_approve,";	// DATES (datetime)
416
        $sql.= " d.fk_user_author, d.fk_user_modif, d.fk_user_validator,";
417
        $sql.= " d.fk_user_valid, d.fk_user_approve,";
418
        $sql.= " d.fk_statut as status, d.fk_c_paiement,";
419
        $sql.= " dp.libelle as libelle_paiement, dp.code as code_paiement";                             // INNER JOIN paiement
420
        $sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element." as d LEFT JOIN ".MAIN_DB_PREFIX."c_paiement as dp ON d.fk_c_paiement = dp.id";
421
        if ($ref) $sql.= " WHERE d.ref = '".$this->db->escape($ref)."'";
422
        else $sql.= " WHERE d.rowid = ".$id;
423
        $sql.= $restrict;
0 ignored issues
show
Bug introduced by
The variable $restrict 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...
424
425
        dol_syslog(get_class($this)."::fetch sql=".$sql, LOG_DEBUG);
426
        $resql = $this->db->query($sql) ;
427
        if ($resql)
428
        {
429
            $obj = $this->db->fetch_object($resql);
430
            if ($obj)
431
            {
432
                $this->id           = $obj->rowid;
433
                $this->ref          = $obj->ref;
434
                $this->total_ht     = $obj->total_ht;
435
                $this->total_tva    = $obj->total_tva;
436
                $this->total_ttc    = $obj->total_ttc;
437
                $this->note_public  = $obj->note_public;
438
                $this->note_private = $obj->note_private;
439
                $this->detail_refuse = $obj->detail_refuse;
440
                $this->detail_cancel = $obj->detail_cancel;
441
442
                $this->date_debut       = $this->db->jdate($obj->date_debut);
443
                $this->date_fin         = $this->db->jdate($obj->date_fin);
444
                $this->date_valid       = $this->db->jdate($obj->date_valid);
445
                $this->date_approve     = $this->db->jdate($obj->date_approve);
446
                $this->date_create      = $this->db->jdate($obj->date_create);
447
                $this->date_modif       = $this->db->jdate($obj->date_modif);
448
                $this->date_refuse      = $this->db->jdate($obj->date_refuse);
449
                $this->date_cancel      = $this->db->jdate($obj->date_cancel);
450
451
                $this->fk_user_author           = $obj->fk_user_author;    // Note fk_user_author is not the 'author' but the guy the expense report is for.
452
                $this->fk_user_modif            = $obj->fk_user_modif;
453
                $this->fk_user_validator        = $obj->fk_user_validator;
454
                $this->fk_user_valid            = $obj->fk_user_valid;
455
                $this->fk_user_refuse           = $obj->fk_user_refuse;
456
                $this->fk_user_cancel           = $obj->fk_user_cancel;
457
                $this->fk_user_approve          = $obj->fk_user_approve;
458
                
459
                $user_author = new User($this->db);
460
                if ($this->fk_user_author > 0) $user_author->fetch($this->fk_user_author);
461
462
                $this->user_author_infos = dolGetFirstLastname($user_author->firstname, $user_author->lastname);
463
464
                $user_approver = new User($this->db);
465
                if ($this->fk_user_validator > 0) $user_approver->fetch($this->fk_user_validator);
466
                $this->user_validator_infos = dolGetFirstLastname($user_approver->firstname, $user_approver->lastname);
467
468
                $this->fk_statut                = $obj->status;
469
                $this->status                   = $obj->status;
470
                $this->fk_c_paiement            = $obj->fk_c_paiement;
471
                $this->paid                     = $obj->paid;
472
473
                if ($this->fk_statut==5 || $this->fk_statut==6)
474
                {
475
                    $user_valid = new User($this->db);
476
                    if ($this->fk_user_valid > 0) $user_valid->fetch($this->fk_user_valid);
477
                    $this->user_valid_infos = dolGetFirstLastname($user_valid->firstname, $user_valid->lastname);
478
                }
479
480
                $this->libelle_statut   = $obj->libelle_statut;
481
                $this->libelle_paiement = $obj->libelle_paiement;
482
                $this->code_statut      = $obj->code_statut;
483
                $this->code_paiement    = $obj->code_paiement;
484
485
                $this->lines = array();
486
487
                $result=$this->fetch_lines();
488
489
                return $result;
490
            }
491
            else
492
            {
493
                return 0;
494
            }
495
        }
496
        else
497
        {
498
            $this->error=$this->db->lasterror();
499
            return -1;
500
        }
501
    }
502
503
    /**
504
     *    Classify the expense report as paid
505
     *
506
     *    @param    int     $id                 Id of expense report
507
     *    @param    user    $fuser              User making change
508
	 *    @param    int     $notrigger          Disable triggers
509
     *    @return   int                         <0 if KO, >0 if OK
510
     */
511
    function set_paid($id, $fuser, $notrigger = 0)
512
    {
513
		$error = 0;
514
		$this->db->begin();
515
		
516
        $sql = "UPDATE ".MAIN_DB_PREFIX."expensereport";
517
        $sql.= " SET fk_statut = 6, paid=1";
518
        $sql.= " WHERE rowid = ".$id." AND fk_statut = 5";
519
520
        dol_syslog(get_class($this)."::set_paid sql=".$sql, LOG_DEBUG);
521
        $resql=$this->db->query($sql);
522
        if ($resql)
523
        {
524
            if ($this->db->affected_rows($resql))
525
            {
526
				if (!$notrigger)
527
				{
528
					// Call trigger
529
					$result=$this->call_trigger('EXPENSE_REPORT_PAID',$fuser);
530
531
					if ($result < 0) {
532
						$error++;
533
					}
534
					// End call triggers
535
				}
536
				
537
				if (empty($error))
538
				{
539
					$this->db->commit();
540
					return 1;
541
				}
542
				else
543
				{
544
					$this->db->rollback();
545
					$this->error=$this->db->error();
546
					return -2;
547
				}
548
            }
549
            else
550
            {
551
				$this->db->commit();
552
                return 0;
553
            }
554
        }
555
        else
556
        {
557
			$this->db->rollback();
558
            dol_print_error($this->db);
559
            return -1;
560
        }
561
    }
562
563
    /**
564
     *  Returns the label status
565
     *
566
     *  @param      int     $mode       0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto
567
     *  @return     string              Label
568
     */
569
    function getLibStatut($mode=0)
570
    {
571
        return $this->LibStatut($this->status,$mode);
572
    }
573
574
    /**
575
     *  Returns the label of a statut
576
     *
577
     *  @param      int     $status     id statut
578
     *  @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
579
     *  @return     string              Label
580
     */
581
    function LibStatut($status,$mode=0)
582
    {
583
        global $langs;
584
585
        if ($mode == 0)
586
            return $langs->transnoentities($this->statuts[$status]);
587
588
        if ($mode == 1)
589
            return $langs->transnoentities($this->statuts_short[$status]);
590
591
        if ($mode == 2)
592
            return img_picto($langs->transnoentities($this->statuts_short[$status]), $this->statuts_logo[$status]).' '.$langs->transnoentities($this->statuts_short[$status]);
593
594
        if ($mode == 3)
595
            return img_picto($langs->transnoentities($this->statuts_short[$status]), $this->statuts_logo[$status]);
596
597
        if ($mode == 4)
598
            return img_picto($langs->transnoentities($this->statuts_short[$status]),$this->statuts_logo[$status]).' '.$langs->transnoentities($this->statuts[$status]);
599
600
        if ($mode == 5)
601
            return '<span class="hideonsmartphone">'.$langs->transnoentities($this->statuts_short[$status]).' </span>'.img_picto($langs->transnoentities($this->statuts_short[$status]),$this->statuts_logo[$status]);
602
603
        if ($mode == 6)
604
            return $langs->transnoentities($this->statuts[$status]).' '.img_picto($langs->transnoentities($this->statuts_short[$status]),$this->statuts_logo[$status]);
605
    }
606
607
608
    /**
609
     *  Load information on object
610
     *
611
     *  @param  int     $id      Id of object
612
     *  @return void
613
     */
614
    function info($id)
615
    {
616
        global $conf;
617
618
        $sql = "SELECT f.rowid,";
619
        $sql.= " f.date_create as datec,";
620
        $sql.= " f.tms as date_modification,";
621
        $sql.= " f.date_valid as datev,";
622
        $sql.= " f.date_approve as datea,";
623
        $sql.= " f.fk_user_author as fk_user_creation,";
624
        $sql.= " f.fk_user_modif as fk_user_modification,";
625
        $sql.= " f.fk_user_valid,";
626
        $sql.= " f.fk_user_approve";
627
        $sql.= " FROM ".MAIN_DB_PREFIX."expensereport as f";
628
        $sql.= " WHERE f.rowid = ".$id;
629
        $sql.= " AND f.entity = ".$conf->entity;
630
631
        $resql = $this->db->query($sql);
632
        if ($resql)
633
        {
634
            if ($this->db->num_rows($resql))
635
            {
636
                $obj = $this->db->fetch_object($resql);
637
638
                $this->id                = $obj->rowid;
639
640
                $this->date_creation     = $this->db->jdate($obj->datec);
641
                $this->date_modification = $this->db->jdate($obj->date_modification);
642
                $this->date_validation   = $this->db->jdate($obj->datev);
643
                $this->date_approbation  = $this->db->jdate($obj->datea);
644
645
                $cuser = new User($this->db);
646
                $cuser->fetch($obj->fk_user_author);
647
                $this->user_creation     = $cuser;
648
649
                if ($obj->fk_user_creation)
650
                {
651
                    $cuser = new User($this->db);
652
                    $cuser->fetch($obj->fk_user_creation);
653
                    $this->user_creation     = $cuser;
654
                }
655
                if ($obj->fk_user_valid)
656
                {
657
                    $vuser = new User($this->db);
658
                    $vuser->fetch($obj->fk_user_valid);
659
                    $this->user_validation     = $vuser;
660
                }
661
                if ($obj->fk_user_modification)
662
                {
663
                    $muser = new User($this->db);
664
                    $muser->fetch($obj->fk_user_modification);
665
                    $this->user_modification   = $muser;
666
                }
667
                if ($obj->fk_user_approve)
668
                {
669
                    $auser = new User($this->db);
670
                    $auser->fetch($obj->fk_user_approve);
671
                    $this->user_approve   = $auser;
672
                }
673
                
674
            }
675
            $this->db->free($resql);
676
        }
677
        else
678
        {
679
            dol_print_error($this->db);
680
        }
681
    }
682
683
684
685
    /**
686
     *  Initialise an instance with random values.
687
     *  Used to build previews or test instances.
688
     *  id must be 0 if object instance is a specimen.
689
     *
690
     *  @return void
691
     */
692
    function initAsSpecimen()
693
    {
694
        global $user,$langs,$conf;
695
696
        $now=dol_now();
697
698
        // Initialise parametres
699
        $this->id=0;
700
        $this->ref = 'SPECIMEN';
701
        $this->specimen=1;
702
        $this->date_create = $now;
703
        $this->date_debut = $now;
704
        $this->date_fin = $now;
705
        $this->date_approve = $now;
706
707
        $type_fees_id = 2;  // TF_TRIP 
708
        
709
        $this->status = 5;
710
        $this->fk_statut = 5;
711
712
        $this->fk_user_author = $user->id;
713
        $this->fk_user_valid = $user->id;
714
        $this->fk_user_approve = $user->id;
715
        $this->fk_user_validator = $user->id;
716
717
        $this->note_private='Private note';
718
        $this->note_public='SPECIMEN';
719
        $nbp = 5;
720
        $xnbp = 0;
721
        while ($xnbp < $nbp)
722
        {
723
            $line=new ExpenseReportLine($this->db);
724
            $line->comments=$langs->trans("Comment")." ".$xnbp;
725
            $line->date=($now-3600*(1+$xnbp));
726
            $line->total_ht=100;
727
            $line->total_tva=20;
728
            $line->total_ttc=120;
729
            $line->qty=1;
730
            $line->vatrate=20;
731
            $line->value_unit=120;
732
            $line->fk_expensereport=0;
733
            $line->type_fees_code='TRA';
734
            $line->fk_c_type_fees=$type_fees_id;
735
736
            $line->projet_ref = 'ABC';
737
738
            $this->lines[$xnbp]=$line;
739
            $xnbp++;
740
741
            $this->total_ht+=$line->total_ht;
742
            $this->total_tva+=$line->total_tva;
743
            $this->total_ttc+=$line->total_ttc;
744
        }
745
    }
746
747
    /**
748
     * fetch_line_by_project
749
     *
750
     * @param   int     $projectid      Project id
751
     * @param   User    $user           User
752
     * @return  int                     <0 if KO, >0 if OK
753
     */
754
    function fetch_line_by_project($projectid,$user='')
755
    {
756
        global $conf,$db,$langs;
757
758
        $langs->load('trips');
759
760
        if ($user->rights->expensereport->lire) {
761
762
            $sql = "SELECT de.fk_expensereport, de.date, de.comments, de.total_ht, de.total_ttc";
763
            $sql.= " FROM ".MAIN_DB_PREFIX."expensereport_det as de";
764
            $sql.= " WHERE de.fk_projet = ".$projectid;
765
766
            dol_syslog(get_class($this)."::fetch sql=".$sql, LOG_DEBUG);
767
            $result = $db->query($sql) ;
768
            if ($result)
769
            {
770
                $num = $db->num_rows($result);
771
                $i = 0;
772
                $total_HT = 0;
773
                $total_TTC = 0;
774
775
                while ($i < $num)
776
                {
777
778
                    $objp = $db->fetch_object($result);
779
780
                    $sql2 = "SELECT d.rowid, d.fk_user_author, d.ref, d.fk_statut";
781
                    $sql2.= " FROM ".MAIN_DB_PREFIX."expensereport as d";
782
                    $sql2.= " WHERE d.rowid = '".$objp->fk_expensereport."'";
783
784
                    $result2 = $db->query($sql2);
785
                    $obj = $db->fetch_object($result2);
786
787
                    $objp->fk_user_author = $obj->fk_user_author;
788
                    $objp->ref = $obj->ref;
789
                    $objp->fk_c_expensereport_status = $obj->fk_statut;
790
                    $objp->rowid = $obj->rowid;
791
792
                    $total_HT = $total_HT + $objp->total_ht;
793
                    $total_TTC = $total_TTC + $objp->total_ttc;
794
                    $author = new User($db);
795
                    $author->fetch($objp->fk_user_author);
796
797
                    print '<tr>';
798
                    print '<td><a href="'.DOL_URL_ROOT.'/expensereport/card.php?id='.$objp->rowid.'">'.$objp->ref_num.'</a></td>';
799
                    print '<td align="center">'.dol_print_date($objp->date,'day').'</td>';
800
                    print '<td>'.$author->getNomUrl().'</td>';
801
                    print '<td>'.$objp->comments.'</td>';
802
                    print '<td align="right">'.price($objp->total_ht).'</td>';
803
                    print '<td align="right">'.price($objp->total_ttc).'</td>';
804
                    print '<td align="right">';
805
806
                    switch($objp->fk_c_expensereport_status) {
807
                        case 4:
808
                            print img_picto($langs->trans('StatusOrderCanceled'),'statut5');
809
                            break;
810
                        case 1:
811
                            print $langs->trans('Draft').' '.img_picto($langs->trans('Draft'),'statut0');
812
                            break;
813
                        case 2:
814
                            print $langs->trans('TripForValid').' '.img_picto($langs->trans('TripForValid'),'statut3');
815
                            break;
816
                        case 5:
817
                            print $langs->trans('TripForPaid').' '.img_picto($langs->trans('TripForPaid'),'statut3');
818
                            break;
819
                        case 6:
820
                            print $langs->trans('TripPaid').' '.img_picto($langs->trans('TripPaid'),'statut4');
821
                            break;
822
                    }
823
                    /*
824
                     if ($status==4) return img_picto($langs->trans('StatusOrderCanceled'),'statut5');
825
                    if ($status==1) return img_picto($langs->trans('StatusOrderDraft'),'statut0');
826
                    if ($status==2) return img_picto($langs->trans('StatusOrderValidated'),'statut1');
827
                    if ($status==2) return img_picto($langs->trans('StatusOrderOnProcess'),'statut3');
828
                    if ($status==5) return img_picto($langs->trans('StatusOrderToBill'),'statut4');
829
                    if ($status==6) return img_picto($langs->trans('StatusOrderOnProcess'),'statut6');
830
                    */
831
                    print '</td>';
832
                    print '</tr>';
833
834
                    $i++;
835
                }
836
837
                print '<tr class="liste_total"><td colspan="4">'.$langs->trans("Number").': '.$i.'</td>';
838
                print '<td align="right" width="100">'.$langs->trans("TotalHT").' : '.price($total_HT).'</td>';
839
                print '<td align="right" width="100">'.$langs->trans("TotalTTC").' : '.price($total_TTC).'</td>';
840
                print '<td>&nbsp;</td>';
841
                print '</tr>';
842
843
            }
844
            else
845
            {
846
                $this->error=$db->lasterror();
847
                return -1;
848
            }
849
        }
850
851
    }
852
853
    /**
854
     * recalculer
855
     * TODO Replace this with call to update_price if not already done
856
     *
857
     * @param   int         $id     Id of expense report
858
     * @return  int                 <0 if KO, >0 if OK
859
     */
860
    function recalculer($id)
861
    {
862
        $sql = 'SELECT tt.total_ht, tt.total_ttc, tt.total_tva';
863
        $sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element_line.' as tt';
864
        $sql.= ' WHERE tt.'.$this->fk_element.' = '.$id;
865
866
        $total_ht = 0; $total_tva = 0; $total_ttc = 0;
867
868
        $result = $this->db->query($sql);
869
        if($result)
870
        {
871
            $num = $this->db->num_rows($result);
872
            $i = 0;
873
            while ($i < $num):
874
            $objp = $this->db->fetch_object($result);
875
            $total_ht+=$objp->total_ht;
876
            $total_tva+=$objp->total_tva;
877
            $i++;
878
            endwhile;
879
880
            $total_ttc = $total_ht + $total_tva;
881
            $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET";
882
            $sql.= " total_ht = ".$total_ht;
883
            $sql.= " , total_ttc = ".$total_ttc;
884
            $sql.= " , total_tva = ".$total_tva;
885
            $sql.= " WHERE rowid = ".$id;
886
            $result = $this->db->query($sql);
887
            if($result):
888
            $this->db->free($result);
889
            return 1;
890
            else:
891
            $this->error=$this->db->lasterror();
892
            dol_syslog(get_class($this)."::recalculer: Error ".$this->error,LOG_ERR);
893
            return -3;
894
            endif;
895
        }
896
        else
897
        {
898
            $this->error=$this->db->lasterror();
899
            dol_syslog(get_class($this)."::recalculer: Error ".$this->error,LOG_ERR);
900
            return -3;
901
        }
902
    }
903
904
    /**
905
     * fetch_lines
906
     *
907
     * @return  int     <0 if OK, >0 if KO
908
     */
909
    function fetch_lines()
910
    {
911
        $this->lines=array();
912
913
        $sql = ' SELECT de.rowid, de.comments, de.qty, de.value_unit, de.date,';
914
        $sql.= ' de.'.$this->fk_element.', de.fk_c_type_fees, de.fk_projet, de.tva_tx,';
915
        $sql.= ' de.total_ht, de.total_tva, de.total_ttc,';
916
        $sql.= ' ctf.code as code_type_fees, ctf.label as libelle_type_fees,';
917
        $sql.= ' p.ref as ref_projet, p.title as title_projet';
918
        $sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element_line.' as de';
919
        $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_type_fees as ctf ON de.fk_c_type_fees = ctf.id';
920
        $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'projet as p ON de.fk_projet = p.rowid';
921
        $sql.= ' WHERE de.'.$this->fk_element.' = '.$this->id;
922
		$sql.= ' ORDER BY de.date ASC';
923
924
        $resql = $this->db->query($sql);
925
        if ($resql)
926
        {
927
            $num = $this->db->num_rows($resql);
928
            $i = 0;
929
            while ($i < $num)
930
            {
931
                $objp = $this->db->fetch_object($resql);
932
933
                $deplig = new ExpenseReportLine($this->db);
934
935
                $deplig->rowid          = $objp->rowid;
936
                $deplig->comments       = $objp->comments;
937
                $deplig->qty            = $objp->qty;
938
                $deplig->value_unit     = $objp->value_unit;
939
                $deplig->date           = $objp->date;
940
941
                $deplig->fk_expensereport = $objp->fk_expensereport;
942
                $deplig->fk_c_type_fees = $objp->fk_c_type_fees;
943
                $deplig->fk_projet      = $objp->fk_projet;
944
945
                $deplig->total_ht       = $objp->total_ht;
946
                $deplig->total_tva      = $objp->total_tva;
947
                $deplig->total_ttc      = $objp->total_ttc;
948
949
                $deplig->type_fees_code     = empty($objp->code_type_fees)?'TF_OTHER':$objp->code_type_fees;
950
                $deplig->type_fees_libelle  = $objp->libelle_type_fees;
951
				$deplig->tva_tx			    = $objp->tva_tx;
952
                $deplig->vatrate            = $objp->tva_tx;
953
                $deplig->projet_ref         = $objp->ref_projet;
954
                $deplig->projet_title       = $objp->title_projet;
955
956
                $this->lines[$i] = $deplig;
957
958
                $i++;
959
            }
960
            $this->db->free($resql);
961
            return 1;
962
        }
963
        else
964
        {
965
            $this->error=$this->db->lasterror();
966
            dol_syslog(get_class($this)."::fetch_lines: Error ".$this->error, LOG_ERR);
967
            return -3;
968
        }
969
    }
970
971
972
    /**
973
     * delete
974
     *
975
     * @param   User    $fuser      User that delete
976
     * @return  int                 <0 if KO, >0 if OK
977
     */
978
    function delete(User $fuser=null)
979
    {
980
        global $user,$langs,$conf;
981
982
        if (! $rowid) $rowid=$this->id;
0 ignored issues
show
Bug introduced by
The variable $rowid seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
983
984
        $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element_line.' WHERE '.$this->fk_element.' = '.$rowid;
0 ignored issues
show
Bug introduced by
The variable $rowid 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...
985
        if ($this->db->query($sql))
986
        {
987
            $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.' WHERE rowid = '.$rowid;
988
            $resql=$this->db->query($sql);
989
            if ($resql)
990
            {
991
                $this->db->commit();
992
                return 1;
993
            }
994
            else
995
            {
996
                $this->error=$this->db->error()." sql=".$sql;
997
                dol_syslog(get_class($this)."::delete ".$this->error, LOG_ERR);
998
                $this->db->rollback();
999
                return -6;
1000
            }
1001
        }
1002
        else
1003
        {
1004
            $this->error=$this->db->error()." sql=".$sql;
1005
            dol_syslog(get_class($this)."::delete ".$this->error, LOG_ERR);
1006
            $this->db->rollback();
1007
            return -4;
1008
        }
1009
    }
1010
1011
    /**
1012
     * Set to status validate
1013
     *
1014
     * @param   User    $fuser      User
1015
	 * @param   int     $notrigger  Disable triggers
1016
     * @return  int                 <0 if KO, 0 if nothing done, >0 if OK
1017
     */
1018
    function setValidate($fuser, $notrigger=0)
1019
    {
1020
        global $conf,$langs;
1021
1022
		$error = 0;
1023
        $this->oldref = $this->ref;
1024
        $expld_car = (empty($conf->global->NDF_EXPLODE_CHAR))?"-":$conf->global->NDF_EXPLODE_CHAR;
1025
1026
        // Sélection de la date de début de la NDF
1027
        $sql = 'SELECT date_debut';
1028
        $sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element;
1029
        $sql.= ' WHERE rowid = '.$this->id;
1030
        $result = $this->db->query($sql);
1031
        $objp = $this->db->fetch_object($result);
1032
        $this->date_debut = $this->db->jdate($objp->date_debut);
1033
1034
        $update_number_int = false;
1035
1036
        // Create next ref if ref is PROVxx
1037
        // Rename directory if dir was a temporary ref
1038
        if (preg_match('/^[\(]?PROV/i', $this->ref))
1039
        {
1040
            // Sélection du numéro de ref suivant
1041
            $ref_next = $this->getNextNumRef();
1042
            $ref_number_int = ($this->ref+1)-1;
1043
            $update_number_int = true;
1044
            // Création du ref_number suivant
1045
            if($ref_next)
1046
            {
1047
                $prefix="ER";
1048
                if (! empty($conf->global->EXPENSE_REPORT_PREFIX)) $prefix=$conf->global->EXPENSE_REPORT_PREFIX;
1049
                $this->ref = str_replace(' ','_', $this->user_author_infos).$expld_car.$prefix.$this->ref.$expld_car.dol_print_date($this->date_debut,'%y%m%d');
1050
            }
1051
            require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1052
            // We rename directory in order to avoid losing the attachments
1053
            $oldref = dol_sanitizeFileName($this->oldref);
1054
            $newref = dol_sanitizeFileName($this->ref);
1055
            $dirsource = $conf->expensereport->dir_output.'/'.$oldref;
1056
            $dirdest = $conf->expensereport->dir_output.'/'.$newref;
1057
            if (file_exists($dirsource))
1058
            {
1059
                dol_syslog(get_class($this)."::setValidate() rename dir ".$dirsource." into ".$dirdest);
1060
1061
                if (@rename($dirsource, $dirdest))
1062
                {
1063
                    dol_syslog("Rename ok");
1064
                    // Rename docs starting with $oldref with $newref
1065
                    $listoffiles=dol_dir_list($conf->expensereport->dir_output.'/'.$newref, 'files', 1, '^'.preg_quote($oldref,'/'));
1066
                    foreach($listoffiles as $fileentry)
1067
                    {
1068
                        $dirsource=$fileentry['name'];
1069
                        $dirdest=preg_replace('/^'.preg_quote($oldref,'/').'/',$newref, $dirsource);
1070
                        $dirsource=$fileentry['path'].'/'.$dirsource;
1071
                        $dirdest=$fileentry['path'].'/'.$dirdest;
1072
                        @rename($dirsource, $dirdest);
1073
                    }
1074
                }
1075
            }
1076
        }
1077
        if ($this->fk_statut != 2)
1078
        {
1079
        	$now = dol_now();
1080
			$this->db->begin();
1081
			
1082
            $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
1083
            $sql.= " SET ref = '".$this->db->escape($this->ref)."', fk_statut = 2, fk_user_valid = ".$fuser->id.", date_valid='".$this->db->idate($now)."'";
1084
            if ($update_number_int) {
1085
                $sql.= ", ref_number_int = ".$ref_number_int;
0 ignored issues
show
Bug introduced by
The variable $ref_number_int 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
            $sql.= ' WHERE rowid = '.$this->id;
1088
            
1089
            $resql=$this->db->query($sql);
1090
            if ($resql)
1091
            {
1092
				if (!$notrigger)
1093
				{
1094
					// Call trigger
1095
					$result=$this->call_trigger('EXPENSE_REPORT_VALIDATE',$fuser);
1096
1097
					if ($result < 0) {
1098
						$error++;
1099
					}
1100
					// End call triggers
1101
				}
1102
				
1103
				if (empty($error))
1104
				{
1105
					$this->db->commit();
1106
					return 1;
1107
				}
1108
				else
1109
				{
1110
					$this->db->rollback();
1111
					$this->error=$this->db->error();
1112
					return -2;
1113
				}
1114
            }
1115
            else
1116
            {
1117
				$this->db->rollback();
1118
                $this->error=$this->db->lasterror();
1119
                return -1;
1120
            }
1121
        }
1122
        else
1123
        {
1124
            dol_syslog(get_class($this)."::setValidate expensereport already with validated status", LOG_WARNING);
1125
        }
1126
        
1127
        return 0;
1128
    }
1129
1130
    /**
1131
     * set_save_from_refuse
1132
     *
1133
     * @param   User    $fuser      User
1134
     * @return  int                 <0 if KO, >0 if OK
1135
     */
1136
    function set_save_from_refuse($fuser)
1137
    {
1138
        global $conf,$langs;
1139
1140
        // Sélection de la date de début de la NDF
1141
        $sql = 'SELECT date_debut';
1142
        $sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element;
1143
        $sql.= ' WHERE rowid = '.$this->id;
1144
1145
        $result = $this->db->query($sql);
1146
1147
        $objp = $this->db->fetch_object($result);
1148
1149
        $this->date_debut = $this->db->jdate($objp->date_debut);
1150
1151
        if ($this->fk_statut != 2)
1152
        {
1153
            $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
1154
            $sql.= " SET fk_statut = 2";
1155
            $sql.= ' WHERE rowid = '.$this->id;
1156
1157
            dol_syslog(get_class($this)."::set_save_from_refuse sql=".$sql, LOG_DEBUG);
1158
1159
            if ($this->db->query($sql))
1160
            {
1161
                return 1;
1162
            }
1163
            else
1164
            {
1165
                $this->error=$this->db->lasterror();
1166
                return -1;
1167
            }
1168
        }
1169
        else
1170
        {
1171
            dol_syslog(get_class($this)."::set_save_from_refuse expensereport already with save status", LOG_WARNING);
1172
        }
1173
    }
1174
1175
    /**
1176
     * Set status to approved
1177
     *
1178
     * @param   User    $fuser      User
1179
	 * @param   int     $notrigger  Disable triggers
1180
     * @return  int                 <0 if KO, 0 if nothing done, >0 if OK
1181
     */
1182
    function setApproved($fuser, $notrigger=0)
1183
    {
1184
        $now=dol_now();
1185
		$error = 0;
1186
		
1187
        // date approval
1188
        $this->date_approve = $this->db->idate($now);
1189
        if ($this->fk_statut != 5)
1190
        {
1191
			$this->db->begin();
1192
			
1193
            $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
1194
            $sql.= " SET ref = '".$this->db->escape($this->ref)."', fk_statut = 5, fk_user_approve = ".$fuser->id.",";
1195
            $sql.= " date_approve='".$this->db->idate($this->date_approve)."'";
1196
            $sql.= ' WHERE rowid = '.$this->id;
1197
            if ($this->db->query($sql))
1198
            {
1199
                if (!$notrigger)
1200
				{
1201
					// Call trigger
1202
					$result=$this->call_trigger('EXPENSE_REPORT_APPROVE',$fuser);
1203
1204
					if ($result < 0) {
1205
						$error++;
1206
					}
1207
					// End call triggers
1208
				}
1209
				
1210
				if (empty($error))
1211
				{
1212
					$this->db->commit();
1213
					return 1;
1214
				}
1215
				else
1216
				{
1217
					$this->db->rollback();
1218
					$this->error=$this->db->error();
1219
					return -2;
1220
				}
1221
            }
1222
            else
1223
            {
1224
				$this->db->rollback();
1225
                $this->error=$this->db->lasterror();
1226
                return -1;
1227
            }
1228
        }
1229
        else
1230
        {
1231
            dol_syslog(get_class($this)."::setApproved expensereport already with approve status", LOG_WARNING);
1232
        }
1233
        
1234
        return 0;
1235
    }
1236
1237
    /**
1238
     * setDeny
1239
     *
1240
     * @param User      $fuser      User
1241
     * @param Details   $details    Details
1242
	 * @param int       $notrigger  Disable triggers
1243
     */
1244
    function setDeny($fuser,$details,$notrigger=0)
1245
    {
1246
        $now = dol_now();
1247
		$error = 0;
1248
		
1249
        // date de refus
1250
        if ($this->fk_statut != 99)
1251
        {
1252
            $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
1253
            $sql.= " SET ref = '".$this->db->escape($this->ref)."', fk_statut = 99, fk_user_refuse = ".$fuser->id.",";
1254
            $sql.= " date_refuse='".$this->db->idate($now)."',";
1255
            $sql.= " detail_refuse='".$this->db->escape($details)."',";
1256
            $sql.= " fk_user_approve = NULL";
1257
            $sql.= ' WHERE rowid = '.$this->id;
1258
            if ($this->db->query($sql))
1259
            {
1260
                $this->fk_statut = 99;
1261
                $this->fk_user_refuse = $fuser->id;
1262
                $this->detail_refuse = $details;
1263
                $this->date_refuse = $now;
1264
                
1265
				if (!$notrigger)
1266
				{
1267
					// Call trigger
1268
					$result=$this->call_trigger('EXPENSE_REPORT_DENY',$fuser);
1269
1270
					if ($result < 0) {
1271
						$error++;
1272
					}
1273
					// End call triggers
1274
				}
1275
				
1276
				if (empty($error))
1277
				{
1278
					$this->db->commit();
1279
					return 1;
1280
				}
1281
				else
1282
				{
1283
					$this->db->rollback();
1284
					$this->error=$this->db->error();
1285
					return -2;
1286
				}
1287
            }
1288
            else
1289
            {
1290
				$this->db->rollback();
1291
                $this->error=$this->db->lasterror();
1292
                return -1;
1293
            }
1294
        }
1295
        else
1296
        {
1297
            dol_syslog(get_class($this)."::setDeny expensereport already with refuse status", LOG_WARNING);
1298
        }
1299
    }
1300
1301
    /**
1302
     * set_unpaid
1303
     *
1304
     * @param   User    $fuser      User
1305
	 * @param   int     $notrigger  Disable triggers
1306
     * @return  int                 <0 if KO, >0 if OK
1307
     */
1308
    function set_unpaid($fuser, $notrigger = 0)
1309
    {
1310
		$error = 0;
1311
		
1312
        if ($this->fk_c_deplacement_statuts != 5)
1313
        {
1314
			$this->db->begin();
1315
			
1316
            $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
1317
            $sql.= " SET fk_statut = 5";
1318
            $sql.= ' WHERE rowid = '.$this->id;
1319
1320
            dol_syslog(get_class($this)."::set_unpaid sql=".$sql, LOG_DEBUG);
1321
1322
			if ($this->db->query($sql))
1323
			{
1324
				if (!$notrigger)
1325
				{
1326
					// Call trigger
1327
					$result=$this->call_trigger('EXPENSE_REPORT_UNPAID',$fuser);
1328
1329
					if ($result < 0) {
1330
						$error++;
1331
					}
1332
					// End call triggers
1333
				}
1334
				
1335
				if (empty($error))
1336
				{
1337
					$this->db->commit();
1338
					return 1;
1339
				}
1340
				else
1341
				{
1342
					$this->db->rollback();
1343
					$this->error=$this->db->error();
1344
					return -2;
1345
				}
1346
			}
1347
			else
1348
			{
1349
				$this->db->rollback();
1350
				$this->error=$this->db->error();
1351
				return -1;
1352
			}
1353
        }
1354
        else
1355
        {
1356
            dol_syslog(get_class($this)."::set_unpaid expensereport already with unpaid status", LOG_WARNING);
1357
        }
1358
    }
1359
1360
    /**
1361
     * set_cancel
1362
     *
1363
     * @param   User    $fuser      User
1364
     * @param   string  $detail     Detail
1365
	 * @param   int     $notrigger  Disable triggers
1366
     * @return  int                 <0 if KO, >0 if OK
1367
     */
1368
    function set_cancel($fuser,$detail, $notrigger=0)
1369
    {
1370
		$error = 0;
1371
        $this->date_cancel = $this->db->idate(gmmktime());
1372
        if ($this->fk_statut != 4)
1373
        {
1374
			$this->db->begin();
1375
			
1376
            $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
1377
            $sql.= " SET fk_statut = 4, fk_user_cancel = ".$fuser->id;
1378
            $sql.= ", date_cancel='".$this->db->idate($this->date_cancel)."'";
1379
            $sql.= " ,detail_cancel='".$this->db->escape($detail)."'";
1380
            $sql.= ' WHERE rowid = '.$this->id;
1381
1382
            dol_syslog(get_class($this)."::set_cancel sql=".$sql, LOG_DEBUG);
1383
1384
            if ($this->db->query($sql))
1385
            {
1386
				if (!$notrigger)
1387
				{
1388
					// Call trigger
1389
					$result=$this->call_trigger('EXPENSE_REPORT_CANCEL',$fuser);
1390
1391
					if ($result < 0) {
1392
						$error++;
1393
					}
1394
					// End call triggers
1395
				}
1396
				
1397
				if (empty($error))
1398
				{
1399
					$this->db->commit();
1400
					return 1;
1401
				}
1402
				else
1403
				{
1404
					$this->db->rollback();
1405
					$this->error=$this->db->error();
1406
					return -2;
1407
				}
1408
            }
1409
            else
1410
            {
1411
				$this->db->rollback();
1412
                $this->error=$this->db->error();
1413
                return -1;
1414
            }
1415
        }
1416
        else
1417
        {
1418
            dol_syslog(get_class($this)."::set_cancel expensereport already with cancel status", LOG_WARNING);
1419
        }
1420
    }
1421
1422
    /**
1423
     * Return next reference of expense report not already used
1424
     *
1425
     * @return    string            free ref
1426
     */
1427
    function getNextNumRef()
1428
    {
1429
        global $conf;
1430
1431
        $expld_car = (empty($conf->global->NDF_EXPLODE_CHAR))?"-":$conf->global->NDF_EXPLODE_CHAR;
1432
        $num_car = (empty($conf->global->NDF_NUM_CAR_REF))?"5":$conf->global->NDF_NUM_CAR_REF;
1433
1434
        $sql = 'SELECT MAX(de.ref_number_int) as max';
1435
        $sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' de';
1436
        
1437
        $result = $this->db->query($sql);
1438
1439
        if($this->db->num_rows($result) > 0):
1440
        $objp = $this->db->fetch_object($result);
1441
        $this->ref = $objp->max;
1442
        $this->ref++;
1443
        while(strlen($this->ref) < $num_car):
1444
        $this->ref = "0".$this->ref;
1445
        endwhile;
1446
        else:
1447
        $this->ref = 1;
0 ignored issues
show
Documentation Bug introduced by
The property $ref was declared of type string, but 1 is of type integer. Maybe add a type cast?

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

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

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
1448
        while(strlen($this->ref) < $num_car):
1449
        $this->ref = "0".$this->ref;
1450
        endwhile;
1451
        endif;
1452
1453
        if ($result):
1454
        return 1;
1455
        else:
1456
        $this->error=$this->db->error();
1457
        return -1;
1458
        endif;
1459
    }
1460
1461
    /**
1462
     *  Return clicable name (with picto eventually)
1463
     *
1464
     *	@param		int		$withpicto		0=No picto, 1=Include picto into link, 2=Only picto
1465
     *	@param		int		$max			Max length of shown ref
1466
     *	@param		int		$short			1=Return just URL
1467
     *	@param		string	$moretitle		Add more text to title tooltip
1468
     *	@param		int		$notooltip		1=Disable tooltip
1469
     *	@return		string					String with URL
1470
     */
1471
    function getNomUrl($withpicto=0,$max=0,$short=0,$moretitle='',$notooltip=0)
1472
    {
1473
        global $langs, $conf;
1474
1475
        $result='';
1476
1477
        $url = DOL_URL_ROOT.'/expensereport/card.php?id='.$this->id;
1478
1479
        if ($short) return $url;
1480
1481
        $picto='trip';
1482
        $label = '<u>' . $langs->trans("ShowExpenseReport") . '</u>';
1483
        if (! empty($this->ref))
1484
            $label .= '<br><b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
1485
        if (! empty($this->total_ht))
1486
            $label.= '<br><b>' . $langs->trans('AmountHT') . ':</b> ' . price($this->total_ht, 0, $langs, 0, -1, -1, $conf->currency);
1487
        if (! empty($this->total_tva))
1488
            $label.= '<br><b>' . $langs->trans('VAT') . ':</b> ' . price($this->total_tva, 0, $langs, 0, -1, -1, $conf->currency);
1489
        if (! empty($this->total_ttc))
1490
            $label.= '<br><b>' . $langs->trans('AmountTTC') . ':</b> ' . price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency);
1491
        if ($moretitle) $label.=' - '.$moretitle;
1492
1493
        $ref=$this->ref;
1494
        if (empty($ref)) $ref=$this->id;
1495
1496
        $linkclose='';
1497
        if (empty($notooltip))
1498
        {
1499
            if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
1500
            {
1501
                $label=$langs->trans("ShowExpenseReport");
1502
                $linkclose.=' alt="'.dol_escape_htmltag($label, 1).'"';
1503
            }
1504
            $linkclose.= ' title="'.dol_escape_htmltag($label, 1).'"';
1505
            $linkclose.=' class="classfortooltip"';
1506
        }
1507
1508
        $linkstart = '<a href="'.$url.'"';
1509
        $linkstart.=$linkclose.'>';
1510
        $linkend='</a>';
1511
1512
        if ($withpicto) $result.=($linkstart.img_object(($notooltip?'':$label), $picto, ($notooltip?'':'class="classfortooltip"'), 0, 0, $notooltip?0:1).$linkend.' ');
1513
        $result.=$linkstart.($max?dol_trunc($ref,$max):$ref).$linkend;
1514
        return $result;
1515
    }
1516
1517
    /**
1518
     *  Update total of an expense report when you add a line.
1519
     *
1520
     *  @param    string    $ligne_total_ht    Amount without taxes
1521
     *  @param    string    $ligne_total_tva    Amount of all taxes
1522
     *  @return    void
1523
     */
1524
    function update_totaux_add($ligne_total_ht,$ligne_total_tva)
1525
    {
1526
        $this->total_ht = $this->total_ht + $ligne_total_ht;
1527
        $this->total_tva = $this->total_tva + $ligne_total_tva;
1528
        $this->total_ttc = $this->total_ht + $this->total_tva;
1529
1530
        $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET";
1531
        $sql.= " total_ht = ".$this->total_ht;
1532
        $sql.= " , total_ttc = ".$this->total_ttc;
1533
        $sql.= " , total_tva = ".$this->total_tva;
1534
        $sql.= " WHERE rowid = ".$this->id;
1535
1536
        $result = $this->db->query($sql);
1537
        if ($result):
1538
        return 1;
1539
        else:
1540
        $this->error=$this->db->error();
1541
        return -1;
1542
        endif;
1543
    }
1544
1545
    /**
1546
     *  Update total of an expense report when you delete a line.
1547
     *
1548
     *  @param    string    $ligne_total_ht    Amount without taxes
1549
     *  @param    string    $ligne_total_tva    Amount of all taxes
1550
     *  @return    void
1551
     */
1552
    function update_totaux_del($ligne_total_ht,$ligne_total_tva)
1553
    {
1554
        $this->total_ht = $this->total_ht - $ligne_total_ht;
1555
        $this->total_tva = $this->total_tva - $ligne_total_tva;
1556
        $this->total_ttc = $this->total_ht + $this->total_tva;
1557
1558
        $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET";
1559
        $sql.= " total_ht = ".$this->total_ht;
1560
        $sql.= " , total_ttc = ".$this->total_ttc;
1561
        $sql.= " , total_tva = ".$this->total_tva;
1562
        $sql.= " WHERE rowid = ".$this->id;
1563
1564
        $result = $this->db->query($sql);
1565
        if ($result):
1566
        return 1;
1567
        else:
1568
        $this->error=$this->db->error();
1569
        return -1;
1570
        endif;
1571
    }
1572
1573
1574
    /**
1575
     * updateline
1576
     *
1577
     * @param   int         $rowid                  Line to edit
1578
     * @param   int         $type_fees_id           Type payment
1579
     * @param   int         $projet_id              Project id
1580
     * @param   double      $vatrate                Vat rate
1581
     * @param   string      $comments               Description
1582
     * @param   real        $qty                    Qty
1583
     * @param   double      $value_unit             Value init
1584
     * @param   int         $date                   Date
1585
     * @param   int         $expensereport_id       Expense report id
1586
     * @return  int                                 <0 if KO, >0 if OK
1587
     */
1588
    function updateline($rowid, $type_fees_id, $projet_id, $vatrate, $comments, $qty, $value_unit, $date, $expensereport_id)
1589
    {
1590
        global $user;
1591
1592
        if ($this->fk_statut==0 || $this->fk_statut==99)
1593
        {
1594
            $this->db->begin();
1595
1596
            // calcul de tous les totaux de la ligne
1597
            $total_ttc  = price2num($qty*$value_unit, 'MT');
1598
1599
            $tx_tva = $vatrate / 100;
1600
            $tx_tva = $tx_tva + 1;
1601
            $total_ht   = price2num($total_ttc/$tx_tva, 'MT');
1602
1603
            $total_tva = price2num($total_ttc - $total_ht, 'MT');
1604
            // fin calculs
1605
1606
            $ligne = new ExpenseReportLine($this->db);
1607
            $ligne->comments        = $comments;
1608
            $ligne->qty             = $qty;
1609
            $ligne->value_unit      = $value_unit;
1610
            $ligne->date            = $date;
1611
1612
            $ligne->fk_expensereport= $expensereport_id;
1613
            $ligne->fk_c_type_fees  = $type_fees_id;
1614
            $ligne->fk_projet       = $projet_id;
1615
1616
            $ligne->total_ht        = $total_ht;
1617
            $ligne->total_tva       = $total_tva;
1618
            $ligne->total_ttc       = $total_ttc;
1619
            $ligne->vatrate         = price2num($vatrate);
1620
            $ligne->rowid           = $rowid;
1621
1622
            // Select des infos sur le type fees
1623
            $sql = "SELECT c.code as code_type_fees, c.label as libelle_type_fees";
1624
            $sql.= " FROM ".MAIN_DB_PREFIX."c_type_fees as c";
1625
            $sql.= " WHERE c.id = ".$type_fees_id;
1626
            $result = $this->db->query($sql);
1627
            $objp_fees = $this->db->fetch_object($result);
1628
            $ligne->type_fees_code      = $objp_fees->code_type_fees;
1629
            $ligne->type_fees_libelle   = $objp_fees->libelle_type_fees;
1630
1631
            // Select des informations du projet
1632
            $sql = "SELECT p.ref as ref_projet, p.title as title_projet";
1633
            $sql.= " FROM ".MAIN_DB_PREFIX."projet as p";
1634
            $sql.= " WHERE p.rowid = ".$projet_id;
1635
            $result = $this->db->query($sql);
1636
            if ($result) {
1637
            	$objp_projet = $this->db->fetch_object($result);
1638
            }
1639
            $ligne->projet_ref          = $objp_projet->ref_projet;
0 ignored issues
show
Bug introduced by
The variable $objp_projet 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...
1640
            $ligne->projet_title        = $objp_projet->title_projet;
1641
1642
            $result = $ligne->update($user);
1643
            if ($result > 0)
1644
            {
1645
                $this->db->commit();
1646
                return 1;
1647
            }
1648
            else
1649
            {
1650
                $this->error=$ligne->error;
1651
                $this->errors=$ligne->errors;
1652
                $this->db->rollback();
1653
                return -2;
1654
            }
1655
        }
1656
    }
1657
1658
    /**
1659
     * deleteline
1660
     *
1661
     * @param   int     $rowid      Row id
1662
     * @param   User    $fuser      User
1663
     * @return  int                 <0 if KO, >0 if OK
1664
     */
1665
    function deleteline($rowid, $fuser='')
1666
    {
1667
        $this->db->begin();
1668
1669
        $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element_line;
1670
        $sql.= ' WHERE rowid = '.$rowid;
1671
1672
        dol_syslog(get_class($this)."::deleteline sql=".$sql);
1673
        $result = $this->db->query($sql);
1674
        if (!$result)
1675
        {
1676
            $this->error=$this->db->error();
1677
            dol_syslog(get_class($this)."::deleteline  Error ".$this->error, LOG_ERR);
1678
            $this->db->rollback();
1679
            return -1;
1680
        }
1681
1682
        $this->db->commit();
1683
1684
        return 1;
1685
    }
1686
1687
    /**
1688
     * periode_existe
1689
     *
1690
     * @param   User    $fuser          User
1691
     * @param   Date    $date_debut     Start date
1692
     * @param   Date    $date_fin       End date
1693
     * @return  int                     <0 if KO, >0 if OK
1694
     */
1695
    function periode_existe($fuser, $date_debut, $date_fin)
1696
    {
1697
        $sql = "SELECT rowid, date_debut, date_fin";
1698
        $sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element;
1699
        $sql.= " WHERE fk_user_author = '{$fuser->id}'";
1700
1701
        dol_syslog(get_class($this)."::periode_existe sql=".$sql);
1702
        $result = $this->db->query($sql);
1703
        if($result)
1704
        {
1705
            $num_lignes = $this->db->num_rows($result); $i = 0;
1706
1707
            if ($num_lignes>0)
1708
            {
1709
                $date_d_form = $date_debut;
1710
                $date_f_form = $date_fin;
1711
1712
                $existe = false;
1713
1714
                while ($i < $num_lignes)
1715
                {
1716
                    $objp = $this->db->fetch_object($result);
1717
1718
                    $date_d_req = $this->db->jdate($objp->date_debut); // 3
1719
                    $date_f_req = $this->db->jdate($objp->date_fin);      // 4
1720
1721
                    if (!($date_f_form < $date_d_req || $date_d_form > $date_f_req)) $existe = true;
1722
1723
                    $i++;
1724
                }
1725
1726
                if($existe) return 1;
1727
                else return 0;
1728
            }
1729
            else
1730
            {
1731
                return 0;
1732
            }
1733
        }
1734
        else
1735
        {
1736
            $this->error=$this->db->lasterror();
1737
            dol_syslog(get_class($this)."::periode_existe  Error ".$this->error, LOG_ERR);
1738
            return -1;
1739
        }
1740
    }
1741
1742
1743
    /**
1744
     * Return list of people with permission to validate expense reports.
1745
     * Search for permission "approve expense report"
1746
     *
1747
     * @return  array       Array of user ids
1748
     */
1749
    function fetch_users_approver_expensereport()
1750
    {
1751
        $users_validator=array();
1752
1753
        $sql = "SELECT DISTINCT ur.fk_user";
1754
        $sql.= " FROM ".MAIN_DB_PREFIX."user_rights as ur, ".MAIN_DB_PREFIX."rights_def as rd";
1755
        $sql.= " WHERE ur.fk_id = rd.id and rd.module = 'expensereport' AND rd.perms = 'approve'";                                              // Permission 'Approve';
1756
        $sql.= "UNION";
1757
        $sql.= " SELECT DISTINCT ugu.fk_user";
1758
        $sql.= " FROM ".MAIN_DB_PREFIX."usergroup_user as ugu, ".MAIN_DB_PREFIX."usergroup_rights as ur, ".MAIN_DB_PREFIX."rights_def as rd";
1759
        $sql.= " WHERE ugu.fk_usergroup = ur.fk_usergroup AND ur.fk_id = rd.id and rd.module = 'expensereport' AND rd.perms = 'approve'";       // Permission 'Approve';
1760
        //print $sql;
1761
        
1762
        dol_syslog(get_class($this)."::fetch_users_approver_expensereport sql=".$sql);
1763
        $result = $this->db->query($sql);
1764
        if($result)
1765
        {
1766
            $num_lignes = $this->db->num_rows($result); $i = 0;
1767
            while ($i < $num_lignes)
1768
            {
1769
                $objp = $this->db->fetch_object($result);
1770
                array_push($users_validator,$objp->fk_user);
1771
                $i++;
1772
            }
1773
            return $users_validator;
1774
        }
1775
        else
1776
        {
1777
            $this->error=$this->db->lasterror();
1778
            dol_syslog(get_class($this)."::fetch_users_approver_expensereport  Error ".$this->error, LOG_ERR);
1779
            return -1;
1780
        }
1781
    }
1782
1783
    /**
1784
     *  Create a document onto disk accordign to template module.
1785
     *
1786
     *  @param      string      $modele         Force le mnodele a utiliser ('' to not force)
1787
     *  @param      Translate   $outputlangs    objet lang a utiliser pour traduction
1788
     *  @param      int         $hidedetails    Hide details of lines
1789
     *  @param      int         $hidedesc       Hide description
1790
     *  @param      int         $hideref        Hide ref
1791
     *  @return     int                         0 if KO, 1 if OK
1792
     */
1793
    public function generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
1794
    {
1795
        global $conf,$langs;
1796
1797
        $langs->load("trips");
1798
1799
	    if (! dol_strlen($modele)) {
1800
1801
		    $modele = 'standard';
1802
1803
		    if ($this->modelpdf) {
1804
			    $modele = $this->modelpdf;
1805
		    } elseif (! empty($conf->global->EXPENSEREPORT_ADDON_PDF)) {
1806
			    $modele = $conf->global->EXPENSEREPORT_ADDON_PDF;
1807
		    }
1808
	    }
1809
1810
        $modelpath = "core/modules/expensereport/doc/";
1811
1812
        return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref);
1813
    }
1814
1815
    /**
1816
     * List of types
1817
     *
1818
     * @param   int     $active     Active or not
1819
     * @return  array
1820
     */
1821
    function listOfTypes($active=1)
1822
    {
1823
        global $langs;
1824
        $ret=array();
1825
        $sql = "SELECT id, code, label";
1826
        $sql.= " FROM ".MAIN_DB_PREFIX."c_type_fees";
1827
        $sql.= " WHERE active = ".$active;
1828
        dol_syslog(get_class($this)."::listOfTypes", LOG_DEBUG);
1829
        $result = $this->db->query($sql);
1830
        if ( $result )
1831
        {
1832
            $num = $this->db->num_rows($result);
1833
            $i=0;
1834
            while ($i < $num)
1835
            {
1836
                $obj = $this->db->fetch_object($result);
1837
                $ret[$obj->code]=(($langs->trans($obj->code)!=$obj->code)?$langs->trans($obj->code):$obj->label);
1838
                $i++;
1839
            }
1840
        }
1841
        else
1842
        {
1843
            dol_print_error($this->db);
1844
        }
1845
        return $ret;
1846
    }
1847
1848
	/**
1849
     *      Charge indicateurs this->nb pour le tableau de bord
1850
     *
1851
     *      @return     int         <0 if KO, >0 if OK
1852
     */
1853
    function load_state_board()
1854
    {
1855
        global $conf;
1856
1857
        $this->nb=array();
1858
1859
        $sql = "SELECT count(ex.rowid) as nb";
1860
        $sql.= " FROM ".MAIN_DB_PREFIX."expensereport as ex";
1861
        $sql.= " WHERE ex.fk_statut > 0";
1862
        $sql.= " AND ex.entity IN (".getEntity('expensereport', 1).")";
1863
1864
        $resql=$this->db->query($sql);
1865
        if ($resql)
1866
        {
1867
            while ($obj=$this->db->fetch_object($resql))
1868
            {
1869
                $this->nb["expensereports"]=$obj->nb;
1870
            }
1871
            $this->db->free($resql);
1872
            return 1;
1873
        }
1874
        else
1875
        {
1876
            dol_print_error($this->db);
1877
            $this->error=$this->db->error();
1878
            return -1;
1879
        }
1880
    }
1881
1882
    /**
1883
     *      Load indicators for dashboard (this->nbtodo and this->nbtodolate)
1884
     *
1885
     *      @param	User	$user   		Objet user
1886
     *      @param  string  $option         'topay' or 'toapprove'
1887
     *      @return WorkboardResponse|int 	<0 if KO, WorkboardResponse if OK
1888
     */
1889
    function load_board($user, $option='topay')
1890
    {
1891
        global $conf, $langs;
1892
1893
        if ($user->societe_id) return -1;   // protection pour eviter appel par utilisateur externe
1894
1895
	    $now=dol_now();
1896
1897
	    $userchildids = $user->getAllChildIds(1);
1898
	    
1899
        $sql = "SELECT ex.rowid, ex.date_valid";
1900
        $sql.= " FROM ".MAIN_DB_PREFIX."expensereport as ex";
1901
        if ($option == 'toapprove') $sql.= " WHERE ex.fk_statut = 2";
1902
        else $sql.= " WHERE ex.fk_statut = 5";
1903
        $sql.= " AND ex.entity IN (".getEntity('expensereport', 1).")";
1904
        $sql.= " AND (ex.fk_user_author IN (".join(',',$userchildids).")";
1905
        $sql.= " OR ex.fk_user_validator IN (".join(',',$userchildids)."))";
1906
1907
        $resql=$this->db->query($sql);
1908
        if ($resql)
1909
        {
1910
	        $langs->load("members");
1911
1912
	        $response = new WorkboardResponse();
1913
	        if ($option == 'toapprove')
1914
	        {
1915
	           $response->warning_delay=$conf->expensereport->approve->warning_delay/60/60/24;
1916
	           $response->label=$langs->trans("ExpenseReportsToApprove");
1917
	           $response->url=DOL_URL_ROOT.'/expensereport/list.php?mainmenu=hrm&amp;statut=2';
1918
	        }
1919
	        else
1920
	        {
1921
	            $response->warning_delay=$conf->expensereport->payment->warning_delay/60/60/24;
1922
	            $response->label=$langs->trans("ExpenseReportsToPay");
1923
	            $response->url=DOL_URL_ROOT.'/expensereport/list.php?mainmenu=hrm&amp;statut=5';
1924
	        }
1925
	        $response->img=img_object('',"trip");
1926
1927
            while ($obj=$this->db->fetch_object($resql))
1928
            {
1929
	            $response->nbtodo++;
1930
                
1931
	            if ($option == 'toapprove')
1932
	            {
1933
	                if ($this->db->jdate($obj->date_valid) < ($now - $conf->expensereport->approve->warning_delay)) {
1934
	                    $response->nbtodolate++;
1935
	                }
1936
	            }
1937
	            else
1938
	            {
1939
                    if ($this->db->jdate($obj->date_valid) < ($now - $conf->expensereport->payment->warning_delay)) {
1940
    	                $response->nbtodolate++;
1941
                    }
1942
	            }
1943
            }
1944
1945
            return $response;
1946
        }
1947
        else
1948
        {
1949
            dol_print_error($this->db);
1950
            $this->error=$this->db->error();
1951
            return -1;
1952
        }
1953
    }
1954
    
1955
    /**
1956
     * Return if an expense report is late or not
1957
     *
1958
     * @param  string  $option          'topay' or 'toapprove'
1959
     * @return boolean                  True if late, False if not late
1960
     */
1961
    public function hasDelay($option)
1962
    {
1963
        global $conf;
1964
    
1965
        //Only valid members
1966
        if ($option == 'toapprove' && $this->status != 2) return false;
1967
        if ($option == 'topay' && $this->status != 5) return false;
1968
    
1969
        $now = dol_now();
1970
        if ($option == 'toapprove')
1971
        {
1972
            return ($this->datevalid?$this->datevalid:$this->date_valid) < ($now - $conf->expensereport->approve->warning_delay);
1973
        }
1974
        else
1975
            return ($this->datevalid?$this->datevalid:$this->date_valid) < ($now - $conf->expensereport->payment->warning_delay);
1976
    }    
1977
}
1978
1979
1980
/**
1981
 * Class of expense report details lines
1982
 */
1983
class ExpenseReportLine
1984
{
1985
    var $db;
1986
    var $error;
1987
1988
    var $rowid;
1989
    var $comments;
1990
    var $qty;
1991
    var $value_unit;
1992
    var $date;
1993
1994
    var $fk_c_type_fees;
1995
    var $fk_projet;
1996
    var $fk_expensereport;
1997
1998
    var $type_fees_code;
1999
    var $type_fees_libelle;
2000
2001
    var $projet_ref;
2002
    var $projet_title;
2003
2004
    var $vatrate;
2005
    var $total_ht;
2006
    var $total_tva;
2007
    var $total_ttc;
2008
2009
    /**
2010
     * Constructor
2011
     *
2012
     * @param DoliDB    $db     Handlet database
2013
     */
2014
    function __construct($db)
2015
    {
2016
        $this->db= $db;
2017
    }
2018
2019
    /**
2020
     * Fetch record for expense report detailed line
2021
     *
2022
     * @param   int     $rowid      Id of object to load
2023
     * @return  int                 <0 if KO, >0 if OK
2024
     */
2025
    function fetch($rowid)
2026
    {
2027
        $sql = 'SELECT fde.rowid, fde.fk_expensereport, fde.fk_c_type_fees, fde.fk_projet, fde.date,';
2028
        $sql.= ' fde.tva_tx as vatrate, fde.comments, fde.qty, fde.value_unit, fde.total_ht, fde.total_tva, fde.total_ttc,';
2029
        $sql.= ' ctf.code as type_fees_code, ctf.label as type_fees_libelle,';
2030
        $sql.= ' pjt.rowid as projet_id, pjt.title as projet_title, pjt.ref as projet_ref';
2031
        $sql.= ' FROM '.MAIN_DB_PREFIX.'expensereport_det as fde';
2032
        $sql.= ' INNER JOIN '.MAIN_DB_PREFIX.'c_type_fees as ctf ON fde.fk_c_type_fees=ctf.id';
2033
        $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'projet as pjt ON fde.fk_projet=pjt.rowid';
2034
        $sql.= ' WHERE fde.rowid = '.$rowid;
2035
2036
        $result = $this->db->query($sql);
2037
2038
        if($result)
2039
        {
2040
            $objp = $this->db->fetch_object($result);
2041
2042
            $this->rowid = $objp->rowid;
2043
            $this->id = $obj->rowid;
0 ignored issues
show
Bug introduced by
The variable $obj 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...
2044
            $this->ref = $obj->ref;
2045
            $this->fk_expensereport = $objp->fk_expensereport;
2046
            $this->comments = $objp->comments;
2047
            $this->qty = $objp->qty;
2048
            $this->date = $objp->date;
2049
            $this->value_unit = $objp->value_unit;
2050
            $this->fk_c_type_fees = $objp->fk_c_type_fees;
2051
            $this->fk_projet = $objp->fk_projet;
2052
            $this->type_fees_code = $objp->type_fees_code;
2053
            $this->type_fees_libelle = $objp->type_fees_libelle;
2054
            $this->projet_ref = $objp->projet_ref;
2055
            $this->projet_title = $objp->projet_title;
2056
            $this->vatrate = $objp->vatrate;
2057
            $this->total_ht = $objp->total_ht;
2058
            $this->total_tva = $objp->total_tva;
2059
            $this->total_ttc = $objp->total_ttc;
2060
2061
            $this->db->free($result);
2062
        } else {
2063
            dol_print_error($this->db);
2064
        }
2065
    }
2066
2067
    /**
2068
     * insert
2069
     *
2070
     * @param   int     $notrigger      1=No trigger
2071
     * @return  int                     <0 if KO, >0 if OK
2072
     */
2073
    function insert($notrigger=0)
2074
    {
2075
        global $langs,$user,$conf;
2076
2077
        $error=0;
2078
2079
        dol_syslog("ExpenseReportLine::Insert rang=".$this->rang, LOG_DEBUG);
2080
2081
        // Clean parameters
2082
        $this->comments=trim($this->comments);
2083
        if (!$this->value_unit_HT) $this->value_unit_HT=0;
2084
        $this->qty = price2num($this->qty);
2085
        $this->vatrate = price2num($this->vatrate);
2086
2087
        $this->db->begin();
2088
2089
        $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'expensereport_det';
2090
        $sql.= ' (fk_expensereport, fk_c_type_fees, fk_projet,';
2091
        $sql.= ' tva_tx, comments, qty, value_unit, total_ht, total_tva, total_ttc, date)';
2092
        $sql.= " VALUES (".$this->fk_expensereport.",";
2093
        $sql.= " ".$this->fk_c_type_fees.",";
2094
        $sql.= " ".($this->fk_projet>0?$this->fk_projet:'null').",";
2095
        $sql.= " ".$this->vatrate.",";
2096
        $sql.= " '".$this->db->escape($this->comments)."',";
2097
        $sql.= " ".$this->qty.",";
2098
        $sql.= " ".$this->value_unit.",";
2099
        $sql.= " ".$this->total_ht.",";
2100
        $sql.= " ".$this->total_tva.",";
2101
        $sql.= " ".$this->total_ttc.",";
2102
        $sql.= "'".$this->db->idate($this->date)."'";
2103
        $sql.= ")";
2104
2105
        dol_syslog("ExpenseReportLine::insert sql=".$sql);
2106
2107
        $resql=$this->db->query($sql);
2108
        if ($resql)
2109
        {
2110
            $this->rowid=$this->db->last_insert_id(MAIN_DB_PREFIX.'expensereport_det');
2111
2112
            $tmpparent=new ExpenseReport($this->db);
2113
            $tmpparent->fetch($this->fk_expensereport);
2114
            $result = $tmpparent->update_price();
2115
            if ($result < 0)
2116
            {
2117
                $error++;
2118
                $this->error = $tmpparent->error;
2119
                $this->errors = $tmpparent->errors;
2120
            }
2121
        }
2122
2123
        if (! $error)
2124
        {
2125
            $this->db->commit();
2126
            return $this->rowid;
2127
        }
2128
        else
2129
        {
2130
            $this->error=$this->db->lasterror();
2131
            dol_syslog("ExpenseReportLine::insert Error ".$this->error, LOG_ERR);
2132
            $this->db->rollback();
2133
            return -2;
2134
        }
2135
    }
2136
2137
    /**
2138
     * update
2139
     *
2140
     * @param   User    $fuser      User
2141
     * @return  int                 <0 if KO, >0 if OK
2142
     */
2143
    function update($fuser)
2144
    {
2145
        global $fuser,$langs,$conf;
2146
2147
        $error=0;
2148
2149
        // Clean parameters
2150
        $this->comments=trim($this->comments);
2151
        $this->vatrate = price2num($this->vatrate);
2152
        $this->value_unit = price2num($this->value_unit);
2153
2154
        $this->db->begin();
2155
2156
        // Mise a jour ligne en base
2157
        $sql = "UPDATE ".MAIN_DB_PREFIX."expensereport_det SET";
2158
        $sql.= " comments='".$this->db->escape($this->comments)."'";
2159
        $sql.= ",value_unit=".$this->value_unit;
2160
        $sql.= ",qty=".$this->qty;
2161
        $sql.= ",date='".$this->db->idate($this->date)."'";
2162
        $sql.= ",total_ht=".$this->total_ht."";
2163
        $sql.= ",total_tva=".$this->total_tva."";
2164
        $sql.= ",total_ttc=".$this->total_ttc."";
2165
        $sql.= ",tva_tx=".$this->vatrate;
2166
        if ($this->fk_c_type_fees) $sql.= ",fk_c_type_fees=".$this->fk_c_type_fees;
2167
        else $sql.= ",fk_c_type_fees=null";
2168
        if ($this->fk_projet) $sql.= ",fk_projet=".$this->fk_projet;
2169
        else $sql.= ",fk_projet=null";
2170
        $sql.= " WHERE rowid = ".$this->rowid;
2171
2172
        dol_syslog("ExpenseReportLine::update sql=".$sql);
2173
2174
        $resql=$this->db->query($sql);
2175
        if ($resql)
2176
        {
2177
            $tmpparent=new ExpenseReport($this->db);
2178
            $result = $tmpparent->fetch($this->fk_expensereport);
2179
            if ($result > 0)
2180
            {
2181
                $result = $tmpparent->update_price();
2182
                if ($result < 0)
2183
                {
2184
                    $error++;
2185
                    $this->error = $tmpparent->error;
2186
                    $this->errors = $tmpparent->errors;
2187
                }
2188
            }
2189
            else
2190
            {
2191
                $error++;
2192
                $this->error = $tmpparent->error;
2193
                $this->errors = $tmpparent->errors;
2194
            }
2195
        }
2196
        else
2197
        {
2198
            $error++;
2199
            dol_print_error($this->db);
2200
        }
2201
2202
        if (! $error)
2203
        {
2204
            $this->db->commit();
2205
            return 1;
2206
        }
2207
        else
2208
        {
2209
            $this->error=$this->db->lasterror();
2210
            dol_syslog("ExpenseReportLine::update Error ".$this->error, LOG_ERR);
2211
            $this->db->rollback();
2212
            return -2;
2213
        }
2214
    }
2215
}
2216
2217
2218
/**
2219
 *    Retourne la liste deroulante des differents etats d'une note de frais.
2220
 *    Les valeurs de la liste sont les id de la table c_expensereport_statuts
2221
 *
2222
 *    @param    int     $selected       preselect status
2223
 *    @param    string  $htmlname       Name of HTML select
2224
 *    @param    int     $useempty       1=Add empty line
2225
 *    @param    int     $useshortlabel  Use short labels
2226
 *    @return   string                  HTML select with status
2227
 */
2228
function select_expensereport_statut($selected='',$htmlname='fk_statut',$useempty=1, $useshortlabel=0)
2229
{
2230
    global $db, $langs;
2231
2232
    $tmpep=new ExpenseReport($db);
2233
2234
    print '<select class="flat" name="'.$htmlname.'">';
2235
    if ($useempty) print '<option value="-1">&nbsp;</option>';
2236
    $arrayoflabels=$tmpep->statuts;
2237
    if ($useshortlabel) $arrayoflabels=$tmpep->statuts_short;
2238
    foreach ($arrayoflabels as $key => $val)
2239
    {
2240
        if ($selected != '' && $selected == $key)
2241
        {
2242
            print '<option value="'.$key.'" selected>';
2243
        }
2244
        else
2245
        {
2246
            print '<option value="'.$key.'">';
2247
        }
2248
        print $langs->trans($val);
2249
        print '</option>';
2250
    }
2251
    print '</select>';
2252
}
2253
2254
/**
2255
 *  Return list of types of notes with select value = id
2256
 *
2257
 *  @param      int     $selected       Preselected type
2258
 *  @param      string  $htmlname       Name of field in form
2259
 *  @param      int     $showempty      Add an empty field
2260
 *  @param      int     $active         1=Active only, 0=Unactive only, -1=All
2261
 *  @return     string                  Select html
2262
 */
2263
function select_type_fees_id($selected='',$htmlname='type',$showempty=0, $active=1)
2264
{
2265
    global $db,$langs,$user;
2266
    $langs->load("trips");
2267
2268
    print '<select class="flat" name="'.$htmlname.'">';
2269
    if ($showempty)
2270
    {
2271
        print '<option value="-1"';
2272
        if ($selected == -1) print ' selected';
2273
        print '>&nbsp;</option>';
2274
    }
2275
2276
    $sql = "SELECT c.id, c.code, c.label as type FROM ".MAIN_DB_PREFIX."c_type_fees as c";
2277
    if ($active >= 0) $sql.= " WHERE c.active = ".$active;
2278
    $sql.= " ORDER BY c.label ASC";
2279
    $resql=$db->query($sql);
2280
    if ($resql)
2281
    {
2282
        $num = $db->num_rows($resql);
2283
        $i = 0;
2284
2285
        while ($i < $num)
2286
        {
2287
            $obj = $db->fetch_object($resql);
2288
            print '<option value="'.$obj->id.'"';
2289
            if ($obj->code == $selected || $obj->id == $selected) print ' selected';
2290
            print '>';
2291
            if ($obj->code != $langs->trans($obj->code)) print $langs->trans($obj->code);
2292
            else print $langs->trans($obj->type);
2293
            $i++;
2294
        }
2295
    }
2296
    print '</select>';
2297
}
2298