dolibarr 23.0.3
bank.lib.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2006-2016 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2012 Regis Houssin <regis.houssin@inodbox.com>
4 * Copyright (C) 2015 Alexandre Spangaro <aspangaro@open-dsi.fr>
5 * Copyright (C) 2016 Juanjo Menent <jmenent@2byte.es>
6 * Copyright (C) 2019 Nicolas ZABOURI <info@inovea-conseil.com>
7 * Copyright (C) 2021 Ferran Marcet <fmarcet@2byte.es>
8 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
9 * Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23 * or see https://www.gnu.org/
24 */
25
40{
41 global $db, $langs, $conf, $user;
42
43 $h = 0;
44 $head = array();
45
46 $head[$h][0] = dolBuildUrl(DOL_URL_ROOT.'/compta/bank/card.php', ['id' => $object->id]);
47 $head[$h][1] = $langs->trans("BankAccount");
48 $head[$h][2] = 'bankname';
49 $h++;
50
51 $head[$h][0] = dolBuildUrl(DOL_URL_ROOT.'/compta/bank/bankentries_list.php', ['id' => $object->id]);
52 $head[$h][1] = $langs->trans("BankTransactions");
53 $head[$h][2] = 'journal';
54 $h++;
55
56 if ($object->canBeConciliated() > 0) {
57 $allowautomaticconciliation = getDolGlobalBool('MAIN_ALLOW_AUTOMATIC_CONCILIATION'); // TODO
58 $titletoconciliatemanual = $langs->trans("Conciliate");
59 $titletoconciliateauto = $langs->trans("Conciliate");
60 if ($allowautomaticconciliation) {
61 $titletoconciliatemanual .= ' ('.$langs->trans("Manual").')';
62 $titletoconciliateauto .= ' ('.$langs->trans("Auto").')';
63 }
64
65 $param = '';
66
67 // If not cash account and can be reconciliate
68 if ($user->hasRight('banque', 'consolidate')) {
69 $query = [
70 'id' => $object->id,
71 'action' => 'reconcile',
72 'sortfield' => 'b.datev,b.dateo,b.rowid',
73 'sortorder' => 'asc,asc,asc',
74 'search_conciliated' => 0,
75 'search_account' => $object->id,
76 ];
77 $head[$h][0] = dolBuildUrl(DOL_URL_ROOT.'/compta/bank/bankentries_list.php', $query).$param;
78 $head[$h][1] = $titletoconciliatemanual;
79 $head[$h][2] = 'reconcile';
80 $h++;
81 }/* else {
82 $buttonreconcile = '<a class="butActionRefused classfortooltip" title="'.$langs->trans("NotEnoughPermissions").'" href="#">'.$titletoconciliatemanual.'</a>';
83 }*/
84
85 if ($allowautomaticconciliation) {
86 // If not cash account and can be reconciliate
87 if ($user->hasRight('banque', 'consolidate')) {
88 $newparam = $param;
89 $newparam = preg_replace('/search_conciliated=\d+/i', '', $newparam);
90
91 $head[$h][0] = DOL_URL_ROOT."/compta/bank/bankentries_list.php?id=".$object->id.'&action=reconcile&sortfield=b.datev,b.dateo,b.rowid&sortorder=asc,asc,asc&search_conciliated=0&search_account='.$object->id.$newparam;
92 $head[$h][1] = $titletoconciliateauto;
93 $head[$h][2] = 'reconcileauto';
94 $h++;
95
96 //$buttonreconcile .= ' <a class="butAction" style="margin-bottom: 5px !important; margin-top: 5px !important" href="'.DOL_URL_ROOT.'/compta/bank/bankentries_list.php?action=reconcile&sortfield=b.datev,b.dateo,b.rowid&sortorder=asc,asc,asc&search_conciliated=0'.$newparam.'">'.$titletoconciliateauto.'</a>';
97 }/* else {
98 $buttonreconcile .= ' <a class="butActionRefused" style="margin-bottom: 5px !important; margin-top: 5px !important" title="'.$langs->trans("NotEnoughPermissions").'" href="#">'.$titletoconciliateauto.'</a>';
99 }*/
100 }
101 }
102
103 if ($object->type != Account::TYPE_CASH || getDolGlobalString('BANK_CAN_RECONCILIATE_CASHACCOUNT')) {
104 $nbReceipts = 0;
105
106 // List of all standing receipts
107 $sql = "SELECT COUNT(DISTINCT(b.num_releve)) as nb";
108 $sql .= " FROM ".MAIN_DB_PREFIX."bank as b";
109 $sql .= " WHERE b.fk_account = ".((int) $object->id);
110
111 $resql = $db->query($sql);
112 if ($resql) {
113 $obj = $db->fetch_object($resql);
114 if ($obj) {
115 $nbReceipts = $obj->nb;
116 }
117 $db->free($resql);
118 }
119
120 $head[$h][0] = dolBuildUrl(DOL_URL_ROOT.'/compta/bank/releve.php', ['account' => $object->id]);
121 $head[$h][1] = $langs->trans("AccountStatements");
122 if (($nbReceipts) > 0) {
123 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($nbReceipts).'</span>';
124 }
125 $head[$h][2] = 'statement';
126 $h++;
127 }
128
129 // Attached files
130 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
131 require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
132 $upload_dir = $conf->bank->dir_output."/".dol_sanitizeFileName($object->ref);
133 $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$'));
134 $nbLinks = Link::count($db, $object->element, $object->id);
135 $head[$h][0] = dolBuildUrl(DOL_URL_ROOT.'/compta/bank/document.php', ['account' => $object->id]);
136 $head[$h][1] = $langs->trans("Documents");
137 if (($nbFiles + $nbLinks) > 0) {
138 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($nbFiles + $nbLinks).'</span>';
139 }
140 $head[$h][2] = 'document';
141 $h++;
142
143 $head[$h][0] = dolBuildUrl(DOL_URL_ROOT.'/compta/bank/annuel.php', ['account' => $object->id]);
144 $head[$h][1] = $langs->trans("Reports");
145 $head[$h][2] = 'annual';
146 $h++;
147
148 $head[$h][0] = dolBuildUrl(DOL_URL_ROOT.'/compta/bank/treso.php', ['account' => $object->id]);
149 $head[$h][1] = $langs->trans("PlannedTransactions");
150 $head[$h][2] = 'cash';
151 $h++;
152
153 // Show more tabs from modules
154 // Entries must be declared in modules descriptor with line
155 // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
156 // $this->tabs = array('entity:-tabname); to remove a tab
157 complete_head_from_modules($conf, $langs, $object, $head, $h, 'bank');
158
159 /*$head[$h][0] = DOL_URL_ROOT . "/compta/bank/info.php?id=" . $object->id;
160 $head[$h][1] = $langs->trans("Info");
161 $head[$h][2] = 'info';
162 $h++;*/
163
164 complete_head_from_modules($conf, $langs, $object, $head, $h, 'bank', 'remove');
165
166 return $head;
167}
168
176{
177 global $db, $langs, $conf, $user;
178
179 $h = 0;
180 $head = array();
181
182 $head[$h][0] = dolBuildUrl(DOL_URL_ROOT.'/compta/bank/annuel.php', ['account' => $object->id]);
183 $head[$h][1] = $langs->trans("IOMonthlyReporting");
184 $head[$h][2] = 'annual';
185 $h++;
186
187 $head[$h][0] = dolBuildUrl(DOL_URL_ROOT.'/compta/bank/graph.php', ['account' => $object->id]);
188 $head[$h][1] = $langs->trans("Graph");
189 $head[$h][2] = 'graph';
190 $h++;
191
192 return $head;
193}
201{
202 global $langs, $conf, $db;
203
204 $langs->loadLangs(array("compta"));
205
206 $extrafields = new ExtraFields($db);
207 $extrafields->fetch_name_optionals_label('bank_account');
208 $extrafields->fetch_name_optionals_label('bank');
209 $extrafields->fetch_name_optionals_label('paiement');
210
211 $h = 0;
212 $head = array();
213
214 $head[$h][0] = dolBuildUrl(DOL_URL_ROOT.'/admin/bank.php');
215 $head[$h][1] = $langs->trans("Miscellaneous");
216 $head[$h][2] = 'general';
217 $h++;
218
219 $head[$h][0] = dolBuildUrl(DOL_URL_ROOT.'/admin/chequereceipts.php');
220 $head[$h][1] = $langs->trans("CheckReceiptShort");
221 $head[$h][2] = 'checkreceipts';
222 $h++;
223
224
225 // Show more tabs from modules
226 // Entries must be declared in modules descriptor with line
227 // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
228 // $this->tabs = array('entity:-tabname); to remove a tab
229 complete_head_from_modules($conf, $langs, $object, $head, $h, 'bank_admin');
230
231 $head[$h][0] = dolBuildUrl(DOL_URL_ROOT.'/admin/bank_extrafields.php');
232 $head[$h][1] = $langs->trans("ExtraFields").' ('.$langs->trans("BankAccounts").')';
233 $nbExtrafields = $extrafields->attributes['bank_account']['count'];
234 if ($nbExtrafields > 0) {
235 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbExtrafields.'</span>';
236 }
237 $head[$h][2] = 'attributes';
238 $h++;
239
240 $head[$h][0] = dolBuildUrl(DOL_URL_ROOT.'/admin/bankline_extrafields.php');
241 $head[$h][1] = $langs->trans("ExtraFields").' ('.$langs->trans("BankTransactions").')';
242 $nbExtrafields = $extrafields->attributes['bank']['count'];
243 if ($nbExtrafields > 0) {
244 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbExtrafields.'</span>';
245 }
246 $head[$h][2] = 'bankline_extrafields';
247 $h++;
248
249 $head[$h][0] = dolBuildUrl(DOL_URL_ROOT.'/admin/bank_payments_extrafields.php');
250 $head[$h][1] = $langs->trans("ExtraFields").' ('.$langs->trans("Payments").')';
251 $nbExtrafields = $extrafields->attributes['paiement']['count'];
252 if ($nbExtrafields > 0) {
253 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbExtrafields.'</span>';
254 }
255 $head[$h][2] = 'bank_payments_extrafields';
256 $h++;
257
258 complete_head_from_modules($conf, $langs, $object, $head, $h, 'bank_admin', 'remove');
259
260 return $head;
261}
262
263
272{
273 global $langs, $conf, $db;
274 $h = 0;
275 $head = array();
276
277 $head[$h][0] = dolBuildUrl(DOL_URL_ROOT.'/compta/bank/releve.php', ['account' => $object->id, 'num' => $num]);
278 $head[$h][1] = $langs->trans("AccountStatement");
279 $head[$h][2] = 'statement';
280 $h++;
281
282 // Attached files
283 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
284 require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
285 $upload_dir = $conf->bank->dir_output."/".$object->id.'/statement/'.dol_sanitizeFileName($num);
286 $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$'));
287 $nbLinks = Link::count($db, $object->element, $object->id);
288
289 $head[$h][0] = dolBuildUrl(DOL_URL_ROOT.'/compta/bank/account_statement_document.php', ['account' => $object->id, 'num' => $num]);
290 $head[$h][1] = $langs->trans("Documents");
291 if (($nbFiles + $nbLinks) > 0) {
292 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($nbFiles + $nbLinks).'</span>';
293 }
294 $head[$h][2] = 'document';
295 $h++;
296
297 complete_head_from_modules($conf, $langs, $object, $head, $h, 'account_statement');
298
299 complete_head_from_modules($conf, $langs, $object, $head, $h, 'account_statement', 'remove');
300
301 return $head;
302}
303
304
312{
313 global $db, $langs, $conf;
314
315 $h = 0;
316 $head = array();
317
318 $head[$h][0] = DOL_URL_ROOT.'/compta/bank/various_payment/card.php?id='.$object->id;
319 $head[$h][1] = $langs->trans("VariousPayment");
320 $head[$h][2] = 'card';
321 $h++;
322
323 // Show more tabs from modules
324 // Entries must be declared in modules descriptor with line
325 // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
326 // $this->tabs = array('entity:-tabname); to remove a tab
327 complete_head_from_modules($conf, $langs, $object, $head, $h, 'various_payment');
328
329 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
330 require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
331 $upload_dir = $conf->bank->dir_output."/".dol_sanitizeFileName($object->ref);
332 $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$'));
333 $nbLinks = Link::count($db, $object->element, $object->id);
334 $head[$h][0] = DOL_URL_ROOT.'/compta/bank/various_payment/document.php?id='.$object->id;
335 $head[$h][1] = $langs->trans('Documents');
336 if (($nbFiles + $nbLinks) > 0) {
337 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($nbFiles + $nbLinks).'</span>';
338 }
339 $head[$h][2] = 'documents';
340 $h++;
341
342 $head[$h][0] = DOL_URL_ROOT.'/compta/bank/various_payment/info.php?id='.$object->id;
343 $head[$h][1] = $langs->trans("Info");
344 $head[$h][2] = 'info';
345 $h++;
346
347 complete_head_from_modules($conf, $langs, $object, $head, $h, 'various_payment', 'remove');
348
349 return $head;
350}
351
359function checkSwiftForAccount($account = null, $swift = null)
360{
361 if ($account == null && $swift == null) {
362 return false;
363 } elseif ($swift == null) {
364 $swift = $account->bic;
365 }
366 if (preg_match("/^([a-zA-Z]){4}([a-zA-Z]){2}([0-9a-zA-Z]){2}([0-9a-zA-Z]{3})?$/", $swift)) {
367 return true;
368 } else {
369 return false;
370 }
371}
372
380function checkIbanForAccount($account = null, $ibantocheck = null)
381{
382 if ($account == null && $ibantocheck == null) {
383 return false;
384 } elseif ($ibantocheck == null) {
385 $ibantocheck = ($account->iban ? $account->iban : $account->iban_prefix); // iban or iban_prefix for backward compatibility
386 }
387 require_once DOL_DOCUMENT_ROOT.'/includes/php-iban/oophp-iban.php';
388
389 $iban = new PHP_IBAN\IBAN($ibantocheck);
390 $check = $iban->Verify();
391
392 if ($check) {
393 return true;
394 } else {
395 return false;
396 }
397}
398
406{
407 if ($account->getCountryCode() == 'FR') {
408 require_once DOL_DOCUMENT_ROOT.'/includes/php-iban/oophp-iban.php';
409 $ibantoprint = preg_replace('/[^a-zA-Z0-9]/', '', empty($account->iban) ? '' : $account->iban);
410 $iban = new PHP_IBAN\IBAN($ibantoprint);
411 return $iban->HumanFormat();
412 }
413
414 return $account->iban;
415}
416
423function checkBanForAccount($account)
424{
425 $country_code = $account->getCountryCode();
426
427 // For compatibility between
428 // account of type CompanyBankAccount class (we use number, cle_rib)
429 // account of type Account class (we use num_compte, cle)
430 if (empty($account->number)) {
431 $account->number = $account->num_compte; // @phan-suppress-current-line PhanUndeclaredProperty
432 }
433 if (empty($account->cle)) {
434 $account->cle = $account->cle_rib;
435 }
436
437 dol_syslog("bank.lib::checkBanForAccount account->code_banque=".$account->code_banque." account->code_guichet=".$account->code_guichet." account->number=".$account->number." account->cle=".$account->cle." account->iban=".$account->iban." country_code=".$country_code, LOG_DEBUG);
438
439 if ($country_code == 'FR') { // France rules
440 $coef = array(62, 34, 3);
441 // Concatenate the code parts
442 $rib = strtolower(trim($account->code_banque).trim($account->code_guichet).trim($account->number).trim($account->cle));
443 // On replace les eventuelles lettres par des chiffres.
444 //$rib = strtr($rib, "abcdefghijklmnopqrstuvwxyz","12345678912345678912345678"); //Ne marche pas
445 $rib = strtr($rib, "abcdefghijklmnopqrstuvwxyz", "12345678912345678923456789");
446 // Separation du rib en 3 groups de 7 + 1 group de 2.
447 // Multiplication de chaque group par les coef du tableau
448
449 for ($i = 0, $s = 0; $i < 3; $i++) {
450 $code = substr($rib, 7 * $i, 7);
451 $s += ((int) $code) * $coef[$i];
452 }
453 // Soustraction du modulo 97 de $s a 97 pour obtenir la cle
454 $cle_rib = 97 - ($s % 97);
455 if ($cle_rib == $account->cle) {
456 return true;
457 }
458 return false;
459 }
460
461 /*
462 if ($country_code == 'BE') { // Belgian rules
463 }
464 */
465
466 if ($country_code == 'ES') { // Spanish rules
467 $CCC = strtolower(trim($account->number));
468 $rib = strtolower(trim($account->code_banque).trim($account->code_guichet));
469 $cle_rib = strtolower(checkES($rib, $CCC));
470 if ($cle_rib == strtolower($account->cle)) {
471 return true;
472 }
473 return false;
474 }
475 if ($country_code == 'AU') { // Australian
476 if (strlen($account->code_banque) > 7) {
477 return false; // Should be 6 but can be 123-456
478 } elseif (strlen($account->code_banque) < 6) {
479 return false; // Should be 6
480 } else {
481 return true;
482 }
483 }
484
485 // No particular rule
486 // If account is CompanyBankAccount class, we use number
487 // If account is Account class, we use num_compte
488 if (empty($account->number)) {
489 return false;
490 }
491
492 return true;
493}
494
495
496
504function checkES($IentOfi, $InumCta)
505{
506 if (empty($IentOfi) || empty($InumCta) || strlen($IentOfi) != 8 || strlen($InumCta) != 10) {
507 $keycontrol = "";
508 return $keycontrol;
509 }
510
511 $ccc = $IentOfi.$InumCta;
512 $numbers = "1234567890";
513
514 $i = 0;
515
516 while ($i <= strlen($ccc) - 1) {
517 if (strpos($numbers, substr($ccc, $i, 1)) === false) {
518 $keycontrol = "";
519 return $keycontrol;
520 }
521 $i++;
522 }
523
524 $values = array(1, 2, 4, 8, 5, 10, 9, 7, 3, 6);
525 $sum = 0;
526
527 for ($i = 2; $i < 10; $i++) {
528 $sum += $values[$i] * (int) substr($IentOfi, $i - 2, 1);
529 }
530
531 $key = 11 - $sum % 11;
532
533 if ($key == 10) {
534 $key = 1;
535 }
536 if ($key == 11) {
537 $key = 0;
538 }
539
540 $keycontrol = $key;
541
542 $sum = 0;
543
544 for ($i = 0; $i < 11; $i++) {
545 $sum += $values[$i] * (int) substr($InumCta, $i, 1); //int to cast result of substr to a number
546 }
547
548 $key = 11 - $sum % 11;
549
550 if ($key == 10) {
551 $key = 1;
552 }
553 if ($key == 11) {
554 $key = 0;
555 }
556
557 $keycontrol .= $key;
558 return $keycontrol;
559}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
checkIbanForAccount($account=null, $ibantocheck=null)
Check IBAN number information for a bank account.
Definition bank.lib.php:380
checkES($IentOfi, $InumCta)
Returns the key for Spanish Banks Accounts.
Definition bank.lib.php:504
bank_report_prepare_head(Account $object)
Prepare array with list of tabs for bank report.
Definition bank.lib.php:175
account_statement_prepare_head($object, $num)
Prepare array with list of tabs.
Definition bank.lib.php:271
checkBanForAccount($account)
Check account number information for a bank account.
Definition bank.lib.php:423
getIbanHumanReadable(Account $account)
Returns the iban human readable.
Definition bank.lib.php:405
bank_prepare_head(Account $object)
Prepare array with list of tabs.
Definition bank.lib.php:39
various_payment_prepare_head($object)
Prepare array with list of tabs.
Definition bank.lib.php:311
checkSwiftForAccount($account=null, $swift=null)
Check SWIFT information for a bank account.
Definition bank.lib.php:359
bank_admin_prepare_head($object)
Prepare array with list of tabs.
Definition bank.lib.php:200
Class to manage bank accounts.
const TYPE_CASH
Cash account.
Class to manage standard extra fields.
dol_dir_list($utf8_path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition files.lib.php:64
dolBuildUrl($url, $params=[], $addtoken=false)
Return path of url.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
getDolGlobalBool($key, $default=false)
Return a Dolibarr global constant boolean value.
complete_head_from_modules($conf, $langs, $object, &$head, &$h, $type, $mode='add', $filterorigmodule='')
Complete or removed entries into a head array (used to build tabs).
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.