dolibarr 22.0.5
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-2025 Frédéric France <frederic.france@free.fr>
13 * Copyright (C) 2024-2025 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
35require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
36
37
41class 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 public $courant;
78
83 public $type;
84
89 public $bank;
90
98 public $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 public $proprio;
169
174 public $owner_name;
175
180 public $owner_address;
181
186 public $owner_zip;
187
192 public $owner_town;
196 public $owner_country_id;
200 public $owner_country_code;
201
208 public $domiciliation;
209
214 public $address;
218 public $state_id;
222 public $state_code;
226 public $state;
230 public $country_id;
231
237 public $type_lib = array();
238
243 public $account_number;
244
248 public $fk_accountancy_journal;
249
253 public $accountancy_journal;
254
259 public $currency_code;
260
267 public $account_currency_code;
268
273 public $min_allowed;
274
279 public $min_desired;
280
285 public $comment;
286
291 public $date_solde;
292
299 public $solde;
300
305 public $balance;
306
311 public $ics;
312
317 public $ics_transfer;
318
322 public $oldref;
323
324
349 // BEGIN MODULEBUILDER PROPERTIES
353 public $fields = array(
354 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 10),
355 'ref' => array('type' => 'varchar(12)', 'label' => 'Ref', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'showoncombobox' => 1, 'position' => 25),
356 'label' => array('type' => 'varchar(30)', 'label' => 'Label', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 30),
357 'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => '1', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 35, 'index' => 1),
358 'bank' => array('type' => 'varchar(60)', 'label' => 'Bank', 'enabled' => 1, 'visible' => -1, 'position' => 40),
359 'code_banque' => array('type' => 'varchar(128)', 'label' => 'Code banque', 'enabled' => 1, 'visible' => -1, 'position' => 45),
360 'code_guichet' => array('type' => 'varchar(6)', 'label' => 'Code guichet', 'enabled' => 1, 'visible' => -1, 'position' => 50),
361 'number' => array('type' => 'varchar(255)', 'label' => 'Number', 'enabled' => 1, 'visible' => -1, 'position' => 55),
362 'cle_rib' => array('type' => 'varchar(5)', 'label' => 'Cle rib', 'enabled' => 1, 'visible' => -1, 'position' => 60),
363 'bic' => array('type' => 'varchar(11)', 'label' => 'Bic', 'enabled' => 1, 'visible' => -1, 'position' => 65),
364 'iban_prefix' => array('type' => 'varchar(34)', 'label' => 'Iban prefix', 'enabled' => 1, 'visible' => -1, 'position' => 70),
365 'country_iban' => array('type' => 'varchar(2)', 'label' => 'Country iban', 'enabled' => 1, 'visible' => -1, 'position' => 75),
366 'cle_iban' => array('type' => 'varchar(2)', 'label' => 'Cle iban', 'enabled' => 1, 'visible' => -1, 'position' => 80),
367 'domiciliation' => array('type' => 'varchar(255)', 'label' => 'Domiciliation', 'enabled' => 1, 'visible' => -1, 'position' => 85),
368 'state_id' => array('type' => 'integer', 'label' => 'StateId', 'enabled' => 1, 'visible' => -1, 'position' => 90),
369 'fk_pays' => array('type' => 'integer', 'label' => 'Country', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 95),
370 'proprio' => array('type' => 'varchar(60)', 'label' => 'Proprio', 'enabled' => 1, 'visible' => -1, 'position' => 100),
371 'owner_address' => array('type' => 'varchar(255)', 'label' => 'Owner address', 'enabled' => 1, 'visible' => -1, 'position' => 105),
372 'owner_zip' => array('type' => 'varchar(25)', 'label' => 'Owner zip', 'enabled' => 1, 'visible' => -1, 'position' => 106),
373 'owner_town' => array('type' => 'varchar(50)', 'label' => 'Owner town', 'enabled' => 1, 'visible' => -1, 'position' => 107),
374 'owner_country_id' => array('type' => 'integer', 'label' => 'Owner country', 'enabled' => 1, 'visible' => -1, 'position' => 108),
375 'courant' => array('type' => 'smallint(6)', 'label' => 'Courant', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 110),
376 'clos' => array('type' => 'smallint(6)', 'label' => 'Clos', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 115),
377 'rappro' => array('type' => 'smallint(6)', 'label' => 'Rappro', 'enabled' => 1, 'visible' => -1, 'position' => 120),
378 'url' => array('type' => 'varchar(128)', 'label' => 'Url', 'enabled' => 1, 'visible' => -1, 'position' => 125),
379 'account_number' => array('type' => 'varchar(32)', 'label' => 'Account number', 'enabled' => 1, 'visible' => -1, 'position' => 130),
380 'fk_accountancy_journal' => array('type' => 'integer', 'label' => 'Accountancy journal ID', 'enabled' => 1, 'visible' => -1, 'position' => 132),
381 'accountancy_journal' => array('type' => 'varchar(20)', 'label' => 'Accountancy journal', 'enabled' => 1, 'visible' => -1, 'position' => 135),
382 'currency_code' => array('type' => 'varchar(3)', 'label' => 'Currency code', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 140),
383 'min_allowed' => array('type' => 'integer', 'label' => 'Min allowed', 'enabled' => 1, 'visible' => -1, 'position' => 145),
384 'min_desired' => array('type' => 'integer', 'label' => 'Min desired', 'enabled' => 1, 'visible' => -1, 'position' => 150),
385 'comment' => array('type' => 'text', 'label' => 'Comment', 'enabled' => 1, 'visible' => -1, 'position' => 155),
386 'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -1, 'position' => 156),
387 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 157),
388 'fk_user_author' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'Fk user author', 'enabled' => 1, 'visible' => -1, 'position' => 160),
389 'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'position' => 165),
390 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 170),
391 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'visible' => 0, 'position' => 175),
392 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'position' => 180),
393 'extraparams' => array('type' => 'varchar(255)', 'label' => 'Extraparams', 'enabled' => 1, 'visible' => -1, 'position' => 185),
394 );
395 // END MODULEBUILDER PROPERTIES
396
400 const TYPE_CURRENT = 1;
404 const TYPE_CASH = 2;
408 const TYPE_SAVINGS = 0;
409
410
411 const STATUS_OPEN = 0;
412 const STATUS_CLOSED = 1;
413
414
420 public function __construct(DoliDB $db)
421 {
422 global $langs;
423
424 $this->db = $db;
425
426 $this->ismultientitymanaged = 1;
427
428 $this->balance = 0;
429
430 $this->type_lib = array(
431 self::TYPE_SAVINGS => $langs->transnoentitiesnoconv("BankType0"),
432 self::TYPE_CURRENT => $langs->transnoentitiesnoconv("BankType1"),
433 self::TYPE_CASH => $langs->transnoentitiesnoconv("BankType2"),
434 );
435
436 $this->labelStatus = array(
437 self::STATUS_OPEN => $langs->transnoentitiesnoconv("StatusAccountOpened"),
438 self::STATUS_CLOSED => $langs->transnoentitiesnoconv("StatusAccountClosed")
439 );
440 }
441
447 public function __toString()
448 {
449 $string = '';
450 foreach ($this->getFieldsToShow() as $val) {
451 if ($val == 'BankCode') {
452 $string .= $this->code_banque.' ';
453 } elseif ($val == 'BankAccountNumber') {
454 $string .= $this->number.' ';
455 } elseif ($val == 'DeskCode') {
456 $string .= $this->code_guichet.' ';
457 } elseif ($val == 'BankAccountNumberKey') {
458 $string .= $this->cle_rib.' ';
459 } elseif ($val == 'BIC') {
460 $string .= $this->bic.' ';
461 } elseif ($val == 'IBAN') {
462 $string .= $this->iban.' ';
463 }
464 }
465
466 return trim($string);
467 }
468
469
475 public function canBeConciliated()
476 {
477 global $conf;
478
479 if (empty($this->rappro)) {
480 return -1;
481 }
482 if ($this->type == Account::TYPE_CASH && !getDolGlobalString('BANK_CAN_RECONCILIATE_CASHACCOUNT')) {
483 return -2;
484 }
485 if ($this->status) {
486 return -3;
487 }
488 return 1;
489 }
490
491
492 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
503 public function add_url_line($line_id, $url_id, $url, $label, $type)
504 {
505 // phpcs:enable
506 // Avoid uk_bank_url collision when the same target (line_id, url_id, type) is linked twice
507 // e.g. two distinct credit transfers for the same employee dispatched on the same bank line.
508 $sqlcheck = "SELECT rowid FROM ".MAIN_DB_PREFIX."bank_url";
509 $sqlcheck .= " WHERE fk_bank = ".((int) $line_id);
510 $sqlcheck .= " AND url_id = ".((int) $url_id);
511 $sqlcheck .= " AND type = '".$this->db->escape($type)."'";
512 $resqlcheck = $this->db->query($sqlcheck);
513 if ($resqlcheck) {
514 $obj = $this->db->fetch_object($resqlcheck);
515 if ($obj) {
516 $this->db->free($resqlcheck);
517 return (int) $obj->rowid;
518 }
519 $this->db->free($resqlcheck);
520 }
521
522 $sql = "INSERT INTO ".MAIN_DB_PREFIX."bank_url (";
523 $sql .= "fk_bank";
524 $sql .= ", url_id";
525 $sql .= ", url"; // deprecated
526 $sql .= ", label";
527 $sql .= ", type";
528 $sql .= ") VALUES (";
529 $sql .= ((int) $line_id);
530 $sql .= ", ".((int) $url_id);
531 $sql .= ", '".$this->db->escape($url)."'"; // deprecated
532 $sql .= ", '".$this->db->escape($label)."'";
533 $sql .= ", '".$this->db->escape($type)."'";
534 $sql .= ")";
535
536 dol_syslog(get_class($this)."::add_url_line", LOG_DEBUG);
537 if ($this->db->query($sql)) {
538 $rowid = $this->db->last_insert_id(MAIN_DB_PREFIX."bank_url");
539 return $rowid;
540 } else {
541 $this->error = $this->db->lasterror();
542 return -1;
543 }
544 }
545
546 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
556 public function get_url($fk_bank = 0, $url_id = 0, $type = '')
557 {
558 // phpcs:enable
559 $lines = array();
560
561 // Check parameters
562 if (!empty($fk_bank) && (!empty($url_id) || !empty($type))) {
563 $this->error = "ErrorBadParameter";
564 return -1;
565 }
566
567 $sql = "SELECT fk_bank, url_id, url, label, type";
568 $sql .= " FROM ".MAIN_DB_PREFIX."bank_url";
569 if ($fk_bank > 0) {
570 $sql .= " WHERE fk_bank = ".((int) $fk_bank);
571 } else {
572 $sql .= " WHERE url_id = ".((int) $url_id)." AND type = '".$this->db->escape($type)."'";
573 }
574 $sql .= " ORDER BY type, label";
575
576 dol_syslog(get_class($this)."::get_url", LOG_DEBUG);
577 $result = $this->db->query($sql);
578 if ($result) {
579 $i = 0;
580 $num = $this->db->num_rows($result);
581 while ($i < $num) {
582 $obj = $this->db->fetch_object($result);
583 // Old links (for compatibility)
584 $lines[$i][0] = $obj->url;
585 $lines[$i][1] = $obj->url_id;
586 $lines[$i][2] = $obj->label;
587 $lines[$i][3] = $obj->type;
588 // New links
589 $lines[$i]['url'] = $obj->url;
590 $lines[$i]['url_id'] = $obj->url_id;
591 $lines[$i]['label'] = $obj->label;
592 $lines[$i]['type'] = $obj->type;
593 $lines[$i]['fk_bank'] = $obj->fk_bank;
594 $i++;
595 }
596 } else {
597 dol_print_error($this->db);
598 }
599
600 return $lines;
601 }
602
622 public function addline($date, $oper, $label, $amount, $num_chq, $categorie, User $user, $emetteur = '', $banque = '', $accountancycode = '', $datev = null, $num_releve = '', $amount_main_currency = null, $note_private = '')
623 {
624 global $langs;
625
626 // Deprecation warning
627 if (is_numeric($oper)) {
628 dol_syslog(__METHOD__.": using numeric operations is deprecated", LOG_WARNING);
629 }
630
631 if (empty($this->id) && !empty($this->rowid)) { // For backward compatibility
632 $this->id = $this->rowid;
633 }
634
635 // Clean parameters
636 $emetteur = trim($emetteur);
637 $banque = trim($banque);
638 $label = trim($label);
639
640 $now = dol_now();
641
642 if (is_numeric($oper)) { // Clean operation to have a code instead of a rowid
643 $sql = "SELECT code FROM ".MAIN_DB_PREFIX."c_paiement";
644 $sql .= " WHERE id = ".((int) $oper);
645 $sql .= " AND entity IN (".getEntity('c_paiement').")";
646 $resql = $this->db->query($sql);
647 if ($resql) {
648 $obj = $this->db->fetch_object($resql);
649 $oper = $obj->code;
650 } else {
651 dol_print_error($this->db, 'Failed to get payment type code');
652 return -1;
653 }
654 }
655
656 // Check parameters
657 if (!$oper) {
658 $this->error = $langs->trans("OperNotDefined");
659 return -1;
660 }
661 if (!$this->id) {
662 $this->error = $langs->trans("ThisIdNotDefined");
663 return -2;
664 }
665 if ($this->type == Account::TYPE_CASH && $oper != 'LIQ') {
666 $this->error = "ErrorCashAccountAcceptsOnlyCashMoney";
667 return -3;
668 }
669
670 $this->db->begin();
671
672 if (is_null($datev) || empty($datev)) {
673 $datev = $date;
674 }
675
676 $accline = new AccountLine($this->db);
677 $accline->datec = $now;
678 $accline->dateo = $date;
679 $accline->datev = $datev;
680 $accline->label = $label;
681 $accline->amount = $amount;
682 $accline->amount_main_currency = $amount_main_currency;
683 $accline->fk_user_author = $user->id;
684 $accline->fk_account = $this->id;
685 $accline->fk_type = $oper;
686 $accline->numero_compte = $accountancycode;
687 $accline->num_releve = $num_releve;
688 $accline->note_private = $note_private;
689
690 if ($num_chq) {
691 $accline->num_chq = $num_chq;
692 }
693
694 if ($emetteur) {
695 $accline->emetteur = $emetteur;
696 }
697
698 if ($banque) {
699 $accline->bank_chq = $banque;
700 }
701
702 if ($accline->insert() > 0) {
703 if ($categorie > 0) {
704 $sql = "INSERT INTO ".MAIN_DB_PREFIX."category_bankline(";
705 $sql .= "lineid, fk_categ";
706 $sql .= ") VALUES (";
707 $sql .= ((int) $accline->id).", ".((int) $categorie);
708 $sql .= ")";
709
710 $result = $this->db->query($sql);
711 if (!$result) {
712 $this->error = $this->db->lasterror();
713 $this->db->rollback();
714
715 return -4;
716 }
717 }
718
719 $this->db->commit();
720
721 return $accline->id;
722 } else {
723 $this->setErrorsFromObject($accline);
724 $this->db->rollback();
725
726 return -5;
727 }
728 }
729
737 public function create($user, $notrigger = 0)
738 {
739 global $langs, $conf;
740
741 $error = 0;
742
743 // Clean parameters
744 if (!$this->min_allowed) {
745 $this->min_allowed = 0;
746 }
747 if (!$this->min_desired) {
748 $this->min_desired = 0;
749 }
750
751 // Check parameters
752 if (empty($this->country_id)) {
753 $langs->load('errors');
754 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Country"));
755 dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
756 return -1;
757 }
758 if (empty($this->ref)) {
759 $langs->load('errors');
760 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Ref"));
761 dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
762 return -1;
763 }
764 if (empty($this->date_solde)) {
765 $langs->load('errors');
766 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("DateInitialBalance"));
767 dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
768 return -1;
769 }
770
771 // Load libraries to check BAN
772 $balance = $this->balance;
773 if (empty($balance) && !empty($this->solde)) {
774 dol_syslog(get_class($this)."::create solde is deprecated use balance", LOG_NOTICE);
775 $balance = $this->solde;
776 }
777 if (empty($balance)) {
778 $balance = 0;
779 }
780 if (empty($this->status && !empty($this->clos))) {
781 dol_syslog(get_class($this)."::create clos is deprecated use status", LOG_NOTICE);
782 $this->status = $this->clos;
783 }
784
785 if (empty($this->country_id) && !empty($this->country_code)) {
786 $country_id = getCountry($this->country_code, '3');
787 $this->country_id = is_int($country_id) ? $country_id : 0;
788 }
789
790 // Load the library to validate/check a BAN account
791 require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
792
793 $now = dol_now();
794
795 $this->db->begin();
796
797 $sql = "INSERT INTO ".MAIN_DB_PREFIX."bank_account (";
798 $sql .= "datec";
799 $sql .= ", ref";
800 $sql .= ", label";
801 $sql .= ", entity";
802 $sql .= ", account_number";
803 $sql .= ", fk_accountancy_journal";
804 $sql .= ", bank";
805 $sql .= ", code_banque";
806 $sql .= ", code_guichet";
807 $sql .= ", number";
808 $sql .= ", cle_rib";
809 $sql .= ", bic";
810 $sql .= ", iban_prefix";
811 $sql .= ", domiciliation";
812 $sql .= ", pti_in_ctti";
813 $sql .= ", proprio";
814 $sql .= ", owner_address";
815 $sql .= ", owner_zip";
816 $sql .= ", owner_town";
817 $sql .= ", owner_country_id";
818 $sql .= ", currency_code";
819 $sql .= ", rappro";
820 $sql .= ", min_allowed";
821 $sql .= ", min_desired";
822 $sql .= ", comment";
823 $sql .= ", state_id";
824 $sql .= ", fk_pays";
825 $sql .= ", ics";
826 $sql .= ", ics_transfer";
827 $sql .= ") VALUES (";
828 $sql .= "'".$this->db->idate($now)."'";
829 $sql .= ", '".$this->db->escape($this->ref)."'";
830 $sql .= ", '".$this->db->escape($this->label)."'";
831 $sql .= ", ".((int) $conf->entity);
832 $sql .= ", '".$this->db->escape($this->account_number)."'";
833 $sql .= ", ".($this->fk_accountancy_journal > 0 ? ((int) $this->fk_accountancy_journal) : "null");
834 $sql .= ", '".$this->db->escape($this->bank)."'";
835 $sql .= ", '".$this->db->escape($this->code_banque)."'";
836 $sql .= ", '".$this->db->escape($this->code_guichet)."'";
837 $sql .= ", '".$this->db->escape($this->number)."'";
838 $sql .= ", '".$this->db->escape($this->cle_rib)."'";
839 $sql .= ", '".$this->db->escape($this->bic)."'";
840 $sql .= ", '".$this->db->escape($this->iban)."'";
841 $sql .= ", '".$this->db->escape($this->address)."'";
842 $sql .= ", ".((int) $this->pti_in_ctti);
843 $sql .= ", '".$this->db->escape($this->owner_name)."'";
844 $sql .= ", '".$this->db->escape($this->owner_address)."'";
845 $sql .= ", '".$this->db->escape($this->owner_zip)."'";
846 $sql .= ", '".$this->db->escape($this->owner_town)."'";
847 $sql .= ", ".($this->owner_country_id > 0 ? ((int) $this->owner_country_id) : "null");
848 $sql .= ", '".$this->db->escape($this->currency_code)."'";
849 $sql .= ", ".((int) $this->rappro);
850 $sql .= ", ".price2num($this->min_allowed, 'MT');
851 $sql .= ", ".price2num($this->min_desired, 'MT');
852 $sql .= ", '".$this->db->escape($this->comment)."'";
853 $sql .= ", ".($this->state_id > 0 ? ((int) $this->state_id) : "null");
854 $sql .= ", ".($this->country_id > 0 ? ((int) $this->country_id) : "null");
855 $sql .= ", '".$this->db->escape($this->ics)."'";
856 $sql .= ", '".$this->db->escape($this->ics_transfer)."'";
857 $sql .= ")";
858
859 dol_syslog(get_class($this)."::create", LOG_DEBUG);
860 $resql = $this->db->query($sql);
861 if ($resql) {
862 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."bank_account");
863
864 $result = $this->update($user, 1);
865 if ($result > 0) {
866 $accline = new AccountLine($this->db);
867 $accline->datec = $now;
868 $accline->label = '('.$langs->trans("InitialBankBalance").')';
869 $accline->amount = (float) price2num($balance);
870 $accline->fk_user_author = $user->id;
871 $accline->fk_account = $this->id;
872 $accline->datev = $this->date_solde;
873 $accline->dateo = $this->date_solde;
874 $accline->fk_type = 'SOLD';
875
876 if ($accline->insert() < 0) {
877 $error++;
878 $this->setErrorsFromObject($accline);
879 }
880
881 if (!$error) {
882 $result = $this->insertExtraFields();
883 if ($result < 0) {
884 $error++;
885 }
886 }
887
888 if (!$error && !$notrigger) {
889 // Call trigger
890 $result = $this->call_trigger('BANKACCOUNT_CREATE', $user);
891 if ($result < 0) {
892 $error++;
893 }
894 // End call triggers
895 }
896 } else {
897 $error++;
898 }
899 } else {
900 if ($this->db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
901 $this->error = $langs->trans("ErrorBankLabelAlreadyExists");
902 $error++;
903 } else {
904 $this->error = $this->db->error()." sql=".$sql;
905 $error++;
906 }
907 }
908
909 if (!$error) {
910 $this->db->commit();
911 return $this->id;
912 } else {
913 $this->db->rollback();
914 return -1 * $error;
915 }
916 }
917
925 public function update($user, $notrigger = 0)
926 {
927 global $langs, $conf;
928
929 if (empty($this->country_id) && !empty($this->country_code)) {
930 $country_id = getCountry($this->country_code, '3');
931 $this->country_id = is_int($country_id) ? $country_id : 0;
932 }
933
934 $error = 0;
935
936 $this->db->begin();
937
938 // Check parameters
939 if (empty($this->country_id)) {
940 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Country"));
941 dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
942 return -1;
943 }
944 if (empty($this->ref)) {
945 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Ref"));
946 dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
947 return -1;
948 }
949 if (!$this->label) {
950 $this->label = "???";
951 }
952
953 $sql = "UPDATE ".MAIN_DB_PREFIX."bank_account SET";
954 $sql .= " ref = '".$this->db->escape($this->ref)."'";
955 $sql .= ",label = '".$this->db->escape($this->label)."'";
956 $sql .= ",courant = ".((int) $this->type);
957 $sql .= ",clos = ".((int) $this->status);
958 $sql .= ",rappro = ".((int) $this->rappro);
959 $sql .= ",url = ".($this->url ? "'".$this->db->escape($this->url)."'" : "null");
960 $sql .= ",account_number = '".$this->db->escape($this->account_number)."'";
961 $sql .= ",fk_accountancy_journal = ".($this->fk_accountancy_journal > 0 ? ((int) $this->fk_accountancy_journal) : "null");
962 $sql .= ",bank = '".$this->db->escape($this->bank)."'";
963 $sql .= ",code_banque='".$this->db->escape($this->code_banque)."'";
964 $sql .= ",code_guichet='".$this->db->escape($this->code_guichet)."'";
965 $sql .= ",number='".$this->db->escape($this->number)."'";
966 $sql .= ",cle_rib='".$this->db->escape($this->cle_rib)."'";
967 $sql .= ",bic='".$this->db->escape($this->bic)."'";
968 $sql .= ",iban_prefix = '".$this->db->escape($this->iban)."'";
969 $sql .= ",domiciliation='".$this->db->escape($this->address)."'";
970 $sql .= ",pti_in_ctti=".((int) $this->pti_in_ctti);
971 $sql .= ",proprio = '".$this->db->escape($this->owner_name)."'";
972 $sql .= ",owner_address = '".$this->db->escape($this->owner_address)."'";
973 $sql .= ",owner_zip = '".$this->db->escape($this->owner_zip)."'";
974 $sql .= ",owner_town = '".$this->db->escape($this->owner_town)."'";
975 $sql .= ",owner_country_id = ".($this->owner_country_id > 0 ? ((int) $this->owner_country_id) : "null");
976
977 $sql .= ",currency_code = '".$this->db->escape($this->currency_code)."'";
978
979 $sql .= ",min_allowed = ".($this->min_allowed != '' ? price2num($this->min_allowed) : "null");
980 $sql .= ",min_desired = ".($this->min_desired != '' ? price2num($this->min_desired) : "null");
981 $sql .= ",comment = '".$this->db->escape($this->comment)."'";
982
983 $sql .= ",state_id = ".($this->state_id > 0 ? ((int) $this->state_id) : "null");
984 $sql .= ",fk_pays = ".($this->country_id > 0 ? ((int) $this->country_id) : "null");
985 $sql .= ",ics = '".$this->db->escape($this->ics)."'";
986 $sql .= ",ics_transfer = '".$this->db->escape($this->ics_transfer)."'";
987
988 $sql .= " WHERE rowid = ".((int) $this->id);
989
990 dol_syslog(get_class($this)."::update", LOG_DEBUG);
991 $result = $this->db->query($sql);
992 if ($result) {
993 // Actions on extra fields (by external module or standard code)
994 if (!$error) {
995 $result = $this->insertExtraFields();
996 if ($result < 0) {
997 $error++;
998 }
999 }
1000
1001 if (!$error && !empty($this->oldref) && $this->oldref !== $this->ref) {
1002 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'bank/".$this->db->escape($this->ref)."'";
1003 $sql .= " WHERE filepath = 'bank/".$this->db->escape($this->oldref)."' and src_object_type='bank_account' and entity = ".((int) $conf->entity);
1004 $resql = $this->db->query($sql);
1005 if (!$resql) {
1006 $error++;
1007 $this->error = $this->db->lasterror();
1008 }
1009
1010 // We rename directory in order not to lose the attachments
1011 $oldref = dol_sanitizeFileName($this->oldref);
1012 $newref = dol_sanitizeFileName($this->ref);
1013 $dirsource = $conf->bank->dir_output.'/'.$oldref;
1014 $dirdest = $conf->bank->dir_output.'/'.$newref;
1015 if (file_exists($dirsource)) {
1016 dol_syslog(get_class($this)."::update rename dir ".$dirsource." into ".$dirdest, LOG_DEBUG);
1017 if (@rename($dirsource, $dirdest)) {
1018 dol_syslog("Rename ok", LOG_DEBUG);
1019 }
1020 }
1021 }
1022
1023 if (!$error && !$notrigger) {
1024 // Call trigger
1025 $result = $this->call_trigger('BANKACCOUNT_MODIFY', $user);
1026 if ($result < 0) {
1027 $error++;
1028 }
1029 // End call triggers
1030 }
1031 } else {
1032 $error++;
1033 $this->error = $this->db->lasterror();
1034 dol_print_error($this->db);
1035 }
1036
1037 if (!$error) {
1038 $this->db->commit();
1039 return $this->id;
1040 } else {
1041 $this->db->rollback();
1042 return -1 * $error;
1043 }
1044 }
1045
1046
1047 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1054 public function update_bban($user = null)
1055 {
1056 // phpcs:enable
1057 global $conf, $langs;
1058
1059 // Load library to get BAN control function
1060 require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1061
1062 dol_syslog(get_class($this)."::update_bban $this->code_banque,$this->code_guichet,$this->number,$this->cle_rib,$this->iban");
1063
1064 // Check parameters
1065 if (!$this->ref) {
1066 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->trans("Ref"));
1067 return -2;
1068 }
1069
1070 $sql = "UPDATE ".MAIN_DB_PREFIX."bank_account SET";
1071 $sql .= " bank = '".$this->db->escape($this->bank)."'";
1072 $sql .= ",code_banque='".$this->db->escape($this->code_banque)."'";
1073 $sql .= ",code_guichet='".$this->db->escape($this->code_guichet)."'";
1074 $sql .= ",number='".$this->db->escape($this->number)."'";
1075 $sql .= ",cle_rib='".$this->db->escape($this->cle_rib)."'";
1076 $sql .= ",bic='".$this->db->escape($this->bic)."'";
1077 $sql .= ",iban_prefix = '".$this->db->escape($this->iban)."'";
1078 $sql .= ",domiciliation='".$this->db->escape($this->address)."'";
1079 $sql .= ",proprio = '".$this->db->escape($this->owner_name)."'";
1080 $sql .= ",owner_address = '".$this->db->escape($this->owner_address)."'";
1081 $sql .= ",owner_zip = '".$this->db->escape($this->owner_zip)."'";
1082 $sql .= ",owner_town = '".$this->db->escape($this->owner_town)."'";
1083 $sql .= ",owner_country_id = ".($this->owner_country_id > 0 ? ((int) $this->owner_country_id) : "null");
1084 $sql .= ",state_id = ".($this->state_id > 0 ? $this->state_id : "null");
1085 $sql .= ",fk_pays = ".($this->country_id > 0 ? $this->country_id : "null");
1086 $sql .= " WHERE rowid = ".((int) $this->id);
1087 $sql .= " AND entity = ".((int) $conf->entity);
1088
1089 dol_syslog(get_class($this)."::update_bban", LOG_DEBUG);
1090
1091 $result = $this->db->query($sql);
1092 if ($result) {
1093 return 1;
1094 } else {
1095 $this->error = $this->db->lasterror();
1096 dol_print_error($this->db);
1097 return -1;
1098 }
1099 }
1100
1101
1109 public function fetch($id, $ref = '')
1110 {
1111 if (empty($id) && empty($ref)) {
1112 $this->error = "ErrorBadParameters";
1113 return -1;
1114 }
1115
1116 $sql = "SELECT ba.rowid, ba.ref, ba.label, ba.bank, ba.number, ba.courant as type, ba.clos as status, ba.rappro, ba.url,";
1117 $sql .= " ba.code_banque, ba.code_guichet, ba.cle_rib, ba.bic, ba.iban_prefix as iban,";
1118 $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,";
1119 $sql .= " ba.account_number, ba.fk_accountancy_journal, ba.currency_code,";
1120 $sql .= " ba.min_allowed, ba.min_desired, ba.comment,";
1121 $sql .= " ba.datec as date_creation, ba.tms as date_modification, ba.ics, ba.ics_transfer,";
1122 $sql .= ' c.code as country_code, c.label as country,';
1123 $sql .= ' d.code_departement as state_code, d.nom as state,';
1124 $sql .= ' aj.code as accountancy_journal';
1125 $sql .= " FROM ".MAIN_DB_PREFIX."bank_account as ba";
1126 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_country as c ON ba.fk_pays = c.rowid';
1127 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_departements as d ON ba.state_id = d.rowid';
1128 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'accounting_journal as aj ON aj.rowid=ba.fk_accountancy_journal';
1129 $sql .= " WHERE ba.entity IN (".getEntity($this->element).")";
1130 if ($id) {
1131 $sql .= " AND ba.rowid = ".((int) $id);
1132 }
1133 if ($ref) {
1134 $sql .= " AND ba.ref = '".$this->db->escape($ref)."'";
1135 }
1136
1137 dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
1138 $result = $this->db->query($sql);
1139 if ($result) {
1140 if ($this->db->num_rows($result)) {
1141 $obj = $this->db->fetch_object($result);
1142
1143 $this->id = $obj->rowid;
1144 $this->rowid = $obj->rowid;
1145 $this->ref = $obj->ref;
1146 $this->label = $obj->label;
1147 $this->type = $obj->type;
1148 $this->courant = $obj->type;
1149 $this->bank = $obj->bank;
1150 $this->clos = $obj->status;
1151 $this->status = $obj->status;
1152 $this->rappro = $obj->rappro;
1153 $this->url = $obj->url;
1154
1155 $this->code_banque = $obj->code_banque;
1156 $this->code_guichet = $obj->code_guichet;
1157 $this->number = $obj->number;
1158 $this->cle_rib = $obj->cle_rib;
1159 $this->bic = $obj->bic;
1160 $this->iban = $obj->iban;
1161 $this->address = $obj->address;
1162
1163 $this->owner_name = $obj->owner_name;
1164 $this->proprio = $this->owner_name;
1165 $this->owner_address = $obj->owner_address;
1166 $this->owner_zip = $obj->owner_zip;
1167 $this->owner_town = $obj->owner_town;
1168 $this->owner_country_id = $obj->owner_country_id;
1169
1170 $this->pti_in_ctti = $obj->pti_in_ctti;
1171
1172 $this->state_id = $obj->state_id;
1173 $this->state_code = $obj->state_code;
1174 $this->state = $obj->state;
1175
1176 $this->country_id = $obj->country_id;
1177 $this->country_code = $obj->country_code;
1178 $this->country = $obj->country;
1179
1180 $this->account_number = $obj->account_number;
1181 $this->fk_accountancy_journal = $obj->fk_accountancy_journal;
1182 $this->accountancy_journal = $obj->accountancy_journal;
1183
1184 $this->currency_code = $obj->currency_code;
1185 $this->account_currency_code = $obj->currency_code;
1186 $this->min_allowed = $obj->min_allowed;
1187 $this->min_desired = $obj->min_desired;
1188 $this->comment = $obj->comment;
1189
1190 $this->date_creation = $this->db->jdate($obj->date_creation);
1191 $this->date_modification = $this->db->jdate($obj->date_modification);
1192
1193 $this->ics = $obj->ics;
1194 $this->ics_transfer = $obj->ics_transfer;
1195
1196 // Retrieve all extrafield
1197 // fetch optionals attributes and labels
1198 $this->fetch_optionals();
1199
1200 return 1;
1201 } else {
1202 return 0;
1203 }
1204 } else {
1205 $this->error = $this->db->lasterror();
1206 $this->errors[] = $this->error;
1207 return -1;
1208 }
1209 }
1210
1221 public function setCategories($categories)
1222 {
1223 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1224 return parent::setCategoriesCommon($categories, Categorie::TYPE_ACCOUNT);
1225 }
1226
1234 public function delete($user, $notrigger = 0)
1235 {
1236 $error = 0;
1237
1238 $this->db->begin();
1239
1240 // @TODO Check there is no child into llx_payment_various, ... to allow deletion ?
1241
1242 // Delete link between tag and bank account
1243 if (!$error) {
1244 $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_account";
1245 $sql .= " WHERE fk_account = ".((int) $this->id);
1246
1247 $resql = $this->db->query($sql);
1248 if (!$resql) {
1249 $error++;
1250 $this->error = "Error ".$this->db->lasterror();
1251 }
1252 }
1253
1254 if (!$error) {
1255 $sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element;
1256 $sql .= " WHERE rowid = ".((int) $this->id);
1257
1258 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1259 $result = $this->db->query($sql);
1260 if ($result) {
1261 // Remove extrafields
1262 if (!$error) {
1263 $result = $this->deleteExtraFields();
1264 if ($result < 0) {
1265 $error++;
1266 dol_syslog(get_class($this)."::delete error -4 ".$this->error, LOG_ERR);
1267 }
1268 }
1269 } else {
1270 $error++;
1271 $this->error = "Error ".$this->db->lasterror();
1272 }
1273 }
1274
1275 if (!$error) {
1276 $this->db->commit();
1277 return 1;
1278 } else {
1279 $this->db->rollback();
1280 return -1;
1281 }
1282 }
1283
1284
1291 public function getLibStatut($mode = 0)
1292 {
1293 return $this->LibStatut($this->status, $mode);
1294 }
1295
1296 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1304 public function LibStatut($status, $mode = 0)
1305 {
1306 // phpcs:enable
1307 global $langs;
1308 $langs->load('banks');
1309
1310 if ($status == self::STATUS_OPEN) {
1311 $label = $langs->transnoentitiesnoconv("StatusAccountOpened");
1312 $labelshort = $langs->transnoentitiesnoconv("StatusAccountOpened");
1313 $statusType = 'status4';
1314 } else {
1315 $label = $langs->transnoentitiesnoconv("StatusAccountClosed");
1316 $labelshort = $langs->transnoentitiesnoconv("StatusAccountClosed");
1317 $statusType = 'status5';
1318 }
1319
1320 return dolGetStatus($label, $labelshort, '', $statusType, $mode);
1321 }
1322
1323
1324 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1330 public function can_be_deleted()
1331 {
1332 // phpcs:enable
1333 $can_be_deleted = false;
1334
1335 $sql = "SELECT COUNT(rowid) as nb";
1336 $sql .= " FROM ".MAIN_DB_PREFIX."bank";
1337 $sql .= " WHERE fk_account = ".((int) $this->id);
1338
1339 $resql = $this->db->query($sql);
1340 if ($resql) {
1341 $obj = $this->db->fetch_object($resql);
1342 if ($obj->nb <= 1) {
1343 $can_be_deleted = true; // Juste le solde
1344 }
1345 } else {
1346 dol_print_error($this->db);
1347 }
1348 return $can_be_deleted;
1349 }
1350
1351
1357 public function error()
1358 {
1359 return $this->error;
1360 }
1361
1370 public function solde($option = 0, $date_end = '', $field = 'dateo')
1371 {
1372 $solde = 0;
1373
1374 $sql = "SELECT sum(amount) as amount";
1375 $sql .= " FROM ".MAIN_DB_PREFIX."bank";
1376 $sql .= " WHERE fk_account = ".((int) $this->id);
1377 if ($option == 1) {
1378 $sql .= " AND ".$this->db->escape($field)." <= '".(!empty($date_end) ? $this->db->idate($date_end) : $this->db->idate(dol_now()))."'";
1379 }
1380
1381 $resql = $this->db->query($sql);
1382 if ($resql) {
1383 if ($this->db->num_rows($resql)) {
1384 $obj = $this->db->fetch_object($resql);
1385 $solde = $obj->amount;
1386 }
1387 $this->db->free($resql);
1388 } else {
1389 $this->errors[] = $this->db->lasterror;
1390 return -1;
1391 }
1392
1393 return (float) price2num($solde, 'MU');
1394 }
1395
1396 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1404 public function load_board(User $user, $filteraccountid = 0)
1405 {
1406 // phpcs:enable
1407 global $conf, $langs;
1408
1409 if ($user->socid) {
1410 return -1; // protection pour eviter appel par utilisateur externe
1411 }
1412
1413 $sql = "SELECT b.rowid, b.datev as datefin";
1414 $sql .= " FROM ".MAIN_DB_PREFIX."bank as b,";
1415 $sql .= " ".MAIN_DB_PREFIX."bank_account as ba";
1416 $sql .= " WHERE b.rappro=0";
1417 $sql .= " AND b.fk_account = ba.rowid";
1418 $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
1419 $sql .= " AND (ba.rappro = 1 AND ba.courant != " . Account::TYPE_CASH . ")"; // Compte rapprochable
1420 $sql .= " AND clos = 0";
1421 if ($filteraccountid) {
1422 $sql .= " AND ba.rowid = ".((int) $filteraccountid);
1423 }
1424
1425 $resql = $this->db->query($sql);
1426 if ($resql) {
1427 $langs->load("banks");
1428 $now = dol_now();
1429
1430 require_once DOL_DOCUMENT_ROOT.'/core/class/workboardresponse.class.php';
1431
1432 $response = new WorkboardResponse();
1433 $response->warning_delay = $conf->bank->rappro->warning_delay / 60 / 60 / 24;
1434 $response->label = $langs->trans("TransactionsToConciliate");
1435 $response->labelShort = $langs->trans("TransactionsToConciliateShort");
1436 $response->url = DOL_URL_ROOT.'/compta/bank/list.php?leftmenu=bank&amp;mainmenu=bank';
1437 $response->img = img_object('', "payment");
1438
1439 while ($obj = $this->db->fetch_object($resql)) {
1440 $response->nbtodo++;
1441 if ($this->db->jdate($obj->datefin) < ($now - $conf->bank->rappro->warning_delay)) {
1442 $response->nbtodolate++;
1443 }
1444 }
1445
1446 return $response;
1447 } else {
1448 dol_print_error($this->db);
1449 $this->error = $this->db->error();
1450 return -1;
1451 }
1452 }
1453
1460 public function loadStateBoard($filteraccountid = 0)
1461 {
1462 global $user;
1463
1464 if ($user->socid) {
1465 return -1; // protection pour eviter appel par utilisateur externe
1466 }
1467
1468 $sql = "SELECT count(b.rowid) as nb";
1469 $sql .= " FROM ".MAIN_DB_PREFIX."bank as b,";
1470 $sql .= " ".MAIN_DB_PREFIX."bank_account as ba";
1471 $sql .= " WHERE b.fk_account = ba.rowid";
1472 $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
1473 $sql .= " AND (ba.rappro = 1 AND ba.courant != 2)"; // Compte rapprochable
1474 $sql .= " AND clos = 0";
1475 if ($filteraccountid) {
1476 $sql .= " AND ba.rowid = ".((int) $filteraccountid);
1477 }
1478
1479 $resql = $this->db->query($sql);
1480 if ($resql) {
1481 while ($obj = $this->db->fetch_object($resql)) {
1482 $this->nb["banklines"] = $obj->nb;
1483 }
1484 $this->db->free($resql);
1485 return 1;
1486 } else {
1487 dol_print_error($this->db);
1488 $this->error = $this->db->error();
1489 return -1;
1490 }
1491 }
1492
1493
1499 public function countAccountToReconcile()
1500 {
1501 global $user;
1502
1503 //Protection against external users
1504 if ($user->socid) {
1505 return 0;
1506 }
1507
1508 $nb = 0;
1509
1510 $sql = "SELECT COUNT(ba.rowid) as nb";
1511 $sql .= " FROM ".MAIN_DB_PREFIX."bank_account as ba";
1512 $sql .= " WHERE ba.rappro > 0 and ba.clos = 0";
1513 $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
1514 if (!getDolGlobalString('BANK_CAN_RECONCILIATE_CASHACCOUNT')) {
1515 $sql .= " AND ba.courant != " . Account::TYPE_CASH;
1516 }
1517
1518 $resql = $this->db->query($sql);
1519 if ($resql) {
1520 $obj = $this->db->fetch_object($resql);
1521 $nb = $obj->nb;
1522 } else {
1523 dol_print_error($this->db);
1524 }
1525
1526 return $nb;
1527 }
1528
1537 public function getTooltipContentArray($params)
1538 {
1539 global $langs;
1540 $langs->loadLangs(['banks', 'compta']);
1541 include_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1542
1543 $datas = array();
1544
1545 $nofetch = !empty($params['nofetch']);
1546 $pictos = img_picto('', $this->picto).' <u class="paddingrightnow">'.$langs->trans("BankAccount").'</u>';
1547 if (isset($this->status)) {
1548 $pictos .= ' '.$this->getLibStatut(5);
1549 }
1550 $datas['picto'] = $pictos;
1551 $datas['ref'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
1552 $datas['label'] = '<br><b>'.$langs->trans('Label').':</b> '.$this->label;
1553 $datas['accountnumber'] = '<br><br><b>'.$langs->trans('AccountNumber').':</b> '.$this->number;
1554 $datas['iban'] = '<br><b>'.$langs->trans('IBAN').':</b> '.getIbanHumanReadable($this);
1555 $datas['bic'] = '<br><b>'.$langs->trans('BIC').':</b> '.$this->bic;
1556 $datas['accountcurrency'] = '<br><br><b>'.$langs->trans("AccountCurrency").':</b> '.$this->currency_code;
1557
1558 if (isModEnabled('accounting')) {
1559 include_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
1560 $langs->load("accountancy");
1561 $datas['accountaccounting'] = '<br><b>'.$langs->trans('AccountAccounting').':</b> '.length_accountg($this->account_number);
1562 $datas['accountancyjournal'] = '<br><b>'.$langs->trans('AccountancyJournal').':</b> '.$this->accountancy_journal;
1563 }
1564 // show categories for this record only in ajax to not overload lists
1565 if (isModEnabled('category') && !$nofetch) {
1566 require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
1567 $form = new Form($this->db);
1568 $datas['categories'] = '<br>' . $form->showCategories($this->id, Categorie::TYPE_ACCOUNT, 1);
1569 }
1570
1571 return $datas;
1572 }
1573
1585 public function getNomUrl($withpicto = 0, $mode = '', $option = '', $save_lastsearch_value = -1, $notooltip = 0, $morecss = '')
1586 {
1587 global $conf, $langs;
1588
1589 if (!empty($conf->dol_no_mouse_hover)) {
1590 $notooltip = 1; // Force disable tooltips
1591 }
1592
1593 include_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1594
1595 $result = '';
1596 $classfortooltip = 'classfortooltip';
1597 $dataparams = '';
1598 $params = [
1599 'id' => $this->id,
1600 'objecttype' => $this->element,
1601 'option' => $option,
1602 'nofetch' => 1,
1603 ];
1604 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1605 $classfortooltip = 'classforajaxtooltip';
1606 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
1607 $label = '';
1608 } else {
1609 $label = implode($this->getTooltipContentArray($params));
1610 }
1611
1612 $url = DOL_URL_ROOT.'/compta/bank/card.php?id='.$this->id;
1613 if ($mode == 'transactions') {
1614 $url = DOL_URL_ROOT.'/compta/bank/bankentries_list.php?id='.$this->id;
1615 } elseif ($mode == 'receipts') {
1616 $url = DOL_URL_ROOT.'/compta/bank/releve.php?account='.$this->id;
1617 }
1618
1619 if ($option != 'nolink') {
1620 // Add param to save lastsearch_values or not
1621 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1622 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1623 $add_save_lastsearch_values = 1;
1624 }
1625 if ($add_save_lastsearch_values) {
1626 $url .= '&save_lastsearch_values=1';
1627 }
1628 }
1629
1630 $linkclose = '';
1631 if (empty($notooltip)) {
1632 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1633 $label = $langs->trans("BankAccount");
1634 $linkclose .= ' alt="'.dolPrintHTMLForAttribute($label).'"';
1635 }
1636 $linkclose .= ($label ? ' title="'.dolPrintHTMLForAttribute($label).'"' : ' title="tocomplete"');
1637 $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
1638 } else {
1639 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1640 }
1641
1642 if ($option == 'nolink' || empty($url)) {
1643 $linkstart = '<span';
1644 } else {
1645 $linkstart = '<a href="'.$url.'"';
1646 }
1647 $linkstart .= $linkclose.'>';
1648 if ($option == 'nolink' || empty($url)) {
1649 $linkend = '</span>';
1650 } else {
1651 $linkend = '</a>';
1652 }
1653
1654 $result .= $linkstart;
1655
1656 if ($withpicto) {
1657 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"'), 0, 0, $notooltip ? 0 : 1);
1658 }
1659 if ($withpicto != 2) {
1660 $result .= $this->ref.($option == 'reflabel' && $this->label ? ' - '.$this->label : '');
1661 }
1662 $result .= $linkend;
1663
1664 return $result;
1665 }
1666
1667
1668 // Method after here are common to Account and CompanyBankAccount
1669
1670
1676 public function verif()
1677 {
1678 require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1679
1680 $error = 0;
1681
1682 // Call functions to check BAN
1683 if (!checkIbanForAccount($this)) {
1684 $error++;
1685 $this->error = 'IBANNotValid';
1686 }
1687 // Call function to check Swift/BIC.
1688 // A non valid BIC/Swift is a problem if: it is not empty or always a problem if WITHDRAWAL_WITHOUT_BIC is not set).
1689 if (!checkSwiftForAccount($this) && (!empty($this->bic) || !getDolGlobalInt('WITHDRAWAL_WITHOUT_BIC'))) {
1690 $error++;
1691 $this->error = 'SwiftNotValid';
1692 }
1693
1694 if (! $error) {
1695 return 1;
1696 } else {
1697 return 0;
1698 }
1699 }
1700
1706 public function getCountryCode()
1707 {
1708 global $mysoc;
1709
1710 // We return country code of bank account
1711 if (!empty($this->country_code)) {
1712 return $this->country_code;
1713 }
1714
1715 // For backward compatibility, we try to guess country from other information
1716 if (!empty($this->iban)) {
1717 // If IBAN defined, we can know country of account from it
1718 $reg = array();
1719 if (preg_match("/^([a-zA-Z][a-zA-Z])/i", $this->iban, $reg)) {
1720 return $reg[1];
1721 }
1722 }
1723
1724 // If this class is linked to a third party
1725 if (!empty($this->socid)) {
1726 require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
1727 $company = new Societe($this->db);
1728 $result = $company->fetch($this->socid);
1729 if (!empty($company->country_code)) {
1730 return $company->country_code;
1731 }
1732 }
1733
1734 // We return country code of managed company
1735 if (!empty($mysoc->country_code)) {
1736 return $mysoc->country_code;
1737 }
1738
1739 return '';
1740 }
1741
1749 public function getBannerAddress($htmlkey, $object)
1750 {
1751 global $conf, $langs;
1752
1753 $out = '';
1754
1755 $outdone = 0;
1756 $coords = $this->getFullAddress(1, ', ', getDolGlobalInt('MAIN_SHOW_REGION_IN_STATE_SELECT'));
1757 if ($coords) {
1758 if (!empty($conf->use_javascript_ajax)) {
1759 // hideonsmatphone because copyToClipboard call jquery dialog that does not work with jmobile
1760 $out .= '<a href="#" class="hideonsmartphone" onclick="return copyToClipboard(\''.dol_escape_js($coords).'\',\''.dol_escape_js($langs->trans("HelpCopyToClipboard")).'\');">';
1761 $out .= img_picto($langs->trans("Address"), 'map-marker-alt');
1762 $out .= '</a> ';
1763 }
1764 $address = dol_print_address($coords, 'address_'.$htmlkey.'_'.$this->id, $this->element, $this->id, 1, ', ');
1765 if ($address) {
1766 $out .= $address;
1767 $outdone++;
1768 }
1769 $outdone++;
1770 }
1771
1772 return $out;
1773 }
1774
1775
1784 public function useDetailedBBAN()
1785 {
1786 $country_code = $this->getCountryCode();
1787
1788 if (in_array($country_code, array('FR', 'ES', 'GA', 'IT', 'NC'))) {
1789 return 1; // France, Spain, Gabon, ... - Not valid for CH
1790 }
1791 if (in_array($country_code, array('AD', 'AU', 'BE', 'CA', 'DE', 'DK', 'GR', 'GB', 'ID', 'IE', 'IR', 'KR', 'NL', 'NZ', 'UK', 'US'))) {
1792 return 2; // Australia, England...
1793 }
1794 return 0;
1795 }
1796
1802 public function needIBAN()
1803 {
1804 global $conf;
1805
1806 if (getDolGlobalString('MAIN_IBAN_IS_NEVER_MANDATORY')) {
1807 return 0;
1808 }
1809
1810 $country_code = $this->getCountryCode();
1811
1812 $country_code_in_EEC = array(
1813 'AT', // Austria
1814 'BE', // Belgium
1815 'BG', // Bulgaria
1816 'CY', // Cyprus
1817 'CZ', // Czech republic
1818 'DE', // Germany
1819 'DK', // Danemark
1820 'EE', // Estonia
1821 'ES', // Spain
1822 'FI', // Finland
1823 'FR', // France
1824 'GB', // United Kingdom
1825 'GR', // Greece
1826 'HR', // Croatia
1827 'NL', // Holland
1828 'HU', // Hungary
1829 'IE', // Ireland
1830 'IM', // Isle of Man - Included in UK
1831 'IT', // Italy
1832 'LT', // Lithuania
1833 'LU', // Luxembourg
1834 'LV', // Latvia
1835 'MC', // Monaco - Included in France
1836 'MT', // Malta
1837 //'NO', // Norway
1838 'PL', // Poland
1839 'PT', // Portugal
1840 'RO', // Romania
1841 'SE', // Sweden
1842 'SK', // Slovakia
1843 'SI', // Slovenia
1844 'UK', // United Kingdom
1845 //'CH', // Switzerland - No. Swizerland in not in EEC
1846 );
1847
1848 if (in_array($country_code, $country_code_in_EEC)) {
1849 return 1; // France, Spain, ...
1850 }
1851 return 0;
1852 }
1853
1859 public function needBIC()
1860 {
1861 if (getDolGlobalString('MAIN_IBAN_IS_NEVER_MANDATORY')) {
1862 return 0;
1863 }
1864
1865 $country_code = $this->getCountryCode();
1866
1867 $country_code_in_EEC = array(
1868 'AD', // Andorra
1869 'BH', // Bahrein
1870 'DK', // Denmark
1871 'FR', // France
1872 'GH', // Ghana
1873 'HU', // Hungary
1874 'JP', // Japan
1875 'LV', // Latvia
1876 'SE', // Sweden
1877 );
1878
1879 if (in_array($country_code, $country_code_in_EEC)) {
1880 return 1; // Andorra, Bahrein, ...
1881 }
1882 return 0;
1883 }
1884
1891 public function info($id)
1892 {
1893 }
1894
1909 public function getFieldsToShow($includeibanbic = 0)
1910 {
1911 //Get the required properties depending on the country
1912 $detailedBBAN = $this->useDetailedBBAN();
1913
1914 if ($detailedBBAN == 0) {
1915 $fieldarray = array(
1916 'BankAccountNumber'
1917 );
1918 } elseif ($detailedBBAN == 2) {
1919 $fieldarray = array(
1920 'BankCode',
1921 'BankAccountNumber'
1922 );
1923 } else {
1924 $fieldarray = self::getAccountNumberOrder();
1925 }
1926
1927 //if ($this->needIBAN()) { // return always IBAN and BIC (this was old behaviour)
1928 if ($includeibanbic) {
1929 $fieldarray[] = 'IBAN';
1930 $fieldarray[] = 'BIC';
1931 }
1932 //}
1933
1934 //Get the order the properties are shown
1935 return $fieldarray;
1936 }
1937
1948 public static function getAccountNumberOrder()
1949 {
1950 global $conf;
1951
1952 $fieldlists = array(
1953 'BankCode',
1954 'DeskCode',
1955 'BankAccountNumber',
1956 'BankAccountNumberKey'
1957 );
1958
1959 if (getDolGlobalString('BANK_SHOW_ORDER_OPTION')) {
1960 if (is_numeric(getDolGlobalString('BANK_SHOW_ORDER_OPTION'))) {
1961 if (getDolGlobalString('BANK_SHOW_ORDER_OPTION') == '1') {
1962 $fieldlists = array(
1963 'BankCode',
1964 'DeskCode',
1965 'BankAccountNumberKey',
1966 'BankAccountNumber'
1967 );
1968 }
1969 } else {
1970 //Replace the old AccountNumber key with the new BankAccountNumber key
1971 $fieldlists = explode(
1972 ' ',
1973 preg_replace('/ ?[^Bank]AccountNumber ?/', 'BankAccountNumber', $conf->global->BANK_SHOW_ORDER_OPTION)
1974 );
1975 }
1976 }
1977
1978 return $fieldlists;
1979 }
1980
1981
1989 public function initAsSpecimen()
1990 {
1991 // Example of IBAN FR7630001007941234567890185
1992 $this->specimen = 1;
1993 $this->ref = 'MBA';
1994 $this->label = 'My Big Company Bank account';
1995 $this->courant = Account::TYPE_CURRENT;
1996 $this->clos = Account::STATUS_OPEN;
1997 $this->type = Account::TYPE_CURRENT;
1998 $this->status = Account::STATUS_OPEN;
1999 $this->code_banque = '30001';
2000 $this->code_guichet = '00794';
2001 $this->number = '12345678901';
2002 $this->cle_rib = '85';
2003 $this->bic = 'AA12';
2004 $this->iban = 'FR7630001007941234567890185';
2005
2006 $this->bank = 'MyBank';
2007 $this->address = 'Rue de Paris';
2008 $this->owner_name = 'Owner';
2009 $this->owner_address = 'Owner address';
2010 $this->owner_zip = 'Owner zip';
2011 $this->owner_town = 'Owner town';
2012 $this->owner_country_id = 1;
2013 $this->country_id = 1;
2014
2015 return 1;
2016 }
2017
2026 public static function replaceThirdparty($dbs, $origin_id, $dest_id)
2027 {
2028 $sql = "UPDATE ".MAIN_DB_PREFIX."bank_url SET url_id = ".((int) $dest_id)." WHERE url_id = ".((int) $origin_id)." AND type='company'";
2029
2030 if ($dbs->query($sql)) {
2031 return true;
2032 } else {
2033 //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.
2034 //$this->errors = $dbs->lasterror();
2035 return false;
2036 }
2037 }
2038
2046 public function getKanbanView($option = '', $arraydata = null)
2047 {
2048 global $langs;
2049
2050 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
2051
2052 $return = '<div class="box-flex-item box-flex-grow-zero">';
2053 $return .= '<div class="info-box info-box-sm">';
2054 $return .= '<span class="info-box-icon bg-infobox-action">';
2055 $return .= img_picto('', $this->picto);
2056 $return .= '</span>';
2057 $return .= '<div class="info-box-content">';
2058 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).'</span>';
2059 if ($selected >= 0) {
2060 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
2061 }
2062 if (property_exists($this, 'type_lib')) {
2063 $return .= '<br><span class="info-box-label opacitymedium" title="'.$this->type_lib[$this->type].'">'.substr($this->type_lib[$this->type], 0, 24).'...</span>';
2064 }
2065 if (method_exists($this, 'solde')) {
2066 $return .= '<br><a href="'.DOL_URL_ROOT.'/compta/bank/bankentries_list.php?id='.$this->id.'">';
2067 $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>';
2068 }
2069 if (method_exists($this, 'getLibStatut')) {
2070 $return .= '<br><div class="info-box-status">'.$this->getLibStatut(3).'</div>';
2071 }
2072 $return .= '</div>';
2073 $return .= '</div>';
2074 $return .= '</div>';
2075 return $return;
2076 }
2077}
2078
2079
2080require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
2081
2085class AccountLine extends CommonObjectLine
2086{
2090 public $db;
2091
2095 public $element = 'bank';
2096
2100 public $table_element = 'bank';
2101
2105 public $picto = 'accountline';
2106
2110 public $id;
2111
2115 public $ref;
2116
2122 public $datec;
2123
2129 public $dateo;
2130
2136 public $datev;
2137
2141 public $amount;
2142
2146 public $amount_main_currency;
2147
2151 public $fk_user_author;
2152
2156 public $fk_user_rappro;
2157
2161 public $fk_type;
2162
2166 public $fk_bordereau;
2167
2171 public $fk_account;
2172
2176 public $bank_account_ref;
2177
2181 public $bank_account_label;
2182
2186 public $numero_compte;
2187
2191 public $emetteur;
2192
2196 public $rappro;
2197
2201 public $num_releve;
2202
2206 public $num_chq;
2207
2211 public $bank_chq;
2212
2216 public $label;
2217
2221 public $note;
2222
2228 public $user_rappro;
2229
2230
2236 public function __construct(DoliDB $db)
2237 {
2238 $this->db = $db;
2239 }
2240
2249 public function fetch($rowid, $ref = '', $num = '')
2250 {
2251 // Check parameters
2252 if (empty($rowid) && empty($ref) && empty($num)) {
2253 return -1;
2254 }
2255
2256 $sql = "SELECT b.rowid, b.datec, b.datev, b.dateo, b.amount, b.label as label, b.fk_account,";
2257 $sql .= " b.fk_user_author, b.fk_user_rappro,";
2258 $sql .= " b.fk_type, b.num_releve, b.num_chq, b.rappro, b.note,";
2259 $sql .= " b.fk_bordereau, b.banque, b.emetteur,";
2260 $sql .= " ba.ref as bank_account_ref, ba.label as bank_account_label";
2261 $sql .= " FROM ".MAIN_DB_PREFIX."bank as b,";
2262 $sql .= " ".MAIN_DB_PREFIX."bank_account as ba";
2263 $sql .= " WHERE b.fk_account = ba.rowid";
2264 $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
2265 if ($num) {
2266 $sql .= " AND b.num_chq = '".$this->db->escape($num)."'";
2267 } elseif ($ref) {
2268 $sql .= " AND b.rowid = '".$this->db->escape($ref)."'";
2269 } else {
2270 $sql .= " AND b.rowid = ".((int) $rowid);
2271 }
2272
2273 dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
2274 $result = $this->db->query($sql);
2275 if ($result) {
2276 $ret = 0;
2277
2278 $obj = $this->db->fetch_object($result);
2279 if ($obj) {
2280 $this->id = $obj->rowid;
2281 $this->rowid = $obj->rowid;
2282 $this->ref = $obj->rowid;
2283
2284 $this->datec = $this->db->jdate($obj->datec);
2285 $this->datev = $this->db->jdate($obj->datev);
2286 $this->dateo = $this->db->jdate($obj->dateo);
2287 $this->amount = $obj->amount;
2288 $this->label = $obj->label;
2289 $this->note = $obj->note;
2290
2291 $this->fk_user_author = $obj->fk_user_author;
2292 $this->fk_user_rappro = $obj->fk_user_rappro;
2293
2294 $this->fk_type = $obj->fk_type; // Type of transaction
2295 $this->rappro = (int) $obj->rappro;
2296 $this->num_releve = $obj->num_releve;
2297
2298 $this->num_chq = $obj->num_chq;
2299 $this->bank_chq = $obj->banque;
2300 $this->fk_bordereau = $obj->fk_bordereau;
2301
2302 $this->fk_account = $obj->fk_account;
2303 $this->bank_account_ref = $obj->bank_account_ref;
2304 $this->bank_account_label = $obj->bank_account_label;
2305
2306 // Retrieve all extrafield
2307 // fetch optionals attributes and labels
2308 $this->fetch_optionals();
2309
2310 $ret = 1;
2311 }
2312 $this->db->free($result);
2313 return $ret;
2314 } else {
2315 return -1;
2316 }
2317 }
2318
2324 public function insert()
2325 {
2326 $error = 0;
2327
2328 $this->db->begin();
2329
2330 $sql = "INSERT INTO ".MAIN_DB_PREFIX."bank (";
2331 $sql .= "datec";
2332 $sql .= ", dateo";
2333 $sql .= ", datev";
2334 $sql .= ", label";
2335 $sql .= ", amount";
2336 $sql .= ", amount_main_currency";
2337 $sql .= ", fk_user_author";
2338 $sql .= ", num_chq";
2339 $sql .= ", fk_account";
2340 $sql .= ", fk_type";
2341 $sql .= ", emetteur,banque";
2342 $sql .= ", rappro";
2343 $sql .= ", numero_compte";
2344 $sql .= ", num_releve";
2345 $sql .= ", note";
2346 $sql .= ") VALUES (";
2347 $sql .= "'".$this->db->idate($this->datec)."'";
2348 $sql .= ", '".$this->db->idate($this->dateo)."'";
2349 $sql .= ", '".$this->db->idate($this->datev)."'";
2350 $sql .= ", '".$this->db->escape($this->label)."'";
2351 $sql .= ", ".price2num($this->amount);
2352 $sql .= ", ".(empty($this->amount_main_currency) ? "NULL" : price2num($this->amount_main_currency));
2353 $sql .= ", ".($this->fk_user_author > 0 ? ((int) $this->fk_user_author) : "null");
2354 $sql .= ", ".($this->num_chq ? "'".$this->db->escape($this->num_chq)."'" : "null");
2355 $sql .= ", '".$this->db->escape((string) $this->fk_account)."'";
2356 $sql .= ", '".$this->db->escape($this->fk_type)."'";
2357 $sql .= ", ".($this->emetteur ? "'".$this->db->escape($this->emetteur)."'" : "null");
2358 $sql .= ", ".($this->bank_chq ? "'".$this->db->escape($this->bank_chq)."'" : "null");
2359 $sql .= ", ".(int) $this->rappro;
2360 $sql .= ", ".($this->numero_compte ? "'".$this->db->escape($this->numero_compte)."'" : "''");
2361 $sql .= ", ".($this->num_releve ? "'".$this->db->escape($this->num_releve)."'" : "null");
2362 $sql .= ", ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "null");
2363 $sql .= ")";
2364
2365
2366 dol_syslog(get_class($this)."::insert", LOG_DEBUG);
2367 $resql = $this->db->query($sql);
2368 if ($resql) {
2369 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'bank');
2370 // Actions on extra fields (by external module or standard code)
2371 $result = $this->insertExtraFields();
2372 if ($result < 0) {
2373 $error++;
2374 }
2375 } else {
2376 $error++;
2377 $this->error = $this->db->lasterror();
2378 dol_print_error($this->db);
2379 }
2380
2381 if (!$error) {
2382 $this->db->commit();
2383 return $this->id;
2384 } else {
2385 $this->db->rollback();
2386 return -1 * $error;
2387 }
2388 }
2389
2397 public function delete($user, $notrigger = 0)
2398 {
2399 $nbko = 0;
2400
2401 if ($this->rappro) {
2402 // Protection to avoid any delete of consolidated lines
2403 $this->error = "ErrorDeleteNotPossibleLineIsConsolidated";
2404 return -1;
2405 }
2406
2407 $this->db->begin();
2408
2409 if (!$notrigger) {
2410 // Call trigger
2411 $result = $this->call_trigger('BANKACCOUNTLINE_DELETE', $user);
2412 if ($result < 0) {
2413 $this->db->rollback();
2414 return -1;
2415 }
2416 // End call triggers
2417 }
2418
2419 // Protection to avoid any delete of accounted lines. Protection on by default
2420 if (!getDolGlobalString('BANK_ALLOW_TRANSACTION_DELETION_EVEN_IF_IN_ACCOUNTING')) {
2421 $sql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."accounting_bookkeeping WHERE doc_type = 'bank' AND fk_doc = ".((int) $this->id);
2422 $resql = $this->db->query($sql);
2423 if ($resql) {
2424 $obj = $this->db->fetch_object($resql);
2425 if ($obj && $obj->nb) {
2426 $this->error = 'ErrorRecordAlreadyInAccountingDeletionNotPossible';
2427 $this->db->rollback();
2428 return -1;
2429 }
2430 } else {
2431 $this->error = $this->db->lasterror();
2432 $this->db->rollback();
2433 return -1;
2434 }
2435 }
2436
2437 // Delete urls
2438 $result = $this->delete_urls($user);
2439 if ($result < 0) {
2440 $nbko++;
2441 }
2442
2443 $sql = "DELETE FROM ".MAIN_DB_PREFIX."category_bankline WHERE lineid=".(int) $this->rowid;
2444 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
2445 $result = $this->db->query($sql);
2446 if (!$result) {
2447 $nbko++;
2448 }
2449
2450 $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank_extrafields WHERE fk_object=".(int) $this->rowid;
2451 $result = $this->db->query($sql);
2452 if (!$result) {
2453 $nbko++;
2454 }
2455
2456 $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank WHERE rowid=".(int) $this->rowid;
2457 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
2458 $result = $this->db->query($sql);
2459 if (!$result) {
2460 $nbko++;
2461 }
2462
2463 if (!$nbko) {
2464 $this->db->commit();
2465 return 1;
2466 } else {
2467 $this->db->rollback();
2468 return -$nbko;
2469 }
2470 }
2471
2472
2473 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2480 public function delete_urls($user = null)
2481 {
2482 // phpcs:enable
2483 $nbko = 0;
2484
2485 if ($this->rappro) {
2486 // Protection to avoid any delete of consolidated lines
2487 $this->error = "ErrorDeleteNotPossibleLineIsConsolidated";
2488 return -1;
2489 }
2490
2491 $this->db->begin();
2492
2493 $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank_url WHERE fk_bank=".(int) $this->rowid;
2494 dol_syslog(get_class($this)."::delete_urls", LOG_DEBUG);
2495 $result = $this->db->query($sql);
2496 if (!$result) {
2497 $nbko++;
2498 }
2499
2500 if (!$nbko) {
2501 $this->db->commit();
2502 return 1;
2503 } else {
2504 $this->db->rollback();
2505 return -$nbko;
2506 }
2507 }
2508
2509
2517 public function update(User $user, $notrigger = 0)
2518 {
2519 $this->db->begin();
2520
2521 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2522 $sql .= " amount = ".price2num($this->amount).",";
2523 $sql .= " datev='".$this->db->idate($this->datev)."',";
2524 $sql .= " dateo='".$this->db->idate($this->dateo)."'";
2525 $sql .= " WHERE rowid = ".((int) $this->rowid);
2526
2527 dol_syslog(get_class($this)."::update", LOG_DEBUG);
2528 $resql = $this->db->query($sql);
2529 if ($resql) {
2530 $this->db->commit();
2531 return 1;
2532 } else {
2533 $this->db->rollback();
2534 $this->error = $this->db->error();
2535 return -1;
2536 }
2537 }
2538
2539
2545 public function updateLabel()
2546 {
2547 $this->db->begin();
2548
2549 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2550 $sql .= " label = '".$this->db->escape($this->label)."'";
2551 $sql .= " WHERE rowid = ".((int) $this->rowid);
2552
2553 dol_syslog(get_class($this)."::update_label", LOG_DEBUG);
2554 $resql = $this->db->query($sql);
2555 if ($resql) {
2556 $this->db->commit();
2557 return 1;
2558 } else {
2559 $this->db->rollback();
2560 $this->error = $this->db->error();
2561 return -1;
2562 }
2563 }
2564
2565
2566 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2575 public function update_conciliation(User $user, $cat, $conciliated = 1)
2576 {
2577 // phpcs:enable
2578 global $conf, $langs;
2579
2580 $this->db->begin();
2581
2582 // Check statement field
2583 if (getDolGlobalString('BANK_STATEMENT_REGEX_RULE')) {
2584 if (!preg_match('/' . getDolGlobalString('BANK_STATEMENT_REGEX_RULE').'/', $this->num_releve)) {
2585 $this->errors[] = $langs->trans("ErrorBankStatementNameMustFollowRegex", getDolGlobalString('BANK_STATEMENT_REGEX_RULE'));
2586 return -1;
2587 }
2588 }
2589
2590 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2591 $sql .= " rappro = ".((int) $conciliated);
2592 $sql .= ", num_releve = '".$this->db->escape($this->num_releve)."'";
2593 if ($conciliated) {
2594 $sql .= ", fk_user_rappro = ".((int) $user->id);
2595 }
2596 $sql .= " WHERE rowid = ".((int) $this->id);
2597
2598 dol_syslog(get_class($this)."::update_conciliation", LOG_DEBUG);
2599 $resql = $this->db->query($sql);
2600 if ($resql) {
2601 if (!empty($cat) && $cat > 0) {
2602 $sql = "INSERT INTO ".MAIN_DB_PREFIX."category_bankline (";
2603 $sql .= "lineid";
2604 $sql .= ", fk_categ";
2605 $sql .= ") VALUES (";
2606 $sql .= $this->id;
2607 $sql .= ", ".((int) $cat);
2608 $sql .= ")";
2609
2610 dol_syslog(get_class($this)."::update_conciliation", LOG_DEBUG);
2611 $this->db->query($sql);
2612
2613 // No error check. Can fail if category already affected
2614 // TODO Do no try the insert if link already exists
2615 }
2616
2617 $this->rappro = (int) $conciliated;
2618
2619 $this->db->commit();
2620 return 1;
2621 } else {
2622 $this->db->rollback();
2623 return -1;
2624 }
2625 }
2626
2627
2628 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2636 public function datev_change($rowid, $sign = 1)
2637 {
2638 // phpcs:enable
2639 $sql = "SELECT datev FROM ".MAIN_DB_PREFIX."bank WHERE rowid = ".((int) $rowid);
2640 $resql = $this->db->query($sql);
2641 if ($resql) {
2642 $obj = $this->db->fetch_object($resql);
2643 $newdate = $this->db->jdate($obj->datev) + (3600 * 24 * $sign);
2644
2645 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2646 $sql .= " datev = '".$this->db->idate($newdate)."'";
2647 $sql .= " WHERE rowid = ".((int) $rowid);
2648
2649 $result = $this->db->query($sql);
2650 if ($result) {
2651 if ($this->db->affected_rows($result)) {
2652 return 1;
2653 }
2654 } else {
2655 dol_print_error($this->db);
2656 return 0;
2657 }
2658 } else {
2659 dol_print_error($this->db);
2660 }
2661 return 0;
2662 }
2663
2664 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2671 public function datev_next($id)
2672 {
2673 // phpcs:enable
2674 return $this->datev_change($id, 1);
2675 }
2676
2677 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2684 public function datev_previous($id)
2685 {
2686 // phpcs:enable
2687 return $this->datev_change($id, -1);
2688 }
2689
2690
2691 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2699 public function dateo_change($rowid, $sign = 1)
2700 {
2701 // phpcs:enable
2702 $sql = "SELECT dateo FROM ".MAIN_DB_PREFIX."bank WHERE rowid = ".((int) $rowid);
2703 $resql = $this->db->query($sql);
2704 if ($resql) {
2705 $obj = $this->db->fetch_object($resql);
2706 $newdate = $this->db->jdate($obj->dateo) + (3600 * 24 * $sign);
2707
2708 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2709 $sql .= " dateo = '".$this->db->idate($newdate)."'";
2710 $sql .= " WHERE rowid = ".((int) $rowid);
2711
2712 $result = $this->db->query($sql);
2713 if ($result) {
2714 if ($this->db->affected_rows($result)) {
2715 return 1;
2716 }
2717 } else {
2718 dol_print_error($this->db);
2719 return 0;
2720 }
2721 } else {
2722 dol_print_error($this->db);
2723 }
2724 return 0;
2725 }
2726
2727 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2734 public function dateo_next($id)
2735 {
2736 // phpcs:enable
2737 return $this->dateo_change($id, 1);
2738 }
2739
2740 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2747 public function dateo_previous($id)
2748 {
2749 // phpcs:enable
2750 return $this->dateo_change($id, -1);
2751 }
2752
2753
2760 public function info($id)
2761 {
2762 $sql = 'SELECT b.rowid, b.datec, b.tms as datem,';
2763 $sql .= ' b.fk_user_author, b.fk_user_rappro';
2764 $sql .= ' FROM '.MAIN_DB_PREFIX.'bank as b';
2765 $sql .= ' WHERE b.rowid = '.((int) $id);
2766
2767 $result = $this->db->query($sql);
2768 if ($result) {
2769 if ($this->db->num_rows($result)) {
2770 $obj = $this->db->fetch_object($result);
2771
2772 $this->id = $obj->rowid;
2773
2774 $this->user_creation_id = $obj->fk_user_author;
2775 $this->user_rappro = $obj->fk_user_rappro;
2776 $this->date_creation = $this->db->jdate($obj->datec);
2777 $this->date_modification = $this->db->jdate($obj->datem);
2778 //$this->date_rappro = $obj->daterappro; // Not yet managed
2779 }
2780 $this->db->free($result);
2781 } else {
2782 dol_print_error($this->db);
2783 }
2784 }
2785
2786
2796 public function getNomUrl($withpicto = 0, $maxlen = 0, $option = '', $notooltip = 0)
2797 {
2798 global $conf, $langs;
2799
2800 $result = '';
2801
2802 $label = img_picto('', $this->picto).' <u>'.$langs->trans("BankTransactionLine").'</u>:<br>';
2803 $label .= '<b>'.$langs->trans("Ref").':</b> '.$this->ref;
2804 if ($this->amount) {
2805 $label .= '<br><strong>'.$langs->trans("Amount").':</strong> '.price($this->amount, 0, $langs, 1, -1, -1, $conf->currency);
2806 }
2807
2808 $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">';
2809 $linkend = '</a>';
2810
2811 $result .= $linkstart;
2812 if ($withpicto) {
2813 $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);
2814 }
2815 if ($withpicto != 2) {
2816 $result .= ($this->ref ? $this->ref : $this->id);
2817 }
2818
2819 $result .= $linkend;
2820
2821 if ($option == 'showall' || $option == 'showconciliated' || $option == 'showconciliatedandaccounted') {
2822 $result .= ' <span class="opacitymedium">(';
2823 }
2824 if ($option == 'showall') {
2825 $result .= $langs->trans("BankAccount").': ';
2826 $accountstatic = new Account($this->db);
2827 $accountstatic->id = $this->fk_account;
2828 $accountstatic->ref = $this->bank_account_ref;
2829 $accountstatic->label = $this->bank_account_label;
2830 $result .= $accountstatic->getNomUrl(0).', ';
2831 }
2832 if ($option == 'showall' || $option == 'showconciliated' || $option == 'showconciliatedandaccounted') {
2833 $result .= $langs->trans("BankLineConciliated").': ';
2834 $result .= yn($this->rappro);
2835 }
2836 if (isModEnabled('accounting') && ($option == 'showall' || $option == 'showconciliatedandaccounted')) {
2837 $sql = "SELECT COUNT(rowid) as nb, MAX(piece_num) as banktransactionid FROM ".MAIN_DB_PREFIX."accounting_bookkeeping";
2838 $sql .= " WHERE doc_type = 'bank' AND fk_doc = ".((int) $this->id);
2839 $resql = $this->db->query($sql);
2840 if ($resql) {
2841 $obj = $this->db->fetch_object($resql);
2842 if ($obj && $obj->nb) {
2843 $result .= ' - '.$langs->trans("Accounted").': <span title="'.$langs->trans("TransactionNumShort").' '.$obj->banktransactionid.'">'.yn(1).'</span>';
2844 } else {
2845 $result .= ' - '.$langs->trans("Accounted").': '.yn(0);
2846 }
2847 }
2848 }
2849 if ($option == 'showall' || $option == 'showconciliated' || $option == 'showconciliatedandaccounted') {
2850 $result .= ')</span>';
2851 }
2852
2853 return $result;
2854 }
2855
2856
2863 public function getLibStatut($mode = 0)
2864 {
2865 return $this->LibStatut($this->status, $mode);
2866 }
2867
2868 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2876 public function LibStatut($status, $mode = 0)
2877 {
2878 // phpcs:enable
2879 return '';
2880 }
2881
2888 public function getVentilExportCompta($mode = 0)
2889 {
2890 $alreadydispatched = 0;
2891
2892 $type = 'bank';
2893
2894 $sql = " SELECT ".($mode ? 'DISTINCT piece_num' : 'COUNT(ab.rowid)')." as nb";
2895 $sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab WHERE ab.doc_type = '".$this->db->escape($type)."' AND ab.fk_doc = ".((int) $this->id);
2896 $resql = $this->db->query($sql);
2897 if ($resql) {
2898 $obj = $this->db->fetch_object($resql);
2899 if ($obj) {
2900 $alreadydispatched = $obj->nb;
2901 }
2902 } else {
2903 $this->error = $this->db->lasterror();
2904 return -1;
2905 }
2906
2907 if ($alreadydispatched) {
2908 return $alreadydispatched;
2909 }
2910 return 0;
2911 }
2912}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:67
length_accountg($account)
Return General accounting account with defined length (used for product and miscellaneous)
checkIbanForAccount($account=null, $ibantocheck=null)
Check IBAN number information for a bank account.
Definition bank.lib.php:363
getIbanHumanReadable(Account $account)
Returns the iban human readable.
Definition bank.lib.php:388
checkSwiftForAccount($account=null, $swift=null)
Check SWIFT information for a bank account.
Definition bank.lib.php:342
$object ref
Definition info.php:90
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 clickable 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.
getCountryCode()
Return account country code.
getLibStatut($mode=0)
Return label of object status.
update_bban($user=null)
Update BBAN (RIB) account fields.
create($user, $notrigger=0)
Create bank account into database.
addline($date, $oper, $label, $amount, $num_chq, $categorie, User $user, $emetteur='', $banque='', $accountancycode='', $datev=null, $num_releve='', $amount_main_currency=null, $note_private='')
Add an entry into table llx_bank.
getBannerAddress($htmlkey, $object)
Return full address for banner.
error()
Return error.
info($id)
Load miscellaneous information for tab "Info".
const TYPE_CASH
Cash account.
update($user, $notrigger=0)
Update bank account card.
__toString()
Shows the account number in the appropriate format.
delete($user, $notrigger=0)
Delete bank account from database.
const TYPE_SAVINGS
Savings account.
getTooltipContentArray($params)
getTooltipContentArray
canBeConciliated()
Return if a bank account need to be conciliated.
can_be_deleted()
Indicates if an account can be deleted or not (without movements)
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.
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.
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition index.php:171
getCountry($searchkey, $withcode='', $dbtouse=null, $outputlangs=null, $entconv=1, $searchlabel='')
Return country label, code or id from an id, code or label.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
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 '.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
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...
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0)
Clean a string to use it as a file name.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
div refaddress div address
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
if(preg_match('/(crypted|dolcrypt):/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:158