Passed
Pull Request — master (#2)
by
unknown
26:19
created

Account::addline()   F

Complexity

Conditions 16
Paths 270

Size

Total Lines 98
Code Lines 61

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
eloc 61
nc 270
nop 11
dl 0
loc 98
rs 3.8583
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/* Copyright (C) 2001-2007	Rodolphe Quiedeville	<[email protected]>
3
 * Copyright (C) 2003		Jean-Louis Bergamo		<[email protected]>
4
 * Copyright (C) 2004-2012	Laurent Destailleur		<[email protected]>
5
 * Copyright (C) 2004		Christophe Combelles	<[email protected]>
6
 * Copyright (C) 2005-2010	Regis Houssin			<[email protected]>
7
 * Copyright (C) 2013		Florian Henry			<[email protected]>
8
 * Copyright (C) 2015-2016	Marcos García			<[email protected]>
9
 * Copyright (C) 2015-2017	Alexandre Spangaro		<[email protected]>
10
 * Copyright (C) 2016		Ferran Marcet   		<[email protected]>
11
 *
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 3 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
 */
25
26
/**
27
 *	\file       htdocs/compta/bank/class/account.class.php
28
 *	\ingroup    bank
29
 *	\brief      File of class to manage bank accounts
30
 */
31
require_once DOL_DOCUMENT_ROOT .'/core/class/commonobject.class.php';
32
33
34
/**
35
 *	Class to manage bank accounts
36
 */
37
class Account extends CommonObject
38
{
39
	/**
40
	 * @var string ID to identify managed object
41
	 */
42
	public $element = 'bank_account';
43
44
	/**
45
	 * @var string Name of table without prefix where object is stored
46
	 */
47
	public $table_element = 'bank_account';
48
49
	/**
50
	 * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
51
	 */
52
	public $picto = 'account';
53
54
	/**
55
	 * @var	int		Use id instead of rowid
56
	 * @deprecated
57
	 * @see $id
58
	 */
59
	public $rowid;
60
61
	/**
62
	 * Account Label
63
	 * @var string
64
	 */
65
	public $label;
66
67
	/**
68
	 * Bank account type. Check TYPE_ constants
69
	 * @var int
70
	 */
71
	public $courant;
72
73
	/**
74
	 * Bank account type. Check TYPE_ constants
75
	 * @var int
76
	 */
77
	public $type;
78
79
	/**
80
	 * Bank name
81
	 * @var string
82
	 */
83
	public $bank;
84
85
	/**
86
	 * Status
87
	 * @var int
88
	 */
89
	public $clos = self::STATUS_OPEN;
90
91
	/**
92
	 * Does it need to be conciliated?
93
	 * @var int
94
	 */
95
	public $rappro=1;
96
97
	/**
98
	 * Webpage
99
	 * @var string
100
	 */
101
	public $url;
102
103
	/**
104
	 * Bank number. If in SEPA area, you should move to IBAN field
105
	 * @var string
106
	 */
107
	public $code_banque;
108
109
	/**
110
	 * Branch number. If in SEPA area, you should move to IBAN field
111
	 * @var string
112
	 */
113
	public $code_guichet;
114
115
	/**
116
	 * Account number. If in SEPA area, you should move to IBAN field
117
	 * @var string
118
	 */
119
	public $number;
120
121
	/**
122
	 * Bank account number control digit. If in SEPA area, you should move to IBAN field
123
	 * @var string
124
	 */
125
	public $cle_rib;
126
127
	/**
128
	 * BIC/Swift code
129
	 * @var string
130
	 */
131
	public $bic;
132
133
	/**
134
	 * IBAN number (International Bank Account Number). Stored into iban_prefix field into database
135
	 * @var
136
	 */
137
	public $iban;
138
139
	/**
140
	 * Name of account holder
141
	 * @var string
142
	 */
143
	public $proprio;
144
145
	/**
146
	 * Address of account holder
147
	 * @var string
148
	 */
149
	public $owner_address;
150
151
	public $state_id;
152
	public $state_code;
153
	public $state;
154
155
	/**
156
	 * Variable containing all account types with their respective translated label.
157
	 * Defined in __construct
158
	 * @var array
159
	 */
160
	public $type_lib = array();
161
162
	/**
163
	 * Variable containing all account statuses with their respective translated label.
164
	 * Defined in __construct
165
	 * @var array
166
	 */
167
	public $status = array();
168
169
	/**
170
	 * Accountancy code
171
	 * @var string
172
	 */
173
	public $account_number;
174
175
	/**
176
     * @var int ID
177
     */
178
	public $fk_accountancy_journal;
179
180
	/**
181
	 * Currency code
182
	 * @var string
183
	 */
184
	public $currency_code;
185
186
	/**
187
	 * Currency code
188
	 * @var string
189
	 * @deprecated Use currency_code instead
190
	 */
191
	public $account_currency_code;
192
193
	/**
194
	 * Authorized minimum balance
195
	 * @var float
196
	 */
197
	public $min_allowed;
198
199
	/**
200
	 * Desired minimum balance
201
	 * @var float
202
	 */
203
	public $min_desired;
204
205
	/**
206
	 * Notes
207
	 * @var string
208
	 */
209
	public $comment;
210
211
	/**
212
	 * Date of the initial balance. Used in Account::create
213
	 * @var int
214
	 */
215
	public $date_solde;
216
217
	/**
218
	 * Current account
219
	 */
220
	const TYPE_CURRENT = 1;
221
	/**
222
	 * Cash account
223
	 */
224
	const TYPE_CASH = 2;
225
	/**
226
	 * Savings account
227
	 */
228
	const TYPE_SAVINGS = 0;
229
230
	const STATUS_OPEN = 0;
231
	const STATUS_CLOSED = 1;
232
233
	/**
234
	 *  Constructor
235
	 *
236
	 *  @param	DoliDB		$db		Database handler
237
	 */
238
	function __construct(DoliDB $db)
239
	{
240
		global $langs;
241
242
		$this->db = $db;
243
244
		$this->solde = 0;
245
246
		$this->type_lib = array(
247
			self::TYPE_SAVINGS => $langs->trans("BankType0"),
248
			self::TYPE_CURRENT => $langs->trans("BankType1"),
249
			self::TYPE_CASH => $langs->trans("BankType2"),
250
		);
251
252
		$this->status = array(
253
			self::STATUS_OPEN => $langs->trans("StatusAccountOpened"),
254
			self::STATUS_CLOSED => $langs->trans("StatusAccountClosed")
255
		);
256
	}
257
258
	/**
259
	 * Shows the account number in the appropriate format
260
	 *
261
	 * @return string
262
	 */
263
	public function __toString()
264
	{
265
		$string = '';
266
267
		foreach ($this->getFieldsToShow() as $val) {
268
269
			if ($val == 'BankCode') {
270
				$string .= $this->code_banque.' ';
271
			} elseif ($val == 'BankAccountNumber') {
272
				$string .= $this->number.' ';
273
			} elseif ($val == 'DeskCode') {
274
				$string .= $this->code_guichet.' ';
275
			} elseif ($val == 'BankAccountNumberKey') {
276
				$string .= $this->cle_rib.' ';
277
			}elseif ($val == 'BIC') {
278
				$string .= $this->bic.' ';
279
			}elseif ($val == 'IBAN') {
280
				$string .= $this->iban.' ';
281
			}
282
		}
283
284
		return trim($string);
285
	}
286
287
288
	/**
289
	 *  Return if a bank account need to be conciliated
290
	 *
291
	 *  @return     int         1 if need to be concialiated, < 0 otherwise.
292
	 */
293
	function canBeConciliated()
294
	{
295
		global $conf;
296
297
		if (empty($this->rappro)) return -1;
298
		if ($this->courant == Account::TYPE_CASH && empty($conf->global->BANK_CAN_RECONCILIATE_CASHACCOUNT)) return -2;
299
		if ($this->clos) return -3;
300
		return 1;
301
	}
302
303
304
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
305
	/**
306
	 *      Add a link between bank line record and its source
307
	 *
308
	 *      @param	int		$line_id    Id ecriture bancaire
309
	 *      @param  int		$url_id     Id parametre url
310
	 *      @param  string	$url        Url
311
	 *      @param  string	$label      Link label
312
	 *      @param  string	$type       Type of link ('payment', 'company', 'member', ...)
313
	 *      @return int         		<0 if KO, id line if OK
314
	 */
315
	function add_url_line($line_id, $url_id, $url, $label, $type)
316
	{
317
        // phpcs:enable
318
		$sql = "INSERT INTO ".MAIN_DB_PREFIX."bank_url (";
319
		$sql.= "fk_bank";
320
		$sql.= ", url_id";
321
		$sql.= ", url";
322
		$sql.= ", label";
323
		$sql.= ", type";
324
		$sql.= ") VALUES (";
325
		$sql.= "'".$line_id."'";
326
		$sql.= ", '".$url_id."'";
327
		$sql.= ", '".$url."'";
328
		$sql.= ", '".$this->db->escape($label)."'";
329
		$sql.= ", '".$type."'";
330
		$sql.= ")";
331
332
		dol_syslog(get_class($this)."::add_url_line", LOG_DEBUG);
333
		if ($this->db->query($sql))
334
		{
335
			$rowid = $this->db->last_insert_id(MAIN_DB_PREFIX."bank_url");
336
			return $rowid;
337
		}
338
		else
339
		{
340
			$this->error=$this->db->lasterror();
341
			return -1;
342
		}
343
	}
344
345
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
346
	/**
347
	 * 		TODO Move this into AccountLine
348
	 *      Return array with links from llx_bank_url
349
	 *
350
	 *      @param  int         $fk_bank    To search using bank transaction id
351
	 *      @param  int         $url_id     To search using link to
352
	 *      @param  string      $type       To search using type
353
	 *      @return array|int               Array of links array('url'=>, 'url_id'=>, 'label'=>, 'type'=> 'fk_bank'=> ) or -1 on error
354
	 */
355
	function get_url($fk_bank='', $url_id='', $type='')
356
	{
357
        // phpcs:enable
358
		$lines = array();
359
360
		// Check parameters
361
		if (! empty($fk_bank) && (! empty($url_id) || ! empty($type)))
362
		{
363
			$this->error="ErrorBadParameter";
364
			return -1;
365
		}
366
367
		$sql = "SELECT fk_bank, url_id, url, label, type";
368
		$sql.= " FROM ".MAIN_DB_PREFIX."bank_url";
369
		if ($fk_bank > 0) {
370
			$sql.= " WHERE fk_bank = ".$fk_bank;
371
		}
372
		else { $sql.= " WHERE url_id = ".$url_id." AND type = '".$type."'";
373
		}
374
		$sql.= " ORDER BY type, label";
375
376
		dol_syslog(get_class($this)."::get_url", LOG_DEBUG);
377
		$result = $this->db->query($sql);
378
		if ($result)
379
		{
380
			$i = 0;
381
			$num = $this->db->num_rows($result);
382
			while ($i < $num)
383
			{
384
				$obj = $this->db->fetch_object($result);
385
				// Anciens liens (pour compatibilite)
386
				$lines[$i][0] = $obj->url;
387
				$lines[$i][1] = $obj->url_id;
388
				$lines[$i][2] = $obj->label;
389
				$lines[$i][3] = $obj->type;
390
				// Nouveaux liens
391
				$lines[$i]['url'] = $obj->url;
392
				$lines[$i]['url_id'] = $obj->url_id;
393
				$lines[$i]['label'] = $obj->label;
394
				$lines[$i]['type'] = $obj->type;
395
				$lines[$i]['fk_bank'] = $obj->fk_bank;
396
				$i++;
397
			}
398
		}
399
		else dol_print_error($this->db);
400
401
		return $lines;
402
	}
403
404
	/**
405
	 *  Add an entry into table ".MAIN_DB_PREFIX."bank
406
	 *
407
	 *  @param	int	        $date			Date operation
408
	 *  @param	string		$oper			1,2,3,4... (deprecated) or 'TYP','VIR','PRE','LIQ','VAD','CB','CHQ'...
409
	 *  @param	string		$label			Descripton
410
	 *  @param	float		$amount			Amount
411
	 *  @param	string		$num_chq		Numero cheque ou virement
412
	 *  @param	int  		$categorie		Category id (optionnal)
413
	 *  @param	User		$user			User that create
414
	 *  @param	string		$emetteur		Name of cheque writer
415
	 *  @param	string		$banque			Bank of cheque writer
416
	 *  @param	string		$accountancycode	When we record a free bank entry, we must provide accounting account if accountancy module is on.
417
	 *  @param	int			$datev			Date value
418
	 *  @return	int							Rowid of added entry, <0 if KO
419
	 */
420
	function addline($date, $oper, $label, $amount, $num_chq, $categorie, User $user, $emetteur='',$banque='', $accountancycode='', $datev=null)
421
	{
422
		// Deprecation warning
423
		if (is_numeric($oper)) {
424
			dol_syslog(__METHOD__ . ": using numeric operations is deprecated", LOG_WARNING);
425
		}
426
427
		// Clean parameters
428
		$emetteur=trim($emetteur);
429
		$banque=trim($banque);
430
431
		$now=dol_now();
432
433
		if (is_numeric($oper))    // Clean operation to have a code instead of a rowid
434
		{
435
			$sql = "SELECT code FROM ".MAIN_DB_PREFIX."c_paiement";
436
			$sql.= " WHERE id=".$oper;
437
			$sql.= " AND entity IN (".getEntity('c_paiement').")";
438
			$resql=$this->db->query($sql);
439
			if ($resql)
440
			{
441
				$obj=$this->db->fetch_object($resql);
442
				$oper=$obj->code;
443
			}
444
			else
445
			{
446
				dol_print_error($this->db,'Failed to get payment type code');
447
				return -1;
448
			}
449
		}
450
451
		// Check parameters
452
		if (! $oper)
453
		{
454
			$this->error="oper not defined";
455
			return -1;
456
		}
457
		if (! $this->rowid)
458
		{
459
			$this->error="this->rowid not defined";
460
			return -2;
461
		}
462
		if ($this->courant == Account::TYPE_CASH && $oper != 'LIQ')
463
		{
464
			$this->error="ErrorCashAccountAcceptsOnlyCashMoney";
465
			return -3;
466
		}
467
468
		$this->db->begin();
469
470
		if (is_null($datev) || empty($datev)) $datev = $date;
471
472
		$accline = new AccountLine($this->db);
473
		$accline->datec = $now;
474
		$accline->dateo = $date;
475
		$accline->datev = $datev;
476
		$accline->label = $label;
477
		$accline->amount = $amount;
478
		$accline->fk_user_author = $user->id;
479
		$accline->fk_account = $this->rowid;
480
		$accline->fk_type = $oper;
0 ignored issues
show
Documentation Bug introduced by
The property $fk_type was declared of type integer, but $oper is of type string. 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...
481
		$accline->numero_compte = $accountancycode;
482
483
		if ($num_chq) {
484
			$accline->num_chq = $num_chq;
485
		}
486
487
		if ($emetteur) {
488
			$accline->emetteur = $emetteur;
0 ignored issues
show
Documentation Bug introduced by
It seems like $emetteur of type string is incompatible with the declared type Societe of property $emetteur.

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

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

Loading history...
489
		}
490
491
		if ($banque) {
492
			$accline->bank_chq = $banque;
493
		}
494
495
		if ($accline->insert() > 0) {
496
497
			if ($categorie>0) {
498
				$sql = "INSERT INTO ".MAIN_DB_PREFIX."bank_class (";
499
				$sql .= "lineid, fk_categ";
500
				$sql .= ") VALUES (";
501
				$sql .= $accline->id.", ".$categorie;
502
				$sql .= ")";
503
504
				$result = $this->db->query($sql);
505
				if (!$result) {
506
					$this->error = $this->db->lasterror();
507
					$this->db->rollback();
508
					return -3;
509
				}
510
			}
511
512
			$this->db->commit();
513
			return $accline->id;
514
		} else {
515
			$this->error = $this->db->lasterror();
516
			$this->db->rollback();
517
			return -2;
518
		}
519
	}
520
521
	/**
522
	 *  Create bank account into database
523
	 *
524
	 *  @param	User	$user		Object user making creation
525
	 *  @param  int     $notrigger  1=Disable triggers
526
	 *  @return int        			< 0 if KO, > 0 if OK
527
	 */
528
	function create(User $user, $notrigger=0)
529
	{
530
		global $langs,$conf, $hookmanager;
531
532
		$error=0;
533
534
		// Clean parameters
535
		if (! $this->min_allowed) $this->min_allowed=0;
536
		if (! $this->min_desired) $this->min_desired=0;
537
		$this->state_id = ($this->state_id?$this->state_id:$this->state_id);
538
		$this->country_id = ($this->country_id?$this->country_id:$this->country_id);
539
540
		// Check parameters
541
		if (empty($this->country_id))
542
		{
543
			$this->error=$langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("Country"));
544
			dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
545
			return -1;
546
		}
547
		if (empty($this->ref))
548
		{
549
			$this->error=$langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("Ref"));
550
			dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
551
			return -1;
552
		}
553
		if (empty($this->date_solde))
554
		{
555
			$this->error=$langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("DateInitialBalance"));
556
			dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
557
			return -1;
558
		}
559
560
		// Chargement librairie pour acces fonction controle RIB
561
		require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
562
563
		$now=dol_now();
564
565
		$this->db->begin();
566
567
		$sql = "INSERT INTO ".MAIN_DB_PREFIX."bank_account (";
568
		$sql.= "datec";
569
		$sql.= ", ref";
570
		$sql.= ", label";
571
		$sql.= ", entity";
572
		$sql.= ", account_number";
573
		$sql.= ", fk_accountancy_journal";
574
		$sql.= ", bank";
575
		$sql.= ", code_banque";
576
		$sql.= ", code_guichet";
577
		$sql.= ", number";
578
		$sql.= ", cle_rib";
579
		$sql.= ", bic";
580
		$sql.= ", iban_prefix";
581
		$sql.= ", domiciliation";
582
		$sql.= ", proprio";
583
		$sql.= ", owner_address";
584
		$sql.= ", currency_code";
585
		$sql.= ", rappro";
586
		$sql.= ", min_allowed";
587
		$sql.= ", min_desired";
588
		$sql.= ", comment";
589
		$sql.= ", state_id";
590
		$sql.= ", fk_pays";
591
		$sql.= ") VALUES (";
592
		$sql.= "'".$this->db->idate($now)."'";
593
		$sql.= ", '".$this->db->escape($this->ref)."'";
594
		$sql.= ", '".$this->db->escape($this->label)."'";
595
		$sql.= ", ".$conf->entity;
596
		$sql.= ", '".$this->db->escape($this->account_number)."'";
597
		$sql.= ", ".($this->fk_accountancy_journal > 0 ? $this->db->escape($this->fk_accountancy_journal) : "null");
598
		$sql.= ", '".$this->db->escape($this->bank)."'";
599
		$sql.= ", '".$this->db->escape($this->code_banque)."'";
600
		$sql.= ", '".$this->db->escape($this->code_guichet)."'";
601
		$sql.= ", '".$this->db->escape($this->number)."'";
602
		$sql.= ", '".$this->db->escape($this->cle_rib)."'";
603
		$sql.= ", '".$this->db->escape($this->bic)."'";
604
		$sql.= ", '".$this->db->escape($this->iban)."'";
605
		$sql.= ", '".$this->db->escape($this->domiciliation)."'";
606
		$sql.= ", '".$this->db->escape($this->proprio)."'";
607
		$sql.= ", '".$this->db->escape($this->owner_address)."'";
608
		$sql.= ", '".$this->db->escape($this->currency_code)."'";
609
		$sql.= ", ".$this->rappro;
610
		$sql.= ", ".price2num($this->min_allowed);
611
		$sql.= ", ".price2num($this->min_desired);
612
		$sql.= ", '".$this->db->escape($this->comment)."'";
613
		$sql.= ", ".($this->state_id>0?$this->state_id:"null");
614
		$sql.= ", ".$this->country_id;
615
		$sql.= ")";
616
617
		dol_syslog(get_class($this)."::create", LOG_DEBUG);
618
		$resql=$this->db->query($sql);
619
		if ($resql)
620
		{
621
			$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."bank_account");
622
623
			$result=$this->update($user, 1);
624
			if ($result > 0)
625
			{
626
				$accline = new AccountLine($this->db);
627
				$accline->datec = $this->db->idate($now);
628
				$accline->label = '('.$langs->trans("InitialBankBalance").')';
629
				$accline->amount = price2num($this->solde);
630
				$accline->fk_user_author = $user->id;
631
				$accline->fk_account = $this->id;
632
				$accline->datev = $this->db->idate($this->date_solde);
633
				$accline->dateo = $this->db->idate($this->date_solde);
634
				$accline->fk_type = 'SOLD';
635
636
				if ($accline->insert() < 0) {
637
					$error++;
638
					$this->error = $accline->error;
639
					$this->errors = $accline->errors;
640
				}
641
642
				if (! $error)
643
				{
644
					$result=$this->insertExtraFields();
645
					if ($result < 0) $error++;
646
				}
647
648
				if (! $error && ! $notrigger)
649
				{
650
					// Call trigger
651
					$result=$this->call_trigger('BANKACCOUNT_CREATE',$user);
652
					if ($result < 0) $error++;
653
					// End call triggers
654
				}
655
			}
656
			else
657
			{
658
				$error++;
659
			}
660
		}
661
		else
662
		{
663
			if ($this->db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS')
664
			{
665
				$this->error=$langs->trans("ErrorBankLabelAlreadyExists");
666
				$error++;
667
			}
668
			else {
669
				$this->error=$this->db->error()." sql=".$sql;
670
				$error++;
671
			}
672
		}
673
674
		if (! $error)
675
		{
676
			$this->db->commit();
677
			return $this->id;
678
		}
679
		else
680
		{
681
			$this->db->rollback();
682
			return -1*$error;
683
		}
684
	}
685
686
	/**
687
	 *    	Update bank account card
688
	 *
689
	 *    	@param	User	$user       Object user making action
690
	 *      @param  int     $notrigger  1=Disable triggers
691
	 *		@return	int					<0 if KO, >0 if OK
692
	 */
693
	function update(User $user, $notrigger = 0)
694
	{
695
		global $langs,$conf, $hookmanager;
696
697
		$error=0;
698
699
		$this->db->begin();
700
701
		// Clean parameters
702
		$this->state_id = ($this->state_id?$this->state_id:$this->state_id);
703
		$this->country_id = ($this->country_id?$this->country_id:$this->country_id);
704
705
		// Check parameters
706
		if (empty($this->country_id))
707
		{
708
			$this->error=$langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("Country"));
709
			dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
710
			return -1;
711
		}
712
		if (empty($this->ref))
713
		{
714
			$this->error=$langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("Ref"));
715
			dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
716
			return -1;
717
		}
718
		if (! $this->label) $this->label = "???";
719
720
		$sql = "UPDATE ".MAIN_DB_PREFIX."bank_account SET ";
721
722
		$sql.= " ref   = '".$this->db->escape($this->ref)."'";
723
		$sql.= ",label = '".$this->db->escape($this->label)."'";
724
725
		$sql.= ",courant = ".$this->courant;
726
		$sql.= ",clos = ".$this->clos;
727
		$sql.= ",rappro = ".$this->rappro;
728
		$sql.= ",url = ".($this->url?"'".$this->db->escape($this->url)."'":"null");
729
		$sql.= ",account_number = '".$this->db->escape($this->account_number)."'";
730
		$sql.= ",fk_accountancy_journal = ".($this->fk_accountancy_journal > 0 ? $this->db->escape($this->fk_accountancy_journal) : "null");
731
		$sql.= ",bank  = '".$this->db->escape($this->bank)."'";
732
		$sql.= ",code_banque='".$this->db->escape($this->code_banque)."'";
733
		$sql.= ",code_guichet='".$this->db->escape($this->code_guichet)."'";
734
		$sql.= ",number='".$this->db->escape($this->number)."'";
735
		$sql.= ",cle_rib='".$this->db->escape($this->cle_rib)."'";
736
		$sql.= ",bic='".$this->db->escape($this->bic)."'";
737
		$sql.= ",iban_prefix = '".$this->db->escape($this->iban)."'";
738
		$sql.= ",domiciliation='".$this->db->escape($this->domiciliation)."'";
739
		$sql.= ",proprio = '".$this->db->escape($this->proprio)."'";
740
		$sql.= ",owner_address = '".$this->db->escape($this->owner_address)."'";
741
742
		$sql.= ",currency_code = '".$this->db->escape($this->currency_code)."'";
743
744
		$sql.= ",min_allowed = ".($this->min_allowed != '' ? price2num($this->min_allowed) : "null");
745
		$sql.= ",min_desired = ".($this->min_desired != '' ? price2num($this->min_desired) : "null");
746
		$sql.= ",comment     = '".$this->db->escape($this->comment)."'";
747
748
		$sql.= ",state_id = ".($this->state_id>0?$this->state_id:"null");
749
		$sql.= ",fk_pays = ".$this->country_id;
750
751
		$sql.= " WHERE rowid = ".$this->id;
752
		$sql.= " AND entity = ".$conf->entity;
753
754
		dol_syslog(get_class($this)."::update", LOG_DEBUG);
755
		$result = $this->db->query($sql);
756
		if ($result)
757
		{
758
			// Actions on extra fields (by external module or standard code)
759
			if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
760
			{
761
				if (! $error)
762
				{
763
					$result=$this->insertExtraFields();
764
					if ($result < 0) $error++;
765
				}
766
			}
767
768
			if (! $error && ! $notrigger)
769
			{
770
				// Call trigger
771
				$result=$this->call_trigger('BANKACCOUNT_UPDATE',$user);
772
				if ($result < 0) $error++;
773
				// End call triggers
774
			}
775
		}
776
		else
777
		{
778
			$error++;
779
			$this->error=$this->db->lasterror();
780
			dol_print_error($this->db);
781
		}
782
783
		if (! $error)
784
		{
785
			$this->db->commit();
786
			return $this->id;
787
		}
788
		else
789
		{
790
			$this->db->rollback();
791
			return -1*$error;
792
		}
793
	}
794
795
796
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
797
	/**
798
	 *  Update BBAN (RIB) account fields
799
	 *
800
	 *  @param	User	$user       Object user making update
801
	 *	@return	int					<0 if KO, >0 if OK
802
	 */
803
	function update_bban(User $user = null)
804
	{
805
        // phpcs:enable
806
		global $conf,$langs;
807
808
		// Clean parameters
809
		$this->state_id = ($this->state_id?$this->state_id:$this->state_id);
810
		$this->country_id = ($this->country_id?$this->country_id:$this->country_id);
811
812
		// Chargement librairie pour acces fonction controle RIB
813
		require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
814
815
		dol_syslog(get_class($this)."::update_bban $this->code_banque,$this->code_guichet,$this->number,$this->cle_rib,$this->iban");
816
817
		// Check parameters
818
		if (! $this->ref)
819
		{
820
			$this->error=$langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->trans("Ref"));
821
			return -2;
822
		}
823
824
		$sql = "UPDATE ".MAIN_DB_PREFIX."bank_account SET ";
825
		$sql.= " bank  = '".$this->db->escape($this->bank)."'";
826
		$sql.= ",code_banque='".$this->db->escape($this->code_banque)."'";
827
		$sql.= ",code_guichet='".$this->db->escape($this->code_guichet)."'";
828
		$sql.= ",number='".$this->db->escape($this->number)."'";
829
		$sql.= ",cle_rib='".$this->db->escape($this->cle_rib)."'";
830
		$sql.= ",bic='".$this->db->escape($this->bic)."'";
831
		$sql.= ",iban_prefix = '".$this->db->escape($this->iban)."'";
832
		$sql.= ",domiciliation='".$this->db->escape($this->domiciliation)."'";
833
		$sql.= ",proprio = '".$this->db->escape($this->proprio)."'";
834
		$sql.= ",owner_address = '".$this->db->escape($this->owner_address)."'";
835
		$sql.= ",state_id = ".($this->state_id>0?$this->state_id:"null");
836
		$sql.= ",fk_pays = ".$this->country_id;
837
		$sql.= " WHERE rowid = ".$this->id;
838
		$sql.= " AND entity = ".$conf->entity;
839
840
		dol_syslog(get_class($this)."::update_bban", LOG_DEBUG);
841
842
		$result = $this->db->query($sql);
843
		if ($result)
844
		{
845
			return 1;
846
		}
847
		else
848
		{
849
			$this->error=$this->db->lasterror();
850
			dol_print_error($this->db);
851
			return -1;
852
		}
853
	}
854
855
856
	/**
857
	 *      Load a bank account into memory from database
858
	 *
859
	 *      @param	int		$id      	Id of bank account to get
860
	 *      @param  string	$ref     	Ref of bank account to get
861
	 *      @return	int					<0 if KO, >0 if OK
862
	 */
863
	function fetch($id, $ref='')
864
	{
865
		global $conf;
866
867
		if (empty($id) && empty($ref))
868
		{
869
			$this->error="ErrorBadParameters";
870
			return -1;
871
		}
872
873
		$sql = "SELECT ba.rowid, ba.ref, ba.label, ba.bank, ba.number, ba.courant, ba.clos, ba.rappro, ba.url,";
874
		$sql.= " ba.code_banque, ba.code_guichet, ba.cle_rib, ba.bic, ba.iban_prefix as iban,";
875
		$sql.= " ba.domiciliation, ba.proprio, ba.owner_address, ba.state_id, ba.fk_pays as country_id,";
876
		$sql.= " ba.account_number, ba.fk_accountancy_journal, ba.currency_code,";
877
		$sql.= " ba.min_allowed, ba.min_desired, ba.comment,";
878
		$sql.= " ba.datec as date_creation, ba.tms as date_update,";
879
		$sql.= ' c.code as country_code, c.label as country,';
880
		$sql.= ' d.code_departement as state_code, d.nom as state';
881
        $sql.= ' , aj.code as accountancy_journal';
882
		$sql.= " FROM ".MAIN_DB_PREFIX."bank_account as ba";
883
		$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_country as c ON ba.fk_pays = c.rowid';
884
		$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_departements as d ON ba.state_id = d.rowid';
885
        $sql.= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'accounting_journal as aj ON aj.rowid=ba.fk_accountancy_journal';
886
		$sql.= " WHERE ba.entity IN (".getEntity($this->element).")";
887
		if ($id)  $sql.= " AND ba.rowid  = ".$id;
888
		if ($ref) $sql.= " AND ba.ref = '".$this->db->escape($ref)."'";
889
890
		dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
891
		$result = $this->db->query($sql);
892
		if ($result)
893
		{
894
			if ($this->db->num_rows($result))
895
			{
896
				$obj = $this->db->fetch_object($result);
897
898
				$this->id            = $obj->rowid;
899
				$this->rowid         = $obj->rowid;
900
				$this->ref           = $obj->ref;
901
				$this->label         = $obj->label;
902
				$this->type          = $obj->courant;
903
				$this->courant       = $obj->courant;
904
				$this->bank          = $obj->bank;
905
				$this->clos          = $obj->clos;
906
				$this->rappro        = $obj->rappro;
907
				$this->url           = $obj->url;
908
909
				$this->code_banque   = $obj->code_banque;
910
				$this->code_guichet  = $obj->code_guichet;
911
				$this->number        = $obj->number;
912
				$this->cle_rib       = $obj->cle_rib;
913
				$this->bic           = $obj->bic;
914
				$this->iban          = $obj->iban;
915
				$this->domiciliation = $obj->domiciliation;
916
				$this->proprio       = $obj->proprio;
917
				$this->owner_address = $obj->owner_address;
918
919
				$this->state_id        = $obj->state_id;
920
				$this->state_code      = $obj->state_code;
921
				$this->state           = $obj->state;
922
923
				$this->country_id    = $obj->country_id;
924
				$this->country_code  = $obj->country_code;
925
				$this->country       = $obj->country;
926
927
				$this->account_number = $obj->account_number;
928
				$this->fk_accountancy_journal = $obj->fk_accountancy_journal;
929
				$this->accountancy_journal = $obj->accountancy_journal;
930
931
				$this->currency_code  = $obj->currency_code;
932
				$this->account_currency_code  = $obj->currency_code;
933
				$this->min_allowed    = $obj->min_allowed;
934
				$this->min_desired    = $obj->min_desired;
935
				$this->comment        = $obj->comment;
936
937
				$this->date_creation  = $this->db->jdate($obj->date_creation);
938
				$this->date_update    = $this->db->jdate($obj->date_update);
939
940
				// Retreive all extrafield
941
				// fetch optionals attributes and labels
942
				$this->fetch_optionals();
943
944
				return 1;
945
			}
946
			else
947
			{
948
				return 0;
949
			}
950
		}
951
		else
952
		{
953
			$this->error=$this->db->lasterror;
954
			$this->errors[]=$this->error;
955
			return -1;
956
		}
957
	}
958
959
	/**
960
	 * Sets object to supplied categories.
961
	 *
962
	 * Deletes object from existing categories not supplied.
963
	 * Adds it to non existing supplied categories.
964
	 * Existing categories are left untouch.
965
	 *
966
	 * @param int[]|int $categories Category or categories IDs
967
     * @return void
968
	 */
969
    public function setCategories($categories)
970
    {
971
		// Handle single category
972
		if (! is_array($categories)) {
973
			$categories = array($categories);
974
		}
975
976
		// Get current categories
977
		require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
978
		$c = new Categorie($this->db);
979
		$existing = $c->containing($this->id, Categorie::TYPE_ACCOUNT, 'id');
980
981
		// Diff
982
		if (is_array($existing)) {
983
			$to_del = array_diff($existing, $categories);
984
			$to_add = array_diff($categories, $existing);
985
		} else {
986
			$to_del = array(); // Nothing to delete
987
			$to_add = $categories;
988
		}
989
990
		// Process
991
		foreach($to_del as $del) {
992
			if ($c->fetch($del) > 0) {
993
				$c->del_type($this, 'account');
994
			}
995
		}
996
		foreach ($to_add as $add) {
997
			if ($c->fetch($add) > 0) {
998
				$c->add_type($this, 'account');
999
			}
1000
		}
1001
1002
		return;
1003
	}
1004
1005
	/**
1006
	 *  Delete bank account from database
1007
	 *
1008
	 *	@param	User	$user	User deleting
1009
	 *  @return int             <0 if KO, >0 if OK
1010
	 */
1011
	function delete(User $user = null)
1012
	{
1013
		global $conf;
1014
1015
		$error=0;
1016
1017
		$this->db->begin();
1018
1019
		// Delete link between tag and bank account
1020
		if (! $error)
1021
		{
1022
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_account";
1023
			$sql.= " WHERE fk_account = ".$this->id;
1024
1025
			$resql = $this->db->query($sql);
1026
			if (!$resql)
1027
			{
1028
				$error++;
1029
				$this->error = "Error ".$this->db->lasterror();
1030
			}
1031
		}
1032
1033
		if (! $error)
1034
		{
1035
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."bank_account";
1036
			$sql.= " WHERE rowid = ".$this->rowid;
1037
1038
			dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1039
			$result = $this->db->query($sql);
1040
			if ($result)
1041
			{
1042
				// Remove extrafields
1043
				if ((empty($conf->global->MAIN_EXTRAFIELDS_DISABLED))) // For avoid conflicts if trigger used
1044
				{
1045
					$result=$this->deleteExtraFields();
1046
					if ($result < 0)
1047
					{
1048
						$error++;
1049
						dol_syslog(get_class($this)."::delete error -4 ".$this->error, LOG_ERR);
1050
					}
1051
				}
1052
			}
1053
			else
1054
			{
1055
				$error++;
1056
				$this->error = "Error ".$this->db->lasterror();
1057
			}
1058
		}
1059
1060
		if (! $error)
1061
		{
1062
			$this->db->commit();
1063
			return 1;
1064
		}
1065
		else
1066
		{
1067
			$this->db->rollback();
1068
			return -1;
1069
		}
1070
	}
1071
1072
1073
	/**
1074
	 *  Return label of object status
1075
	 *
1076
	 *  @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
1077
	 *  @return     string        		    Label
1078
	 */
1079
	function getLibStatut($mode=0)
1080
	{
1081
		return $this->LibStatut($this->clos,$mode);
1082
	}
1083
1084
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1085
	/**
1086
	 *  Return label of given object status
1087
	 *
1088
	 *  @param	 int		$statut        	Id statut
1089
	 *  @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
1090
	 *  @return  string        			    Label
1091
	 */
1092
	function LibStatut($statut, $mode = 0)
1093
	{
1094
        // phpcs:enable
1095
		global $langs;
1096
		$langs->load('banks');
1097
1098
		if ($statut == self::STATUS_OPEN) {
1099
			$label = $langs->trans("StatusAccountOpened");
1100
			$picto = img_picto($label, 'statut4');
1101
		} else {
1102
			$label = $langs->trans("StatusAccountClosed");
1103
			$picto = img_picto($label, 'statut5');
1104
		}
1105
1106
		if ($mode == 2) {
1107
			return $picto.' '.$label;
1108
		} elseif ($mode == 3) {
1109
			return $picto;
1110
		} elseif ($mode == 4) {
1111
			return $picto.' '.$label;
1112
		} elseif ($mode == 5) {
1113
			return $label.' '.$picto;
1114
		} elseif ($mode == 6) {
1115
			return $label.' '.$picto;
1116
		}
1117
1118
		//There is no short mode for this label
1119
		return $label;
1120
	}
1121
1122
1123
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1124
	/**
1125
	 *    Renvoi si un compte peut etre supprimer ou non (sans mouvements)
1126
	 *
1127
	 *    @return     boolean     vrai si peut etre supprime, faux sinon
1128
	 */
1129
	function can_be_deleted()
1130
	{
1131
        // phpcs:enable
1132
		$can_be_deleted=false;
1133
1134
		$sql = "SELECT COUNT(rowid) as nb";
1135
		$sql.= " FROM ".MAIN_DB_PREFIX."bank";
1136
		$sql.= " WHERE fk_account=".$this->id;
1137
1138
		$resql = $this->db->query($sql);
1139
		if ($resql) {
1140
			$obj=$this->db->fetch_object($resql);
1141
			if ($obj->nb <= 1) $can_be_deleted=true;    // Juste le solde
1142
		}
1143
		else {
1144
			dol_print_error($this->db);
1145
		}
1146
		return $can_be_deleted;
1147
	}
1148
1149
1150
	/**
1151
	 *   Return error
1152
	 *
1153
	 *   @return	string		Error string
1154
	 */
1155
	function error()
1156
	{
1157
		return $this->error;
1158
	}
1159
1160
	/**
1161
	 * 	Return current sold
1162
	 *
1163
	 * 	@param	int		$option		1=Exclude future operation date (this is to exclude input made in advance and have real account sold)
1164
	 *	@return	int					Current sold (value date <= today)
1165
	 */
1166
	function solde($option=0)
1167
	{
1168
		$solde=0;
1169
1170
		$sql = "SELECT sum(amount) as amount";
1171
		$sql.= " FROM ".MAIN_DB_PREFIX."bank";
1172
		$sql.= " WHERE fk_account = ".$this->id;
1173
		if ($option == 1) $sql.= " AND dateo <= '".$this->db->idate(dol_now())."'";
1174
1175
		$resql = $this->db->query($sql);
1176
		if ($resql)
1177
		{
1178
			if ($this->db->num_rows($resql))
1179
			{
1180
				$obj=$this->db->fetch_object($resql);
1181
				$solde = $obj->amount;
1182
			}
1183
			$this->db->free($resql);
1184
		} else {
1185
			$this->errors[]=$this->db->lasterror;
1186
			return -1;
1187
		}
1188
1189
		return price2num($solde, 'MU');
1190
	}
1191
1192
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1193
	/**
1194
	 *      Load indicators for dashboard (this->nbtodo and this->nbtodolate)
1195
	 *
1196
	 *      @param	User	$user        		Objet user
1197
	 *		@param	int		$filteraccountid	To get info for a particular account id
1198
	 *      @return WorkboardResponse|int 		<0 if KO, WorkboardResponse if OK
1199
	 */
1200
	function load_board(User $user, $filteraccountid = 0)
1201
	{
1202
        // phpcs:enable
1203
		global $conf, $langs;
1204
1205
		if ($user->societe_id) return -1;   // protection pour eviter appel par utilisateur externe
1206
1207
		$sql = "SELECT b.rowid, b.datev as datefin";
1208
		$sql.= " FROM ".MAIN_DB_PREFIX."bank as b,";
1209
		$sql.= " ".MAIN_DB_PREFIX."bank_account as ba";
1210
		$sql.= " WHERE b.rappro=0";
1211
		$sql.= " AND b.fk_account = ba.rowid";
1212
		$sql.= " AND ba.entity IN (".getEntity('bank_account').")";
1213
		$sql.= " AND (ba.rappro = 1 AND ba.courant != 2)";	// Compte rapprochable
1214
		$sql.= " AND clos = 0";
1215
		if ($filteraccountid) $sql.=" AND ba.rowid = ".$filteraccountid;
1216
1217
		$resql=$this->db->query($sql);
1218
		if ($resql)
1219
		{
1220
			$langs->load("banks");
1221
			$now=dol_now();
1222
1223
			require_once DOL_DOCUMENT_ROOT.'/core/class/workboardresponse.class.php';
1224
1225
			$response = new WorkboardResponse();
1226
			$response->warning_delay=$conf->bank->rappro->warning_delay/60/60/24;
1227
			$response->label=$langs->trans("TransactionsToConciliate");
1228
			$response->url=DOL_URL_ROOT.'/compta/bank/list.php?leftmenu=bank&amp;mainmenu=bank';
1229
			$response->img=img_object('',"payment");
1230
1231
			while ($obj=$this->db->fetch_object($resql))
1232
			{
1233
				$response->nbtodo++;
1234
				if ($this->db->jdate($obj->datefin) < ($now - $conf->bank->rappro->warning_delay)) {
1235
					$response->nbtodolate++;
1236
				}
1237
			}
1238
1239
			return $response;
1240
		}
1241
		else
1242
		{
1243
			dol_print_error($this->db);
1244
			$this->error=$this->db->error();
1245
			return -1;
1246
		}
1247
	}
1248
1249
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1250
	/**
1251
	 *      Charge indicateurs this->nb de tableau de bord
1252
	 *		@param		int			$filteraccountid	To get info for a particular account id
1253
	 *      @return     int         <0 if ko, >0 if ok
1254
	 */
1255
	function load_state_board($filteraccountid = 0)
1256
	{
1257
        // phpcs:enable
1258
		global $user;
1259
1260
		if ($user->societe_id) return -1;   // protection pour eviter appel par utilisateur externe
1261
1262
		$sql = "SELECT count(b.rowid) as nb";
1263
		$sql.= " FROM ".MAIN_DB_PREFIX."bank as b,";
1264
		$sql.= " ".MAIN_DB_PREFIX."bank_account as ba";
1265
		$sql.= " WHERE b.fk_account = ba.rowid";
1266
		$sql.= " AND ba.entity IN (".getEntity('bank_account').")";
1267
		$sql.= " AND (ba.rappro = 1 AND ba.courant != 2)";	// Compte rapprochable
1268
		$sql.= " AND clos = 0";
1269
		if ($filteraccountid) $sql.=" AND ba.rowid = ".$filteraccountid;
1270
1271
		$resql=$this->db->query($sql);
1272
		if ($resql)
1273
		{
1274
			while ($obj=$this->db->fetch_object($resql))
1275
			{
1276
				$this->nb["banklines"]=$obj->nb;
1277
			}
1278
			$this->db->free($resql);
1279
			return 1;
1280
		}
1281
		else
1282
		{
1283
			dol_print_error($this->db);
1284
			$this->error=$this->db->error();
1285
			return -1;
1286
		}
1287
	}
1288
1289
1290
	/**
1291
	 *      Load indicators for dashboard (this->nbtodo and this->nbtodolate)
1292
	 *
1293
	 *      @return int     Nb of account we can reconciliate
1294
	 */
1295
	public static function countAccountToReconcile()
1296
	{
1297
		global $db, $conf, $user;
1298
1299
		//Protection against external users
1300
		if ($user->societe_id) {
1301
			return 0;
1302
		}
1303
1304
		$nb=0;
1305
1306
		$sql = "SELECT COUNT(ba.rowid) as nb";
1307
		$sql.= " FROM ".MAIN_DB_PREFIX."bank_account as ba";
1308
		$sql.= " WHERE ba.rappro > 0 and ba.clos = 0";
1309
		$sql.= " AND ba.entity IN (".getEntity('bank_account').")";
1310
		if (empty($conf->global->BANK_CAN_RECONCILIATE_CASHACCOUNT)) $sql.= " AND ba.courant != 2";
1311
		$resql=$db->query($sql);
1312
		if ($resql)
1313
		{
1314
			$obj = $db->fetch_object($resql);
1315
			$nb = $obj->nb;
1316
		}
1317
		else dol_print_error($db);
1318
1319
		return $nb;
1320
	}
1321
1322
	/**
1323
	 *  Return clicable name (with picto eventually)
1324
	 *
1325
	 *	@param	int		$withpicto					Include picto into link
1326
	 *  @param  string	$mode           			''=Link to card, 'transactions'=Link to transactions card
1327
	 *  @param  string  $option         			''=Show ref, 'reflabel'=Show ref+label
1328
	 *  @param  int     $save_lastsearch_value    	-1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
1329
     *  @param	int  	$notooltip		 			1=Disable tooltip
1330
	 *	@return	string								Chaine avec URL
1331
	 */
1332
	function getNomUrl($withpicto=0, $mode='', $option='', $save_lastsearch_value=-1, $notooltip=0)
1333
	{
1334
		global $conf, $langs, $user;
1335
1336
		$result='';
1337
		$label = '<u>' . $langs->trans("ShowAccount") . '</u>';
1338
		$label .= '<br><b>' . $langs->trans('BankAccount') . ':</b> ' . $this->label;
1339
		$label .= '<br><b>' . $langs->trans('AccountNumber') . ':</b> ' . $this->number;
1340
		$label .= '<br><b>' . $langs->trans("AccountCurrency") . ':</b> ' . $this->currency_code;
1341
1342
		if (empty($user->rights->banque->lire) || !empty($user->socid))
1343
		{
1344
			$option = 'nolink';
1345
		}
1346
1347
		if (! empty($conf->accounting->enabled))
1348
		{
1349
			include_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
1350
			$langs->load("accountancy");
1351
			$label .= '<br><b>' . $langs->trans('AccountAccounting') . ':</b> ' . length_accountg($this->account_number);
1352
			$label .= '<br><b>' . $langs->trans('AccountancyJournal') . ':</b> ' . $this->accountancy_journal;
1353
		}
1354
		$linkclose = '" title="'.dol_escape_htmltag($label, 1).'" class="classfortooltip">';
1355
1356
		$url = DOL_URL_ROOT.'/compta/bank/card.php?id='.$this->id;
1357
		if ($mode == 'transactions')
1358
		{
1359
			$url = DOL_URL_ROOT.'/compta/bank/bankentries_list.php?id='.$this->id;
1360
		}
1361
		else if ($mode == 'receipts')
1362
		{
1363
			$url = DOL_URL_ROOT.'/compta/bank/releve.php?account='.$this->id;
1364
		}
1365
1366
		if ($option != 'nolink')
1367
		{
1368
			// Add param to save lastsearch_values or not
1369
			$add_save_lastsearch_values=($save_lastsearch_value == 1 ? 1 : 0);
1370
			if ($save_lastsearch_value == -1 && preg_match('/list\.php/',$_SERVER["PHP_SELF"])) $add_save_lastsearch_values=1;
1371
			if ($add_save_lastsearch_values) $url.='&save_lastsearch_values=1';
1372
		}
1373
1374
		$linkstart = '<a href="'.$url.$linkclose;
1375
		$linkend = '</a>';
1376
1377
                if ($option == 'nolink') {
1378
                    $linkstart = '';
1379
                    $linkend = '';
1380
                }
1381
1382
		$result .= $linkstart;
1383
		if ($withpicto) $result.=img_object(($notooltip?'':$label), $this->picto, ($notooltip?(($withpicto != 2) ? 'class="paddingright"' : ''):'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip?0:1);
1384
		if ($withpicto != 2) $result.= $this->ref.($option == 'reflabel' && $this->label ? ' - '.$this->label : '');
1385
		$result .= $linkend;
1386
1387
		return $result;
1388
	}
1389
1390
1391
	// Method after here are common to Account and CompanyBankAccount
1392
1393
1394
	/**
1395
	 *     Return if an account has valid information for Direct debit payment
1396
	 *
1397
	 *     @return     int         1 if correct, <=0 if wrong
1398
	 */
1399
	function verif()
1400
	{
1401
		require_once DOL_DOCUMENT_ROOT . '/core/lib/bank.lib.php';
1402
1403
		$this->error_number = 0;
1404
1405
		// Call function to check BAN
1406
1407
		if (! checkIbanForAccount($this) || ! checkSwiftForAccount($this))
1408
		{
1409
			$this->error_number = 12;
1410
			$this->error_message = 'IBANSWIFTControlError';
1411
		}
1412
		/*if (! checkBanForAccount($this))
1413
        {
1414
            $this->error_number = 12;
1415
            $this->error_message = 'BANControlError';
1416
        }*/
1417
1418
		if ($this->error_number == 0)
1419
		{
1420
			return 1;
1421
		}
1422
		else
1423
		{
1424
			return 0;
1425
		}
1426
	}
1427
1428
	/**
1429
	 * 	Return account country code
1430
	 *
1431
	 *	@return		string		country code
1432
	 */
1433
	function getCountryCode()
1434
	{
1435
		global $mysoc;
1436
1437
		// We return country code of bank account
1438
		if (! empty($this->country_code)) return $this->country_code;
1439
1440
		// For backward compatibility, we try to guess country from other information
1441
		if (! empty($this->iban))
1442
		{
1443
			// If IBAN defined, we can know country of account from it
1444
			if (preg_match("/^([a-zA-Z][a-zA-Z])/i",$this->iban,$reg)) return $reg[1];
1445
		}
1446
1447
		// If this class is linked to a third party
1448
		if (! empty($this->socid))
1449
		{
1450
			require_once DOL_DOCUMENT_ROOT .'/societe/class/societe.class.php';
1451
			$company=new Societe($this->db);
1452
			$result=$company->fetch($this->socid);
1453
			if (! empty($company->country_code)) return $company->country_code;
1454
		}
1455
1456
		// We return country code of managed company
1457
		if (! empty($mysoc->country_code)) return $mysoc->country_code;
1458
1459
		return '';
1460
	}
1461
1462
	/**
1463
	 * Return if a bank account is defined with detailed information (bank code, desk code, number and key).
1464
	 * More information on codes used by countries on page http://en.wikipedia.org/wiki/Bank_code
1465
	 *
1466
	 * @return		int        0=No bank code need + Account number is enough
1467
	 *                         1=Need 2 fields for bank code: Bank, Desk (France, Spain, ...) + Account number and key
1468
	 *                         2=Need 1 field for bank code:  Bank only (Sort code for Great Britain, BSB for Australia) + Account number
1469
	 */
1470
	function useDetailedBBAN()
1471
	{
1472
		$country_code=$this->getCountryCode();
1473
1474
		if (in_array($country_code,array('FR','ES','GA','IT','NC'))) return 1; // France, Spain, Gabon, ... - Not valid for CH
1475
		if (in_array($country_code,array('AU','BE','CA','DE','DK','GR','GB','ID','IE','IR','KR','NL','NZ','UK','US'))) return 2;      // Australia, England...
1476
		return 0;
1477
	}
1478
1479
	/**
1480
	 * Return 1 if IBAN / BIC is mandatory (otherwise option)
1481
	 *
1482
	 * @return		int        1 = mandatory / 0 = Not mandatory
1483
	 */
1484
	function needIBAN()
1485
	{
1486
		$country_code=$this->getCountryCode();
1487
1488
		$country_code_in_EEC=array(
1489
				'AT',	// Austria
1490
				'BE',	// Belgium
1491
				'BG',	// Bulgaria
1492
				'CY',	// Cyprus
1493
				'CZ',	// Czech republic
1494
				'DE',	// Germany
1495
				'DK',	// Danemark
1496
				'EE',	// Estonia
1497
				'ES',	// Spain
1498
				'FI',	// Finland
1499
				'FR',	// France
1500
				'GB',	// United Kingdom
1501
				'GR',	// Greece
1502
				'HR',   // Croatia
1503
				'NL',	// Holland
1504
				'HU',	// Hungary
1505
				'IE',	// Ireland
1506
				'IM',	// Isle of Man - Included in UK
1507
				'IT',	// Italy
1508
				'LT',	// Lithuania
1509
				'LU',	// Luxembourg
1510
				'LV',	// Latvia
1511
				'MC',	// Monaco - Included in France
1512
				'MT',	// Malta
1513
				//'NO',	// Norway
1514
				'PL',	// Poland
1515
				'PT',	// Portugal
1516
				'RO',	// Romania
1517
				'SE',	// Sweden
1518
				'SK',	// Slovakia
1519
				'SI',	// Slovenia
1520
				'UK',	// United Kingdom
1521
				//'CH',	// Switzerland - No. Swizerland in not in EEC
1522
		);
1523
1524
		if (in_array($country_code,$country_code_in_EEC)) return 1; // France, Spain, ...
1525
		return 0;
1526
	}
1527
1528
	/**
1529
	 *	Load miscellaneous information for tab "Info"
1530
	 *
1531
	 *	@param  int		$id		Id of object to load
1532
	 *	@return	void
1533
	 */
1534
	function info($id)
1535
	{
1536
	}
1537
1538
	/**
1539
	 * Returns the fields in order that this bank account should show to the user
1540
	 * Will return an array with the following values:
1541
	 * - BankAccountNumber
1542
	 * - BankCode
1543
	 * - BankAccountNumberKey
1544
	 * - DeskCode
1545
	 *
1546
	 * Some countries show less or more bank account properties to the user
1547
	 *
1548
	 * @param  int     $includeibanbic         1=Return also key for IBAN and BIC
1549
	 * @return array
1550
	 * @see useDetailedBBAN
1551
	 */
1552
	public function getFieldsToShow($includeibanbic=0)
1553
	{
1554
		//Get the required properties depending on the country
1555
		$detailedBBAN = $this->useDetailedBBAN();
1556
1557
		if ($detailedBBAN == 0) {
1558
			$fieldarray= array(
1559
					'BankAccountNumber'
1560
			);
1561
		} elseif ($detailedBBAN == 2) {
1562
			$fieldarray= array(
1563
					'BankCode',
1564
					'BankAccountNumber'
1565
			);
1566
		} else {
1567
			$fieldarray=self::getAccountNumberOrder();
1568
		}
1569
1570
		//if ($this->needIBAN()) {    // return always IBAN and BIC (this was old behaviour)
1571
		if ($includeibanbic)
1572
		{
1573
			$fieldarray[]='IBAN';
1574
			$fieldarray[]='BIC';
1575
		}
1576
		//}
1577
1578
		//Get the order the properties are shown
1579
		return $fieldarray;
1580
	}
1581
1582
	/**
1583
	 * Returns the components of the bank account in order.
1584
	 * Will return an array with the following values:
1585
	 * - BankAccountNumber
1586
	 * - BankCode
1587
	 * - BankAccountNumberKey
1588
	 * - DeskCode
1589
	 *
1590
	 * @return array
1591
	 */
1592
	public static function getAccountNumberOrder()
1593
	{
1594
		global $conf;
1595
1596
		$fieldlists = array(
1597
				'BankCode',
1598
				'DeskCode',
1599
				'BankAccountNumber',
1600
				'BankAccountNumberKey'
1601
		);
1602
1603
		if (!empty($conf->global->BANK_SHOW_ORDER_OPTION)) {
1604
			if (is_numeric($conf->global->BANK_SHOW_ORDER_OPTION)) {
1605
				if ($conf->global->BANK_SHOW_ORDER_OPTION == '1') {
1606
					$fieldlists = array(
1607
						'BankCode',
1608
						'DeskCode',
1609
						'BankAccountNumberKey',
1610
						'BankAccountNumber'
1611
					);
1612
				}
1613
			} else {
1614
				//Replace the old AccountNumber key with the new BankAccountNumber key
1615
				$fieldlists = explode(
1616
					' ',
1617
					preg_replace('/ ?[^Bank]AccountNumber ?/', 'BankAccountNumber',
1618
						$conf->global->BANK_SHOW_ORDER_OPTION)
1619
				);
1620
			}
1621
		}
1622
1623
		return $fieldlists;
1624
	}
1625
1626
1627
	/**
1628
	 *  Initialise an instance with random values.
1629
	 *  Used to build previews or test instances.
1630
	 *	id must be 0 if object instance is a specimen.
1631
	 *
1632
	 *  @return	void
1633
	 */
1634
	function initAsSpecimen()
1635
	{
1636
		$this->specimen        = 1;
1637
		$this->ref             = 'MBA';
1638
		$this->label           = 'My Big Company Bank account';
1639
		$this->bank            = 'MyBank';
1640
		$this->courant         = Account::TYPE_CURRENT;
1641
		$this->clos            = Account::STATUS_OPEN;
1642
		$this->code_banque     = '123';
1643
		$this->code_guichet    = '456';
1644
		$this->number          = 'ABC12345';
1645
		$this->cle_rib         = '50';
1646
		$this->bic             = 'AA12';
1647
		$this->iban            = 'FR999999999';
1648
		$this->domiciliation   = 'My bank address';
1649
		$this->proprio         = 'Owner';
1650
		$this->owner_address   = 'Owner address';
1651
		$this->country_id      = 1;
1652
	}
1653
}
1654
1655
1656
/**
1657
 *	Class to manage bank transaction lines
1658
 */
1659
class AccountLine extends CommonObject
1660
{
1661
	/**
1662
	 * @var string Error code (or message)
1663
	 */
1664
	public $error='';
1665
1666
    /**
1667
     * @var DoliDB Database handler.
1668
     */
1669
    public $db;
1670
1671
	/**
1672
	 * @var string ID to identify managed object
1673
	 */
1674
	public $element='bank';
1675
1676
	/**
1677
	 * @var string Name of table without prefix where object is stored
1678
	 */
1679
	public $table_element='bank';
1680
1681
	/**
1682
	 * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
1683
	 */
1684
	public $picto = 'generic';
1685
1686
	/**
1687
	 * @var int ID
1688
	 */
1689
	public $id;
1690
1691
    /**
1692
     * @var string Ref
1693
     */
1694
    public $ref;
1695
1696
	public $datec;
1697
	public $dateo;
1698
1699
	/**
1700
	 * Value date
1701
	 */
1702
	public $datev;
1703
	public $amount;
1704
1705
    /**
1706
     * @var string bank transaction lines label
1707
     */
1708
    public $label;
1709
1710
    public $note;
1711
1712
    /**
1713
     * @var int ID
1714
     */
1715
	public $fk_user_author;
1716
1717
	/**
1718
     * @var int ID
1719
     */
1720
	public $fk_user_rappro;
1721
1722
	/**
1723
     * @var int ID
1724
     */
1725
	public $fk_type;
1726
1727
	public $rappro;        // Is it conciliated
1728
	public $num_releve;    // If conciliated, what is bank statement
1729
	public $num_chq;       // Num of cheque
1730
	public $bank_chq;      // Bank of cheque
1731
1732
	/**
1733
     * @var int ID of cheque receipt
1734
     */
1735
	public $fk_bordereau;
1736
1737
	/**
1738
     * @var int ID of bank account
1739
     */
1740
	public $fk_account;
1741
1742
	public $bank_account_label;    // Label of bank account
1743
1744
    /**
1745
	 * Issuer
1746
	 * @var Societe
1747
	 */
1748
	public $emetteur;
1749
1750
	/**
1751
	 *  Constructor
1752
	 *
1753
	 *  @param	DoliDB	$db		Database handler
1754
	 */
1755
	function __construct(DoliDB $db)
1756
	{
1757
		$this->db = $db;
1758
	}
1759
1760
	/**
1761
	 *  Load into memory content of a bank transaction line
1762
	 *
1763
	 *  @param		int		$rowid   	Id of bank transaction to load
1764
	 *  @param      string	$ref     	Ref of bank transaction to load
1765
	 *  @param      string	$num     	External num to load (ex: num of transaction for paypal fee)
1766
	 *	@return		int					<0 if KO, 0 if OK but not found, >0 if OK and found
1767
	 */
1768
	function fetch($rowid,$ref='',$num='')
1769
	{
1770
		global $conf;
1771
1772
		// Check parameters
1773
		if (empty($rowid) && empty($ref) && empty($num)) return -1;
1774
1775
		$sql = "SELECT b.rowid, b.datec, b.datev, b.dateo, b.amount, b.label as label, b.fk_account,";
1776
		$sql.= " b.fk_user_author, b.fk_user_rappro,";
1777
		$sql.= " b.fk_type, b.num_releve, b.num_chq, b.rappro, b.note,";
1778
		$sql.= " b.fk_bordereau, b.banque, b.emetteur,";
1779
		//$sql.= " b.author"; // Is this used ?
1780
		$sql.= " ba.ref as bank_account_ref, ba.label as bank_account_label";
1781
		$sql.= " FROM ".MAIN_DB_PREFIX."bank as b,";
1782
		$sql.= " ".MAIN_DB_PREFIX."bank_account as ba";
1783
		$sql.= " WHERE b.fk_account = ba.rowid";
1784
		$sql.= " AND ba.entity IN (".getEntity('bank_account').")";
1785
		if ($num) $sql.= " AND b.num_chq='".$this->db->escape($num)."'";
1786
		else if ($ref) $sql.= " AND b.rowid='".$this->db->escape($ref)."'";
1787
		else $sql.= " AND b.rowid=".$rowid;
1788
1789
		dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
1790
		$result = $this->db->query($sql);
1791
		if ($result)
1792
		{
1793
			$ret=0;
1794
1795
			$obj = $this->db->fetch_object($result);
1796
			if ($obj)
1797
			{
1798
				$this->id				= $obj->rowid;
1799
				$this->rowid			= $obj->rowid;
1800
				$this->ref				= $obj->rowid;
1801
1802
				$this->datec			= $obj->datec;
1803
				$this->datev			= $obj->datev;
1804
				$this->dateo			= $obj->dateo;
1805
				$this->amount			= $obj->amount;
1806
				$this->label			= $obj->label;
1807
				$this->note				= $obj->note;
1808
1809
				$this->fk_user_author	= $obj->fk_user_author;
1810
				$this->fk_user_rappro	= $obj->fk_user_rappro;
1811
1812
				$this->fk_type			= $obj->fk_type;      // Type of transaction
1813
				$this->rappro			= $obj->rappro;
1814
				$this->num_releve		= $obj->num_releve;
1815
1816
				$this->num_chq			= $obj->num_chq;
1817
				$this->bank_chq			= $obj->banque;
1818
				$this->fk_bordereau		= $obj->fk_bordereau;
1819
1820
				$this->fk_account		= $obj->fk_account;
1821
				$this->bank_account_ref   = $obj->bank_account_ref;
1822
				$this->bank_account_label = $obj->bank_account_label;
1823
1824
				$ret=1;
1825
			}
1826
			$this->db->free($result);
1827
			return $ret;
1828
		}
1829
		else
1830
		{
1831
			return -1;
1832
		}
1833
	}
1834
1835
	/**
1836
	 * Inserts a transaction to a bank account
1837
	 *
1838
	 * @return int <0 if KO, rowid of the line if OK
1839
	 */
1840
	public function insert()
1841
	{
1842
		$sql = "INSERT INTO ".MAIN_DB_PREFIX."bank (";
1843
		$sql .= "datec";
1844
		$sql .= ", dateo";
1845
		$sql .= ", datev";
1846
		$sql .= ", label";
1847
		$sql .= ", amount";
1848
		$sql .= ", fk_user_author";
1849
		$sql .= ", num_chq";
1850
		$sql .= ", fk_account";
1851
		$sql .= ", fk_type";
1852
		$sql .= ", emetteur,banque";
1853
		$sql .= ", rappro";
1854
		$sql .= ", numero_compte";
1855
		$sql .= ") VALUES (";
1856
		$sql .= "'".$this->db->idate($this->datec)."'";
1857
		$sql .= ", '".$this->db->idate($this->dateo)."'";
1858
		$sql .= ", '".$this->db->idate($this->datev)."'";
1859
		$sql .= ", '".$this->db->escape($this->label)."'";
1860
		$sql .= ", ".price2num($this->amount);
1861
		$sql .= ", ".($this->fk_user_author > 0 ? $this->fk_user_author :"null");
1862
		$sql .= ", ".($this->num_chq ? "'".$this->db->escape($this->num_chq)."'" : "null");
1863
		$sql .= ", '".$this->db->escape($this->fk_account)."'";
1864
		$sql .= ", '".$this->db->escape($this->fk_type)."'";
1865
		$sql .= ", ".($this->emetteur ? "'".$this->db->escape($this->emetteur)."'" : "null");
1866
		$sql .= ", ".($this->bank_chq ? "'".$this->db->escape($this->bank_chq)."'" : "null");
1867
		$sql .= ", ".(int) $this->rappro;
1868
		$sql .= ", ".($this->numero_compte ? "'".$this->db->escape($this->numero_compte)."'" : "''");
0 ignored issues
show
Bug Best Practice introduced by
The property numero_compte does not exist on AccountLine. Did you maybe forget to declare it?
Loading history...
1869
		$sql .= ")";
1870
1871
		dol_syslog(get_class($this)."::insert", LOG_DEBUG);
1872
		$resql = $this->db->query($sql);
1873
1874
		if (!$resql) {
1875
			$this->error = $this->db->lasterror();
1876
			return -1;
1877
		}
1878
1879
		$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'bank');
1880
1881
		return $this->id;
1882
	}
1883
1884
	/**
1885
	 *      Delete transaction bank line record
1886
	 *
1887
	 *		@param	User	$user	User object that delete
1888
	 *      @return	int 			<0 if KO, >0 if OK
1889
	 */
1890
	function delete(User $user = null)
1891
	{
1892
		$nbko=0;
1893
1894
		if ($this->rappro)
1895
		{
1896
			// Protection to avoid any delete of consolidated lines
1897
			$this->error="ErrorDeleteNotPossibleLineIsConsolidated";
1898
			return -1;
1899
		}
1900
1901
		$this->db->begin();
1902
1903
		// Delete urls
1904
		$result=$this->delete_urls($user);
1905
		if ($result < 0)
1906
		{
1907
			$nbko++;
1908
		}
1909
1910
		$sql = "DELETE FROM ".MAIN_DB_PREFIX."bank_class WHERE lineid=".(int) $this->rowid;
1911
		dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1912
		$result = $this->db->query($sql);
1913
		if (! $result) $nbko++;
1914
1915
		$sql = "DELETE FROM ".MAIN_DB_PREFIX."bank WHERE rowid=".(int) $this->rowid;
1916
		dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1917
		$result = $this->db->query($sql);
1918
		if (! $result) $nbko++;
1919
1920
		if (! $nbko)
1921
		{
1922
			$this->db->commit();
1923
			return 1;
1924
		}
1925
		else
1926
		{
1927
			$this->db->rollback();
1928
			return -$nbko;
1929
		}
1930
	}
1931
1932
1933
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1934
	/**
1935
	 *      Delete bank line records
1936
	 *
1937
	 *		@param	User	$user	User object that delete
1938
	 *      @return	int 			<0 if KO, >0 if OK
1939
	 */
1940
	function delete_urls(User $user = null)
1941
	{
1942
        // phpcs:enable
1943
		$nbko=0;
1944
1945
		if ($this->rappro)
1946
		{
1947
			// Protection to avoid any delete of consolidated lines
1948
			$this->error="ErrorDeleteNotPossibleLineIsConsolidated";
1949
			return -1;
1950
		}
1951
1952
		$this->db->begin();
1953
1954
		$sql = "DELETE FROM ".MAIN_DB_PREFIX."bank_url WHERE fk_bank=".(int) $this->rowid;
1955
		dol_syslog(get_class($this)."::delete_urls", LOG_DEBUG);
1956
		$result = $this->db->query($sql);
1957
		if (! $result) $nbko++;
1958
1959
		if (! $nbko)
1960
		{
1961
			$this->db->commit();
1962
			return 1;
1963
		}
1964
		else
1965
		{
1966
			$this->db->rollback();
1967
			return -$nbko;
1968
		}
1969
	}
1970
1971
1972
	/**
1973
	 *		Update bank account record in database
1974
	 *
1975
	 *		@param	User	$user			Object user making update
1976
	 *		@param 	int		$notrigger		0=Disable all triggers
1977
	 *		@return	int						<0 if KO, >0 if OK
1978
	 */
1979
	function update(User $user, $notrigger = 0)
1980
	{
1981
		$this->db->begin();
1982
1983
		$sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
1984
		$sql.= " amount = ".price2num($this->amount).",";
1985
		$sql.= " datev='".$this->db->idate($this->datev)."',";
1986
		$sql.= " dateo='".$this->db->idate($this->dateo)."'";
1987
		$sql.= " WHERE rowid = ".$this->rowid;
1988
1989
		dol_syslog(get_class($this)."::update", LOG_DEBUG);
1990
		$resql = $this->db->query($sql);
1991
		if ($resql)
1992
		{
1993
			$this->db->commit();
1994
			return 1;
1995
		}
1996
		else
1997
		{
1998
			$this->db->rollback();
1999
			$this->error=$this->db->error();
2000
			return -1;
2001
		}
2002
	}
2003
2004
2005
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2006
	/**
2007
	 *	Update conciliation field
2008
	 *
2009
	 *	@param	User	$user			Objet user making update
2010
	 *	@param 	int		$cat			Category id
2011
	 *	@param	int		$conciliated	1=Set transaction to conciliated, 0=Keep transaction non conciliated
2012
	 *	@return	int						<0 if KO, >0 if OK
2013
	 */
2014
	function update_conciliation(User $user, $cat, $conciliated=1)
2015
	{
2016
        // phpcs:enable
2017
		global $conf,$langs;
2018
2019
		$this->db->begin();
2020
2021
		// Check statement field
2022
		if (! empty($conf->global->BANK_STATEMENT_REGEX_RULE))
2023
		{
2024
			if (! preg_match('/'.$conf->global->BANK_STATEMENT_REGEX_RULE.'/', $this->num_releve))
2025
			{
2026
				$this->errors[]=$langs->trans("ErrorBankStatementNameMustFollowRegex", $conf->global->BANK_STATEMENT_REGEX_RULE);
2027
				return -1;
2028
			}
2029
		}
2030
2031
		$sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2032
		$sql.= " rappro = ".$conciliated;
2033
		$sql.= ", num_releve = '".$this->db->escape($this->num_releve)."'";
2034
		if ($conciliated) $sql.= ", fk_user_rappro = ".$user->id;
2035
		$sql.= " WHERE rowid = ".$this->id;
2036
2037
		dol_syslog(get_class($this)."::update_conciliation", LOG_DEBUG);
2038
		$resql = $this->db->query($sql);
2039
		if ($resql)
2040
		{
2041
			if (! empty($cat))
2042
			{
2043
				$sql = "INSERT INTO ".MAIN_DB_PREFIX."bank_class (";
2044
				$sql.= "lineid";
2045
				$sql.= ", fk_categ";
2046
				$sql.= ") VALUES (";
2047
				$sql.= $this->id;
2048
				$sql.= ", ".$cat;
2049
				$sql.= ")";
2050
2051
				dol_syslog(get_class($this)."::update_conciliation", LOG_DEBUG);
2052
				$this->db->query($sql);
2053
2054
				// No error check. Can fail if category already affected
2055
			}
2056
2057
			$this->rappro=1;
2058
2059
			$this->db->commit();
2060
			return 1;
2061
		}
2062
		else
2063
		{
2064
			$this->db->rollback();
2065
			return -1;
2066
		}
2067
	}
2068
2069
2070
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2071
	/**
2072
	 * 	Increase/decrease value date of a rowid
2073
	 *
2074
	 *	@param	int		$rowid		Id of line
2075
	 *	@param	int		$sign		1 or -1
2076
	 *	@return	int					>0 if OK, 0 if KO
2077
	 */
2078
	function datev_change($rowid,$sign=1)
2079
	{
2080
        // phpcs:enable
2081
		$sql = "SELECT datev FROM ".MAIN_DB_PREFIX."bank WHERE rowid = ".$rowid;
2082
		$resql = $this->db->query($sql);
2083
		if ($resql)
2084
		{
2085
			$obj=$this->db->fetch_object($resql);
2086
			$newdate=$this->db->jdate($obj->datev)+(3600*24*$sign);
2087
2088
			$sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2089
			$sql.= " datev = '".$this->db->idate($newdate)."'";
2090
			$sql.= " WHERE rowid = ".$rowid;
2091
2092
			$result = $this->db->query($sql);
2093
			if ($result)
2094
			{
2095
				if ($this->db->affected_rows($result))
2096
				{
2097
					return 1;
2098
				}
2099
			}
2100
			else
2101
			{
2102
				dol_print_error($this->db);
2103
				return 0;
2104
			}
2105
		}
2106
		else dol_print_error($this->db);
2107
		return 0;
2108
	}
2109
2110
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2111
	/**
2112
	 * 	Increase value date of a rowid
2113
	 *
2114
	 *	@param	int		$id		Id of line to change
2115
	 *	@return	int				>0 if OK, 0 if KO
2116
	 */
2117
	function datev_next($id)
2118
	{
2119
        // phpcs:enable
2120
		return $this->datev_change($id,1);
2121
	}
2122
2123
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2124
	/**
2125
	 * 	Decrease value date of a rowid
2126
	 *
2127
	 *	@param	int		$id		Id of line to change
2128
	 *	@return	int				>0 if OK, 0 if KO
2129
	 */
2130
	function datev_previous($id)
2131
	{
2132
        // phpcs:enable
2133
		return $this->datev_change($id,-1);
2134
	}
2135
2136
2137
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2138
	/**
2139
	 * 	Increase/decrease operation date of a rowid
2140
	 *
2141
	 *	@param	int		$rowid		Id of line
2142
	 *	@param	int		$sign		1 or -1
2143
	 *	@return	int					>0 if OK, 0 if KO
2144
	 */
2145
	function dateo_change($rowid,$sign=1)
2146
	{
2147
        // phpcs:enable
2148
		$sql = "SELECT dateo FROM ".MAIN_DB_PREFIX."bank WHERE rowid = ".$rowid;
2149
		$resql = $this->db->query($sql);
2150
		if ($resql)
2151
		{
2152
			$obj=$this->db->fetch_object($resql);
2153
			$newdate=$this->db->jdate($obj->dateo)+(3600*24*$sign);
2154
2155
			$sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2156
			$sql.= " dateo = '".$this->db->idate($newdate)."'";
2157
			$sql.= " WHERE rowid = ".$rowid;
2158
2159
			$result = $this->db->query($sql);
2160
			if ($result)
2161
			{
2162
				if ($this->db->affected_rows($result))
2163
				{
2164
					return 1;
2165
				}
2166
			}
2167
			else
2168
			{
2169
				dol_print_error($this->db);
2170
				return 0;
2171
			}
2172
		}
2173
		else dol_print_error($this->db);
2174
		return 0;
2175
	}
2176
2177
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2178
	/**
2179
	 * 	Increase operation date of a rowid
2180
	 *
2181
	 *	@param	int		$id		Id of line to change
2182
	 *	@return	int				>0 if OK, 0 if KO
2183
	 */
2184
	function dateo_next($id)
2185
	{
2186
        // phpcs:enable
2187
		return $this->dateo_change($id,1);
2188
	}
2189
2190
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2191
	/**
2192
	 * 	Decrease operation date of a rowid
2193
	 *
2194
	 *	@param	int		$id		Id of line to change
2195
	 *	@return	int				>0 if OK, 0 if KO
2196
	 */
2197
	function dateo_previous($id)
2198
	{
2199
        // phpcs:enable
2200
		return $this->dateo_change($id,-1);
2201
	}
2202
2203
2204
	/**
2205
	 *	Load miscellaneous information for tab "Info"
2206
	 *
2207
	 *	@param  int		$id		Id of object to load
2208
	 *	@return	void
2209
	 */
2210
	function info($id)
2211
	{
2212
		$sql = 'SELECT b.rowid, b.datec, b.tms as datem,';
2213
		$sql.= ' b.fk_user_author, b.fk_user_rappro';
2214
		$sql.= ' FROM '.MAIN_DB_PREFIX.'bank as b';
2215
		$sql.= ' WHERE b.rowid = '.$id;
2216
2217
		$result=$this->db->query($sql);
2218
		if ($result)
2219
		{
2220
			if ($this->db->num_rows($result))
2221
			{
2222
				$obj = $this->db->fetch_object($result);
2223
				$this->id = $obj->rowid;
2224
2225
				if ($obj->fk_user_author)
2226
				{
2227
					$cuser = new User($this->db);
2228
					$cuser->fetch($obj->fk_user_author);
2229
					$this->user_creation     = $cuser;
2230
				}
2231
				if ($obj->fk_user_rappro)
2232
				{
2233
					$ruser = new User($this->db);
2234
					$ruser->fetch($obj->fk_user_rappro);
2235
					$this->user_rappro = $ruser;
2236
				}
2237
2238
				$this->date_creation     = $this->db->jdate($obj->datec);
2239
				$this->date_modification = $this->db->jdate($obj->datem);
2240
				//$this->date_rappro       = $obj->daterappro;    // Not yet managed
2241
			}
2242
			$this->db->free($result);
2243
		}
2244
		else
2245
		{
2246
			dol_print_error($this->db);
2247
		}
2248
	}
2249
2250
2251
	/**
2252
	 *    	Return clicable name (with picto eventually)
2253
	 *
2254
	 *		@param	int		$withpicto		0=No picto, 1=Include picto into link, 2=Only picto
2255
	 *		@param	int		$maxlen			Longueur max libelle
2256
	 *		@param	string	$option			Option ('showall')
2257
	 * 		@param	int     $notooltip		1=Disable tooltip
2258
	 *		@return	string					Chaine avec URL
2259
	 */
2260
	function getNomUrl($withpicto=0,$maxlen=0,$option='',$notooltip=0)
2261
	{
2262
		global $langs;
2263
2264
		$result='';
2265
		$label=$langs->trans("ShowTransaction").': '.$this->rowid;
2266
		$linkstart = '<a href="'.DOL_URL_ROOT.'/compta/bank/ligne.php?rowid='.$this->rowid.'" title="'.dol_escape_htmltag($label, 1).'" class="classfortooltip">';
2267
		$linkend='</a>';
2268
2269
		$result .= $linkstart;
2270
		if ($withpicto) $result.=img_object(($notooltip?'':$label), ($this->picto?$this->picto:'account'), ($notooltip?(($withpicto != 2) ? 'class="paddingright"' : ''):'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip?0:1);
2271
		if ($withpicto != 2) $result.=($this->ref?$this->ref:$this->rowid);
2272
		$result .= $linkend;
2273
2274
		if ($option == 'showall' || $option == 'showconciliated') $result.=' (';
2275
		if ($option == 'showall')
2276
		{
2277
			$result.=$langs->trans("BankAccount").': ';
2278
			$accountstatic=new Account($this->db);
2279
			$accountstatic->id=$this->fk_account;
2280
			$accountstatic->ref=$this->bank_account_ref;
2281
			$accountstatic->label=$this->bank_account_label;
2282
			$result.=$accountstatic->getNomUrl(0).', ';
2283
		}
2284
		if ($option == 'showall' || $option == 'showconciliated')
2285
		{
2286
			$result.=$langs->trans("BankLineConciliated").': ';
2287
			$result.=yn($this->rappro);
2288
		}
2289
		if ($option == 'showall' || $option == 'showconciliated') $result.=')';
2290
2291
		return $result;
2292
	}
2293
2294
2295
	/**
2296
	 *    Return label of status (activity, closed)
2297
	 *
2298
	 *    @param	int		$mode       0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long
2299
	 *    @return   string        		Libelle
2300
	 */
2301
	function getLibStatut($mode=0)
2302
	{
2303
		return $this->LibStatut($this->status,$mode);
2304
	}
2305
2306
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2307
	/**
2308
	 *  Renvoi le libelle d'un statut donne
2309
	 *
2310
	 *  @param	int		$statut         Id statut
2311
	 *  @param	int		$mode           0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
2312
	 *  @return	string          		Libelle du statut
2313
	 */
2314
	function LibStatut($statut,$mode=0)
2315
	{
2316
        // phpcs:enable
2317
		global $langs;
2318
		//$langs->load('companies');
2319
		/*
2320
        if ($mode == 0)
2321
        {
2322
            if ($statut==0) return $langs->trans("ActivityCeased");
2323
            if ($statut==1) return $langs->trans("InActivity");
2324
        }
2325
        if ($mode == 1)
2326
        {
2327
            if ($statut==0) return $langs->trans("ActivityCeased");
2328
            if ($statut==1) return $langs->trans("InActivity");
2329
        }
2330
        if ($mode == 2)
2331
        {
2332
            if ($statut==0) return img_picto($langs->trans("ActivityCeased"),'statut5', 'class="pictostatus"').' '.$langs->trans("ActivityCeased");
2333
            if ($statut==1) return img_picto($langs->trans("InActivity"),'statut4', 'class="pictostatus"').' '.$langs->trans("InActivity");
2334
        }
2335
        if ($mode == 3)
2336
        {
2337
            if ($statut==0) return img_picto($langs->trans("ActivityCeased"),'statut5', 'class="pictostatus"');
2338
            if ($statut==1) return img_picto($langs->trans("InActivity"),'statut4', 'class="pictostatus"');
2339
        }
2340
        if ($mode == 4)
2341
        {
2342
            if ($statut==0) return img_picto($langs->trans("ActivityCeased"),'statut5', 'class="pictostatus"').' '.$langs->trans("ActivityCeased");
2343
            if ($statut==1) return img_picto($langs->trans("InActivity"),'statut4', 'class="pictostatus"').' '.$langs->trans("InActivity");
2344
        }
2345
        if ($mode == 5)
2346
        {
2347
            if ($statut==0) return $langs->trans("ActivityCeased").' '.img_picto($langs->trans("ActivityCeased"),'statut5', 'class="pictostatus"');
2348
            if ($statut==1) return $langs->trans("InActivity").' '.img_picto($langs->trans("InActivity"),'statut4', 'class="pictostatus"');
2349
        }*/
2350
	}
2351
2352
2353
	/**
2354
	 *	Return if a bank line was dispatched into bookkeeping
2355
	 *
2356
	 *	@return     int         <0 if KO, 0=no, 1=yes
2357
	 */
2358
	public function getVentilExportCompta()
2359
	{
2360
		$alreadydispatched = 0;
2361
2362
		$type = 'bank';
2363
2364
		$sql = " SELECT COUNT(ab.rowid) as nb FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab WHERE ab.doc_type='".$type."' AND ab.fk_doc = ".$this->id;
2365
		$resql = $this->db->query($sql);
2366
		if ($resql)
2367
		{
2368
			$obj = $this->db->fetch_object($resql);
2369
			if ($obj)
2370
			{
2371
				$alreadydispatched = $obj->nb;
2372
			}
2373
		}
2374
		else
2375
		{
2376
			$this->error = $this->db->lasterror();
2377
			return -1;
2378
		}
2379
2380
		if ($alreadydispatched)
2381
		{
2382
			return 1;
2383
		}
2384
		return 0;
2385
	}
2386
}
2387