bank.lib.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  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. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  21. * or see https://www.gnu.org/
  22. */
  23. /**
  24. * \file htdocs/core/lib/bank.lib.php
  25. * \ingroup bank
  26. * \brief Ensemble de fonctions de base pour le module banque
  27. */
  28. /**
  29. * Prepare array with list of tabs
  30. *
  31. * @param Account $object Object related to tabs
  32. * @return array Array of tabs to show
  33. */
  34. function bank_prepare_head(Account $object)
  35. {
  36. global $db, $langs, $conf;
  37. $h = 0;
  38. $head = array();
  39. $head[$h][0] = DOL_URL_ROOT.'/compta/bank/card.php?id='.$object->id;
  40. $head[$h][1] = $langs->trans("BankAccount");
  41. $head[$h][2] = 'bankname';
  42. $h++;
  43. $head[$h][0] = DOL_URL_ROOT."/compta/bank/bankentries_list.php?id=".$object->id;
  44. $head[$h][1] = $langs->trans("BankTransactions");
  45. $head[$h][2] = 'journal';
  46. $h++;
  47. // if ($conf->global->MAIN_FEATURES_LEVEL >= 1)
  48. // {
  49. $head[$h][0] = DOL_URL_ROOT."/compta/bank/treso.php?account=".$object->id;
  50. $head[$h][1] = $langs->trans("PlannedTransactions");
  51. $head[$h][2] = 'cash';
  52. $h++;
  53. // }
  54. $head[$h][0] = DOL_URL_ROOT."/compta/bank/annuel.php?account=".$object->id;
  55. $head[$h][1] = $langs->trans("IOMonthlyReporting");
  56. $head[$h][2] = 'annual';
  57. $h++;
  58. $head[$h][0] = DOL_URL_ROOT."/compta/bank/graph.php?account=".$object->id;
  59. $head[$h][1] = $langs->trans("Graph");
  60. $head[$h][2] = 'graph';
  61. $h++;
  62. if ($object->courant != Account::TYPE_CASH || getDolGlobalString('BANK_CAN_RECONCILIATE_CASHACCOUNT')) {
  63. $nbReceipts = 0;
  64. // List of all standing receipts
  65. $sql = "SELECT COUNT(DISTINCT(b.num_releve)) as nb";
  66. $sql .= " FROM ".MAIN_DB_PREFIX."bank as b";
  67. $sql .= " WHERE b.fk_account = ".((int) $object->id);
  68. $resql = $db->query($sql);
  69. if ($resql) {
  70. $obj = $db->fetch_object($resql);
  71. if ($obj) {
  72. $nbReceipts = $obj->nb;
  73. }
  74. $db->free($resql);
  75. }
  76. $head[$h][0] = DOL_URL_ROOT."/compta/bank/releve.php?account=".((int) $object->id);
  77. $head[$h][1] = $langs->trans("AccountStatements");
  78. if (($nbReceipts) > 0) {
  79. $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($nbReceipts).'</span>';
  80. }
  81. $head[$h][2] = 'statement';
  82. $h++;
  83. }
  84. // Attached files
  85. require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  86. require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
  87. $upload_dir = $conf->bank->dir_output."/".dol_sanitizeFileName($object->ref);
  88. $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$'));
  89. $nbLinks = Link::count($db, $object->element, $object->id);
  90. $head[$h][0] = DOL_URL_ROOT."/compta/bank/document.php?account=".$object->id;
  91. $head[$h][1] = $langs->trans("Documents");
  92. if (($nbFiles + $nbLinks) > 0) {
  93. $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($nbFiles + $nbLinks).'</span>';
  94. }
  95. $head[$h][2] = 'document';
  96. $h++;
  97. // Show more tabs from modules
  98. // Entries must be declared in modules descriptor with line
  99. // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
  100. // $this->tabs = array('entity:-tabname); to remove a tab
  101. complete_head_from_modules($conf, $langs, $object, $head, $h, 'bank');
  102. /*$head[$h][0] = DOL_URL_ROOT . "/compta/bank/info.php?id=" . $object->id;
  103. $head[$h][1] = $langs->trans("Info");
  104. $head[$h][2] = 'info';
  105. $h++;*/
  106. complete_head_from_modules($conf, $langs, $object, $head, $h, 'bank', 'remove');
  107. return $head;
  108. }
  109. /**
  110. * Prepare array with list of tabs
  111. *
  112. * @param Object $object Object related to tabs
  113. * @return array Array of tabs to shoc
  114. */
  115. function bank_admin_prepare_head($object)
  116. {
  117. global $langs, $conf, $db;
  118. $langs->loadLangs(array("compta"));
  119. $extrafields = new ExtraFields($db);
  120. $extrafields->fetch_name_optionals_label('bank_account');
  121. $extrafields->fetch_name_optionals_label('bank');
  122. $h = 0;
  123. $head = array();
  124. $head[$h][0] = DOL_URL_ROOT.'/admin/bank.php';
  125. $head[$h][1] = $langs->trans("Miscellaneous");
  126. $head[$h][2] = 'general';
  127. $h++;
  128. $head[$h][0] = DOL_URL_ROOT.'/admin/chequereceipts.php';
  129. $head[$h][1] = $langs->trans("CheckReceiptShort");
  130. $head[$h][2] = 'checkreceipts';
  131. $h++;
  132. // Show more tabs from modules
  133. // Entries must be declared in modules descriptor with line
  134. // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
  135. // $this->tabs = array('entity:-tabname); to remove a tab
  136. complete_head_from_modules($conf, $langs, $object, $head, $h, 'bank_admin');
  137. $head[$h][0] = DOL_URL_ROOT.'/admin/bank_extrafields.php';
  138. $head[$h][1] = $langs->trans("ExtraFields").' ('.$langs->trans("BankAccounts").')';
  139. $nbExtrafields = $extrafields->attributes['bank_account']['count'];
  140. if ($nbExtrafields > 0) {
  141. $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbExtrafields.'</span>';
  142. }
  143. $head[$h][2] = 'attributes';
  144. $h++;
  145. $head[$h][0] = DOL_URL_ROOT.'/admin/bankline_extrafields.php';
  146. $head[$h][1] = $langs->trans("ExtraFields").' ('.$langs->trans("BankTransactions").')';
  147. $nbExtrafields = $extrafields->attributes['bank']['count'];
  148. if ($nbExtrafields > 0) {
  149. $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbExtrafields.'</span>';
  150. }
  151. $head[$h][2] = 'bankline_extrafields';
  152. $h++;
  153. complete_head_from_modules($conf, $langs, $object, $head, $h, 'bank_admin', 'remove');
  154. return $head;
  155. }
  156. /**
  157. * Prepare array with list of tabs
  158. *
  159. * @param Object $object Object related to tabs
  160. * @param Object $num val to account statement
  161. * @return array Array of tabs to shoc
  162. */
  163. function account_statement_prepare_head($object, $num)
  164. {
  165. global $langs, $conf, $db;
  166. $h = 0;
  167. $head = array();
  168. $head[$h][0] = DOL_URL_ROOT.'/compta/bank/releve.php?account='.$object->id.'&num='.$num;
  169. $head[$h][1] = $langs->trans("AccountStatement");
  170. $head[$h][2] = 'statement';
  171. $h++;
  172. // Attached files
  173. require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  174. require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
  175. $upload_dir = $conf->bank->dir_output."/".$object->id.'/statement/'.dol_sanitizeFileName($num);
  176. $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$'));
  177. $nbLinks = Link::count($db, $object->element, $object->id);
  178. $head[$h][0] = DOL_URL_ROOT."/compta/bank/account_statement_document.php?account=".$object->id."&num=".$num;
  179. $head[$h][1] = $langs->trans("Documents");
  180. if (($nbFiles + $nbLinks) > 0) {
  181. $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($nbFiles + $nbLinks).'</span>';
  182. }
  183. $head[$h][2] = 'document';
  184. $h++;
  185. complete_head_from_modules($conf, $langs, $object, $head, $h, 'account_statement');
  186. complete_head_from_modules($conf, $langs, $object, $head, $h, 'account_statement', 'remove');
  187. return $head;
  188. }
  189. /**
  190. * Prepare array with list of tabs
  191. *
  192. * @param Object $object Object related to tabs
  193. * @return array Array of tabs to shoc
  194. */
  195. function various_payment_prepare_head($object)
  196. {
  197. global $db, $langs, $conf;
  198. $h = 0;
  199. $head = array();
  200. $head[$h][0] = DOL_URL_ROOT.'/compta/bank/various_payment/card.php?id='.$object->id;
  201. $head[$h][1] = $langs->trans("VariousPayment");
  202. $head[$h][2] = 'card';
  203. $h++;
  204. // Show more tabs from modules
  205. // Entries must be declared in modules descriptor with line
  206. // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
  207. // $this->tabs = array('entity:-tabname); to remove a tab
  208. complete_head_from_modules($conf, $langs, $object, $head, $h, 'various_payment');
  209. require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  210. require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
  211. $upload_dir = $conf->bank->dir_output."/".dol_sanitizeFileName($object->ref);
  212. $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$'));
  213. $nbLinks = Link::count($db, $object->element, $object->id);
  214. $head[$h][0] = DOL_URL_ROOT.'/compta/bank/various_payment/document.php?id='.$object->id;
  215. $head[$h][1] = $langs->trans('Documents');
  216. if (($nbFiles + $nbLinks) > 0) {
  217. $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($nbFiles + $nbLinks).'</span>';
  218. }
  219. $head[$h][2] = 'documents';
  220. $h++;
  221. $head[$h][0] = DOL_URL_ROOT.'/compta/bank/various_payment/info.php?id='.$object->id;
  222. $head[$h][1] = $langs->trans("Info");
  223. $head[$h][2] = 'info';
  224. $h++;
  225. complete_head_from_modules($conf, $langs, $object, $head, $h, 'various_payment', 'remove');
  226. return $head;
  227. }
  228. /**
  229. * Check SWIFT informations for a bank account
  230. *
  231. * @param Account $account A bank account (used to get BIC/SWIFT)
  232. * @param string $swift Swift value (used to get BIC/SWIFT, param $account non used if provided)
  233. * @return boolean True if informations are valid, false otherwise
  234. */
  235. function checkSwiftForAccount(Account $account = null, $swift = null)
  236. {
  237. if ($account == null && $swift == null) {
  238. return false;
  239. } elseif ($swift == null) {
  240. $swift = $account->bic;
  241. }
  242. if (preg_match("/^([a-zA-Z]){4}([a-zA-Z]){2}([0-9a-zA-Z]){2}([0-9a-zA-Z]{3})?$/", $swift)) {
  243. return true;
  244. } else {
  245. return false;
  246. }
  247. }
  248. /**
  249. * Check IBAN number informations for a bank account.
  250. *
  251. * @param Account $account A bank account
  252. * @param string $ibantocheck Bank account number (used to get BAN, $account not used if provided)
  253. * @return boolean True if informations are valid, false otherwise
  254. */
  255. function checkIbanForAccount(Account $account = null, $ibantocheck = null)
  256. {
  257. if ($account == null && $ibantocheck == null) {
  258. return false;
  259. } elseif ($ibantocheck == null) {
  260. $ibantocheck = ($account->iban ? $account->iban : $account->iban_prefix); // iban or iban_prefix for backward compatibility
  261. }
  262. require_once DOL_DOCUMENT_ROOT.'/includes/php-iban/oophp-iban.php';
  263. $iban = new PHP_IBAN\IBAN($ibantocheck);
  264. $check = $iban->Verify();
  265. if ($check) {
  266. return true;
  267. } else {
  268. return false;
  269. }
  270. }
  271. /**
  272. * Returns the iban human readable
  273. *
  274. * @param Account $account Account object
  275. * @return string
  276. */
  277. function getIbanHumanReadable(Account $account)
  278. {
  279. if ($account->getCountryCode() == 'FR') {
  280. require_once DOL_DOCUMENT_ROOT.'/includes/php-iban/oophp-iban.php';
  281. $ibantoprint = preg_replace('/[^a-zA-Z0-9]/', '', empty($account->iban) ? '' : $account->iban);
  282. $iban = new PHP_IBAN\IBAN($ibantoprint);
  283. return $iban->HumanFormat();
  284. }
  285. return $account->iban;
  286. }
  287. /**
  288. * Check account number informations for a bank account
  289. *
  290. * @param Account $account A bank account
  291. * @return boolean True if informations are valid, false otherwise
  292. */
  293. function checkBanForAccount($account)
  294. {
  295. $country_code = $account->getCountryCode();
  296. // For compatibility between
  297. // account of type CompanyBankAccount class (we use number, cle_rib)
  298. // account of type Account class (we use num_compte, cle)
  299. if (empty($account->number)) {
  300. $account->number = $account->num_compte;
  301. }
  302. if (empty($account->cle)) {
  303. $account->cle = $account->cle_rib;
  304. }
  305. 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);
  306. if ($country_code == 'FR') { // France rules
  307. $coef = array(62, 34, 3);
  308. // Concatenation des differents codes.
  309. $rib = strtolower(trim($account->code_banque).trim($account->code_guichet).trim($account->number).trim($account->cle));
  310. // On remplace les eventuelles lettres par des chiffres.
  311. //$rib = strtr($rib, "abcdefghijklmnopqrstuvwxyz","12345678912345678912345678"); //Ne marche pas
  312. $rib = strtr($rib, "abcdefghijklmnopqrstuvwxyz", "12345678912345678923456789");
  313. // Separation du rib en 3 groupes de 7 + 1 groupe de 2.
  314. // Multiplication de chaque groupe par les coef du tableau
  315. for ($i = 0, $s = 0; $i < 3; $i++) {
  316. $code = substr($rib, 7 * $i, 7);
  317. $s += ((int) $code) * $coef[$i];
  318. }
  319. // Soustraction du modulo 97 de $s a 97 pour obtenir la cle
  320. $cle_rib = 97 - ($s % 97);
  321. if ($cle_rib == $account->cle) {
  322. return true;
  323. }
  324. return false;
  325. }
  326. if ($country_code == 'BE') { // Belgium rules
  327. }
  328. if ($country_code == 'ES') { // Spanish rules
  329. $CCC = strtolower(trim($account->number));
  330. $rib = strtolower(trim($account->code_banque).trim($account->code_guichet));
  331. $cle_rib = strtolower(checkES($rib, $CCC));
  332. if ($cle_rib == strtolower($account->cle)) {
  333. return true;
  334. }
  335. return false;
  336. }
  337. if ($country_code == 'AU') { // Australian
  338. if (strlen($account->code_banque) > 7) {
  339. return false; // Sould be 6 but can be 123-456
  340. } elseif (strlen($account->code_banque) < 6) {
  341. return false; // Sould be 6
  342. } else {
  343. return true;
  344. }
  345. }
  346. // No particular rule
  347. // If account is CompanyBankAccount class, we use number
  348. // If account is Account class, we use num_compte
  349. if (empty($account->number)) {
  350. return false;
  351. }
  352. return true;
  353. }
  354. /**
  355. * Returns the key for Spanish Banks Accounts
  356. *
  357. * @param string $IentOfi IentOfi
  358. * @param string $InumCta InumCta
  359. * @return string Key
  360. */
  361. function checkES($IentOfi, $InumCta)
  362. {
  363. if (empty($IentOfi) || empty($InumCta) || strlen($IentOfi) != 8 || strlen($InumCta) != 10) {
  364. $keycontrol = "";
  365. return $keycontrol;
  366. }
  367. $ccc = $IentOfi.$InumCta;
  368. $numbers = "1234567890";
  369. $i = 0;
  370. while ($i <= strlen($ccc) - 1) {
  371. if (strpos($numbers, substr($ccc, $i, 1)) === false) {
  372. $keycontrol = "";
  373. return $keycontrol;
  374. }
  375. $i++;
  376. }
  377. $values = array(1, 2, 4, 8, 5, 10, 9, 7, 3, 6);
  378. $sum = 0;
  379. for ($i = 2; $i < 10; $i++) {
  380. $sum += $values[$i] * substr($IentOfi, $i - 2, 1);
  381. }
  382. $key = 11 - $sum % 11;
  383. if ($key == 10) {
  384. $key = 1;
  385. }
  386. if ($key == 11) {
  387. $key = 0;
  388. }
  389. $keycontrol = $key;
  390. $sum = 0;
  391. for ($i = 0; $i < 11; $i++) {
  392. $sum += $values[$i] * (int) substr($InumCta, $i, 1); //int to cast result of substr to a number
  393. }
  394. $key = 11 - $sum % 11;
  395. if ($key == 10) {
  396. $key = 1;
  397. }
  398. if ($key == 11) {
  399. $key = 0;
  400. }
  401. $keycontrol .= $key;
  402. return $keycontrol;
  403. }