dolibarr  20.0.0-beta
account.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2001-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2003 Jean-Louis Bergamo <jlb@j1b.org>
4  * Copyright (C) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
5  * Copyright (C) 2004 Christophe Combelles <ccomb@free.fr>
6  * Copyright (C) 2005-2010 Regis Houssin <regis.houssin@inodbox.com>
7  * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
8  * Copyright (C) 2015-2016 Marcos García <marcosgdf@gmail.com>
9  * Copyright (C) 2015-2017 Alexandre Spangaro <aspangaro@open-dsi.fr>
10  * Copyright (C) 2016 Ferran Marcet <fmarcet@2byte.es>
11  * Copyright (C) 2019 JC Prieto <jcprieto@virtual20.com><prietojc@gmail.com>
12  * Copyright (C) 2022-2024 Frédéric France <frederic.france@free.fr>
13  * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
14  *
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 3 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program. If not, see <https://www.gnu.org/licenses/>.
27  */
28 
35 require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
36 
37 
41 class Account extends CommonObject
42 {
46  public $element = 'bank_account';
47 
51  public $table_element = 'bank_account';
52 
56  public $picto = 'account';
57 
63  public $rowid;
64 
69  public $label;
70 
77  private $courant;
78 
83  public $type;
84 
89  public $bank;
90 
98  private $clos = self::STATUS_OPEN;
99 
104  public $rappro = 1;
105 
110  public $url;
111 
116  public $code_banque;
117 
122  public $code_guichet;
123 
128  public $number;
129 
134  public $cle_rib;
135 
140  public $bic;
141 
146  public $iban;
147 
154  public $iban_prefix;
155 
160  public $pti_in_ctti = 0;
161 
168  private $proprio;
169 
174  public $owner_name;
175 
180  public $owner_address;
181 
186  public $owner_zip;
187 
192  public $owner_town;
193  public $owner_country_id;
194  public $owner_country_code;
195 
202  private $domiciliation;
203 
208  public $address;
209  public $state_id;
210  public $state_code;
211  public $state;
212  public $country_id;
213 
219  public $type_lib = array();
220 
225  public $account_number;
226 
230  public $fk_accountancy_journal;
231 
235  public $accountancy_journal;
236 
241  public $currency_code;
242 
249  public $account_currency_code;
250 
255  public $min_allowed;
256 
261  public $min_desired;
262 
267  public $comment;
268 
273  public $date_solde;
274 
281  private $solde;
282 
287  public $balance;
288 
293  public $ics;
294 
299  public $ics_transfer;
300 
301 
326  // BEGIN MODULEBUILDER PROPERTIES
330  public $fields = array(
331  'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 10),
332  'ref' => array('type' => 'varchar(12)', 'label' => 'Ref', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'showoncombobox' => 1, 'position' => 25),
333  'label' => array('type' => 'varchar(30)', 'label' => 'Label', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 30),
334  'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => '1', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 35, 'index' => 1),
335  'bank' => array('type' => 'varchar(60)', 'label' => 'Bank', 'enabled' => 1, 'visible' => -1, 'position' => 40),
336  'code_banque' => array('type' => 'varchar(128)', 'label' => 'Code banque', 'enabled' => 1, 'visible' => -1, 'position' => 45),
337  'code_guichet' => array('type' => 'varchar(6)', 'label' => 'Code guichet', 'enabled' => 1, 'visible' => -1, 'position' => 50),
338  'number' => array('type' => 'varchar(255)', 'label' => 'Number', 'enabled' => 1, 'visible' => -1, 'position' => 55),
339  'cle_rib' => array('type' => 'varchar(5)', 'label' => 'Cle rib', 'enabled' => 1, 'visible' => -1, 'position' => 60),
340  'bic' => array('type' => 'varchar(11)', 'label' => 'Bic', 'enabled' => 1, 'visible' => -1, 'position' => 65),
341  'iban_prefix' => array('type' => 'varchar(34)', 'label' => 'Iban prefix', 'enabled' => 1, 'visible' => -1, 'position' => 70),
342  'country_iban' => array('type' => 'varchar(2)', 'label' => 'Country iban', 'enabled' => 1, 'visible' => -1, 'position' => 75),
343  'cle_iban' => array('type' => 'varchar(2)', 'label' => 'Cle iban', 'enabled' => 1, 'visible' => -1, 'position' => 80),
344  'domiciliation' => array('type' => 'varchar(255)', 'label' => 'Domiciliation', 'enabled' => 1, 'visible' => -1, 'position' => 85),
345  'state_id' => array('type' => 'integer', 'label' => 'StateId', 'enabled' => 1, 'visible' => -1, 'position' => 90),
346  'fk_pays' => array('type' => 'integer', 'label' => 'Country', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 95),
347  'proprio' => array('type' => 'varchar(60)', 'label' => 'Proprio', 'enabled' => 1, 'visible' => -1, 'position' => 100),
348  'owner_address' => array('type' => 'varchar(255)', 'label' => 'Owner address', 'enabled' => 1, 'visible' => -1, 'position' => 105),
349  'owner_zip' => array('type' => 'varchar(25)', 'label' => 'Owner zip', 'enabled' => 1, 'visible' => -1, 'position' => 106),
350  'owner_town' => array('type' => 'varchar(50)', 'label' => 'Owner town', 'enabled' => 1, 'visible' => -1, 'position' => 107),
351  'owner_country_id' => array('type' => 'integer', 'label' => 'Owner country', 'enabled' => 1, 'visible' => -1, 'position' => 108),
352  'courant' => array('type' => 'smallint(6)', 'label' => 'Courant', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 110),
353  'clos' => array('type' => 'smallint(6)', 'label' => 'Clos', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 115),
354  'rappro' => array('type' => 'smallint(6)', 'label' => 'Rappro', 'enabled' => 1, 'visible' => -1, 'position' => 120),
355  'url' => array('type' => 'varchar(128)', 'label' => 'Url', 'enabled' => 1, 'visible' => -1, 'position' => 125),
356  'account_number' => array('type' => 'varchar(32)', 'label' => 'Account number', 'enabled' => 1, 'visible' => -1, 'position' => 130),
357  'fk_accountancy_journal' => array('type' => 'integer', 'label' => 'Accountancy journal ID', 'enabled' => 1, 'visible' => -1, 'position' => 132),
358  'accountancy_journal' => array('type' => 'varchar(20)', 'label' => 'Accountancy journal', 'enabled' => 1, 'visible' => -1, 'position' => 135),
359  'currency_code' => array('type' => 'varchar(3)', 'label' => 'Currency code', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 140),
360  'min_allowed' => array('type' => 'integer', 'label' => 'Min allowed', 'enabled' => 1, 'visible' => -1, 'position' => 145),
361  'min_desired' => array('type' => 'integer', 'label' => 'Min desired', 'enabled' => 1, 'visible' => -1, 'position' => 150),
362  'comment' => array('type' => 'text', 'label' => 'Comment', 'enabled' => 1, 'visible' => -1, 'position' => 155),
363  'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -1, 'position' => 156),
364  'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 157),
365  'fk_user_author' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'Fk user author', 'enabled' => 1, 'visible' => -1, 'position' => 160),
366  'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'position' => 165),
367  'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 170),
368  'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'visible' => 0, 'position' => 175),
369  'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'position' => 180),
370  'extraparams' => array('type' => 'varchar(255)', 'label' => 'Extraparams', 'enabled' => 1, 'visible' => -1, 'position' => 185),
371  );
372  // END MODULEBUILDER PROPERTIES
373 
377  const TYPE_CURRENT = 1;
381  const TYPE_CASH = 2;
385  const TYPE_SAVINGS = 0;
386 
387 
388  const STATUS_OPEN = 0;
389  const STATUS_CLOSED = 1;
390 
391 
397  protected function deprecatedProperties()
398  {
399  return array(
400  'proprio' => 'owner_name',
401  'domiciliation' => 'owner_address',
402  'courant' => 'type',
403  'clos' => 'status',
404  'solde' => 'balance',
405  ) + parent::deprecatedProperties();
406  }
407 
413  public function __construct(DoliDB $db)
414  {
415  global $langs;
416 
417  $this->db = $db;
418 
419  $this->ismultientitymanaged = 1;
420 
421  $this->balance = 0;
422 
423  $this->type_lib = array(
424  self::TYPE_SAVINGS => $langs->transnoentitiesnoconv("BankType0"),
425  self::TYPE_CURRENT => $langs->transnoentitiesnoconv("BankType1"),
426  self::TYPE_CASH => $langs->transnoentitiesnoconv("BankType2"),
427  );
428 
429  $this->labelStatus = array(
430  self::STATUS_OPEN => $langs->transnoentitiesnoconv("StatusAccountOpened"),
431  self::STATUS_CLOSED => $langs->transnoentitiesnoconv("StatusAccountClosed")
432  );
433  }
434 
440  public function __toString()
441  {
442  $string = '';
443  foreach ($this->getFieldsToShow() as $val) {
444  if ($val == 'BankCode') {
445  $string .= $this->code_banque.' ';
446  } elseif ($val == 'BankAccountNumber') {
447  $string .= $this->number.' ';
448  } elseif ($val == 'DeskCode') {
449  $string .= $this->code_guichet.' ';
450  } elseif ($val == 'BankAccountNumberKey') {
451  $string .= $this->cle_rib.' ';
452  } elseif ($val == 'BIC') {
453  $string .= $this->bic.' ';
454  } elseif ($val == 'IBAN') {
455  $string .= $this->iban.' ';
456  }
457  }
458 
459  return trim($string);
460  }
461 
462 
468  public function canBeConciliated()
469  {
470  global $conf;
471 
472  if (empty($this->rappro)) {
473  return -1;
474  }
475  if ($this->type == Account::TYPE_CASH && !getDolGlobalString('BANK_CAN_RECONCILIATE_CASHACCOUNT')) {
476  return -2;
477  }
478  if ($this->status) {
479  return -3;
480  }
481  return 1;
482  }
483 
484 
485  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
496  public function add_url_line($line_id, $url_id, $url, $label, $type)
497  {
498  // phpcs:enable
499  $sql = "INSERT INTO ".MAIN_DB_PREFIX."bank_url (";
500  $sql .= "fk_bank";
501  $sql .= ", url_id";
502  $sql .= ", url"; // deprecated
503  $sql .= ", label";
504  $sql .= ", type";
505  $sql .= ") VALUES (";
506  $sql .= ((int) $line_id);
507  $sql .= ", ".((int) $url_id);
508  $sql .= ", '".$this->db->escape($url)."'"; // deprecated
509  $sql .= ", '".$this->db->escape($label)."'";
510  $sql .= ", '".$this->db->escape($type)."'";
511  $sql .= ")";
512 
513  dol_syslog(get_class($this)."::add_url_line", LOG_DEBUG);
514  if ($this->db->query($sql)) {
515  $rowid = $this->db->last_insert_id(MAIN_DB_PREFIX."bank_url");
516  return $rowid;
517  } else {
518  $this->error = $this->db->lasterror();
519  return -1;
520  }
521  }
522 
523  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
533  public function get_url($fk_bank = 0, $url_id = 0, $type = '')
534  {
535  // phpcs:enable
536  $lines = array();
537 
538  // Check parameters
539  if (!empty($fk_bank) && (!empty($url_id) || !empty($type))) {
540  $this->error = "ErrorBadParameter";
541  return -1;
542  }
543 
544  $sql = "SELECT fk_bank, url_id, url, label, type";
545  $sql .= " FROM ".MAIN_DB_PREFIX."bank_url";
546  if ($fk_bank > 0) {
547  $sql .= " WHERE fk_bank = ".((int) $fk_bank);
548  } else {
549  $sql .= " WHERE url_id = ".((int) $url_id)." AND type = '".$this->db->escape($type)."'";
550  }
551  $sql .= " ORDER BY type, label";
552 
553  dol_syslog(get_class($this)."::get_url", LOG_DEBUG);
554  $result = $this->db->query($sql);
555  if ($result) {
556  $i = 0;
557  $num = $this->db->num_rows($result);
558  while ($i < $num) {
559  $obj = $this->db->fetch_object($result);
560  // Anciens liens (pour compatibilite)
561  $lines[$i][0] = $obj->url;
562  $lines[$i][1] = $obj->url_id;
563  $lines[$i][2] = $obj->label;
564  $lines[$i][3] = $obj->type;
565  // Nouveaux liens
566  $lines[$i]['url'] = $obj->url;
567  $lines[$i]['url_id'] = $obj->url_id;
568  $lines[$i]['label'] = $obj->label;
569  $lines[$i]['type'] = $obj->type;
570  $lines[$i]['fk_bank'] = $obj->fk_bank;
571  $i++;
572  }
573  } else {
574  dol_print_error($this->db);
575  }
576 
577  return $lines;
578  }
579 
598  public function addline($date, $oper, $label, $amount, $num_chq, $categorie, User $user, $emetteur = '', $banque = '', $accountancycode = '', $datev = null, $num_releve = '', $amount_main_currency = null)
599  {
600  global $langs;
601 
602  // Deprecation warning
603  if (is_numeric($oper)) {
604  dol_syslog(__METHOD__.": using numeric operations is deprecated", LOG_WARNING);
605  }
606 
607  if (empty($this->id) && !empty($this->rowid)) { // For backward compatibility
608  $this->id = $this->rowid;
609  }
610 
611  // Clean parameters
612  $emetteur = trim($emetteur);
613  $banque = trim($banque);
614  $label = trim($label);
615 
616  $now = dol_now();
617 
618  if (is_numeric($oper)) { // Clean operation to have a code instead of a rowid
619  $sql = "SELECT code FROM ".MAIN_DB_PREFIX."c_paiement";
620  $sql .= " WHERE id = ".((int) $oper);
621  $sql .= " AND entity IN (".getEntity('c_paiement').")";
622  $resql = $this->db->query($sql);
623  if ($resql) {
624  $obj = $this->db->fetch_object($resql);
625  $oper = $obj->code;
626  } else {
627  dol_print_error($this->db, 'Failed to get payment type code');
628  return -1;
629  }
630  }
631 
632  // Check parameters
633  if (!$oper) {
634  $this->error = $langs->trans("OperNotDefined");
635  return -1;
636  }
637  if (!$this->id) {
638  $this->error = $langs->trans("ThisIdNotDefined");
639  return -2;
640  }
641  if ($this->type == Account::TYPE_CASH && $oper != 'LIQ') {
642  $this->error = "ErrorCashAccountAcceptsOnlyCashMoney";
643  return -3;
644  }
645 
646  $this->db->begin();
647 
648  if (is_null($datev) || empty($datev)) {
649  $datev = $date;
650  }
651 
652  $accline = new AccountLine($this->db);
653  $accline->datec = $now;
654  $accline->dateo = $date;
655  $accline->datev = $datev;
656  $accline->label = $label;
657  $accline->amount = $amount;
658  $accline->amount_main_currency = $amount_main_currency;
659  $accline->fk_user_author = $user->id;
660  $accline->fk_account = $this->id;
661  $accline->fk_type = $oper;
662  $accline->numero_compte = $accountancycode;
663  $accline->num_releve = $num_releve;
664 
665  if ($num_chq) {
666  $accline->num_chq = $num_chq;
667  }
668 
669  if ($emetteur) {
670  $accline->emetteur = $emetteur;
671  }
672 
673  if ($banque) {
674  $accline->bank_chq = $banque;
675  }
676 
677  if ($accline->insert() > 0) {
678  if ($categorie > 0) {
679  $sql = "INSERT INTO ".MAIN_DB_PREFIX."bank_class(";
680  $sql .= "lineid, fk_categ";
681  $sql .= ") VALUES (";
682  $sql .= ((int) $accline->id).", '".$this->db->escape($categorie)."'";
683  $sql .= ")";
684 
685  $result = $this->db->query($sql);
686  if (!$result) {
687  $this->error = $this->db->lasterror();
688  $this->db->rollback();
689 
690  return -4;
691  }
692  }
693 
694  $this->db->commit();
695 
696  return $accline->id;
697  } else {
698  $this->setErrorsFromObject($accline);
699  $this->db->rollback();
700 
701  return -5;
702  }
703  }
704 
712  public function create(User $user, $notrigger = 0)
713  {
714  global $langs, $conf;
715 
716  $error = 0;
717 
718  // Clean parameters
719  if (!$this->min_allowed) {
720  $this->min_allowed = 0;
721  }
722  if (!$this->min_desired) {
723  $this->min_desired = 0;
724  }
725 
726  // Check parameters
727  if (empty($this->country_id)) {
728  $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Country"));
729  dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
730  return -1;
731  }
732  if (empty($this->ref)) {
733  $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Ref"));
734  dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
735  return -1;
736  }
737  if (empty($this->date_solde)) {
738  $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("DateInitialBalance"));
739  dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
740  return -1;
741  }
742 
743  // Load libraries to check BAN
744  $balance = $this->balance;
745  if (empty($balance) && !empty($this->solde)) {
746  $balance = $this->solde;
747  }
748  if (empty($balance)) {
749  $balance = 0;
750  }
751  if (empty($this->address && !empty($this->domiciliation))) {
752  dol_syslog(get_class($this)."::create domiciliation is deprecated use address", LOG_NOTICE);
753  $this->address = $this->domiciliation;
754  }
755  if (empty($this->status && !empty($this->clos))) {
756  dol_syslog(get_class($this)."::create clos is deprecated use status", LOG_NOTICE);
757  $this->status = $this->clos;
758  }
759 
760  // Load the library to validate/check a BAN account
761  require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
762 
763  $now = dol_now();
764 
765  $this->db->begin();
766 
767  $sql = "INSERT INTO ".MAIN_DB_PREFIX."bank_account (";
768  $sql .= "datec";
769  $sql .= ", ref";
770  $sql .= ", label";
771  $sql .= ", entity";
772  $sql .= ", account_number";
773  $sql .= ", fk_accountancy_journal";
774  $sql .= ", bank";
775  $sql .= ", code_banque";
776  $sql .= ", code_guichet";
777  $sql .= ", number";
778  $sql .= ", cle_rib";
779  $sql .= ", bic";
780  $sql .= ", iban_prefix";
781  $sql .= ", domiciliation";
782  $sql .= ", pti_in_ctti";
783  $sql .= ", proprio";
784  $sql .= ", owner_address";
785  $sql .= ", owner_zip";
786  $sql .= ", owner_town";
787  $sql .= ", owner_country_id";
788  $sql .= ", currency_code";
789  $sql .= ", rappro";
790  $sql .= ", min_allowed";
791  $sql .= ", min_desired";
792  $sql .= ", comment";
793  $sql .= ", state_id";
794  $sql .= ", fk_pays";
795  $sql .= ", ics";
796  $sql .= ", ics_transfer";
797  $sql .= ") VALUES (";
798  $sql .= "'".$this->db->idate($now)."'";
799  $sql .= ", '".$this->db->escape($this->ref)."'";
800  $sql .= ", '".$this->db->escape($this->label)."'";
801  $sql .= ", ".((int) $conf->entity);
802  $sql .= ", '".$this->db->escape($this->account_number)."'";
803  $sql .= ", ".($this->fk_accountancy_journal > 0 ? ((int) $this->fk_accountancy_journal) : "null");
804  $sql .= ", '".$this->db->escape($this->bank)."'";
805  $sql .= ", '".$this->db->escape($this->code_banque)."'";
806  $sql .= ", '".$this->db->escape($this->code_guichet)."'";
807  $sql .= ", '".$this->db->escape($this->number)."'";
808  $sql .= ", '".$this->db->escape($this->cle_rib)."'";
809  $sql .= ", '".$this->db->escape($this->bic)."'";
810  $sql .= ", '".$this->db->escape($this->iban)."'";
811  $sql .= ", '".$this->db->escape($this->address)."'";
812  $sql .= ", ".((int) $this->pti_in_ctti);
813  $sql .= ", '".$this->db->escape($this->proprio)."'";
814  $sql .= ", '".$this->db->escape($this->owner_address)."'";
815  $sql .= ", '".$this->db->escape($this->owner_zip)."'";
816  $sql .= ", '".$this->db->escape($this->owner_town)."'";
817  $sql .= ", ".($this->owner_country_id > 0 ? ((int) $this->owner_country_id) : "null");
818  $sql .= ", '".$this->db->escape($this->currency_code)."'";
819  $sql .= ", ".((int) $this->rappro);
820  $sql .= ", ".price2num($this->min_allowed, 'MT');
821  $sql .= ", ".price2num($this->min_desired, 'MT');
822  $sql .= ", '".$this->db->escape($this->comment)."'";
823  $sql .= ", ".($this->state_id > 0 ? ((int) $this->state_id) : "null");
824  $sql .= ", ".($this->country_id > 0 ? ((int) $this->country_id) : "null");
825  $sql .= ", '".$this->db->escape($this->ics)."'";
826  $sql .= ", '".$this->db->escape($this->ics_transfer)."'";
827  $sql .= ")";
828 
829  dol_syslog(get_class($this)."::create", LOG_DEBUG);
830  $resql = $this->db->query($sql);
831  if ($resql) {
832  $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."bank_account");
833 
834  $result = $this->update($user, 1);
835  if ($result > 0) {
836  $accline = new AccountLine($this->db);
837  $accline->datec = $now;
838  $accline->label = '('.$langs->trans("InitialBankBalance").')';
839  $accline->amount = (float) price2num($balance);
840  $accline->fk_user_author = $user->id;
841  $accline->fk_account = $this->id;
842  $accline->datev = $this->date_solde;
843  $accline->dateo = $this->date_solde;
844  $accline->fk_type = 'SOLD';
845 
846  if ($accline->insert() < 0) {
847  $error++;
848  $this->error = $accline->error;
849  $this->errors = $accline->errors;
850  }
851 
852  if (!$error) {
853  $result = $this->insertExtraFields();
854  if ($result < 0) {
855  $error++;
856  }
857  }
858 
859  if (!$error && !$notrigger) {
860  // Call trigger
861  $result = $this->call_trigger('BANKACCOUNT_CREATE', $user);
862  if ($result < 0) {
863  $error++;
864  }
865  // End call triggers
866  }
867  } else {
868  $error++;
869  }
870  } else {
871  if ($this->db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
872  $this->error = $langs->trans("ErrorBankLabelAlreadyExists");
873  $error++;
874  } else {
875  $this->error = $this->db->error()." sql=".$sql;
876  $error++;
877  }
878  }
879 
880  if (!$error) {
881  $this->db->commit();
882  return $this->id;
883  } else {
884  $this->db->rollback();
885  return -1 * $error;
886  }
887  }
888 
896  public function update(User $user, $notrigger = 0)
897  {
898  global $langs, $conf;
899 
900  $error = 0;
901 
902  $this->db->begin();
903 
904  // Check parameters
905  if (empty($this->country_id)) {
906  $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Country"));
907  dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
908  return -1;
909  }
910  if (empty($this->ref)) {
911  $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Ref"));
912  dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
913  return -1;
914  }
915  if (!$this->label) {
916  $this->label = "???";
917  }
918 
919  $sql = "UPDATE ".MAIN_DB_PREFIX."bank_account SET ";
920 
921  $sql .= " ref = '".$this->db->escape($this->ref)."'";
922  $sql .= ",label = '".$this->db->escape($this->label)."'";
923 
924  $sql .= ",courant = ".((int) $this->type);
925  $sql .= ",clos = ".((int) $this->status);
926  $sql .= ",rappro = ".((int) $this->rappro);
927  $sql .= ",url = ".($this->url ? "'".$this->db->escape($this->url)."'" : "null");
928  $sql .= ",account_number = '".$this->db->escape($this->account_number)."'";
929  $sql .= ",fk_accountancy_journal = ".($this->fk_accountancy_journal > 0 ? ((int) $this->fk_accountancy_journal) : "null");
930  $sql .= ",bank = '".$this->db->escape($this->bank)."'";
931  $sql .= ",code_banque='".$this->db->escape($this->code_banque)."'";
932  $sql .= ",code_guichet='".$this->db->escape($this->code_guichet)."'";
933  $sql .= ",number='".$this->db->escape($this->number)."'";
934  $sql .= ",cle_rib='".$this->db->escape($this->cle_rib)."'";
935  $sql .= ",bic='".$this->db->escape($this->bic)."'";
936  $sql .= ",iban_prefix = '".$this->db->escape($this->iban)."'";
937  $sql .= ",domiciliation='".$this->db->escape($this->address)."'";
938  $sql .= ",pti_in_ctti=".((int) $this->pti_in_ctti);
939  $sql .= ",proprio = '".$this->db->escape($this->proprio)."'";
940  $sql .= ",owner_address = '".$this->db->escape($this->owner_address)."'";
941  $sql .= ",owner_zip = '".$this->db->escape($this->owner_zip)."'";
942  $sql .= ",owner_town = '".$this->db->escape($this->owner_town)."'";
943  $sql .= ",owner_country_id = ".($this->owner_country_id > 0 ? ((int) $this->owner_country_id) : "null");
944 
945  $sql .= ",currency_code = '".$this->db->escape($this->currency_code)."'";
946 
947  $sql .= ",min_allowed = ".($this->min_allowed != '' ? price2num($this->min_allowed) : "null");
948  $sql .= ",min_desired = ".($this->min_desired != '' ? price2num($this->min_desired) : "null");
949  $sql .= ",comment = '".$this->db->escape($this->comment)."'";
950 
951  $sql .= ",state_id = ".($this->state_id > 0 ? ((int) $this->state_id) : "null");
952  $sql .= ",fk_pays = ".($this->country_id > 0 ? ((int) $this->country_id) : "null");
953  $sql .= ",ics = '".$this->db->escape($this->ics)."'";
954  $sql .= ",ics_transfer = '".$this->db->escape($this->ics_transfer)."'";
955 
956  $sql .= " WHERE rowid = ".((int) $this->id);
957 
958  dol_syslog(get_class($this)."::update", LOG_DEBUG);
959  $result = $this->db->query($sql);
960  if ($result) {
961  // Actions on extra fields (by external module or standard code)
962  if (!$error) {
963  $result = $this->insertExtraFields();
964  if ($result < 0) {
965  $error++;
966  }
967  }
968 
969  if (!$error && !$notrigger) {
970  // Call trigger
971  $result = $this->call_trigger('BANKACCOUNT_MODIFY', $user);
972  if ($result < 0) {
973  $error++;
974  }
975  // End call triggers
976  }
977  } else {
978  $error++;
979  $this->error = $this->db->lasterror();
980  dol_print_error($this->db);
981  }
982 
983  if (!$error) {
984  $this->db->commit();
985  return $this->id;
986  } else {
987  $this->db->rollback();
988  return -1 * $error;
989  }
990  }
991 
992 
993  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1000  public function update_bban(User $user = null)
1001  {
1002  // phpcs:enable
1003  global $conf, $langs;
1004 
1005  // Load library to get BAN control function
1006  require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1007 
1008  dol_syslog(get_class($this)."::update_bban $this->code_banque,$this->code_guichet,$this->number,$this->cle_rib,$this->iban");
1009 
1010  // Check parameters
1011  if (!$this->ref) {
1012  $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->trans("Ref"));
1013  return -2;
1014  }
1015 
1016  $sql = "UPDATE ".MAIN_DB_PREFIX."bank_account SET ";
1017  $sql .= " bank = '".$this->db->escape($this->bank)."'";
1018  $sql .= ",code_banque='".$this->db->escape($this->code_banque)."'";
1019  $sql .= ",code_guichet='".$this->db->escape($this->code_guichet)."'";
1020  $sql .= ",number='".$this->db->escape($this->number)."'";
1021  $sql .= ",cle_rib='".$this->db->escape($this->cle_rib)."'";
1022  $sql .= ",bic='".$this->db->escape($this->bic)."'";
1023  $sql .= ",iban_prefix = '".$this->db->escape($this->iban)."'";
1024  $sql .= ",domiciliation='".$this->db->escape($this->domiciliation)."'";
1025  $sql .= ",proprio = '".$this->db->escape($this->proprio)."'";
1026  $sql .= ",owner_address = '".$this->db->escape($this->owner_address)."'";
1027  $sql .= ",owner_zip = '".$this->db->escape($this->owner_zip)."'";
1028  $sql .= ",owner_town = '".$this->db->escape($this->owner_town)."'";
1029  $sql .= ",owner_country_id = ".($this->owner_country_id > 0 ? ((int) $this->owner_country_id) : "null");
1030  $sql .= ",state_id = ".($this->state_id > 0 ? $this->state_id : "null");
1031  $sql .= ",fk_pays = ".($this->country_id > 0 ? $this->country_id : "null");
1032  $sql .= " WHERE rowid = ".((int) $this->id);
1033  $sql .= " AND entity = ".((int) $conf->entity);
1034 
1035  dol_syslog(get_class($this)."::update_bban", LOG_DEBUG);
1036 
1037  $result = $this->db->query($sql);
1038  if ($result) {
1039  return 1;
1040  } else {
1041  $this->error = $this->db->lasterror();
1042  dol_print_error($this->db);
1043  return -1;
1044  }
1045  }
1046 
1047 
1055  public function fetch($id, $ref = '')
1056  {
1057  if (empty($id) && empty($ref)) {
1058  $this->error = "ErrorBadParameters";
1059  return -1;
1060  }
1061 
1062  $sql = "SELECT ba.rowid, ba.ref, ba.label, ba.bank, ba.number, ba.courant as type, ba.clos as status, ba.rappro, ba.url,";
1063  $sql .= " ba.code_banque, ba.code_guichet, ba.cle_rib, ba.bic, ba.iban_prefix as iban,";
1064  $sql .= " ba.domiciliation as address, ba.pti_in_ctti, ba.proprio as owner_name, ba.owner_address, ba.owner_zip, ba.owner_town, ba.owner_country_id, ba.state_id, ba.fk_pays as country_id,";
1065  $sql .= " ba.account_number, ba.fk_accountancy_journal, ba.currency_code,";
1066  $sql .= " ba.min_allowed, ba.min_desired, ba.comment,";
1067  $sql .= " ba.datec as date_creation, ba.tms as date_modification, ba.ics, ba.ics_transfer,";
1068  $sql .= ' c.code as country_code, c.label as country,';
1069  $sql .= ' d.code_departement as state_code, d.nom as state,';
1070  $sql .= ' aj.code as accountancy_journal';
1071  $sql .= " FROM ".MAIN_DB_PREFIX."bank_account as ba";
1072  $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_country as c ON ba.fk_pays = c.rowid';
1073  $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_departements as d ON ba.state_id = d.rowid';
1074  $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'accounting_journal as aj ON aj.rowid=ba.fk_accountancy_journal';
1075  $sql .= " WHERE ba.entity IN (".getEntity($this->element).")";
1076  if ($id) {
1077  $sql .= " AND ba.rowid = ".((int) $id);
1078  }
1079  if ($ref) {
1080  $sql .= " AND ba.ref = '".$this->db->escape($ref)."'";
1081  }
1082 
1083  dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
1084  $result = $this->db->query($sql);
1085  if ($result) {
1086  if ($this->db->num_rows($result)) {
1087  $obj = $this->db->fetch_object($result);
1088 
1089  $this->id = $obj->rowid;
1090  $this->rowid = $obj->rowid;
1091  $this->ref = $obj->ref;
1092  $this->label = $obj->label;
1093  $this->type = $obj->type;
1094  $this->courant = $obj->type;
1095  $this->bank = $obj->bank;
1096  $this->clos = $obj->status;
1097  $this->status = $obj->status;
1098  $this->rappro = $obj->rappro;
1099  $this->url = $obj->url;
1100 
1101  $this->code_banque = $obj->code_banque;
1102  $this->code_guichet = $obj->code_guichet;
1103  $this->number = $obj->number;
1104  $this->cle_rib = $obj->cle_rib;
1105  $this->bic = $obj->bic;
1106  $this->iban = $obj->iban;
1107  $this->domiciliation = $obj->address;
1108  $this->address = $obj->address;
1109  $this->pti_in_ctti = $obj->pti_in_ctti;
1110  $this->proprio = $obj->owner_name;
1111  $this->owner_name = $obj->owner_name;
1112  $this->owner_address = $obj->owner_address;
1113  $this->owner_zip = $obj->owner_zip;
1114  $this->owner_town = $obj->owner_town;
1115  $this->owner_country_id = $obj->owner_country_id;
1116 
1117  $this->state_id = $obj->state_id;
1118  $this->state_code = $obj->state_code;
1119  $this->state = $obj->state;
1120 
1121  $this->country_id = $obj->country_id;
1122  $this->country_code = $obj->country_code;
1123  $this->country = $obj->country;
1124 
1125  $this->account_number = $obj->account_number;
1126  $this->fk_accountancy_journal = $obj->fk_accountancy_journal;
1127  $this->accountancy_journal = $obj->accountancy_journal;
1128 
1129  $this->currency_code = $obj->currency_code;
1130  $this->account_currency_code = $obj->currency_code;
1131  $this->min_allowed = $obj->min_allowed;
1132  $this->min_desired = $obj->min_desired;
1133  $this->comment = $obj->comment;
1134 
1135  $this->date_creation = $this->db->jdate($obj->date_creation);
1136  $this->date_modification = $this->db->jdate($obj->date_modification);
1137 
1138  $this->ics = $obj->ics;
1139  $this->ics_transfer = $obj->ics_transfer;
1140 
1141  // Retrieve all extrafield
1142  // fetch optionals attributes and labels
1143  $this->fetch_optionals();
1144 
1145  return 1;
1146  } else {
1147  return 0;
1148  }
1149  } else {
1150  $this->error = $this->db->lasterror();
1151  $this->errors[] = $this->error;
1152  return -1;
1153  }
1154  }
1155 
1166  public function setCategories($categories)
1167  {
1168  require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1169  return parent::setCategoriesCommon($categories, Categorie::TYPE_ACCOUNT);
1170  }
1171 
1179  public function delete(User $user = null, $notrigger = 0)
1180  {
1181  $error = 0;
1182 
1183  $this->db->begin();
1184 
1185  // @TODO Check there is no child into llx_payment_various, ... to allow deletion ?
1186 
1187  // Delete link between tag and bank account
1188  if (!$error) {
1189  $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_account";
1190  $sql .= " WHERE fk_account = ".((int) $this->id);
1191 
1192  $resql = $this->db->query($sql);
1193  if (!$resql) {
1194  $error++;
1195  $this->error = "Error ".$this->db->lasterror();
1196  }
1197  }
1198 
1199  if (!$error) {
1200  $sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element;
1201  $sql .= " WHERE rowid = ".((int) $this->id);
1202 
1203  dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1204  $result = $this->db->query($sql);
1205  if ($result) {
1206  // Remove extrafields
1207  if (!$error) {
1208  $result = $this->deleteExtraFields();
1209  if ($result < 0) {
1210  $error++;
1211  dol_syslog(get_class($this)."::delete error -4 ".$this->error, LOG_ERR);
1212  }
1213  }
1214  } else {
1215  $error++;
1216  $this->error = "Error ".$this->db->lasterror();
1217  }
1218  }
1219 
1220  if (!$error) {
1221  $this->db->commit();
1222  return 1;
1223  } else {
1224  $this->db->rollback();
1225  return -1;
1226  }
1227  }
1228 
1229 
1236  public function getLibStatut($mode = 0)
1237  {
1238  return $this->LibStatut($this->status, $mode);
1239  }
1240 
1241  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1249  public function LibStatut($status, $mode = 0)
1250  {
1251  // phpcs:enable
1252  global $langs;
1253  $langs->load('banks');
1254 
1255  if ($status == self::STATUS_OPEN) {
1256  $label = $langs->transnoentitiesnoconv("StatusAccountOpened");
1257  $labelshort = $langs->transnoentitiesnoconv("StatusAccountOpened");
1258  $statusType = 'status4';
1259  } else {
1260  $label = $langs->transnoentitiesnoconv("StatusAccountClosed");
1261  $labelshort = $langs->transnoentitiesnoconv("StatusAccountClosed");
1262  $statusType = 'status5';
1263  }
1264 
1265  return dolGetStatus($label, $labelshort, '', $statusType, $mode);
1266  }
1267 
1268 
1269  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1275  public function can_be_deleted()
1276  {
1277  // phpcs:enable
1278  $can_be_deleted = false;
1279 
1280  $sql = "SELECT COUNT(rowid) as nb";
1281  $sql .= " FROM ".MAIN_DB_PREFIX."bank";
1282  $sql .= " WHERE fk_account = ".((int) $this->id);
1283 
1284  $resql = $this->db->query($sql);
1285  if ($resql) {
1286  $obj = $this->db->fetch_object($resql);
1287  if ($obj->nb <= 1) {
1288  $can_be_deleted = true; // Juste le solde
1289  }
1290  } else {
1291  dol_print_error($this->db);
1292  }
1293  return $can_be_deleted;
1294  }
1295 
1296 
1302  public function error()
1303  {
1304  return $this->error;
1305  }
1306 
1315  public function solde($option = 0, $date_end = '', $field = 'dateo')
1316  {
1317  $solde = 0;
1318 
1319  $sql = "SELECT sum(amount) as amount";
1320  $sql .= " FROM ".MAIN_DB_PREFIX."bank";
1321  $sql .= " WHERE fk_account = ".((int) $this->id);
1322  if ($option == 1) {
1323  $sql .= " AND ".$this->db->escape($field)." <= '".(!empty($date_end) ? $this->db->idate($date_end) : $this->db->idate(dol_now()))."'";
1324  }
1325 
1326  $resql = $this->db->query($sql);
1327  if ($resql) {
1328  if ($this->db->num_rows($resql)) {
1329  $obj = $this->db->fetch_object($resql);
1330  $solde = $obj->amount;
1331  }
1332  $this->db->free($resql);
1333  } else {
1334  $this->errors[] = $this->db->lasterror;
1335  return -1;
1336  }
1337 
1338  return (float) price2num($solde, 'MU');
1339  }
1340 
1341  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1349  public function load_board(User $user, $filteraccountid = 0)
1350  {
1351  // phpcs:enable
1352  global $conf, $langs;
1353 
1354  if ($user->socid) {
1355  return -1; // protection pour eviter appel par utilisateur externe
1356  }
1357 
1358  $sql = "SELECT b.rowid, b.datev as datefin";
1359  $sql .= " FROM ".MAIN_DB_PREFIX."bank as b,";
1360  $sql .= " ".MAIN_DB_PREFIX."bank_account as ba";
1361  $sql .= " WHERE b.rappro=0";
1362  $sql .= " AND b.fk_account = ba.rowid";
1363  $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
1364  $sql .= " AND (ba.rappro = 1 AND ba.courant != " . Account::TYPE_CASH . ")"; // Compte rapprochable
1365  $sql .= " AND clos = 0";
1366  if ($filteraccountid) {
1367  $sql .= " AND ba.rowid = ".((int) $filteraccountid);
1368  }
1369 
1370  $resql = $this->db->query($sql);
1371  if ($resql) {
1372  $langs->load("banks");
1373  $now = dol_now();
1374 
1375  require_once DOL_DOCUMENT_ROOT.'/core/class/workboardresponse.class.php';
1376 
1377  $response = new WorkboardResponse();
1378  $response->warning_delay = $conf->bank->rappro->warning_delay / 60 / 60 / 24;
1379  $response->label = $langs->trans("TransactionsToConciliate");
1380  $response->labelShort = $langs->trans("TransactionsToConciliateShort");
1381  $response->url = DOL_URL_ROOT.'/compta/bank/list.php?leftmenu=bank&amp;mainmenu=bank';
1382  $response->img = img_object('', "payment");
1383 
1384  while ($obj = $this->db->fetch_object($resql)) {
1385  $response->nbtodo++;
1386  if ($this->db->jdate($obj->datefin) < ($now - $conf->bank->rappro->warning_delay)) {
1387  $response->nbtodolate++;
1388  }
1389  }
1390 
1391  return $response;
1392  } else {
1393  dol_print_error($this->db);
1394  $this->error = $this->db->error();
1395  return -1;
1396  }
1397  }
1398 
1405  public function loadStateBoard($filteraccountid = 0)
1406  {
1407  global $user;
1408 
1409  if ($user->socid) {
1410  return -1; // protection pour eviter appel par utilisateur externe
1411  }
1412 
1413  $sql = "SELECT count(b.rowid) as nb";
1414  $sql .= " FROM ".MAIN_DB_PREFIX."bank as b,";
1415  $sql .= " ".MAIN_DB_PREFIX."bank_account as ba";
1416  $sql .= " WHERE b.fk_account = ba.rowid";
1417  $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
1418  $sql .= " AND (ba.rappro = 1 AND ba.courant != 2)"; // Compte rapprochable
1419  $sql .= " AND clos = 0";
1420  if ($filteraccountid) {
1421  $sql .= " AND ba.rowid = ".((int) $filteraccountid);
1422  }
1423 
1424  $resql = $this->db->query($sql);
1425  if ($resql) {
1426  while ($obj = $this->db->fetch_object($resql)) {
1427  $this->nb["banklines"] = $obj->nb;
1428  }
1429  $this->db->free($resql);
1430  return 1;
1431  } else {
1432  dol_print_error($this->db);
1433  $this->error = $this->db->error();
1434  return -1;
1435  }
1436  }
1437 
1438 
1444  public function countAccountToReconcile()
1445  {
1446  global $db, $conf, $user;
1447 
1448  //Protection against external users
1449  if ($user->socid) {
1450  return 0;
1451  }
1452 
1453  $nb = 0;
1454 
1455  $sql = "SELECT COUNT(ba.rowid) as nb";
1456  $sql .= " FROM ".MAIN_DB_PREFIX."bank_account as ba";
1457  $sql .= " WHERE ba.rappro > 0 and ba.clos = 0";
1458  $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
1459  if (!getDolGlobalString('BANK_CAN_RECONCILIATE_CASHACCOUNT')) {
1460  $sql .= " AND ba.courant != " . Account::TYPE_CASH;
1461  }
1462  $resql = $this->db->query($sql);
1463  if ($resql) {
1464  $obj = $this->db->fetch_object($resql);
1465  $nb = $obj->nb;
1466  } else {
1467  dol_print_error($this->db);
1468  }
1469 
1470  return $nb;
1471  }
1472 
1480  public function getTooltipContentArray($params)
1481  {
1482  global $langs;
1483  $langs->loadLangs(['banks', 'compta']);
1484  include_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1485 
1486  $datas = array();
1487 
1488  $nofetch = !empty($params['nofetch']);
1489  $pictos = img_picto('', $this->picto).' <u class="paddingrightnow">'.$langs->trans("BankAccount").'</u>';
1490  if (isset($this->status)) {
1491  $pictos .= ' '.$this->getLibStatut(5);
1492  }
1493  $datas['picto'] = $pictos;
1494  $datas['label'] = '<br><b>'.$langs->trans('Label').':</b> '.$this->label;
1495  $datas['accountnumber'] = '<br><b>'.$langs->trans('AccountNumber').':</b> '.$this->number;
1496  $datas['iban'] = '<br><b>'.$langs->trans('IBAN').':</b> '.getIbanHumanReadable($this);
1497  $datas['bic'] = '<br><b>'.$langs->trans('BIC').':</b> '.$this->bic;
1498  $datas['accountcurrency'] = '<br><b>'.$langs->trans("AccountCurrency").':</b> '.$this->currency_code;
1499 
1500  if (isModEnabled('accounting')) {
1501  include_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
1502  $langs->load("accountancy");
1503  $datas['accountaccounting'] = '<br><b>'.$langs->trans('AccountAccounting').':</b> '.length_accountg($this->account_number);
1504  $datas['accountancyjournal'] = '<br><b>'.$langs->trans('AccountancyJournal').':</b> '.$this->accountancy_journal;
1505  }
1506  // show categories for this record only in ajax to not overload lists
1507  if (isModEnabled('category') && !$nofetch) {
1508  require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
1509  $form = new Form($this->db);
1510  $datas['categories'] = '<br>' . $form->showCategories($this->id, Categorie::TYPE_ACCOUNT, 1);
1511  }
1512 
1513  return $datas;
1514  }
1515 
1527  public function getNomUrl($withpicto = 0, $mode = '', $option = '', $save_lastsearch_value = -1, $notooltip = 0, $morecss = '')
1528  {
1529  global $conf, $langs;
1530 
1531  if (!empty($conf->dol_no_mouse_hover)) {
1532  $notooltip = 1; // Force disable tooltips
1533  }
1534 
1535  include_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1536 
1537  $result = '';
1538  $classfortooltip = 'classfortooltip';
1539  $dataparams = '';
1540  $params = [
1541  'id' => $this->id,
1542  'objecttype' => $this->element,
1543  'option' => $option,
1544  'nofetch' => 1,
1545  ];
1546  if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1547  $classfortooltip = 'classforajaxtooltip';
1548  $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
1549  $label = '';
1550  } else {
1551  $label = implode($this->getTooltipContentArray($params));
1552  }
1553 
1554  $url = DOL_URL_ROOT.'/compta/bank/card.php?id='.$this->id;
1555  if ($mode == 'transactions') {
1556  $url = DOL_URL_ROOT.'/compta/bank/bankentries_list.php?id='.$this->id;
1557  } elseif ($mode == 'receipts') {
1558  $url = DOL_URL_ROOT.'/compta/bank/releve.php?account='.$this->id;
1559  }
1560 
1561  if ($option != 'nolink') {
1562  // Add param to save lastsearch_values or not
1563  $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1564  if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1565  $add_save_lastsearch_values = 1;
1566  }
1567  if ($add_save_lastsearch_values) {
1568  $url .= '&save_lastsearch_values=1';
1569  }
1570  }
1571 
1572  $linkclose = '';
1573  if (empty($notooltip)) {
1574  if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1575  $label = $langs->trans("BankAccount");
1576  $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
1577  }
1578  $linkclose .= ($label ? ' title="'.dol_escape_htmltag($label, 1).'"' : ' title="tocomplete"');
1579  $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
1580  } else {
1581  $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1582  }
1583 
1584  if ($option == 'nolink' || empty($url)) {
1585  $linkstart = '<span';
1586  } else {
1587  $linkstart = '<a href="'.$url.'"';
1588  }
1589  $linkstart .= $linkclose.'>';
1590  if ($option == 'nolink' || empty($url)) {
1591  $linkend = '</span>';
1592  } else {
1593  $linkend = '</a>';
1594  }
1595 
1596  $result .= $linkstart;
1597 
1598  if ($withpicto) {
1599  $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"'), 0, 0, $notooltip ? 0 : 1);
1600  }
1601  if ($withpicto != 2) {
1602  $result .= $this->ref.($option == 'reflabel' && $this->label ? ' - '.$this->label : '');
1603  }
1604  $result .= $linkend;
1605 
1606  return $result;
1607  }
1608 
1609 
1610  // Method after here are common to Account and CompanyBankAccount
1611 
1612 
1618  public function verif()
1619  {
1620  require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1621 
1622  $error = 0;
1623 
1624  // Call functions to check BAN
1625  if (!checkIbanForAccount($this)) {
1626  $error++;
1627  $this->error = 'IBANNotValid';
1628  }
1629  if (!checkSwiftForAccount($this)) {
1630  $error++;
1631  $this->error = 'SwiftNotValid';
1632  }
1633 
1634  if (! $error) {
1635  return 1;
1636  } else {
1637  return 0;
1638  }
1639  }
1640 
1646  public function getCountryCode()
1647  {
1648  global $mysoc;
1649 
1650  // We return country code of bank account
1651  if (!empty($this->country_code)) {
1652  return $this->country_code;
1653  }
1654 
1655  // For backward compatibility, we try to guess country from other information
1656  if (!empty($this->iban)) {
1657  // If IBAN defined, we can know country of account from it
1658  $reg = array();
1659  if (preg_match("/^([a-zA-Z][a-zA-Z])/i", $this->iban, $reg)) {
1660  return $reg[1];
1661  }
1662  }
1663 
1664  // If this class is linked to a third party
1665  if (!empty($this->socid)) {
1666  require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
1667  $company = new Societe($this->db);
1668  $result = $company->fetch($this->socid);
1669  if (!empty($company->country_code)) {
1670  return $company->country_code;
1671  }
1672  }
1673 
1674  // We return country code of managed company
1675  if (!empty($mysoc->country_code)) {
1676  return $mysoc->country_code;
1677  }
1678 
1679  return '';
1680  }
1681 
1689  public function getBannerAddress($htmlkey, $object)
1690  {
1691  global $conf, $langs;
1692 
1693  $out = '';
1694 
1695  $outdone = 0;
1696  $coords = $this->getFullAddress(1, ', ', getDolGlobalInt('MAIN_SHOW_REGION_IN_STATE_SELECT'));
1697  if ($coords) {
1698  if (!empty($conf->use_javascript_ajax)) {
1699  // hideonsmatphone because copyToClipboard call jquery dialog that does not work with jmobile
1700  $out .= '<a href="#" class="hideonsmartphone" onclick="return copyToClipboard(\''.dol_escape_js($coords).'\',\''.dol_escape_js($langs->trans("HelpCopyToClipboard")).'\');">';
1701  $out .= img_picto($langs->trans("Address"), 'map-marker-alt');
1702  $out .= '</a> ';
1703  }
1704  $address = dol_print_address($coords, 'address_'.$htmlkey.'_'.$this->id, $this->element, $this->id, 1, ', ');
1705  if ($address) {
1706  $out .= $address;
1707  $outdone++;
1708  }
1709  $outdone++;
1710  }
1711 
1712  return $out;
1713  }
1714 
1715 
1724  public function useDetailedBBAN()
1725  {
1726  $country_code = $this->getCountryCode();
1727 
1728  if (in_array($country_code, array('FR', 'ES', 'GA', 'IT', 'NC'))) {
1729  return 1; // France, Spain, Gabon, ... - Not valid for CH
1730  }
1731  if (in_array($country_code, array('AD', 'AU', 'BE', 'CA', 'DE', 'DK', 'GR', 'GB', 'ID', 'IE', 'IR', 'KR', 'NL', 'NZ', 'UK', 'US'))) {
1732  return 2; // Australia, England...
1733  }
1734  return 0;
1735  }
1736 
1742  public function needIBAN()
1743  {
1744  global $conf;
1745 
1746  if (getDolGlobalString('MAIN_IBAN_IS_NEVER_MANDATORY')) {
1747  return 0;
1748  }
1749 
1750  $country_code = $this->getCountryCode();
1751 
1752  $country_code_in_EEC = array(
1753  'AT', // Austria
1754  'BE', // Belgium
1755  'BG', // Bulgaria
1756  'CY', // Cyprus
1757  'CZ', // Czech republic
1758  'DE', // Germany
1759  'DK', // Danemark
1760  'EE', // Estonia
1761  'ES', // Spain
1762  'FI', // Finland
1763  'FR', // France
1764  'GB', // United Kingdom
1765  'GR', // Greece
1766  'HR', // Croatia
1767  'NL', // Holland
1768  'HU', // Hungary
1769  'IE', // Ireland
1770  'IM', // Isle of Man - Included in UK
1771  'IT', // Italy
1772  'LT', // Lithuania
1773  'LU', // Luxembourg
1774  'LV', // Latvia
1775  'MC', // Monaco - Included in France
1776  'MT', // Malta
1777  //'NO', // Norway
1778  'PL', // Poland
1779  'PT', // Portugal
1780  'RO', // Romania
1781  'SE', // Sweden
1782  'SK', // Slovakia
1783  'SI', // Slovenia
1784  'UK', // United Kingdom
1785  //'CH', // Switzerland - No. Swizerland in not in EEC
1786  );
1787 
1788  if (in_array($country_code, $country_code_in_EEC)) {
1789  return 1; // France, Spain, ...
1790  }
1791  return 0;
1792  }
1793 
1800  public function info($id)
1801  {
1802  }
1803 
1818  public function getFieldsToShow($includeibanbic = 0)
1819  {
1820  //Get the required properties depending on the country
1821  $detailedBBAN = $this->useDetailedBBAN();
1822 
1823  if ($detailedBBAN == 0) {
1824  $fieldarray = array(
1825  'BankAccountNumber'
1826  );
1827  } elseif ($detailedBBAN == 2) {
1828  $fieldarray = array(
1829  'BankCode',
1830  'BankAccountNumber'
1831  );
1832  } else {
1833  $fieldarray = self::getAccountNumberOrder();
1834  }
1835 
1836  //if ($this->needIBAN()) { // return always IBAN and BIC (this was old behaviour)
1837  if ($includeibanbic) {
1838  $fieldarray[] = 'IBAN';
1839  $fieldarray[] = 'BIC';
1840  }
1841  //}
1842 
1843  //Get the order the properties are shown
1844  return $fieldarray;
1845  }
1846 
1857  public static function getAccountNumberOrder()
1858  {
1859  global $conf;
1860 
1861  $fieldlists = array(
1862  'BankCode',
1863  'DeskCode',
1864  'BankAccountNumber',
1865  'BankAccountNumberKey'
1866  );
1867 
1868  if (getDolGlobalString('BANK_SHOW_ORDER_OPTION')) {
1869  if (is_numeric(getDolGlobalString('BANK_SHOW_ORDER_OPTION'))) {
1870  if (getDolGlobalString('BANK_SHOW_ORDER_OPTION') == '1') {
1871  $fieldlists = array(
1872  'BankCode',
1873  'DeskCode',
1874  'BankAccountNumberKey',
1875  'BankAccountNumber'
1876  );
1877  }
1878  } else {
1879  //Replace the old AccountNumber key with the new BankAccountNumber key
1880  $fieldlists = explode(
1881  ' ',
1882  preg_replace('/ ?[^Bank]AccountNumber ?/', 'BankAccountNumber', $conf->global->BANK_SHOW_ORDER_OPTION)
1883  );
1884  }
1885  }
1886 
1887  return $fieldlists;
1888  }
1889 
1890 
1898  public function initAsSpecimen()
1899  {
1900  // Example of IBAN FR7630001007941234567890185
1901  $this->specimen = 1;
1902  $this->ref = 'MBA';
1903  $this->label = 'My Big Company Bank account';
1904  $this->courant = Account::TYPE_CURRENT;
1905  $this->clos = Account::STATUS_OPEN;
1906  $this->type = Account::TYPE_CURRENT;
1907  $this->status = Account::STATUS_OPEN;
1908  $this->code_banque = '30001';
1909  $this->code_guichet = '00794';
1910  $this->number = '12345678901';
1911  $this->cle_rib = '85';
1912  $this->bic = 'AA12';
1913  $this->iban = 'FR7630001007941234567890185';
1914 
1915  $this->bank = 'MyBank';
1916  $this->address = 'Rue de Paris';
1917  $this->proprio = 'Owner';
1918  $this->owner_name = 'Owner';
1919  $this->owner_address = 'Owner address';
1920  $this->owner_zip = 'Owner zip';
1921  $this->owner_town = 'Owner town';
1922  $this->owner_country_id = 'Owner country_id';
1923  $this->country_id = 1;
1924 
1925  return 1;
1926  }
1927 
1936  public static function replaceThirdparty($dbs, $origin_id, $dest_id)
1937  {
1938  $sql = "UPDATE ".MAIN_DB_PREFIX."bank_url SET url_id = ".((int) $dest_id)." WHERE url_id = ".((int) $origin_id)." AND type='company'";
1939 
1940  if ($dbs->query($sql)) {
1941  return true;
1942  } else {
1943  //if ($ignoreerrors) return true; // TODO Not enough. If there is A-B on kept thirdparty and B-C on old one, we must get A-B-C after merge. Not A-B.
1944  //$this->errors = $dbs->lasterror();
1945  return false;
1946  }
1947  }
1948 
1956  public function getKanbanView($option = '', $arraydata = null)
1957  {
1958  global $langs;
1959 
1960  $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
1961 
1962  $return = '<div class="box-flex-item box-flex-grow-zero">';
1963  $return .= '<div class="info-box info-box-sm">';
1964  $return .= '<span class="info-box-icon bg-infobox-action">';
1965  $return .= img_picto('', $this->picto);
1966  $return .= '</span>';
1967  $return .= '<div class="info-box-content">';
1968  $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).'</span>';
1969  if ($selected >= 0) {
1970  $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
1971  }
1972  if (property_exists($this, 'type_lib')) {
1973  $return .= '<br><span class="info-box-label opacitymedium" title="'.$this->type_lib[$this->type].'">'.substr($this->type_lib[$this->type], 0, 24).'...</span>';
1974  }
1975  if (method_exists($this, 'solde')) {
1976  $return .= '<br><a href="'.DOL_URL_ROOT.'/compta/bank/bankentries_list.php?id='.$this->id.'">';
1977  $return .= '<span class="opacitymedium">'.$langs->trans("Balance").'</span> : <span class="amount">'.price(price2num($this->solde(1), 'MT'), 0, $langs, 1, -1, -1, $this->currency_code).'</span>';
1978  }
1979  if (method_exists($this, 'getLibStatut')) {
1980  $return .= '<br><div class="info-box-status">'.$this->getLibStatut(3).'</div>';
1981  }
1982  $return .= '</div>';
1983  $return .= '</div>';
1984  $return .= '</div>';
1985  return $return;
1986  }
1987 }
1988 
1989 
1990 require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
1991 
1995 class AccountLine extends CommonObjectLine
1996 {
2000  public $db;
2001 
2005  public $element = 'bank';
2006 
2010  public $table_element = 'bank';
2011 
2015  public $picto = 'accountline';
2016 
2020  public $id;
2021 
2025  public $ref;
2026 
2032  public $datec;
2033 
2039  public $dateo;
2040 
2046  public $datev;
2047 
2051  public $amount;
2052 
2056  public $amount_main_currency;
2057 
2061  public $fk_user_author;
2062 
2066  public $fk_user_rappro;
2067 
2071  public $fk_type;
2072 
2076  public $fk_bordereau;
2077 
2081  public $fk_account;
2082 
2086  public $bank_account_ref;
2087 
2091  public $bank_account_label;
2092 
2096  public $numero_compte;
2097 
2101  public $emetteur;
2102 
2106  public $rappro;
2107 
2111  public $num_releve;
2112 
2116  public $num_chq;
2117 
2121  public $bank_chq;
2122 
2126  public $label;
2127 
2131  public $note;
2132 
2137  public $user_rappro;
2138 
2139 
2145  public function __construct(DoliDB $db)
2146  {
2147  $this->db = $db;
2148  }
2149 
2158  public function fetch($rowid, $ref = '', $num = '')
2159  {
2160  // Check parameters
2161  if (empty($rowid) && empty($ref) && empty($num)) {
2162  return -1;
2163  }
2164 
2165  $sql = "SELECT b.rowid, b.datec, b.datev, b.dateo, b.amount, b.label as label, b.fk_account,";
2166  $sql .= " b.fk_user_author, b.fk_user_rappro,";
2167  $sql .= " b.fk_type, b.num_releve, b.num_chq, b.rappro, b.note,";
2168  $sql .= " b.fk_bordereau, b.banque, b.emetteur,";
2169  $sql .= " ba.ref as bank_account_ref, ba.label as bank_account_label";
2170  $sql .= " FROM ".MAIN_DB_PREFIX."bank as b,";
2171  $sql .= " ".MAIN_DB_PREFIX."bank_account as ba";
2172  $sql .= " WHERE b.fk_account = ba.rowid";
2173  $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
2174  if ($num) {
2175  $sql .= " AND b.num_chq = '".$this->db->escape($num)."'";
2176  } elseif ($ref) {
2177  $sql .= " AND b.rowid = '".$this->db->escape($ref)."'";
2178  } else {
2179  $sql .= " AND b.rowid = ".((int) $rowid);
2180  }
2181 
2182  dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
2183  $result = $this->db->query($sql);
2184  if ($result) {
2185  $ret = 0;
2186 
2187  $obj = $this->db->fetch_object($result);
2188  if ($obj) {
2189  $this->id = $obj->rowid;
2190  $this->rowid = $obj->rowid;
2191  $this->ref = $obj->rowid;
2192 
2193  $this->datec = $this->db->jdate($obj->datec);
2194  $this->datev = $this->db->jdate($obj->datev);
2195  $this->dateo = $this->db->jdate($obj->dateo);
2196  $this->amount = $obj->amount;
2197  $this->label = $obj->label;
2198  $this->note = $obj->note;
2199 
2200  $this->fk_user_author = $obj->fk_user_author;
2201  $this->fk_user_rappro = $obj->fk_user_rappro;
2202 
2203  $this->fk_type = $obj->fk_type; // Type of transaction
2204  $this->rappro = (int) $obj->rappro;
2205  $this->num_releve = $obj->num_releve;
2206 
2207  $this->num_chq = $obj->num_chq;
2208  $this->bank_chq = $obj->banque;
2209  $this->fk_bordereau = $obj->fk_bordereau;
2210 
2211  $this->fk_account = $obj->fk_account;
2212  $this->bank_account_ref = $obj->bank_account_ref;
2213  $this->bank_account_label = $obj->bank_account_label;
2214 
2215  // Retrieve all extrafield
2216  // fetch optionals attributes and labels
2217  $this->fetch_optionals();
2218 
2219  $ret = 1;
2220  }
2221  $this->db->free($result);
2222  return $ret;
2223  } else {
2224  return -1;
2225  }
2226  }
2227 
2233  public function insert()
2234  {
2235  $error = 0;
2236 
2237  $this->db->begin();
2238 
2239  $sql = "INSERT INTO ".MAIN_DB_PREFIX."bank (";
2240  $sql .= "datec";
2241  $sql .= ", dateo";
2242  $sql .= ", datev";
2243  $sql .= ", label";
2244  $sql .= ", amount";
2245  $sql .= ", amount_main_currency";
2246  $sql .= ", fk_user_author";
2247  $sql .= ", num_chq";
2248  $sql .= ", fk_account";
2249  $sql .= ", fk_type";
2250  $sql .= ", emetteur,banque";
2251  $sql .= ", rappro";
2252  $sql .= ", numero_compte";
2253  $sql .= ", num_releve";
2254  $sql .= ") VALUES (";
2255  $sql .= "'".$this->db->idate($this->datec)."'";
2256  $sql .= ", '".$this->db->idate($this->dateo)."'";
2257  $sql .= ", '".$this->db->idate($this->datev)."'";
2258  $sql .= ", '".$this->db->escape($this->label)."'";
2259  $sql .= ", ".price2num($this->amount);
2260  $sql .= ", ".(empty($this->amount_main_currency) ? "NULL" : price2num($this->amount_main_currency));
2261  $sql .= ", ".($this->fk_user_author > 0 ? ((int) $this->fk_user_author) : "null");
2262  $sql .= ", ".($this->num_chq ? "'".$this->db->escape($this->num_chq)."'" : "null");
2263  $sql .= ", '".$this->db->escape($this->fk_account)."'";
2264  $sql .= ", '".$this->db->escape($this->fk_type)."'";
2265  $sql .= ", ".($this->emetteur ? "'".$this->db->escape($this->emetteur)."'" : "null");
2266  $sql .= ", ".($this->bank_chq ? "'".$this->db->escape($this->bank_chq)."'" : "null");
2267  $sql .= ", ".(int) $this->rappro;
2268  $sql .= ", ".($this->numero_compte ? "'".$this->db->escape($this->numero_compte)."'" : "''");
2269  $sql .= ", ".($this->num_releve ? "'".$this->db->escape($this->num_releve)."'" : "null");
2270  $sql .= ")";
2271 
2272 
2273  dol_syslog(get_class($this)."::insert", LOG_DEBUG);
2274  $resql = $this->db->query($sql);
2275  if ($resql) {
2276  $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'bank');
2277  // Actions on extra fields (by external module or standard code)
2278  $result = $this->insertExtraFields();
2279  if ($result < 0) {
2280  $error++;
2281  }
2282  } else {
2283  $error++;
2284  $this->error = $this->db->lasterror();
2285  dol_print_error($this->db);
2286  }
2287 
2288  if (!$error) {
2289  $this->db->commit();
2290  return $this->id;
2291  } else {
2292  $this->db->rollback();
2293  return -1 * $error;
2294  }
2295  }
2296 
2304  public function delete(User $user = null, $notrigger = 0)
2305  {
2306  $nbko = 0;
2307 
2308  if ($this->rappro) {
2309  // Protection to avoid any delete of consolidated lines
2310  $this->error = "ErrorDeleteNotPossibleLineIsConsolidated";
2311  return -1;
2312  }
2313 
2314  $this->db->begin();
2315 
2316  if (!$notrigger) {
2317  // Call trigger
2318  $result = $this->call_trigger('BANKACCOUNTLINE_DELETE', $user);
2319  if ($result < 0) {
2320  $this->db->rollback();
2321  return -1;
2322  }
2323  // End call triggers
2324  }
2325 
2326  // Protection to avoid any delete of accounted lines. Protection on by default
2327  if (!getDolGlobalString('BANK_ALLOW_TRANSACTION_DELETION_EVEN_IF_IN_ACCOUNTING')) {
2328  $sql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."accounting_bookkeeping WHERE doc_type = 'bank' AND fk_doc = ".((int) $this->id);
2329  $resql = $this->db->query($sql);
2330  if ($resql) {
2331  $obj = $this->db->fetch_object($resql);
2332  if ($obj && $obj->nb) {
2333  $this->error = 'ErrorRecordAlreadyInAccountingDeletionNotPossible';
2334  $this->db->rollback();
2335  return -1;
2336  }
2337  } else {
2338  $this->error = $this->db->lasterror();
2339  $this->db->rollback();
2340  return -1;
2341  }
2342  }
2343 
2344  // Delete urls
2345  $result = $this->delete_urls($user);
2346  if ($result < 0) {
2347  $nbko++;
2348  }
2349 
2350  $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank_class WHERE lineid=".(int) $this->rowid;
2351  dol_syslog(get_class($this)."::delete", LOG_DEBUG);
2352  $result = $this->db->query($sql);
2353  if (!$result) {
2354  $nbko++;
2355  }
2356 
2357  $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank_extrafields WHERE fk_object=".(int) $this->rowid;
2358  $result = $this->db->query($sql);
2359  if (!$result) {
2360  $nbko++;
2361  }
2362 
2363  $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank WHERE rowid=".(int) $this->rowid;
2364  dol_syslog(get_class($this)."::delete", LOG_DEBUG);
2365  $result = $this->db->query($sql);
2366  if (!$result) {
2367  $nbko++;
2368  }
2369 
2370  if (!$nbko) {
2371  $this->db->commit();
2372  return 1;
2373  } else {
2374  $this->db->rollback();
2375  return -$nbko;
2376  }
2377  }
2378 
2379 
2380  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2387  public function delete_urls(User $user = null)
2388  {
2389  // phpcs:enable
2390  $nbko = 0;
2391 
2392  if ($this->rappro) {
2393  // Protection to avoid any delete of consolidated lines
2394  $this->error = "ErrorDeleteNotPossibleLineIsConsolidated";
2395  return -1;
2396  }
2397 
2398  $this->db->begin();
2399 
2400  $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank_url WHERE fk_bank=".(int) $this->rowid;
2401  dol_syslog(get_class($this)."::delete_urls", LOG_DEBUG);
2402  $result = $this->db->query($sql);
2403  if (!$result) {
2404  $nbko++;
2405  }
2406 
2407  if (!$nbko) {
2408  $this->db->commit();
2409  return 1;
2410  } else {
2411  $this->db->rollback();
2412  return -$nbko;
2413  }
2414  }
2415 
2416 
2424  public function update(User $user, $notrigger = 0)
2425  {
2426  $this->db->begin();
2427 
2428  $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2429  $sql .= " amount = ".price2num($this->amount).",";
2430  $sql .= " datev='".$this->db->idate($this->datev)."',";
2431  $sql .= " dateo='".$this->db->idate($this->dateo)."'";
2432  $sql .= " WHERE rowid = ".((int) $this->rowid);
2433 
2434  dol_syslog(get_class($this)."::update", LOG_DEBUG);
2435  $resql = $this->db->query($sql);
2436  if ($resql) {
2437  $this->db->commit();
2438  return 1;
2439  } else {
2440  $this->db->rollback();
2441  $this->error = $this->db->error();
2442  return -1;
2443  }
2444  }
2445 
2446 
2452  public function updateLabel()
2453  {
2454  $this->db->begin();
2455 
2456  $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2457  $sql .= " label = '".$this->db->escape($this->label)."'";
2458  $sql .= " WHERE rowid = ".((int) $this->rowid);
2459 
2460  dol_syslog(get_class($this)."::update_label", LOG_DEBUG);
2461  $resql = $this->db->query($sql);
2462  if ($resql) {
2463  $this->db->commit();
2464  return 1;
2465  } else {
2466  $this->db->rollback();
2467  $this->error = $this->db->error();
2468  return -1;
2469  }
2470  }
2471 
2472 
2473  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2482  public function update_conciliation(User $user, $cat, $conciliated = 1)
2483  {
2484  // phpcs:enable
2485  global $conf, $langs;
2486 
2487  $this->db->begin();
2488 
2489  // Check statement field
2490  if (getDolGlobalString('BANK_STATEMENT_REGEX_RULE')) {
2491  if (!preg_match('/' . getDolGlobalString('BANK_STATEMENT_REGEX_RULE').'/', $this->num_releve)) {
2492  $this->errors[] = $langs->trans("ErrorBankStatementNameMustFollowRegex", getDolGlobalString('BANK_STATEMENT_REGEX_RULE'));
2493  return -1;
2494  }
2495  }
2496 
2497  $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2498  $sql .= " rappro = ".((int) $conciliated);
2499  $sql .= ", num_releve = '".$this->db->escape($this->num_releve)."'";
2500  if ($conciliated) {
2501  $sql .= ", fk_user_rappro = ".$user->id;
2502  }
2503  $sql .= " WHERE rowid = ".((int) $this->id);
2504 
2505  dol_syslog(get_class($this)."::update_conciliation", LOG_DEBUG);
2506  $resql = $this->db->query($sql);
2507  if ($resql) {
2508  if (!empty($cat) && $cat > 0) {
2509  $sql = "INSERT INTO ".MAIN_DB_PREFIX."bank_class (";
2510  $sql .= "lineid";
2511  $sql .= ", fk_categ";
2512  $sql .= ") VALUES (";
2513  $sql .= $this->id;
2514  $sql .= ", ".((int) $cat);
2515  $sql .= ")";
2516 
2517  dol_syslog(get_class($this)."::update_conciliation", LOG_DEBUG);
2518  $this->db->query($sql);
2519 
2520  // No error check. Can fail if category already affected
2521  // TODO Do no try the insert if link already exists
2522  }
2523 
2524  $this->rappro = 1;
2525 
2526  $this->db->commit();
2527  return 1;
2528  } else {
2529  $this->db->rollback();
2530  return -1;
2531  }
2532  }
2533 
2534 
2535  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2543  public function datev_change($rowid, $sign = 1)
2544  {
2545  // phpcs:enable
2546  $sql = "SELECT datev FROM ".MAIN_DB_PREFIX."bank WHERE rowid = ".((int) $rowid);
2547  $resql = $this->db->query($sql);
2548  if ($resql) {
2549  $obj = $this->db->fetch_object($resql);
2550  $newdate = $this->db->jdate($obj->datev) + (3600 * 24 * $sign);
2551 
2552  $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2553  $sql .= " datev = '".$this->db->idate($newdate)."'";
2554  $sql .= " WHERE rowid = ".((int) $rowid);
2555 
2556  $result = $this->db->query($sql);
2557  if ($result) {
2558  if ($this->db->affected_rows($result)) {
2559  return 1;
2560  }
2561  } else {
2562  dol_print_error($this->db);
2563  return 0;
2564  }
2565  } else {
2566  dol_print_error($this->db);
2567  }
2568  return 0;
2569  }
2570 
2571  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2578  public function datev_next($id)
2579  {
2580  // phpcs:enable
2581  return $this->datev_change($id, 1);
2582  }
2583 
2584  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2591  public function datev_previous($id)
2592  {
2593  // phpcs:enable
2594  return $this->datev_change($id, -1);
2595  }
2596 
2597 
2598  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2606  public function dateo_change($rowid, $sign = 1)
2607  {
2608  // phpcs:enable
2609  $sql = "SELECT dateo FROM ".MAIN_DB_PREFIX."bank WHERE rowid = ".((int) $rowid);
2610  $resql = $this->db->query($sql);
2611  if ($resql) {
2612  $obj = $this->db->fetch_object($resql);
2613  $newdate = $this->db->jdate($obj->dateo) + (3600 * 24 * $sign);
2614 
2615  $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2616  $sql .= " dateo = '".$this->db->idate($newdate)."'";
2617  $sql .= " WHERE rowid = ".((int) $rowid);
2618 
2619  $result = $this->db->query($sql);
2620  if ($result) {
2621  if ($this->db->affected_rows($result)) {
2622  return 1;
2623  }
2624  } else {
2625  dol_print_error($this->db);
2626  return 0;
2627  }
2628  } else {
2629  dol_print_error($this->db);
2630  }
2631  return 0;
2632  }
2633 
2634  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2641  public function dateo_next($id)
2642  {
2643  // phpcs:enable
2644  return $this->dateo_change($id, 1);
2645  }
2646 
2647  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2654  public function dateo_previous($id)
2655  {
2656  // phpcs:enable
2657  return $this->dateo_change($id, -1);
2658  }
2659 
2660 
2667  public function info($id)
2668  {
2669  $sql = 'SELECT b.rowid, b.datec, b.tms as datem,';
2670  $sql .= ' b.fk_user_author, b.fk_user_rappro';
2671  $sql .= ' FROM '.MAIN_DB_PREFIX.'bank as b';
2672  $sql .= ' WHERE b.rowid = '.((int) $id);
2673 
2674  $result = $this->db->query($sql);
2675  if ($result) {
2676  if ($this->db->num_rows($result)) {
2677  $obj = $this->db->fetch_object($result);
2678 
2679  $this->id = $obj->rowid;
2680 
2681  $this->user_creation_id = $obj->fk_user_author;
2682  $this->user_rappro = $obj->fk_user_rappro;
2683  $this->date_creation = $this->db->jdate($obj->datec);
2684  $this->date_modification = $this->db->jdate($obj->datem);
2685  //$this->date_rappro = $obj->daterappro; // Not yet managed
2686  }
2687  $this->db->free($result);
2688  } else {
2689  dol_print_error($this->db);
2690  }
2691  }
2692 
2693 
2703  public function getNomUrl($withpicto = 0, $maxlen = 0, $option = '', $notooltip = 0)
2704  {
2705  global $conf, $langs;
2706 
2707  $result = '';
2708 
2709  $label = img_picto('', $this->picto).' <u>'.$langs->trans("BankTransactionLine").'</u>:<br>';
2710  $label .= '<b>'.$langs->trans("Ref").':</b> '.$this->ref;
2711  if ($this->amount) {
2712  $label .= '<br><strong>'.$langs->trans("Amount").':</strong> '.price($this->amount, 0, $langs, 1, -1, -1, $conf->currency);
2713  }
2714 
2715  $linkstart = '<a href="'.DOL_URL_ROOT.'/compta/bank/line.php?rowid='.((int) $this->id).'&save_lastsearch_values=1" title="'.dol_escape_htmltag($label, 1).'" class="classfortooltip">';
2716  $linkend = '</a>';
2717 
2718  $result .= $linkstart;
2719  if ($withpicto) {
2720  $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);
2721  }
2722  if ($withpicto != 2) {
2723  $result .= ($this->ref ? $this->ref : $this->id);
2724  }
2725 
2726  $result .= $linkend;
2727 
2728  if ($option == 'showall' || $option == 'showconciliated' || $option == 'showconciliatedandaccounted') {
2729  $result .= ' <span class="opacitymedium">(';
2730  }
2731  if ($option == 'showall') {
2732  $result .= $langs->trans("BankAccount").': ';
2733  $accountstatic = new Account($this->db);
2734  $accountstatic->id = $this->fk_account;
2735  $accountstatic->ref = $this->bank_account_ref;
2736  $accountstatic->label = $this->bank_account_label;
2737  $result .= $accountstatic->getNomUrl(0).', ';
2738  }
2739  if ($option == 'showall' || $option == 'showconciliated' || $option == 'showconciliatedandaccounted') {
2740  $result .= $langs->trans("BankLineConciliated").': ';
2741  $result .= yn($this->rappro);
2742  }
2743  if (isModEnabled('accounting') && ($option == 'showall' || $option == 'showconciliatedandaccounted')) {
2744  $sql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."accounting_bookkeeping";
2745  $sql .= " WHERE doc_type = 'bank' AND fk_doc = ".((int) $this->id);
2746  $resql = $this->db->query($sql);
2747  if ($resql) {
2748  $obj = $this->db->fetch_object($resql);
2749  if ($obj && $obj->nb) {
2750  $result .= ' - '.$langs->trans("Accounted").': '.yn(1);
2751  } else {
2752  $result .= ' - '.$langs->trans("Accounted").': '.yn(0);
2753  }
2754  }
2755  }
2756  if ($option == 'showall' || $option == 'showconciliated' || $option == 'showconciliatedandaccounted') {
2757  $result .= ')</span>';
2758  }
2759 
2760  return $result;
2761  }
2762 
2763 
2770  public function getLibStatut($mode = 0)
2771  {
2772  return $this->LibStatut($this->status, $mode);
2773  }
2774 
2775  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2783  public function LibStatut($status, $mode = 0)
2784  {
2785  // phpcs:enable
2786  return '';
2787  }
2788 
2794  public function getVentilExportCompta()
2795  {
2796  $alreadydispatched = 0;
2797 
2798  $type = 'bank';
2799 
2800  $sql = " SELECT COUNT(ab.rowid) as nb FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab WHERE ab.doc_type='".$this->db->escape($type)."' AND ab.fk_doc = ".((int) $this->id);
2801  $resql = $this->db->query($sql);
2802  if ($resql) {
2803  $obj = $this->db->fetch_object($resql);
2804  if ($obj) {
2805  $alreadydispatched = $obj->nb;
2806  }
2807  } else {
2808  $this->error = $this->db->lasterror();
2809  return -1;
2810  }
2811 
2812  if ($alreadydispatched) {
2813  return 1;
2814  }
2815  return 0;
2816  }
2817 }
if($user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition: card.php:58
length_accountg($account)
Return General accounting account with defined length (used for product and miscellaneous)
print $langs trans("AuditedSecurityEvents").'</strong >< span class="opacitymedium"></span >< br > status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition: security.php:607
checkSwiftForAccount(Account $account=null, $swift=null)
Check SWIFT information for a bank account.
Definition: bank.lib.php:284
checkIbanForAccount(Account $account=null, $ibantocheck=null)
Check IBAN number information for a bank account.
Definition: bank.lib.php:305
getIbanHumanReadable(Account $account)
Returns the iban human readable.
Definition: bank.lib.php:330
$object ref
Definition: info.php:79
Class to manage bank accounts.
solde($option=0, $date_end='', $field='dateo')
Return current balance.
fetch($id, $ref='')
Load a bank account into memory from database.
__construct(DoliDB $db)
Constructor.
getNomUrl($withpicto=0, $mode='', $option='', $save_lastsearch_value=-1, $notooltip=0, $morecss='')
Return clicable name (with picto eventually)
add_url_line($line_id, $url_id, $url, $label, $type)
Add a link between bank line record and its source.
loadStateBoard($filteraccountid=0)
Load the indicators this->nb for the state board.
update(User $user, $notrigger=0)
Update bank account card.
getCountryCode()
Return account country code.
getLibStatut($mode=0)
Return label of object status.
delete(User $user=null, $notrigger=0)
Delete bank account from database.
getBannerAddress($htmlkey, $object)
Return full address for banner.
error()
Return error.
deprecatedProperties()
Provide list of deprecated properties and replacements.
info($id)
Load miscellaneous information for tab "Info".
const TYPE_CASH
Cash account.
__toString()
Shows the account number in the appropriate format.
const TYPE_SAVINGS
Savings account.
getTooltipContentArray($params)
getTooltipContentArray
canBeConciliated()
Return if a bank account need to be conciliated.
create(User $user, $notrigger=0)
Create bank account into database.
can_be_deleted()
Indicates if an account can be deleted or not (without movements)
update_bban(User $user=null)
Update BBAN (RIB) account fields.
const TYPE_CURRENT
Current account.
setCategories($categories)
Sets object to supplied categories.
countAccountToReconcile()
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
verif()
Return if an account has valid information for Direct debit payment.
getFieldsToShow($includeibanbic=0)
Returns the fields in order that this bank account should show to the user Will return an array with ...
load_board(User $user, $filteraccountid=0)
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
get_url($fk_bank=0, $url_id=0, $type='')
TODO Move this into AccountLine Return array with links from llx_bank_url.
addline($date, $oper, $label, $amount, $num_chq, $categorie, User $user, $emetteur='', $banque='', $accountancycode='', $datev=null, $num_releve='', $amount_main_currency=null)
Add an entry into table ".MAIN_DB_PREFIX."bank.
LibStatut($status, $mode=0)
Return label of given object status.
Class to manage bank transaction lines.
Parent class of all other business classes (invoices, contracts, proposals, orders,...
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this->array_options This method is in most cases call...
setErrorsFromObject($object)
setErrorsFromObject
getFullAddress($withcountry=0, $sep="\n", $withregion=0, $extralangcode='')
Return full address of contact.
deleteExtraFields()
Delete all extra fields values for the current object.
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Class to manage Dolibarr database access.
Class to manage generation of HTML components Only common components must be here.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage Dolibarr users.
Definition: user.class.php:50
if(isModEnabled('invoice') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&!getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD') && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') && $user->hasRight('tax', 'charges', 'lire')) if(isModEnabled('invoice') &&isModEnabled('order') && $user->hasRight("commande", "lire") &&!getDolGlobalString('WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER')) $sql
Social contributions to pay.
Definition: index.php:745
print *****$script_file(".$version.") pid c cd cd cd description as p label as s rowid
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
td amount
Definition: global.inc.php:554
table table fiche title col title div col right btnTitle icon
Automatically calls the icon named with the corresponding "object_" prefix.
if(!defined( 'CSRFCHECK_WITH_TOKEN'))
div float
Buy price without taxes.
Definition: style.css.php:960
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:123