dolibarr 25.0.0-alpha
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 // Avoid uk_bank_url collision when the same target (line_id, url_id, type) is linked twice
512 // e.g. two distinct credit transfers for the same employee dispatched on the same bank line.
513 $sqlcheck = "SELECT rowid FROM ".MAIN_DB_PREFIX."bank_url";
514 $sqlcheck .= " WHERE fk_bank = ".((int) $line_id);
515 $sqlcheck .= " AND url_id = ".((int) $url_id);
516 $sqlcheck .= " AND type = '".$this->db->escape($type)."'";
517 $resqlcheck = $this->db->query($sqlcheck);
518 if ($resqlcheck) {
519 $obj = $this->db->fetch_object($resqlcheck);
520 if ($obj) {
521 $this->db->free($resqlcheck);
522 return (int) $obj->rowid;
523 }
524 $this->db->free($resqlcheck);
525 }
526
527 $sql = "INSERT INTO ".MAIN_DB_PREFIX."bank_url (";
528 $sql .= "fk_bank";
529 $sql .= ", url_id";
530 $sql .= ", url"; // deprecated
531 $sql .= ", label";
532 $sql .= ", type";
533 $sql .= ") VALUES (";
534 $sql .= ((int) $line_id);
535 $sql .= ", ".((int) $url_id);
536 $sql .= ", '".$this->db->escape($url)."'"; // deprecated
537 $sql .= ", '".$this->db->escape($label)."'";
538 $sql .= ", '".$this->db->escape($type)."'";
539 $sql .= ")";
540
541 dol_syslog(get_class($this)."::add_url_line", LOG_DEBUG);
542 if ($this->db->query($sql)) {
543 $rowid = $this->db->last_insert_id(MAIN_DB_PREFIX."bank_url");
544 return $rowid;
545 } else {
546 $this->error = $this->db->lasterror();
547 return -1;
548 }
549 }
550
551 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
561 public function get_url($fk_bank = 0, $url_id = 0, $type = '')
562 {
563 // phpcs:enable
564 $lines = array();
565
566 // Check parameters
567 if (!empty($fk_bank) && (!empty($url_id) || !empty($type))) {
568 $this->error = "ErrorBadParameter";
569 return -1;
570 }
571
572 $sql = "SELECT fk_bank, url_id, url, label, type";
573 $sql .= " FROM ".MAIN_DB_PREFIX."bank_url";
574 if ($fk_bank > 0) {
575 $sql .= " WHERE fk_bank = ".((int) $fk_bank);
576 } else {
577 $sql .= " WHERE url_id = ".((int) $url_id)." AND type = '".$this->db->escape($type)."'";
578 }
579 $sql .= " ORDER BY type, label";
580
581 dol_syslog(get_class($this)."::get_url", LOG_DEBUG);
582 $result = $this->db->query($sql);
583 if ($result) {
584 $i = 0;
585 $num = $this->db->num_rows($result);
586 while ($i < $num) {
587 $obj = $this->db->fetch_object($result);
588 // Old links (for compatibility)
589 $lines[$i][0] = $obj->url;
590 $lines[$i][1] = $obj->url_id;
591 $lines[$i][2] = $obj->label;
592 $lines[$i][3] = $obj->type;
593 // New links
594 $lines[$i]['url'] = $obj->url;
595 $lines[$i]['url_id'] = $obj->url_id;
596 $lines[$i]['label'] = $obj->label;
597 $lines[$i]['type'] = $obj->type;
598 $lines[$i]['fk_bank'] = $obj->fk_bank;
599 $i++;
600 }
601 } else {
602 dol_print_error($this->db);
603 }
604
605 return $lines;
606 }
607
627 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 = '')
628 {
629 global $langs;
630
631 // Deprecation warning
632 if (is_numeric($oper)) {
633 dol_syslog(__METHOD__.": using numeric operations is deprecated", LOG_WARNING);
634 }
635
636 if (empty($this->id) && !empty($this->rowid)) { // For backward compatibility
637 $this->id = $this->rowid;
638 }
639
640 // Clean parameters
641 $emetteur = trim($emetteur);
642 $banque = trim($banque);
643 $label = trim($label);
644
645 $now = dol_now();
646
647 if (is_numeric($oper)) { // Clean operation to have a code instead of a rowid
648 $sql = "SELECT code FROM ".MAIN_DB_PREFIX."c_paiement";
649 $sql .= " WHERE id = ".((int) $oper);
650 $sql .= " AND entity IN (".getEntity('c_paiement').")";
651 $resql = $this->db->query($sql);
652 if ($resql) {
653 $obj = $this->db->fetch_object($resql);
654 $oper = $obj->code;
655 } else {
656 dol_print_error($this->db, 'Failed to get payment type code');
657 return -1;
658 }
659 }
660
661 // Check parameters
662 if (!$oper) {
663 $this->error = $langs->trans("OperNotDefined");
664 return -1;
665 }
666 if (!$this->id) {
667 $this->error = $langs->trans("ThisIdNotDefined");
668 return -2;
669 }
670 if ($this->type == Account::TYPE_CASH && $oper != 'LIQ') {
671 $this->error = "ErrorCashAccountAcceptsOnlyCashMoney";
672 return -3;
673 }
674
675 $this->db->begin();
676
677 if (is_null($datev) || empty($datev)) {
678 $datev = $date;
679 }
680
681 $accline = new AccountLine($this->db);
682 $accline->datec = $now;
683 $accline->dateo = $date;
684 $accline->datev = $datev;
685 $accline->label = $label;
686 $accline->amount = $amount;
687 $accline->amount_main_currency = $amount_main_currency;
688 $accline->fk_user_author = $user->id;
689 $accline->fk_account = $this->id;
690 $accline->fk_type = $oper;
691 $accline->numero_compte = $accountancycode;
692 $accline->num_releve = $num_releve;
693 $accline->note_private = $note_private;
694
695 if ($num_chq) {
696 $accline->num_chq = $num_chq;
697 }
698
699 if ($emetteur) {
700 $accline->emetteur = $emetteur;
701 }
702
703 if ($banque) {
704 $accline->bank_chq = $banque;
705 }
706
707 if ($accline->insert() > 0) {
708 if ($categorie > 0) {
709 $sql = "INSERT INTO ".MAIN_DB_PREFIX."category_bankline(";
710 $sql .= "lineid, fk_categ";
711 $sql .= ") VALUES (";
712 $sql .= ((int) $accline->id).", ".((int) $categorie);
713 $sql .= ")";
714
715 $result = $this->db->query($sql);
716 if (!$result) {
717 $this->error = $this->db->lasterror();
718 $this->db->rollback();
719
720 return -4;
721 }
722 }
723
724 $this->db->commit();
725
726 return $accline->id;
727 } else {
728 $this->setErrorsFromObject($accline);
729 $this->db->rollback();
730
731 return -5;
732 }
733 }
734
742 public function create($user, $notrigger = 0)
743 {
744 global $langs, $conf;
745
746 $error = 0;
747
748 // Clean parameters
749 if (!$this->min_allowed) {
750 $this->min_allowed = 0;
751 }
752 if (!$this->min_desired) {
753 $this->min_desired = 0;
754 }
755
756 // Check parameters
757 if (empty($this->country_id)) {
758 $langs->load('errors');
759 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Country"));
760 dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
761 return -1;
762 }
763 if (empty($this->ref)) {
764 $langs->load('errors');
765 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Ref"));
766 dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
767 return -1;
768 }
769 if (empty($this->date_solde)) {
770 $langs->load('errors');
771 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("DateInitialBalance"));
772 dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
773 return -1;
774 }
775
776 // Load libraries to check BAN
777 $balance = $this->balance;
778 if (empty($balance) && !empty($this->solde)) {
779 dol_syslog(get_class($this)."::create solde is deprecated use balance", LOG_NOTICE);
780 $balance = $this->solde;
781 }
782 if (empty($balance)) {
783 $balance = 0;
784 }
785 if (empty($this->status && !empty($this->clos))) {
786 dol_syslog(get_class($this)."::create clos is deprecated use status", LOG_NOTICE);
787 $this->status = $this->clos;
788 }
789
790 if (empty($this->country_id) && !empty($this->country_code)) {
791 $country_id = getCountry($this->country_code, '3');
792 $this->country_id = is_int($country_id) ? $country_id : 0;
793 }
794
795 // Load the library to validate/check a BAN account
796 require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
797
798 $now = dol_now();
799
800 $this->db->begin();
801
802 $sql = "INSERT INTO ".MAIN_DB_PREFIX."bank_account (";
803 $sql .= "datec";
804 $sql .= ", ref";
805 $sql .= ", label";
806 $sql .= ", entity";
807 $sql .= ", account_number";
808 $sql .= ", fk_accountancy_journal";
809 $sql .= ", bank";
810 $sql .= ", code_banque";
811 $sql .= ", code_guichet";
812 $sql .= ", number";
813 $sql .= ", cle_rib";
814 $sql .= ", bic";
815 $sql .= ", iban_prefix";
816 $sql .= ", domiciliation";
817 $sql .= ", pti_in_ctti";
818 $sql .= ", proprio";
819 $sql .= ", owner_address";
820 $sql .= ", owner_zip";
821 $sql .= ", owner_town";
822 $sql .= ", owner_country_id";
823 $sql .= ", currency_code";
824 $sql .= ", rappro";
825 $sql .= ", min_allowed";
826 $sql .= ", min_desired";
827 $sql .= ", comment";
828 $sql .= ", state_id";
829 $sql .= ", fk_pays";
830 $sql .= ", ics";
831 $sql .= ", ics_transfer";
832 $sql .= ") VALUES (";
833 $sql .= "'".$this->db->idate($now)."'";
834 $sql .= ", '".$this->db->escape($this->ref)."'";
835 $sql .= ", '".$this->db->escape($this->label)."'";
836 $sql .= ", ".((int) $conf->entity);
837 $sql .= ", '".$this->db->escape($this->account_number)."'";
838 $sql .= ", ".($this->fk_accountancy_journal > 0 ? ((int) $this->fk_accountancy_journal) : "null");
839 $sql .= ", '".$this->db->escape($this->bank)."'";
840 $sql .= ", '".$this->db->escape($this->code_banque)."'";
841 $sql .= ", '".$this->db->escape($this->code_guichet)."'";
842 $sql .= ", '".$this->db->escape($this->number)."'";
843 $sql .= ", '".$this->db->escape($this->cle_rib)."'";
844 $sql .= ", '".$this->db->escape($this->bic)."'";
845 $sql .= ", '".$this->db->escape($this->iban)."'";
846 $sql .= ", '".$this->db->escape($this->address)."'";
847 $sql .= ", ".((int) $this->pti_in_ctti);
848 $sql .= ", '".$this->db->escape($this->owner_name)."'";
849 $sql .= ", '".$this->db->escape($this->owner_address)."'";
850 $sql .= ", '".$this->db->escape($this->owner_zip)."'";
851 $sql .= ", '".$this->db->escape($this->owner_town)."'";
852 $sql .= ", ".($this->owner_country_id > 0 ? ((int) $this->owner_country_id) : "null");
853 $sql .= ", '".$this->db->escape($this->currency_code)."'";
854 $sql .= ", ".((int) $this->rappro);
855 $sql .= ", ".price2num($this->min_allowed, 'MT');
856 $sql .= ", ".price2num($this->min_desired, 'MT');
857 $sql .= ", '".$this->db->escape($this->comment)."'";
858 $sql .= ", ".($this->state_id > 0 ? ((int) $this->state_id) : "null");
859 $sql .= ", ".($this->country_id > 0 ? ((int) $this->country_id) : "null");
860 $sql .= ", '".$this->db->escape($this->ics)."'";
861 $sql .= ", '".$this->db->escape($this->ics_transfer)."'";
862 $sql .= ")";
863
864 dol_syslog(get_class($this)."::create", LOG_DEBUG);
865 $resql = $this->db->query($sql);
866 if ($resql) {
867 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."bank_account");
868
869 $result = $this->update($user, 1);
870 if ($result > 0) {
871 $accline = new AccountLine($this->db);
872 $accline->datec = $now;
873 $accline->label = '('.$langs->trans("InitialBankBalance").')';
874 $accline->amount = (float) price2num($balance);
875 $accline->fk_user_author = $user->id;
876 $accline->fk_account = $this->id;
877 $accline->datev = $this->date_solde;
878 $accline->dateo = $this->date_solde;
879 $accline->fk_type = 'SOLD';
880
881 if ($accline->insert() < 0) {
882 $error++;
883 $this->setErrorsFromObject($accline);
884 }
885
886 if (!$error) {
887 $result = $this->insertExtraFields();
888 if ($result < 0) {
889 $error++;
890 }
891 }
892
893 if (!$error && !$notrigger) {
894 // Call trigger
895 $result = $this->call_trigger('BANKACCOUNT_CREATE', $user);
896 if ($result < 0) {
897 $error++;
898 }
899 // End call triggers
900 }
901 } else {
902 $error++;
903 }
904 } else {
905 if ($this->db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
906 $this->error = $langs->trans("ErrorBankLabelAlreadyExists");
907 $error++;
908 } else {
909 $this->error = $this->db->error()." sql=".$sql;
910 $error++;
911 }
912 }
913
914 if (!$error) {
915 $this->db->commit();
916 return $this->id;
917 } else {
918 $this->db->rollback();
919 return -1 * $error;
920 }
921 }
922
930 public function update($user, $notrigger = 0)
931 {
932 global $langs, $conf;
933
934 if (empty($this->country_id) && !empty($this->country_code)) {
935 $country_id = getCountry($this->country_code, '3');
936 $this->country_id = is_int($country_id) ? $country_id : 0;
937 }
938
939 $error = 0;
940
941 $this->db->begin();
942
943 // Check parameters
944 if (empty($this->country_id)) {
945 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Country"));
946 dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
947 return -1;
948 }
949 if (empty($this->ref)) {
950 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Ref"));
951 dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
952 return -1;
953 }
954 if (!$this->label) {
955 $this->label = "???";
956 }
957
958 $sql = "UPDATE ".MAIN_DB_PREFIX."bank_account SET";
959 $sql .= " ref = '".$this->db->escape($this->ref)."'";
960 $sql .= ",label = '".$this->db->escape($this->label)."'";
961 $sql .= ",courant = ".((int) $this->type);
962 $sql .= ",clos = ".((int) $this->status);
963 $sql .= ",rappro = ".((int) $this->rappro);
964 $sql .= ",url = ".($this->url ? "'".$this->db->escape($this->url)."'" : "null");
965 $sql .= ",account_number = '".$this->db->escape($this->account_number)."'";
966 $sql .= ",fk_accountancy_journal = ".($this->fk_accountancy_journal > 0 ? ((int) $this->fk_accountancy_journal) : "null");
967 $sql .= ",bank = '".$this->db->escape($this->bank)."'";
968 $sql .= ",code_banque='".$this->db->escape($this->code_banque)."'";
969 $sql .= ",code_guichet='".$this->db->escape($this->code_guichet)."'";
970 $sql .= ",number='".$this->db->escape($this->number)."'";
971 $sql .= ",cle_rib='".$this->db->escape($this->cle_rib)."'";
972 $sql .= ",bic='".$this->db->escape($this->bic)."'";
973 $sql .= ",iban_prefix = '".$this->db->escape($this->iban)."'";
974 $sql .= ",domiciliation='".$this->db->escape($this->address)."'";
975 $sql .= ",pti_in_ctti=".((int) $this->pti_in_ctti);
976 $sql .= ",proprio = '".$this->db->escape($this->owner_name)."'";
977 $sql .= ",owner_address = '".$this->db->escape($this->owner_address)."'";
978 $sql .= ",owner_zip = '".$this->db->escape($this->owner_zip)."'";
979 $sql .= ",owner_town = '".$this->db->escape($this->owner_town)."'";
980 $sql .= ",owner_country_id = ".($this->owner_country_id > 0 ? ((int) $this->owner_country_id) : "null");
981
982 $sql .= ",currency_code = '".$this->db->escape($this->currency_code)."'";
983
984 $sql .= ",min_allowed = ".($this->min_allowed != '' ? price2num($this->min_allowed) : "null");
985 $sql .= ",min_desired = ".($this->min_desired != '' ? price2num($this->min_desired) : "null");
986 $sql .= ",comment = '".$this->db->escape($this->comment)."'";
987
988 $sql .= ",state_id = ".($this->state_id > 0 ? ((int) $this->state_id) : "null");
989 $sql .= ",fk_pays = ".($this->country_id > 0 ? ((int) $this->country_id) : "null");
990 $sql .= ",ics = '".$this->db->escape($this->ics)."'";
991 $sql .= ",ics_transfer = '".$this->db->escape($this->ics_transfer)."'";
992
993 $sql .= " WHERE rowid = ".((int) $this->id);
994
995 dol_syslog(get_class($this)."::update", LOG_DEBUG);
996 $result = $this->db->query($sql);
997 if ($result) {
998 // Actions on extra fields (by external module or standard code)
999 if (!$error) {
1000 $result = $this->insertExtraFields();
1001 if ($result < 0) {
1002 $error++;
1003 }
1004 }
1005
1006 if (!$error && !empty($this->oldref) && $this->oldref !== $this->ref) {
1007 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'bank/".$this->db->escape($this->ref)."'";
1008 $sql .= " WHERE filepath = 'bank/".$this->db->escape($this->oldref)."' and src_object_type = 'bank_account' and entity = ".((int) $conf->entity);
1009 $resql = $this->db->query($sql);
1010 if (!$resql) {
1011 $error++;
1012 $this->error = $this->db->lasterror();
1013 }
1014
1015 // We rename directory in order not to lose the attachments
1016 $oldref = dol_sanitizeFileName($this->oldref);
1017 $newref = dol_sanitizeFileName($this->ref);
1018 $dirsource = $conf->bank->dir_output.'/'.$oldref;
1019 $dirdest = $conf->bank->dir_output.'/'.$newref;
1020 if (file_exists($dirsource)) {
1021 dol_syslog(get_class($this)."::update rename dir ".$dirsource." into ".$dirdest, LOG_DEBUG);
1022 if (@rename($dirsource, $dirdest)) {
1023 dol_syslog("Rename ok", LOG_DEBUG);
1024 }
1025 }
1026 }
1027
1028 if (!$error && !$notrigger) {
1029 // Call trigger
1030 $result = $this->call_trigger('BANKACCOUNT_MODIFY', $user);
1031 if ($result < 0) {
1032 $error++;
1033 }
1034 // End call triggers
1035 }
1036 } else {
1037 $error++;
1038 $this->error = $this->db->lasterror();
1039 dol_print_error($this->db);
1040 }
1041
1042 if (!$error) {
1043 $this->db->commit();
1044 return $this->id;
1045 } else {
1046 $this->db->rollback();
1047 return -1 * $error;
1048 }
1049 }
1050
1051
1052 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1059 public function update_bban($user = null)
1060 {
1061 // phpcs:enable
1062 global $conf, $langs;
1063
1064 // Load library to get BAN control function
1065 require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1066
1067 dol_syslog(get_class($this)."::update_bban $this->code_banque,$this->code_guichet,$this->number,$this->cle_rib,$this->iban");
1068
1069 // Check parameters
1070 if (!$this->ref) {
1071 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->trans("Ref"));
1072 return -2;
1073 }
1074
1075 $sql = "UPDATE ".MAIN_DB_PREFIX."bank_account SET";
1076 $sql .= " bank = '".$this->db->escape($this->bank)."'";
1077 $sql .= ",code_banque='".$this->db->escape($this->code_banque)."'";
1078 $sql .= ",code_guichet='".$this->db->escape($this->code_guichet)."'";
1079 $sql .= ",number='".$this->db->escape($this->number)."'";
1080 $sql .= ",cle_rib='".$this->db->escape($this->cle_rib)."'";
1081 $sql .= ",bic='".$this->db->escape($this->bic)."'";
1082 $sql .= ",iban_prefix = '".$this->db->escape($this->iban)."'";
1083 $sql .= ",domiciliation='".$this->db->escape($this->address)."'";
1084 $sql .= ",proprio = '".$this->db->escape($this->owner_name)."'";
1085 $sql .= ",owner_address = '".$this->db->escape($this->owner_address)."'";
1086 $sql .= ",owner_zip = '".$this->db->escape($this->owner_zip)."'";
1087 $sql .= ",owner_town = '".$this->db->escape($this->owner_town)."'";
1088 $sql .= ",owner_country_id = ".($this->owner_country_id > 0 ? ((int) $this->owner_country_id) : "null");
1089 $sql .= ",state_id = ".($this->state_id > 0 ? ((int) $this->state_id) : "null");
1090 $sql .= ",fk_pays = ".($this->country_id > 0 ? ((int) $this->country_id) : "null");
1091 $sql .= " WHERE rowid = ".((int) $this->id);
1092 $sql .= " AND entity = ".((int) $conf->entity);
1093
1094 dol_syslog(get_class($this)."::update_bban", LOG_DEBUG);
1095
1096 $result = $this->db->query($sql);
1097 if ($result) {
1098 return 1;
1099 } else {
1100 $this->error = $this->db->lasterror();
1101 dol_print_error($this->db);
1102 return -1;
1103 }
1104 }
1105
1106
1114 public function fetch($id, $ref = '')
1115 {
1116 if (empty($id) && empty($ref)) {
1117 $this->error = "ErrorBadParameters";
1118 return -1;
1119 }
1120
1121 $sql = "SELECT ba.rowid, ba.ref, ba.label, ba.bank, ba.number, ba.courant as type, ba.clos as status, ba.rappro, ba.url,";
1122 $sql .= " ba.code_banque, ba.code_guichet, ba.cle_rib, ba.bic, ba.iban_prefix as iban,";
1123 $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,";
1124 $sql .= " ba.account_number, ba.fk_accountancy_journal, ba.currency_code,";
1125 $sql .= " ba.min_allowed, ba.min_desired, ba.comment,";
1126 $sql .= " ba.datec as date_creation, ba.tms as date_modification, ba.ics, ba.ics_transfer,";
1127 $sql .= ' c.code as country_code, c.label as country,';
1128 $sql .= ' d.code_departement as state_code, d.nom as state,';
1129 $sql .= ' aj.code as accountancy_journal';
1130 $sql .= " FROM ".MAIN_DB_PREFIX."bank_account as ba";
1131 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_country as c ON ba.fk_pays = c.rowid';
1132 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_departements as d ON ba.state_id = d.rowid';
1133 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'accounting_journal as aj ON aj.rowid=ba.fk_accountancy_journal';
1134 $sql .= " WHERE ba.entity IN (".getEntity($this->element).")";
1135 if ($id) {
1136 $sql .= " AND ba.rowid = ".((int) $id);
1137 }
1138 if ($ref) {
1139 $sql .= " AND ba.ref = '".$this->db->escape($ref)."'";
1140 }
1141
1142 dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
1143 $result = $this->db->query($sql);
1144 if ($result) {
1145 if ($this->db->num_rows($result)) {
1146 $obj = $this->db->fetch_object($result);
1147
1148 $this->id = $obj->rowid;
1149 $this->rowid = $obj->rowid;
1150 $this->ref = $obj->ref;
1151 $this->label = $obj->label;
1152 $this->type = $obj->type;
1153 $this->courant = $obj->type;
1154 $this->bank = $obj->bank;
1155 $this->clos = $obj->status;
1156 $this->status = $obj->status;
1157 $this->rappro = $obj->rappro;
1158 $this->url = $obj->url;
1159
1160 $this->code_banque = $obj->code_banque;
1161 $this->code_guichet = $obj->code_guichet;
1162 $this->number = $obj->number;
1163 $this->cle_rib = $obj->cle_rib;
1164 $this->bic = $obj->bic;
1165 $this->iban = $obj->iban;
1166 $this->address = $obj->address;
1167
1168 $this->owner_name = $obj->owner_name;
1169 $this->proprio = $this->owner_name;
1170 $this->owner_address = $obj->owner_address;
1171 $this->owner_zip = $obj->owner_zip;
1172 $this->owner_town = $obj->owner_town;
1173 $this->owner_country_id = $obj->owner_country_id;
1174
1175 $this->pti_in_ctti = $obj->pti_in_ctti;
1176
1177 $this->state_id = $obj->state_id;
1178 $this->state_code = $obj->state_code;
1179 $this->state = $obj->state;
1180
1181 $this->country_id = $obj->country_id;
1182 $this->country_code = $obj->country_code;
1183 $this->country = $obj->country;
1184
1185 $this->account_number = $obj->account_number;
1186 $this->fk_accountancy_journal = $obj->fk_accountancy_journal;
1187 $this->accountancy_journal = $obj->accountancy_journal;
1188
1189 $this->currency_code = $obj->currency_code;
1190 $this->account_currency_code = $obj->currency_code;
1191 $this->min_allowed = $obj->min_allowed;
1192 $this->min_desired = $obj->min_desired;
1193 $this->comment = $obj->comment;
1194
1195 $this->date_creation = $this->db->jdate($obj->date_creation);
1196 $this->date_modification = $this->db->jdate($obj->date_modification);
1197
1198 $this->ics = $obj->ics;
1199 $this->ics_transfer = $obj->ics_transfer;
1200
1201 // Retrieve all extrafield
1202 // fetch optionals attributes and labels
1203 $this->fetch_optionals();
1204
1205 return 1;
1206 } else {
1207 return 0;
1208 }
1209 } else {
1210 $this->error = $this->db->lasterror();
1211 $this->errors[] = $this->error;
1212 return -1;
1213 }
1214 }
1215
1226 public function setCategories($categories)
1227 {
1228 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1229 return parent::setCategoriesCommon($categories, Categorie::TYPE_ACCOUNT);
1230 }
1231
1239 public function delete($user, $notrigger = 0)
1240 {
1241 $error = 0;
1242
1243 $this->db->begin();
1244
1245 // @TODO Check there is no child into llx_payment_various, ... to allow deletion ?
1246
1247 // Delete link between tag and bank account
1248 if (!$error) {
1249 $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_account";
1250 $sql .= " WHERE fk_account = ".((int) $this->id);
1251
1252 $resql = $this->db->query($sql);
1253 if (!$resql) {
1254 $error++;
1255 $this->error = "Error ".$this->db->lasterror();
1256 }
1257 }
1258
1259 if (!$error) {
1260 $sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element;
1261 $sql .= " WHERE rowid = ".((int) $this->id);
1262
1263 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1264 $result = $this->db->query($sql);
1265 if ($result) {
1266 // Remove extrafields
1267 if (!$error) {
1268 $result = $this->deleteExtraFields();
1269 if ($result < 0) {
1270 $error++;
1271 dol_syslog(get_class($this)."::delete error -4 ".$this->error, LOG_ERR);
1272 }
1273 }
1274 } else {
1275 $error++;
1276 $this->error = "Error ".$this->db->lasterror();
1277 }
1278 }
1279
1280 if (!$error) {
1281 $this->db->commit();
1282 return 1;
1283 } else {
1284 $this->db->rollback();
1285 return -1;
1286 }
1287 }
1288
1289
1296 public function getLibStatut($mode = 0)
1297 {
1298 return $this->LibStatut($this->status, $mode);
1299 }
1300
1301 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1309 public function LibStatut($status, $mode = 0)
1310 {
1311 // phpcs:enable
1312 global $langs;
1313 $langs->load('banks');
1314
1315 if ($status == self::STATUS_OPEN) {
1316 $label = $langs->transnoentitiesnoconv("StatusAccountOpened");
1317 $labelshort = $langs->transnoentitiesnoconv("StatusAccountOpened");
1318 $statusType = 'status4';
1319 } else {
1320 $label = $langs->transnoentitiesnoconv("StatusAccountClosed");
1321 $labelshort = $langs->transnoentitiesnoconv("StatusAccountClosed");
1322 $statusType = 'status5';
1323 }
1324
1325 return dolGetStatus($label, $labelshort, '', $statusType, $mode);
1326 }
1327
1328
1329 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1335 public function can_be_deleted()
1336 {
1337 // phpcs:enable
1338 $can_be_deleted = false;
1339
1340 $sql = "SELECT COUNT(rowid) as nb";
1341 $sql .= " FROM ".MAIN_DB_PREFIX."bank";
1342 $sql .= " WHERE fk_account = ".((int) $this->id);
1343
1344 $resql = $this->db->query($sql);
1345 if ($resql) {
1346 $obj = $this->db->fetch_object($resql);
1347 if ($obj->nb <= 1) {
1348 $can_be_deleted = true; // Juste le solde
1349 }
1350 } else {
1351 dol_print_error($this->db);
1352 }
1353 return $can_be_deleted;
1354 }
1355
1356
1362 public function error()
1363 {
1364 return $this->error;
1365 }
1366
1375 public function solde($option = 0, $date_end = '', $field = 'dateo')
1376 {
1377 $solde = 0;
1378
1379 $sql = "SELECT sum(amount) as amount";
1380 $sql .= " FROM ".MAIN_DB_PREFIX."bank";
1381 $sql .= " WHERE fk_account = ".((int) $this->id);
1382 if ($option == 1) {
1383 $sql .= " AND ".$this->db->sanitize($field)." <= '".(!empty($date_end) ? $this->db->idate($date_end) : $this->db->idate(dol_now()))."'";
1384 }
1385
1386 $resql = $this->db->query($sql);
1387 if ($resql) {
1388 if ($this->db->num_rows($resql)) {
1389 $obj = $this->db->fetch_object($resql);
1390 $solde = $obj->amount;
1391 }
1392 $this->db->free($resql);
1393 } else {
1394 $this->errors[] = $this->db->lasterror;
1395 return -1;
1396 }
1397
1398 return (float) price2num($solde, 'MU');
1399 }
1400
1401 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1409 public function load_board(User $user, $filteraccountid = 0)
1410 {
1411 // phpcs:enable
1412 global $conf, $langs;
1413
1414 if ($user->socid) {
1415 return -1; // Protection to prevent calls by external users
1416 }
1417
1418 $sql = "SELECT b.rowid, b.datev as datefin";
1419 $sql .= " FROM ".MAIN_DB_PREFIX."bank as b,";
1420 $sql .= " ".MAIN_DB_PREFIX."bank_account as ba";
1421 $sql .= " WHERE b.rappro=0";
1422 $sql .= " AND b.fk_account = ba.rowid";
1423 $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
1424 $sql .= " AND (ba.rappro = 1 AND ba.courant != " . Account::TYPE_CASH . ")"; // Compte rapprochable
1425 $sql .= " AND clos = 0";
1426 if ($filteraccountid) {
1427 $sql .= " AND ba.rowid = ".((int) $filteraccountid);
1428 }
1429 $resql = $this->db->query($sql);
1430 if ($resql) {
1431 $langs->load("banks");
1432 $now = dol_now();
1433
1434 require_once DOL_DOCUMENT_ROOT.'/core/class/workboardresponse.class.php';
1435
1436 $response = new WorkboardResponse();
1437 $response->warning_delay = $conf->bank->rappro->warning_delay / 60 / 60 / 24;
1438 $response->label = $langs->trans("TransactionsToConciliate");
1439 $response->labelShort = $langs->trans("TransactionsToConciliateShort");
1440 $response->url = DOL_URL_ROOT.'/compta/bank/list.php?leftmenu=bank&amp;mainmenu=bank';
1441 $response->img = img_object('', "payment");
1442
1443 while ($obj = $this->db->fetch_object($resql)) {
1444 $response->nbtodo++;
1445 if ((int) $this->db->jdate($obj->datefin) < ($now - $conf->bank->rappro->warning_delay)) {
1446 $response->nbtodolate++;
1447 }
1448 }
1449 return $response;
1450 } else {
1451 dol_print_error($this->db);
1452 $this->error = $this->db->error();
1453 return -1;
1454 }
1455 }
1456
1463 public function loadStateBoard($filteraccountid = 0)
1464 {
1465 global $user;
1466
1467 if ($user->socid) {
1468 return -1; // Protection to prevent calls by external users
1469 }
1470
1471 $sql = "SELECT count(b.rowid) as nb";
1472 $sql .= " FROM ".MAIN_DB_PREFIX."bank as b,";
1473 $sql .= " ".MAIN_DB_PREFIX."bank_account as ba";
1474 $sql .= " WHERE b.fk_account = ba.rowid";
1475 $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
1476 $sql .= " AND (ba.rappro = 1 AND ba.courant != 2)"; // Compte rapprochable
1477 $sql .= " AND clos = 0";
1478 if ($filteraccountid) {
1479 $sql .= " AND ba.rowid = ".((int) $filteraccountid);
1480 }
1481
1482 $resql = $this->db->query($sql);
1483 if ($resql) {
1484 while ($obj = $this->db->fetch_object($resql)) {
1485 $this->nb["banklines"] = $obj->nb;
1486 }
1487 $this->db->free($resql);
1488 return 1;
1489 } else {
1490 dol_print_error($this->db);
1491 $this->error = $this->db->error();
1492 return -1;
1493 }
1494 }
1495
1496
1502 public function countAccountToReconcile()
1503 {
1504 global $user;
1505
1506 //Protection against external users
1507 if ($user->socid) {
1508 return 0;
1509 }
1510
1511 $nb = 0;
1512
1513 $sql = "SELECT COUNT(ba.rowid) as nb";
1514 $sql .= " FROM ".MAIN_DB_PREFIX."bank_account as ba";
1515 $sql .= " WHERE ba.rappro > 0 and ba.clos = 0";
1516 $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
1517 if (!getDolGlobalString('BANK_CAN_RECONCILIATE_CASHACCOUNT')) {
1518 $sql .= " AND ba.courant != " . Account::TYPE_CASH;
1519 }
1520
1521 $resql = $this->db->query($sql);
1522 if ($resql) {
1523 $obj = $this->db->fetch_object($resql);
1524 $nb = (int) $obj->nb;
1525 } else {
1526 dol_print_error($this->db);
1527 }
1528
1529 return $nb;
1530 }
1531
1540 public function getTooltipContentArray($params)
1541 {
1542 global $langs;
1543 $langs->loadLangs(['banks', 'compta']);
1544 include_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1545
1546 $datas = array();
1547
1548 $nofetch = !empty($params['nofetch']);
1549 $pictos = img_picto('', $this->picto).' <u class="paddingrightnow">'.$langs->trans("BankAccount").'</u>';
1550 if (isset($this->status)) {
1551 $pictos .= ' '.$this->getLibStatut(5);
1552 }
1553 $datas['picto'] = $pictos;
1554 $datas['ref'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
1555 $datas['label'] = '<br><b>'.$langs->trans('Label').':</b> '.$this->label;
1556 $datas['accountnumber'] = '<br><br><b>'.$langs->trans('AccountNumber').':</b> '.$this->number;
1557 $datas['iban'] = '<br><b>'.$langs->trans('IBAN').':</b> '.getIbanHumanReadable($this);
1558 $datas['bic'] = '<br><b>'.$langs->trans('BIC').':</b> '.$this->bic;
1559 $datas['accountcurrency'] = '<br><br><b>'.$langs->trans("AccountCurrency").':</b> '.$this->currency_code;
1560
1561 if (isModEnabled('accounting')) {
1562 include_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
1563 $langs->load("accountancy");
1564 $datas['accountaccounting'] = '<br><b>'.$langs->trans('AccountAccounting').':</b> '.length_accountg($this->account_number);
1565 $datas['accountancyjournal'] = '<br><b>'.$langs->trans('AccountancyJournal').':</b> '.$this->accountancy_journal;
1566 }
1567 // show categories for this record only in ajax to not overload lists
1568 if (isModEnabled('category') && !$nofetch) {
1569 require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
1570 $form = new Form($this->db);
1571 $datas['categories'] = '<br>' . $form->showCategories($this->id, Categorie::TYPE_ACCOUNT, 1);
1572 }
1573
1574 return $datas;
1575 }
1576
1588 public function getNomUrl($withpicto = 0, $mode = '', $option = '', $save_lastsearch_value = -1, $notooltip = 0, $morecss = '')
1589 {
1590 global $conf, $langs;
1591
1592 if (!empty($conf->dol_no_mouse_hover)) {
1593 $notooltip = 1; // Force disable tooltips
1594 }
1595
1596 include_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1597
1598 $result = '';
1599 $classfortooltip = 'classfortooltip';
1600 $dataparams = '';
1601 $params = [
1602 'id' => $this->id,
1603 'objecttype' => $this->element,
1604 'option' => $option,
1605 'nofetch' => 1,
1606 ];
1607 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1608 $classfortooltip = 'classforajaxtooltip';
1609 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
1610 $label = '';
1611 } else {
1612 $label = implode($this->getTooltipContentArray($params));
1613 }
1614
1615 $url = DOL_URL_ROOT.'/compta/bank/card.php?id='.$this->id;
1616 if ($mode == 'transactions') {
1617 $url = DOL_URL_ROOT.'/compta/bank/bankentries_list.php?id='.$this->id;
1618 } elseif ($mode == 'receipts') {
1619 $url = DOL_URL_ROOT.'/compta/bank/releve.php?account='.$this->id;
1620 }
1621
1622 if ($option != 'nolink') {
1623 // Add param to save lastsearch_values or not
1624 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1625 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1626 $add_save_lastsearch_values = 1;
1627 }
1628 if ($add_save_lastsearch_values) {
1629 $url .= '&save_lastsearch_values=1';
1630 }
1631 }
1632
1633 $linkclose = '';
1634 if (empty($notooltip)) {
1635 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1636 $label = $langs->trans("BankAccount");
1637 $linkclose .= ' alt="'.dolPrintHTMLForAttribute($label).'"';
1638 }
1639 $linkclose .= ($label ? ' title="'.dolPrintHTMLForAttribute($label).'"' : ' title="tocomplete"');
1640 $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
1641 } else {
1642 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1643 }
1644
1645 if ($option == 'nolink' || empty($url)) {
1646 $linkstart = '<span';
1647 } else {
1648 $linkstart = '<a href="'.$url.'"';
1649 }
1650 $linkstart .= $linkclose.'>';
1651 if ($option == 'nolink' || empty($url)) {
1652 $linkend = '</span>';
1653 } else {
1654 $linkend = '</a>';
1655 }
1656
1657 $result .= $linkstart;
1658
1659 if ($withpicto) {
1660 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"'), 0, 0, $notooltip ? 0 : 1);
1661 }
1662 if ($withpicto != 2) {
1663 $result .= $this->ref.($option == 'reflabel' && $this->label ? ' - '.$this->label : '');
1664 }
1665 $result .= $linkend;
1666
1667 return $result;
1668 }
1669
1670
1671 // Method after here are common to Account and CompanyBankAccount
1672
1673
1679 public function verif()
1680 {
1681 require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1682
1683 $error = 0;
1684
1685 // Call functions to check BAN
1686 if (!checkIbanForAccount($this)) {
1687 $error++;
1688 $this->error = 'IBANNotValid';
1689 }
1690 // Call function to check Swift/BIC.
1691 // A non valid BIC/Swift is a problem if: it is not empty or always a problem if WITHDRAWAL_WITHOUT_BIC is not set).
1692 if (!checkSwiftForAccount($this) && (!empty($this->bic) || !getDolGlobalInt('WITHDRAWAL_WITHOUT_BIC'))) {
1693 $error++;
1694 $this->error = 'SwiftNotValid';
1695 }
1696
1697 if (! $error) {
1698 return 1;
1699 } else {
1700 return 0;
1701 }
1702 }
1703
1709 public function getCountryCode()
1710 {
1711 global $mysoc;
1712
1713 // We return country code of bank account
1714 if (!empty($this->country_code)) {
1715 return $this->country_code;
1716 }
1717
1718 // For backward compatibility, we try to guess country from other information
1719 if (!empty($this->iban)) {
1720 // If IBAN defined, we can know country of account from it
1721 $reg = array();
1722 if (preg_match("/^([a-zA-Z][a-zA-Z])/i", $this->iban, $reg)) {
1723 return $reg[1];
1724 }
1725 }
1726
1727 // If this class is linked to a third party
1728 if (!empty($this->socid)) {
1729 require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
1730 $company = new Societe($this->db);
1731 $result = $company->fetch($this->socid);
1732 if (!empty($company->country_code)) {
1733 return $company->country_code;
1734 }
1735 }
1736
1737 // We return country code of managed company
1738 if (!empty($mysoc->country_code)) {
1739 return $mysoc->country_code;
1740 }
1741
1742 return '';
1743 }
1744
1752 public function getBannerAddress($htmlkey, $object)
1753 {
1754 global $conf, $langs;
1755
1756 $out = '';
1757
1758 $outdone = 0;
1759 $coords = $this->getFullAddress(1, ', ', getDolGlobalInt('MAIN_SHOW_REGION_IN_STATE_SELECT'));
1760 if ($coords) {
1761 if (!empty($conf->use_javascript_ajax)) {
1762 // hideonsmatphone because copyToClipboard call jquery dialog that does not work with jmobile
1763 $out .= '<a href="#" class="hideonsmartphone" onclick="return copyToClipboard(\''.dol_escape_js($coords).'\',\''.dol_escape_js($langs->trans("HelpCopyToClipboard")).'\');">';
1764 $out .= img_picto($langs->trans("Address"), 'map-marker-alt');
1765 $out .= '</a> ';
1766 }
1767 $address = dol_print_address($coords, 'address_'.$htmlkey.'_'.$this->id, $this->element, $this->id, 1, ', ');
1768 if ($address) {
1769 $out .= $address;
1770 $outdone++;
1771 }
1772 $outdone++;
1773 }
1774
1775 return $out;
1776 }
1777
1778
1787 public function useDetailedBBAN()
1788 {
1789 $country_code = $this->getCountryCode();
1790
1791 if (in_array($country_code, array('FR', 'ES', 'GA', 'IT', 'NC'))) {
1792 return 1; // France, Spain, Gabon, ... - Not valid for CH
1793 }
1794 if (in_array($country_code, array('AD', 'AU', 'BE', 'CA', 'DE', 'DK', 'GR', 'GB', 'ID', 'IE', 'IR', 'KR', 'NL', 'NZ', 'UK', 'US'))) {
1795 return 2; // Australia, England...
1796 }
1797 return 0;
1798 }
1799
1805 public function needIBAN()
1806 {
1807 global $conf;
1808
1809 if (getDolGlobalString('MAIN_IBAN_IS_NEVER_MANDATORY')) {
1810 return 0;
1811 }
1812
1813 $country_code = $this->getCountryCode();
1814
1815 $country_code_in_EEC = array(
1816 'AT', // Austria
1817 'BE', // Belgium
1818 'BG', // Bulgaria
1819 'CY', // Cyprus
1820 'CZ', // Czech republic
1821 'DE', // Germany
1822 'DK', // Danemark
1823 'EE', // Estonia
1824 'ES', // Spain
1825 'FI', // Finland
1826 'FR', // France
1827 'GB', // United Kingdom
1828 'GR', // Greece
1829 'HR', // Croatia
1830 'NL', // Holland
1831 'HU', // Hungary
1832 'IE', // Ireland
1833 'IM', // Isle of Man - Included in UK
1834 'IT', // Italy
1835 'LT', // Lithuania
1836 'LU', // Luxembourg
1837 'LV', // Latvia
1838 'MC', // Monaco - Included in France
1839 'MT', // Malta
1840 //'NO', // Norway
1841 'PL', // Poland
1842 'PT', // Portugal
1843 'RO', // Romania
1844 'SE', // Sweden
1845 'SK', // Slovakia
1846 'SI', // Slovenia
1847 'UK', // United Kingdom
1848 //'CH', // Switzerland - No. Swizerland in not in EEC
1849 );
1850
1851 if (in_array($country_code, $country_code_in_EEC)) {
1852 return 1; // France, Spain, ...
1853 }
1854 return 0;
1855 }
1856
1862 public function needBIC()
1863 {
1864 if (getDolGlobalString('MAIN_IBAN_IS_NEVER_MANDATORY')) {
1865 return 0;
1866 }
1867
1868 $country_code = $this->getCountryCode();
1869
1870 $country_code_in_EEC = array(
1871 'AD', // Andorra
1872 'BH', // Bahrein
1873 'DK', // Denmark
1874 'FR', // France
1875 'GH', // Ghana
1876 'HU', // Hungary
1877 'JP', // Japan
1878 'LV', // Latvia
1879 'SE', // Sweden
1880 );
1881
1882 if (in_array($country_code, $country_code_in_EEC)) {
1883 return 1; // Andorra, Bahrein, ...
1884 }
1885 return 0;
1886 }
1887
1894 public function info($id)
1895 {
1896 }
1897
1912 public function getFieldsToShow($includeibanbic = 0)
1913 {
1914 //Get the required properties depending on the country
1915 $detailedBBAN = $this->useDetailedBBAN();
1916
1917 if ($detailedBBAN == 0) {
1918 $fieldarray = array(
1919 'BankAccountNumber'
1920 );
1921 } elseif ($detailedBBAN == 2) {
1922 $fieldarray = array(
1923 'BankCode',
1924 'BankAccountNumber'
1925 );
1926 } else {
1927 $fieldarray = self::getAccountNumberOrder();
1928 }
1929
1930 //if ($this->needIBAN()) { // return always IBAN and BIC (this was old behaviour)
1931 if ($includeibanbic) {
1932 $fieldarray[] = 'IBAN';
1933 $fieldarray[] = 'BIC';
1934 }
1935 //}
1936
1937 //Get the order the properties are shown
1938 return $fieldarray;
1939 }
1940
1951 public static function getAccountNumberOrder()
1952 {
1953 global $conf;
1954
1955 $fieldlists = array(
1956 'BankCode',
1957 'DeskCode',
1958 'BankAccountNumber',
1959 'BankAccountNumberKey'
1960 );
1961
1962 if (getDolGlobalString('BANK_SHOW_ORDER_OPTION')) {
1963 if (is_numeric(getDolGlobalString('BANK_SHOW_ORDER_OPTION'))) {
1964 if (getDolGlobalString('BANK_SHOW_ORDER_OPTION') == '1') {
1965 $fieldlists = array(
1966 'BankCode',
1967 'DeskCode',
1968 'BankAccountNumberKey',
1969 'BankAccountNumber'
1970 );
1971 }
1972 } else {
1973 //Replace the old AccountNumber key with the new BankAccountNumber key
1974 $fieldlists = explode(
1975 ' ',
1976 preg_replace('/ ?[^Bank]AccountNumber ?/', 'BankAccountNumber', $conf->global->BANK_SHOW_ORDER_OPTION)
1977 );
1978 }
1979 }
1980
1981 return $fieldlists;
1982 }
1983
1984
1992 public function initAsSpecimen()
1993 {
1994 // Example of IBAN FR7630001007941234567890185
1995 $this->specimen = 1;
1996 $this->ref = 'MBA';
1997 $this->label = 'My Big Company Bank account';
1998 $this->clos = Account::STATUS_OPEN;
1999 $this->type = Account::TYPE_CURRENT;
2000 $this->status = Account::STATUS_OPEN;
2001 $this->code_banque = '30001';
2002 $this->code_guichet = '00794';
2003 $this->number = '12345678901';
2004 $this->cle_rib = '85';
2005 $this->bic = 'AA12';
2006 $this->iban = 'FR7630001007941234567890185';
2007
2008 $this->bank = 'MyBank';
2009 $this->address = 'Rue de Paris';
2010 $this->owner_name = 'Owner';
2011 $this->owner_address = 'Owner address';
2012 $this->owner_zip = 'Owner zip';
2013 $this->owner_town = 'Owner town';
2014 $this->owner_country_id = 1;
2015 $this->country_id = 1;
2016
2017 return 1;
2018 }
2019
2028 public static function replaceThirdparty($dbs, $origin_id, $dest_id)
2029 {
2030 $sql = "UPDATE ".MAIN_DB_PREFIX."bank_url SET url_id = ".((int) $dest_id)." WHERE url_id = ".((int) $origin_id)." AND type = 'company'";
2031
2032 if ($dbs->query($sql)) {
2033 return true;
2034 } else {
2035 //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.
2036 //$this->errors = $dbs->lasterror();
2037 return false;
2038 }
2039 }
2040
2048 public function getKanbanView($option = '', $arraydata = null)
2049 {
2050 global $langs;
2051
2052 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
2053
2054 $return = '<div class="box-flex-item box-flex-grow-zero">';
2055 $return .= '<div class="info-box info-box-sm">';
2056 $return .= '<span class="info-box-icon bg-infobox-action">';
2057 $return .= img_picto('', $this->picto);
2058 $return .= '</span>';
2059 $return .= '<div class="info-box-content">';
2060 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).'</span>';
2061 if ($selected >= 0) {
2062 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
2063 }
2064 if (property_exists($this, 'type_lib')) {
2065 $return .= '<br><span class="info-box-label opacitymedium" title="'.$this->type_lib[$this->type].'">'.substr($this->type_lib[$this->type], 0, 24).'...</span>';
2066 }
2067 if (method_exists($this, 'solde')) {
2068 $return .= '<br><a href="'.DOL_URL_ROOT.'/compta/bank/bankentries_list.php?id='.$this->id.'">';
2069 $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>';
2070 }
2071 if (method_exists($this, 'getLibStatut')) {
2072 $return .= '<br><div class="info-box-status">'.$this->getLibStatut(3).'</div>';
2073 }
2074 $return .= '</div>';
2075 $return .= '</div>';
2076 $return .= '</div>';
2077 return $return;
2078 }
2079}
2080
2081
2082require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
2083
2087class AccountLine extends CommonObjectLine
2088{
2092 public $db;
2093
2097 public $element = 'bank';
2098
2102 public $table_element = 'bank';
2103
2107 public $picto = 'accountline';
2108
2112 public $id;
2113
2117 public $ref;
2118
2124 public $datec;
2125
2131 public $dateo;
2132
2138 public $datev;
2139
2143 public $amount;
2144
2148 public $amount_main_currency;
2149
2153 public $fk_user_author;
2154
2158 public $fk_user_rappro;
2159
2163 public $fk_type;
2164
2168 public $fk_bordereau;
2169
2173 public $fk_account;
2174
2178 public $bank_account_ref;
2179
2183 public $bank_account_label;
2184
2188 public $numero_compte;
2189
2193 public $emetteur;
2194
2198 public $rappro;
2199
2203 public $num_releve;
2204
2208 public $num_chq;
2209
2213 public $bank_chq;
2214
2218 public $label;
2219
2223 public $note;
2224
2230 public $user_rappro;
2231
2232
2238 public function __construct(DoliDB $db)
2239 {
2240 $this->db = $db;
2241 }
2242
2251 public function fetch($rowid, $ref = '', $num = '')
2252 {
2253 // Check parameters
2254 if (empty($rowid) && empty($ref) && empty($num)) {
2255 return -1;
2256 }
2257
2258 $sql = "SELECT b.rowid, b.datec, b.datev, b.dateo, b.amount, b.label as label, b.fk_account,";
2259 $sql .= " b.fk_user_author, b.fk_user_rappro,";
2260 $sql .= " b.fk_type, b.num_releve, b.num_chq, b.rappro, b.note,";
2261 $sql .= " b.fk_bordereau, b.banque, b.emetteur,";
2262 $sql .= " ba.ref as bank_account_ref, ba.label as bank_account_label";
2263 $sql .= " FROM ".MAIN_DB_PREFIX."bank as b,";
2264 $sql .= " ".MAIN_DB_PREFIX."bank_account as ba";
2265 $sql .= " WHERE b.fk_account = ba.rowid";
2266 $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
2267 if ($num) {
2268 $sql .= " AND b.num_chq = '".$this->db->escape($num)."'";
2269 } elseif ($ref) {
2270 $sql .= " AND b.rowid = '".$this->db->escape($ref)."'";
2271 } else {
2272 $sql .= " AND b.rowid = ".((int) $rowid);
2273 }
2274
2275 dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
2276 $result = $this->db->query($sql);
2277 if ($result) {
2278 $ret = 0;
2279
2280 $obj = $this->db->fetch_object($result);
2281 if ($obj) {
2282 $this->id = $obj->rowid;
2283 $this->rowid = $obj->rowid;
2284 $this->ref = $obj->rowid;
2285
2286 $this->datec = $this->db->jdate($obj->datec);
2287 $this->datev = $this->db->jdate($obj->datev);
2288 $this->dateo = $this->db->jdate($obj->dateo);
2289 $this->amount = $obj->amount;
2290 $this->label = $obj->label;
2291 $this->note = $obj->note;
2292
2293 $this->fk_user_author = $obj->fk_user_author;
2294 $this->fk_user_rappro = $obj->fk_user_rappro;
2295
2296 $this->fk_type = $obj->fk_type; // Type of transaction
2297 $this->rappro = (int) $obj->rappro;
2298 $this->num_releve = $obj->num_releve;
2299
2300 $this->num_chq = $obj->num_chq;
2301 $this->bank_chq = $obj->banque;
2302 $this->fk_bordereau = $obj->fk_bordereau;
2303
2304 $this->fk_account = $obj->fk_account;
2305 $this->bank_account_ref = $obj->bank_account_ref;
2306 $this->bank_account_label = $obj->bank_account_label;
2307
2308 // Retrieve all extrafield
2309 // fetch optionals attributes and labels
2310 $this->fetch_optionals();
2311
2312 $ret = 1;
2313 }
2314 $this->db->free($result);
2315 return $ret;
2316 } else {
2317 return -1;
2318 }
2319 }
2320
2326 public function insert()
2327 {
2328 $error = 0;
2329
2330 $this->db->begin();
2331
2332 $sql = "INSERT INTO ".MAIN_DB_PREFIX."bank (";
2333 $sql .= "datec";
2334 $sql .= ", dateo";
2335 $sql .= ", datev";
2336 $sql .= ", label";
2337 $sql .= ", amount";
2338 $sql .= ", amount_main_currency";
2339 $sql .= ", fk_user_author";
2340 $sql .= ", num_chq";
2341 $sql .= ", fk_account";
2342 $sql .= ", fk_type";
2343 $sql .= ", emetteur,banque";
2344 $sql .= ", rappro";
2345 $sql .= ", numero_compte";
2346 $sql .= ", num_releve";
2347 $sql .= ", note";
2348 $sql .= ") VALUES (";
2349 $sql .= "'".$this->db->idate($this->datec)."'";
2350 $sql .= ", '".$this->db->idate($this->dateo)."'";
2351 $sql .= ", '".$this->db->idate($this->datev)."'";
2352 $sql .= ", '".$this->db->escape($this->label)."'";
2353 $sql .= ", ".price2num($this->amount);
2354 $sql .= ", ".(empty($this->amount_main_currency) ? "NULL" : price2num($this->amount_main_currency));
2355 $sql .= ", ".($this->fk_user_author > 0 ? ((int) $this->fk_user_author) : "null");
2356 $sql .= ", ".($this->num_chq ? "'".$this->db->escape($this->num_chq)."'" : "null");
2357 $sql .= ", '".$this->db->escape((string) $this->fk_account)."'";
2358 $sql .= ", '".$this->db->escape($this->fk_type)."'";
2359 $sql .= ", ".($this->emetteur ? "'".$this->db->escape($this->emetteur)."'" : "null");
2360 $sql .= ", ".($this->bank_chq ? "'".$this->db->escape($this->bank_chq)."'" : "null");
2361 $sql .= ", ".(int) $this->rappro;
2362 $sql .= ", ".($this->numero_compte ? "'".$this->db->escape($this->numero_compte)."'" : "''");
2363 $sql .= ", ".($this->num_releve ? "'".$this->db->escape($this->num_releve)."'" : "null");
2364 $sql .= ", ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "null");
2365 $sql .= ")";
2366
2367
2368 dol_syslog(get_class($this)."::insert", LOG_DEBUG);
2369 $resql = $this->db->query($sql);
2370 if ($resql) {
2371 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'bank');
2372 // Actions on extra fields (by external module or standard code)
2373 $result = $this->insertExtraFields();
2374 if ($result < 0) {
2375 $error++;
2376 }
2377 } else {
2378 $error++;
2379 $this->error = $this->db->lasterror();
2380 dol_print_error($this->db);
2381 }
2382
2383 if (!$error) {
2384 $this->db->commit();
2385 return $this->id;
2386 } else {
2387 $this->db->rollback();
2388 return -1 * $error;
2389 }
2390 }
2391
2399 public function delete($user, $notrigger = 0)
2400 {
2401 $nbko = 0;
2402
2403 if ($this->rappro) {
2404 // Protection to avoid any delete of consolidated lines
2405 $this->error = "ErrorDeleteNotPossibleLineIsConsolidated";
2406 return -1;
2407 }
2408
2409 $this->db->begin();
2410
2411 if (!$notrigger) {
2412 // Call trigger
2413 $result = $this->call_trigger('BANKACCOUNTLINE_DELETE', $user);
2414 if ($result < 0) {
2415 $this->db->rollback();
2416 return -1;
2417 }
2418 // End call triggers
2419 }
2420
2421 // Protection to avoid any delete of accounted lines. Protection on by default
2422 if (!getDolGlobalString('BANK_ALLOW_TRANSACTION_DELETION_EVEN_IF_IN_ACCOUNTING')) {
2423 $sql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."accounting_bookkeeping WHERE doc_type = 'bank' AND fk_doc = ".((int) $this->id);
2424 $resql = $this->db->query($sql);
2425 if ($resql) {
2426 $obj = $this->db->fetch_object($resql);
2427 if ($obj && $obj->nb) {
2428 $this->error = 'ErrorRecordAlreadyInAccountingDeletionNotPossible';
2429 $this->db->rollback();
2430 return -1;
2431 }
2432 } else {
2433 $this->error = $this->db->lasterror();
2434 $this->db->rollback();
2435 return -1;
2436 }
2437 }
2438
2439 // Delete urls
2440 $result = $this->delete_urls($user);
2441 if ($result < 0) {
2442 $nbko++;
2443 }
2444
2445 $sql = "DELETE FROM ".MAIN_DB_PREFIX."category_bankline WHERE lineid=".(int) $this->rowid;
2446 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
2447 $result = $this->db->query($sql);
2448 if (!$result) {
2449 $nbko++;
2450 }
2451
2452 $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank_extrafields WHERE fk_object=".(int) $this->rowid;
2453 $result = $this->db->query($sql);
2454 if (!$result) {
2455 $nbko++;
2456 }
2457
2458 $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank WHERE rowid=".(int) $this->rowid;
2459 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
2460 $result = $this->db->query($sql);
2461 if (!$result) {
2462 $nbko++;
2463 }
2464
2465 if (!$nbko) {
2466 $this->db->commit();
2467 return 1;
2468 } else {
2469 $this->db->rollback();
2470 return -$nbko;
2471 }
2472 }
2473
2474
2475 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2482 public function delete_urls($user = null)
2483 {
2484 // phpcs:enable
2485 $nbko = 0;
2486
2487 if ($this->rappro) {
2488 // Protection to avoid any delete of consolidated lines
2489 $this->error = "ErrorDeleteNotPossibleLineIsConsolidated";
2490 return -1;
2491 }
2492
2493 $this->db->begin();
2494
2495 $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank_url WHERE fk_bank=".(int) $this->rowid;
2496 dol_syslog(get_class($this)."::delete_urls", LOG_DEBUG);
2497 $result = $this->db->query($sql);
2498 if (!$result) {
2499 $nbko++;
2500 }
2501
2502 if (!$nbko) {
2503 $this->db->commit();
2504 return 1;
2505 } else {
2506 $this->db->rollback();
2507 return -$nbko;
2508 }
2509 }
2510
2511
2519 public function update(User $user, $notrigger = 0)
2520 {
2521 $this->db->begin();
2522
2523 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2524 $sql .= " amount = ".price2num($this->amount).",";
2525 $sql .= " datev='".$this->db->idate($this->datev)."',";
2526 $sql .= " dateo='".$this->db->idate($this->dateo)."'";
2527 $sql .= " WHERE rowid = ".((int) $this->rowid);
2528
2529 dol_syslog(get_class($this)."::update", LOG_DEBUG);
2530 $resql = $this->db->query($sql);
2531 if ($resql) {
2532 $this->db->commit();
2533 return 1;
2534 } else {
2535 $this->db->rollback();
2536 $this->error = $this->db->error();
2537 return -1;
2538 }
2539 }
2540
2541
2547 public function updateLabel()
2548 {
2549 $this->db->begin();
2550
2551 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2552 $sql .= " label = '".$this->db->escape($this->label)."'";
2553 $sql .= " WHERE rowid = ".((int) $this->rowid);
2554
2555 dol_syslog(get_class($this)."::update_label", LOG_DEBUG);
2556 $resql = $this->db->query($sql);
2557 if ($resql) {
2558 $this->db->commit();
2559 return 1;
2560 } else {
2561 $this->db->rollback();
2562 $this->error = $this->db->error();
2563 return -1;
2564 }
2565 }
2566
2567
2568 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2577 public function update_conciliation(User $user, $cat, $conciliated = 1)
2578 {
2579 // phpcs:enable
2580 global $conf, $langs;
2581
2582 $this->db->begin();
2583
2584 // Check statement field
2585 if (getDolGlobalString('BANK_STATEMENT_REGEX_RULE')) {
2586 if (!preg_match('/' . getDolGlobalString('BANK_STATEMENT_REGEX_RULE').'/', $this->num_releve)) {
2587 $this->errors[] = $langs->trans("ErrorBankStatementNameMustFollowRegex", getDolGlobalString('BANK_STATEMENT_REGEX_RULE'));
2588 return -1;
2589 }
2590 }
2591
2592 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2593 $sql .= " rappro = ".((int) $conciliated);
2594 $sql .= ", num_releve = '".$this->db->escape($this->num_releve)."'";
2595 if ($conciliated) {
2596 $sql .= ", fk_user_rappro = ".((int) $user->id);
2597 }
2598 $sql .= " WHERE rowid = ".((int) $this->id);
2599
2600 dol_syslog(get_class($this)."::update_conciliation", LOG_DEBUG);
2601 $resql = $this->db->query($sql);
2602 if ($resql) {
2603 if (!empty($cat) && $cat > 0) {
2604 $sql = "INSERT INTO ".MAIN_DB_PREFIX."category_bankline (";
2605 $sql .= "lineid";
2606 $sql .= ", fk_categ";
2607 $sql .= ") VALUES (";
2608 $sql .= ((int) $this->id);
2609 $sql .= ", ".((int) $cat);
2610 $sql .= ")";
2611
2612 dol_syslog(get_class($this)."::update_conciliation", LOG_DEBUG);
2613 $this->db->query($sql);
2614
2615 // No error check. Can fail if category already affected
2616 // TODO Do no try the insert if link already exists
2617 }
2618
2619 $this->rappro = (int) $conciliated;
2620
2621 $this->db->commit();
2622 return 1;
2623 } else {
2624 $this->db->rollback();
2625 return -1;
2626 }
2627 }
2628
2629
2630 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2638 public function datev_change($rowid, $sign = 1)
2639 {
2640 // phpcs:enable
2641 $sql = "SELECT datev FROM ".MAIN_DB_PREFIX."bank WHERE rowid = ".((int) $rowid);
2642 $resql = $this->db->query($sql);
2643 if ($resql) {
2644 $obj = $this->db->fetch_object($resql);
2645 $newdate = (int) $this->db->jdate($obj->datev) + (3600 * 24 * $sign);
2646
2647 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2648 $sql .= " datev = '".$this->db->idate($newdate)."'";
2649 $sql .= " WHERE rowid = ".((int) $rowid);
2650
2651 $result = $this->db->query($sql);
2652 if ($result) {
2653 if ($this->db->affected_rows($result)) {
2654 return 1;
2655 }
2656 } else {
2657 dol_print_error($this->db);
2658 return 0;
2659 }
2660 } else {
2661 dol_print_error($this->db);
2662 }
2663 return 0;
2664 }
2665
2666 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2673 public function datev_next($id)
2674 {
2675 // phpcs:enable
2676 return $this->datev_change($id, 1);
2677 }
2678
2679 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2686 public function datev_previous($id)
2687 {
2688 // phpcs:enable
2689 return $this->datev_change($id, -1);
2690 }
2691
2692
2693 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2701 public function dateo_change($rowid, $sign = 1)
2702 {
2703 // phpcs:enable
2704 $sql = "SELECT dateo FROM ".MAIN_DB_PREFIX."bank WHERE rowid = ".((int) $rowid);
2705 $resql = $this->db->query($sql);
2706 if ($resql) {
2707 $obj = $this->db->fetch_object($resql);
2708 $newdate = (int) $this->db->jdate($obj->dateo) + (3600 * 24 * $sign);
2709
2710 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2711 $sql .= " dateo = '".$this->db->idate($newdate)."'";
2712 $sql .= " WHERE rowid = ".((int) $rowid);
2713
2714 $result = $this->db->query($sql);
2715 if ($result) {
2716 if ($this->db->affected_rows($result)) {
2717 return 1;
2718 }
2719 } else {
2720 dol_print_error($this->db);
2721 return 0;
2722 }
2723 } else {
2724 dol_print_error($this->db);
2725 }
2726 return 0;
2727 }
2728
2729 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2736 public function dateo_next($id)
2737 {
2738 // phpcs:enable
2739 return $this->dateo_change($id, 1);
2740 }
2741
2742 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2749 public function dateo_previous($id)
2750 {
2751 // phpcs:enable
2752 return $this->dateo_change($id, -1);
2753 }
2754
2755
2762 public function info($id)
2763 {
2764 $sql = 'SELECT b.rowid, b.datec, b.tms as datem,';
2765 $sql .= ' b.fk_user_author, b.fk_user_rappro';
2766 $sql .= ' FROM '.MAIN_DB_PREFIX.'bank as b';
2767 $sql .= ' WHERE b.rowid = '.((int) $id);
2768
2769 $result = $this->db->query($sql);
2770 if ($result) {
2771 if ($this->db->num_rows($result)) {
2772 $obj = $this->db->fetch_object($result);
2773
2774 $this->id = $obj->rowid;
2775
2776 $this->user_creation_id = $obj->fk_user_author;
2777 $this->user_rappro = $obj->fk_user_rappro;
2778 $this->date_creation = $this->db->jdate($obj->datec);
2779 $this->date_modification = $this->db->jdate($obj->datem);
2780 //$this->date_rappro = $obj->daterappro; // Not yet managed
2781 }
2782 $this->db->free($result);
2783 } else {
2784 dol_print_error($this->db);
2785 }
2786 }
2787
2788
2798 public function getNomUrl($withpicto = 0, $maxlen = 0, $option = '', $notooltip = 0)
2799 {
2800 global $conf, $langs;
2801
2802 $result = '';
2803
2804 $label = img_picto('', $this->picto).' <u>'.$langs->trans("BankTransactionLine").'</u>:<br>';
2805 $label .= '<b>'.$langs->trans("Ref").':</b> '.$this->ref;
2806 if ($this->amount) {
2807 $label .= '<br><strong>'.$langs->trans("Amount").':</strong> '.price($this->amount, 0, $langs, 1, -1, -1, $conf->currency);
2808 }
2809
2810 $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">';
2811 $linkend = '</a>';
2812
2813 $result .= $linkstart;
2814 if ($withpicto) {
2815 $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);
2816 }
2817 if ($withpicto != 2) {
2818 $result .= ($this->ref ? $this->ref : $this->id);
2819 }
2820
2821 $result .= $linkend;
2822
2823 if ($option == 'showall' || $option == 'showconciliated' || $option == 'showconciliatedandaccounted') {
2824 $result .= ' <span class="opacitymedium">(';
2825 }
2826 if ($option == 'showall') {
2827 $result .= $langs->trans("BankAccount").': ';
2828 $accountstatic = new Account($this->db);
2829 $accountstatic->id = $this->fk_account;
2830 $accountstatic->ref = $this->bank_account_ref;
2831 $accountstatic->label = $this->bank_account_label;
2832 $result .= $accountstatic->getNomUrl(0).', ';
2833 }
2834 if ($option == 'showall' || $option == 'showconciliated' || $option == 'showconciliatedandaccounted') {
2835 $result .= $langs->trans("BankLineConciliated").': ';
2836 $result .= yn($this->rappro);
2837 }
2838 if (isModEnabled('accounting') && ($option == 'showall' || $option == 'showconciliatedandaccounted')) {
2839 $sql = "SELECT COUNT(rowid) as nb, MAX(piece_num) as banktransactionid FROM ".MAIN_DB_PREFIX."accounting_bookkeeping";
2840 $sql .= " WHERE doc_type = 'bank' AND fk_doc = ".((int) $this->id);
2841 $resql = $this->db->query($sql);
2842 if ($resql) {
2843 $obj = $this->db->fetch_object($resql);
2844 if ($obj && $obj->nb) {
2845 $result .= ' - '.$langs->trans("Accounted").': <span title="'.$langs->trans("TransactionNumShort").' '.$obj->banktransactionid.'">'.yn(1).'</span>';
2846 } else {
2847 $result .= ' - '.$langs->trans("Accounted").': '.yn(0);
2848 }
2849 }
2850 }
2851 if ($option == 'showall' || $option == 'showconciliated' || $option == 'showconciliatedandaccounted') {
2852 $result .= ')</span>';
2853 }
2854
2855 return $result;
2856 }
2857
2858
2865 public function getLibStatut($mode = 0)
2866 {
2867 return $this->LibStatut($this->status, $mode);
2868 }
2869
2870 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2878 public function LibStatut($status, $mode = 0)
2879 {
2880 // phpcs:enable
2881 return '';
2882 }
2883
2890 public function getVentilExportCompta($mode = 0)
2891 {
2892 $alreadydispatched = 0;
2893
2894 $type = 'bank';
2895
2896 $sql = " SELECT ".($mode ? 'DISTINCT piece_num' : 'COUNT(ab.rowid)')." as nb";
2897 $sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab WHERE ab.doc_type = '".$this->db->escape($type)."' AND ab.fk_doc = ".((int) $this->id);
2898 $resql = $this->db->query($sql);
2899 if ($resql) {
2900 $obj = $this->db->fetch_object($resql);
2901 if ($obj) {
2902 $alreadydispatched = $obj->nb;
2903 }
2904 } else {
2905 $this->error = $this->db->lasterror();
2906 return -1;
2907 }
2908
2909 if ($alreadydispatched) {
2910 return $alreadydispatched;
2911 }
2912 return 0;
2913 }
2914}
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:169
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.
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return 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