multicurrency.class.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966
  1. <?php
  2. /* Copyright (C) 2007-2020 Laurent Destailleur <eldy@users.sourceforge.net>
  3. * Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>
  4. * Copyright (C) 2015 Florian Henry <florian.henry@open-concept.pro>
  5. * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
  6. * Copyright (C) 2016 Pierre-Henry Favre <phf@atm-consulting.fr>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. */
  21. /**
  22. * \file htdocs/multicurrency/class/multicurrency.class.php
  23. * \ingroup multicurrency
  24. * \brief This file is a CRUD class file (Create/Read/Update/Delete) for multicurrency
  25. */
  26. // Put here all includes required by your class file
  27. require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
  28. require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
  29. /**
  30. * Class Currency
  31. *
  32. * Put here description of your class
  33. * @see CommonObject
  34. */
  35. class MultiCurrency extends CommonObject
  36. {
  37. /**
  38. * @var string Id to identify managed objects
  39. */
  40. public $element = 'multicurrency';
  41. /**
  42. * @var string Name of table without prefix where object is stored
  43. */
  44. public $table_element = 'multicurrency';
  45. /**
  46. * @var string Name of table without prefix where object is stored
  47. */
  48. public $table_element_line = "multicurrency_rate";
  49. /**
  50. * @var CurrencyRate[] rates
  51. */
  52. public $rates = array();
  53. /**
  54. * @var mixed Sample property 1
  55. */
  56. public $id;
  57. /**
  58. * @var mixed Sample property 1
  59. */
  60. public $code;
  61. /**
  62. * @var mixed Sample property 2
  63. */
  64. public $name;
  65. /**
  66. * @var int Entity
  67. */
  68. public $entity;
  69. /**
  70. * @var mixed Sample property 2
  71. */
  72. public $date_create;
  73. /**
  74. * @var mixed Sample property 2
  75. */
  76. public $fk_user;
  77. /**
  78. * @var mixed Sample property 2
  79. */
  80. public $rate;
  81. /**
  82. * Constructor
  83. *
  84. * @param DoliDb $db Database handler
  85. */
  86. public function __construct(DoliDB $db)
  87. {
  88. $this->db = $db;
  89. return 1;
  90. }
  91. /**
  92. * Create object into database
  93. *
  94. * @param User $user User that creates
  95. * @param bool $trigger true=launch triggers after, false=disable triggers
  96. * @return int <0 if KO, Id of created object if OK
  97. */
  98. public function create(User $user, $trigger = true)
  99. {
  100. global $conf, $langs;
  101. dol_syslog('MultiCurrency::create', LOG_DEBUG);
  102. $error = 0;
  103. if (self::checkCodeAlreadyExists($this->code)) {
  104. $error++;
  105. $this->errors[] = $langs->trans('multicurrency_code_already_added');
  106. return -1;
  107. }
  108. if (empty($this->entity) || $this->entity <= 0) {
  109. $this->entity = $conf->entity;
  110. }
  111. $now = dol_now();
  112. // Insert request
  113. $sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element."(";
  114. $sql .= ' code,';
  115. $sql .= ' name,';
  116. $sql .= ' entity,';
  117. $sql .= ' date_create,';
  118. $sql .= ' fk_user';
  119. $sql .= ') VALUES (';
  120. $sql .= " '".$this->db->escape($this->code)."',";
  121. $sql .= " '".$this->db->escape($this->name)."',";
  122. $sql .= " ".((int) $this->entity).",";
  123. $sql .= " '".$this->db->idate($now)."',";
  124. $sql .= " ".((int) $user->id);
  125. $sql .= ')';
  126. $this->db->begin();
  127. dol_syslog(__METHOD__, LOG_DEBUG);
  128. $resql = $this->db->query($sql);
  129. if (!$resql) {
  130. $error++;
  131. $this->errors[] = 'Error '.$this->db->lasterror();
  132. dol_syslog('MultiCurrency::create '.join(',', $this->errors), LOG_ERR);
  133. }
  134. if (!$error) {
  135. $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
  136. $this->date_create = $now;
  137. $this->fk_user = $user->id;
  138. if ($trigger) {
  139. $result = $this->call_trigger('CURRENCY_CREATE', $user);
  140. if ($result < 0) {
  141. $error++;
  142. }
  143. }
  144. }
  145. if ($error) {
  146. $this->db->rollback();
  147. return -1 * $error;
  148. } else {
  149. $this->db->commit();
  150. return $this->id;
  151. }
  152. }
  153. /**
  154. * Load object in memory from the database
  155. *
  156. * @param int $id Id object
  157. * @param string $code code
  158. * @return int <0 if KO, 0 if not found, >0 if OK
  159. */
  160. public function fetch($id, $code = null)
  161. {
  162. dol_syslog('MultiCurrency::fetch', LOG_DEBUG);
  163. global $conf;
  164. $sql = "SELECT";
  165. $sql .= ' c.rowid, c.name, c.code, c.entity, c.date_create, c.fk_user';
  166. $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' AS c';
  167. if (!empty($code)) {
  168. $sql .= ' WHERE c.code = \''.$this->db->escape($code).'\' AND c.entity = '.$conf->entity;
  169. } else {
  170. $sql .= ' WHERE c.rowid = '.((int) $id);
  171. }
  172. dol_syslog(__METHOD__, LOG_DEBUG);
  173. $resql = $this->db->query($sql);
  174. if ($resql) {
  175. $numrows = $this->db->num_rows($resql);
  176. if ($numrows) {
  177. $obj = $this->db->fetch_object($resql);
  178. $this->id = $obj->rowid;
  179. $this->name = $obj->name;
  180. $this->code = $obj->code;
  181. $this->entity = $obj->entity;
  182. $this->date_create = $obj->date_create;
  183. $this->fk_user = $obj->fk_user;
  184. $this->fetchAllCurrencyRate();
  185. $this->getRate();
  186. }
  187. $this->db->free($resql);
  188. if ($numrows) {
  189. return 1;
  190. } else {
  191. return 0;
  192. }
  193. } else {
  194. $this->errors[] = 'Error '.$this->db->lasterror();
  195. dol_syslog('MultiCurrency::fetch '.join(',', $this->errors), LOG_ERR);
  196. return -1;
  197. }
  198. }
  199. /**
  200. * Load all rates in object from the database
  201. *
  202. * @return int <0 if KO, >=0 if OK
  203. */
  204. public function fetchAllCurrencyRate()
  205. {
  206. $sql = "SELECT cr.rowid";
  207. $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element_line.' as cr';
  208. $sql .= ' WHERE cr.fk_multicurrency = '.((int) $this->id);
  209. $sql .= ' ORDER BY cr.date_sync DESC';
  210. $this->rates = array();
  211. dol_syslog(__METHOD__, LOG_DEBUG);
  212. $resql = $this->db->query($sql);
  213. if ($resql) {
  214. $num = $this->db->num_rows($resql);
  215. while ($obj = $this->db->fetch_object($resql)) {
  216. $rate = new CurrencyRate($this->db);
  217. $rate->fetch($obj->rowid);
  218. $this->rates[] = $rate;
  219. }
  220. $this->db->free($resql);
  221. return $num;
  222. } else {
  223. $this->errors[] = 'Error '.$this->db->lasterror();
  224. dol_syslog('MultiCurrency::fetchAllCurrencyRate '.join(',', $this->errors), LOG_ERR);
  225. return -1;
  226. }
  227. }
  228. /**
  229. * Update object into database
  230. *
  231. * @param User $user User that modifies
  232. * @param bool $trigger true=launch triggers after, false=disable triggers
  233. * @return int <0 if KO, >0 if OK
  234. */
  235. public function update(User $user, $trigger = true)
  236. {
  237. $error = 0;
  238. dol_syslog('MultiCurrency::update', LOG_DEBUG);
  239. // Clean parameters
  240. $this->name = trim($this->name);
  241. $this->code = trim($this->code);
  242. // Check parameters
  243. if (empty($this->code)) {
  244. $error++;
  245. dol_syslog('MultiCurrency::update $this->code can not be empty', LOG_ERR);
  246. return -1;
  247. }
  248. // Update request
  249. $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET";
  250. $sql .= " name = '".$this->db->escape($this->name)."'";
  251. $sql .= " code = '".$this->db->escape($this->code)."'";
  252. $sql .= " WHERE rowid = ".((int) $this->id);
  253. $this->db->begin();
  254. $resql = $this->db->query($sql);
  255. if (!$resql) {
  256. $error++;
  257. $this->errors[] = 'Error '.$this->db->lasterror();
  258. dol_syslog('MultiCurrency::update '.join(',', $this->errors), LOG_ERR);
  259. }
  260. if (!$error && $trigger) {
  261. $result = $this->call_trigger('CURRENCY_MODIFY', $user);
  262. if ($result < 0) {
  263. $error++;
  264. }
  265. }
  266. // Commit or rollback
  267. if ($error) {
  268. $this->db->rollback();
  269. return -1 * $error;
  270. } else {
  271. $this->db->commit();
  272. return 1;
  273. }
  274. }
  275. /**
  276. * Delete object in database
  277. *
  278. * @param bool $trigger true=launch triggers after, false=disable triggers
  279. * @return int <0 if KO, >0 if OK
  280. */
  281. public function delete($trigger = true)
  282. {
  283. global $user;
  284. dol_syslog('MultiCurrency::delete', LOG_DEBUG);
  285. $error = 0;
  286. $this->db->begin();
  287. if ($trigger) {
  288. $result = $this->call_trigger('CURRENCY_DELETE', $user);
  289. if ($result < 0) {
  290. $error++;
  291. }
  292. }
  293. if (!$error) {
  294. // Delete all rates before
  295. if (!$this->deleteRates()) {
  296. $error++;
  297. $this->errors[] = 'Error '.$this->db->lasterror();
  298. dol_syslog('Currency::delete '.join(',', $this->errors), LOG_ERR);
  299. }
  300. $sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element;
  301. $sql .= " WHERE rowid = ".((int) $this->id);
  302. dol_syslog(__METHOD__, LOG_DEBUG);
  303. $resql = $this->db->query($sql);
  304. if (!$resql) {
  305. $error++;
  306. $this->errors[] = 'Error '.$this->db->lasterror();
  307. dol_syslog('MultiCurrency::delete '.join(',', $this->errors), LOG_ERR);
  308. }
  309. }
  310. // Commit or rollback
  311. if ($error) {
  312. $this->db->rollback();
  313. return -1 * $error;
  314. } else {
  315. $this->db->commit();
  316. return 1;
  317. }
  318. }
  319. /**
  320. * Delete rates in database
  321. *
  322. * @return bool false if KO, true if OK
  323. */
  324. public function deleteRates()
  325. {
  326. foreach ($this->rates as &$rate) {
  327. if ($rate->delete() <= 0) {
  328. return false;
  329. }
  330. }
  331. return true;
  332. }
  333. /**
  334. * Add a Rate into database
  335. *
  336. * @param double $rate rate value
  337. * @return int -1 if KO, 1 if OK
  338. */
  339. public function addRate($rate)
  340. {
  341. $currencyRate = new CurrencyRate($this->db);
  342. $currencyRate->rate = price2num($rate);
  343. if ($currencyRate->create($this->id) > 0) {
  344. $this->rate = $currencyRate;
  345. return 1;
  346. } else {
  347. $this->rate = null;
  348. $this->errors = $currencyRate->errors;
  349. return -1;
  350. }
  351. }
  352. /**
  353. * Try get label of code in llx_currency then add rate.
  354. *
  355. * @param string $code currency code
  356. * @param double $rate new rate
  357. * @return int -1 if KO, 1 if OK, 2 if label found and OK
  358. */
  359. public function addRateFromDolibarr($code, $rate)
  360. {
  361. global $user;
  362. $currency = new MultiCurrency($this->db);
  363. $currency->code = $code;
  364. $currency->name = $code;
  365. $sql = "SELECT label FROM ".MAIN_DB_PREFIX."c_currencies WHERE code_iso = '".$this->db->escape($code)."'";
  366. dol_syslog(__METHOD__, LOG_DEBUG);
  367. $resql = $this->db->query($sql);
  368. if ($resql && ($line = $this->db->fetch_object($resql))) {
  369. $currency->name = $line->label;
  370. }
  371. if ($currency->create($user) > 0) {
  372. $currency->addRate($rate);
  373. if (!empty($line)) {
  374. return 2;
  375. } else {
  376. return 1;
  377. }
  378. }
  379. return -1;
  380. }
  381. /**
  382. * Add new entry into llx_multicurrency_rate
  383. *
  384. * @param double $rate rate value
  385. * @return int <0 if KO, >0 if OK
  386. */
  387. public function updateRate($rate)
  388. {
  389. return $this->addRate($rate);
  390. }
  391. /**
  392. * Fetch CurrencyRate object in $this->rate
  393. *
  394. * @return int <0 if KO, 0 if not found, >0 if OK
  395. */
  396. public function getRate()
  397. {
  398. $sql = "SELECT cr.rowid";
  399. $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element_line." as cr";
  400. $sql .= " WHERE cr.fk_multicurrency = ".((int) $this->id);
  401. $sql .= " AND cr.date_sync = (SELECT MAX(cr2.date_sync) FROM ".MAIN_DB_PREFIX.$this->table_element_line." AS cr2 WHERE cr2.fk_multicurrency = ".((int) $this->id).")";
  402. dol_syslog(__METHOD__, LOG_DEBUG);
  403. $resql = $this->db->query($sql);
  404. if ($resql && ($obj = $this->db->fetch_object($resql))) {
  405. $this->rate = new CurrencyRate($this->db);
  406. return $this->rate->fetch($obj->rowid);
  407. }
  408. }
  409. /**
  410. * Get id of currency from code
  411. *
  412. * @param DoliDB $dbs object db
  413. * @param string $code code value search
  414. *
  415. * @return int 0 if not found, >0 if OK
  416. */
  417. public static function getIdFromCode($dbs, $code)
  418. {
  419. global $conf;
  420. $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."multicurrency WHERE code = '".$dbs->escape($code)."' AND entity = ".((int) $conf->entity);
  421. dol_syslog(__METHOD__, LOG_DEBUG);
  422. $resql = $dbs->query($sql);
  423. if ($resql && $obj = $dbs->fetch_object($resql)) {
  424. return $obj->rowid;
  425. } else {
  426. return 0;
  427. }
  428. }
  429. /**
  430. * Get id and rate of currency from code
  431. *
  432. * @param DoliDB $dbs Object db
  433. * @param string $code Code value search
  434. * @param integer $date_document Date from document (propal, order, invoice, ...)
  435. *
  436. * @return array [0] => id currency
  437. * [1] => rate
  438. */
  439. public static function getIdAndTxFromCode($dbs, $code, $date_document = '')
  440. {
  441. global $conf;
  442. $sql1 = "SELECT m.rowid, mc.rate FROM ".MAIN_DB_PREFIX."multicurrency m";
  443. $sql1 .= ' LEFT JOIN '.MAIN_DB_PREFIX.'multicurrency_rate mc ON (m.rowid = mc.fk_multicurrency)';
  444. $sql1 .= " WHERE m.code = '".$dbs->escape($code)."'";
  445. $sql1 .= " AND m.entity IN (".getEntity('multicurrency').")";
  446. $sql2 = '';
  447. if (!empty($conf->global->MULTICURRENCY_USE_RATE_ON_DOCUMENT_DATE) && !empty($date_document)) { // Use last known rate compared to document date
  448. $tmparray = dol_getdate($date_document);
  449. $sql2 .= " AND mc.date_sync <= '".$dbs->idate(dol_mktime(23, 59, 59, $tmparray['mon'], $tmparray['mday'], $tmparray['year'], true))."'";
  450. }
  451. $sql3 = " ORDER BY mc.date_sync DESC LIMIT 1";
  452. dol_syslog(__METHOD__, LOG_DEBUG);
  453. $resql = $dbs->query($sql1.$sql2.$sql3);
  454. if ($resql && $obj = $dbs->fetch_object($resql)) {
  455. return array($obj->rowid, $obj->rate);
  456. } else {
  457. if (!empty($conf->global->MULTICURRENCY_USE_RATE_ON_DOCUMENT_DATE)) {
  458. $resql = $dbs->query($sql1.$sql3);
  459. if ($resql && $obj = $dbs->fetch_object($resql)) {
  460. return array($obj->rowid, $obj->rate);
  461. }
  462. }
  463. return array(0, 1);
  464. }
  465. }
  466. /**
  467. * Get the conversion of amount with invoice rate
  468. *
  469. * @param int $fk_facture id of facture
  470. * @param double $amount amount to convert
  471. * @param string $way 'dolibarr' mean the amount is in dolibarr currency
  472. * @param string $table facture or facture_fourn
  473. * @return double|boolean amount converted or false if conversion fails
  474. */
  475. public static function getAmountConversionFromInvoiceRate($fk_facture, $amount, $way = 'dolibarr', $table = 'facture')
  476. {
  477. $multicurrency_tx = self::getInvoiceRate($fk_facture, $table);
  478. if ($multicurrency_tx) {
  479. if ($way == 'dolibarr') {
  480. return price2num($amount * $multicurrency_tx, 'MU');
  481. } else {
  482. return price2num($amount / $multicurrency_tx, 'MU');
  483. }
  484. } else {
  485. return false;
  486. }
  487. }
  488. /**
  489. * Get current invoite rate
  490. *
  491. * @param int $fk_facture id of facture
  492. * @param string $table facture or facture_fourn
  493. * @return float|bool Rate of currency or false if error
  494. */
  495. public static function getInvoiceRate($fk_facture, $table = 'facture')
  496. {
  497. global $db;
  498. $sql = "SELECT multicurrency_tx FROM ".MAIN_DB_PREFIX.$table." WHERE rowid = ".((int) $fk_facture);
  499. dol_syslog(__METHOD__, LOG_DEBUG);
  500. $resql = $db->query($sql);
  501. if ($resql && ($line = $db->fetch_object($resql))) {
  502. return $line->multicurrency_tx;
  503. }
  504. return false;
  505. }
  506. /**
  507. * With free account we can't set source then recalcul all rates to force another source.
  508. * This modify the array &$TRate.
  509. *
  510. * @param stdClass $TRate Object containing all currencies rates
  511. * @return int -1 if KO, 0 if nothing, 1 if OK
  512. */
  513. public static function recalculRates(&$TRate)
  514. {
  515. global $conf;
  516. if ($conf->currency != $conf->global->MULTICURRENCY_APP_SOURCE) {
  517. $alternate_source = 'USD'.$conf->currency;
  518. if (!empty($TRate->{$alternate_source})) {
  519. $coef = $TRate->USDUSD / $TRate->{$alternate_source};
  520. foreach ($TRate as $attr => &$rate) {
  521. $rate *= $coef;
  522. }
  523. return 1;
  524. }
  525. return -1; // Alternate souce not found
  526. }
  527. return 0; // Nothing to do
  528. }
  529. /**
  530. * Sync rates from API
  531. *
  532. * @param string $key Key to use. Come from $conf->global->MULTICURRENCY_APP_ID.
  533. * @param int $addifnotfound Add if not found
  534. * @return int <0 if KO, >0 if OK
  535. */
  536. public static function syncRates($key, $addifnotfound = 0)
  537. {
  538. global $conf, $db, $langs;
  539. include_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
  540. $urlendpoint = 'http://api.currencylayer.com/live?access_key='.$key;
  541. $urlendpoint .= '&source=' . (empty($conf->global->MULTICURRENCY_APP_SOURCE) ? 'USD' : $conf->global->MULTICURRENCY_APP_SOURCE);
  542. dol_syslog("Call url endpoint ".$urlendpoint);
  543. $resget = getURLContent($urlendpoint);
  544. if ($resget['content']) {
  545. $response = $resget['content'];
  546. $response = json_decode($response);
  547. if ($response->success) {
  548. $TRate = $response->quotes;
  549. $timestamp = $response->timestamp;
  550. if (self::recalculRates($TRate) >= 0) {
  551. foreach ($TRate as $currency_code => $rate) {
  552. $code = substr($currency_code, 3, 3);
  553. $obj = new MultiCurrency($db);
  554. if ($obj->fetch(null, $code) > 0) {
  555. $obj->updateRate($rate);
  556. } elseif ($addifnotfound) {
  557. self::addRateFromDolibarr($code, $rate);
  558. }
  559. }
  560. }
  561. return 1;
  562. } else {
  563. dol_syslog("Failed to call endpoint ".$response->error->info, LOG_WARNING);
  564. setEventMessages($langs->trans('multicurrency_syncronize_error', $response->error->info), null, 'errors');
  565. return -1;
  566. }
  567. }
  568. }
  569. /**
  570. * Check in database if the current code already exists
  571. *
  572. * @param string $code current code to search
  573. * @return boolean True if exists, false if not exists
  574. */
  575. public function checkCodeAlreadyExists($code)
  576. {
  577. $currencytmp = new MultiCurrency($this->db);
  578. if ($currencytmp->fetch('', $code) > 0) {
  579. return true;
  580. } else {
  581. return false;
  582. }
  583. }
  584. }
  585. /**
  586. * Class CurrencyRate
  587. */
  588. class CurrencyRate extends CommonObjectLine
  589. {
  590. /**
  591. * @var string Id to identify managed objects
  592. */
  593. public $element = 'multicurrency_rate';
  594. /**
  595. * @var string Name of table without prefix where object is stored
  596. */
  597. public $table_element = 'multicurrency_rate';
  598. /**
  599. * @var int ID
  600. */
  601. public $id;
  602. /**
  603. * @var double Rate
  604. */
  605. public $rate;
  606. /**
  607. * @var integer Date synchronisation
  608. */
  609. public $date_sync;
  610. /**
  611. * @var int Id of currency
  612. */
  613. public $fk_multicurrency;
  614. /**
  615. * @var int Id of entity
  616. */
  617. public $entity;
  618. /**
  619. * Constructor
  620. *
  621. * @param DoliDb $db Database handler
  622. */
  623. public function __construct(DoliDB $db)
  624. {
  625. $this->db = $db;
  626. return 1;
  627. }
  628. /**
  629. * Create object into database
  630. *
  631. * @param int $fk_multicurrency Id of currency
  632. * @param bool $trigger true=launch triggers after, false=disable triggers
  633. * @return int <0 if KO, Id of created object if OK
  634. */
  635. public function create($fk_multicurrency, $trigger = true)
  636. {
  637. global $conf, $user;
  638. dol_syslog('CurrencyRate::create', LOG_DEBUG);
  639. $error = 0;
  640. $this->rate = price2num($this->rate);
  641. if (empty($this->entity) || $this->entity <= 0) {
  642. $this->entity = $conf->entity;
  643. }
  644. $now = empty($this->date_sync) ? dol_now() : $this->date_sync;
  645. // Insert request
  646. $sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element."(";
  647. $sql .= ' rate,';
  648. $sql .= ' date_sync,';
  649. $sql .= ' fk_multicurrency,';
  650. $sql .= ' entity';
  651. $sql .= ') VALUES (';
  652. $sql .= ' '.((float) $this->rate).',';
  653. $sql .= " '".$this->db->idate($now)."',";
  654. $sql .= " ".((int) $fk_multicurrency).",";
  655. $sql .= " ".((int) $this->entity);
  656. $sql .= ')';
  657. $this->db->begin();
  658. dol_syslog(__METHOD__, LOG_DEBUG);
  659. $resql = $this->db->query($sql);
  660. if (!$resql) {
  661. $error++;
  662. $this->errors[] = 'Error '.$this->db->lasterror();
  663. dol_syslog('CurrencyRate::create '.join(',', $this->errors), LOG_ERR);
  664. }
  665. if (!$error) {
  666. $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
  667. $this->fk_multicurrency = $fk_multicurrency;
  668. $this->date_sync = $now;
  669. if ($trigger) {
  670. $result = $this->call_trigger('CURRENCYRATE_CREATE', $user);
  671. if ($result < 0) {
  672. $error++;
  673. }
  674. }
  675. }
  676. if ($error) {
  677. $this->db->rollback();
  678. return -1 * $error;
  679. } else {
  680. $this->db->commit();
  681. return $this->id;
  682. }
  683. }
  684. /**
  685. * Load object in memory from the database
  686. *
  687. * @param int $id Id object
  688. * @return int <0 if KO, 0 if not found, >0 if OK
  689. */
  690. public function fetch($id)
  691. {
  692. dol_syslog('CurrencyRate::fetch', LOG_DEBUG);
  693. $sql = "SELECT cr.rowid, cr.rate, cr.date_sync, cr.fk_multicurrency, cr.entity";
  694. $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." AS cr";
  695. $sql .= " WHERE cr.rowid = ".((int) $id);
  696. dol_syslog(__METHOD__, LOG_DEBUG);
  697. $resql = $this->db->query($sql);
  698. if ($resql) {
  699. $numrows = $this->db->num_rows($resql);
  700. if ($numrows) {
  701. $obj = $this->db->fetch_object($resql);
  702. $this->id = $obj->rowid;
  703. $this->rate = $obj->rate;
  704. $this->date_sync = $this->db->jdate($obj->date_sync);
  705. $this->fk_multicurrency = $obj->fk_multicurrency;
  706. $this->entity = $obj->entity;
  707. }
  708. $this->db->free($resql);
  709. if ($numrows) {
  710. return 1;
  711. } else {
  712. return 0;
  713. }
  714. } else {
  715. $this->errors[] = 'Error '.$this->db->lasterror();
  716. dol_syslog('CurrencyRate::fetch '.join(',', $this->errors), LOG_ERR);
  717. return -1;
  718. }
  719. }
  720. /**
  721. * Update object into database
  722. *
  723. * @param bool $trigger true=launch triggers after, false=disable triggers
  724. * @return int <0 if KO, >0 if OK
  725. */
  726. public function update($trigger = true)
  727. {
  728. global $user;
  729. $error = 0;
  730. dol_syslog('CurrencyRate::update', LOG_DEBUG);
  731. $this->rate = price2num($this->rate);
  732. // Update request
  733. $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
  734. $sql .= "SET rate = ".((float) $this->rate);
  735. if (!empty($this->date_sync)) {
  736. $sql .= ", date_sync = '".$this->db->idate($this->date_sync)."'";
  737. }
  738. if (!empty($this->fk_multicurrency)) {
  739. $sql .= ', fk_multicurrency = '.((int) $this->fk_multicurrency);
  740. }
  741. $sql .= " WHERE rowid =".((int) $this->id);
  742. $this->db->begin();
  743. dol_syslog(__METHOD__, LOG_DEBUG);
  744. $resql = $this->db->query($sql);
  745. if (!$resql) {
  746. $error++;
  747. $this->errors[] = 'Error '.$this->db->lasterror();
  748. dol_syslog('CurrencyRate::update '.join(',', $this->errors), LOG_ERR);
  749. }
  750. if (!$error && $trigger) {
  751. $result = $this->call_trigger('CURRENCYRATE_MODIFY', $user);
  752. if ($result < 0) {
  753. $error++;
  754. }
  755. }
  756. // Commit or rollback
  757. if ($error) {
  758. $this->db->rollback();
  759. return -1 * $error;
  760. } else {
  761. $this->db->commit();
  762. return 1;
  763. }
  764. }
  765. /**
  766. * Delete object in database
  767. *
  768. * @param bool $trigger true=launch triggers after, false=disable triggers
  769. * @return int <0 if KO, >0 if OK
  770. */
  771. public function delete($trigger = true)
  772. {
  773. global $user;
  774. dol_syslog('CurrencyRate::delete', LOG_DEBUG);
  775. $error = 0;
  776. $this->db->begin();
  777. if ($trigger) {
  778. $result = $this->call_trigger('CURRENCYRATE_DELETE', $user);
  779. if ($result < 0) {
  780. $error++;
  781. }
  782. }
  783. if (!$error) {
  784. $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element;
  785. $sql .= ' WHERE rowid='.((int) $this->id);
  786. dol_syslog(__METHOD__, LOG_DEBUG);
  787. $resql = $this->db->query($sql);
  788. if (!$resql) {
  789. $error++;
  790. $this->errors[] = 'Error '.$this->db->lasterror();
  791. dol_syslog('CurrencyRate::delete '.join(',', $this->errors), LOG_ERR);
  792. }
  793. }
  794. // Commit or rollback
  795. if ($error) {
  796. $this->db->rollback();
  797. return -1 * $error;
  798. } else {
  799. $this->db->commit();
  800. return 1;
  801. }
  802. }
  803. }