mirror of
https://github.com/frappe/erpnext.git
synced 2026-09-01 07:37:04 +00:00
Merge pull request #55918 from frappe/mergify/bp/version-15-hotfix/pr-55755
feat(currency exchange settings): frankfurter v2 support (backport #55755)
This commit is contained in:
@@ -11,22 +11,28 @@ frappe.ui.form.on("Currency Exchange Settings", {
|
|||||||
},
|
},
|
||||||
callback: function (r) {
|
callback: function (r) {
|
||||||
if (r && r.message) {
|
if (r && r.message) {
|
||||||
|
let result = [],
|
||||||
|
params = {};
|
||||||
if (frm.doc.service_provider == "exchangerate.host") {
|
if (frm.doc.service_provider == "exchangerate.host") {
|
||||||
let result = ["result"];
|
result = ["result"];
|
||||||
let params = {
|
params = {
|
||||||
date: "{transaction_date}",
|
date: "{transaction_date}",
|
||||||
from: "{from_currency}",
|
from: "{from_currency}",
|
||||||
to: "{to_currency}",
|
to: "{to_currency}",
|
||||||
};
|
};
|
||||||
add_param(frm, r.message, params, result);
|
|
||||||
} else if (["frankfurter.app", "frankfurter.dev"].includes(frm.doc.service_provider)) {
|
} else if (["frankfurter.app", "frankfurter.dev"].includes(frm.doc.service_provider)) {
|
||||||
let result = ["rates", "{to_currency}"];
|
result = ["rates", "{to_currency}"];
|
||||||
let params = {
|
params = {
|
||||||
base: "{from_currency}",
|
base: "{from_currency}",
|
||||||
symbols: "{to_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);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
"fieldname": "service_provider",
|
"fieldname": "service_provider",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"label": "Service Provider",
|
"label": "Service Provider",
|
||||||
"options": "frankfurter.dev\nexchangerate.host\nCustom",
|
"options": "frankfurter.dev\nexchangerate.host\nfrankfurter.dev - v2\nCustom",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -104,7 +104,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2025-11-25 13:03:41.896424",
|
"modified": "2026-06-15 11:25:55.873110",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Currency Exchange Settings",
|
"name": "Currency Exchange Settings",
|
||||||
@@ -121,24 +121,11 @@
|
|||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"create": 1,
|
|
||||||
"delete": 1,
|
|
||||||
"email": 1,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"role": "Accounts Manager",
|
|
||||||
"share": 1,
|
|
||||||
"write": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"create": 1,
|
|
||||||
"delete": 1,
|
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"role": "Accounts User",
|
"role": "Accounts User",
|
||||||
"share": 1,
|
"share": 1
|
||||||
"write": 1
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"row_format": "Dynamic",
|
"row_format": "Dynamic",
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class CurrencyExchangeSettings(Document):
|
|||||||
disabled: DF.Check
|
disabled: DF.Check
|
||||||
req_params: DF.Table[CurrencyExchangeSettingsDetails]
|
req_params: DF.Table[CurrencyExchangeSettingsDetails]
|
||||||
result_key: DF.Table[CurrencyExchangeSettingsResult]
|
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
|
url: DF.Data | None
|
||||||
use_http: DF.Check
|
use_http: DF.Check
|
||||||
# end: auto-generated types
|
# 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": "base", "value": "{from_currency}"})
|
||||||
self.append("req_params", {"key": "symbols", "value": "{to_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):
|
def validate_parameters(self):
|
||||||
params = {}
|
params = {}
|
||||||
for row in self.req_params:
|
for row in self.req_params:
|
||||||
@@ -105,13 +113,20 @@ class CurrencyExchangeSettings(Document):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_api_endpoint(service_provider: str | None = None, use_http: bool = False):
|
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":
|
if service_provider == "exchangerate.host":
|
||||||
api = "api.exchangerate.host/convert"
|
api = "api.exchangerate.host/convert"
|
||||||
elif service_provider == "frankfurter.app":
|
elif service_provider == "frankfurter.app":
|
||||||
api = "api.frankfurter.app/{transaction_date}"
|
api = "api.frankfurter.app/{transaction_date}"
|
||||||
elif service_provider == "frankfurter.dev":
|
elif service_provider == "frankfurter.dev":
|
||||||
api = "api.frankfurter.dev/v1/{transaction_date}"
|
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://"
|
protocol = "https://"
|
||||||
if use_http:
|
if use_http:
|
||||||
|
|||||||
@@ -68,13 +68,16 @@ def patched_requests_get(*args, **kwargs):
|
|||||||
if kwargs["params"].get("date") and kwargs["params"].get("from") and kwargs["params"].get("to"):
|
if kwargs["params"].get("date") and kwargs["params"].get("from") and kwargs["params"].get("to"):
|
||||||
if test_exchange_values.get(kwargs["params"]["date"]):
|
if test_exchange_values.get(kwargs["params"]["date"]):
|
||||||
return PatchResponse({"result": test_exchange_values[kwargs["params"]["date"]]}, 200)
|
return PatchResponse({"result": test_exchange_values[kwargs["params"]["date"]]}, 200)
|
||||||
elif args[0].startswith("https://api.frankfurter.dev") and kwargs.get("params"):
|
elif args[0].startswith("https://api.frankfurter.dev/v1") and kwargs.get("params"):
|
||||||
if kwargs["params"].get("base") and kwargs["params"].get("symbols"):
|
if kwargs["params"].get("base") and kwargs["params"].get("symbols"):
|
||||||
date = args[0].replace("https://api.frankfurter.dev/v1/", "")
|
date = args[0].replace("https://api.frankfurter.dev/v1/", "")
|
||||||
if test_exchange_values.get(date):
|
if test_exchange_values.get(date):
|
||||||
return PatchResponse(
|
return PatchResponse(
|
||||||
{"rates": {kwargs["params"].get("symbols"): test_exchange_values.get(date)}}, 200
|
{"rates": {kwargs["params"].get("symbols"): test_exchange_values.get(date)}}, 200
|
||||||
)
|
)
|
||||||
|
elif args[0].startswith("https://api.frankfurter.dev/v2") and kwargs.get("params"):
|
||||||
|
if kwargs["params"].get("date") and test_exchange_values.get(kwargs["params"]["date"]):
|
||||||
|
return PatchResponse({"rate": test_exchange_values.get(kwargs["params"]["date"])}, 200)
|
||||||
|
|
||||||
return PatchResponse({"rates": None}, 404)
|
return PatchResponse({"rates": None}, 404)
|
||||||
|
|
||||||
|
|||||||
@@ -90,14 +90,7 @@ def set_single_defaults():
|
|||||||
def setup_currency_exchange():
|
def setup_currency_exchange():
|
||||||
ces = frappe.get_single("Currency Exchange Settings")
|
ces = frappe.get_single("Currency Exchange Settings")
|
||||||
try:
|
try:
|
||||||
ces.set("result_key", [])
|
ces.service_provider = "frankfurter.dev - v2"
|
||||||
ces.set("req_params", [])
|
|
||||||
|
|
||||||
ces.api_endpoint = "https://api.frankfurter.dev/v1/{transaction_date}"
|
|
||||||
ces.append("result_key", {"key": "rates"})
|
|
||||||
ces.append("result_key", {"key": "{to_currency}"})
|
|
||||||
ces.append("req_params", {"key": "base", "value": "{from_currency}"})
|
|
||||||
ces.append("req_params", {"key": "symbols", "value": "{to_currency}"})
|
|
||||||
ces.save()
|
ces.save()
|
||||||
except frappe.ValidationError:
|
except frappe.ValidationError:
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ def get_exchange_rate(from_currency, to_currency, transaction_date=None, args=No
|
|||||||
if entries:
|
if entries:
|
||||||
return flt(entries[0].exchange_rate)
|
return flt(entries[0].exchange_rate)
|
||||||
|
|
||||||
if frappe.get_cached_value("Currency Exchange Settings", "Currency Exchange Settings", "disabled"):
|
if frappe.get_single_value("Currency Exchange Settings", "disabled"):
|
||||||
return 0.00
|
return 0.00
|
||||||
|
|
||||||
pegged_currencies = {}
|
pegged_currencies = {}
|
||||||
|
|||||||
Reference in New Issue
Block a user