dolibarr 24.0.0-beta
account.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2001-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2003 Jean-Louis Bergamo <jlb@j1b.org>
4 * Copyright (C) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
5 * Copyright (C) 2004 Christophe Combelles <ccomb@free.fr>
6 * Copyright (C) 2005-2010 Regis Houssin <regis.houssin@inodbox.com>
7 * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
8 * Copyright (C) 2015-2016 Marcos García <marcosgdf@gmail.com>
9 * Copyright (C) 2015-2017 Alexandre Spangaro <aspangaro@open-dsi.fr>
10 * Copyright (C) 2016 Ferran Marcet <fmarcet@2byte.es>
11 * Copyright (C) 2019 JC Prieto <jcprieto@virtual20.com><prietojc@gmail.com>
12 * Copyright (C) 2022-2025 Frédéric France <frederic.france@free.fr>
13 * Copyright (C) 2024-2026 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 $ref;
64
70 public $rowid;
71
76 public $label;
77
84 public $courant;
85
90 public $type;
91
96 public $bank;
97
105 public $clos = self::STATUS_OPEN;
106
111 public $rappro = 1;
112
117 public $url;
118
123 public $code_banque;
124
129 public $code_guichet;
130
135 public $number;
136
141 public $cle_rib;
142
147 public $bic;
148
153 public $iban;
154
161 public $iban_prefix;
162
167 public $pti_in_ctti = 0;
168
175 public $proprio;
176
181 public $owner_name;
182
187 public $owner_address;
188
193 public $owner_zip;
194
199 public $owner_town;
203 public $owner_country_id;
207 public $owner_country_code;
208
215 public $domiciliation;
216
221 public $address;
225 public $state_id;
229 public $state_code;
233 public $state;
237 public $country_id;
238
244 public $type_lib = array();
245
250 public $account_number;
251
255 public $fk_accountancy_journal;
256
260 public $accountancy_journal;
261
266 public $currency_code;
267
274 public $account_currency_code;
275
280 public $min_allowed;
281
286 public $min_desired;
287
292 public $comment;
293
298 public $date_solde;
299
306 public $solde;
307
312 public $balance;
313
318 public $ics;
319
324 public $ics_transfer;
325
329 public $oldref;
330
331
356 // BEGIN MODULEBUILDER PROPERTIES
360 public $fields = array(
361 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 10),
362 'ref' => array('type' => 'varchar(12)', 'label' => 'Ref', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'showoncombobox' => 1, 'position' => 25),
363 'label' => array('type' => 'varchar(30)', 'label' => 'Label', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 30),
364 'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => '1', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 35, 'index' => 1),
365 'bank' => array('type' => 'varchar(60)', 'label' => 'Bank', 'enabled' => 1, 'visible' => -1, 'position' => 40),
366 'code_banque' => array('type' => 'varchar(128)', 'label' => 'Code banque', 'enabled' => 1, 'visible' => -1, 'position' => 45),
367 'code_guichet' => array('type' => 'varchar(6)', 'label' => 'Code guichet', 'enabled' => 1, 'visible' => -1, 'position' => 50),
368 'number' => array('type' => 'varchar(255)', 'label' => 'Number', 'enabled' => 1, 'visible' => -1, 'position' => 55),
369 'cle_rib' => array('type' => 'varchar(5)', 'label' => 'Cle rib', 'enabled' => 1, 'visible' => -1, 'position' => 60),
370 'bic' => array('type' => 'varchar(11)', 'label' => 'Bic', 'enabled' => 1, 'visible' => -1, 'position' => 65),
371 'iban_prefix' => array('type' => 'varchar(34)', 'label' => 'Iban prefix', 'enabled' => 1, 'visible' => -1, 'position' => 70),
372 'country_iban' => array('type' => 'varchar(2)', 'label' => 'Country iban', 'enabled' => 1, 'visible' => -1, 'position' => 75),
373 'cle_iban' => array('type' => 'varchar(2)', 'label' => 'Cle iban', 'enabled' => 1, 'visible' => -1, 'position' => 80),
374 'domiciliation' => array('type' => 'varchar(255)', 'label' => 'Domiciliation', 'enabled' => 1, 'visible' => -1, 'position' => 85),
375 'state_id' => array('type' => 'integer', 'label' => 'StateId', 'enabled' => 1, 'visible' => -1, 'position' => 90),
376 'fk_pays' => array('type' => 'integer', 'label' => 'Country', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 95),
377 'proprio' => array('type' => 'varchar(60)', 'label' => 'Proprio', 'enabled' => 1, 'visible' => -1, 'position' => 100),
378 'owner_address' => array('type' => 'varchar(255)', 'label' => 'Owner address', 'enabled' => 1, 'visible' => -1, 'position' => 105),
379 'owner_zip' => array('type' => 'varchar(25)', 'label' => 'Owner zip', 'enabled' => 1, 'visible' => -1, 'position' => 106),
380 'owner_town' => array('type' => 'varchar(50)', 'label' => 'Owner town', 'enabled' => 1, 'visible' => -1, 'position' => 107),
381 'owner_country_id' => array('type' => 'integer', 'label' => 'Owner country', 'enabled' => 1, 'visible' => -1, 'position' => 108),
382 'courant' => array('type' => 'smallint(6)', 'label' => 'Courant', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 110),
383 'clos' => array('type' => 'smallint(6)', 'label' => 'Clos', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 115),
384 'rappro' => array('type' => 'smallint(6)', 'label' => 'Rappro', 'enabled' => 1, 'visible' => -1, 'position' => 120),
385 'url' => array('type' => 'varchar(128)', 'label' => 'Url', 'enabled' => 1, 'visible' => -1, 'position' => 125),
386 'account_number' => array('type' => 'varchar(32)', 'label' => 'Account number', 'enabled' => 1, 'visible' => -1, 'position' => 130),
387 'fk_accountancy_journal' => array('type' => 'integer', 'label' => 'Accountancy journal ID', 'enabled' => 1, 'visible' => -1, 'position' => 132),
388 'accountancy_journal' => array('type' => 'varchar(20)', 'label' => 'Accountancy journal', 'enabled' => 1, 'visible' => -1, 'position' => 135),
389 'currency_code' => array('type' => 'varchar(3)', 'label' => 'Currency code', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 140),
390 'min_allowed' => array('type' => 'integer', 'label' => 'Min allowed', 'enabled' => 1, 'visible' => -1, 'position' => 145),
391 'min_desired' => array('type' => 'integer', 'label' => 'Min desired', 'enabled' => 1, 'visible' => -1, 'position' => 150),
392 'comment' => array('type' => 'text', 'label' => 'Comment', 'enabled' => 1, 'visible' => -1, 'position' => 155),
393 'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -1, 'position' => 156),
394 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 157),
395 'fk_user_author' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserAuthor', 'enabled' => 1, 'visible' => -1, 'position' => 160),
396 'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'position' => 165),
397 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 170),
398 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'visible' => 0, 'position' => 175),
399 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'position' => 180),
400 'extraparams' => array('type' => 'varchar(255)', 'label' => 'Extraparams', 'enabled' => 1, 'visible' => -1, 'position' => 185),
401 );
402 // END MODULEBUILDER PROPERTIES
403
407 const TYPE_CURRENT = 1;
411 const TYPE_CASH = 2;
415 const TYPE_SAVINGS = 0;
416
417
418 const STATUS_OPEN = 0;
419 const STATUS_CLOSED = 1;
420
421
427 public function __construct(DoliDB $db)
428 {
429 global $langs;
430
431 $this->db = $db;
432
433 $this->ismultientitymanaged = 1;
434
435 $this->balance = 0;
436
437 $this->type_lib = array(
438 self::TYPE_SAVINGS => $langs->transnoentitiesnoconv("BankType0"),
439 self::TYPE_CURRENT => $langs->transnoentitiesnoconv("BankType1"),
440 self::TYPE_CASH => $langs->transnoentitiesnoconv("BankType2"),
441 );
442
443 $this->labelStatus = array(
444 self::STATUS_OPEN => $langs->transnoentitiesnoconv("StatusAccountOpened"),
445 self::STATUS_CLOSED => $langs->transnoentitiesnoconv("StatusAccountClosed")
446 );
447 }
448
454 public function __toString()
455 {
456 $string = '';
457 foreach ($this->getFieldsToShow() as $val) {
458 if ($val == 'BankCode') {
459 $string .= $this->code_banque.' ';
460 } elseif ($val == 'BankAccountNumber') {
461 $string .= $this->number.' ';
462 } elseif ($val == 'DeskCode') {
463 $string .= $this->code_guichet.' ';
464 } elseif ($val == 'BankAccountNumberKey') {
465 $string .= $this->cle_rib.' ';
466 } elseif ($val == 'BIC') {
467 $string .= $this->bic.' ';
468 } elseif ($val == 'IBAN') {
469 $string .= $this->iban.' ';
470 }
471 }
472
473 return trim($string);
474 }
475
476
482 public function canBeConciliated()
483 {
484 if (empty($this->rappro)) {
485 return -1;
486 }
487 if ($this->type == Account::TYPE_CASH && !getDolGlobalString('BANK_CAN_RECONCILIATE_CASHACCOUNT')) {
488 return -2;
489 }
490 if ($this->status) {
491 return -3;
492 }
493 return 1;
494 }
495
496
497 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
508 public function add_url_line($line_id, $url_id, $url, $label, $type)
509 {
510 // phpcs:enable
511 $sql = "INSERT INTO ".MAIN_DB_PREFIX."bank_url (";
512 $sql .= "fk_bank";
513 $sql .= ", url_id";
514 $sql .= ", url"; // deprecated
515 $sql .= ", label";
516 $sql .= ", type";
517 $sql .= ") VALUES (";
518 $sql .= ((int) $line_id);
519 $sql .= ", ".((int) $url_id);
520 $sql .= ", '".$this->db->escape($url)."'"; // deprecated
521 $sql .= ", '".$this->db->escape($label)."'";
522 $sql .= ", '".$this->db->escape($type)."'";
523 $sql .= ")";
524
525 dol_syslog(get_class($this)."::add_url_line", LOG_DEBUG);
526 if ($this->db->query($sql)) {
527 $rowid = $this->db->last_insert_id(MAIN_DB_PREFIX."bank_url");
528 return $rowid;
529 } else {
530 $this->error = $this->db->lasterror();
531 return -1;
532 }
533 }
534
535 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
545 public function get_url($fk_bank = 0, $url_id = 0, $type = '')
546 {
547 // phpcs:enable
548 $lines = array();
549
550 // Check parameters
551 if (!empty($fk_bank) && (!empty($url_id) || !empty($type))) {
552 $this->error = "ErrorBadParameter";
553 return -1;
554 }
555
556 $sql = "SELECT fk_bank, url_id, url, label, type";
557 $sql .= " FROM ".MAIN_DB_PREFIX."bank_url";
558 if ($fk_bank > 0) {
559 $sql .= " WHERE fk_bank = ".((int) $fk_bank);
560 } else {
561 $sql .= " WHERE url_id = ".((int) $url_id)." AND type = '".$this->db->escape($type)."'";
562 }
563 $sql .= " ORDER BY type, label";
564
565 dol_syslog(get_class($this)."::get_url", LOG_DEBUG);
566 $result = $this->db->query($sql);
567 if ($result) {
568 $i = 0;
569 $num = $this->db->num_rows($result);
570 while ($i < $num) {
571 $obj = $this->db->fetch_object($result);
572 // Old links (for compatibility)
573 $lines[$i][0] = $obj->url;
574 $lines[$i][1] = $obj->url_id;
575 $lines[$i][2] = $obj->label;
576 $lines[$i][3] = $obj->type;
577 // New links
578 $lines[$i]['url'] = $obj->url;
579 $lines[$i]['url_id'] = $obj->url_id;
580 $lines[$i]['label'] = $obj->label;
581 $lines[$i]['type'] = $obj->type;
582 $lines[$i]['fk_bank'] = $obj->fk_bank;
583 $i++;
584 }
585 } else {
586 dol_print_error($this->db);
587 }
588
589 return $lines;
590 }
591
611 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 = '')
612 {
613 global $langs;
614
615 // Deprecation warning
616 if (is_numeric($oper)) {
617 dol_syslog(__METHOD__.": using numeric operations is deprecated", LOG_WARNING);
618 }
619
620 if (empty($this->id) && !empty($this->rowid)) { // For backward compatibility
621 $this->id = $this->rowid;
622 }
623
624 // Clean parameters
625 $emetteur = trim($emetteur);
626 $banque = trim($banque);
627 $label = trim($label);
628
629 $now = dol_now();
630
631 if (is_numeric($oper)) { // Clean operation to have a code instead of a rowid
632 $sql = "SELECT code FROM ".MAIN_DB_PREFIX."c_paiement";
633 $sql .= " WHERE id = ".((int) $oper);
634 $sql .= " AND entity IN (".getEntity('c_paiement').")";
635 $resql = $this->db->query($sql);
636 if ($resql) {
637 $obj = $this->db->fetch_object($resql);
638 $oper = $obj->code;
639 } else {
640 dol_print_error($this->db, 'Failed to get payment type code');
641 return -1;
642 }
643 }
644
645 // Check parameters
646 if (!$oper) {
647 $this->error = $langs->trans("OperNotDefined");
648 return -1;
649 }
650 if (!$this->id) {
651 $this->error = $langs->trans("ThisIdNotDefined");
652 return -2;
653 }
654 if ($this->type == Account::TYPE_CASH && $oper != 'LIQ') {
655 $this->error = "ErrorCashAccountAcceptsOnlyCashMoney";
656 return -3;
657 }
658
659 $this->db->begin();
660
661 if (is_null($datev) || empty($datev)) {
662 $datev = $date;
663 }
664
665 $accline = new AccountLine($this->db);
666 $accline->datec = $now;
667 $accline->dateo = $date;
668 $accline->datev = $datev;
669 $accline->label = $label;
670 $accline->amount = $amount;
671 $accline->amount_main_currency = $amount_main_currency;
672 $accline->fk_user_author = $user->id;
673 $accline->fk_account = $this->id;
674 $accline->fk_type = $oper;
675 $accline->numero_compte = $accountancycode;
676 $accline->num_releve = $num_releve;
677 $accline->note_private = $note_private;
678
679 if ($num_chq) {
680 $accline->num_chq = $num_chq;
681 }
682
683 if ($emetteur) {
684 $accline->emetteur = $emetteur;
685 }
686
687 if ($banque) {
688 $accline->bank_chq = $banque;
689 }
690
691 if ($accline->insert() > 0) {
692 if ($categorie > 0) {
693 $sql = "INSERT INTO ".MAIN_DB_PREFIX."category_bankline(";
694 $sql .= "lineid, fk_categ";
695 $sql .= ") VALUES (";
696 $sql .= ((int) $accline->id).", ".((int) $categorie);
697 $sql .= ")";
698
699 $result = $this->db->query($sql);
700 if (!$result) {
701 $this->error = $this->db->lasterror();
702 $this->db->rollback();
703
704 return -4;
705 }
706 }
707
708 $this->db->commit();
709
710 return $accline->id;
711 } else {
712 $this->setErrorsFromObject($accline);
713 $this->db->rollback();
714
715 return -5;
716 }
717 }
718
726 public function create($user, $notrigger = 0)
727 {
728 global $langs, $conf;
729
730 $error = 0;
731
732 // Clean parameters
733 if (!$this->min_allowed) {
734 $this->min_allowed = 0;
735 }
736 if (!$this->min_desired) {
737 $this->min_desired = 0;
738 }
739
740 // Check parameters
741 if (empty($this->country_id)) {
742 $langs->load('errors');
743 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Country"));
744 dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
745 return -1;
746 }
747 if (empty($this->ref)) {
748 $langs->load('errors');
749 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Ref"));
750 dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
751 return -1;
752 }
753 if (empty($this->date_solde)) {
754 $langs->load('errors');
755 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("DateInitialBalance"));
756 dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
757 return -1;
758 }
759
760 // Load libraries to check BAN
761 $balance = $this->balance;
762 if (empty($balance) && !empty($this->solde)) {
763 dol_syslog(get_class($this)."::create solde is deprecated use balance", LOG_NOTICE);
764 $balance = $this->solde;
765 }
766 if (empty($balance)) {
767 $balance = 0;
768 }
769 if (empty($this->status && !empty($this->clos))) {
770 dol_syslog(get_class($this)."::create clos is deprecated use status", LOG_NOTICE);
771 $this->status = $this->clos;
772 }
773
774 if (empty($this->country_id) && !empty($this->country_code)) {
775 $country_id = getCountry($this->country_code, '3');
776 $this->country_id = is_int($country_id) ? $country_id : 0;
777 }
778
779 // Load the library to validate/check a BAN account
780 require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
781
782 $now = dol_now();
783
784 $this->db->begin();
785
786 $sql = "INSERT INTO ".MAIN_DB_PREFIX."bank_account (";
787 $sql .= "datec";
788 $sql .= ", ref";
789 $sql .= ", label";
790 $sql .= ", entity";
791 $sql .= ", account_number";
792 $sql .= ", fk_accountancy_journal";
793 $sql .= ", bank";
794 $sql .= ", code_banque";
795 $sql .= ", code_guichet";
796 $sql .= ", number";
797 $sql .= ", cle_rib";
798 $sql .= ", bic";
799 $sql .= ", iban_prefix";
800 $sql .= ", domiciliation";
801 $sql .= ", pti_in_ctti";
802 $sql .= ", proprio";
803 $sql .= ", owner_address";
804 $sql .= ", owner_zip";
805 $sql .= ", owner_town";
806 $sql .= ", owner_country_id";
807 $sql .= ", currency_code";
808 $sql .= ", rappro";
809 $sql .= ", min_allowed";
810 $sql .= ", min_desired";
811 $sql .= ", comment";
812 $sql .= ", state_id";
813 $sql .= ", fk_pays";
814 $sql .= ", ics";
815 $sql .= ", ics_transfer";
816 $sql .= ") VALUES (";
817 $sql .= "'".$this->db->idate($now)."'";
818 $sql .= ", '".$this->db->escape($this->ref)."'";
819 $sql .= ", '".$this->db->escape($this->label)."'";
820 $sql .= ", ".((int) $conf->entity);
821 $sql .= ", '".$this->db->escape($this->account_number)."'";
822 $sql .= ", ".($this->fk_accountancy_journal > 0 ? ((int) $this->fk_accountancy_journal) : "null");
823 $sql .= ", '".$this->db->escape($this->bank)."'";
824 $sql .= ", '".$this->db->escape($this->code_banque)."'";
825 $sql .= ", '".$this->db->escape($this->code_guichet)."'";
826 $sql .= ", '".$this->db->escape($this->number)."'";
827 $sql .= ", '".$this->db->escape($this->cle_rib)."'";
828 $sql .= ", '".$this->db->escape($this->bic)."'";
829 $sql .= ", '".$this->db->escape($this->iban)."'";
830 $sql .= ", '".$this->db->escape($this->address)."'";
831 $sql .= ", ".((int) $this->pti_in_ctti);
832 $sql .= ", '".$this->db->escape($this->owner_name)."'";
833 $sql .= ", '".$this->db->escape($this->owner_address)."'";
834 $sql .= ", '".$this->db->escape($this->owner_zip)."'";
835 $sql .= ", '".$this->db->escape($this->owner_town)."'";
836 $sql .= ", ".($this->owner_country_id > 0 ? ((int) $this->owner_country_id) : "null");
837 $sql .= ", '".$this->db->escape($this->currency_code)."'";
838 $sql .= ", ".((int) $this->rappro);
839 $sql .= ", ".price2num($this->min_allowed, 'MT');
840 $sql .= ", ".price2num($this->min_desired, 'MT');
841 $sql .= ", '".$this->db->escape($this->comment)."'";
842 $sql .= ", ".($this->state_id > 0 ? ((int) $this->state_id) : "null");
843 $sql .= ", ".($this->country_id > 0 ? ((int) $this->country_id) : "null");
844 $sql .= ", '".$this->db->escape($this->ics)."'";
845 $sql .= ", '".$this->db->escape($this->ics_transfer)."'";
846 $sql .= ")";
847
848 dol_syslog(get_class($this)."::create", LOG_DEBUG);
849 $resql = $this->db->query($sql);
850 if ($resql) {
851 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."bank_account");
852
853 $result = $this->update($user, 1);
854 if ($result > 0) {
855 $accline = new AccountLine($this->db);
856 $accline->datec = $now;
857 $accline->label = '('.$langs->trans("InitialBankBalance").')';
858 $accline->amount = (float) price2num($balance);
859 $accline->fk_user_author = $user->id;
860 $accline->fk_account = $this->id;
861 $accline->datev = $this->date_solde;
862 $accline->dateo = $this->date_solde;
863 $accline->fk_type = 'SOLD';
864
865 if ($accline->insert() < 0) {
866 $error++;
867 $this->setErrorsFromObject($accline);
868 }
869
870 if (!$error) {
871 $result = $this->insertExtraFields();
872 if ($result < 0) {
873 $error++;
874 }
875 }
876
877 if (!$error && !$notrigger) {
878 // Call trigger
879 $result = $this->call_trigger('BANKACCOUNT_CREATE', $user);
880 if ($result < 0) {
881 $error++;
882 }
883 // End call triggers
884 }
885 } else {
886 $error++;
887 }
888 } else {
889 if ($this->db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
890 $this->error = $langs->trans("ErrorBankLabelAlreadyExists");
891 $error++;
892 } else {
893 $this->error = $this->db->error()." sql=".$sql;
894 $error++;
895 }
896 }
897
898 if (!$error) {
899 $this->db->commit();
900 return $this->id;
901 } else {
902 $this->db->rollback();
903 return -1 * $error;
904 }
905 }
906
914 public function update($user, $notrigger = 0)
915 {
916 global $langs, $conf;
917
918 if (empty($this->country_id) && !empty($this->country_code)) {
919 $country_id = getCountry($this->country_code, '3');
920 $this->country_id = is_int($country_id) ? $country_id : 0;
921 }
922
923 $error = 0;
924
925 $this->db->begin();
926
927 // Check parameters
928 if (empty($this->country_id)) {
929 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Country"));
930 dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
931 return -1;
932 }
933 if (empty($this->ref)) {
934 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Ref"));
935 dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
936 return -1;
937 }
938 if (!$this->label) {
939 $this->label = "???";
940 }
941
942 $sql = "UPDATE ".MAIN_DB_PREFIX."bank_account SET";
943 $sql .= " ref = '".$this->db->escape($this->ref)."'";
944 $sql .= ",label = '".$this->db->escape($this->label)."'";
945 $sql .= ",courant = ".((int) $this->type);
946 $sql .= ",clos = ".((int) $this->status);
947 $sql .= ",rappro = ".((int) $this->rappro);
948 $sql .= ",url = ".($this->url ? "'".$this->db->escape($this->url)."'" : "null");
949 $sql .= ",account_number = '".$this->db->escape($this->account_number)."'";
950 $sql .= ",fk_accountancy_journal = ".($this->fk_accountancy_journal > 0 ? ((int) $this->fk_accountancy_journal) : "null");
951 $sql .= ",bank = '".$this->db->escape($this->bank)."'";
952 $sql .= ",code_banque='".$this->db->escape($this->code_banque)."'";
953 $sql .= ",code_guichet='".$this->db->escape($this->code_guichet)."'";
954 $sql .= ",number='".$this->db->escape($this->number)."'";
955 $sql .= ",cle_rib='".$this->db->escape($this->cle_rib)."'";
956 $sql .= ",bic='".$this->db->escape($this->bic)."'";
957 $sql .= ",iban_prefix = '".$this->db->escape($this->iban)."'";
958 $sql .= ",domiciliation='".$this->db->escape($this->address)."'";
959 $sql .= ",pti_in_ctti=".((int) $this->pti_in_ctti);
960 $sql .= ",proprio = '".$this->db->escape($this->owner_name)."'";
961 $sql .= ",owner_address = '".$this->db->escape($this->owner_address)."'";
962 $sql .= ",owner_zip = '".$this->db->escape($this->owner_zip)."'";
963 $sql .= ",owner_town = '".$this->db->escape($this->owner_town)."'";
964 $sql .= ",owner_country_id = ".($this->owner_country_id > 0 ? ((int) $this->owner_country_id) : "null");
965
966 $sql .= ",currency_code = '".$this->db->escape($this->currency_code)."'";
967
968 $sql .= ",min_allowed = ".($this->min_allowed != '' ? price2num($this->min_allowed) : "null");
969 $sql .= ",min_desired = ".($this->min_desired != '' ? price2num($this->min_desired) : "null");
970 $sql .= ",comment = '".$this->db->escape($this->comment)."'";
971
972 $sql .= ",state_id = ".($this->state_id > 0 ? ((int) $this->state_id) : "null");
973 $sql .= ",fk_pays = ".($this->country_id > 0 ? ((int) $this->country_id) : "null");
974 $sql .= ",ics = '".$this->db->escape($this->ics)."'";
975 $sql .= ",ics_transfer = '".$this->db->escape($this->ics_transfer)."'";
976
977 $sql .= " WHERE rowid = ".((int) $this->id);
978
979 dol_syslog(get_class($this)."::update", LOG_DEBUG);
980 $result = $this->db->query($sql);
981 if ($result) {
982 // Actions on extra fields (by external module or standard code)
983 if (!$error) {
984 $result = $this->insertExtraFields();
985 if ($result < 0) {
986 $error++;
987 }
988 }
989
990 if (!$error && !empty($this->oldref) && $this->oldref !== $this->ref) {
991 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'bank/".$this->db->escape($this->ref)."'";
992 $sql .= " WHERE filepath = 'bank/".$this->db->escape($this->oldref)."' and src_object_type = 'bank_account' and entity = ".((int) $conf->entity);
993 $resql = $this->db->query($sql);
994 if (!$resql) {
995 $error++;
996 $this->error = $this->db->lasterror();
997 }
998
999 // We rename directory in order not to lose the attachments
1000 $oldref = dol_sanitizeFileName($this->oldref);
1001 $newref = dol_sanitizeFileName($this->ref);
1002 $dirsource = $conf->bank->dir_output.'/'.$oldref;
1003 $dirdest = $conf->bank->dir_output.'/'.$newref;
1004 if (file_exists($dirsource)) {
1005 dol_syslog(get_class($this)."::update rename dir ".$dirsource." into ".$dirdest, LOG_DEBUG);
1006 if (@rename($dirsource, $dirdest)) {
1007 dol_syslog("Rename ok", LOG_DEBUG);
1008 }
1009 }
1010 }
1011
1012 if (!$error && !$notrigger) {
1013 // Call trigger
1014 $result = $this->call_trigger('BANKACCOUNT_MODIFY', $user);
1015 if ($result < 0) {
1016 $error++;
1017 }
1018 // End call triggers
1019 }
1020 } else {
1021 $error++;
1022 $this->error = $this->db->lasterror();
1023 dol_print_error($this->db);
1024 }
1025
1026 if (!$error) {
1027 $this->db->commit();
1028 return $this->id;
1029 } else {
1030 $this->db->rollback();
1031 return -1 * $error;
1032 }
1033 }
1034
1035
1036 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1043 public function update_bban($user = null)
1044 {
1045 // phpcs:enable
1046 global $conf, $langs;
1047
1048 // Load library to get BAN control function
1049 require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1050
1051 dol_syslog(get_class($this)."::update_bban $this->code_banque,$this->code_guichet,$this->number,$this->cle_rib,$this->iban");
1052
1053 // Check parameters
1054 if (!$this->ref) {
1055 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->trans("Ref"));
1056 return -2;
1057 }
1058
1059 $sql = "UPDATE ".MAIN_DB_PREFIX."bank_account SET";
1060 $sql .= " bank = '".$this->db->escape($this->bank)."'";
1061 $sql .= ",code_banque='".$this->db->escape($this->code_banque)."'";
1062 $sql .= ",code_guichet='".$this->db->escape($this->code_guichet)."'";
1063 $sql .= ",number='".$this->db->escape($this->number)."'";
1064 $sql .= ",cle_rib='".$this->db->escape($this->cle_rib)."'";
1065 $sql .= ",bic='".$this->db->escape($this->bic)."'";
1066 $sql .= ",iban_prefix = '".$this->db->escape($this->iban)."'";
1067 $sql .= ",domiciliation='".$this->db->escape($this->address)."'";
1068 $sql .= ",proprio = '".$this->db->escape($this->owner_name)."'";
1069 $sql .= ",owner_address = '".$this->db->escape($this->owner_address)."'";
1070 $sql .= ",owner_zip = '".$this->db->escape($this->owner_zip)."'";
1071 $sql .= ",owner_town = '".$this->db->escape($this->owner_town)."'";
1072 $sql .= ",owner_country_id = ".($this->owner_country_id > 0 ? ((int) $this->owner_country_id) : "null");
1073 $sql .= ",state_id = ".($this->state_id > 0 ? $this->state_id : "null");
1074 $sql .= ",fk_pays = ".($this->country_id > 0 ? $this->country_id : "null");
1075 $sql .= " WHERE rowid = ".((int) $this->id);
1076 $sql .= " AND entity = ".((int) $conf->entity);
1077
1078 dol_syslog(get_class($this)."::update_bban", LOG_DEBUG);
1079
1080 $result = $this->db->query($sql);
1081 if ($result) {
1082 return 1;
1083 } else {
1084 $this->error = $this->db->lasterror();
1085 dol_print_error($this->db);
1086 return -1;
1087 }
1088 }
1089
1090
1098 public function fetch($id, $ref = '')
1099 {
1100 if (empty($id) && empty($ref)) {
1101 $this->error = "ErrorBadParameters";
1102 return -1;
1103 }
1104
1105 $sql = "SELECT ba.rowid, ba.ref, ba.label, ba.bank, ba.number, ba.courant as type, ba.clos as status, ba.rappro, ba.url,";
1106 $sql .= " ba.code_banque, ba.code_guichet, ba.cle_rib, ba.bic, ba.iban_prefix as iban,";
1107 $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,";
1108 $sql .= " ba.account_number, ba.fk_accountancy_journal, ba.currency_code,";
1109 $sql .= " ba.min_allowed, ba.min_desired, ba.comment,";
1110 $sql .= " ba.datec as date_creation, ba.tms as date_modification, ba.ics, ba.ics_transfer,";
1111 $sql .= ' c.code as country_code, c.label as country,';
1112 $sql .= ' d.code_departement as state_code, d.nom as state,';
1113 $sql .= ' aj.code as accountancy_journal';
1114 $sql .= " FROM ".MAIN_DB_PREFIX."bank_account as ba";
1115 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_country as c ON ba.fk_pays = c.rowid';
1116 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_departements as d ON ba.state_id = d.rowid';
1117 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'accounting_journal as aj ON aj.rowid=ba.fk_accountancy_journal';
1118 $sql .= " WHERE ba.entity IN (".getEntity($this->element).")";
1119 if ($id) {
1120 $sql .= " AND ba.rowid = ".((int) $id);
1121 }
1122 if ($ref) {
1123 $sql .= " AND ba.ref = '".$this->db->escape($ref)."'";
1124 }
1125
1126 dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
1127 $result = $this->db->query($sql);
1128 if ($result) {
1129 if ($this->db->num_rows($result)) {
1130 $obj = $this->db->fetch_object($result);
1131
1132 $this->id = $obj->rowid;
1133 $this->rowid = $obj->rowid;
1134 $this->ref = $obj->ref;
1135 $this->label = $obj->label;
1136 $this->type = $obj->type;
1137 $this->courant = $obj->type;
1138 $this->bank = $obj->bank;
1139 $this->clos = $obj->status;
1140 $this->status = $obj->status;
1141 $this->rappro = $obj->rappro;
1142 $this->url = $obj->url;
1143
1144 $this->code_banque = $obj->code_banque;
1145 $this->code_guichet = $obj->code_guichet;
1146 $this->number = $obj->number;
1147 $this->cle_rib = $obj->cle_rib;
1148 $this->bic = $obj->bic;
1149 $this->iban = $obj->iban;
1150 $this->address = $obj->address;
1151
1152 $this->owner_name = $obj->owner_name;
1153 $this->proprio = $this->owner_name;
1154 $this->owner_address = $obj->owner_address;
1155 $this->owner_zip = $obj->owner_zip;
1156 $this->owner_town = $obj->owner_town;
1157 $this->owner_country_id = $obj->owner_country_id;
1158
1159 $this->pti_in_ctti = $obj->pti_in_ctti;
1160
1161 $this->state_id = $obj->state_id;
1162 $this->state_code = $obj->state_code;
1163 $this->state = $obj->state;
1164
1165 $this->country_id = $obj->country_id;
1166 $this->country_code = $obj->country_code;
1167 $this->country = $obj->country;
1168
1169 $this->account_number = $obj->account_number;
1170 $this->fk_accountancy_journal = $obj->fk_accountancy_journal;
1171 $this->accountancy_journal = $obj->accountancy_journal;
1172
1173 $this->currency_code = $obj->currency_code;
1174 $this->account_currency_code = $obj->currency_code;
1175 $this->min_allowed = $obj->min_allowed;
1176 $this->min_desired = $obj->min_desired;
1177 $this->comment = $obj->comment;
1178
1179 $this->date_creation = $this->db->jdate($obj->date_creation);
1180 $this->date_modification = $this->db->jdate($obj->date_modification);
1181
1182 $this->ics = $obj->ics;
1183 $this->ics_transfer = $obj->ics_transfer;
1184
1185 // Retrieve all extrafield
1186 // fetch optionals attributes and labels
1187 $this->fetch_optionals();
1188
1189 return 1;
1190 } else {
1191 return 0;
1192 }
1193 } else {
1194 $this->error = $this->db->lasterror();
1195 $this->errors[] = $this->error;
1196 return -1;
1197 }
1198 }
1199
1210 public function setCategories($categories)
1211 {
1212 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1213 return parent::setCategoriesCommon($categories, Categorie::TYPE_ACCOUNT);
1214 }
1215
1223 public function delete($user, $notrigger = 0)
1224 {
1225 $error = 0;
1226
1227 $this->db->begin();
1228
1229 // @TODO Check there is no child into llx_payment_various, ... to allow deletion ?
1230
1231 // Delete link between tag and bank account
1232 if (!$error) {
1233 $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_account";
1234 $sql .= " WHERE fk_account = ".((int) $this->id);
1235
1236 $resql = $this->db->query($sql);
1237 if (!$resql) {
1238 $error++;
1239 $this->error = "Error ".$this->db->lasterror();
1240 }
1241 }
1242
1243 if (!$error) {
1244 $sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element;
1245 $sql .= " WHERE rowid = ".((int) $this->id);
1246
1247 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1248 $result = $this->db->query($sql);
1249 if ($result) {
1250 // Remove extrafields
1251 if (!$error) {
1252 $result = $this->deleteExtraFields();
1253 if ($result < 0) {
1254 $error++;
1255 dol_syslog(get_class($this)."::delete error -4 ".$this->error, LOG_ERR);
1256 }
1257 }
1258 } else {
1259 $error++;
1260 $this->error = "Error ".$this->db->lasterror();
1261 }
1262 }
1263
1264 if (!$error) {
1265 $this->db->commit();
1266 return 1;
1267 } else {
1268 $this->db->rollback();
1269 return -1;
1270 }
1271 }
1272
1273
1280 public function getLibStatut($mode = 0)
1281 {
1282 return $this->LibStatut($this->status, $mode);
1283 }
1284
1285 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1293 public function LibStatut($status, $mode = 0)
1294 {
1295 // phpcs:enable
1296 global $langs;
1297 $langs->load('banks');
1298
1299 if ($status == self::STATUS_OPEN) {
1300 $label = $langs->transnoentitiesnoconv("StatusAccountOpened");
1301 $labelshort = $langs->transnoentitiesnoconv("StatusAccountOpened");
1302 $statusType = 'status4';
1303 } else {
1304 $label = $langs->transnoentitiesnoconv("StatusAccountClosed");
1305 $labelshort = $langs->transnoentitiesnoconv("StatusAccountClosed");
1306 $statusType = 'status5';
1307 }
1308
1309 return dolGetStatus($label, $labelshort, '', $statusType, $mode);
1310 }
1311
1312
1313 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1319 public function can_be_deleted()
1320 {
1321 // phpcs:enable
1322 $can_be_deleted = false;
1323
1324 $sql = "SELECT COUNT(rowid) as nb";
1325 $sql .= " FROM ".MAIN_DB_PREFIX."bank";
1326 $sql .= " WHERE fk_account = ".((int) $this->id);
1327
1328 $resql = $this->db->query($sql);
1329 if ($resql) {
1330 $obj = $this->db->fetch_object($resql);
1331 if ($obj->nb <= 1) {
1332 $can_be_deleted = true; // Juste le solde
1333 }
1334 } else {
1335 dol_print_error($this->db);
1336 }
1337 return $can_be_deleted;
1338 }
1339
1340
1346 public function error()
1347 {
1348 return $this->error;
1349 }
1350
1359 public function solde($option = 0, $date_end = '', $field = 'dateo')
1360 {
1361 $solde = 0;
1362
1363 $sql = "SELECT sum(amount) as amount";
1364 $sql .= " FROM ".MAIN_DB_PREFIX."bank";
1365 $sql .= " WHERE fk_account = ".((int) $this->id);
1366 if ($option == 1) {
1367 $sql .= " AND ".$this->db->escape($field)." <= '".(!empty($date_end) ? $this->db->idate($date_end) : $this->db->idate(dol_now()))."'";
1368 }
1369
1370 $resql = $this->db->query($sql);
1371 if ($resql) {
1372 if ($this->db->num_rows($resql)) {
1373 $obj = $this->db->fetch_object($resql);
1374 $solde = $obj->amount;
1375 }
1376 $this->db->free($resql);
1377 } else {
1378 $this->errors[] = $this->db->lasterror;
1379 return -1;
1380 }
1381
1382 return (float) price2num($solde, 'MU');
1383 }
1384
1385 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1393 public function load_board(User $user, $filteraccountid = 0)
1394 {
1395 // phpcs:enable
1396 global $conf, $langs;
1397
1398 if ($user->socid) {
1399 return -1; // Protection to prevent calls by external users
1400 }
1401
1402 $sql = "SELECT b.rowid, b.datev as datefin";
1403 $sql .= " FROM ".MAIN_DB_PREFIX."bank as b,";
1404 $sql .= " ".MAIN_DB_PREFIX."bank_account as ba";
1405 $sql .= " WHERE b.rappro=0";
1406 $sql .= " AND b.fk_account = ba.rowid";
1407 $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
1408 $sql .= " AND (ba.rappro = 1 AND ba.courant != " . Account::TYPE_CASH . ")"; // Compte rapprochable
1409 $sql .= " AND clos = 0";
1410 if ($filteraccountid) {
1411 $sql .= " AND ba.rowid = ".((int) $filteraccountid);
1412 }
1413 $resql = $this->db->query($sql);
1414 if ($resql) {
1415 $langs->load("banks");
1416 $now = dol_now();
1417
1418 require_once DOL_DOCUMENT_ROOT.'/core/class/workboardresponse.class.php';
1419
1420 $response = new WorkboardResponse();
1421 $response->warning_delay = $conf->bank->rappro->warning_delay / 60 / 60 / 24;
1422 $response->label = $langs->trans("TransactionsToConciliate");
1423 $response->labelShort = $langs->trans("TransactionsToConciliateShort");
1424 $response->url = DOL_URL_ROOT.'/compta/bank/list.php?leftmenu=bank&amp;mainmenu=bank';
1425 $response->img = img_object('', "payment");
1426
1427 while ($obj = $this->db->fetch_object($resql)) {
1428 $response->nbtodo++;
1429 if ((int) $this->db->jdate($obj->datefin) < ($now - $conf->bank->rappro->warning_delay)) {
1430 $response->nbtodolate++;
1431 }
1432 }
1433 return $response;
1434 } else {
1435 dol_print_error($this->db);
1436 $this->error = $this->db->error();
1437 return -1;
1438 }
1439 }
1440
1447 public function loadStateBoard($filteraccountid = 0)
1448 {
1449 global $user;
1450
1451 if ($user->socid) {
1452 return -1; // Protection to prevent calls by external users
1453 }
1454
1455 $sql = "SELECT count(b.rowid) as nb";
1456 $sql .= " FROM ".MAIN_DB_PREFIX."bank as b,";
1457 $sql .= " ".MAIN_DB_PREFIX."bank_account as ba";
1458 $sql .= " WHERE b.fk_account = ba.rowid";
1459 $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
1460 $sql .= " AND (ba.rappro = 1 AND ba.courant != 2)"; // Compte rapprochable
1461 $sql .= " AND clos = 0";
1462 if ($filteraccountid) {
1463 $sql .= " AND ba.rowid = ".((int) $filteraccountid);
1464 }
1465
1466 $resql = $this->db->query($sql);
1467 if ($resql) {
1468 while ($obj = $this->db->fetch_object($resql)) {
1469 $this->nb["banklines"] = $obj->nb;
1470 }
1471 $this->db->free($resql);
1472 return 1;
1473 } else {
1474 dol_print_error($this->db);
1475 $this->error = $this->db->error();
1476 return -1;
1477 }
1478 }
1479
1480
1486 public function countAccountToReconcile()
1487 {
1488 global $user;
1489
1490 //Protection against external users
1491 if ($user->socid) {
1492 return 0;
1493 }
1494
1495 $nb = 0;
1496
1497 $sql = "SELECT COUNT(ba.rowid) as nb";
1498 $sql .= " FROM ".MAIN_DB_PREFIX."bank_account as ba";
1499 $sql .= " WHERE ba.rappro > 0 and ba.clos = 0";
1500 $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
1501 if (!getDolGlobalString('BANK_CAN_RECONCILIATE_CASHACCOUNT')) {
1502 $sql .= " AND ba.courant != " . Account::TYPE_CASH;
1503 }
1504
1505 $resql = $this->db->query($sql);
1506 if ($resql) {
1507 $obj = $this->db->fetch_object($resql);
1508 $nb = (int) $obj->nb;
1509 } else {
1510 dol_print_error($this->db);
1511 }
1512
1513 return $nb;
1514 }
1515
1524 public function getTooltipContentArray($params)
1525 {
1526 global $langs;
1527 $langs->loadLangs(['banks', 'compta']);
1528 include_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1529
1530 $datas = array();
1531
1532 $nofetch = !empty($params['nofetch']);
1533 $pictos = img_picto('', $this->picto).' <u class="paddingrightnow">'.$langs->trans("BankAccount").'</u>';
1534 if (isset($this->status)) {
1535 $pictos .= ' '.$this->getLibStatut(5);
1536 }
1537 $datas['picto'] = $pictos;
1538 $datas['ref'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
1539 $datas['label'] = '<br><b>'.$langs->trans('Label').':</b> '.$this->label;
1540 $datas['accountnumber'] = '<br><br><b>'.$langs->trans('AccountNumber').':</b> '.$this->number;
1541 $datas['iban'] = '<br><b>'.$langs->trans('IBAN').':</b> '.getIbanHumanReadable($this);
1542 $datas['bic'] = '<br><b>'.$langs->trans('BIC').':</b> '.$this->bic;
1543 $datas['accountcurrency'] = '<br><br><b>'.$langs->trans("AccountCurrency").':</b> '.$this->currency_code;
1544
1545 if (isModEnabled('accounting')) {
1546 include_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
1547 $langs->load("accountancy");
1548 $datas['accountaccounting'] = '<br><b>'.$langs->trans('AccountAccounting').':</b> '.length_accountg($this->account_number);
1549 $datas['accountancyjournal'] = '<br><b>'.$langs->trans('AccountancyJournal').':</b> '.$this->accountancy_journal;
1550 }
1551 // show categories for this record only in ajax to not overload lists
1552 if (isModEnabled('category') && !$nofetch) {
1553 require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
1554 $form = new Form($this->db);
1555 $datas['categories'] = '<br>' . $form->showCategories($this->id, Categorie::TYPE_ACCOUNT, 1);
1556 }
1557
1558 return $datas;
1559 }
1560
1572 public function getNomUrl($withpicto = 0, $mode = '', $option = '', $save_lastsearch_value = -1, $notooltip = 0, $morecss = '')
1573 {
1574 global $conf, $langs;
1575
1576 if (!empty($conf->dol_no_mouse_hover)) {
1577 $notooltip = 1; // Force disable tooltips
1578 }
1579
1580 include_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1581
1582 $result = '';
1583 $classfortooltip = 'classfortooltip';
1584 $dataparams = '';
1585 $params = [
1586 'id' => $this->id,
1587 'objecttype' => $this->element,
1588 'option' => $option,
1589 'nofetch' => 1,
1590 ];
1591 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1592 $classfortooltip = 'classforajaxtooltip';
1593 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
1594 $label = '';
1595 } else {
1596 $label = implode($this->getTooltipContentArray($params));
1597 }
1598
1599 $url = DOL_URL_ROOT.'/compta/bank/card.php?id='.$this->id;
1600 if ($mode == 'transactions') {
1601 $url = DOL_URL_ROOT.'/compta/bank/bankentries_list.php?id='.$this->id;
1602 } elseif ($mode == 'receipts') {
1603 $url = DOL_URL_ROOT.'/compta/bank/releve.php?account='.$this->id;
1604 }
1605
1606 if ($option != 'nolink') {
1607 // Add param to save lastsearch_values or not
1608 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1609 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1610 $add_save_lastsearch_values = 1;
1611 }
1612 if ($add_save_lastsearch_values) {
1613 $url .= '&save_lastsearch_values=1';
1614 }
1615 }
1616
1617 $linkclose = '';
1618 if (empty($notooltip)) {
1619 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1620 $label = $langs->trans("BankAccount");
1621 $linkclose .= ' alt="'.dolPrintHTMLForAttribute($label).'"';
1622 }
1623 $linkclose .= ($label ? ' title="'.dolPrintHTMLForAttribute($label).'"' : ' title="tocomplete"');
1624 $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
1625 } else {
1626 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1627 }
1628
1629 if ($option == 'nolink' || empty($url)) {
1630 $linkstart = '<span';
1631 } else {
1632 $linkstart = '<a href="'.$url.'"';
1633 }
1634 $linkstart .= $linkclose.'>';
1635 if ($option == 'nolink' || empty($url)) {
1636 $linkend = '</span>';
1637 } else {
1638 $linkend = '</a>';
1639 }
1640
1641 $result .= $linkstart;
1642
1643 if ($withpicto) {
1644 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"'), 0, 0, $notooltip ? 0 : 1);
1645 }
1646 if ($withpicto != 2) {
1647 $result .= $this->ref.($option == 'reflabel' && $this->label ? ' - '.$this->label : '');
1648 }
1649 $result .= $linkend;
1650
1651 return $result;
1652 }
1653
1654
1655 // Method after here are common to Account and CompanyBankAccount
1656
1657
1663 public function verif()
1664 {
1665 require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1666
1667 $error = 0;
1668
1669 // Call functions to check BAN
1670 if (!checkIbanForAccount($this)) {
1671 $error++;
1672 $this->error = 'IBANNotValid';
1673 }
1674 // Call function to check Swift/BIC.
1675 // A non valid BIC/Swift is a problem if: it is not empty or always a problem if WITHDRAWAL_WITHOUT_BIC is not set).
1676 if (!checkSwiftForAccount($this) && (!empty($this->bic) || !getDolGlobalInt('WITHDRAWAL_WITHOUT_BIC'))) {
1677 $error++;
1678 $this->error = 'SwiftNotValid';
1679 }
1680
1681 if (! $error) {
1682 return 1;
1683 } else {
1684 return 0;
1685 }
1686 }
1687
1693 public function getCountryCode()
1694 {
1695 global $mysoc;
1696
1697 // We return country code of bank account
1698 if (!empty($this->country_code)) {
1699 return $this->country_code;
1700 }
1701
1702 // For backward compatibility, we try to guess country from other information
1703 if (!empty($this->iban)) {
1704 // If IBAN defined, we can know country of account from it
1705 $reg = array();
1706 if (preg_match("/^([a-zA-Z][a-zA-Z])/i", $this->iban, $reg)) {
1707 return $reg[1];
1708 }
1709 }
1710
1711 // If this class is linked to a third party
1712 if (!empty($this->socid)) {
1713 require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
1714 $company = new Societe($this->db);
1715 $result = $company->fetch($this->socid);
1716 if (!empty($company->country_code)) {
1717 return $company->country_code;
1718 }
1719 }
1720
1721 // We return country code of managed company
1722 if (!empty($mysoc->country_code)) {
1723 return $mysoc->country_code;
1724 }
1725
1726 return '';
1727 }
1728
1736 public function getBannerAddress($htmlkey, $object)
1737 {
1738 global $conf, $langs;
1739
1740 $out = '';
1741
1742 $outdone = 0;
1743 $coords = $this->getFullAddress(1, ', ', getDolGlobalInt('MAIN_SHOW_REGION_IN_STATE_SELECT'));
1744 if ($coords) {
1745 if (!empty($conf->use_javascript_ajax)) {
1746 // hideonsmatphone because copyToClipboard call jquery dialog that does not work with jmobile
1747 $out .= '<a href="#" class="hideonsmartphone" onclick="return copyToClipboard(\''.dol_escape_js($coords).'\',\''.dol_escape_js($langs->trans("HelpCopyToClipboard")).'\');">';
1748 $out .= img_picto($langs->trans("Address"), 'map-marker-alt');
1749 $out .= '</a> ';
1750 }
1751 $address = dol_print_address($coords, 'address_'.$htmlkey.'_'.$this->id, $this->element, $this->id, 1, ', ');
1752 if ($address) {
1753 $out .= $address;
1754 $outdone++;
1755 }
1756 $outdone++;
1757 }
1758
1759 return $out;
1760 }
1761
1762
1771 public function useDetailedBBAN()
1772 {
1773 $country_code = $this->getCountryCode();
1774
1775 if (in_array($country_code, array('FR', 'ES', 'GA', 'IT', 'NC'))) {
1776 return 1; // France, Spain, Gabon, ... - Not valid for CH
1777 }
1778 if (in_array($country_code, array('AD', 'AU', 'BE', 'CA', 'DE', 'DK', 'GR', 'GB', 'ID', 'IE', 'IR', 'KR', 'NL', 'NZ', 'UK', 'US'))) {
1779 return 2; // Australia, England...
1780 }
1781 return 0;
1782 }
1783
1789 public function needIBAN()
1790 {
1791 global $conf;
1792
1793 if (getDolGlobalString('MAIN_IBAN_IS_NEVER_MANDATORY')) {
1794 return 0;
1795 }
1796
1797 $country_code = $this->getCountryCode();
1798
1799 $country_code_in_EEC = array(
1800 'AT', // Austria
1801 'BE', // Belgium
1802 'BG', // Bulgaria
1803 'CY', // Cyprus
1804 'CZ', // Czech republic
1805 'DE', // Germany
1806 'DK', // Danemark
1807 'EE', // Estonia
1808 'ES', // Spain
1809 'FI', // Finland
1810 'FR', // France
1811 'GB', // United Kingdom
1812 'GR', // Greece
1813 'HR', // Croatia
1814 'NL', // Holland
1815 'HU', // Hungary
1816 'IE', // Ireland
1817 'IM', // Isle of Man - Included in UK
1818 'IT', // Italy
1819 'LT', // Lithuania
1820 'LU', // Luxembourg
1821 'LV', // Latvia
1822 'MC', // Monaco - Included in France
1823 'MT', // Malta
1824 //'NO', // Norway
1825 'PL', // Poland
1826 'PT', // Portugal
1827 'RO', // Romania
1828 'SE', // Sweden
1829 'SK', // Slovakia
1830 'SI', // Slovenia
1831 'UK', // United Kingdom
1832 //'CH', // Switzerland - No. Swizerland in not in EEC
1833 );
1834
1835 if (in_array($country_code, $country_code_in_EEC)) {
1836 return 1; // France, Spain, ...
1837 }
1838 return 0;
1839 }
1840
1846 public function needBIC()
1847 {
1848 if (getDolGlobalString('MAIN_IBAN_IS_NEVER_MANDATORY')) {
1849 return 0;
1850 }
1851
1852 $country_code = $this->getCountryCode();
1853
1854 $country_code_in_EEC = array(
1855 'AD', // Andorra
1856 'BH', // Bahrein
1857 'DK', // Denmark
1858 'FR', // France
1859 'GH', // Ghana
1860 'HU', // Hungary
1861 'JP', // Japan
1862 'LV', // Latvia
1863 'SE', // Sweden
1864 );
1865
1866 if (in_array($country_code, $country_code_in_EEC)) {
1867 return 1; // Andorra, Bahrein, ...
1868 }
1869 return 0;
1870 }
1871
1878 public function info($id)
1879 {
1880 }
1881
1896 public function getFieldsToShow($includeibanbic = 0)
1897 {
1898 //Get the required properties depending on the country
1899 $detailedBBAN = $this->useDetailedBBAN();
1900
1901 if ($detailedBBAN == 0) {
1902 $fieldarray = array(
1903 'BankAccountNumber'
1904 );
1905 } elseif ($detailedBBAN == 2) {
1906 $fieldarray = array(
1907 'BankCode',
1908 'BankAccountNumber'
1909 );
1910 } else {
1911 $fieldarray = self::getAccountNumberOrder();
1912 }
1913
1914 //if ($this->needIBAN()) { // return always IBAN and BIC (this was old behaviour)
1915 if ($includeibanbic) {
1916 $fieldarray[] = 'IBAN';
1917 $fieldarray[] = 'BIC';
1918 }
1919 //}
1920
1921 //Get the order the properties are shown
1922 return $fieldarray;
1923 }
1924
1935 public static function getAccountNumberOrder()
1936 {
1937 global $conf;
1938
1939 $fieldlists = array(
1940 'BankCode',
1941 'DeskCode',
1942 'BankAccountNumber',
1943 'BankAccountNumberKey'
1944 );
1945
1946 if (getDolGlobalString('BANK_SHOW_ORDER_OPTION')) {
1947 if (is_numeric(getDolGlobalString('BANK_SHOW_ORDER_OPTION'))) {
1948 if (getDolGlobalString('BANK_SHOW_ORDER_OPTION') == '1') {
1949 $fieldlists = array(
1950 'BankCode',
1951 'DeskCode',
1952 'BankAccountNumberKey',
1953 'BankAccountNumber'
1954 );
1955 }
1956 } else {
1957 //Replace the old AccountNumber key with the new BankAccountNumber key
1958 $fieldlists = explode(
1959 ' ',
1960 preg_replace('/ ?[^Bank]AccountNumber ?/', 'BankAccountNumber', $conf->global->BANK_SHOW_ORDER_OPTION)
1961 );
1962 }
1963 }
1964
1965 return $fieldlists;
1966 }
1967
1968
1976 public function initAsSpecimen()
1977 {
1978 // Example of IBAN FR7630001007941234567890185
1979 $this->specimen = 1;
1980 $this->ref = 'MBA';
1981 $this->label = 'My Big Company Bank account';
1982 $this->clos = Account::STATUS_OPEN;
1983 $this->type = Account::TYPE_CURRENT;
1984 $this->status = Account::STATUS_OPEN;
1985 $this->code_banque = '30001';
1986 $this->code_guichet = '00794';
1987 $this->number = '12345678901';
1988 $this->cle_rib = '85';
1989 $this->bic = 'AA12';
1990 $this->iban = 'FR7630001007941234567890185';
1991
1992 $this->bank = 'MyBank';
1993 $this->address = 'Rue de Paris';
1994 $this->owner_name = 'Owner';
1995 $this->owner_address = 'Owner address';
1996 $this->owner_zip = 'Owner zip';
1997 $this->owner_town = 'Owner town';
1998 $this->owner_country_id = 1;
1999 $this->country_id = 1;
2000
2001 return 1;
2002 }
2003
2012 public static function replaceThirdparty($dbs, $origin_id, $dest_id)
2013 {
2014 $sql = "UPDATE ".MAIN_DB_PREFIX."bank_url SET url_id = ".((int) $dest_id)." WHERE url_id = ".((int) $origin_id)." AND type = 'company'";
2015
2016 if ($dbs->query($sql)) {
2017 return true;
2018 } else {
2019 //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.
2020 //$this->errors = $dbs->lasterror();
2021 return false;
2022 }
2023 }
2024
2032 public function getKanbanView($option = '', $arraydata = null)
2033 {
2034 global $langs;
2035
2036 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
2037
2038 $return = '<div class="box-flex-item box-flex-grow-zero">';
2039 $return .= '<div class="info-box info-box-sm">';
2040 $return .= '<span class="info-box-icon bg-infobox-action">';
2041 $return .= img_picto('', $this->picto);
2042 $return .= '</span>';
2043 $return .= '<div class="info-box-content">';
2044 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).'</span>';
2045 if ($selected >= 0) {
2046 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
2047 }
2048 if (property_exists($this, 'type_lib')) {
2049 $return .= '<br><span class="info-box-label opacitymedium" title="'.$this->type_lib[$this->type].'">'.substr($this->type_lib[$this->type], 0, 24).'...</span>';
2050 }
2051 if (method_exists($this, 'solde')) {
2052 $return .= '<br><a href="'.DOL_URL_ROOT.'/compta/bank/bankentries_list.php?id='.$this->id.'">';
2053 $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>';
2054 }
2055 if (method_exists($this, 'getLibStatut')) {
2056 $return .= '<br><div class="info-box-status">'.$this->getLibStatut(3).'</div>';
2057 }
2058 $return .= '</div>';
2059 $return .= '</div>';
2060 $return .= '</div>';
2061 return $return;
2062 }
2063}
2064
2065
2066require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
2067
2071class AccountLine extends CommonObjectLine
2072{
2076 public $db;
2077
2081 public $element = 'bank';
2082
2086 public $table_element = 'bank';
2087
2091 public $picto = 'accountline';
2092
2096 public $id;
2097
2101 public $ref;
2102
2108 public $datec;
2109
2115 public $dateo;
2116
2122 public $datev;
2123
2127 public $amount;
2128
2132 public $amount_main_currency;
2133
2137 public $fk_user_author;
2138
2142 public $fk_user_rappro;
2143
2147 public $fk_type;
2148
2152 public $fk_bordereau;
2153
2157 public $fk_account;
2158
2162 public $bank_account_ref;
2163
2167 public $bank_account_label;
2168
2172 public $numero_compte;
2173
2177 public $emetteur;
2178
2182 public $rappro;
2183
2187 public $num_releve;
2188
2192 public $num_chq;
2193
2197 public $bank_chq;
2198
2202 public $label;
2203
2207 public $note;
2208
2214 public $user_rappro;
2215
2216
2222 public function __construct(DoliDB $db)
2223 {
2224 $this->db = $db;
2225 }
2226
2235 public function fetch($rowid, $ref = '', $num = '')
2236 {
2237 // Check parameters
2238 if (empty($rowid) && empty($ref) && empty($num)) {
2239 return -1;
2240 }
2241
2242 $sql = "SELECT b.rowid, b.datec, b.datev, b.dateo, b.amount, b.label as label, b.fk_account,";
2243 $sql .= " b.fk_user_author, b.fk_user_rappro,";
2244 $sql .= " b.fk_type, b.num_releve, b.num_chq, b.rappro, b.note,";
2245 $sql .= " b.fk_bordereau, b.banque, b.emetteur,";
2246 $sql .= " ba.ref as bank_account_ref, ba.label as bank_account_label";
2247 $sql .= " FROM ".MAIN_DB_PREFIX."bank as b,";
2248 $sql .= " ".MAIN_DB_PREFIX."bank_account as ba";
2249 $sql .= " WHERE b.fk_account = ba.rowid";
2250 $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
2251 if ($num) {
2252 $sql .= " AND b.num_chq = '".$this->db->escape($num)."'";
2253 } elseif ($ref) {
2254 $sql .= " AND b.rowid = '".$this->db->escape($ref)."'";
2255 } else {
2256 $sql .= " AND b.rowid = ".((int) $rowid);
2257 }
2258
2259 dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
2260 $result = $this->db->query($sql);
2261 if ($result) {
2262 $ret = 0;
2263
2264 $obj = $this->db->fetch_object($result);
2265 if ($obj) {
2266 $this->id = $obj->rowid;
2267 $this->rowid = $obj->rowid;
2268 $this->ref = $obj->rowid;
2269
2270 $this->datec = $this->db->jdate($obj->datec);
2271 $this->datev = $this->db->jdate($obj->datev);
2272 $this->dateo = $this->db->jdate($obj->dateo);
2273 $this->amount = $obj->amount;
2274 $this->label = $obj->label;
2275 $this->note = $obj->note;
2276
2277 $this->fk_user_author = $obj->fk_user_author;
2278 $this->fk_user_rappro = $obj->fk_user_rappro;
2279
2280 $this->fk_type = $obj->fk_type; // Type of transaction
2281 $this->rappro = (int) $obj->rappro;
2282 $this->num_releve = $obj->num_releve;
2283
2284 $this->num_chq = $obj->num_chq;
2285 $this->bank_chq = $obj->banque;
2286 $this->fk_bordereau = $obj->fk_bordereau;
2287
2288 $this->fk_account = $obj->fk_account;
2289 $this->bank_account_ref = $obj->bank_account_ref;
2290 $this->bank_account_label = $obj->bank_account_label;
2291
2292 // Retrieve all extrafield
2293 // fetch optionals attributes and labels
2294 $this->fetch_optionals();
2295
2296 $ret = 1;
2297 }
2298 $this->db->free($result);
2299 return $ret;
2300 } else {
2301 return -1;
2302 }
2303 }
2304
2310 public function insert()
2311 {
2312 $error = 0;
2313
2314 $this->db->begin();
2315
2316 $sql = "INSERT INTO ".MAIN_DB_PREFIX."bank (";
2317 $sql .= "datec";
2318 $sql .= ", dateo";
2319 $sql .= ", datev";
2320 $sql .= ", label";
2321 $sql .= ", amount";
2322 $sql .= ", amount_main_currency";
2323 $sql .= ", fk_user_author";
2324 $sql .= ", num_chq";
2325 $sql .= ", fk_account";
2326 $sql .= ", fk_type";
2327 $sql .= ", emetteur,banque";
2328 $sql .= ", rappro";
2329 $sql .= ", numero_compte";
2330 $sql .= ", num_releve";
2331 $sql .= ", note";
2332 $sql .= ") VALUES (";
2333 $sql .= "'".$this->db->idate($this->datec)."'";
2334 $sql .= ", '".$this->db->idate($this->dateo)."'";
2335 $sql .= ", '".$this->db->idate($this->datev)."'";
2336 $sql .= ", '".$this->db->escape($this->label)."'";
2337 $sql .= ", ".price2num($this->amount);
2338 $sql .= ", ".(empty($this->amount_main_currency) ? "NULL" : price2num($this->amount_main_currency));
2339 $sql .= ", ".($this->fk_user_author > 0 ? ((int) $this->fk_user_author) : "null");
2340 $sql .= ", ".($this->num_chq ? "'".$this->db->escape($this->num_chq)."'" : "null");
2341 $sql .= ", '".$this->db->escape((string) $this->fk_account)."'";
2342 $sql .= ", '".$this->db->escape($this->fk_type)."'";
2343 $sql .= ", ".($this->emetteur ? "'".$this->db->escape($this->emetteur)."'" : "null");
2344 $sql .= ", ".($this->bank_chq ? "'".$this->db->escape($this->bank_chq)."'" : "null");
2345 $sql .= ", ".(int) $this->rappro;
2346 $sql .= ", ".($this->numero_compte ? "'".$this->db->escape($this->numero_compte)."'" : "''");
2347 $sql .= ", ".($this->num_releve ? "'".$this->db->escape($this->num_releve)."'" : "null");
2348 $sql .= ", ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "null");
2349 $sql .= ")";
2350
2351
2352 dol_syslog(get_class($this)."::insert", LOG_DEBUG);
2353 $resql = $this->db->query($sql);
2354 if ($resql) {
2355 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'bank');
2356 // Actions on extra fields (by external module or standard code)
2357 $result = $this->insertExtraFields();
2358 if ($result < 0) {
2359 $error++;
2360 }
2361 } else {
2362 $error++;
2363 $this->error = $this->db->lasterror();
2364 dol_print_error($this->db);
2365 }
2366
2367 if (!$error) {
2368 $this->db->commit();
2369 return $this->id;
2370 } else {
2371 $this->db->rollback();
2372 return -1 * $error;
2373 }
2374 }
2375
2383 public function delete($user, $notrigger = 0)
2384 {
2385 $nbko = 0;
2386
2387 if ($this->rappro) {
2388 // Protection to avoid any delete of consolidated lines
2389 $this->error = "ErrorDeleteNotPossibleLineIsConsolidated";
2390 return -1;
2391 }
2392
2393 $this->db->begin();
2394
2395 if (!$notrigger) {
2396 // Call trigger
2397 $result = $this->call_trigger('BANKACCOUNTLINE_DELETE', $user);
2398 if ($result < 0) {
2399 $this->db->rollback();
2400 return -1;
2401 }
2402 // End call triggers
2403 }
2404
2405 // Protection to avoid any delete of accounted lines. Protection on by default
2406 if (!getDolGlobalString('BANK_ALLOW_TRANSACTION_DELETION_EVEN_IF_IN_ACCOUNTING')) {
2407 $sql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."accounting_bookkeeping WHERE doc_type = 'bank' AND fk_doc = ".((int) $this->id);
2408 $resql = $this->db->query($sql);
2409 if ($resql) {
2410 $obj = $this->db->fetch_object($resql);
2411 if ($obj && $obj->nb) {
2412 $this->error = 'ErrorRecordAlreadyInAccountingDeletionNotPossible';
2413 $this->db->rollback();
2414 return -1;
2415 }
2416 } else {
2417 $this->error = $this->db->lasterror();
2418 $this->db->rollback();
2419 return -1;
2420 }
2421 }
2422
2423 // Delete urls
2424 $result = $this->delete_urls($user);
2425 if ($result < 0) {
2426 $nbko++;
2427 }
2428
2429 $sql = "DELETE FROM ".MAIN_DB_PREFIX."category_bankline WHERE lineid=".(int) $this->rowid;
2430 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
2431 $result = $this->db->query($sql);
2432 if (!$result) {
2433 $nbko++;
2434 }
2435
2436 $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank_extrafields WHERE fk_object=".(int) $this->rowid;
2437 $result = $this->db->query($sql);
2438 if (!$result) {
2439 $nbko++;
2440 }
2441
2442 $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank WHERE rowid=".(int) $this->rowid;
2443 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
2444 $result = $this->db->query($sql);
2445 if (!$result) {
2446 $nbko++;
2447 }
2448
2449 if (!$nbko) {
2450 $this->db->commit();
2451 return 1;
2452 } else {
2453 $this->db->rollback();
2454 return -$nbko;
2455 }
2456 }
2457
2458
2459 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2466 public function delete_urls($user = null)
2467 {
2468 // phpcs:enable
2469 $nbko = 0;
2470
2471 if ($this->rappro) {
2472 // Protection to avoid any delete of consolidated lines
2473 $this->error = "ErrorDeleteNotPossibleLineIsConsolidated";
2474 return -1;
2475 }
2476
2477 $this->db->begin();
2478
2479 $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank_url WHERE fk_bank=".(int) $this->rowid;
2480 dol_syslog(get_class($this)."::delete_urls", LOG_DEBUG);
2481 $result = $this->db->query($sql);
2482 if (!$result) {
2483 $nbko++;
2484 }
2485
2486 if (!$nbko) {
2487 $this->db->commit();
2488 return 1;
2489 } else {
2490 $this->db->rollback();
2491 return -$nbko;
2492 }
2493 }
2494
2495
2503 public function update(User $user, $notrigger = 0)
2504 {
2505 $this->db->begin();
2506
2507 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2508 $sql .= " amount = ".price2num($this->amount).",";
2509 $sql .= " datev='".$this->db->idate($this->datev)."',";
2510 $sql .= " dateo='".$this->db->idate($this->dateo)."'";
2511 $sql .= " WHERE rowid = ".((int) $this->rowid);
2512
2513 dol_syslog(get_class($this)."::update", LOG_DEBUG);
2514 $resql = $this->db->query($sql);
2515 if ($resql) {
2516 $this->db->commit();
2517 return 1;
2518 } else {
2519 $this->db->rollback();
2520 $this->error = $this->db->error();
2521 return -1;
2522 }
2523 }
2524
2525
2531 public function updateLabel()
2532 {
2533 $this->db->begin();
2534
2535 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2536 $sql .= " label = '".$this->db->escape($this->label)."'";
2537 $sql .= " WHERE rowid = ".((int) $this->rowid);
2538
2539 dol_syslog(get_class($this)."::update_label", LOG_DEBUG);
2540 $resql = $this->db->query($sql);
2541 if ($resql) {
2542 $this->db->commit();
2543 return 1;
2544 } else {
2545 $this->db->rollback();
2546 $this->error = $this->db->error();
2547 return -1;
2548 }
2549 }
2550
2551
2552 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2561 public function update_conciliation(User $user, $cat, $conciliated = 1)
2562 {
2563 // phpcs:enable
2564 global $conf, $langs;
2565
2566 $this->db->begin();
2567
2568 // Check statement field
2569 if (getDolGlobalString('BANK_STATEMENT_REGEX_RULE')) {
2570 if (!preg_match('/' . getDolGlobalString('BANK_STATEMENT_REGEX_RULE').'/', $this->num_releve)) {
2571 $this->errors[] = $langs->trans("ErrorBankStatementNameMustFollowRegex", getDolGlobalString('BANK_STATEMENT_REGEX_RULE'));
2572 return -1;
2573 }
2574 }
2575
2576 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2577 $sql .= " rappro = ".((int) $conciliated);
2578 $sql .= ", num_releve = '".$this->db->escape($this->num_releve)."'";
2579 if ($conciliated) {
2580 $sql .= ", fk_user_rappro = ".((int) $user->id);
2581 }
2582 $sql .= " WHERE rowid = ".((int) $this->id);
2583
2584 dol_syslog(get_class($this)."::update_conciliation", LOG_DEBUG);
2585 $resql = $this->db->query($sql);
2586 if ($resql) {
2587 if (!empty($cat) && $cat > 0) {
2588 $sql = "INSERT INTO ".MAIN_DB_PREFIX."category_bankline (";
2589 $sql .= "lineid";
2590 $sql .= ", fk_categ";
2591 $sql .= ") VALUES (";
2592 $sql .= $this->id;
2593 $sql .= ", ".((int) $cat);
2594 $sql .= ")";
2595
2596 dol_syslog(get_class($this)."::update_conciliation", LOG_DEBUG);
2597 $this->db->query($sql);
2598
2599 // No error check. Can fail if category already affected
2600 // TODO Do no try the insert if link already exists
2601 }
2602
2603 $this->rappro = (int) $conciliated;
2604
2605 $this->db->commit();
2606 return 1;
2607 } else {
2608 $this->db->rollback();
2609 return -1;
2610 }
2611 }
2612
2613
2614 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2622 public function datev_change($rowid, $sign = 1)
2623 {
2624 // phpcs:enable
2625 $sql = "SELECT datev FROM ".MAIN_DB_PREFIX."bank WHERE rowid = ".((int) $rowid);
2626 $resql = $this->db->query($sql);
2627 if ($resql) {
2628 $obj = $this->db->fetch_object($resql);
2629 $newdate = (int) $this->db->jdate($obj->datev) + (3600 * 24 * $sign);
2630
2631 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2632 $sql .= " datev = '".$this->db->idate($newdate)."'";
2633 $sql .= " WHERE rowid = ".((int) $rowid);
2634
2635 $result = $this->db->query($sql);
2636 if ($result) {
2637 if ($this->db->affected_rows($result)) {
2638 return 1;
2639 }
2640 } else {
2641 dol_print_error($this->db);
2642 return 0;
2643 }
2644 } else {
2645 dol_print_error($this->db);
2646 }
2647 return 0;
2648 }
2649
2650 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2657 public function datev_next($id)
2658 {
2659 // phpcs:enable
2660 return $this->datev_change($id, 1);
2661 }
2662
2663 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2670 public function datev_previous($id)
2671 {
2672 // phpcs:enable
2673 return $this->datev_change($id, -1);
2674 }
2675
2676
2677 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2685 public function dateo_change($rowid, $sign = 1)
2686 {
2687 // phpcs:enable
2688 $sql = "SELECT dateo FROM ".MAIN_DB_PREFIX."bank WHERE rowid = ".((int) $rowid);
2689 $resql = $this->db->query($sql);
2690 if ($resql) {
2691 $obj = $this->db->fetch_object($resql);
2692 $newdate = (int) $this->db->jdate($obj->dateo) + (3600 * 24 * $sign);
2693
2694 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2695 $sql .= " dateo = '".$this->db->idate($newdate)."'";
2696 $sql .= " WHERE rowid = ".((int) $rowid);
2697
2698 $result = $this->db->query($sql);
2699 if ($result) {
2700 if ($this->db->affected_rows($result)) {
2701 return 1;
2702 }
2703 } else {
2704 dol_print_error($this->db);
2705 return 0;
2706 }
2707 } else {
2708 dol_print_error($this->db);
2709 }
2710 return 0;
2711 }
2712
2713 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2720 public function dateo_next($id)
2721 {
2722 // phpcs:enable
2723 return $this->dateo_change($id, 1);
2724 }
2725
2726 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2733 public function dateo_previous($id)
2734 {
2735 // phpcs:enable
2736 return $this->dateo_change($id, -1);
2737 }
2738
2739
2746 public function info($id)
2747 {
2748 $sql = 'SELECT b.rowid, b.datec, b.tms as datem,';
2749 $sql .= ' b.fk_user_author, b.fk_user_rappro';
2750 $sql .= ' FROM '.MAIN_DB_PREFIX.'bank as b';
2751 $sql .= ' WHERE b.rowid = '.((int) $id);
2752
2753 $result = $this->db->query($sql);
2754 if ($result) {
2755 if ($this->db->num_rows($result)) {
2756 $obj = $this->db->fetch_object($result);
2757
2758 $this->id = $obj->rowid;
2759
2760 $this->user_creation_id = $obj->fk_user_author;
2761 $this->user_rappro = $obj->fk_user_rappro;
2762 $this->date_creation = $this->db->jdate($obj->datec);
2763 $this->date_modification = $this->db->jdate($obj->datem);
2764 //$this->date_rappro = $obj->daterappro; // Not yet managed
2765 }
2766 $this->db->free($result);
2767 } else {
2768 dol_print_error($this->db);
2769 }
2770 }
2771
2772
2782 public function getNomUrl($withpicto = 0, $maxlen = 0, $option = '', $notooltip = 0)
2783 {
2784 global $conf, $langs;
2785
2786 $result = '';
2787
2788 $label = img_picto('', $this->picto).' <u>'.$langs->trans("BankTransactionLine").'</u>:<br>';
2789 $label .= '<b>'.$langs->trans("Ref").':</b> '.$this->ref;
2790 if ($this->amount) {
2791 $label .= '<br><strong>'.$langs->trans("Amount").':</strong> '.price($this->amount, 0, $langs, 1, -1, -1, $conf->currency);
2792 }
2793
2794 $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">';
2795 $linkend = '</a>';
2796
2797 $result .= $linkstart;
2798 if ($withpicto) {
2799 $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);
2800 }
2801 if ($withpicto != 2) {
2802 $result .= ($this->ref ? $this->ref : $this->id);
2803 }
2804
2805 $result .= $linkend;
2806
2807 if ($option == 'showall' || $option == 'showconciliated' || $option == 'showconciliatedandaccounted') {
2808 $result .= ' <span class="opacitymedium">(';
2809 }
2810 if ($option == 'showall') {
2811 $result .= $langs->trans("BankAccount").': ';
2812 $accountstatic = new Account($this->db);
2813 $accountstatic->id = $this->fk_account;
2814 $accountstatic->ref = $this->bank_account_ref;
2815 $accountstatic->label = $this->bank_account_label;
2816 $result .= $accountstatic->getNomUrl(0).', ';
2817 }
2818 if ($option == 'showall' || $option == 'showconciliated' || $option == 'showconciliatedandaccounted') {
2819 $result .= $langs->trans("BankLineConciliated").': ';
2820 $result .= yn($this->rappro);
2821 }
2822 if (isModEnabled('accounting') && ($option == 'showall' || $option == 'showconciliatedandaccounted')) {
2823 $sql = "SELECT COUNT(rowid) as nb, MAX(piece_num) as banktransactionid FROM ".MAIN_DB_PREFIX."accounting_bookkeeping";
2824 $sql .= " WHERE doc_type = 'bank' AND fk_doc = ".((int) $this->id);
2825 $resql = $this->db->query($sql);
2826 if ($resql) {
2827 $obj = $this->db->fetch_object($resql);
2828 if ($obj && $obj->nb) {
2829 $result .= ' - '.$langs->trans("Accounted").': <span title="'.$langs->trans("TransactionNumShort").' '.$obj->banktransactionid.'">'.yn(1).'</span>';
2830 } else {
2831 $result .= ' - '.$langs->trans("Accounted").': '.yn(0);
2832 }
2833 }
2834 }
2835 if ($option == 'showall' || $option == 'showconciliated' || $option == 'showconciliatedandaccounted') {
2836 $result .= ')</span>';
2837 }
2838
2839 return $result;
2840 }
2841
2842
2849 public function getLibStatut($mode = 0)
2850 {
2851 return $this->LibStatut($this->status, $mode);
2852 }
2853
2854 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2862 public function LibStatut($status, $mode = 0)
2863 {
2864 // phpcs:enable
2865 return '';
2866 }
2867
2874 public function getVentilExportCompta($mode = 0)
2875 {
2876 $alreadydispatched = 0;
2877
2878 $type = 'bank';
2879
2880 $sql = " SELECT ".($mode ? 'DISTINCT piece_num' : 'COUNT(ab.rowid)')." as nb";
2881 $sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab WHERE ab.doc_type = '".$this->db->escape($type)."' AND ab.fk_doc = ".((int) $this->id);
2882 $resql = $this->db->query($sql);
2883 if ($resql) {
2884 $obj = $this->db->fetch_object($resql);
2885 if ($obj) {
2886 $alreadydispatched = $obj->nb;
2887 }
2888 } else {
2889 $this->error = $this->db->lasterror();
2890 return -1;
2891 }
2892
2893 if ($alreadydispatched) {
2894 return $alreadydispatched;
2895 }
2896 return 0;
2897 }
2898}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
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:390
getIbanHumanReadable(Account $account)
Returns the iban human readable.
Definition bank.lib.php:415
checkSwiftForAccount($account=null, $swift=null)
Check SWIFT information for a bank account.
Definition bank.lib.php:369
$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.
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:168
getCountry($searchkey, $withcode='', $dbtouse=null, $outputlangs=null, $entconv=1, $searchlabel='')
Return country label, code or id from an id, code or label.
global $mysoc
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_now($mode='gmt')
Return date for now.
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_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
div refaddress div address
print $langs trans('Date')." left Ref Label right Qty right Price right TotalHT right TotalTTC right right right right right right right right right centpercent right TotalHT right n right VAT right n right TotalVAT right n No sujeto a RE IRPF right TotalLT1 right n right TotalLT2 right n right TotalTTC right n takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency right TotalTTC takeposcustomercurrency right takeposcustomercurrency n right Paid right PaymentTypeShortLIQ right SELECT p pos_change as p datep as p p num_paiement as f pf amount as amount
Definition receipt.php:489
if(preg_match('/(crypted|dolcrypt):/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
Definition repair.php:130