30require_once DOL_DOCUMENT_ROOT.
'/core/class/commonobject.class.php';
31require_once DOL_DOCUMENT_ROOT.
'/multicurrency/class/currencyrate.class.php';
44 public $element =
'multicurrency';
49 public $table_element =
'multicurrency';
54 public $table_element_line =
"multicurrency_rate";
59 public $rates = array();
102 const MULTICURRENCY_APP_ENDPOINT_DEFAULT =
'https://api.currencylayer.com/live?access_key=__MULTICURRENCY_APP_KEY__&source=__MULTICURRENCY_APP_SOURCE__';
116 $urlendpoint =
getDolGlobalString(
"MULTICURRENCY_APP_ENDPOINT", self::MULTICURRENCY_APP_ENDPOINT_DEFAULT);
118 $this->urlendpoint = str_replace(array(
'__MULTICURRENCY_APP_KEY__',
'__MULTICURRENCY_APP_SOURCE__'), array($key, $source), $urlendpoint);
130 global
$conf, $langs;
132 dol_syslog(
'MultiCurrency::create', LOG_DEBUG);
136 if (self::checkCodeAlreadyExists($this->code)) {
138 $this->errors[] = $langs->trans(
'multicurrency_code_already_added');
142 if (empty($this->entity) || $this->entity <= 0) {
143 $this->entity =
$conf->entity;
148 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.$this->table_element.
"(";
152 $sql .=
' date_create,';
154 $sql .=
') VALUES (';
155 $sql .=
" '".$this->db->escape($this->code).
"',";
156 $sql .=
" '".$this->db->escape($this->
name).
"',";
157 $sql .=
" ".((int) $this->entity).
",";
158 $sql .=
" '".$this->db->idate($now).
"',";
159 $sql .=
" ".((int) $user->id);
165 $resql = $this->db->query($sql);
168 $this->errors[] =
'Error '.$this->db->lasterror();
169 dol_syslog(
'MultiCurrency::create '.implode(
',', $this->errors), LOG_ERR);
173 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
174 $this->date_create = $now;
175 $this->fk_user = $user->id;
177 if (empty($notrigger)) {
178 $result = $this->call_trigger(
'CURRENCY_CREATE', $user);
186 $this->db->rollback();
203 public function fetch($id, $code =
null)
205 dol_syslog(
'MultiCurrency::fetch', LOG_DEBUG);
207 $sql =
"SELECT c.rowid, c.name, c.code, c.entity, c.date_create, c.fk_user";
208 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" AS c";
210 $sql .=
" WHERE c.code = '".$this->db->escape($code).
"'";
211 $sql .=
" AND c.entity IN (".getEntity($this->element).
")";
213 $sql .=
' WHERE c.rowid = '.((int) $id);
217 $resql = $this->db->query($sql);
220 $numrows = $this->db->num_rows($resql);
222 $obj = $this->db->fetch_object($resql);
224 $this->
id = $obj->rowid;
225 $this->
name = $obj->name;
226 $this->code = $obj->code;
227 $this->entity = $obj->entity;
228 $this->date_create = $obj->date_create;
229 $this->fk_user = $obj->fk_user;
234 $this->db->free($resql);
242 $this->errors[] =
'Error '.$this->db->lasterror();
243 dol_syslog(
'MultiCurrency::fetch '.implode(
',', $this->errors), LOG_ERR);
256 $sql =
"SELECT cr.rowid";
257 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element_line.
" as cr";
258 $sql .=
" WHERE cr.entity IN (".getEntity($this->element).
")";
259 $sql .=
" AND cr.fk_multicurrency = ".((int) $this->
id);
260 $sql .=
" ORDER BY cr.date_sync DESC";
262 $this->rates = array();
265 $resql = $this->db->query($sql);
267 $num = $this->db->num_rows($resql);
269 while ($obj = $this->db->fetch_object($resql)) {
271 $rate->fetch($obj->rowid);
273 $this->rates[] = $rate;
275 $this->db->free($resql);
279 $this->errors[] =
'Error '.$this->db->lasterror();
280 dol_syslog(
'MultiCurrency::fetchAllCurrencyRate '.implode(
',', $this->errors), LOG_ERR);
297 dol_syslog(
'MultiCurrency::update', LOG_DEBUG);
301 $this->code = trim($this->code);
304 if (empty($this->code)) {
306 dol_syslog(
'MultiCurrency::update $this->code can not be empty', LOG_ERR);
312 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element.
" SET";
313 $sql .=
" name = '".$this->db->escape($this->
name).
"',";
314 $sql .=
" code = '".$this->db->escape($this->code).
"'";
315 $sql .=
" WHERE rowid = ".((int) $this->
id);
319 $resql = $this->db->query($sql);
322 $this->errors[] =
'Error '.$this->db->lasterror();
323 dol_syslog(
'MultiCurrency::update '.implode(
',', $this->errors), LOG_ERR);
326 if (!$error && empty($notrigger)) {
327 $result = $this->call_trigger(
'CURRENCY_MODIFY', $user);
335 $this->db->rollback();
352 public function delete(
User $user, $notrigger = 0)
354 dol_syslog(
'MultiCurrency::delete', LOG_DEBUG);
360 if (empty($notrigger)) {
361 $result = $this->call_trigger(
'CURRENCY_DELETE', $user);
371 $this->errors[] =
'Error '.$this->db->lasterror();
372 dol_syslog(
'Currency::delete '.implode(
',', $this->errors), LOG_ERR);
375 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.$this->table_element;
376 $sql .=
" WHERE rowid = ".((int) $this->
id);
379 $resql = $this->db->query($sql);
382 $this->errors[] =
'Error '.$this->db->lasterror();
383 dol_syslog(
'MultiCurrency::delete '.implode(
',', $this->errors), LOG_ERR);
389 $this->db->rollback();
408 foreach ($this->rates as &$rate) {
409 if ($rate->delete($user) <= 0) {
428 $currencyRate->rate = (float)
price2num($rate);
430 if ($currencyRate->create($user, $this->id) > 0) {
431 $this->rate = $currencyRate;
435 $this->errors = $currencyRate->errors;
452 $currency->code = $code;
453 $currency->name = $code;
455 $sql =
"SELECT label FROM ".MAIN_DB_PREFIX.
"c_currencies WHERE code_iso = '".$this->db->escape($code).
"'";
458 $resql = $this->db->query($sql);
459 if ($resql && ($line = $this->db->fetch_object($resql))) {
460 $currency->name = $line->label;
463 if ($currency->create($user) > 0) {
464 $currency->addRate($rate);
494 $sql =
"SELECT cr.rowid";
495 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element_line.
" as cr";
496 $sql .=
" WHERE cr.entity IN (".getEntity($this->element).
")";
497 $sql .=
" AND cr.fk_multicurrency = ".((int) $this->
id);
498 $sql .=
" AND cr.date_sync = (SELECT MAX(cr2.date_sync) FROM ".MAIN_DB_PREFIX.$this->table_element_line.
" AS cr2";
499 $sql .=
" WHERE cr2.entity IN (".getEntity($this->element).
") AND cr2.fk_multicurrency = ".((int) $this->
id).
")";
503 $resql = $this->db->query($sql);
504 if ($resql && ($obj = $this->db->fetch_object($resql))) {
506 return $this->rate->fetch($obj->rowid);
524 $sql =
"SELECT rowid FROM ".MAIN_DB_PREFIX.
"multicurrency WHERE code = '".$dbs->escape($code).
"' AND entity = ".((int)
$conf->entity);
527 $resql = $dbs->query($sql);
528 if ($resql && $obj = $dbs->fetch_object($resql)) {
547 $sql1 =
"SELECT m.rowid, mc.rate, mc.rate_direct FROM ".MAIN_DB_PREFIX.
"multicurrency m";
548 $sql1 .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'multicurrency_rate mc ON (m.rowid = mc.fk_multicurrency)';
549 $sql1 .=
" WHERE m.code = '".$dbs->escape($code).
"'";
550 $sql1 .=
" AND m.entity IN (".getEntity(
'multicurrency').
")";
552 if (
getDolGlobalString(
'MULTICURRENCY_USE_RATE_ON_DOCUMENT_DATE') && !empty($date_document)) {
554 $sql2 .=
" AND mc.date_sync <= '".$dbs->idate(
dol_mktime(23, 59, 59, $tmparray[
'mon'], $tmparray[
'mday'], $tmparray[
'year'],
true)).
"'";
556 $sql3 =
" ORDER BY mc.date_sync DESC LIMIT 1";
559 $resql = $dbs->query($sql1.$sql2.$sql3);
561 if ($resql && $obj = $dbs->fetch_object($resql)) {
562 return array($obj->rowid, $obj->rate);
565 $resql = $dbs->query($sql1.$sql3);
566 if ($resql && $obj = $dbs->fetch_object($resql)) {
567 return array($obj->rowid, $obj->rate, $obj->rate_direct);
587 if (!is_null($invoice_rate)) {
588 $multicurrency_tx = $invoice_rate;
591 $multicurrency_tx = $tmparray[
'invoice_multicurrency_tx'];
594 if ($multicurrency_tx) {
595 if ($way ==
'dolibarr') {
596 return (
float)
price2num($amount * $multicurrency_tx,
'MU');
598 return (
float)
price2num($amount / $multicurrency_tx,
'MU');
616 $sql =
"SELECT multicurrency_tx, multicurrency_code";
617 $sql .=
" FROM ".MAIN_DB_PREFIX.$db->sanitize($table);
618 $sql .=
" WHERE rowid = ".((int) $fk_facture);
621 $resql =
$db->query($sql);
622 if ($resql && ($line =
$db->fetch_object($resql))) {
623 return array(
'invoice_multicurrency_tx' => $line->multicurrency_tx,
'invoice_multicurrency_code' => $line->multicurrency_code);
642 $alternate_source =
'USD'.getDolCurrency();
643 if (!empty($TRate->$alternate_source)) {
644 $coef = 1 / $TRate->$alternate_source;
645 foreach ($TRate as $attr => &$rate) {
648 $TRate->USDUSD = $coef;
667 public function syncRates($nu = 0, $addifnotfound = 0, $mode =
"")
672 if ($mode ==
"cron") {
673 $this->output = $langs->trans(
'Use of API for currency update is disabled by option MULTICURRENCY_DISABLE_SYNC_CURRENCYLAYER');
675 setEventMessages($langs->trans(
'Use of API for currency update is disabled by option MULTICURRENCY_DISABLE_SYNC_CURRENCYLAYER'),
null,
'errors');
680 include_once DOL_DOCUMENT_ROOT.
'/core/lib/geturl.lib.php';
682 $urlendpoint = $this->urlendpoint;
684 dol_syslog(
"Call url endpoint ".$urlendpoint);
688 $resget =
getURLContent($urlendpoint,
'GET',
'', 1, $addheaders);
695 if (!empty($resget[
'content'])) {
696 $response = $resget[
'content'];
697 $response = json_decode($response);
699 if ($response->success) {
700 $TRate = $response->quotes;
705 foreach ($TRate as $currency_code => $rate) {
706 $code = substr($currency_code, 3, 3);
708 if ($obj->fetch(0, $code) > 0) {
709 $obj->updateRate($rate);
710 } elseif ($addifnotfound) {
716 if ($mode ==
"cron") {
721 if (isset($response->error->info)) {
722 $error_info_syslog = $response->error->info;
723 $error_info = $error_info_syslog;
725 $error_info_syslog = json_encode($response);
726 if (empty($resget[
'content'])) {
727 $error_info =
"No error information found (see syslog)";
729 $error_info = $resget[
'content'];
733 dol_syslog(
"Failed to call endpoint ".$error_info_syslog, LOG_WARNING);
735 $this->output = $langs->trans(
'multicurrency_syncronize_error', $error_info);
740 $this->output = $resget[
'curl_error_msg'];
755 if ($currencytmp->fetch(0, $code) > 0) {
Parent class of all other business classes (invoices, contracts, proposals, orders,...
Class to manage Dolibarr database access.
static getInvoiceRate($fk_facture, $table='facture')
Get current invoite rate.
getRate()
Fetch CurrencyRate object in $this->rate.
static getIdAndTxFromCode($dbs, $code, $date_document=0)
Get id and rate of currency from code.
update(User $user, $notrigger=0)
Update object into database.
syncRates($nu=0, $addifnotfound=0, $mode="")
Sync rates from API.
fetchAllCurrencyRate()
Load all rates in object from the database.
static getAmountConversionFromInvoiceRate($fk_facture, $amount, $way='dolibarr', $table='facture', $invoice_rate=null)
Get the conversion of amount with invoice rate.
checkCodeAlreadyExists($code)
Check in database if the current code already exists.
updateRate($rate)
Add new entry into llx_multicurrency_rate.
static getIdFromCode($dbs, $code)
Get id of currency from code.
__construct(DoliDB $db)
Constructor.
deleteRates()
Delete rates in database.
create(User $user, $notrigger=0)
Create object into database.
addRateFromDolibarr($code, $rate)
Try get label of code in llx_currency then add rate.
recalculRates(&$TRate)
With free account we can't set source to something else than US, to we recalculate all rates to force...
fetch($id, $code=null)
Load object in memory from the database.
addRate($rate)
Add a Rate into database.
Class to manage Dolibarr users.
dol_now($mode='gmt')
Return date for now.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
getDolCurrency()
Return the main currency ('EUR', 'USD', ...)
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.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
getURLContent($url, $postorget='GET', $param='', $followlocation=1, $addheaders=array(), $allowedschemes=array('http', 'https'), $localurl=0, $ssl_verifypeer=-1, $timeoutconnect=0, $timeoutresponse=0, $otherCurlOptions=array(), $morelogsuffix='')
Function to get a content from an URL (use proxy if proxy defined).
$conf db name
Only used if Module[ID]Name translation string is not found.