Completed
Branch develop (b928bb)
by
unknown
27:14
created

BookKeeping::deleteByImportkey()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 13
nc 2
nop 1
dl 0
loc 20
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/* Copyright (C) 2014-2016 Olivier Geffroy      <[email protected]>
3
 * Copyright (C) 2015-2016 Alexandre Spangaro   <[email protected]>
4
 * Copyright (C) 2015-2016 Florian Henry		<[email protected]>
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18
 */
19
20
/**
21
 *	\file       htdocs/accountancy/class/bookkeeping.class.php
22
 *	\ingroup    Advanced accountancy
23
 *	\brief      File of class to manage general ledger
24
 */
25
26
// Class
27
require_once DOL_DOCUMENT_ROOT . '/core/class/commonobject.class.php';
28
29
/**
30
 * Class to manage general ledger
31
 */
32
class BookKeeping extends CommonObject
33
{
34
	/**
35
	 *
36
	 * @var string Error code (or message)
37
	 * @deprecated
38
	 *
39
	 * @see Accountingbookkeeping::errors
40
	 */
41
	public $error;
42
	/**
43
	 *
44
	 * @var string[] Error codes (or messages)
45
	 */
46
	public $errors = array ();
47
	/**
48
	 *
49
	 * @var string Id to identify managed objects
50
	 */
51
	public $element = 'accountingbookkeeping';
52
	/**
53
	 *
54
	 * @var string Name of table without prefix where object is stored
55
	 */
56
	public $table_element = 'accounting_bookkeeping';  
57
	
58
	
59
	public $entity = 1;
60
	
61
	
62
	/**
63
	 *
64
	 * @var BookKeepingLine[] Lines
65
	 */
66
	public $lines = array ();
67
	
68
	
69
	/**
70
	 *
71
	 * @var int ID
72
	 */
73
	public $id;
74
	/**
75
	 */
76
	public $doc_date = '';
77
	public $doc_type;
78
	public $doc_ref;
79
	public $fk_doc;
80
	public $fk_docdet;
81
	public $code_tiers;
82
	public $numero_compte;
83
	public $label_compte;
84
	public $debit;
85
	public $credit;
86
	public $montant;
87
	public $sens;
88
	public $fk_user_author;
89
	public $import_key;
90
	public $code_journal;
91
	public $piece_num;
92
	
93
	/**
94
	 */
95
	
96
	/**
97
	 * Constructor
98
	 *
99
	 * @param DoliDb $db Database handler
100
	 */
101
	public function __construct(DoliDB $db) {
102
		$this->db = $db;
103
	}
104
	
105
	/**
106
	 * Create object into database
107
	 *
108
	 * @param  User    $user       User that creates
109
	 * @param  bool    $notrigger  false=launch triggers after, true=disable triggers
110
	 * @return int                 <0 if KO, Id of created object if OK
111
	 */
112
	public function create(User $user, $notrigger = false) {
113
	    global $conf, $langs;
114
	    
115
		dol_syslog(__METHOD__, LOG_DEBUG);
116
		
117
		$error = 0;
118
		
119
		// Clean parameters
120
		if (isset($this->doc_type)) {
121
			$this->doc_type = trim($this->doc_type);
122
		}
123
		if (isset($this->doc_ref)) {
124
			$this->doc_ref = trim($this->doc_ref);
125
		}
126
		if (isset($this->fk_doc)) {
127
			$this->fk_doc = trim($this->fk_doc);
128
		}
129
		if (isset($this->fk_docdet)) {
130
			$this->fk_docdet = trim($this->fk_docdet);
131
		}
132
		if (isset($this->code_tiers)) {
133
			$this->code_tiers = trim($this->code_tiers);
134
		}
135
		if (isset($this->numero_compte)) {
136
			$this->numero_compte = trim($this->numero_compte);
137
		}
138
		if (isset($this->label_compte)) {
139
			$this->label_compte = trim($this->label_compte);
140
		}
141
		if (isset($this->debit)) {
142
			$this->debit = trim($this->debit);
143
		}
144
		if (isset($this->credit)) {
145
			$this->credit = trim($this->credit);
146
		}
147
		if (isset($this->montant)) {
148
			$this->montant = trim($this->montant);
149
		}
150
		if (isset($this->sens)) {
151
			$this->sens = trim($this->sens);
152
		}
153
		if (isset($this->fk_user_author)) {
154
			$this->fk_user_author = trim($this->fk_user_author);
155
		}
156
		if (isset($this->import_key)) {
157
			$this->import_key = trim($this->import_key);
158
		}
159
		if (isset($this->code_journal)) {
160
			$this->code_journal = trim($this->code_journal);
161
		}
162
		if (isset($this->piece_num)) {
163
			$this->piece_num = trim($this->piece_num);
164
		}
165
		if (empty($this->debit)) $this->debit = 0;
166
		if (empty($this->credit)) $this->credit = 0;
167
		
168
		// Check parameters
169
		if (empty($this->numero_compte) || $this->numero_compte == '-1')
170
		{
171
		    $langs->load("errors");
172
            $this->errors[]=$langs->trans('ErrorFieldAccountNotDefinedForBankLine', $this->fk_docdet);		    
173
		    return -1;
174
		}
175
		
176
		
177
		$this->db->begin();
178
		
179
		$this->piece_num = 0;
180
		
181
		// first check if line not yet in bookkeeping
182
		$sql = "SELECT count(*) as nb";
183
		$sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
184
		$sql .= " WHERE doc_type = '" . $this->doc_type . "'";
185
		$sql .= " AND fk_docdet = " . $this->fk_docdet;
186
		$sql .= " AND numero_compte = '" . $this->numero_compte . "'";
187
	    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
188
		
189
		$resql = $this->db->query($sql);
190
		
191
		if ($resql) {
192
			$row = $this->db->fetch_object($resql);
193
			if ($row->nb == 0) {
194
				
195
				// Determine piece_num
196
				$sqlnum = "SELECT piece_num";
197
				$sqlnum .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
198
				$sqlnum .= " WHERE doc_type = '" . $this->doc_type . "'";
199
				$sqlnum .= " AND fk_docdet = '" . $this->fk_docdet . "'";
200
				$sqlnum .= " AND doc_ref = '" . $this->doc_ref . "'";
201
			    $sqlnum .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
202
				
203
				dol_syslog(get_class($this) . ":: create sqlnum=" . $sqlnum, LOG_DEBUG);
204
				$resqlnum = $this->db->query($sqlnum);
205
				if ($resqlnum) {
206
					$objnum = $this->db->fetch_object($resqlnum);
207
					$this->piece_num = $objnum->piece_num;
208
				}
209
				dol_syslog(get_class($this) . ":: create this->piece_num=" . $this->piece_num, LOG_DEBUG);
210
				if (empty($this->piece_num)) {
211
					$sqlnum = "SELECT MAX(piece_num)+1 as maxpiecenum";
212
					$sqlnum .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
213
				    $sqlnum .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")";
214
						
215
					dol_syslog(get_class($this) . ":: create sqlnum=" . $sqlnum, LOG_DEBUG);
216
					$resqlnum = $this->db->query($sqlnum);
217
					if ($resqlnum) {
218
						$objnum = $this->db->fetch_object($resqlnum);
219
						$this->piece_num = $objnum->maxpiecenum;
220
					}
221
				}
222
				dol_syslog(get_class($this) . ":: create this->piece_num=" . $this->piece_num, LOG_DEBUG);
223
				if (empty($this->piece_num)) {
224
					$this->piece_num = 1;
225
				}
226
				
227
				$now = dol_now();
228
				if (empty($this->date_create)) {
229
					$this->date_create = $now;
230
				}
231
				
232
				$sql = "INSERT INTO " . MAIN_DB_PREFIX . $this->table_element . " (";
233
				$sql .= "doc_date";
234
				$sql .= ", doc_type";
235
				$sql .= ", doc_ref";
236
				$sql .= ", fk_doc";
237
				$sql .= ", fk_docdet";
238
				$sql .= ", code_tiers";
239
				$sql .= ", numero_compte";
240
				$sql .= ", label_compte";
241
				$sql .= ", debit";
242
				$sql .= ", credit";
243
				$sql .= ", montant";
244
				$sql .= ", sens";
245
				$sql .= ", fk_user_author";
246
				$sql .= ", import_key";
247
				$sql .= ", code_journal";
248
				$sql .= ", piece_num";
249
				$sql .= ', entity';				
250
				$sql .= ") VALUES (";
251
				$sql .= "'" . $this->db->idate($this->doc_date) . "'";
252
				$sql .= ",'" . $this->doc_type . "'";
253
				$sql .= ",'" . $this->doc_ref . "'";
254
				$sql .= "," . $this->fk_doc;
255
				$sql .= "," . $this->fk_docdet;
256
				$sql .= ",'" . $this->code_tiers . "'";
257
				$sql .= ",'" . $this->numero_compte . "'";
258
				$sql .= ",'" . $this->db->escape($this->label_compte) . "'";
259
				$sql .= "," . $this->debit;
260
				$sql .= "," . $this->credit;
261
				$sql .= "," . $this->montant;
262
				$sql .= ",'" . $this->sens . "'";
263
				$sql .= ",'" . $this->fk_user_author . "'";
264
				$sql .= ",'" . $this->db->idate($this->date_create). "'";
265
				$sql .= ",'" . $this->code_journal . "'";
266
				$sql .= "," . $this->piece_num;
267
				$sql .= ", " . (! isset($this->entity) ? '1' : $this->entity);
268
				$sql .= ")";
269
				
270
				dol_syslog(get_class($this) . ":: create sql=" . $sql, LOG_DEBUG);
271
				$resql = $this->db->query($sql);
272
				if ($resql) {
273
					$id = $this->db->last_insert_id(MAIN_DB_PREFIX . $this->table_element);
274
					
275
					if ($id > 0) {
276
						$this->id = $id;
277
						$result = 0;
278
					} else {
279
						$result = - 2;
280
						$error ++;
281
						$this->errors[] = 'Error Create Error ' . $result . ' lecture ID';
282
						dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR);
283
					}
284
				} else {
285
					$result = - 1;
286
					$error ++;
287
					$this->errors[] = 'Error ' . $this->db->lasterror();
288
					dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR);
289
				}
290
			} else {     // Already exists
291
				$result = -3;
292
				$error++;
293
				$this->errors[] = 'Error Transaction for ('.$this->doc_type.', '.$this->doc_ref.', '.$this->fk_docdet.') were already recorded';
294
				dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_WARNING);
295
			}
296
		} else {
297
			$result = - 5;
298
			$error ++;
299
			$this->errors[] = 'Error ' . $this->db->lasterror();
300
			dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR);
301
		}
302
		
303
		if (! $error) {
304
			
305
			if (! $notrigger) {
306
				// Uncomment this and change MYOBJECT to your own tag if you
307
				// want this action to call a trigger.
308
				
309
				// // Call triggers
310
				// $result=$this->call_trigger('MYOBJECT_CREATE',$user);
311
				// if ($result < 0) $error++;
312
				// // End call triggers
313
			}
314
		}
315
		
316
		// Commit or rollback
317
		if ($error) {
318
			$this->db->rollback();
319
			
320
			return - 1 * $error;
321
		} else {
322
			$this->db->commit();
323
			
324
			return $result;
325
		}
326
	}
327
	
328
	/**
329
	 * Create object into database
330
	 *
331
	 * @param  User    $user       User that creates
332
	 * @param  bool    $notrigger  false=launch triggers after, true=disable triggers
333
	 * @return int                 <0 if KO, Id of created object if OK
334
	 */
335
	public function createStd(User $user, $notrigger = false) {
336
		dol_syslog(__METHOD__, LOG_DEBUG);
337
		
338
		$error = 0;
339
		
340
		// Clean parameters
341
		
342
		if (isset($this->doc_type)) {
343
			$this->doc_type = trim($this->doc_type);
344
		}
345
		if (isset($this->doc_ref)) {
346
			$this->doc_ref = trim($this->doc_ref);
347
		}
348
		if (isset($this->fk_doc)) {
349
			$this->fk_doc = trim($this->fk_doc);
350
		}
351
		if (isset($this->fk_docdet)) {
352
			$this->fk_docdet = trim($this->fk_docdet);
353
		}
354
		if (isset($this->code_tiers)) {
355
			$this->code_tiers = trim($this->code_tiers);
356
		}
357
		if (isset($this->numero_compte)) {
358
			$this->numero_compte = trim($this->numero_compte);
359
		}
360
		if (isset($this->label_compte)) {
361
			$this->label_compte = trim($this->label_compte);
362
		}
363
		if (isset($this->debit)) {
364
			$this->debit = trim($this->debit);
365
		}
366
		if (isset($this->credit)) {
367
			$this->credit = trim($this->credit);
368
		}
369
		if (isset($this->montant)) {
370
			$this->montant = trim($this->montant);
371
		}
372
		if (isset($this->sens)) {
373
			$this->sens = trim($this->sens);
374
		}
375
		if (isset($this->fk_user_author)) {
376
			$this->fk_user_author = trim($this->fk_user_author);
377
		}
378
		if (isset($this->import_key)) {
379
			$this->import_key = trim($this->import_key);
380
		}
381
		if (isset($this->code_journal)) {
382
			$this->code_journal = trim($this->code_journal);
383
		}
384
		if (isset($this->piece_num)) {
385
			$this->piece_num = trim($this->piece_num);
386
		}
387
		if (empty($this->debit)) $this->debit = 0;
388
		if (empty($this->credit)) $this->credit = 0;
389
		
390
		// Check parameters
391
		// Put here code to add control on parameters values
392
		
393
		// Insert request
394
		$sql = 'INSERT INTO ' . MAIN_DB_PREFIX . $this->table_element . '(';
395
		$sql .= 'doc_date,';
396
		$sql .= 'doc_type,';
397
		$sql .= 'doc_ref,';
398
		$sql .= 'fk_doc,';
399
		$sql .= 'fk_docdet,';
400
		$sql .= 'code_tiers,';
401
		$sql .= 'numero_compte,';
402
		$sql .= 'label_compte,';
403
		$sql .= 'debit,';
404
		$sql .= 'credit,';
405
		$sql .= 'montant,';
406
		$sql .= 'sens,';
407
		$sql .= 'fk_user_author,';
408
		$sql .= 'import_key,';
409
		$sql .= 'code_journal,';
410
		$sql .= 'piece_num,';
411
		$sql .= 'entity';
412
		$sql .= ') VALUES (';
413
		$sql .= ' ' . (! isset($this->doc_date) || dol_strlen($this->doc_date) == 0 ? 'NULL' : "'" . $this->db->idate($this->doc_date) . "'") . ',';
414
		$sql .= ' ' . (! isset($this->doc_type) ? 'NULL' : "'" . $this->db->escape($this->doc_type) . "'") . ',';
415
		$sql .= ' ' . (! isset($this->doc_ref) ? 'NULL' : "'" . $this->db->escape($this->doc_ref) . "'") . ',';
416
		$sql .= ' ' . (empty($this->fk_doc) ? '0' : $this->fk_doc) . ',';
417
		$sql .= ' ' . (empty($this->fk_docdet) ? '0' : $this->fk_docdet) . ',';
418
		$sql .= ' ' . (! isset($this->code_tiers) ? 'NULL' : "'" . $this->db->escape($this->code_tiers) . "'") . ',';
419
		$sql .= ' ' . (! isset($this->numero_compte) ? "'NotDefined'" : "'" . $this->db->escape($this->numero_compte) . "'") . ',';
420
		$sql .= ' ' . (! isset($this->label_compte) ? 'NULL' : "'" . $this->db->escape($this->label_compte) . "'") . ',';
421
		$sql .= ' ' . (! isset($this->debit) ? 'NULL' : $this->debit ). ',';
422
		$sql .= ' ' . (! isset($this->credit) ? 'NULL' : $this->credit ). ',';
423
		$sql .= ' ' . (! isset($this->montant) ? 'NULL' : $this->montant ). ',';
424
		$sql .= ' ' . (! isset($this->sens) ? 'NULL' : "'" . $this->db->escape($this->sens) . "'") . ',';
425
		$sql .= ' ' . $user->id . ',';
426
		$sql .= ' ' . (! isset($this->import_key) ? 'NULL' : "'" . $this->db->escape($this->import_key) . "'") . ',';
427
		$sql .= ' ' . (empty($this->code_journal) ? 'NULL' : "'" . $this->db->escape($this->code_journal) . "'") . ',';
428
		$sql .= ' ' . (empty($this->piece_num) ? 'NULL' : $this->piece_num).',';
429
		$sql .= ' ' . (! isset($this->entity) ? '1' : $this->entity);
430
		$sql .= ')';
431
		
432
		$this->db->begin();
433
		
434
		$resql = $this->db->query($sql);
435
		if (! $resql) {
436
			$error ++;
437
			$this->errors[] = 'Error ' . $this->db->lasterror();
438
			dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR);
439
		}
440
		
441
		if (! $error) {
442
			$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . $this->table_element);
443
			
444
			if (! $notrigger) {
445
				// Uncomment this and change MYOBJECT to your own tag if you
446
				// want this action to call a trigger.
447
				
448
				// // Call triggers
449
				// $result=$this->call_trigger('MYOBJECT_CREATE',$user);
450
				// if ($result < 0) $error++;
451
				// // End call triggers
452
			}
453
		}
454
		
455
		// Commit or rollback
456
		if ($error) {
457
			$this->db->rollback();
458
			
459
			return - 1 * $error;
460
		} else {
461
			$this->db->commit();
462
			
463
			return $this->id;
464
		}
465
	}
466
	
467
	/**
468
	 * Load object in memory from the database
469
	 *
470
	 * @param int $id Id object
471
	 * @param string $ref Ref
472
	 * 
473
	 * @return int <0 if KO, 0 if not found, >0 if OK
474
	 */
475
	public function fetch($id, $ref = null) {
476
		global $conf;
477
		
478
	    dol_syslog(__METHOD__, LOG_DEBUG);
479
		
480
		$sql = 'SELECT';
481
		$sql .= ' t.rowid,';
482
		$sql .= " t.doc_date,";
483
		$sql .= " t.doc_type,";
484
		$sql .= " t.doc_ref,";
485
		$sql .= " t.fk_doc,";
486
		$sql .= " t.fk_docdet,";
487
		$sql .= " t.code_tiers,";
488
		$sql .= " t.numero_compte,";
489
		$sql .= " t.label_compte,";
490
		$sql .= " t.debit,";
491
		$sql .= " t.credit,";
492
		$sql .= " t.montant,";
493
		$sql .= " t.sens,";
494
		$sql .= " t.fk_user_author,";
495
		$sql .= " t.import_key,";
496
		$sql .= " t.code_journal,";
497
		$sql .= " t.piece_num";
498
		$sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t';
499
		$sql .= ' WHERE 1 = 1';
500
	    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
501
		if (null !== $ref) {
502
			$sql .= ' AND t.ref = ' . '\'' . $ref . '\'';
503
		} else {
504
			$sql .= ' AND t.rowid = ' . $id;
505
		}
506
		
507
		$resql = $this->db->query($sql);
508
		if ($resql) {
509
			$numrows = $this->db->num_rows($resql);
510
			if ($numrows) {
511
				$obj = $this->db->fetch_object($resql);
512
				
513
				$this->id = $obj->rowid;
514
				
515
				$this->doc_date = $this->db->jdate($obj->doc_date);
1 ignored issue
show
Documentation Bug introduced by
It seems like $this->db->jdate($obj->doc_date) can also be of type integer. However, the property $doc_date is declared as type string. Maybe add an additional type check?

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

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

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

class Id
{
    public $id;

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

}

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

$account_id = false;

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

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
516
				$this->doc_type = $obj->doc_type;
517
				$this->doc_ref = $obj->doc_ref;
518
				$this->fk_doc = $obj->fk_doc;
519
				$this->fk_docdet = $obj->fk_docdet;
520
				$this->code_tiers = $obj->code_tiers;
521
				$this->numero_compte = $obj->numero_compte;
522
				$this->label_compte = $obj->label_compte;
523
				$this->debit = $obj->debit;
524
				$this->credit = $obj->credit;
525
				$this->montant = $obj->montant;
526
				$this->sens = $obj->sens;
527
				$this->fk_user_author = $obj->fk_user_author;
528
				$this->import_key = $obj->import_key;
529
				$this->code_journal = $obj->code_journal;
530
				$this->piece_num = $obj->piece_num;
531
			}
532
			$this->db->free($resql);
533
			
534
			if ($numrows) {
535
				return 1;
536
			} else {
537
				return 0;
538
			}
539
		} else {
540
			$this->errors[] = 'Error ' . $this->db->lasterror();
541
			dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR);
542
			
543
			return - 1;
544
		}
545
	}
546
  
547
  /**
548
	 * Load object in memory from the database
549
	 *
550
	 * @param string $sortorder Sort Order
551
	 * @param string $sortfield Sort field
552
	 * @param int $limit offset limit
553
	 * @param int $offset offset limit
554
	 * @param array $filter filter array
555
	 * @param string $filtermode filter mode (AND or OR)
556
	 *       
557
	 * @return int <0 if KO, >0 if OK
558
	 */
559
	public function fetchAllByAccount($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') {
560
		global $conf;
561
		
562
	    dol_syslog(__METHOD__, LOG_DEBUG);
563
		
564
		$sql = 'SELECT';
565
		$sql .= ' t.rowid,';
566
		$sql .= " t.doc_date,";
567
		$sql .= " t.doc_type,";
568
		$sql .= " t.doc_ref,";
569
		$sql .= " t.fk_doc,";
570
		$sql .= " t.fk_docdet,";
571
		$sql .= " t.code_tiers,";
572
		$sql .= " t.numero_compte,";
573
		$sql .= " t.label_compte,";
574
		$sql .= " t.debit,";
575
		$sql .= " t.credit,";
576
		$sql .= " t.montant,";
577
		$sql .= " t.sens,";
578
		$sql .= " t.fk_user_author,";
579
		$sql .= " t.import_key,";
580
		$sql .= " t.code_journal,";
581
		$sql .= " t.piece_num";
582
		// Manage filter
583
		$sqlwhere = array ();
584
		if (count($filter) > 0) {
585
			foreach ( $filter as $key => $value ) {
586
				if ($key == 't.doc_date') {
587
					$sqlwhere[] = $key . '=\'' . $this->db->idate($value) . '\'';
588
				} elseif ($key == 't.doc_date>=' || $key == 't.doc_date<=') {
589
					$sqlwhere[] = $key . '\'' . $this->db->idate($value) . '\'';
590
				} elseif ($key == 't.numero_compte>=' || $key == 't.numero_compte<=' || $key == 't.code_tiers>=' || $key == 't.code_tiers<=') {
591
					$sqlwhere[] = $key . '\'' . $this->db->escape($value) . '\'';
592
				} elseif ($key == 't.fk_doc' || $key == 't.fk_docdet' || $key == 't.piece_num') {
593
					$sqlwhere[] = $key . '=' . $value;
594
				} elseif ($key == 't.code_tiers' || $key == 't.numero_compte') {
595
					$sqlwhere[] = $key . ' LIKE \'' . $this->db->escape($value) . '%\'';
596
				} elseif ($key == 't.label_compte') {
597
					$sqlwhere[] = $key . ' LIKE \'' . $this->db->escape($value) . '%\'';
598
				}else {
599
					$sqlwhere[] = $key . ' LIKE \'%' . $this->db->escape($value) . '%\'';
600
				}
601
			}
602
		}
603
		$sql.= ' WHERE 1 = 1';
604
	    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
605
		if (count($sqlwhere) > 0) {
606
			$sql .= ' AND ' . implode(' ' . $filtermode . ' ', $sqlwhere);
607
		}
608
        // Affichage par compte comptable
609
        $sql .= ' ORDER BY t.numero_compte ASC';
610
		if (! empty($sortfield)) {
611
            $sql .= ', ' . $sortfield . ' ' .$sortorder;
612
		}
613
		if (! empty($limit)) {
614
			$sql .= ' ' . $this->db->plimit($limit + 1, $offset);
615
		} 
616
		$this->lines = array ();
617
		
618
		$resql = $this->db->query($sql);
619
		if ($resql) {
620
			$num = $this->db->num_rows($resql);
621
			
622
			while ( $obj = $this->db->fetch_object($resql) ) {
623
				$line = new BookKeepingLine();
624
				
625
				$line->id = $obj->rowid;
626
				
627
				$line->doc_date = $this->db->jdate($obj->doc_date);
1 ignored issue
show
Documentation Bug introduced by
It seems like $this->db->jdate($obj->doc_date) can also be of type integer. However, the property $doc_date is declared as type string. Maybe add an additional type check?

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

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

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

class Id
{
    public $id;

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

}

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

$account_id = false;

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

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
628
				$line->doc_type = $obj->doc_type;
629
				$line->doc_ref = $obj->doc_ref;
630
				$line->fk_doc = $obj->fk_doc;
631
				$line->fk_docdet = $obj->fk_docdet;
632
				$line->code_tiers = $obj->code_tiers;
633
				$line->numero_compte = $obj->numero_compte;
634
				$line->label_compte = $obj->label_compte;
635
				$line->debit = $obj->debit;
636
				$line->credit = $obj->credit;
637
				$line->montant = $obj->montant;
638
				$line->sens = $obj->sens;
639
				$line->fk_user_author = $obj->fk_user_author;
640
				$line->import_key = $obj->import_key;
641
				$line->code_journal = $obj->code_journal;
642
				$line->piece_num = $obj->piece_num;
643
				
644
				$this->lines[] = $line;
645
			}
646
			$this->db->free($resql);
647
			
648
			return $num;
649
		} else {
650
			$this->errors[] = 'Error ' . $this->db->lasterror();
651
			dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR);
652
			
653
			return - 1;
654
		}
655
	}
656
  
657
	
658
	/**
659
	 * Load object in memory from the database
660
	 *
661
	 * @param string $sortorder Sort Order
662
	 * @param string $sortfield Sort field
663
	 * @param int $limit offset limit
664
	 * @param int $offset offset limit
665
	 * @param array $filter filter array
666
	 * @param string $filtermode filter mode (AND or OR)
667
	 *       
668
	 * @return int <0 if KO, >0 if OK
669
	 */
670
	public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') {
671
		global $conf;
672
		
673
	    dol_syslog(__METHOD__, LOG_DEBUG);
674
		
675
		$sql = 'SELECT';
676
		$sql .= ' t.rowid,';
677
		$sql .= " t.doc_date,";
678
		$sql .= " t.doc_type,";
679
		$sql .= " t.doc_ref,";
680
		$sql .= " t.fk_doc,";
681
		$sql .= " t.fk_docdet,";
682
		$sql .= " t.code_tiers,";
683
		$sql .= " t.numero_compte,";
684
		$sql .= " t.label_compte,";
685
		$sql .= " t.debit,";
686
		$sql .= " t.credit,";
687
		$sql .= " t.montant,";
688
		$sql .= " t.sens,";
689
		$sql .= " t.fk_user_author,";
690
		$sql .= " t.import_key,";
691
		$sql .= " t.code_journal,";
692
		$sql .= " t.piece_num";
693
		$sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t';
694
		// Manage filter
695
		$sqlwhere = array ();
696
		if (count($filter) > 0) {
697
			foreach ( $filter as $key => $value ) {
698
				if ($key == 't.doc_date') {
699
					$sqlwhere[] = $key . '=\'' . $this->db->idate($value) . '\'';
700
				} elseif ($key == 't.doc_date>=' || $key == 't.doc_date<=') {
701
					$sqlwhere[] = $key . '\'' . $this->db->idate($value) . '\'';
702
				} elseif ($key == 't.numero_compte>=' || $key == 't.numero_compte<=' || $key == 't.code_tiers>=' || $key == 't.code_tiers<=') {
703
					$sqlwhere[] = $key . '\'' . $this->db->escape($value) . '\'';
704
				} elseif ($key == 't.fk_doc' || $key == 't.fk_docdet' || $key == 't.piece_num') {
705
					$sqlwhere[] = $key . '=' . $value;
706
				} elseif ($key == 't.code_tiers' || $key == 't.numero_compte') {
707
					$sqlwhere[] = $key . ' LIKE \'' . $this->db->escape($value) . '%\'';
708
				} else {
709
					$sqlwhere[] = $key . ' LIKE \'%' . $this->db->escape($value) . '%\'';
710
				}
711
			}
712
		}
713
		$sql.= ' WHERE 1 = 1';
714
	    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
715
		if (count($sqlwhere) > 0) {
716
			$sql .= ' AND ' . implode(' ' . $filtermode . ' ', $sqlwhere);
717
		}
718
		
719
		if (! empty($sortfield)) {
720
			$sql .= $this->db->order($sortfield, $sortorder);
721
		}
722
		if (! empty($limit)) {
723
			$sql .= ' ' . $this->db->plimit($limit + 1, $offset);
724
		}
725
		$this->lines = array ();
726
		
727
		$resql = $this->db->query($sql);
728
		if ($resql) {
729
			$num = $this->db->num_rows($resql);
730
			
731
			while ( $obj = $this->db->fetch_object($resql) ) {
732
				$line = new BookKeepingLine();
733
				
734
				$line->id = $obj->rowid;
735
				
736
				$line->doc_date = $this->db->jdate($obj->doc_date);
1 ignored issue
show
Documentation Bug introduced by
It seems like $this->db->jdate($obj->doc_date) can also be of type integer. However, the property $doc_date is declared as type string. Maybe add an additional type check?

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

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

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

class Id
{
    public $id;

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

}

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

$account_id = false;

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

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
737
				$line->doc_type = $obj->doc_type;
738
				$line->doc_ref = $obj->doc_ref;
739
				$line->fk_doc = $obj->fk_doc;
740
				$line->fk_docdet = $obj->fk_docdet;
741
				$line->code_tiers = $obj->code_tiers;
742
				$line->numero_compte = $obj->numero_compte;
743
				$line->label_compte = $obj->label_compte;
744
				$line->debit = $obj->debit;
745
				$line->credit = $obj->credit;
746
				$line->montant = $obj->montant;
747
				$line->sens = $obj->sens;
748
				$line->fk_user_author = $obj->fk_user_author;
749
				$line->import_key = $obj->import_key;
750
				$line->code_journal = $obj->code_journal;
751
				$line->piece_num = $obj->piece_num;
752
				
753
				$this->lines[] = $line;
754
			}
755
			$this->db->free($resql);
756
			
757
			return $num;
758
		} else {
759
			$this->errors[] = 'Error ' . $this->db->lasterror();
760
			dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR);
761
			
762
			return - 1;
763
		}
764
	}
765
	
766
	/**
767
	 * Load object in memory from the database
768
	 *
769
	 * @param string $sortorder Sort Order
770
	 * @param string $sortfield Sort field
771
	 * @param int $limit offset limit
772
	 * @param int $offset offset limit
773
	 * @param array $filter filter array
774
	 * @param string $filtermode filter mode (AND or OR)
775
	 *
776
	 * @return int <0 if KO, >0 if OK
777
	 */
778
	public function fetchAllBalance($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') {
779
		global $conf;
780
		
781
	    dol_syslog(__METHOD__, LOG_DEBUG);
782
	
783
		$sql = 'SELECT';
784
		$sql .= " t.numero_compte,";
785
		$sql .= " SUM(t.debit) as debit,";
786
		$sql .= " SUM(t.credit) as credit";
787
		$sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t';
788
		// Manage filter
789
		$sqlwhere = array ();
790
		if (count($filter) > 0) {
791
			foreach ( $filter as $key => $value ) {
792
				if ($key == 't.doc_date') {
793
					$sqlwhere[] = $key . '=\'' . $this->db->idate($value) . '\'';
794
				} elseif ($key == 't.doc_date>=' || $key == 't.doc_date<=') {
795
					$sqlwhere[] = $key . '\'' . $this->db->idate($value) . '\'';
796
				} elseif ($key == 't.numero_compte>=' || $key == 't.numero_compte<=' || $key == 't.code_tiers>=' || $key == 't.code_tiers<=') {
797
					$sqlwhere[] = $key . '\'' . $this->db->escape($value) . '\'';
798
				} elseif ($key == 't.fk_doc' || $key == 't.fk_docdet' || $key == 't.piece_num') {
799
					$sqlwhere[] = $key . '=' . $value;
800
				} elseif ($key == 't.code_tiers' || $key == 't.numero_compte') {
801
					$sqlwhere[] = $key . ' LIKE \'' . $this->db->escape($value) . '%\'';
802
				} else {
803
					$sqlwhere[] = $key . ' LIKE \'%' . $this->db->escape($value) . '%\'';
804
				}
805
			}
806
		}
807
		$sql.= ' WHERE 1 = 1';
808
	    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
809
		if (count($sqlwhere) > 0) {
810
			$sql .= ' AND ' . implode(' ' . $filtermode . ' ', $sqlwhere);
811
		}
812
		
813
		$sql .= ' GROUP BY t.numero_compte';
814
	
815
		if (! empty($sortfield)) {
816
			$sql .= $this->db->order($sortfield, $sortorder); 
817
		}
818
		if (! empty($limit)) {
819
			$sql .= ' ' . $this->db->plimit($limit + 1, $offset);
820
		}
821
		$this->lines = array ();
822
	
823
		$resql = $this->db->query($sql);
824
		if ($resql) {
825
			$num = $this->db->num_rows($resql);
826
	
827
			while ( $obj = $this->db->fetch_object($resql) ) {
828
				$line = new BookKeepingLine();
829
				
830
				$line->numero_compte = $obj->numero_compte;
831
				$line->debit = $obj->debit;
832
				$line->credit = $obj->credit;
833
				$this->lines[] = $line;
834
			}
835
			$this->db->free($resql);
836
	
837
			return $num;
838
		} else {
839
			$this->errors[] = 'Error ' . $this->db->lasterror();
840
			dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR);
841
	
842
			return - 1;
843
		}
844
	}
845
	
846
	/**
847
	 * Update object into database
848
	 *
849
	 * @param User $user User that modifies
850
	 * @param bool $notrigger false=launch triggers after, true=disable triggers
851
	 *       
852
	 * @return int <0 if KO, >0 if OK
853
	 */
854
	public function update(User $user, $notrigger = false) {
855
		$error = 0;
856
		
857
		dol_syslog(__METHOD__, LOG_DEBUG);
858
		
859
		// Clean parameters
860
		
861
		if (isset($this->doc_type)) {
862
			$this->doc_type = trim($this->doc_type);
863
		}
864
		if (isset($this->doc_ref)) {
865
			$this->doc_ref = trim($this->doc_ref);
866
		}
867
		if (isset($this->fk_doc)) {
868
			$this->fk_doc = trim($this->fk_doc);
869
		}
870
		if (isset($this->fk_docdet)) {
871
			$this->fk_docdet = trim($this->fk_docdet);
872
		}
873
		if (isset($this->code_tiers)) {
874
			$this->code_tiers = trim($this->code_tiers);
875
		}
876
		if (isset($this->numero_compte)) {
877
			$this->numero_compte = trim($this->numero_compte);
878
		}
879
		if (isset($this->label_compte)) {
880
			$this->label_compte = trim($this->label_compte);
881
		}
882
		if (isset($this->debit)) {
883
			$this->debit = trim($this->debit);
884
		}
885
		if (isset($this->credit)) {
886
			$this->credit = trim($this->credit);
887
		}
888
		if (isset($this->montant)) {
889
			$this->montant = trim($this->montant);
890
		}
891
		if (isset($this->sens)) {
892
			$this->sens = trim($this->sens);
893
		}
894
		if (isset($this->fk_user_author)) {
895
			$this->fk_user_author = trim($this->fk_user_author);
896
		}
897
		if (isset($this->import_key)) {
898
			$this->import_key = trim($this->import_key);
899
		}
900
		if (isset($this->code_journal)) {
901
			$this->code_journal = trim($this->code_journal);
902
		}
903
		if (isset($this->piece_num)) {
904
			$this->piece_num = trim($this->piece_num);
905
		}
906
		
907
		// Check parameters
908
		// Put here code to add a control on parameters values
909
		
910
		// Update request
911
		$sql = 'UPDATE ' . MAIN_DB_PREFIX . $this->table_element . ' SET';
912
		$sql .= ' doc_date = ' . (! isset($this->doc_date) || dol_strlen($this->doc_date) != 0 ? "'" . $this->db->idate($this->doc_date) . "'" : 'null') . ',';
913
		$sql .= ' doc_type = ' . (isset($this->doc_type) ? "'" . $this->db->escape($this->doc_type) . "'" : "null") . ',';
914
		$sql .= ' doc_ref = ' . (isset($this->doc_ref) ? "'" . $this->db->escape($this->doc_ref) . "'" : "null") . ',';
915
		$sql .= ' fk_doc = ' . (isset($this->fk_doc) ? $this->fk_doc : "null") . ',';
916
		$sql .= ' fk_docdet = ' . (isset($this->fk_docdet) ? $this->fk_docdet : "null") . ',';
917
		$sql .= ' code_tiers = ' . (isset($this->code_tiers) ? "'" . $this->db->escape($this->code_tiers) . "'" : "null") . ',';
918
		$sql .= ' numero_compte = ' . (isset($this->numero_compte) ? "'" . $this->db->escape($this->numero_compte) . "'" : "null") . ',';
919
		$sql .= ' label_compte = ' . (isset($this->label_compte) ? "'" . $this->db->escape($this->label_compte) . "'" : "null") . ',';
920
		$sql .= ' debit = ' . (isset($this->debit) ? $this->debit : "null") . ',';
921
		$sql .= ' credit = ' . (isset($this->credit) ? $this->credit : "null") . ',';
922
		$sql .= ' montant = ' . (isset($this->montant) ? $this->montant : "null") . ',';
923
		$sql .= ' sens = ' . (isset($this->sens) ? "'" . $this->db->escape($this->sens) . "'" : "null") . ',';
924
		$sql .= ' fk_user_author = ' . (isset($this->fk_user_author) ? $this->fk_user_author : "null") . ',';
925
		$sql .= ' import_key = ' . (isset($this->import_key) ? "'" . $this->db->escape($this->import_key) . "'" : "null") . ',';
926
		$sql .= ' code_journal = ' . (isset($this->code_journal) ? "'" . $this->db->escape($this->code_journal) . "'" : "null") . ',';
927
		$sql .= ' piece_num = ' . (isset($this->piece_num) ? $this->piece_num : "null");
928
		$sql .= ' WHERE rowid=' . $this->id;
929
		
930
		$this->db->begin();
931
		
932
		$resql = $this->db->query($sql);
933
		if (! $resql) {
934
			$error ++;
935
			$this->errors[] = 'Error ' . $this->db->lasterror();
936
			dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR);
937
		}
938
		
939
		if (! $error && ! $notrigger) {
940
			// Uncomment this and change MYOBJECT to your own tag if you
941
			// want this action calls a trigger.
942
			
943
			// // Call triggers
944
			// $result=$this->call_trigger('MYOBJECT_MODIFY',$user);
945
			// if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail}
946
			// // End call triggers
947
		}
948
		
949
		// Commit or rollback
950
		if ($error) {
951
			$this->db->rollback();
952
			
953
			return - 1 * $error;
954
		} else {
955
			$this->db->commit();
956
			
957
			return 1;
958
		}
959
	}
960
	
961
	/**
962
	 * Delete object in database
963
	 *
964
	 * @param User $user User that deletes
965
	 * @param bool $notrigger false=launch triggers after, true=disable triggers
966
	 *       
967
	 * @return int <0 if KO, >0 if OK
968
	 */
969
	public function delete(User $user, $notrigger = false) {
970
		dol_syslog(__METHOD__, LOG_DEBUG);
971
		
972
		$error = 0;
973
		
974
		$this->db->begin();
975
		
976
		if (! $error) {
977
			if (! $notrigger) {
978
				// Uncomment this and change MYOBJECT to your own tag if you
979
				// want this action calls a trigger.
980
				
981
				// // Call triggers
982
				// $result=$this->call_trigger('MYOBJECT_DELETE',$user);
983
				// if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail}
984
				// // End call triggers
985
			}
986
		}
987
		
988
		if (! $error) {
989
			$sql = 'DELETE FROM ' . MAIN_DB_PREFIX . $this->table_element;
990
			$sql .= ' WHERE rowid=' . $this->id;
991
			
992
			$resql = $this->db->query($sql);
993
			if (! $resql) {
994
				$error ++;
995
				$this->errors[] = 'Error ' . $this->db->lasterror();
996
				dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR);
997
			}
998
		}
999
		
1000
		// Commit or rollback
1001
		if ($error) {
1002
			$this->db->rollback();
1003
			
1004
			return - 1 * $error;
1005
		} else {
1006
			$this->db->commit();
1007
			
1008
			return 1;
1009
		}
1010
	}
1011
	
1012
	/**
1013
	 * Delete bookkepping by importkey
1014
	 *
1015
	 * @param  string       $importkey      Import key
1016
	 * @return int Result
1017
	 */
1018
	function deleteByImportkey($importkey) {
1019
		$this->db->begin();
1020
		
1021
		// first check if line not yet in bookkeeping
1022
		$sql = "DELETE";
1023
		$sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
1024
		$sql .= " WHERE import_key = '" . $importkey . "'";
1025
		
1026
		$resql = $this->db->query($sql);
1027
		
1028
		if (! $resql) {
1029
			$this->errors[] = "Error " . $this->db->lasterror();
1030
			dol_syslog(get_class($this)."::delete Error " . $this->db->lasterror(), LOG_ERR);
1031
			$this->db->rollback();
1032
			return - 1;
1033
		}
1034
		
1035
		$this->db->commit();
1036
		return 1;
1037
	}
1038
	
1039
	/**
1040
	 * Delete bookkepping by year
1041
	 *
1042
	 * @param  string $delyear      Year to delete
1043
	 * @param  string $journal      Journal to delete
1044
	 * @return int                  <0 if KO, >0 if OK
1045
	 */
1046
	function deleteByYearAndJournal($delyear='', $journal='') {
1047
	    global $conf;
1048
	    
1049
	    if (empty($delyear) && empty($journal)) 
1050
	    {
1051
	        return -1;
1052
	    }
1053
	    
1054
		$this->db->begin();
1055
		
1056
		// first check if line not yet in bookkeeping
1057
		$sql = "DELETE";
1058
		$sql.= " FROM " . MAIN_DB_PREFIX . $this->table_element;
1059
		$sql.= " WHERE 1 = 1";
1060
		if (! empty($delyear)) $sql.= " AND YEAR(doc_date) = " . $delyear;         // FIXME Must use between
1061
		if (! empty($journal)) $sql.= " AND code_journal = '".$journal."'";
1062
	    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
1063
		$resql = $this->db->query($sql);
1064
		
1065
		if (! $resql) {
1066
			$this->errors[] = "Error " . $this->db->lasterror();
1067
			foreach ( $this->errors as $errmsg ) {
1068
				dol_syslog(get_class($this) . "::delete " . $errmsg, LOG_ERR);
1069
				$this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
1070
			}
1071
			$this->db->rollback();
1072
			return -1;
1073
		}
1074
		
1075
		$this->db->commit();
1076
		return 1;
1077
	}
1078
	
1079
	/**
1080
	 * Delete bookkepping by piece number
1081
	 *
1082
	 * @param int $piecenum peicenum to delete
1083
	 * @return int Result
1084
	 */
1085
	function deleteMvtNum($piecenum) {
1086
	    global $conf;
1087
	    
1088
		$this->db->begin();
1089
		
1090
		// first check if line not yet in bookkeeping
1091
		$sql = "DELETE";
1092
		$sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
1093
		$sql .= " WHERE piece_num = " . $piecenum;
1094
	    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
1095
		
1096
		$resql = $this->db->query($sql);
1097
		
1098
		if (! $resql) {
1099
			$this->errors[] = "Error " . $this->db->lasterror();
1100
			foreach ( $this->errors as $errmsg ) {
1101
				dol_syslog(get_class($this) . "::delete " . $errmsg, LOG_ERR);
1102
				$this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
1103
			}
1104
			$this->db->rollback();
1105
			return - 1;
1106
		}
1107
		
1108
		$this->db->commit();
1109
		return 1;
1110
	}
1111
	
1112
	/**
1113
	 * Load an object from its id and create a new one in database
1114
	 *
1115
	 * @param int $fromid Id of object to clone
1116
	 *       
1117
	 * @return int New id of clone
1118
	 */
1119
	public function createFromClone($fromid) {
1120
		dol_syslog(__METHOD__, LOG_DEBUG);
1121
		
1122
		global $user;
1123
		$error = 0;
1124
		$object = new Accountingbookkeeping($this->db);
1125
		
1126
		$this->db->begin();
1127
		
1128
		// Load source object
1129
		$object->fetch($fromid);
1130
		// Reset object
1131
		$object->id = 0;
1132
		
1133
		// Clear fields
1134
		// ...
1135
		
1136
		// Create clone
1137
		$result = $object->create($user);
1138
		
1139
		// Other options
1140
		if ($result < 0) {
1141
			$error ++;
1142
			$this->errors = $object->errors;
1143
			dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR);
1144
		}
1145
		
1146
		// End
1147
		if (! $error) {
1148
			$this->db->commit();
1149
			
1150
			return $object->id;
1151
		} else {
1152
			$this->db->rollback();
1153
			
1154
			return - 1;
1155
		}
1156
	}
1157
	
1158
	/**
1159
	 * Initialise object with example values
1160
	 * Id must be 0 if object instance is a specimen
1161
	 *
1162
	 * @return void
1163
	 */
1164
	public function initAsSpecimen() {
1165
		$this->id = 0;
1166
		
1167
		$this->doc_date = '';
1168
		$this->doc_type = '';
1169
		$this->doc_ref = '';
1170
		$this->fk_doc = '';
1171
		$this->fk_docdet = '';
1172
		$this->code_tiers = '';
1173
		$this->numero_compte = '';
1174
		$this->label_compte = '';
1175
		$this->debit = '';
1176
		$this->credit = '';
1177
		$this->montant = '';
1178
		$this->sens = '';
1179
		$this->fk_user_author = '';
1180
		$this->import_key = '';
1181
		$this->code_journal = '';
1182
		$this->piece_num = '';
1183
	}
1184
	
1185
	/**
1186
	 * Load an accounting document into memory from database
1187
	 *
1188
	 * @param int $piecenum Accounting document to get
1189
	 * @return int <0 if KO, >0 if OK
1190
	 */
1191
	public function fetchPerMvt($piecenum) {
1192
		global $conf;
1193
		
1194
	    $sql = "SELECT piece_num,doc_date,code_journal,doc_ref,doc_type";
1195
		$sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
1196
		$sql .= " WHERE piece_num = " . $piecenum;
1197
	    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
1198
		
1199
		dol_syslog(get_class($this) . "::" . __METHOD__, LOG_DEBUG);
1200
		$result = $this->db->query($sql);
1201
		if ($result) {
1202
			$obj = $this->db->fetch_object($result);
1203
			
1204
			$this->piece_num = $obj->piece_num;
1205
			$this->code_journal = $obj->code_journal;
1206
			$this->doc_date = $this->db->jdate($obj->doc_date);
1 ignored issue
show
Documentation Bug introduced by
It seems like $this->db->jdate($obj->doc_date) can also be of type integer. However, the property $doc_date is declared as type string. Maybe add an additional type check?

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

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

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

class Id
{
    public $id;

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

}

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

$account_id = false;

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

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
1207
			$this->doc_ref = $obj->doc_ref;
1208
			$this->doc_type = $obj->doc_type;
1209
		} else {
1210
			$this->error = "Error " . $this->db->lasterror();
1211
			dol_syslog(get_class($this) . "::" . __METHOD__ . $this->error, LOG_ERR);
1212
			return - 1;
1213
		}
1214
		
1215
		return 1;
1216
	}
1217
	
1218
	/**
1219
	 * Return next number movement
1220
	 *
1221
	 * @return string      Next numero to use
1222
	 */
1223
	public function getNextNumMvt() 
1224
	{
1225
	    global $conf;
1226
	    
1227
		$sql = "SELECT MAX(piece_num)+1 as max FROM " . MAIN_DB_PREFIX . $this->table_element;
1228
	    $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")";
1229
		
1230
		dol_syslog(get_class($this) . "getNextNumMvt sql=" . $sql, LOG_DEBUG);
1231
		$result = $this->db->query($sql);
1232
1233
		if ($result) {
1234
			$obj = $this->db->fetch_object($result);
1235
	        if ($obj) $result = $obj->max;
1236
	        if (empty($result)) $result = 1;
1237
	        return $result;
1238
		} else {
1239
			$this->error = "Error " . $this->db->lasterror();
1240
			dol_syslog(get_class($this) . "::getNextNumMvt " . $this->error, LOG_ERR);
1241
			return - 1;
1242
		}
1243
	}
1244
	
1245
	/**
1246
	 * Load all informations of accountancy document
1247
	 *
1248
	 * @param int $piecenum id of line to get
1249
	 * @return int <0 if KO, >0 if OK
1250
	 */
1251
	function fetch_all_per_mvt($piecenum) {
1252
	    global $conf;
1253
	    
1254
		$sql = "SELECT rowid, doc_date, doc_type,";
1255
		$sql .= " doc_ref, fk_doc, fk_docdet, code_tiers,";
1256
		$sql .= " numero_compte, label_compte, debit, credit,";
1257
		$sql .= " montant, sens, fk_user_author, import_key, code_journal, piece_num";
1258
		$sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
1259
		$sql .= " WHERE piece_num = " . $piecenum;
1260
	    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
1261
		
1262
		dol_syslog(get_class($this) . "::" . __METHOD__, LOG_DEBUG);
1263
		$result = $this->db->query($sql);
1264
		if ($result) {
1265
			
1266
			while ( $obj = $this->db->fetch_object($result) ) {
1267
				
1268
				$line = new BookKeepingLine();
1269
				
1270
				$line->id = $obj->rowid;
1271
				
1272
				$line->doc_date = $this->db->jdate($obj->doc_date);
1 ignored issue
show
Documentation Bug introduced by
It seems like $this->db->jdate($obj->doc_date) can also be of type integer. However, the property $doc_date is declared as type string. Maybe add an additional type check?

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

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

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

class Id
{
    public $id;

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

}

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

$account_id = false;

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

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
1273
				$line->doc_type = $obj->doc_type;
1274
				$line->doc_ref = $obj->doc_ref;
1275
				$line->fk_doc = $obj->fk_doc;
1276
				$line->fk_docdet = $obj->fk_docdet;
1277
				$line->code_tiers = $obj->code_tiers;
1278
				$line->numero_compte = $obj->numero_compte;
1279
				$line->label_compte = $obj->label_compte;
1280
				$line->debit = $obj->debit;
1281
				$line->credit = $obj->credit;
1282
				$line->montant = $obj->montant;
1283
				$line->sens = $obj->sens;
1284
				$line->code_journal = $obj->code_journal;
1285
				$line->piece_num = $obj->piece_num;
1286
				
1287
				$this->linesmvt[] = $line;
1288
			}
1289
		} else {
1290
			$this->error = "Error " . $this->db->lasterror();
1291
			dol_syslog(get_class($this) . "::" . __METHOD__ . $this->error, LOG_ERR);
1292
			return - 1;
1293
		}
1294
		
1295
		return 1;
1296
	}
1297
	
1298
	/**
1299
	 * Export bookkeping
1300
	 *
1301
	 * @param string $model Model
1302
	 * @return int Result
1303
	 */
1304
	function export_bookkeping($model = 'ebp') {
1305
	    global $conf;
1306
	    
1307
		$sql = "SELECT rowid, doc_date, doc_type,";
1308
		$sql .= " doc_ref, fk_doc, fk_docdet, code_tiers,";
1309
		$sql .= " numero_compte, label_compte, debit, credit,";
1310
		$sql .= " montant, sens, fk_user_author, import_key, code_journal, piece_num";
1311
		$sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
1312
	    $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")";
1313
		
1314
		dol_syslog(get_class($this) . "::export_bookkeping", LOG_DEBUG);
1315
		
1316
		$resql = $this->db->query($sql);
1317
		
1318
		if ($resql) {
1319
			$this->linesexport = array ();
1320
			
1321
			$num = $this->db->num_rows($resql);
1322
			while ( $obj = $this->db->fetch_object($resql) ) {
1323
				$line = new BookKeepingLine();
1324
				
1325
				$line->id = $obj->rowid;
1326
				
1327
				$line->doc_date = $this->db->jdate($obj->doc_date);
1 ignored issue
show
Documentation Bug introduced by
It seems like $this->db->jdate($obj->doc_date) can also be of type integer. However, the property $doc_date is declared as type string. Maybe add an additional type check?

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

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

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

class Id
{
    public $id;

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

}

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

$account_id = false;

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

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
1328
				$line->doc_type = $obj->doc_type;
1329
				$line->doc_ref = $obj->doc_ref;
1330
				$line->fk_doc = $obj->fk_doc;
1331
				$line->fk_docdet = $obj->fk_docdet;
1332
				$line->code_tiers = $obj->code_tiers;
1333
				$line->numero_compte = $obj->numero_compte;
1334
				$line->label_compte = $obj->label_compte;
1335
				$line->debit = $obj->debit;
1336
				$line->credit = $obj->credit;
1337
				$line->montant = $obj->montant;
1338
				$line->sens = $obj->sens;
1339
				$line->code_journal = $obj->code_journal;
1340
				$line->piece_num = $obj->piece_num;
1341
				
1342
				$this->linesexport[] = $line;
1343
			}
1344
			$this->db->free($resql);
1345
			
1346
			return $num;
1347
		} else {
1348
			$this->error = "Error " . $this->db->lasterror();
1349
			dol_syslog(get_class($this) . "::export_bookkeping " . $this->error, LOG_ERR);
1350
			return - 1;
1351
		}
1352
	}
1353
  
1354
  
1355
  
1356
    /**
1357
    * Return list of accounts with label by chart of accounts
1358
    *
1359
    * @param string  $selectid   Preselected chart of accounts
1360
    * @param string  $htmlname   Name of field in html form
1361
    * @param int     $showempty  Add an empty field
1362
    * @param array   $event      Event options
1363
    * @param int     $select_in  Value is a aa.rowid (0 default) or aa.account_number (1)
1364
    * @param int     $select_out Set value returned by select 0=rowid (default), 1=account_number
1365
    * @param int     $aabase     Set accounting_account base class to display empty=all or from 1 to 8 will display only account beginning by this number
1366
    * @return string String with HTML select
1367
    */
1368
    function select_account($selectid, $htmlname = 'account', $showempty = 0, $event = array(), $select_in = 0, $select_out = 0, $aabase = '') {
1369
        global $conf;
1370
        
1371
        require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php';
1372
        
1373
        $pcgver = $conf->global->CHARTOFACCOUNTS;
1374
        
1375
        $sql = "SELECT DISTINCT ab.numero_compte as account_number, aa.label as label, aa.rowid as rowid, aa.fk_pcg_version";
1376
        $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as ab";
1377
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.account_number = ab.numero_compte";
1378
        $sql .= " AND aa.active = 1";
1379
        $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version";
1380
        $sql .= " AND asy.rowid = " . $pcgver;
1381
	    $sql .= " AND ab.entity IN (" . getEntity("accountancy", 1) . ")";
1382
        $sql .= " ORDER BY account_number ASC";
1383
        
1384
        dol_syslog(get_class($this) . "::select_account", LOG_DEBUG);
1385
        $resql = $this->db->query($sql);
1386
        
1387
        if (! $resql) {
1388
            $this->error = "Error " . $this->db->lasterror();
1389
            dol_syslog(get_class($this) . "::select_account " . $this->error, LOG_ERR);
1390
            return - 1;
1391
        }
1392
        
1393
        $out = ajax_combobox($htmlname, $event);
1394
        
1395
        $options = array();
1396
        $selected = null;
1397
        
1398
        while ($obj = $this->db->fetch_object($resql)) {
1399
            $label = length_accountg($obj->account_number) . ' - ' . $obj->label;
1400
            
1401
            $select_value_in = $obj->rowid;
1402
            $select_value_out = $obj->rowid;
1403
            
1404
            if ($select_in == 1) {
1405
                $select_value_in = $obj->account_number;
1406
            }
1407
            if ($select_out == 1) {
1408
                $select_value_out = $obj->account_number;
1409
            }
1410
            
1411
            // Remember guy's we store in database llx_facturedet the rowid of accounting_account and not the account_number
1412
            // Because same account_number can be share between different accounting_system and do have the same meaning
1413
            if (($selectid != '') && $selectid == $select_value_in) {
1414
                $selected = $select_value_out;
1415
            }
1416
            
1417
            $options[$select_value_out] = $label;
1418
        }
1419
        
1420
        $out .= Form::selectarray($htmlname, $options, $selected, $showempty, 0, 0, '', 0, 0, 0, '', 'maxwidth300');
1421
        $this->db->free($resql);
1422
        return $out;
1423
    }
1424
1425
  
1426
	
1427
	/**
1428
	* Description of a root accounting account 
1429
	*
1430
	* @param 	string 	$account	Accounting account
1431
	* @return 	string 	            Root account
1432
	*/
1433
	function get_compte_racine($account = null)
1434
	{	
1435
		global $conf;
1436
		$pcgver = $conf->global->CHARTOFACCOUNTS;
1437
        
1438
        $sql  = "SELECT root.account_number, root.label as label";
1439
        $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as aa";
1440
        $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version";
1441
        $sql .= " AND asy.rowid = " . $pcgver;
1442
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as parent ON aa.account_parent = parent.rowid";
1443
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as root ON parent.account_parent = root.rowid";
1444
        $sql .= " WHERE aa.account_number = '" . $account . "'";  
1445
        $sql .= " AND parent.active = 1";
1446
        $sql .= " AND root.active = 1";
1447
        $sql .= " AND aa.entity IN (" . getEntity("accountancy", 1) . ")";
1448
        
1449
		dol_syslog(get_class($this) . "::select_account sql=" . $sql, LOG_DEBUG);
1450
		$resql = $this->db->query($sql);
1451
		if ($resql) {
1452
			$obj = '';
1453
			if ($this->db->num_rows($resql)) {
1454
				$obj = $this->db->fetch_object($resql);	
1455
			}
1456
							
1457
			return $obj->label;
1458
			
1459
		} else {
1460
			$this->error = "Error " . $this->db->lasterror();
1461
			dol_syslog(__METHOD__ . " " . $this->error, LOG_ERR);
1462
1463
			return -1;
1464
		}
1465
	}
1466
  
1467
  
1468
  /**
1469
	* Description of accounting account
1470
	*
1471
	* @param 	string 	$account	Accounting account
1472
	* @return 	string 	            Account desc
1473
	*/
1474
	function get_compte_desc($account = null)
1475
	{	
1476
		global $conf;
1477
		
1478
		$pcgver = $conf->global->CHARTOFACCOUNTS;
1479
		$sql  = "SELECT aa.account_number, aa.label, aa.rowid, aa.fk_pcg_version, cat.label as category";
1480
		$sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as aa ";
1481
		$sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version";
1482
		$sql .= " AND aa.account_number = '" . $account . "'";
1483
		$sql .= " AND asy.rowid = " . $pcgver;
1484
		$sql .= " AND aa.active = 1";
1485
		$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_accounting_category as cat ON aa.fk_accounting_category = cat.rowid";
1486
	    $sql .= " WHERE aa.entity IN (" . getEntity("accountancy", 1) . ")";
1487
		
1488
		dol_syslog(get_class($this) . "::select_account sql=" . $sql, LOG_DEBUG);
1489
		$resql = $this->db->query($sql);
1490
		if ($resql) {
1491
			$obj = '';
1492
			if ($this->db->num_rows($resql)) {
1493
				$obj = $this->db->fetch_object($resql);	
1494
			}
1495
			
1496
			if(empty($obj->category)){				
1497
				return $obj->label;
1498
			}else{
1499
				return $obj->label.' ('.$obj->category.')';
1500
				
1501
			}
1502
		} else {
1503
			$this->error = "Error " . $this->db->lasterror();
1504
			dol_syslog(__METHOD__ . " " . $this->error, LOG_ERR);
1505
			return -1;
1506
		}
1507
	}
1508
	
1509
}
1510
1511
1512
/**
1513
 * Class BookKeepingLine
1514
 */
1515
class BookKeepingLine
1516
{
1517
	public $id;
1518
	public $doc_date = '';
1519
	public $doc_type;
1520
	public $doc_ref;
1521
	public $fk_doc;
1522
	public $fk_docdet;
1523
	public $code_tiers;
1524
	public $numero_compte;
1525
	public $label_compte;
1526
	public $debit;
1527
	public $credit;
1528
	public $montant;
1529
	public $sens;
1530
	public $fk_user_author;
1531
	public $import_key;
1532
	public $code_journal;
1533
	public $piece_num;
1534
}
1535