From e804bf33ba388debd6a601220aa6709cbf19daee Mon Sep 17 00:00:00 2001 From: diptanilsaha Date: Tue, 9 Jun 2026 11:58:30 +0530 Subject: [PATCH] feat(currency exchange settings): frankfurter v2 support (cherry picked from commit 56bfe6b6a695b2d93ceedf8d50082aa732789b2a) --- .../currency_exchange_settings.js | 18 ++++++++++++------ .../currency_exchange_settings.json | 6 +++--- .../currency_exchange_settings.py | 19 +++++++++++++++++-- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.js b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.js index 40f0938ee1c..950092a2382 100644 --- a/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.js +++ b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.js @@ -11,22 +11,28 @@ frappe.ui.form.on("Currency Exchange Settings", { }, callback: function (r) { if (r && r.message) { + let result = [], + params = {}; if (frm.doc.service_provider == "exchangerate.host") { - let result = ["result"]; - let params = { + result = ["result"]; + params = { date: "{transaction_date}", from: "{from_currency}", to: "{to_currency}", }; - add_param(frm, r.message, params, result); } else if (["frankfurter.app", "frankfurter.dev"].includes(frm.doc.service_provider)) { - let result = ["rates", "{to_currency}"]; - let params = { + result = ["rates", "{to_currency}"]; + params = { base: "{from_currency}", symbols: "{to_currency}", }; - add_param(frm, r.message, params, result); + } else if (frm.doc.service_provider == "frankfurter.dev - v2") { + result = ["rate"]; + params = { + date: "{transaction_date}", + }; } + add_param(frm, r.message, params, result); } }, }); diff --git a/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.json b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.json index 9f0852bb686..2fbb0086245 100644 --- a/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.json +++ b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.json @@ -1,5 +1,6 @@ { "actions": [], + "allow_bulk_edit": 1, "creation": "2022-01-10 13:03:26.237081", "doctype": "DocType", "editable_grid": 1, @@ -78,7 +79,7 @@ "fieldname": "service_provider", "fieldtype": "Select", "label": "Service Provider", - "options": "frankfurter.dev\nexchangerate.host\nCustom", + "options": "frankfurter.dev\nexchangerate.host\nfrankfurter.dev - v2\nCustom", "reqd": 1 }, { @@ -101,11 +102,10 @@ "label": "Use HTTP Protocol" } ], - "hide_toolbar": 0, "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2026-03-16 13:28:21.075743", + "modified": "2026-06-09 11:34:10.432378", "modified_by": "Administrator", "module": "Accounts", "name": "Currency Exchange Settings", diff --git a/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.py b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.py index 55f967fc788..3d7651cb485 100644 --- a/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.py +++ b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.py @@ -29,7 +29,7 @@ class CurrencyExchangeSettings(Document): disabled: DF.Check req_params: DF.Table[CurrencyExchangeSettingsDetails] result_key: DF.Table[CurrencyExchangeSettingsResult] - service_provider: DF.Literal["frankfurter.dev", "exchangerate.host", "Custom"] + service_provider: DF.Literal["frankfurter.dev", "exchangerate.host", "frankfurter.dev - v2", "Custom"] url: DF.Data | None use_http: DF.Check # end: auto-generated types @@ -70,6 +70,14 @@ class CurrencyExchangeSettings(Document): self.append("req_params", {"key": "base", "value": "{from_currency}"}) self.append("req_params", {"key": "symbols", "value": "{to_currency}"}) + elif self.service_provider == "frankfurter.dev - v2": + self.set("result_key", []) + self.set("req_params", []) + + self.api_endpoint = get_api_endpoint(self.service_provider, self.use_http) + self.append("result_key", {"key": "rate"}) + self.append("req_params", {"key": "date", "value": "{transaction_date}"}) + def validate_parameters(self): params = {} for row in self.req_params: @@ -105,13 +113,20 @@ class CurrencyExchangeSettings(Document): @frappe.whitelist() def get_api_endpoint(service_provider: str | None = None, use_http: bool = False): - if service_provider and service_provider in ["exchangerate.host", "frankfurter.dev", "frankfurter.app"]: + if service_provider and service_provider in [ + "exchangerate.host", + "frankfurter.dev", + "frankfurter.app", + "frankfurter.dev - v2", + ]: if service_provider == "exchangerate.host": api = "api.exchangerate.host/convert" elif service_provider == "frankfurter.app": api = "api.frankfurter.app/{transaction_date}" elif service_provider == "frankfurter.dev": api = "api.frankfurter.dev/v1/{transaction_date}" + elif service_provider == "frankfurter.dev - v2": + api = "api.frankfurter.dev/v2/rate/{from_currency}/{to_currency}" protocol = "https://" if use_http: