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