dolibarr 21.0.4
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-2024 Frédéric France <frederic.france@free.fr>
13 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 3 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program. If not, see <https://www.gnu.org/licenses/>.
27 */
28
35require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
36
37
41class Account extends CommonObject
42{
46 public $element = 'bank_account';
47
51 public $table_element = 'bank_account';
52
56 public $picto = 'account';
57
63 public $rowid;
64
69 public $label;
70
77 public $courant;
78
83 public $type;
84
89 public $bank;
90
98 public $clos = self::STATUS_OPEN;
99
104 public $rappro = 1;
105
110 public $url;
111
116 public $code_banque;
117
122 public $code_guichet;
123
128 public $number;
129
134 public $cle_rib;
135
140 public $bic;
141
146 public $iban;
147
154 public $iban_prefix;
155
160 public $pti_in_ctti = 0;
161
168 public $proprio;
169
174 public $owner_name;
175
180 public $owner_address;
181
186 public $owner_zip;
187
192 public $owner_town;
196 public $owner_country_id;
200 public $owner_country_code;
201
208 public $domiciliation;
209
214 public $address;
218 public $state_id;
222 public $state_code;
226 public $state;
230 public $country_id;
231
237 public $type_lib = array();
238
243 public $account_number;
244
248 public $fk_accountancy_journal;
249
253 public $accountancy_journal;
254
259 public $currency_code;
260
267 public $account_currency_code;
268
273 public $min_allowed;
274
279 public $min_desired;
280
285 public $comment;
286
291 public $date_solde;
292
299 public $solde;
300
305 public $balance;
306
311 public $ics;
312
317 public $ics_transfer;
318
322 public $oldref;
323
324
349 // BEGIN MODULEBUILDER PROPERTIES
353 public $fields = array(
354 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 10),
355 'ref' => array('type' => 'varchar(12)', 'label' => 'Ref', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'showoncombobox' => 1, 'position' => 25),
356 'label' => array('type' => 'varchar(30)', 'label' => 'Label', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 30),
357 'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => '1', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 35, 'index' => 1),
358 'bank' => array('type' => 'varchar(60)', 'label' => 'Bank', 'enabled' => 1, 'visible' => -1, 'position' => 40),
359 'code_banque' => array('type' => 'varchar(128)', 'label' => 'Code banque', 'enabled' => 1, 'visible' => -1, 'position' => 45),
360 'code_guichet' => array('type' => 'varchar(6)', 'label' => 'Code guichet', 'enabled' => 1, 'visible' => -1, 'position' => 50),
361 'number' => array('type' => 'varchar(255)', 'label' => 'Number', 'enabled' => 1, 'visible' => -1, 'position' => 55),
362 'cle_rib' => array('type' => 'varchar(5)', 'label' => 'Cle rib', 'enabled' => 1, 'visible' => -1, 'position' => 60),
363 'bic' => array('type' => 'varchar(11)', 'label' => 'Bic', 'enabled' => 1, 'visible' => -1, 'position' => 65),
364 'iban_prefix' => array('type' => 'varchar(34)', 'label' => 'Iban prefix', 'enabled' => 1, 'visible' => -1, 'position' => 70),
365 'country_iban' => array('type' => 'varchar(2)', 'label' => 'Country iban', 'enabled' => 1, 'visible' => -1, 'position' => 75),
366 'cle_iban' => array('type' => 'varchar(2)', 'label' => 'Cle iban', 'enabled' => 1, 'visible' => -1, 'position' => 80),
367 'domiciliation' => array('type' => 'varchar(255)', 'label' => 'Domiciliation', 'enabled' => 1, 'visible' => -1, 'position' => 85),
368 'state_id' => array('type' => 'integer', 'label' => 'StateId', 'enabled' => 1, 'visible' => -1, 'position' => 90),
369 'fk_pays' => array('type' => 'integer', 'label' => 'Country', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 95),
370 'proprio' => array('type' => 'varchar(60)', 'label' => 'Proprio', 'enabled' => 1, 'visible' => -1, 'position' => 100),
371 'owner_address' => array('type' => 'varchar(255)', 'label' => 'Owner address', 'enabled' => 1, 'visible' => -1, 'position' => 105),
372 'owner_zip' => array('type' => 'varchar(25)', 'label' => 'Owner zip', 'enabled' => 1, 'visible' => -1, 'position' => 106),
373 'owner_town' => array('type' => 'varchar(50)', 'label' => 'Owner town', 'enabled' => 1, 'visible' => -1, 'position' => 107),
374 'owner_country_id' => array('type' => 'integer', 'label' => 'Owner country', 'enabled' => 1, 'visible' => -1, 'position' => 108),
375 'courant' => array('type' => 'smallint(6)', 'label' => 'Courant', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 110),
376 'clos' => array('type' => 'smallint(6)', 'label' => 'Clos', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 115),
377 'rappro' => array('type' => 'smallint(6)', 'label' => 'Rappro', 'enabled' => 1, 'visible' => -1, 'position' => 120),
378 'url' => array('type' => 'varchar(128)', 'label' => 'Url', 'enabled' => 1, 'visible' => -1, 'position' => 125),
379 'account_number' => array('type' => 'varchar(32)', 'label' => 'Account number', 'enabled' => 1, 'visible' => -1, 'position' => 130),
380 'fk_accountancy_journal' => array('type' => 'integer', 'label' => 'Accountancy journal ID', 'enabled' => 1, 'visible' => -1, 'position' => 132),
381 'accountancy_journal' => array('type' => 'varchar(20)', 'label' => 'Accountancy journal', 'enabled' => 1, 'visible' => -1, 'position' => 135),
382 'currency_code' => array('type' => 'varchar(3)', 'label' => 'Currency code', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 140),
383 'min_allowed' => array('type' => 'integer', 'label' => 'Min allowed', 'enabled' => 1, 'visible' => -1, 'position' => 145),
384 'min_desired' => array('type' => 'integer', 'label' => 'Min desired', 'enabled' => 1, 'visible' => -1, 'position' => 150),
385 'comment' => array('type' => 'text', 'label' => 'Comment', 'enabled' => 1, 'visible' => -1, 'position' => 155),
386 'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -1, 'position' => 156),
387 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 157),
388 'fk_user_author' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'Fk user author', 'enabled' => 1, 'visible' => -1, 'position' => 160),
389 'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'position' => 165),
390 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 170),
391 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'visible' => 0, 'position' => 175),
392 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'position' => 180),
393 'extraparams' => array('type' => 'varchar(255)', 'label' => 'Extraparams', 'enabled' => 1, 'visible' => -1, 'position' => 185),
394 );
395 // END MODULEBUILDER PROPERTIES
396
400 const TYPE_CURRENT = 1;
404 const TYPE_CASH = 2;
408 const TYPE_SAVINGS = 0;
409
410
411 const STATUS_OPEN = 0;
412 const STATUS_CLOSED = 1;
413
414
420 public function __construct(DoliDB $db)
421 {
422 global $langs;
423
424 $this->db = $db;
425
426 $this->ismultientitymanaged = 1;
427
428 $this->balance = 0;
429
430 $this->type_lib = array(
431 self::TYPE_SAVINGS => $langs->transnoentitiesnoconv("BankType0"),
432 self::TYPE_CURRENT => $langs->transnoentitiesnoconv("BankType1"),
433 self::TYPE_CASH => $langs->transnoentitiesnoconv("BankType2"),
434 );
435
436 $this->labelStatus = array(
437 self::STATUS_OPEN => $langs->transnoentitiesnoconv("StatusAccountOpened"),
438 self::STATUS_CLOSED => $langs->transnoentitiesnoconv("StatusAccountClosed")
439 );
440 }
441
447 public function __toString()
448 {
449 $string = '';
450 foreach ($this->getFieldsToShow() as $val) {
451 if ($val == 'BankCode') {
452 $string .= $this->code_banque.' ';
453 } elseif ($val == 'BankAccountNumber') {
454 $string .= $this->number.' ';
455 } elseif ($val == 'DeskCode') {
456 $string .= $this->code_guichet.' ';
457 } elseif ($val == 'BankAccountNumberKey') {
458 $string .= $this->cle_rib.' ';
459 } elseif ($val == 'BIC') {
460 $string .= $this->bic.' ';
461 } elseif ($val == 'IBAN') {
462 $string .= $this->iban.' ';
463 }
464 }
465
466 return trim($string);
467 }
468
469
475 public function canBeConciliated()
476 {
477 global $conf;
478
479 if (empty($this->rappro)) {
480 return -1;
481 }
482 if ($this->type == Account::TYPE_CASH && !getDolGlobalString('BANK_CAN_RECONCILIATE_CASHACCOUNT')) {
483 return -2;
484 }
485 if ($this->status) {
486 return -3;
487 }
488 return 1;
489 }
490
491
492 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
503 public function add_url_line($line_id, $url_id, $url, $label, $type)
504 {
505 // phpcs:enable
506 // Avoid uk_bank_url collision when the same target (line_id, url_id, type) is linked twice
507 // e.g. two distinct credit transfers for the same employee dispatched on the same bank line.
508 $sqlcheck = "SELECT rowid FROM ".MAIN_DB_PREFIX."bank_url";
509 $sqlcheck .= " WHERE fk_bank = ".((int) $line_id);
510 $sqlcheck .= " AND url_id = ".((int) $url_id);
511 $sqlcheck .= " AND type = '".$this->db->escape($type)."'";
512 $resqlcheck = $this->db->query($sqlcheck);
513 if ($resqlcheck) {
514 $obj = $this->db->fetch_object($resqlcheck);
515 if ($obj) {
516 $this->db->free($resqlcheck);
517 return (int) $obj->rowid;
518 }
519 $this->db->free($resqlcheck);
520 }
521
522 $sql = "INSERT INTO ".MAIN_DB_PREFIX."bank_url (";
523 $sql .= "fk_bank";
524 $sql .= ", url_id";
525 $sql .= ", url"; // deprecated
526 $sql .= ", label";
527 $sql .= ", type";
528 $sql .= ") VALUES (";
529 $sql .= ((int) $line_id);
530 $sql .= ", ".((int) $url_id);
531 $sql .= ", '".$this->db->escape($url)."'"; // deprecated
532 $sql .= ", '".$this->db->escape($label)."'";
533 $sql .= ", '".$this->db->escape($type)."'";
534 $sql .= ")";
535
536 dol_syslog(get_class($this)."::add_url_line", LOG_DEBUG);
537 if ($this->db->query($sql)) {
538 $rowid = $this->db->last_insert_id(MAIN_DB_PREFIX."bank_url");
539 return $rowid;
540 } else {
541 $this->error = $this->db->lasterror();
542 return -1;
543 }
544 }
545
546 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
556 public function get_url($fk_bank = 0, $url_id = 0, $type = '')
557 {
558 // phpcs:enable
559 $lines = array();
560
561 // Check parameters
562 if (!empty($fk_bank) && (!empty($url_id) || !empty($type))) {
563 $this->error = "ErrorBadParameter";
564 return -1;
565 }
566
567 $sql = "SELECT fk_bank, url_id, url, label, type";
568 $sql .= " FROM ".MAIN_DB_PREFIX."bank_url";
569 if ($fk_bank > 0) {
570 $sql .= " WHERE fk_bank = ".((int) $fk_bank);
571 } else {
572 $sql .= " WHERE url_id = ".((int) $url_id)." AND type = '".$this->db->escape($type)."'";
573 }
574 $sql .= " ORDER BY type, label";
575
576 dol_syslog(get_class($this)."::get_url", LOG_DEBUG);
577 $result = $this->db->query($sql);
578 if ($result) {
579 $i = 0;
580 $num = $this->db->num_rows($result);
581 while ($i < $num) {
582 $obj = $this->db->fetch_object($result);
583 // Old links (for compatibility)
584 $lines[$i][0] = $obj->url;
585 $lines[$i][1] = $obj->url_id;
586 $lines[$i][2] = $obj->label;
587 $lines[$i][3] = $obj->type;
588 // New links
589 $lines[$i]['url'] = $obj->url;
590 $lines[$i]['url_id'] = $obj->url_id;
591 $lines[$i]['label'] = $obj->label;
592 $lines[$i]['type'] = $obj->type;
593 $lines[$i]['fk_bank'] = $obj->fk_bank;
594 $i++;
595 }
596 } else {
597 dol_print_error($this->db);
598 }
599
600 return $lines;
601 }
602
621 public function addline($date, $oper, $label, $amount, $num_chq, $categorie, User $user, $emetteur = '', $banque = '', $accountancycode = '', $datev = null, $num_releve = '', $amount_main_currency = null)
622 {
623 global $langs;
624
625 // Deprecation warning
626 if (is_numeric($oper)) {
627 dol_syslog(__METHOD__.": using numeric operations is deprecated", LOG_WARNING);
628 }
629
630 if (empty($this->id) && !empty($this->rowid)) { // For backward compatibility
631 $this->id = $this->rowid;
632 }
633
634 // Clean parameters
635 $emetteur = trim($emetteur);
636 $banque = trim($banque);
637 $label = trim($label);
638
639 $now = dol_now();
640
641 if (is_numeric($oper)) { // Clean operation to have a code instead of a rowid
642 $sql = "SELECT code FROM ".MAIN_DB_PREFIX."c_paiement";
643 $sql .= " WHERE id = ".((int) $oper);
644 $sql .= " AND entity IN (".getEntity('c_paiement').")";
645 $resql = $this->db->query($sql);
646 if ($resql) {
647 $obj = $this->db->fetch_object($resql);
648 $oper = $obj->code;
649 } else {
650 dol_print_error($this->db, 'Failed to get payment type code');
651 return -1;
652 }
653 }
654
655 // Check parameters
656 if (!$oper) {
657 $this->error = $langs->trans("OperNotDefined");
658 return -1;
659 }
660 if (!$this->id) {
661 $this->error = $langs->trans("ThisIdNotDefined");
662 return -2;
663 }
664 if ($this->type == Account::TYPE_CASH && $oper != 'LIQ') {
665 $this->error = "ErrorCashAccountAcceptsOnlyCashMoney";
666 return -3;
667 }
668
669 $this->db->begin();
670
671 if (is_null($datev) || empty($datev)) {
672 $datev = $date;
673 }
674
675 $accline = new AccountLine($this->db);
676 $accline->datec = $now;
677 $accline->dateo = $date;
678 $accline->datev = $datev;
679 $accline->label = $label;
680 $accline->amount = $amount;
681 $accline->amount_main_currency = $amount_main_currency;
682 $accline->fk_user_author = $user->id;
683 $accline->fk_account = $this->id;
684 $accline->fk_type = $oper;
685 $accline->numero_compte = $accountancycode;
686 $accline->num_releve = $num_releve;
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).", '".$this->db->escape($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 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Country"));
752 dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
753 return -1;
754 }
755 if (empty($this->ref)) {
756 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Ref"));
757 dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
758 return -1;
759 }
760 if (empty($this->date_solde)) {
761 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("DateInitialBalance"));
762 dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
763 return -1;
764 }
765
766 // Load libraries to check BAN
767 $balance = $this->balance;
768 if (empty($balance) && !empty($this->solde)) {
769 $balance = $this->solde;
770 }
771 if (empty($balance)) {
772 $balance = 0;
773 }
774 if (empty($this->status && !empty($this->clos))) {
775 dol_syslog(get_class($this)."::create clos is deprecated use status", LOG_NOTICE);
776 $this->status = $this->clos;
777 }
778
779 // Load the library to validate/check a BAN account
780 require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
781
782 $now = dol_now();
783
784 $this->db->begin();
785
786 $sql = "INSERT INTO ".MAIN_DB_PREFIX."bank_account (";
787 $sql .= "datec";
788 $sql .= ", ref";
789 $sql .= ", label";
790 $sql .= ", entity";
791 $sql .= ", account_number";
792 $sql .= ", fk_accountancy_journal";
793 $sql .= ", bank";
794 $sql .= ", code_banque";
795 $sql .= ", code_guichet";
796 $sql .= ", number";
797 $sql .= ", cle_rib";
798 $sql .= ", bic";
799 $sql .= ", iban_prefix";
800 $sql .= ", domiciliation";
801 $sql .= ", pti_in_ctti";
802 $sql .= ", proprio";
803 $sql .= ", owner_address";
804 $sql .= ", owner_zip";
805 $sql .= ", owner_town";
806 $sql .= ", owner_country_id";
807 $sql .= ", currency_code";
808 $sql .= ", rappro";
809 $sql .= ", min_allowed";
810 $sql .= ", min_desired";
811 $sql .= ", comment";
812 $sql .= ", state_id";
813 $sql .= ", fk_pays";
814 $sql .= ", ics";
815 $sql .= ", ics_transfer";
816 $sql .= ") VALUES (";
817 $sql .= "'".$this->db->idate($now)."'";
818 $sql .= ", '".$this->db->escape($this->ref)."'";
819 $sql .= ", '".$this->db->escape($this->label)."'";
820 $sql .= ", ".((int) $conf->entity);
821 $sql .= ", '".$this->db->escape($this->account_number)."'";
822 $sql .= ", ".($this->fk_accountancy_journal > 0 ? ((int) $this->fk_accountancy_journal) : "null");
823 $sql .= ", '".$this->db->escape($this->bank)."'";
824 $sql .= ", '".$this->db->escape($this->code_banque)."'";
825 $sql .= ", '".$this->db->escape($this->code_guichet)."'";
826 $sql .= ", '".$this->db->escape($this->number)."'";
827 $sql .= ", '".$this->db->escape($this->cle_rib)."'";
828 $sql .= ", '".$this->db->escape($this->bic)."'";
829 $sql .= ", '".$this->db->escape($this->iban)."'";
830 $sql .= ", '".$this->db->escape($this->address)."'";
831 $sql .= ", ".((int) $this->pti_in_ctti);
832 $sql .= ", '".$this->db->escape($this->owner_name)."'";
833 $sql .= ", '".$this->db->escape($this->owner_address)."'";
834 $sql .= ", '".$this->db->escape($this->owner_zip)."'";
835 $sql .= ", '".$this->db->escape($this->owner_town)."'";
836 $sql .= ", ".($this->owner_country_id > 0 ? ((int) $this->owner_country_id) : "null");
837 $sql .= ", '".$this->db->escape($this->currency_code)."'";
838 $sql .= ", ".((int) $this->rappro);
839 $sql .= ", ".price2num($this->min_allowed, 'MT');
840 $sql .= ", ".price2num($this->min_desired, 'MT');
841 $sql .= ", '".$this->db->escape($this->comment)."'";
842 $sql .= ", ".($this->state_id > 0 ? ((int) $this->state_id) : "null");
843 $sql .= ", ".($this->country_id > 0 ? ((int) $this->country_id) : "null");
844 $sql .= ", '".$this->db->escape($this->ics)."'";
845 $sql .= ", '".$this->db->escape($this->ics_transfer)."'";
846 $sql .= ")";
847
848 dol_syslog(get_class($this)."::create", LOG_DEBUG);
849 $resql = $this->db->query($sql);
850 if ($resql) {
851 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."bank_account");
852
853 $result = $this->update($user, 1);
854 if ($result > 0) {
855 $accline = new AccountLine($this->db);
856 $accline->datec = $now;
857 $accline->label = '('.$langs->trans("InitialBankBalance").')';
858 $accline->amount = (float) price2num($balance);
859 $accline->fk_user_author = $user->id;
860 $accline->fk_account = $this->id;
861 $accline->datev = $this->date_solde;
862 $accline->dateo = $this->date_solde;
863 $accline->fk_type = 'SOLD';
864
865 if ($accline->insert() < 0) {
866 $error++;
867 $this->error = $accline->error;
868 $this->errors = $accline->errors;
869 }
870
871 if (!$error) {
872 $result = $this->insertExtraFields();
873 if ($result < 0) {
874 $error++;
875 }
876 }
877
878 if (!$error && !$notrigger) {
879 // Call trigger
880 $result = $this->call_trigger('BANKACCOUNT_CREATE', $user);
881 if ($result < 0) {
882 $error++;
883 }
884 // End call triggers
885 }
886 } else {
887 $error++;
888 }
889 } else {
890 if ($this->db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
891 $this->error = $langs->trans("ErrorBankLabelAlreadyExists");
892 $error++;
893 } else {
894 $this->error = $this->db->error()." sql=".$sql;
895 $error++;
896 }
897 }
898
899 if (!$error) {
900 $this->db->commit();
901 return $this->id;
902 } else {
903 $this->db->rollback();
904 return -1 * $error;
905 }
906 }
907
915 public function update($user, $notrigger = 0)
916 {
917 global $langs, $conf;
918
919 $error = 0;
920
921 $this->db->begin();
922
923 // Check parameters
924 if (empty($this->country_id)) {
925 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Country"));
926 dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
927 return -1;
928 }
929 if (empty($this->ref)) {
930 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Ref"));
931 dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
932 return -1;
933 }
934 if (!$this->label) {
935 $this->label = "???";
936 }
937
938 $sql = "UPDATE ".MAIN_DB_PREFIX."bank_account SET";
939 $sql .= " ref = '".$this->db->escape($this->ref)."'";
940 $sql .= ",label = '".$this->db->escape($this->label)."'";
941 $sql .= ",courant = ".((int) $this->type);
942 $sql .= ",clos = ".((int) $this->status);
943 $sql .= ",rappro = ".((int) $this->rappro);
944 $sql .= ",url = ".($this->url ? "'".$this->db->escape($this->url)."'" : "null");
945 $sql .= ",account_number = '".$this->db->escape($this->account_number)."'";
946 $sql .= ",fk_accountancy_journal = ".($this->fk_accountancy_journal > 0 ? ((int) $this->fk_accountancy_journal) : "null");
947 $sql .= ",bank = '".$this->db->escape($this->bank)."'";
948 $sql .= ",code_banque='".$this->db->escape($this->code_banque)."'";
949 $sql .= ",code_guichet='".$this->db->escape($this->code_guichet)."'";
950 $sql .= ",number='".$this->db->escape($this->number)."'";
951 $sql .= ",cle_rib='".$this->db->escape($this->cle_rib)."'";
952 $sql .= ",bic='".$this->db->escape($this->bic)."'";
953 $sql .= ",iban_prefix = '".$this->db->escape($this->iban)."'";
954 $sql .= ",domiciliation='".$this->db->escape($this->address)."'";
955 $sql .= ",pti_in_ctti=".((int) $this->pti_in_ctti);
956 $sql .= ",proprio = '".$this->db->escape($this->owner_name)."'";
957 $sql .= ",owner_address = '".$this->db->escape($this->owner_address)."'";
958 $sql .= ",owner_zip = '".$this->db->escape($this->owner_zip)."'";
959 $sql .= ",owner_town = '".$this->db->escape($this->owner_town)."'";
960 $sql .= ",owner_country_id = ".($this->owner_country_id > 0 ? ((int) $this->owner_country_id) : "null");
961
962 $sql .= ",currency_code = '".$this->db->escape($this->currency_code)."'";
963
964 $sql .= ",min_allowed = ".($this->min_allowed != '' ? price2num($this->min_allowed) : "null");
965 $sql .= ",min_desired = ".($this->min_desired != '' ? price2num($this->min_desired) : "null");
966 $sql .= ",comment = '".$this->db->escape($this->comment)."'";
967
968 $sql .= ",state_id = ".($this->state_id > 0 ? ((int) $this->state_id) : "null");
969 $sql .= ",fk_pays = ".($this->country_id > 0 ? ((int) $this->country_id) : "null");
970 $sql .= ",ics = '".$this->db->escape($this->ics)."'";
971 $sql .= ",ics_transfer = '".$this->db->escape($this->ics_transfer)."'";
972
973 $sql .= " WHERE rowid = ".((int) $this->id);
974
975 dol_syslog(get_class($this)."::update", LOG_DEBUG);
976 $result = $this->db->query($sql);
977 if ($result) {
978 // Actions on extra fields (by external module or standard code)
979 if (!$error) {
980 $result = $this->insertExtraFields();
981 if ($result < 0) {
982 $error++;
983 }
984 }
985
986 if (!$error && !empty($this->oldref) && $this->oldref !== $this->ref) {
987 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'bank/".$this->db->escape($this->ref)."'";
988 $sql .= " WHERE filepath = 'bank/".$this->db->escape($this->oldref)."' and src_object_type='bank_account' and entity = ".((int) $conf->entity);
989 $resql = $this->db->query($sql);
990 if (!$resql) {
991 $error++;
992 $this->error = $this->db->lasterror();
993 }
994
995 // We rename directory in order not to lose the attachments
996 $oldref = dol_sanitizeFileName($this->oldref);
997 $newref = dol_sanitizeFileName($this->ref);
998 $dirsource = $conf->bank->dir_output.'/'.$oldref;
999 $dirdest = $conf->bank->dir_output.'/'.$newref;
1000 if (file_exists($dirsource)) {
1001 dol_syslog(get_class($this)."::update rename dir ".$dirsource." into ".$dirdest, LOG_DEBUG);
1002 if (@rename($dirsource, $dirdest)) {
1003 dol_syslog("Rename ok", LOG_DEBUG);
1004 }
1005 }
1006 }
1007
1008 if (!$error && !$notrigger) {
1009 // Call trigger
1010 $result = $this->call_trigger('BANKACCOUNT_MODIFY', $user);
1011 if ($result < 0) {
1012 $error++;
1013 }
1014 // End call triggers
1015 }
1016 } else {
1017 $error++;
1018 $this->error = $this->db->lasterror();
1019 dol_print_error($this->db);
1020 }
1021
1022 if (!$error) {
1023 $this->db->commit();
1024 return $this->id;
1025 } else {
1026 $this->db->rollback();
1027 return -1 * $error;
1028 }
1029 }
1030
1031
1032 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1039 public function update_bban($user = null)
1040 {
1041 // phpcs:enable
1042 global $conf, $langs;
1043
1044 // Load library to get BAN control function
1045 require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1046
1047 dol_syslog(get_class($this)."::update_bban $this->code_banque,$this->code_guichet,$this->number,$this->cle_rib,$this->iban");
1048
1049 // Check parameters
1050 if (!$this->ref) {
1051 $this->error = $langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->trans("Ref"));
1052 return -2;
1053 }
1054
1055 $sql = "UPDATE ".MAIN_DB_PREFIX."bank_account SET";
1056 $sql .= " bank = '".$this->db->escape($this->bank)."'";
1057 $sql .= ",code_banque='".$this->db->escape($this->code_banque)."'";
1058 $sql .= ",code_guichet='".$this->db->escape($this->code_guichet)."'";
1059 $sql .= ",number='".$this->db->escape($this->number)."'";
1060 $sql .= ",cle_rib='".$this->db->escape($this->cle_rib)."'";
1061 $sql .= ",bic='".$this->db->escape($this->bic)."'";
1062 $sql .= ",iban_prefix = '".$this->db->escape($this->iban)."'";
1063 $sql .= ",domiciliation='".$this->db->escape($this->address)."'";
1064 $sql .= ",proprio = '".$this->db->escape($this->owner_name)."'";
1065 $sql .= ",owner_address = '".$this->db->escape($this->owner_address)."'";
1066 $sql .= ",owner_zip = '".$this->db->escape($this->owner_zip)."'";
1067 $sql .= ",owner_town = '".$this->db->escape($this->owner_town)."'";
1068 $sql .= ",owner_country_id = ".($this->owner_country_id > 0 ? ((int) $this->owner_country_id) : "null");
1069 $sql .= ",state_id = ".($this->state_id > 0 ? $this->state_id : "null");
1070 $sql .= ",fk_pays = ".($this->country_id > 0 ? $this->country_id : "null");
1071 $sql .= " WHERE rowid = ".((int) $this->id);
1072 $sql .= " AND entity = ".((int) $conf->entity);
1073
1074 dol_syslog(get_class($this)."::update_bban", LOG_DEBUG);
1075
1076 $result = $this->db->query($sql);
1077 if ($result) {
1078 return 1;
1079 } else {
1080 $this->error = $this->db->lasterror();
1081 dol_print_error($this->db);
1082 return -1;
1083 }
1084 }
1085
1086
1094 public function fetch($id, $ref = '')
1095 {
1096 if (empty($id) && empty($ref)) {
1097 $this->error = "ErrorBadParameters";
1098 return -1;
1099 }
1100
1101 $sql = "SELECT ba.rowid, ba.ref, ba.label, ba.bank, ba.number, ba.courant as type, ba.clos as status, ba.rappro, ba.url,";
1102 $sql .= " ba.code_banque, ba.code_guichet, ba.cle_rib, ba.bic, ba.iban_prefix as iban,";
1103 $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,";
1104 $sql .= " ba.account_number, ba.fk_accountancy_journal, ba.currency_code,";
1105 $sql .= " ba.min_allowed, ba.min_desired, ba.comment,";
1106 $sql .= " ba.datec as date_creation, ba.tms as date_modification, ba.ics, ba.ics_transfer,";
1107 $sql .= ' c.code as country_code, c.label as country,';
1108 $sql .= ' d.code_departement as state_code, d.nom as state,';
1109 $sql .= ' aj.code as accountancy_journal';
1110 $sql .= " FROM ".MAIN_DB_PREFIX."bank_account as ba";
1111 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_country as c ON ba.fk_pays = c.rowid';
1112 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_departements as d ON ba.state_id = d.rowid';
1113 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'accounting_journal as aj ON aj.rowid=ba.fk_accountancy_journal';
1114 $sql .= " WHERE ba.entity IN (".getEntity($this->element).")";
1115 if ($id) {
1116 $sql .= " AND ba.rowid = ".((int) $id);
1117 }
1118 if ($ref) {
1119 $sql .= " AND ba.ref = '".$this->db->escape($ref)."'";
1120 }
1121
1122 dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
1123 $result = $this->db->query($sql);
1124 if ($result) {
1125 if ($this->db->num_rows($result)) {
1126 $obj = $this->db->fetch_object($result);
1127
1128 $this->id = $obj->rowid;
1129 $this->rowid = $obj->rowid;
1130 $this->ref = $obj->ref;
1131 $this->label = $obj->label;
1132 $this->type = $obj->type;
1133 $this->courant = $obj->type;
1134 $this->bank = $obj->bank;
1135 $this->clos = $obj->status;
1136 $this->status = $obj->status;
1137 $this->rappro = $obj->rappro;
1138 $this->url = $obj->url;
1139
1140 $this->code_banque = $obj->code_banque;
1141 $this->code_guichet = $obj->code_guichet;
1142 $this->number = $obj->number;
1143 $this->cle_rib = $obj->cle_rib;
1144 $this->bic = $obj->bic;
1145 $this->iban = $obj->iban;
1146 $this->address = $obj->address;
1147
1148 $this->owner_name = $obj->owner_name;
1149 $this->proprio = $this->owner_name;
1150 $this->owner_address = $obj->owner_address;
1151 $this->owner_zip = $obj->owner_zip;
1152 $this->owner_town = $obj->owner_town;
1153 $this->owner_country_id = $obj->owner_country_id;
1154
1155 $this->pti_in_ctti = $obj->pti_in_ctti;
1156
1157 $this->state_id = $obj->state_id;
1158 $this->state_code = $obj->state_code;
1159 $this->state = $obj->state;
1160
1161 $this->country_id = $obj->country_id;
1162 $this->country_code = $obj->country_code;
1163 $this->country = $obj->country;
1164
1165 $this->account_number = $obj->account_number;
1166 $this->fk_accountancy_journal = $obj->fk_accountancy_journal;
1167 $this->accountancy_journal = $obj->accountancy_journal;
1168
1169 $this->currency_code = $obj->currency_code;
1170 $this->account_currency_code = $obj->currency_code;
1171 $this->min_allowed = $obj->min_allowed;
1172 $this->min_desired = $obj->min_desired;
1173 $this->comment = $obj->comment;
1174
1175 $this->date_creation = $this->db->jdate($obj->date_creation);
1176 $this->date_modification = $this->db->jdate($obj->date_modification);
1177
1178 $this->ics = $obj->ics;
1179 $this->ics_transfer = $obj->ics_transfer;
1180
1181 // Retrieve all extrafield
1182 // fetch optionals attributes and labels
1183 $this->fetch_optionals();
1184
1185 return 1;
1186 } else {
1187 return 0;
1188 }
1189 } else {
1190 $this->error = $this->db->lasterror();
1191 $this->errors[] = $this->error;
1192 return -1;
1193 }
1194 }
1195
1206 public function setCategories($categories)
1207 {
1208 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1209 return parent::setCategoriesCommon($categories, Categorie::TYPE_ACCOUNT);
1210 }
1211
1219 public function delete($user = null, $notrigger = 0)
1220 {
1221 $error = 0;
1222
1223 $this->db->begin();
1224
1225 // @TODO Check there is no child into llx_payment_various, ... to allow deletion ?
1226
1227 // Delete link between tag and bank account
1228 if (!$error) {
1229 $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_account";
1230 $sql .= " WHERE fk_account = ".((int) $this->id);
1231
1232 $resql = $this->db->query($sql);
1233 if (!$resql) {
1234 $error++;
1235 $this->error = "Error ".$this->db->lasterror();
1236 }
1237 }
1238
1239 if (!$error) {
1240 $sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element;
1241 $sql .= " WHERE rowid = ".((int) $this->id);
1242
1243 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1244 $result = $this->db->query($sql);
1245 if ($result) {
1246 // Remove extrafields
1247 if (!$error) {
1248 $result = $this->deleteExtraFields();
1249 if ($result < 0) {
1250 $error++;
1251 dol_syslog(get_class($this)."::delete error -4 ".$this->error, LOG_ERR);
1252 }
1253 }
1254 } else {
1255 $error++;
1256 $this->error = "Error ".$this->db->lasterror();
1257 }
1258 }
1259
1260 if (!$error) {
1261 $this->db->commit();
1262 return 1;
1263 } else {
1264 $this->db->rollback();
1265 return -1;
1266 }
1267 }
1268
1269
1276 public function getLibStatut($mode = 0)
1277 {
1278 return $this->LibStatut($this->status, $mode);
1279 }
1280
1281 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1289 public function LibStatut($status, $mode = 0)
1290 {
1291 // phpcs:enable
1292 global $langs;
1293 $langs->load('banks');
1294
1295 if ($status == self::STATUS_OPEN) {
1296 $label = $langs->transnoentitiesnoconv("StatusAccountOpened");
1297 $labelshort = $langs->transnoentitiesnoconv("StatusAccountOpened");
1298 $statusType = 'status4';
1299 } else {
1300 $label = $langs->transnoentitiesnoconv("StatusAccountClosed");
1301 $labelshort = $langs->transnoentitiesnoconv("StatusAccountClosed");
1302 $statusType = 'status5';
1303 }
1304
1305 return dolGetStatus($label, $labelshort, '', $statusType, $mode);
1306 }
1307
1308
1309 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1315 public function can_be_deleted()
1316 {
1317 // phpcs:enable
1318 $can_be_deleted = false;
1319
1320 $sql = "SELECT COUNT(rowid) as nb";
1321 $sql .= " FROM ".MAIN_DB_PREFIX."bank";
1322 $sql .= " WHERE fk_account = ".((int) $this->id);
1323
1324 $resql = $this->db->query($sql);
1325 if ($resql) {
1326 $obj = $this->db->fetch_object($resql);
1327 if ($obj->nb <= 1) {
1328 $can_be_deleted = true; // Juste le solde
1329 }
1330 } else {
1331 dol_print_error($this->db);
1332 }
1333 return $can_be_deleted;
1334 }
1335
1336
1342 public function error()
1343 {
1344 return $this->error;
1345 }
1346
1355 public function solde($option = 0, $date_end = '', $field = 'dateo')
1356 {
1357 $solde = 0;
1358
1359 $sql = "SELECT sum(amount) as amount";
1360 $sql .= " FROM ".MAIN_DB_PREFIX."bank";
1361 $sql .= " WHERE fk_account = ".((int) $this->id);
1362 if ($option == 1) {
1363 $sql .= " AND ".$this->db->escape($field)." <= '".(!empty($date_end) ? $this->db->idate($date_end) : $this->db->idate(dol_now()))."'";
1364 }
1365
1366 $resql = $this->db->query($sql);
1367 if ($resql) {
1368 if ($this->db->num_rows($resql)) {
1369 $obj = $this->db->fetch_object($resql);
1370 $solde = $obj->amount;
1371 }
1372 $this->db->free($resql);
1373 } else {
1374 $this->errors[] = $this->db->lasterror;
1375 return -1;
1376 }
1377
1378 return (float) price2num($solde, 'MU');
1379 }
1380
1381 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1389 public function load_board(User $user, $filteraccountid = 0)
1390 {
1391 // phpcs:enable
1392 global $conf, $langs;
1393
1394 if ($user->socid) {
1395 return -1; // protection pour eviter appel par utilisateur externe
1396 }
1397
1398 $sql = "SELECT b.rowid, b.datev as datefin";
1399 $sql .= " FROM ".MAIN_DB_PREFIX."bank as b,";
1400 $sql .= " ".MAIN_DB_PREFIX."bank_account as ba";
1401 $sql .= " WHERE b.rappro=0";
1402 $sql .= " AND b.fk_account = ba.rowid";
1403 $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
1404 $sql .= " AND (ba.rappro = 1 AND ba.courant != " . Account::TYPE_CASH . ")"; // Compte rapprochable
1405 $sql .= " AND clos = 0";
1406 if ($filteraccountid) {
1407 $sql .= " AND ba.rowid = ".((int) $filteraccountid);
1408 }
1409
1410 $resql = $this->db->query($sql);
1411 if ($resql) {
1412 $langs->load("banks");
1413 $now = dol_now();
1414
1415 require_once DOL_DOCUMENT_ROOT.'/core/class/workboardresponse.class.php';
1416
1417 $response = new WorkboardResponse();
1418 $response->warning_delay = $conf->bank->rappro->warning_delay / 60 / 60 / 24;
1419 $response->label = $langs->trans("TransactionsToConciliate");
1420 $response->labelShort = $langs->trans("TransactionsToConciliateShort");
1421 $response->url = DOL_URL_ROOT.'/compta/bank/list.php?leftmenu=bank&amp;mainmenu=bank';
1422 $response->img = img_object('', "payment");
1423
1424 while ($obj = $this->db->fetch_object($resql)) {
1425 $response->nbtodo++;
1426 if ($this->db->jdate($obj->datefin) < ($now - $conf->bank->rappro->warning_delay)) {
1427 $response->nbtodolate++;
1428 }
1429 }
1430
1431 return $response;
1432 } else {
1433 dol_print_error($this->db);
1434 $this->error = $this->db->error();
1435 return -1;
1436 }
1437 }
1438
1445 public function loadStateBoard($filteraccountid = 0)
1446 {
1447 global $user;
1448
1449 if ($user->socid) {
1450 return -1; // protection pour eviter appel par utilisateur externe
1451 }
1452
1453 $sql = "SELECT count(b.rowid) as nb";
1454 $sql .= " FROM ".MAIN_DB_PREFIX."bank as b,";
1455 $sql .= " ".MAIN_DB_PREFIX."bank_account as ba";
1456 $sql .= " WHERE b.fk_account = ba.rowid";
1457 $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
1458 $sql .= " AND (ba.rappro = 1 AND ba.courant != 2)"; // Compte rapprochable
1459 $sql .= " AND clos = 0";
1460 if ($filteraccountid) {
1461 $sql .= " AND ba.rowid = ".((int) $filteraccountid);
1462 }
1463
1464 $resql = $this->db->query($sql);
1465 if ($resql) {
1466 while ($obj = $this->db->fetch_object($resql)) {
1467 $this->nb["banklines"] = $obj->nb;
1468 }
1469 $this->db->free($resql);
1470 return 1;
1471 } else {
1472 dol_print_error($this->db);
1473 $this->error = $this->db->error();
1474 return -1;
1475 }
1476 }
1477
1478
1484 public function countAccountToReconcile()
1485 {
1486 global $user;
1487
1488 //Protection against external users
1489 if ($user->socid) {
1490 return 0;
1491 }
1492
1493 $nb = 0;
1494
1495 $sql = "SELECT COUNT(ba.rowid) as nb";
1496 $sql .= " FROM ".MAIN_DB_PREFIX."bank_account as ba";
1497 $sql .= " WHERE ba.rappro > 0 and ba.clos = 0";
1498 $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
1499 if (!getDolGlobalString('BANK_CAN_RECONCILIATE_CASHACCOUNT')) {
1500 $sql .= " AND ba.courant != " . Account::TYPE_CASH;
1501 }
1502
1503 $resql = $this->db->query($sql);
1504 if ($resql) {
1505 $obj = $this->db->fetch_object($resql);
1506 $nb = $obj->nb;
1507 } else {
1508 dol_print_error($this->db);
1509 }
1510
1511 return $nb;
1512 }
1513
1520 public function getTooltipContentArray($params)
1521 {
1522 global $langs;
1523 $langs->loadLangs(['banks', 'compta']);
1524 include_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1525
1526 $datas = array();
1527
1528 $nofetch = !empty($params['nofetch']);
1529 $pictos = img_picto('', $this->picto).' <u class="paddingrightnow">'.$langs->trans("BankAccount").'</u>';
1530 if (isset($this->status)) {
1531 $pictos .= ' '.$this->getLibStatut(5);
1532 }
1533 $datas['picto'] = $pictos;
1534 $datas['label'] = '<br><b>'.$langs->trans('Label').':</b> '.$this->label;
1535 $datas['accountnumber'] = '<br><b>'.$langs->trans('AccountNumber').':</b> '.$this->number;
1536 $datas['iban'] = '<br><b>'.$langs->trans('IBAN').':</b> '.getIbanHumanReadable($this);
1537 $datas['bic'] = '<br><b>'.$langs->trans('BIC').':</b> '.$this->bic;
1538 $datas['accountcurrency'] = '<br><b>'.$langs->trans("AccountCurrency").':</b> '.$this->currency_code;
1539
1540 if (isModEnabled('accounting')) {
1541 include_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
1542 $langs->load("accountancy");
1543 $datas['accountaccounting'] = '<br><b>'.$langs->trans('AccountAccounting').':</b> '.length_accountg($this->account_number);
1544 $datas['accountancyjournal'] = '<br><b>'.$langs->trans('AccountancyJournal').':</b> '.$this->accountancy_journal;
1545 }
1546 // show categories for this record only in ajax to not overload lists
1547 if (isModEnabled('category') && !$nofetch) {
1548 require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
1549 $form = new Form($this->db);
1550 $datas['categories'] = '<br>' . $form->showCategories($this->id, Categorie::TYPE_ACCOUNT, 1);
1551 }
1552
1553 return $datas;
1554 }
1555
1567 public function getNomUrl($withpicto = 0, $mode = '', $option = '', $save_lastsearch_value = -1, $notooltip = 0, $morecss = '')
1568 {
1569 global $conf, $langs;
1570
1571 if (!empty($conf->dol_no_mouse_hover)) {
1572 $notooltip = 1; // Force disable tooltips
1573 }
1574
1575 include_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1576
1577 $result = '';
1578 $classfortooltip = 'classfortooltip';
1579 $dataparams = '';
1580 $params = [
1581 'id' => $this->id,
1582 'objecttype' => $this->element,
1583 'option' => $option,
1584 'nofetch' => 1,
1585 ];
1586 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1587 $classfortooltip = 'classforajaxtooltip';
1588 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
1589 $label = '';
1590 } else {
1591 $label = implode($this->getTooltipContentArray($params));
1592 }
1593
1594 $url = DOL_URL_ROOT.'/compta/bank/card.php?id='.$this->id;
1595 if ($mode == 'transactions') {
1596 $url = DOL_URL_ROOT.'/compta/bank/bankentries_list.php?id='.$this->id;
1597 } elseif ($mode == 'receipts') {
1598 $url = DOL_URL_ROOT.'/compta/bank/releve.php?account='.$this->id;
1599 }
1600
1601 if ($option != 'nolink') {
1602 // Add param to save lastsearch_values or not
1603 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1604 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1605 $add_save_lastsearch_values = 1;
1606 }
1607 if ($add_save_lastsearch_values) {
1608 $url .= '&save_lastsearch_values=1';
1609 }
1610 }
1611
1612 $linkclose = '';
1613 if (empty($notooltip)) {
1614 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1615 $label = $langs->trans("BankAccount");
1616 $linkclose .= ' alt="'.dolPrintHTMLForAttribute($label).'"';
1617 }
1618 $linkclose .= ($label ? ' title="'.dolPrintHTMLForAttribute($label).'"' : ' title="tocomplete"');
1619 $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
1620 } else {
1621 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1622 }
1623
1624 if ($option == 'nolink' || empty($url)) {
1625 $linkstart = '<span';
1626 } else {
1627 $linkstart = '<a href="'.$url.'"';
1628 }
1629 $linkstart .= $linkclose.'>';
1630 if ($option == 'nolink' || empty($url)) {
1631 $linkend = '</span>';
1632 } else {
1633 $linkend = '</a>';
1634 }
1635
1636 $result .= $linkstart;
1637
1638 if ($withpicto) {
1639 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"'), 0, 0, $notooltip ? 0 : 1);
1640 }
1641 if ($withpicto != 2) {
1642 $result .= $this->ref.($option == 'reflabel' && $this->label ? ' - '.$this->label : '');
1643 }
1644 $result .= $linkend;
1645
1646 return $result;
1647 }
1648
1649
1650 // Method after here are common to Account and CompanyBankAccount
1651
1652
1658 public function verif()
1659 {
1660 require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
1661
1662 $error = 0;
1663
1664 // Call functions to check BAN
1665 if (!checkIbanForAccount($this)) {
1666 $error++;
1667 $this->error = 'IBANNotValid';
1668 }
1669 // Call function to check Swift/BIC.
1670 // A non valid BIC/Swift is a problem if: it is not empty or always a problem if WITHDRAWAL_WITHOUT_BIC is not set).
1671 if (!checkSwiftForAccount($this) && (!empty($this->bic) || !getDolGlobalInt('WITHDRAWAL_WITHOUT_BIC'))) {
1672 $error++;
1673 $this->error = 'SwiftNotValid';
1674 }
1675
1676 if (! $error) {
1677 return 1;
1678 } else {
1679 return 0;
1680 }
1681 }
1682
1688 public function getCountryCode()
1689 {
1690 global $mysoc;
1691
1692 // We return country code of bank account
1693 if (!empty($this->country_code)) {
1694 return $this->country_code;
1695 }
1696
1697 // For backward compatibility, we try to guess country from other information
1698 if (!empty($this->iban)) {
1699 // If IBAN defined, we can know country of account from it
1700 $reg = array();
1701 if (preg_match("/^([a-zA-Z][a-zA-Z])/i", $this->iban, $reg)) {
1702 return $reg[1];
1703 }
1704 }
1705
1706 // If this class is linked to a third party
1707 if (!empty($this->socid)) {
1708 require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
1709 $company = new Societe($this->db);
1710 $result = $company->fetch($this->socid);
1711 if (!empty($company->country_code)) {
1712 return $company->country_code;
1713 }
1714 }
1715
1716 // We return country code of managed company
1717 if (!empty($mysoc->country_code)) {
1718 return $mysoc->country_code;
1719 }
1720
1721 return '';
1722 }
1723
1731 public function getBannerAddress($htmlkey, $object)
1732 {
1733 global $conf, $langs;
1734
1735 $out = '';
1736
1737 $outdone = 0;
1738 $coords = $this->getFullAddress(1, ', ', getDolGlobalInt('MAIN_SHOW_REGION_IN_STATE_SELECT'));
1739 if ($coords) {
1740 if (!empty($conf->use_javascript_ajax)) {
1741 // hideonsmatphone because copyToClipboard call jquery dialog that does not work with jmobile
1742 $out .= '<a href="#" class="hideonsmartphone" onclick="return copyToClipboard(\''.dol_escape_js($coords).'\',\''.dol_escape_js($langs->trans("HelpCopyToClipboard")).'\');">';
1743 $out .= img_picto($langs->trans("Address"), 'map-marker-alt');
1744 $out .= '</a> ';
1745 }
1746 $address = dol_print_address($coords, 'address_'.$htmlkey.'_'.$this->id, $this->element, $this->id, 1, ', ');
1747 if ($address) {
1748 $out .= $address;
1749 $outdone++;
1750 }
1751 $outdone++;
1752 }
1753
1754 return $out;
1755 }
1756
1757
1766 public function useDetailedBBAN()
1767 {
1768 $country_code = $this->getCountryCode();
1769
1770 if (in_array($country_code, array('FR', 'ES', 'GA', 'IT', 'NC'))) {
1771 return 1; // France, Spain, Gabon, ... - Not valid for CH
1772 }
1773 if (in_array($country_code, array('AD', 'AU', 'BE', 'CA', 'DE', 'DK', 'GR', 'GB', 'ID', 'IE', 'IR', 'KR', 'NL', 'NZ', 'UK', 'US'))) {
1774 return 2; // Australia, England...
1775 }
1776 return 0;
1777 }
1778
1784 public function needIBAN()
1785 {
1786 global $conf;
1787
1788 if (getDolGlobalString('MAIN_IBAN_IS_NEVER_MANDATORY')) {
1789 return 0;
1790 }
1791
1792 $country_code = $this->getCountryCode();
1793
1794 $country_code_in_EEC = array(
1795 'AT', // Austria
1796 'BE', // Belgium
1797 'BG', // Bulgaria
1798 'CY', // Cyprus
1799 'CZ', // Czech republic
1800 'DE', // Germany
1801 'DK', // Danemark
1802 'EE', // Estonia
1803 'ES', // Spain
1804 'FI', // Finland
1805 'FR', // France
1806 'GB', // United Kingdom
1807 'GR', // Greece
1808 'HR', // Croatia
1809 'NL', // Holland
1810 'HU', // Hungary
1811 'IE', // Ireland
1812 'IM', // Isle of Man - Included in UK
1813 'IT', // Italy
1814 'LT', // Lithuania
1815 'LU', // Luxembourg
1816 'LV', // Latvia
1817 'MC', // Monaco - Included in France
1818 'MT', // Malta
1819 //'NO', // Norway
1820 'PL', // Poland
1821 'PT', // Portugal
1822 'RO', // Romania
1823 'SE', // Sweden
1824 'SK', // Slovakia
1825 'SI', // Slovenia
1826 'UK', // United Kingdom
1827 //'CH', // Switzerland - No. Swizerland in not in EEC
1828 );
1829
1830 if (in_array($country_code, $country_code_in_EEC)) {
1831 return 1; // France, Spain, ...
1832 }
1833 return 0;
1834 }
1835
1841 public function needBIC()
1842 {
1843 if (getDolGlobalString('MAIN_IBAN_IS_NEVER_MANDATORY')) {
1844 return 0;
1845 }
1846
1847 $country_code = $this->getCountryCode();
1848
1849 $country_code_in_EEC = array(
1850 'AD', // Andorra
1851 'BH', // Bahrein
1852 'DK', // Denmark
1853 'FR', // France
1854 'GH', // Ghana
1855 'HU', // Hungary
1856 'JP', // Japan
1857 'LV', // Latvia
1858 'SE', // Sweden
1859 );
1860
1861 if (in_array($country_code, $country_code_in_EEC)) {
1862 return 1; // Andorra, Bahrein, ...
1863 }
1864 return 0;
1865 }
1866
1873 public function info($id)
1874 {
1875 }
1876
1891 public function getFieldsToShow($includeibanbic = 0)
1892 {
1893 //Get the required properties depending on the country
1894 $detailedBBAN = $this->useDetailedBBAN();
1895
1896 if ($detailedBBAN == 0) {
1897 $fieldarray = array(
1898 'BankAccountNumber'
1899 );
1900 } elseif ($detailedBBAN == 2) {
1901 $fieldarray = array(
1902 'BankCode',
1903 'BankAccountNumber'
1904 );
1905 } else {
1906 $fieldarray = self::getAccountNumberOrder();
1907 }
1908
1909 //if ($this->needIBAN()) { // return always IBAN and BIC (this was old behaviour)
1910 if ($includeibanbic) {
1911 $fieldarray[] = 'IBAN';
1912 $fieldarray[] = 'BIC';
1913 }
1914 //}
1915
1916 //Get the order the properties are shown
1917 return $fieldarray;
1918 }
1919
1930 public static function getAccountNumberOrder()
1931 {
1932 global $conf;
1933
1934 $fieldlists = array(
1935 'BankCode',
1936 'DeskCode',
1937 'BankAccountNumber',
1938 'BankAccountNumberKey'
1939 );
1940
1941 if (getDolGlobalString('BANK_SHOW_ORDER_OPTION')) {
1942 if (is_numeric(getDolGlobalString('BANK_SHOW_ORDER_OPTION'))) {
1943 if (getDolGlobalString('BANK_SHOW_ORDER_OPTION') == '1') {
1944 $fieldlists = array(
1945 'BankCode',
1946 'DeskCode',
1947 'BankAccountNumberKey',
1948 'BankAccountNumber'
1949 );
1950 }
1951 } else {
1952 //Replace the old AccountNumber key with the new BankAccountNumber key
1953 $fieldlists = explode(
1954 ' ',
1955 preg_replace('/ ?[^Bank]AccountNumber ?/', 'BankAccountNumber', $conf->global->BANK_SHOW_ORDER_OPTION)
1956 );
1957 }
1958 }
1959
1960 return $fieldlists;
1961 }
1962
1963
1971 public function initAsSpecimen()
1972 {
1973 // Example of IBAN FR7630001007941234567890185
1974 $this->specimen = 1;
1975 $this->ref = 'MBA';
1976 $this->label = 'My Big Company Bank account';
1977 $this->courant = Account::TYPE_CURRENT;
1978 $this->clos = Account::STATUS_OPEN;
1979 $this->type = Account::TYPE_CURRENT;
1980 $this->status = Account::STATUS_OPEN;
1981 $this->code_banque = '30001';
1982 $this->code_guichet = '00794';
1983 $this->number = '12345678901';
1984 $this->cle_rib = '85';
1985 $this->bic = 'AA12';
1986 $this->iban = 'FR7630001007941234567890185';
1987
1988 $this->bank = 'MyBank';
1989 $this->address = 'Rue de Paris';
1990 $this->owner_name = 'Owner';
1991 $this->owner_address = 'Owner address';
1992 $this->owner_zip = 'Owner zip';
1993 $this->owner_town = 'Owner town';
1994 $this->owner_country_id = 1;
1995 $this->country_id = 1;
1996
1997 return 1;
1998 }
1999
2008 public static function replaceThirdparty($dbs, $origin_id, $dest_id)
2009 {
2010 $sql = "UPDATE ".MAIN_DB_PREFIX."bank_url SET url_id = ".((int) $dest_id)." WHERE url_id = ".((int) $origin_id)." AND type='company'";
2011
2012 if ($dbs->query($sql)) {
2013 return true;
2014 } else {
2015 //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.
2016 //$this->errors = $dbs->lasterror();
2017 return false;
2018 }
2019 }
2020
2028 public function getKanbanView($option = '', $arraydata = null)
2029 {
2030 global $langs;
2031
2032 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
2033
2034 $return = '<div class="box-flex-item box-flex-grow-zero">';
2035 $return .= '<div class="info-box info-box-sm">';
2036 $return .= '<span class="info-box-icon bg-infobox-action">';
2037 $return .= img_picto('', $this->picto);
2038 $return .= '</span>';
2039 $return .= '<div class="info-box-content">';
2040 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).'</span>';
2041 if ($selected >= 0) {
2042 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
2043 }
2044 if (property_exists($this, 'type_lib')) {
2045 $return .= '<br><span class="info-box-label opacitymedium" title="'.$this->type_lib[$this->type].'">'.substr($this->type_lib[$this->type], 0, 24).'...</span>';
2046 }
2047 if (method_exists($this, 'solde')) {
2048 $return .= '<br><a href="'.DOL_URL_ROOT.'/compta/bank/bankentries_list.php?id='.$this->id.'">';
2049 $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>';
2050 }
2051 if (method_exists($this, 'getLibStatut')) {
2052 $return .= '<br><div class="info-box-status">'.$this->getLibStatut(3).'</div>';
2053 }
2054 $return .= '</div>';
2055 $return .= '</div>';
2056 $return .= '</div>';
2057 return $return;
2058 }
2059}
2060
2061
2062require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
2063
2067class AccountLine extends CommonObjectLine
2068{
2072 public $db;
2073
2077 public $element = 'bank';
2078
2082 public $table_element = 'bank';
2083
2087 public $picto = 'accountline';
2088
2092 public $id;
2093
2097 public $ref;
2098
2104 public $datec;
2105
2111 public $dateo;
2112
2118 public $datev;
2119
2123 public $amount;
2124
2128 public $amount_main_currency;
2129
2133 public $fk_user_author;
2134
2138 public $fk_user_rappro;
2139
2143 public $fk_type;
2144
2148 public $fk_bordereau;
2149
2153 public $fk_account;
2154
2158 public $bank_account_ref;
2159
2163 public $bank_account_label;
2164
2168 public $numero_compte;
2169
2173 public $emetteur;
2174
2178 public $rappro;
2179
2183 public $num_releve;
2184
2188 public $num_chq;
2189
2193 public $bank_chq;
2194
2198 public $label;
2199
2203 public $note;
2204
2210 public $user_rappro;
2211
2212
2218 public function __construct(DoliDB $db)
2219 {
2220 $this->db = $db;
2221 }
2222
2231 public function fetch($rowid, $ref = '', $num = '')
2232 {
2233 // Check parameters
2234 if (empty($rowid) && empty($ref) && empty($num)) {
2235 return -1;
2236 }
2237
2238 $sql = "SELECT b.rowid, b.datec, b.datev, b.dateo, b.amount, b.label as label, b.fk_account,";
2239 $sql .= " b.fk_user_author, b.fk_user_rappro,";
2240 $sql .= " b.fk_type, b.num_releve, b.num_chq, b.rappro, b.note,";
2241 $sql .= " b.fk_bordereau, b.banque, b.emetteur,";
2242 $sql .= " ba.ref as bank_account_ref, ba.label as bank_account_label";
2243 $sql .= " FROM ".MAIN_DB_PREFIX."bank as b,";
2244 $sql .= " ".MAIN_DB_PREFIX."bank_account as ba";
2245 $sql .= " WHERE b.fk_account = ba.rowid";
2246 $sql .= " AND ba.entity IN (".getEntity('bank_account').")";
2247 if ($num) {
2248 $sql .= " AND b.num_chq = '".$this->db->escape($num)."'";
2249 } elseif ($ref) {
2250 $sql .= " AND b.rowid = '".$this->db->escape($ref)."'";
2251 } else {
2252 $sql .= " AND b.rowid = ".((int) $rowid);
2253 }
2254
2255 dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
2256 $result = $this->db->query($sql);
2257 if ($result) {
2258 $ret = 0;
2259
2260 $obj = $this->db->fetch_object($result);
2261 if ($obj) {
2262 $this->id = $obj->rowid;
2263 $this->rowid = $obj->rowid;
2264 $this->ref = $obj->rowid;
2265
2266 $this->datec = $this->db->jdate($obj->datec);
2267 $this->datev = $this->db->jdate($obj->datev);
2268 $this->dateo = $this->db->jdate($obj->dateo);
2269 $this->amount = $obj->amount;
2270 $this->label = $obj->label;
2271 $this->note = $obj->note;
2272
2273 $this->fk_user_author = $obj->fk_user_author;
2274 $this->fk_user_rappro = $obj->fk_user_rappro;
2275
2276 $this->fk_type = $obj->fk_type; // Type of transaction
2277 $this->rappro = (int) $obj->rappro;
2278 $this->num_releve = $obj->num_releve;
2279
2280 $this->num_chq = $obj->num_chq;
2281 $this->bank_chq = $obj->banque;
2282 $this->fk_bordereau = $obj->fk_bordereau;
2283
2284 $this->fk_account = $obj->fk_account;
2285 $this->bank_account_ref = $obj->bank_account_ref;
2286 $this->bank_account_label = $obj->bank_account_label;
2287
2288 // Retrieve all extrafield
2289 // fetch optionals attributes and labels
2290 $this->fetch_optionals();
2291
2292 $ret = 1;
2293 }
2294 $this->db->free($result);
2295 return $ret;
2296 } else {
2297 return -1;
2298 }
2299 }
2300
2306 public function insert()
2307 {
2308 $error = 0;
2309
2310 $this->db->begin();
2311
2312 $sql = "INSERT INTO ".MAIN_DB_PREFIX."bank (";
2313 $sql .= "datec";
2314 $sql .= ", dateo";
2315 $sql .= ", datev";
2316 $sql .= ", label";
2317 $sql .= ", amount";
2318 $sql .= ", amount_main_currency";
2319 $sql .= ", fk_user_author";
2320 $sql .= ", num_chq";
2321 $sql .= ", fk_account";
2322 $sql .= ", fk_type";
2323 $sql .= ", emetteur,banque";
2324 $sql .= ", rappro";
2325 $sql .= ", numero_compte";
2326 $sql .= ", num_releve";
2327 $sql .= ") VALUES (";
2328 $sql .= "'".$this->db->idate($this->datec)."'";
2329 $sql .= ", '".$this->db->idate($this->dateo)."'";
2330 $sql .= ", '".$this->db->idate($this->datev)."'";
2331 $sql .= ", '".$this->db->escape($this->label)."'";
2332 $sql .= ", ".price2num($this->amount);
2333 $sql .= ", ".(empty($this->amount_main_currency) ? "NULL" : price2num($this->amount_main_currency));
2334 $sql .= ", ".($this->fk_user_author > 0 ? ((int) $this->fk_user_author) : "null");
2335 $sql .= ", ".($this->num_chq ? "'".$this->db->escape($this->num_chq)."'" : "null");
2336 $sql .= ", '".$this->db->escape($this->fk_account)."'";
2337 $sql .= ", '".$this->db->escape($this->fk_type)."'";
2338 $sql .= ", ".($this->emetteur ? "'".$this->db->escape($this->emetteur)."'" : "null");
2339 $sql .= ", ".($this->bank_chq ? "'".$this->db->escape($this->bank_chq)."'" : "null");
2340 $sql .= ", ".(int) $this->rappro;
2341 $sql .= ", ".($this->numero_compte ? "'".$this->db->escape($this->numero_compte)."'" : "''");
2342 $sql .= ", ".($this->num_releve ? "'".$this->db->escape($this->num_releve)."'" : "null");
2343 $sql .= ")";
2344
2345
2346 dol_syslog(get_class($this)."::insert", LOG_DEBUG);
2347 $resql = $this->db->query($sql);
2348 if ($resql) {
2349 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'bank');
2350 // Actions on extra fields (by external module or standard code)
2351 $result = $this->insertExtraFields();
2352 if ($result < 0) {
2353 $error++;
2354 }
2355 } else {
2356 $error++;
2357 $this->error = $this->db->lasterror();
2358 dol_print_error($this->db);
2359 }
2360
2361 if (!$error) {
2362 $this->db->commit();
2363 return $this->id;
2364 } else {
2365 $this->db->rollback();
2366 return -1 * $error;
2367 }
2368 }
2369
2377 public function delete($user = null, $notrigger = 0)
2378 {
2379 $nbko = 0;
2380
2381 if ($this->rappro) {
2382 // Protection to avoid any delete of consolidated lines
2383 $this->error = "ErrorDeleteNotPossibleLineIsConsolidated";
2384 return -1;
2385 }
2386
2387 $this->db->begin();
2388
2389 if (!$notrigger) {
2390 // Call trigger
2391 $result = $this->call_trigger('BANKACCOUNTLINE_DELETE', $user);
2392 if ($result < 0) {
2393 $this->db->rollback();
2394 return -1;
2395 }
2396 // End call triggers
2397 }
2398
2399 // Protection to avoid any delete of accounted lines. Protection on by default
2400 if (!getDolGlobalString('BANK_ALLOW_TRANSACTION_DELETION_EVEN_IF_IN_ACCOUNTING')) {
2401 $sql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."accounting_bookkeeping WHERE doc_type = 'bank' AND fk_doc = ".((int) $this->id);
2402 $resql = $this->db->query($sql);
2403 if ($resql) {
2404 $obj = $this->db->fetch_object($resql);
2405 if ($obj && $obj->nb) {
2406 $this->error = 'ErrorRecordAlreadyInAccountingDeletionNotPossible';
2407 $this->db->rollback();
2408 return -1;
2409 }
2410 } else {
2411 $this->error = $this->db->lasterror();
2412 $this->db->rollback();
2413 return -1;
2414 }
2415 }
2416
2417 // Delete urls
2418 $result = $this->delete_urls($user);
2419 if ($result < 0) {
2420 $nbko++;
2421 }
2422
2423 $sql = "DELETE FROM ".MAIN_DB_PREFIX."category_bankline WHERE lineid=".(int) $this->rowid;
2424 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
2425 $result = $this->db->query($sql);
2426 if (!$result) {
2427 $nbko++;
2428 }
2429
2430 $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank_extrafields WHERE fk_object=".(int) $this->rowid;
2431 $result = $this->db->query($sql);
2432 if (!$result) {
2433 $nbko++;
2434 }
2435
2436 $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank WHERE rowid=".(int) $this->rowid;
2437 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
2438 $result = $this->db->query($sql);
2439 if (!$result) {
2440 $nbko++;
2441 }
2442
2443 if (!$nbko) {
2444 $this->db->commit();
2445 return 1;
2446 } else {
2447 $this->db->rollback();
2448 return -$nbko;
2449 }
2450 }
2451
2452
2453 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2460 public function delete_urls($user = null)
2461 {
2462 // phpcs:enable
2463 $nbko = 0;
2464
2465 if ($this->rappro) {
2466 // Protection to avoid any delete of consolidated lines
2467 $this->error = "ErrorDeleteNotPossibleLineIsConsolidated";
2468 return -1;
2469 }
2470
2471 $this->db->begin();
2472
2473 $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank_url WHERE fk_bank=".(int) $this->rowid;
2474 dol_syslog(get_class($this)."::delete_urls", LOG_DEBUG);
2475 $result = $this->db->query($sql);
2476 if (!$result) {
2477 $nbko++;
2478 }
2479
2480 if (!$nbko) {
2481 $this->db->commit();
2482 return 1;
2483 } else {
2484 $this->db->rollback();
2485 return -$nbko;
2486 }
2487 }
2488
2489
2497 public function update(User $user, $notrigger = 0)
2498 {
2499 $this->db->begin();
2500
2501 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2502 $sql .= " amount = ".price2num($this->amount).",";
2503 $sql .= " datev='".$this->db->idate($this->datev)."',";
2504 $sql .= " dateo='".$this->db->idate($this->dateo)."'";
2505 $sql .= " WHERE rowid = ".((int) $this->rowid);
2506
2507 dol_syslog(get_class($this)."::update", LOG_DEBUG);
2508 $resql = $this->db->query($sql);
2509 if ($resql) {
2510 $this->db->commit();
2511 return 1;
2512 } else {
2513 $this->db->rollback();
2514 $this->error = $this->db->error();
2515 return -1;
2516 }
2517 }
2518
2519
2525 public function updateLabel()
2526 {
2527 $this->db->begin();
2528
2529 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2530 $sql .= " label = '".$this->db->escape($this->label)."'";
2531 $sql .= " WHERE rowid = ".((int) $this->rowid);
2532
2533 dol_syslog(get_class($this)."::update_label", LOG_DEBUG);
2534 $resql = $this->db->query($sql);
2535 if ($resql) {
2536 $this->db->commit();
2537 return 1;
2538 } else {
2539 $this->db->rollback();
2540 $this->error = $this->db->error();
2541 return -1;
2542 }
2543 }
2544
2545
2546 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2555 public function update_conciliation(User $user, $cat, $conciliated = 1)
2556 {
2557 // phpcs:enable
2558 global $conf, $langs;
2559
2560 $this->db->begin();
2561
2562 // Check statement field
2563 if (getDolGlobalString('BANK_STATEMENT_REGEX_RULE')) {
2564 if (!preg_match('/' . getDolGlobalString('BANK_STATEMENT_REGEX_RULE').'/', $this->num_releve)) {
2565 $this->errors[] = $langs->trans("ErrorBankStatementNameMustFollowRegex", getDolGlobalString('BANK_STATEMENT_REGEX_RULE'));
2566 return -1;
2567 }
2568 }
2569
2570 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2571 $sql .= " rappro = ".((int) $conciliated);
2572 $sql .= ", num_releve = '".$this->db->escape($this->num_releve)."'";
2573 if ($conciliated) {
2574 $sql .= ", fk_user_rappro = ".$user->id;
2575 }
2576 $sql .= " WHERE rowid = ".((int) $this->id);
2577
2578 dol_syslog(get_class($this)."::update_conciliation", LOG_DEBUG);
2579 $resql = $this->db->query($sql);
2580 if ($resql) {
2581 if (!empty($cat) && $cat > 0) {
2582 $sql = "INSERT INTO ".MAIN_DB_PREFIX."category_bankline (";
2583 $sql .= "lineid";
2584 $sql .= ", fk_categ";
2585 $sql .= ") VALUES (";
2586 $sql .= $this->id;
2587 $sql .= ", ".((int) $cat);
2588 $sql .= ")";
2589
2590 dol_syslog(get_class($this)."::update_conciliation", LOG_DEBUG);
2591 $this->db->query($sql);
2592
2593 // No error check. Can fail if category already affected
2594 // TODO Do no try the insert if link already exists
2595 }
2596
2597 $this->rappro = (int) $conciliated;
2598
2599 $this->db->commit();
2600 return 1;
2601 } else {
2602 $this->db->rollback();
2603 return -1;
2604 }
2605 }
2606
2607
2608 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2616 public function datev_change($rowid, $sign = 1)
2617 {
2618 // phpcs:enable
2619 $sql = "SELECT datev FROM ".MAIN_DB_PREFIX."bank WHERE rowid = ".((int) $rowid);
2620 $resql = $this->db->query($sql);
2621 if ($resql) {
2622 $obj = $this->db->fetch_object($resql);
2623 $newdate = $this->db->jdate($obj->datev) + (3600 * 24 * $sign);
2624
2625 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2626 $sql .= " datev = '".$this->db->idate($newdate)."'";
2627 $sql .= " WHERE rowid = ".((int) $rowid);
2628
2629 $result = $this->db->query($sql);
2630 if ($result) {
2631 if ($this->db->affected_rows($result)) {
2632 return 1;
2633 }
2634 } else {
2635 dol_print_error($this->db);
2636 return 0;
2637 }
2638 } else {
2639 dol_print_error($this->db);
2640 }
2641 return 0;
2642 }
2643
2644 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2651 public function datev_next($id)
2652 {
2653 // phpcs:enable
2654 return $this->datev_change($id, 1);
2655 }
2656
2657 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2664 public function datev_previous($id)
2665 {
2666 // phpcs:enable
2667 return $this->datev_change($id, -1);
2668 }
2669
2670
2671 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2679 public function dateo_change($rowid, $sign = 1)
2680 {
2681 // phpcs:enable
2682 $sql = "SELECT dateo FROM ".MAIN_DB_PREFIX."bank WHERE rowid = ".((int) $rowid);
2683 $resql = $this->db->query($sql);
2684 if ($resql) {
2685 $obj = $this->db->fetch_object($resql);
2686 $newdate = $this->db->jdate($obj->dateo) + (3600 * 24 * $sign);
2687
2688 $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET";
2689 $sql .= " dateo = '".$this->db->idate($newdate)."'";
2690 $sql .= " WHERE rowid = ".((int) $rowid);
2691
2692 $result = $this->db->query($sql);
2693 if ($result) {
2694 if ($this->db->affected_rows($result)) {
2695 return 1;
2696 }
2697 } else {
2698 dol_print_error($this->db);
2699 return 0;
2700 }
2701 } else {
2702 dol_print_error($this->db);
2703 }
2704 return 0;
2705 }
2706
2707 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2714 public function dateo_next($id)
2715 {
2716 // phpcs:enable
2717 return $this->dateo_change($id, 1);
2718 }
2719
2720 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2727 public function dateo_previous($id)
2728 {
2729 // phpcs:enable
2730 return $this->dateo_change($id, -1);
2731 }
2732
2733
2740 public function info($id)
2741 {
2742 $sql = 'SELECT b.rowid, b.datec, b.tms as datem,';
2743 $sql .= ' b.fk_user_author, b.fk_user_rappro';
2744 $sql .= ' FROM '.MAIN_DB_PREFIX.'bank as b';
2745 $sql .= ' WHERE b.rowid = '.((int) $id);
2746
2747 $result = $this->db->query($sql);
2748 if ($result) {
2749 if ($this->db->num_rows($result)) {
2750 $obj = $this->db->fetch_object($result);
2751
2752 $this->id = $obj->rowid;
2753
2754 $this->user_creation_id = $obj->fk_user_author;
2755 $this->user_rappro = $obj->fk_user_rappro;
2756 $this->date_creation = $this->db->jdate($obj->datec);
2757 $this->date_modification = $this->db->jdate($obj->datem);
2758 //$this->date_rappro = $obj->daterappro; // Not yet managed
2759 }
2760 $this->db->free($result);
2761 } else {
2762 dol_print_error($this->db);
2763 }
2764 }
2765
2766
2776 public function getNomUrl($withpicto = 0, $maxlen = 0, $option = '', $notooltip = 0)
2777 {
2778 global $conf, $langs;
2779
2780 $result = '';
2781
2782 $label = img_picto('', $this->picto).' <u>'.$langs->trans("BankTransactionLine").'</u>:<br>';
2783 $label .= '<b>'.$langs->trans("Ref").':</b> '.$this->ref;
2784 if ($this->amount) {
2785 $label .= '<br><strong>'.$langs->trans("Amount").':</strong> '.price($this->amount, 0, $langs, 1, -1, -1, $conf->currency);
2786 }
2787
2788 $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">';
2789 $linkend = '</a>';
2790
2791 $result .= $linkstart;
2792 if ($withpicto) {
2793 $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);
2794 }
2795 if ($withpicto != 2) {
2796 $result .= ($this->ref ? $this->ref : $this->id);
2797 }
2798
2799 $result .= $linkend;
2800
2801 if ($option == 'showall' || $option == 'showconciliated' || $option == 'showconciliatedandaccounted') {
2802 $result .= ' <span class="opacitymedium">(';
2803 }
2804 if ($option == 'showall') {
2805 $result .= $langs->trans("BankAccount").': ';
2806 $accountstatic = new Account($this->db);
2807 $accountstatic->id = $this->fk_account;
2808 $accountstatic->ref = $this->bank_account_ref;
2809 $accountstatic->label = $this->bank_account_label;
2810 $result .= $accountstatic->getNomUrl(0).', ';
2811 }
2812 if ($option == 'showall' || $option == 'showconciliated' || $option == 'showconciliatedandaccounted') {
2813 $result .= $langs->trans("BankLineConciliated").': ';
2814 $result .= yn($this->rappro);
2815 }
2816 if (isModEnabled('accounting') && ($option == 'showall' || $option == 'showconciliatedandaccounted')) {
2817 $sql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."accounting_bookkeeping";
2818 $sql .= " WHERE doc_type = 'bank' AND fk_doc = ".((int) $this->id);
2819 $resql = $this->db->query($sql);
2820 if ($resql) {
2821 $obj = $this->db->fetch_object($resql);
2822 if ($obj && $obj->nb) {
2823 $result .= ' - '.$langs->trans("Accounted").': '.yn(1);
2824 } else {
2825 $result .= ' - '.$langs->trans("Accounted").': '.yn(0);
2826 }
2827 }
2828 }
2829 if ($option == 'showall' || $option == 'showconciliated' || $option == 'showconciliatedandaccounted') {
2830 $result .= ')</span>';
2831 }
2832
2833 return $result;
2834 }
2835
2836
2843 public function getLibStatut($mode = 0)
2844 {
2845 return $this->LibStatut($this->status, $mode);
2846 }
2847
2848 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2856 public function LibStatut($status, $mode = 0)
2857 {
2858 // phpcs:enable
2859 return '';
2860 }
2861
2867 public function getVentilExportCompta()
2868 {
2869 $alreadydispatched = 0;
2870
2871 $type = 'bank';
2872
2873 $sql = " SELECT COUNT(ab.rowid) as nb FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab WHERE ab.doc_type='".$this->db->escape($type)."' AND ab.fk_doc = ".((int) $this->id);
2874 $resql = $this->db->query($sql);
2875 if ($resql) {
2876 $obj = $this->db->fetch_object($resql);
2877 if ($obj) {
2878 $alreadydispatched = $obj->nb;
2879 }
2880 } else {
2881 $this->error = $this->db->lasterror();
2882 return -1;
2883 }
2884
2885 if ($alreadydispatched) {
2886 return 1;
2887 }
2888 return 0;
2889 }
2890}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:66
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:342
getIbanHumanReadable(Account $account)
Returns the iban human readable.
Definition bank.lib.php:367
checkSwiftForAccount($account=null, $swift=null)
Check SWIFT information for a bank account.
Definition bank.lib.php:321
$object ref
Definition info.php:89
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.
getBannerAddress($htmlkey, $object)
Return full address for banner.
error()
Return error.
info($id)
Load miscellaneous information for tab "Info".
const TYPE_CASH
Cash account.
delete($user=null, $notrigger=0)
Delete bank account from database.
update($user, $notrigger=0)
Update bank account card.
__toString()
Shows the account number in the appropriate format.
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.
addline($date, $oper, $label, $amount, $num_chq, $categorie, User $user, $emetteur='', $banque='', $accountancycode='', $datev=null, $num_releve='', $amount_main_currency=null)
Add an entry into table ".MAIN_DB_PREFIX."bank.
LibStatut($status, $mode=0)
Return label of given object status.
Class to manage bank transaction lines.
Parent class of all other business classes (invoices, contracts, proposals, orders,...
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this->array_options This method is in most cases call...
setErrorsFromObject($object)
setErrorsFromObject
getFullAddress($withcountry=0, $sep="\n", $withregion=0, $extralangcode='')
Return full address of contact.
deleteExtraFields()
Delete all extra fields values for the current object.
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Class to manage Dolibarr database access.
Class to manage generation of HTML components Only common components must be here.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage Dolibarr users.
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition index.php:171
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0)
Clean a string to use it as a file name.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
div refaddress div address
if(!defined( 'CSRFCHECK_WITH_TOKEN'))
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:150