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 $sql = "INSERT INTO ".MAIN_DB_PREFIX."bank_url (";
507 $sql .= "fk_bank";
508 $sql .= ", url_id";
509 $sql .= ", url"; // deprecated
510 $sql .= ", label";
511 $sql .= ", type";
512 $sql .= ") VALUES (";
513 $sql .= ((int) $line_id);
514 $sql .= ", ".((int) $url_id);
515 $sql .= ", '".$this->db->escape($url)."'"; // deprecated
516 $sql .= ", '".$this->db->escape($label)."'";
517 $sql .= ", '".$this->db->escape($type)."'";
518 $sql .= ")";
519
520 dol_syslog(get_class($this)."::add_url_line", LOG_DEBUG);
521 if ($this->db->query($sql)) {
522 $rowid = $this->db->last_insert_id(MAIN_DB_PREFIX."bank_url");
523 return $rowid;
524 } else {
525 $this->error = $this->db->lasterror();
526 return -1;
527 }
528 }
529
530 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
540 public function get_url($fk_bank = 0, $url_id = 0, $type = '')
541 {
542 // phpcs:enable
543 $lines = array();
544
545 // Check parameters
546 if (!empty($fk_bank) && (!empty($url_id) || !empty($type))) {
547 $this->error = "ErrorBadParameter";
548 return -1;
549 }
550
551 $sql = "SELECT fk_bank, url_id, url, label, type";
552 $sql .= " FROM ".MAIN_DB_PREFIX."bank_url";
553 if ($fk_bank > 0) {
554 $sql .= " WHERE fk_bank = ".((int) $fk_bank);
555 } else {
556 $sql .= " WHERE url_id = ".((int) $url_id)." AND type = '".$this->db->escape($type)."'";
557 }
558 $sql .= " ORDER BY type, label";
559
560 dol_syslog(get_class($this)."::get_url", LOG_DEBUG);
561 $result = $this->db->query($sql);
562 if ($result) {
563 $i = 0;
564 $num = $this->db->num_rows($result);
565 while ($i < $num) {
566 $obj = $this->db->fetch_object($result);
567 // Old links (for compatibility)
568 $lines[$i][0] = $obj->url;
569 $lines[$i][1] = $obj->url_id;
570 $lines[$i][2] = $obj->label;
571 $lines[$i][3] = $obj->type;
572 // New links
573 $lines[$i]['url'] = $obj->url;
574 $lines[$i]['url_id'] = $obj->url_id;
575 $lines[$i]['label'] = $obj->label;
576 $lines[$i]['type'] = $obj->type;
577 $lines[$i]['fk_bank'] = $obj->fk_bank;
578 $i++;
579 }
580 } else {
581 dol_print_error($this->db);
582 }
583
584 return $lines;
585 }
586
606 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 = '')
607 {
608 global $langs;
609
610 // Deprecation warning
611 if (is_numeric($oper)) {
612 dol_syslog(__METHOD__.": using numeric operations is deprecated", LOG_WARNING);
613 }
614
615 if (empty($this->id) && !empty($this->rowid)) { // For backward compatibility
616 $this->id = $this->rowid;
617 }
618
619 // Clean parameters
620 $emetteur = trim($emetteur);
621 $banque = trim($banque);
622 $label = trim($label);
623
624 $now = dol_now();
625
626 if (is_numeric($oper)) { // Clean operation to have a code instead of a rowid
627 $sql = "SELECT code FROM ".MAIN_DB_PREFIX."c_paiement";
628 $sql .= " WHERE id = ".((int) $oper);
629 $sql .= " AND entity IN (".getEntity('c_paiement').")";
630 $resql = $this->db->query($sql);
631 if ($resql) {
632 $obj = $this->db->fetch_object($resql);
633 $oper = $obj->code;
634 } else {
635 dol_print_error($this->db, 'Failed to get payment type code');
636 return -1;
637 }
638 }
639
640 // Check parameters
641 if (!$oper) {
642 $this->error = $langs->trans("OperNotDefined");
643 return -1;
644 }
645 if (!$this->id) {
646 $this->error = $langs->trans("ThisIdNotDefined");
647 return -2;
648 }
649 if ($this->type == Account::TYPE_CASH && $oper != 'LIQ') {
650 $this->error = "ErrorCashAccountAcceptsOnlyCashMoney";
651 return -3;
652 }
653
654 $this->db->begin();
655
656 if (is_null($datev) || empty($datev)) {
657 $datev = $date;
658 }
659
660 $accline = new AccountLine($this->db);
661 $accline->datec = $now;
662 $accline->dateo = $date;
663 $accline->datev = $datev;
664 $accline->label = $label;
665 $accline->amount = $amount;
666 $accline->amount_main_currency = $amount_main_currency;
667 $accline->fk_user_author = $user->id;
668 $accline->fk_account = $this->id;
669 $accline->fk_type = $oper;
670 $accline->numero_compte = $accountancycode;
671 $accline->num_releve = $num_releve;
672 $accline->note_private = $note_private;
673
674 if ($num_chq) {
675 $accline->num_chq = $num_chq;
676 }
677
678 if ($emetteur) {
679 $accline->emetteur = $emetteur;
680 }
681
682 if ($banque) {
683 $accline->bank_chq = $banque;
684 }
685
686 if ($accline->insert() > 0) {
687 if ($categorie > 0) {
688 $sql = "INSERT INTO ".MAIN_DB_PREFIX."category_bankline(";
689 $sql .= "lineid, fk_categ";
690 $sql .= ") VALUES (";
691 $sql .= ((int) $accline->id).", ".((int) $categorie);
692 $sql .= ")";
693
694 $result = $this->db->query($sql);
695 if (!$result) {
696 $this->error = $this->db->lasterror();
697 $this->db->rollback();
698
699 return -4;
700 }
701 }
702
703 $this->db->commit();
704
705 return $accline->id;
706 } else {
707 $this->setErrorsFromObject($accline);
708 $this->db->rollback();
709
710 return -5;
711 }
712 }
713
721 public function create($user, $notrigger = 0)
722 {
723 global $langs, $conf;
724
725 $error = 0;
726
727 // Clean parameters
728 if (!$this->min_allowed) {
729 $this->min_allowed = 0;
730 }
731 if (!$this->min_desired) {
732 $this->min_desired = 0;
733 }
734
735 // Check parameters
736 if (empty($this->country_id)) {
737 $langs->load('errors');
738 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Country"));
739 dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
740 return -1;
741 }
742 if (empty($this->ref)) {
743 $langs->load('errors');
744 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Ref"));
745 dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
746 return -1;
747 }
748 if (empty($this->date_solde)) {
749 $langs->load('errors');
750 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("DateInitialBalance"));
751 dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
752 return -1;
753 }
754
755 // Load libraries to check BAN
756 $balance = $this->balance;
757 if (empty($balance) && !empty($this->solde)) {
758 dol_syslog(get_class($this)."::create solde is deprecated use balance", LOG_NOTICE);
759 $balance = $this->solde;
760 }
761 if (empty($balance)) {
762 $balance = 0;
763 }
764 if (empty($this->status && !empty($this->clos))) {
765 dol_syslog(get_class($this)."::create clos is deprecated use status", LOG_NOTICE);
766 $this->status = $this->clos;
767 }
768
769 if (empty($this->country_id) && !empty($this->country_code)) {
770 $country_id = getCountry($this->country_code, '3');
771 $this->country_id = is_int($country_id) ? $country_id : 0;
772 }
773
774 // Load the library to validate/check a BAN account
775 require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
776
777 $now = dol_now();
778
779 $this->db->begin();
780
781 $sql = "INSERT INTO ".MAIN_DB_PREFIX."bank_account (";
782 $sql .= "datec";
783 $sql .= ", ref";
784 $sql .= ", label";
785 $sql .= ", entity";
786 $sql .= ", account_number";
787 $sql .= ", fk_accountancy_journal";
788 $sql .= ", bank";
789 $sql .= ", code_banque";
790 $sql .= ", code_guichet";
791 $sql .= ", number";
792 $sql .= ", cle_rib";
793 $sql .= ", bic";
794 $sql .= ", iban_prefix";
795 $sql .= ", domiciliation";
796 $sql .= ", pti_in_ctti";
797 $sql .= ", proprio";
798 $sql .= ", owner_address";
799 $sql .= ", owner_zip";
800 $sql .= ", owner_town";
801 $sql .= ", owner_country_id";
802 $sql .= ", currency_code";
803 $sql .= ", rappro";
804 $sql .= ", min_allowed";
805 $sql .= ", min_desired";
806 $sql .= ", comment";
807 $sql .= ", state_id";
808 $sql .= ", fk_pays";
809 $sql .= ", ics";
810 $sql .= ", ics_transfer";
811 $sql .= ") VALUES (";
812 $sql .= "'".$this->db->idate($now)."'";
813 $sql .= ", '".$this->db->escape($this->ref)."'";
814 $sql .= ", '".$this->db->escape($this->label)."'";
815 $sql .= ", ".((int) $conf->entity);
816 $sql .= ", '".$this->db->escape($this->account_number)."'";
817 $sql .= ", ".($this->fk_accountancy_journal > 0 ? ((int) $this->fk_accountancy_journal) : "null");
818 $sql .= ", '".$this->db->escape($this->bank)."'";
819 $sql .= ", '".$this->db->escape($this->code_banque)."'";
820 $sql .= ", '".$this->db->escape($this->code_guichet)."'";
821 $sql .= ", '".$this->db->escape($this->number)."'";
822 $sql .= ", '".$this->db->escape($this->cle_rib)."'";
823 $sql .= ", '".$this->db->escape($this->bic)."'";
824 $sql .= ", '".$this->db->escape($this->iban)."'";
825 $sql .= ", '".$this->db->escape($this->address)."'";
826 $sql .= ", ".((int) $this->pti_in_ctti);
827 $sql .= ", '".$this->db->escape($this->owner_name)."'";
828 $sql .= ", '".$this->db->escape($this->owner_address)."'";
829 $sql .= ", '".$this->db->escape($this->owner_zip)."'";
830 $sql .= ", '".$this->db->escape($this->owner_town)."'";
831 $sql .= ", ".($this->owner_country_id > 0 ? ((int) $this->owner_country_id) : "null");
832 $sql .= ", '".$this->db->escape($this->currency_code)."'";
833 $sql .= ", ".((int) $this->rappro);
834 $sql .= ", ".price2num($this->min_allowed, 'MT');
835 $sql .= ", ".price2num($this->min_desired, 'MT');
836 $sql .= ", '".$this->db->escape($this->comment)."'";
837 $sql .= ", ".($this->state_id > 0 ? ((int) $this->state_id) : "null");
838 $sql .= ", ".($this->country_id > 0 ? ((int) $this->country_id) : "null");
839 $sql .= ", '".$this->db->escape($this->ics)."'";
840 $sql .= ", '".$this->db->escape($this->ics_transfer)."'";
841 $sql .= ")";
842
843 dol_syslog(get_class($this)."::create", LOG_DEBUG);
844 $resql = $this->db->query($sql);
845 if ($resql) {
846 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."bank_account");
847
848 $result = $this->update($user, 1);
849 if ($result > 0) {
850 $accline = new AccountLine($this->db);
851 $accline->datec = $now;
852 $accline->label = '('.$langs->trans("InitialBankBalance").')';
853 $accline->amount = (float) price2num($balance);
854 $accline->fk_user_author = $user->id;
855 $accline->fk_account = $this->id;
856 $accline->datev = $this->date_solde;
857 $accline->dateo = $this->date_solde;
858 $accline->fk_type = 'SOLD';
859
860 if ($accline->insert() < 0) {
861 $error++;
862 $this->setErrorsFromObject($accline);
863 }
864
865 if (!$error) {
866 $result = $this->insertExtraFields();
867 if ($result < 0) {
868 $error++;
869 }
870 }
871
872 if (!$error && !$notrigger) {
873 // Call trigger
874 $result = $this->call_trigger('BANKACCOUNT_CREATE', $user);
875 if ($result < 0) {
876 $error++;
877 }
878 // End call triggers
879 }
880 } else {
881 $error++;
882 }
883 } else {
884 if ($this->db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
885 $this->error = $langs->trans("ErrorBankLabelAlreadyExists");
886 $error++;
887 } else {
888 $this->error = $this->db->error()." sql=".$sql;
889 $error++;
890 }
891 }
892
893 if (!$error) {
894 $this->db->commit();
895 return $this->id;
896 } else {
897 $this->db->rollback();
898 return -1 * $error;
899 }
900 }
901
909 public function update($user, $notrigger = 0)
910 {
911 global $langs, $conf;
912
913 if (empty($this->country_id) && !empty($this->country_code)) {
914 $country_id = getCountry($this->country_code, '3');
915 $this->country_id = is_int($country_id) ? $country_id : 0;
916 }
917
918 $error = 0;
919
920 $this->db->begin();
921
922 // Check parameters
923 if (empty($this->country_id)) {
924 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Country"));
925 dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
926 return -1;
927 }
928 if (empty($this->ref)) {
929 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Ref"));
930 dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
931 return -1;
932 }
933 if (!$this->label) {
934 $this->label = "???";
935 }
936
937 $sql = "UPDATE ".MAIN_DB_PREFIX."bank_account SET";
938 $sql .= " ref = '".$this->db->escape($this->ref)."'";
939 $sql .= ",label = '".$this->db->escape($this->label)."'";
940 $sql .= ",courant = ".((int) $this->type);
941 $sql .= ",clos = ".((int) $this->status);
942 $sql .= ",rappro = ".((int) $this->rappro);
943 $sql .= ",url = ".($this->url ? "'".$this->db->escape($this->url)."'" : "null");
944 $sql .= ",account_number = '".$this->db->escape($this->account_number)."'";
945 $sql .= ",fk_accountancy_journal = ".($this->fk_accountancy_journal > 0 ? ((int) $this->fk_accountancy_journal) : "null");
946 $sql .= ",bank = '".$this->db->escape($this->bank)."'";
947 $sql .= ",code_banque='".$this->db->escape($this->code_banque)."'";
948 $sql .= ",code_guichet='".$this->db->escape($this->code_guichet)."'";
949 $sql .= ",number='".$this->db->escape($this->number)."'";
950 $sql .= ",cle_rib='".$this->db->escape($this->cle_rib)."'";
951 $sql .= ",bic='".$this->db->escape($this->bic)."'";
952 $sql .= ",iban_prefix = '".$this->db->escape($this->iban)."'";
953 $sql .= ",domiciliation='".$this->db->escape($this->address)."'";
954 $sql .= ",pti_in_ctti=".((int) $this->pti_in_ctti);
955 $sql .= ",proprio = '".$this->db->escape($this->owner_name)."'";
956 $sql .= ",owner_address = '".$this->db->escape($this->owner_address)."'";
957 $sql .= ",owner_zip = '".$this->db->escape($this->owner_zip)."'";
958 $sql .= ",owner_town = '".$this->db->escape($this->owner_town)."'";
959 $sql .= ",owner_country_id = ".($this->owner_country_id > 0 ? ((int) $this->owner_country_id) : "null");
960
961 $sql .= ",currency_code = '".$this->db->escape($this->currency_code)."'";
962
963 $sql .= ",min_allowed = ".($this->min_allowed != '' ? price2num($this->min_allowed) : "null");
964 $sql .= ",min_desired = ".($this->min_desired != '' ? price2num($this->min_desired) : "null");
965 $sql .= ",comment = '".$this->db->escape($this->comment)."'";
966
967 $sql .= ",state_id = ".($this->state_id > 0 ? ((int) $this->state_id) : "null");
968 $sql .= ",fk_pays = ".($this->country_id > 0 ? ((int) $this->country_id) : "null");
969 $sql .= ",ics = '".$this->db->escape($this->ics)."'";
970 $sql .= ",ics_transfer = '".$this->db->escape($this->ics_transfer)."'";
971
972 $sql .= " WHERE rowid = ".((int) $this->id);
973
974 dol_syslog(get_class($this)."::update", LOG_DEBUG);
975 $result = $this->db->query($sql);
976 if ($result) {
977 // Actions on extra fields (by external module or standard code)
978 if (!$error) {
979 $result = $this->insertExtraFields();
980 if ($result < 0) {
981 $error++;
982 }
983 }
984
985 if (!$error && !empty($this->oldref) && $this->oldref !== $this->ref) {
986 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'bank/".$this->db->escape($this->ref)."'";
987 $sql .= " WHERE filepath = 'bank/".$this->db->escape($this->oldref)."' and src_object_type='bank_account' and entity = ".((int) $conf->entity);
988 $resql = $this->db->query($sql);
989 if (!$resql) {
990 $error++;
991 $this->error = $this->db->lasterror();
992 }
993
994 // We rename directory in order not to lose the attachments
995 $oldref = dol_sanitizeFileName($this->oldref);
996 $newref = dol_sanitizeFileName($this->ref);
997 $dirsource = $conf->bank->dir_output.'/'.$oldref;
998 $dirdest = $conf->bank->dir_output.'/'.$newref;
999 if (file_exists($dirsource)) {
1000 dol_syslog(get_class($this)."::update rename dir ".$dirsource." into ".$dirdest, LOG_DEBUG);
1001 if (@rename($dirsource, $dirdest)) {
1002 dol_syslog("Rename ok", LOG_DEBUG);
1003 }
1004 }
1005 }
1006
1007 if (!$error && !$notrigger) {
1008 // Call trigger
1009 $result = $this->call_trigger('BANKACCOUNT_MODIFY', $user);
1010 if ($result < 0) {
1011 $error++;
1012 }
1013 // End call triggers
1014 }
1015 } else {
1016 $error++;
1017 $this->error = $this->db->lasterror();
1018 dol_print_error($this->db);
1019 }
1020
1021 if (!$error) {
1022 $this->db->commit();
1023 return $this->id;
1024 } else {
1025 $this->db->rollback();
1026 return -1 * $error;
1027 }
1028 }
1029
1030
1031 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1038 public function update_bban($user = null)
1039 {
1040 // phpcs:enable
1041 global $conf, $langs;
1042
1043 // Load library to get BAN control function
1044 require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1045
1046 dol_syslog(get_class($this)."::update_bban $this->code_banque,$this->code_guichet,$this->number,$this->cle_rib,$this->iban");
1047
1048 // Check parameters
1049 if (!$this->ref) {
1050 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->trans("Ref"));
1051 return -2;
1052 }
1053
1054 $sql = "UPDATE ".MAIN_DB_PREFIX."bank_account SET";
1055 $sql .= " bank = '".$this->db->escape($this->bank)."'";
1056 $sql .= ",code_banque='".$this->db->escape($this->code_banque)."'";
1057 $sql .= ",code_guichet='".$this->db->escape($this->code_guichet)."'";
1058 $sql .= ",number='".$this->db->escape($this->number)."'";
1059 $sql .= ",cle_rib='".$this->db->escape($this->cle_rib)."'";
1060 $sql .= ",bic='".$this->db->escape($this->bic)."'";
1061 $sql .= ",iban_prefix = '".$this->db->escape($this->iban)."'";
1062 $sql .= ",domiciliation='".$this->db->escape($this->address)."'";
1063 $sql .= ",proprio = '".$this->db->escape($this->owner_name)."'";
1064 $sql .= ",owner_address = '".$this->db->escape($this->owner_address)."'";
1065 $sql .= ",owner_zip = '".$this->db->escape($this->owner_zip)."'";
1066 $sql .= ",owner_town = '".$this->db->escape($this->owner_town)."'";
1067 $sql .= ",owner_country_id = ".($this->owner_country_id > 0 ? ((int) $this->owner_country_id) : "null");
1068 $sql .= ",state_id = ".($this->state_id > 0 ? $this->state_id : "null");
1069 $sql .= ",fk_pays = ".($this->country_id > 0 ? $this->country_id : "null");
1070 $sql .= " WHERE rowid = ".((int) $this->id);
1071 $sql .= " AND entity = ".((int) $conf->entity);
1072
1073 dol_syslog(get_class($this)."::update_bban", LOG_DEBUG);
1074
1075 $result = $this->db->query($sql);
1076 if ($result) {
1077 return 1;
1078 } else {
1079 $this->error = $this->db->lasterror();
1080 dol_print_error($this->db);
1081 return -1;
1082 }
1083 }
1084
1085
1093 public function fetch($id, $ref = '')
1094 {
1095 if (empty($id) && empty($ref)) {
1096 $this->error = "ErrorBadParameters";
1097 return -1;
1098 }
1099
1100 $sql = "SELECT ba.rowid, ba.ref, ba.label, ba.bank, ba.number, ba.courant as type, ba.clos as status, ba.rappro, ba.url,";
1101 $sql .= " ba.code_banque, ba.code_guichet, ba.cle_rib, ba.bic, ba.iban_prefix as iban,";
1102 $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,";
1103 $sql .= " ba.account_number, ba.fk_accountancy_journal, ba.currency_code,";
1104 $sql .= " ba.min_allowed, ba.min_desired, ba.comment,";
1105 $sql .= " ba.datec as date_creation, ba.tms as date_modification, ba.ics, ba.ics_transfer,";
1106 $sql .= ' c.code as country_code, c.label as country,';
1107 $sql .= ' d.code_departement as state_code, d.nom as state,';
1108 $sql .= ' aj.code as accountancy_journal';
1109 $sql .= " FROM ".MAIN_DB_PREFIX."bank_account as ba";
1110 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_country as c ON ba.fk_pays = c.rowid';
1111 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_departements as d ON ba.state_id = d.rowid';
1112 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'accounting_journal as aj ON aj.rowid=ba.fk_accountancy_journal';
1113 $sql .= " WHERE ba.entity IN (".getEntity($this->element).")";
1114 if ($id) {
1115 $sql .= " AND ba.rowid = ".((int) $id);
1116 }
1117 if ($ref) {
1118 $sql .= " AND ba.ref = '".$this->db->escape($ref)."'";
1119 }
1120
1121 dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
1122 $result = $this->db->query($sql);
1123 if ($result) {
1124 if ($this->db->num_rows($result)) {
1125 $obj = $this->db->fetch_object($result);
1126
1127 $this->id = $obj->rowid;
1128 $this->rowid = $obj->rowid;
1129 $this->ref = $obj->ref;
1130 $this->label = $obj->label;
1131 $this->type = $obj->type;
1132 $this->courant = $obj->type;
1133 $this->bank = $obj->bank;
1134 $this->clos = $obj->status;
1135 $this->status = $obj->status;
1136 $this->rappro = $obj->rappro;
1137 $this->url = $obj->url;
1138
1139 $this->code_banque = $obj->code_banque;
1140 $this->code_guichet = $obj->code_guichet;
1141 $this->number = $obj->number;
1142 $this->cle_rib = $obj->cle_rib;
1143 $this->bic = $obj->bic;
1144 $this->iban = $obj->iban;
1145 $this->address = $obj->address;
1146
1147 $this->owner_name = $obj->owner_name;
1148 $this->proprio = $this->owner_name;
1149 $this->owner_address = $obj->owner_address;
1150 $this->owner_zip = $obj->owner_zip;
1151 $this->owner_town = $obj->owner_town;
1152 $this->owner_country_id = $obj->owner_country_id;
1153
1154 $this->pti_in_ctti = $obj->pti_in_ctti;
1155
1156 $this->state_id = $obj->state_id;
1157 $this->state_code = $obj->state_code;
1158 $this->state = $obj->state;
1159
1160 $this->country_id = $obj->country_id;
1161 $this->country_code = $obj->country_code;
1162 $this->country = $obj->country;
1163
1164 $this->account_number = $obj->account_number;
1165 $this->fk_accountancy_journal = $obj->fk_accountancy_journal;
1166 $this->accountancy_journal = $obj->accountancy_journal;
1167
1168 $this->currency_code = $obj->currency_code;
1169 $this->account_currency_code = $obj->currency_code;
1170 $this->min_allowed = $obj->min_allowed;
1171 $this->min_desired = $obj->min_desired;
1172 $this->comment = $obj->comment;
1173
1174 $this->date_creation = $this->db->jdate($obj->date_creation);
1175 $this->date_modification = $this->db->jdate($obj->date_modification);
1176
1177 $this->ics = $obj->ics;
1178 $this->ics_transfer = $obj->ics_transfer;
1179
1180 // Retrieve all extrafield
1181 // fetch optionals attributes and labels
1182 $this->fetch_optionals();
1183
1184 return 1;
1185 } else {
1186 return 0;
1187 }
1188 } else {
1189 $this->error = $this->db->lasterror();
1190 $this->errors[] = $this->error;
1191 return -1;
1192 }
1193 }
1194
1205 public function setCategories($categories)
1206 {
1207 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1208 return parent::setCategoriesCommon($categories, Categorie::TYPE_ACCOUNT);
1209 }
1210
1218 public function delete($user, $notrigger = 0)
1219 {
1220 $error = 0;
1221
1222 $this->db->begin();
1223
1224 // @TODO Check there is no child into llx_payment_various, ... to allow deletion ?
1225
1226 // Delete link between tag and bank account
1227 if (!$error) {
1228 $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_account";
1229 $sql .= " WHERE fk_account = ".((int) $this->id);
1230
1231 $resql = $this->db->query($sql);
1232 if (!$resql) {
1233 $error++;
1234 $this->error = "Error ".$this->db->lasterror();
1235 }
1236 }
1237
1238 if (!$error) {
1239 $sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element;
1240 $sql .= " WHERE rowid = ".((int) $this->id);
1241
1242 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1243 $result = $this->db->query($sql);
1244 if ($result) {
1245 // Remove extrafields
1246 if (!$error) {
1247 $result = $this->deleteExtraFields();
1248 if ($result < 0) {
1249 $error++;
1250 dol_syslog(get_class($this)."::delete error -4 ".$this->error, LOG_ERR);
1251 }
1252 }
1253 } else {
1254 $error++;
1255 $this->error = "Error ".$this->db->lasterror();
1256 }
1257 }
1258
1259 if (!$error) {
1260 $this->db->commit();
1261 return 1;
1262 } else {
1263 $this->db->rollback();
1264 return -1;
1265 }
1266 }
1267
1268
1275 public function getLibStatut($mode = 0)
1276 {
1277 return $this->LibStatut($this->status, $mode);
1278 }
1279
1280 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1288 public function LibStatut($status, $mode = 0)
1289 {
1290 // phpcs:enable
1291 global $langs;
1292 $langs->load('banks');
1293
1294 if ($status == self::STATUS_OPEN) {
1295 $label = $langs->transnoentitiesnoconv("StatusAccountOpened");
1296 $labelshort = $langs->transnoentitiesnoconv("StatusAccountOpened");
1297 $statusType = 'status4';
1298 } else {
1299 $label = $langs->transnoentitiesnoconv("StatusAccountClosed");
1300 $labelshort = $langs->transnoentitiesnoconv("StatusAccountClosed");
1301 $statusType = 'status5';
1302 }
1303
1304 return dolGetStatus($label, $labelshort, '', $statusType, $mode);
1305 }
1306
1307
1308 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1314 public function can_be_deleted()
1315 {
1316 // phpcs:enable
1317 $can_be_deleted = false;
1318
1319 $sql = "SELECT COUNT(rowid) as nb";
1320 $sql .= " FROM ".MAIN_DB_PREFIX."bank";
1321 $sql .= " WHERE fk_account = ".((int) $this->id);
1322
1323 $resql = $this->db->query($sql);
1324 if ($resql) {
1325 $obj = $this->db->fetch_object($resql);
1326 if ($obj->nb <= 1) {
1327 $can_be_deleted = true; // Juste le solde
1328 }
1329 } else {
1330 dol_print_error($this->db);
1331 }
1332 return $can_be_deleted;
1333 }
1334
1335
1341 public function error()
1342 {
1343 return $this->error;
1344 }
1345
1354 public function solde($option = 0, $date_end = '', $field = 'dateo')
1355 {
1356 $solde = 0;
1357
1358 $sql = "SELECT sum(amount) as amount";
1359 $sql .= " FROM ".MAIN_DB_PREFIX."bank";
1360 $sql .= " WHERE fk_account = ".((int) $this->id);
1361 if ($option == 1) {
1362 $sql .= " AND ".$this->db->escape($field)." <= '".(!empty($date_end) ? $this->db->idate($date_end) : $this->db->idate(dol_now()))."'";
1363 }
1364
1365 $resql = $this->db->query($sql);
1366 if ($resql) {
1367 if ($this->db->num_rows($resql)) {
1368 $obj = $this->db->fetch_object($resql);
1369 $solde = $obj->amount;
1370 }
1371 $this->db->free($resql);
1372 } else {
1373 $this->errors[] = $this->db->lasterror;
1374 return -1;
1375 }
1376
1377 return (float) price2num($solde, 'MU');
1378 }
1379
1380 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1388 public function load_board(User $user, $filteraccountid = 0)
1389 {
1390 // phpcs:enable
1391 global $conf, $langs;
1392
1393 if ($user->socid) {
1394 return -1; // protection pour eviter appel par utilisateur externe
1395 }
1396
1397 $sql = "SELECT b.rowid, b.datev as datefin";
1398 $sql .= " FROM ".MAIN_DB_PREFIX."bank as b,";
1399 $sql .= " ".MAIN_DB_PREFIX."bank_account as ba";
1400 $sql .= " WHERE b.rappro=0";
1401 $sql .= " AND b.fk_account = ba.rowid";
1402 $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
1403 $sql .= " AND (ba.rappro = 1 AND ba.courant != " . Account::TYPE_CASH . ")"; // Compte rapprochable
1404 $sql .= " AND clos = 0";
1405 if ($filteraccountid) {
1406 $sql .= " AND ba.rowid = ".((int) $filteraccountid);
1407 }
1408
1409 $resql = $this->db->query($sql);
1410 if ($resql) {
1411 $langs->load("banks");
1412 $now = dol_now();
1413
1414 require_once DOL_DOCUMENT_ROOT.'/core/class/workboardresponse.class.php';
1415
1416 $response = new WorkboardResponse();
1417 $response->warning_delay = $conf->bank->rappro->warning_delay / 60 / 60 / 24;
1418 $response->label = $langs->trans("TransactionsToConciliate");
1419 $response->labelShort = $langs->trans("TransactionsToConciliateShort");
1420 $response->url = DOL_URL_ROOT.'/compta/bank/list.php?leftmenu=bank&amp;mainmenu=bank';
1421 $response->img = img_object('', "payment");
1422
1423 while ($obj = $this->db->fetch_object($resql)) {
1424 $response->nbtodo++;
1425 if ($this->db->jdate($obj->datefin) < ($now - $conf->bank->rappro->warning_delay)) {
1426 $response->nbtodolate++;
1427 }
1428 }
1429
1430 return $response;
1431 } else {
1432 dol_print_error($this->db);
1433 $this->error = $this->db->error();
1434 return -1;
1435 }
1436 }
1437
1444 public function loadStateBoard($filteraccountid = 0)
1445 {
1446 global $user;
1447
1448 if ($user->socid) {
1449 return -1; // protection pour eviter appel par utilisateur externe
1450 }
1451
1452 $sql = "SELECT count(b.rowid) as nb";
1453 $sql .= " FROM ".MAIN_DB_PREFIX."bank as b,";
1454 $sql .= " ".MAIN_DB_PREFIX."bank_account as ba";
1455 $sql .= " WHERE b.fk_account = ba.rowid";
1456 $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
1457 $sql .= " AND (ba.rappro = 1 AND ba.courant != 2)"; // Compte rapprochable
1458 $sql .= " AND clos = 0";
1459 if ($filteraccountid) {
1460 $sql .= " AND ba.rowid = ".((int) $filteraccountid);
1461 }
1462
1463 $resql = $this->db->query($sql);
1464 if ($resql) {
1465 while ($obj = $this->db->fetch_object($resql)) {
1466 $this->nb["banklines"] = $obj->nb;
1467 }
1468 $this->db->free($resql);
1469 return 1;
1470 } else {
1471 dol_print_error($this->db);
1472 $this->error = $this->db->error();
1473 return -1;
1474 }
1475 }
1476
1477
1483 public function countAccountToReconcile()
1484 {
1485 global $user;
1486
1487 //Protection against external users
1488 if ($user->socid) {
1489 return 0;
1490 }
1491
1492 $nb = 0;
1493
1494 $sql = "SELECT COUNT(ba.rowid) as nb";
1495 $sql .= " FROM ".MAIN_DB_PREFIX."bank_account as ba";
1496 $sql .= " WHERE ba.rappro > 0 and ba.clos = 0";
1497 $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
1498 if (!getDolGlobalString('BANK_CAN_RECONCILIATE_CASHACCOUNT')) {
1499 $sql .= " AND ba.courant != " . Account::TYPE_CASH;
1500 }
1501
1502 $resql = $this->db->query($sql);
1503 if ($resql) {
1504 $obj = $this->db->fetch_object($resql);
1505 $nb = $obj->nb;
1506 } else {
1507 dol_print_error($this->db);
1508 }
1509
1510 return $nb;
1511 }
1512
1521 public function getTooltipContentArray($params)
1522 {
1523 global $langs;
1524 $langs->loadLangs(['banks', 'compta']);
1525 include_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1526
1527 $datas = array();
1528
1529 $nofetch = !empty($params['nofetch']);
1530 $pictos = img_picto('', $this->picto).' <u class="paddingrightnow">'.$langs->trans("BankAccount").'</u>';
1531 if (isset($this->status)) {
1532 $pictos .= ' '.$this->getLibStatut(5);
1533 }
1534 $datas['picto'] = $pictos;
1535 $datas['ref'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
1536 $datas['label'] = '<br><b>'.$langs->trans('Label').':</b> '.$this->label;
1537 $datas['accountnumber'] = '<br><br><b>'.$langs->trans('AccountNumber').':</b> '.$this->number;
1538 $datas['iban'] = '<br><b>'.$langs->trans('IBAN').':</b> '.getIbanHumanReadable($this);
1539 $datas['bic'] = '<br><b>'.$langs->trans('BIC').':</b> '.$this->bic;
1540 $datas['accountcurrency'] = '<br><br><b>'.$langs->trans("AccountCurrency").':</b> '.$this->currency_code;
1541
1542 if (isModEnabled('accounting')) {
1543 include_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
1544 $langs->load("accountancy");
1545 $datas['accountaccounting'] = '<br><b>'.$langs->trans('AccountAccounting').':</b> '.length_accountg($this->account_number);
1546 $datas['accountancyjournal'] = '<br><b>'.$langs->trans('AccountancyJournal').':</b> '.$this->accountancy_journal;
1547 }
1548 // show categories for this record only in ajax to not overload lists
1549 if (isModEnabled('category') && !$nofetch) {
1550 require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
1551 $form = new Form($this->db);
1552 $datas['categories'] = '<br>' . $form->showCategories($this->id, Categorie::TYPE_ACCOUNT, 1);
1553 }
1554
1555 return $datas;
1556 }
1557
1569 public function getNomUrl($withpicto = 0, $mode = '', $option = '', $save_lastsearch_value = -1, $notooltip = 0, $morecss = '')
1570 {
1571 global $conf, $langs;
1572
1573 if (!empty($conf->dol_no_mouse_hover)) {
1574 $notooltip = 1; // Force disable tooltips
1575 }
1576
1577 include_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1578
1579 $result = '';
1580 $classfortooltip = 'classfortooltip';
1581 $dataparams = '';
1582 $params = [
1583 'id' => $this->id,
1584 'objecttype' => $this->element,
1585 'option' => $option,
1586 'nofetch' => 1,
1587 ];
1588 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1589 $classfortooltip = 'classforajaxtooltip';
1590 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
1591 $label = '';
1592 } else {
1593 $label = implode($this->getTooltipContentArray($params));
1594 }
1595
1596 $url = DOL_URL_ROOT.'/compta/bank/card.php?id='.$this->id;
1597 if ($mode == 'transactions') {
1598 $url = DOL_URL_ROOT.'/compta/bank/bankentries_list.php?id='.$this->id;
1599 } elseif ($mode == 'receipts') {
1600 $url = DOL_URL_ROOT.'/compta/bank/releve.php?account='.$this->id;
1601 }
1602
1603 if ($option != 'nolink') {
1604 // Add param to save lastsearch_values or not
1605 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1606 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1607 $add_save_lastsearch_values = 1;
1608 }
1609 if ($add_save_lastsearch_values) {
1610 $url .= '&save_lastsearch_values=1';
1611 }
1612 }
1613
1614 $linkclose = '';
1615 if (empty($notooltip)) {
1616 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1617 $label = $langs->trans("BankAccount");
1618 $linkclose .= ' alt="'.dolPrintHTMLForAttribute($label).'"';
1619 }
1620 $linkclose .= ($label ? ' title="'.dolPrintHTMLForAttribute($label).'"' : ' title="tocomplete"');
1621 $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
1622 } else {
1623 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1624 }
1625
1626 if ($option == 'nolink' || empty($url)) {
1627 $linkstart = '<span';
1628 } else {
1629 $linkstart = '<a href="'.$url.'"';
1630 }
1631 $linkstart .= $linkclose.'>';
1632 if ($option == 'nolink' || empty($url)) {
1633 $linkend = '</span>';
1634 } else {
1635 $linkend = '</a>';
1636 }
1637
1638 $result .= $linkstart;
1639
1640 if ($withpicto) {
1641 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"'), 0, 0, $notooltip ? 0 : 1);
1642 }
1643 if ($withpicto != 2) {
1644 $result .= $this->ref.($option == 'reflabel' && $this->label ? ' - '.$this->label : '');
1645 }
1646 $result .= $linkend;
1647
1648 return $result;
1649 }
1650
1651
1652 // Method after here are common to Account and CompanyBankAccount
1653
1654
1660 public function verif()
1661 {
1662 require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1663
1664 $error = 0;
1665
1666 // Call functions to check BAN
1667 if (!checkIbanForAccount($this)) {
1668 $error++;
1669 $this->error = 'IBANNotValid';
1670 }
1671 // Call function to check Swift/BIC.
1672 // A non valid BIC/Swift is a problem if: it is not empty or always a problem if WITHDRAWAL_WITHOUT_BIC is not set).
1673 if (!checkSwiftForAccount($this) && (!empty($this->bic) || !getDolGlobalInt('WITHDRAWAL_WITHOUT_BIC'))) {
1674 $error++;
1675 $this->error = 'SwiftNotValid';
1676 }
1677
1678 if (! $error) {
1679 return 1;
1680 } else {
1681 return 0;
1682 }
1683 }
1684
1690 public function getCountryCode()
1691 {
1692 global $mysoc;
1693
1694 // We return country code of bank account
1695 if (!empty($this->country_code)) {
1696 return $this->country_code;
1697 }
1698
1699 // For backward compatibility, we try to guess country from other information
1700 if (!empty($this->iban)) {
1701 // If IBAN defined, we can know country of account from it
1702 $reg = array();
1703 if (preg_match("/^([a-zA-Z][a-zA-Z])/i", $this->iban, $reg)) {
1704 return $reg[1];
1705 }
1706 }
1707
1708 // If this class is linked to a third party
1709 if (!empty($this->socid)) {
1710 require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
1711 $company = new Societe($this->db);
1712 $result = $company->fetch($this->socid);
1713 if (!empty($company->country_code)) {
1714 return $company->country_code;
1715 }
1716 }
1717
1718 // We return country code of managed company
1719 if (!empty($mysoc->country_code)) {
1720 return $mysoc->country_code;
1721 }
1722
1723 return '';
1724 }
1725
1733 public function getBannerAddress($htmlkey, $object)
1734 {
1735 global $conf, $langs;
1736
1737 $out = '';
1738
1739 $outdone = 0;
1740 $coords = $this->getFullAddress(1, ', ', getDolGlobalInt('MAIN_SHOW_REGION_IN_STATE_SELECT'));
1741 if ($coords) {
1742 if (!empty($conf->use_javascript_ajax)) {
1743 // hideonsmatphone because copyToClipboard call jquery dialog that does not work with jmobile
1744 $out .= '<a href="#" class="hideonsmartphone" onclick="return copyToClipboard(\''.dol_escape_js($coords).'\',\''.dol_escape_js($langs->trans("HelpCopyToClipboard")).'\');">';
1745 $out .= img_picto($langs->trans("Address"), 'map-marker-alt');
1746 $out .= '</a> ';
1747 }
1748 $address = dol_print_address($coords, 'address_'.$htmlkey.'_'.$this->id, $this->element, $this->id, 1, ', ');
1749 if ($address) {
1750 $out .= $address;
1751 $outdone++;
1752 }
1753 $outdone++;
1754 }
1755
1756 return $out;
1757 }
1758
1759
1768 public function useDetailedBBAN()
1769 {
1770 $country_code = $this->getCountryCode();
1771
1772 if (in_array($country_code, array('FR', 'ES', 'GA', 'IT', 'NC'))) {
1773 return 1; // France, Spain, Gabon, ... - Not valid for CH
1774 }
1775 if (in_array($country_code, array('AD', 'AU', 'BE', 'CA', 'DE', 'DK', 'GR', 'GB', 'ID', 'IE', 'IR', 'KR', 'NL', 'NZ', 'UK', 'US'))) {
1776 return 2; // Australia, England...
1777 }
1778 return 0;
1779 }
1780
1786 public function needIBAN()
1787 {
1788 global $conf;
1789
1790 if (getDolGlobalString('MAIN_IBAN_IS_NEVER_MANDATORY')) {
1791 return 0;
1792 }
1793
1794 $country_code = $this->getCountryCode();
1795
1796 $country_code_in_EEC = array(
1797 'AT', // Austria
1798 'BE', // Belgium
1799 'BG', // Bulgaria
1800 'CY', // Cyprus
1801 'CZ', // Czech republic
1802 'DE', // Germany
1803 'DK', // Danemark
1804 'EE', // Estonia
1805 'ES', // Spain
1806 'FI', // Finland
1807 'FR', // France
1808 'GB', // United Kingdom
1809 'GR', // Greece
1810 'HR', // Croatia
1811 'NL', // Holland
1812 'HU', // Hungary
1813 'IE', // Ireland
1814 'IM', // Isle of Man - Included in UK
1815 'IT', // Italy
1816 'LT', // Lithuania
1817 'LU', // Luxembourg
1818 'LV', // Latvia
1819 'MC', // Monaco - Included in France
1820 'MT', // Malta
1821 //'NO', // Norway
1822 'PL', // Poland
1823 'PT', // Portugal
1824 'RO', // Romania
1825 'SE', // Sweden
1826 'SK', // Slovakia
1827 'SI', // Slovenia
1828 'UK', // United Kingdom
1829 //'CH', // Switzerland - No. Swizerland in not in EEC
1830 );
1831
1832 if (in_array($country_code, $country_code_in_EEC)) {
1833 return 1; // France, Spain, ...
1834 }
1835 return 0;
1836 }
1837
1843 public function needBIC()
1844 {
1845 if (getDolGlobalString('MAIN_IBAN_IS_NEVER_MANDATORY')) {
1846 return 0;
1847 }
1848
1849 $country_code = $this->getCountryCode();
1850
1851 $country_code_in_EEC = array(
1852 'AD', // Andorra
1853 'BH', // Bahrein
1854 'DK', // Denmark
1855 'FR', // France
1856 'GH', // Ghana
1857 'HU', // Hungary
1858 'JP', // Japan
1859 'LV', // Latvia
1860 'SE', // Sweden
1861 );
1862
1863 if (in_array($country_code, $country_code_in_EEC)) {
1864 return 1; // Andorra, Bahrein, ...
1865 }
1866 return 0;
1867 }
1868
1875 public function info($id)
1876 {
1877 }
1878
1893 public function getFieldsToShow($includeibanbic = 0)
1894 {
1895 //Get the required properties depending on the country
1896 $detailedBBAN = $this->useDetailedBBAN();
1897
1898 if ($detailedBBAN == 0) {
1899 $fieldarray = array(
1900 'BankAccountNumber'
1901 );
1902 } elseif ($detailedBBAN == 2) {
1903 $fieldarray = array(
1904 'BankCode',
1905 'BankAccountNumber'
1906 );
1907 } else {
1908 $fieldarray = self::getAccountNumberOrder();
1909 }
1910
1911 //if ($this->needIBAN()) { // return always IBAN and BIC (this was old behaviour)
1912 if ($includeibanbic) {
1913 $fieldarray[] = 'IBAN';
1914 $fieldarray[] = 'BIC';
1915 }
1916 //}
1917
1918 //Get the order the properties are shown
1919 return $fieldarray;
1920 }
1921
1932 public static function getAccountNumberOrder()
1933 {
1934 global $conf;
1935
1936 $fieldlists = array(
1937 'BankCode',
1938 'DeskCode',
1939 'BankAccountNumber',
1940 'BankAccountNumberKey'
1941 );
1942
1943 if (getDolGlobalString('BANK_SHOW_ORDER_OPTION')) {
1944 if (is_numeric(getDolGlobalString('BANK_SHOW_ORDER_OPTION'))) {
1945 if (getDolGlobalString('BANK_SHOW_ORDER_OPTION') == '1') {
1946 $fieldlists = array(
1947 'BankCode',
1948 'DeskCode',
1949 'BankAccountNumberKey',
1950 'BankAccountNumber'
1951 );
1952 }
1953 } else {
1954 //Replace the old AccountNumber key with the new BankAccountNumber key
1955 $fieldlists = explode(
1956 ' ',
1957 preg_replace('/ ?[^Bank]AccountNumber ?/', 'BankAccountNumber', $conf->global->BANK_SHOW_ORDER_OPTION)
1958 );
1959 }
1960 }
1961
1962 return $fieldlists;
1963 }
1964
1965
1973 public function initAsSpecimen()
1974 {
1975 // Example of IBAN FR7630001007941234567890185
1976 $this->specimen = 1;
1977 $this->ref = 'MBA';
1978 $this->label = 'My Big Company Bank account';
1979 $this->courant = Account::TYPE_CURRENT;
1980 $this->clos = Account::STATUS_OPEN;
1981 $this->type = Account::TYPE_CURRENT;
1982 $this->status = Account::STATUS_OPEN;
1983 $this->code_banque = '30001';
1984 $this->code_guichet = '00794';
1985 $this->number = '12345678901';
1986 $this->cle_rib = '85';
1987 $this->bic = 'AA12';
1988 $this->iban = 'FR7630001007941234567890185';
1989
1990 $this->bank = 'MyBank';
1991 $this->address = 'Rue de Paris';
1992 $this->owner_name = 'Owner';
1993 $this->owner_address = 'Owner address';
1994 $this->owner_zip = 'Owner zip';
1995 $this->owner_town = 'Owner town';
1996 $this->owner_country_id = 1;
1997 $this->country_id = 1;
1998
1999 return 1;
2000 }
2001
2010 public static function replaceThirdparty($dbs, $origin_id, $dest_id)
2011 {
2012 $sql = "UPDATE ".MAIN_DB_PREFIX."bank_url SET url_id = ".((int) $dest_id)." WHERE url_id = ".((int) $origin_id)." AND type='company'";
2013
2014 if ($dbs->query($sql)) {
2015 return true;
2016 } else {
2017 //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.
2018 //$this->errors = $dbs->lasterror();
2019 return false;
2020 }
2021 }
2022
2030 public function getKanbanView($option = '', $arraydata = null)
2031 {
2032 global $langs;
2033
2034 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
2035
2036 $return = '<div class="box-flex-item box-flex-grow-zero">';
2037 $return .= '<div class="info-box info-box-sm">';
2038 $return .= '<span class="info-box-icon bg-infobox-action">';
2039 $return .= img_picto('', $this->picto);
2040 $return .= '</span>';
2041 $return .= '<div class="info-box-content">';
2042 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).'</span>';
2043 if ($selected >= 0) {
2044 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
2045 }
2046 if (property_exists($this, 'type_lib')) {
2047 $return .= '<br><span class="info-box-label opacitymedium" title="'.$this->type_lib[$this->type].'">'.substr($this->type_lib[$this->type], 0, 24).'...</span>';
2048 }
2049 if (method_exists($this, 'solde')) {
2050 $return .= '<br><a href="'.DOL_URL_ROOT.'/compta/bank/bankentries_list.php?id='.$this->id.'">';
2051 $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>';
2052 }
2053 if (method_exists($this, 'getLibStatut')) {
2054 $return .= '<br><div class="info-box-status">'.$this->getLibStatut(3).'</div>';
2055 }
2056 $return .= '</div>';
2057 $return .= '</div>';
2058 $return .= '</div>';
2059 return $return;
2060 }
2061}
2062
2063
2064require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
2065
2069class AccountLine extends CommonObjectLine
2070{
2074 public $db;
2075
2079 public $element = 'bank';
2080
2084 public $table_element = 'bank';
2085
2089 public $picto = 'accountline';
2090
2094 public $id;
2095
2099 public $ref;
2100
2106 public $datec;
2107
2113 public $dateo;
2114
2120 public $datev;
2121
2125 public $amount;
2126
2130 public $amount_main_currency;
2131
2135 public $fk_user_author;
2136
2140 public $fk_user_rappro;
2141
2145 public $fk_type;
2146
2150 public $fk_bordereau;
2151
2155 public $fk_account;
2156
2160 public $bank_account_ref;
2161
2165 public $bank_account_label;
2166
2170 public $numero_compte;
2171
2175 public $emetteur;
2176
2180 public $rappro;
2181
2185 public $num_releve;
2186
2190 public $num_chq;
2191
2195 public $bank_chq;
2196
2200 public $label;
2201
2205 public $note;
2206
2212 public $user_rappro;
2213
2214
2220 public function __construct(DoliDB $db)
2221 {
2222 $this->db = $db;
2223 }
2224
2233 public function fetch($rowid, $ref = '', $num = '')
2234 {
2235 // Check parameters
2236 if (empty($rowid) && empty($ref) && empty($num)) {
2237 return -1;
2238 }
2239
2240 $sql = "SELECT b.rowid, b.datec, b.datev, b.dateo, b.amount, b.label as label, b.fk_account,";
2241 $sql .= " b.fk_user_author, b.fk_user_rappro,";
2242 $sql .= " b.fk_type, b.num_releve, b.num_chq, b.rappro, b.note,";
2243 $sql .= " b.fk_bordereau, b.banque, b.emetteur,";
2244 $sql .= " ba.ref as bank_account_ref, ba.label as bank_account_label";
2245 $sql .= " FROM ".MAIN_DB_PREFIX."bank as b,";
2246 $sql .= " ".MAIN_DB_PREFIX."bank_account as ba";
2247 $sql .= " WHERE b.fk_account = ba.rowid";
2248 $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
2249 if ($num) {
2250 $sql .= " AND b.num_chq = '".$this->db->escape($num)."'";
2251 } elseif ($ref) {
2252 $sql .= " AND b.rowid = '".$this->db->escape($ref)."'";
2253 } else {
2254 $sql .= " AND b.rowid = ".((int) $rowid);
2255 }
2256
2257 dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
2258 $result = $this->db->query($sql);
2259 if ($result) {
2260 $ret = 0;
2261
2262 $obj = $this->db->fetch_object($result);
2263 if ($obj) {
2264 $this->id = $obj->rowid;
2265 $this->rowid = $obj->rowid;
2266 $this->ref = $obj->rowid;
2267
2268 $this->datec = $this->db->jdate($obj->datec);
2269 $this->datev = $this->db->jdate($obj->datev);
2270 $this->dateo = $this->db->jdate($obj->dateo);
2271 $this->amount = $obj->amount;
2272 $this->label = $obj->label;
2273 $this->note = $obj->note;
2274
2275 $this->fk_user_author = $obj->fk_user_author;
2276 $this->fk_user_rappro = $obj->fk_user_rappro;
2277
2278 $this->fk_type = $obj->fk_type; // Type of transaction
2279 $this->rappro = (int) $obj->rappro;
2280 $this->num_releve = $obj->num_releve;
2281
2282 $this->num_chq = $obj->num_chq;
2283 $this->bank_chq = $obj->banque;
2284 $this->fk_bordereau = $obj->fk_bordereau;
2285
2286 $this->fk_account = $obj->fk_account;
2287 $this->bank_account_ref = $obj->bank_account_ref;
2288 $this->bank_account_label = $obj->bank_account_label;
2289
2290 // Retrieve all extrafield
2291 // fetch optionals attributes and labels
2292 $this->fetch_optionals();
2293
2294 $ret = 1;
2295 }
2296 $this->db->free($result);
2297 return $ret;
2298 } else {
2299 return -1;
2300 }
2301 }
2302
2308 public function insert()
2309 {
2310 $error = 0;
2311
2312 $this->db->begin();
2313
2314 $sql = "INSERT INTO ".MAIN_DB_PREFIX."bank (";
2315 $sql .= "datec";
2316 $sql .= ", dateo";
2317 $sql .= ", datev";
2318 $sql .= ", label";
2319 $sql .= ", amount";
2320 $sql .= ", amount_main_currency";
2321 $sql .= ", fk_user_author";
2322 $sql .= ", num_chq";
2323 $sql .= ", fk_account";
2324 $sql .= ", fk_type";
2325 $sql .= ", emetteur,banque";
2326 $sql .= ", rappro";
2327 $sql .= ", numero_compte";
2328 $sql .= ", num_releve";
2329 $sql .= ", note";
2330 $sql .= ") VALUES (";
2331 $sql .= "'".$this->db->idate($this->datec)."'";
2332 $sql .= ", '".$this->db->idate($this->dateo)."'";
2333 $sql .= ", '".$this->db->idate($this->datev)."'";
2334 $sql .= ", '".$this->db->escape($this->label)."'";
2335 $sql .= ", ".price2num($this->amount);
2336 $sql .= ", ".(empty($this->amount_main_currency) ? "NULL" : price2num($this->amount_main_currency));
2337 $sql .= ", ".($this->fk_user_author > 0 ? ((int) $this->fk_user_author) : "null");
2338 $sql .= ", ".($this->num_chq ? "'".$this->db->escape($this->num_chq)."'" : "null");
2339 $sql .= ", '".$this->db->escape((string) $this->fk_account)."'";
2340 $sql .= ", '".$this->db->escape($this->fk_type)."'";
2341 $sql .= ", ".($this->emetteur ? "'".$this->db->escape($this->emetteur)."'" : "null");
2342 $sql .= ", ".($this->bank_chq ? "'".$this->db->escape($this->bank_chq)."'" : "null");
2343 $sql .= ", ".(int) $this->rappro;
2344 $sql .= ", ".($this->numero_compte ? "'".$this->db->escape($this->numero_compte)."'" : "''");
2345 $sql .= ", ".($this->num_releve ? "'".$this->db->escape($this->num_releve)."'" : "null");
2346 $sql .= ", ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "null");
2347 $sql .= ")";
2348
2349
2350 dol_syslog(get_class($this)."::insert", LOG_DEBUG);
2351 $resql = $this->db->query($sql);
2352 if ($resql) {
2353 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'bank');
2354 // Actions on extra fields (by external module or standard code)
2355 $result = $this->insertExtraFields();
2356 if ($result < 0) {
2357 $error++;
2358 }
2359 } else {
2360 $error++;
2361 $this->error = $this->db->lasterror();
2362 dol_print_error($this->db);
2363 }
2364
2365 if (!$error) {
2366 $this->db->commit();
2367 return $this->id;
2368 } else {
2369 $this->db->rollback();
2370 return -1 * $error;
2371 }
2372 }
2373
2381 public function delete($user, $notrigger = 0)
2382 {
2383 $nbko = 0;
2384
2385 if ($this->rappro) {
2386 // Protection to avoid any delete of consolidated lines
2387 $this->error = "ErrorDeleteNotPossibleLineIsConsolidated";
2388 return -1;
2389 }
2390
2391 $this->db->begin();
2392
2393 if (!$notrigger) {
2394 // Call trigger
2395 $result = $this->call_trigger('BANKACCOUNTLINE_DELETE', $user);
2396 if ($result < 0) {
2397 $this->db->rollback();
2398 return -1;
2399 }
2400 // End call triggers
2401 }
2402
2403 // Protection to avoid any delete of accounted lines. Protection on by default
2404 if (!getDolGlobalString('BANK_ALLOW_TRANSACTION_DELETION_EVEN_IF_IN_ACCOUNTING')) {
2405 $sql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."accounting_bookkeeping WHERE doc_type = 'bank' AND fk_doc = ".((int) $this->id);
2406 $resql = $this->db->query($sql);
2407 if ($resql) {
2408 $obj = $this->db->fetch_object($resql);
2409 if ($obj && $obj->nb) {
2410 $this->error = 'ErrorRecordAlreadyInAccountingDeletionNotPossible';
2411 $this->db->rollback();
2412 return -1;
2413 }
2414 } else {
2415 $this->error = $this->db->lasterror();
2416 $this->db->rollback();
2417 return -1;
2418 }
2419 }
2420
2421 // Delete urls
2422 $result = $this->delete_urls($user);
2423 if ($result < 0) {
2424 $nbko++;
2425 }
2426
2427 $sql = "DELETE FROM ".MAIN_DB_PREFIX."category_bankline WHERE lineid=".(int) $this->rowid;
2428 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
2429 $result = $this->db->query($sql);
2430 if (!$result) {
2431 $nbko++;
2432 }
2433
2434 $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank_extrafields WHERE fk_object=".(int) $this->rowid;
2435 $result = $this->db->query($sql);
2436 if (!$result) {
2437 $nbko++;
2438 }
2439
2440 $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank WHERE rowid=".(int) $this->rowid;
2441 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
2442 $result = $this->db->query($sql);
2443 if (!$result) {
2444 $nbko++;
2445 }
2446
2447 if (!$nbko) {
2448 $this->db->commit();
2449 return 1;
2450 } else {
2451 $this->db->rollback();
2452 return -$nbko;
2453 }
2454 }
2455
2456
2457 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2464 public function delete_urls($user = null)
2465 {
2466 // phpcs:enable
2467 $nbko = 0;
2468
2469 if ($this->rappro) {
2470 // Protection to avoid any delete of consolidated lines
2471 $this->error = "ErrorDeleteNotPossibleLineIsConsolidated";
2472 return -1;
2473 }
2474
2475 $this->db->begin();
2476
2477 $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank_url WHERE fk_bank=".(int) $this->rowid;
2478 dol_syslog(get_class($this)."::delete_urls", LOG_DEBUG);
2479 $result = $this->db->query($sql);
2480 if (!$result) {
2481 $nbko++;
2482 }
2483
2484 if (!$nbko) {
2485 $this->db->commit();
2486 return 1;
2487 } else {
2488 $this->db->rollback();
2489 return -$nbko;
2490 }
2491 }
2492
2493
2501 public function update(User $user, $notrigger = 0)
2502 {
2503 $this->db->begin();
2504
2505 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2506 $sql .= " amount = ".price2num($this->amount).",";
2507 $sql .= " datev='".$this->db->idate($this->datev)."',";
2508 $sql .= " dateo='".$this->db->idate($this->dateo)."'";
2509 $sql .= " WHERE rowid = ".((int) $this->rowid);
2510
2511 dol_syslog(get_class($this)."::update", LOG_DEBUG);
2512 $resql = $this->db->query($sql);
2513 if ($resql) {
2514 $this->db->commit();
2515 return 1;
2516 } else {
2517 $this->db->rollback();
2518 $this->error = $this->db->error();
2519 return -1;
2520 }
2521 }
2522
2523
2529 public function updateLabel()
2530 {
2531 $this->db->begin();
2532
2533 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2534 $sql .= " label = '".$this->db->escape($this->label)."'";
2535 $sql .= " WHERE rowid = ".((int) $this->rowid);
2536
2537 dol_syslog(get_class($this)."::update_label", LOG_DEBUG);
2538 $resql = $this->db->query($sql);
2539 if ($resql) {
2540 $this->db->commit();
2541 return 1;
2542 } else {
2543 $this->db->rollback();
2544 $this->error = $this->db->error();
2545 return -1;
2546 }
2547 }
2548
2549
2550 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2559 public function update_conciliation(User $user, $cat, $conciliated = 1)
2560 {
2561 // phpcs:enable
2562 global $conf, $langs;
2563
2564 $this->db->begin();
2565
2566 // Check statement field
2567 if (getDolGlobalString('BANK_STATEMENT_REGEX_RULE')) {
2568 if (!preg_match('/' . getDolGlobalString('BANK_STATEMENT_REGEX_RULE').'/', $this->num_releve)) {
2569 $this->errors[] = $langs->trans("ErrorBankStatementNameMustFollowRegex", getDolGlobalString('BANK_STATEMENT_REGEX_RULE'));
2570 return -1;
2571 }
2572 }
2573
2574 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2575 $sql .= " rappro = ".((int) $conciliated);
2576 $sql .= ", num_releve = '".$this->db->escape($this->num_releve)."'";
2577 if ($conciliated) {
2578 $sql .= ", fk_user_rappro = ".((int) $user->id);
2579 }
2580 $sql .= " WHERE rowid = ".((int) $this->id);
2581
2582 dol_syslog(get_class($this)."::update_conciliation", LOG_DEBUG);
2583 $resql = $this->db->query($sql);
2584 if ($resql) {
2585 if (!empty($cat) && $cat > 0) {
2586 $sql = "INSERT INTO ".MAIN_DB_PREFIX."category_bankline (";
2587 $sql .= "lineid";
2588 $sql .= ", fk_categ";
2589 $sql .= ") VALUES (";
2590 $sql .= $this->id;
2591 $sql .= ", ".((int) $cat);
2592 $sql .= ")";
2593
2594 dol_syslog(get_class($this)."::update_conciliation", LOG_DEBUG);
2595 $this->db->query($sql);
2596
2597 // No error check. Can fail if category already affected
2598 // TODO Do no try the insert if link already exists
2599 }
2600
2601 $this->rappro = (int) $conciliated;
2602
2603 $this->db->commit();
2604 return 1;
2605 } else {
2606 $this->db->rollback();
2607 return -1;
2608 }
2609 }
2610
2611
2612 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2620 public function datev_change($rowid, $sign = 1)
2621 {
2622 // phpcs:enable
2623 $sql = "SELECT datev FROM ".MAIN_DB_PREFIX."bank WHERE rowid = ".((int) $rowid);
2624 $resql = $this->db->query($sql);
2625 if ($resql) {
2626 $obj = $this->db->fetch_object($resql);
2627 $newdate = $this->db->jdate($obj->datev) + (3600 * 24 * $sign);
2628
2629 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2630 $sql .= " datev = '".$this->db->idate($newdate)."'";
2631 $sql .= " WHERE rowid = ".((int) $rowid);
2632
2633 $result = $this->db->query($sql);
2634 if ($result) {
2635 if ($this->db->affected_rows($result)) {
2636 return 1;
2637 }
2638 } else {
2639 dol_print_error($this->db);
2640 return 0;
2641 }
2642 } else {
2643 dol_print_error($this->db);
2644 }
2645 return 0;
2646 }
2647
2648 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2655 public function datev_next($id)
2656 {
2657 // phpcs:enable
2658 return $this->datev_change($id, 1);
2659 }
2660
2661 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2668 public function datev_previous($id)
2669 {
2670 // phpcs:enable
2671 return $this->datev_change($id, -1);
2672 }
2673
2674
2675 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2683 public function dateo_change($rowid, $sign = 1)
2684 {
2685 // phpcs:enable
2686 $sql = "SELECT dateo FROM ".MAIN_DB_PREFIX."bank WHERE rowid = ".((int) $rowid);
2687 $resql = $this->db->query($sql);
2688 if ($resql) {
2689 $obj = $this->db->fetch_object($resql);
2690 $newdate = $this->db->jdate($obj->dateo) + (3600 * 24 * $sign);
2691
2692 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2693 $sql .= " dateo = '".$this->db->idate($newdate)."'";
2694 $sql .= " WHERE rowid = ".((int) $rowid);
2695
2696 $result = $this->db->query($sql);
2697 if ($result) {
2698 if ($this->db->affected_rows($result)) {
2699 return 1;
2700 }
2701 } else {
2702 dol_print_error($this->db);
2703 return 0;
2704 }
2705 } else {
2706 dol_print_error($this->db);
2707 }
2708 return 0;
2709 }
2710
2711 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2718 public function dateo_next($id)
2719 {
2720 // phpcs:enable
2721 return $this->dateo_change($id, 1);
2722 }
2723
2724 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2731 public function dateo_previous($id)
2732 {
2733 // phpcs:enable
2734 return $this->dateo_change($id, -1);
2735 }
2736
2737
2744 public function info($id)
2745 {
2746 $sql = 'SELECT b.rowid, b.datec, b.tms as datem,';
2747 $sql .= ' b.fk_user_author, b.fk_user_rappro';
2748 $sql .= ' FROM '.MAIN_DB_PREFIX.'bank as b';
2749 $sql .= ' WHERE b.rowid = '.((int) $id);
2750
2751 $result = $this->db->query($sql);
2752 if ($result) {
2753 if ($this->db->num_rows($result)) {
2754 $obj = $this->db->fetch_object($result);
2755
2756 $this->id = $obj->rowid;
2757
2758 $this->user_creation_id = $obj->fk_user_author;
2759 $this->user_rappro = $obj->fk_user_rappro;
2760 $this->date_creation = $this->db->jdate($obj->datec);
2761 $this->date_modification = $this->db->jdate($obj->datem);
2762 //$this->date_rappro = $obj->daterappro; // Not yet managed
2763 }
2764 $this->db->free($result);
2765 } else {
2766 dol_print_error($this->db);
2767 }
2768 }
2769
2770
2780 public function getNomUrl($withpicto = 0, $maxlen = 0, $option = '', $notooltip = 0)
2781 {
2782 global $conf, $langs;
2783
2784 $result = '';
2785
2786 $label = img_picto('', $this->picto).' <u>'.$langs->trans("BankTransactionLine").'</u>:<br>';
2787 $label .= '<b>'.$langs->trans("Ref").':</b> '.$this->ref;
2788 if ($this->amount) {
2789 $label .= '<br><strong>'.$langs->trans("Amount").':</strong> '.price($this->amount, 0, $langs, 1, -1, -1, $conf->currency);
2790 }
2791
2792 $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">';
2793 $linkend = '</a>';
2794
2795 $result .= $linkstart;
2796 if ($withpicto) {
2797 $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);
2798 }
2799 if ($withpicto != 2) {
2800 $result .= ($this->ref ? $this->ref : $this->id);
2801 }
2802
2803 $result .= $linkend;
2804
2805 if ($option == 'showall' || $option == 'showconciliated' || $option == 'showconciliatedandaccounted') {
2806 $result .= ' <span class="opacitymedium">(';
2807 }
2808 if ($option == 'showall') {
2809 $result .= $langs->trans("BankAccount").': ';
2810 $accountstatic = new Account($this->db);
2811 $accountstatic->id = $this->fk_account;
2812 $accountstatic->ref = $this->bank_account_ref;
2813 $accountstatic->label = $this->bank_account_label;
2814 $result .= $accountstatic->getNomUrl(0).', ';
2815 }
2816 if ($option == 'showall' || $option == 'showconciliated' || $option == 'showconciliatedandaccounted') {
2817 $result .= $langs->trans("BankLineConciliated").': ';
2818 $result .= yn($this->rappro);
2819 }
2820 if (isModEnabled('accounting') && ($option == 'showall' || $option == 'showconciliatedandaccounted')) {
2821 $sql = "SELECT COUNT(rowid) as nb, MAX(piece_num) as banktransactionid FROM ".MAIN_DB_PREFIX."accounting_bookkeeping";
2822 $sql .= " WHERE doc_type = 'bank' AND fk_doc = ".((int) $this->id);
2823 $resql = $this->db->query($sql);
2824 if ($resql) {
2825 $obj = $this->db->fetch_object($resql);
2826 if ($obj && $obj->nb) {
2827 $result .= ' - '.$langs->trans("Accounted").': <span title="'.$langs->trans("TransactionNumShort").' '.$obj->banktransactionid.'">'.yn(1).'</span>';
2828 } else {
2829 $result .= ' - '.$langs->trans("Accounted").': '.yn(0);
2830 }
2831 }
2832 }
2833 if ($option == 'showall' || $option == 'showconciliated' || $option == 'showconciliatedandaccounted') {
2834 $result .= ')</span>';
2835 }
2836
2837 return $result;
2838 }
2839
2840
2847 public function getLibStatut($mode = 0)
2848 {
2849 return $this->LibStatut($this->status, $mode);
2850 }
2851
2852 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2860 public function LibStatut($status, $mode = 0)
2861 {
2862 // phpcs:enable
2863 return '';
2864 }
2865
2872 public function getVentilExportCompta($mode = 0)
2873 {
2874 $alreadydispatched = 0;
2875
2876 $type = 'bank';
2877
2878 $sql = " SELECT ".($mode ? 'DISTINCT piece_num' : 'COUNT(ab.rowid)')." as nb";
2879 $sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab WHERE ab.doc_type = '".$this->db->escape($type)."' AND ab.fk_doc = ".((int) $this->id);
2880 $resql = $this->db->query($sql);
2881 if ($resql) {
2882 $obj = $this->db->fetch_object($resql);
2883 if ($obj) {
2884 $alreadydispatched = $obj->nb;
2885 }
2886 } else {
2887 $this->error = $this->db->lasterror();
2888 return -1;
2889 }
2890
2891 if ($alreadydispatched) {
2892 return $alreadydispatched;
2893 }
2894 return 0;
2895 }
2896}
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