diff --git a/crm/fcrm/doctype/crm_currency_exchange_settings/crm_currency_exchange_settings.py b/crm/fcrm/doctype/crm_currency_exchange_settings/crm_currency_exchange_settings.py index aafc54e2..da4aadd6 100644 --- a/crm/fcrm/doctype/crm_currency_exchange_settings/crm_currency_exchange_settings.py +++ b/crm/fcrm/doctype/crm_currency_exchange_settings/crm_currency_exchange_settings.py @@ -1,10 +1,55 @@ # Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -# import frappe +import frappe +import requests +from frappe import _ from frappe.model.document import Document class CRMCurrencyExchangeSettings(Document): pass + +def get_exchange_rate(from_currency, to_currency, date=None): + if not date: + date = "latest" + + api_endpoint = f"https://api.frankfurter.app/{date}?from={from_currency}&to={to_currency}" + res = requests.get(api_endpoint, timeout=5) + if res.ok: + data = res.json() + return data["rates"][to_currency] + + # Fallback to exchangerate.host if Frankfurter API fails + ces = frappe.get_single("CRM Currency Exchange Settings") + if ces and ces.service_provider == "exchangerate.host": + if not ces.access_key: + frappe.throw( + _("Access Key is required for Service Provider: {0}").format( + frappe.bold(ces.service_provider) + ) + ) + + params = { + "access_key": ces.access_key, + "from": from_currency, + "to": to_currency, + "amount": 1, + } + + if date != "latest": + params["date"] = date + + api_endpoint = "https://api.exchangerate.host/convert" + + res = requests.get(api_endpoint, params=params, timeout=5) + if res.ok: + data = res.json() + return data["result"] + + frappe.log_error( + title="Exchange Rate Fetch Error", + message=f"Failed to fetch exchange rate from {from_currency} to {to_currency} on {date}", + ) + return 1.0 # Default exchange rate if API call fails or no rate found diff --git a/crm/fcrm/doctype/crm_deal/crm_deal.py b/crm/fcrm/doctype/crm_deal/crm_deal.py index 4b9bc95d..a682d4ba 100644 --- a/crm/fcrm/doctype/crm_deal/crm_deal.py +++ b/crm/fcrm/doctype/crm_deal/crm_deal.py @@ -6,11 +6,11 @@ from frappe import _ from frappe.desk.form.assign_to import add as assign from frappe.model.document import Document +from crm.fcrm.doctype.crm_currency_exchange_settings.crm_currency_exchange_settings import get_exchange_rate from crm.fcrm.doctype.crm_service_level_agreement.utils import get_sla from crm.fcrm.doctype.crm_status_change_log.crm_status_change_log import ( add_status_change_log, ) -from crm.utils import get_exchange_rate class CRMDeal(Document): diff --git a/crm/fcrm/doctype/crm_organization/crm_organization.py b/crm/fcrm/doctype/crm_organization/crm_organization.py index e528435c..6c736eee 100644 --- a/crm/fcrm/doctype/crm_organization/crm_organization.py +++ b/crm/fcrm/doctype/crm_organization/crm_organization.py @@ -4,7 +4,7 @@ import frappe from frappe.model.document import Document -from crm.utils import get_exchange_rate +from crm.fcrm.doctype.crm_currency_exchange_settings.crm_currency_exchange_settings import get_exchange_rate class CRMOrganization(Document): diff --git a/crm/utils/__init__.py b/crm/utils/__init__.py index 0e4582df..92ee37d7 100644 --- a/crm/utils/__init__.py +++ b/crm/utils/__init__.py @@ -267,24 +267,3 @@ def sales_user_only(fn): return fn(*args, **kwargs) return wrapper - - -def get_exchange_rate(from_currency, to_currency, date=None): - if not date: - date = "latest" - - url = f"https://api.frankfurter.app/{date}?from={from_currency}&to={to_currency}" - - for _i in range(3): - response = requests.get(url) - if response.status_code == 200: - data = response.json() - rate = data["rates"].get(to_currency) - if rate: - return rate - - frappe.log_error( - title="Exchange Rate Fetch Error", - message=f"Failed to fetch exchange rate from {from_currency} to {to_currency} on {date}", - ) - return 1.0 # Default exchange rate if API call fails or no rate found