Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: multiple service providers for Currency Exchange rates #37385

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
frappe.ui.form.on('Accounts Settings', {
refresh: function(frm) {

},
validate_access_key(frm) {
frappe.call({
doc: frm.doc,
method: "validate_access_key"
});
}
});

Expand Down
68 changes: 48 additions & 20 deletions erpnext/accounts/doctype/accounts_settings/accounts_settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@
"currency_exchange_section",
"allow_stale",
"stale_days",
"service_provider",
"column_break_eiyok",
"access_key",
"validate_access_key",
"report_settings_sb",
"use_custom_cash_flow"
],
Expand Down Expand Up @@ -282,32 +286,56 @@
"label": "Enable Common Party Accounting"
},
{
"default": "0",
"description": "Enabling this will allow creation of multi-currency invoices against single party account in company currency",
"fieldname": "allow_multi_currency_invoices_against_single_party_account",
"fieldtype": "Check",
"label": "Allow multi-currency invoices against single party account"
},
{
"default": "0",
"description": "Split Early Payment Discount Loss into Income and Tax Loss",
"fieldname": "book_tax_discount_loss",
"fieldtype": "Check",
"label": "Book Tax Loss on Early Payment Discount"
},
{
"default": "0",
"fieldname": "show_taxes_as_table_in_print",
"fieldtype": "Check",
"label": "Show Taxes as Table in Print"
}
"default": "0",
"description": "Enabling this will allow creation of multi-currency invoices against single party account in company currency",
"fieldname": "allow_multi_currency_invoices_against_single_party_account",
"fieldtype": "Check",
"label": "Allow multi-currency invoices against single party account"
},
{
"default": "0",
"description": "Split Early Payment Discount Loss into Income and Tax Loss",
"fieldname": "book_tax_discount_loss",
"fieldtype": "Check",
"label": "Book Tax Loss on Early Payment Discount"
},
{
"default": "0",
"fieldname": "show_taxes_as_table_in_print",
"fieldtype": "Check",
"label": "Show Taxes as Table in Print"
},
{
"default": "frankfurter.app",
"fieldname": "service_provider",
"fieldtype": "Select",
"label": "Service Provider",
"options": "frankfurter.app\nexchangerate.host"
},
{
"depends_on": "eval:doc.service_provider == \"exchangerate.host\"",
"description": "Access Key is mandatory for exchangerate.host",
"fieldname": "access_key",
"fieldtype": "Data",
"label": "Access Key"
},
{
"depends_on": "eval:doc.service_provider == \"exchangerate.host\"",
"fieldname": "validate_access_key",
"fieldtype": "Button",
"label": "Validate Access Key"
},
{
"fieldname": "column_break_eiyok",
"fieldtype": "Column Break"
}
],
"icon": "icon-cog",
"idx": 1,
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2023-06-13 18:47:46.430291",
"modified": "2023-10-07 14:20:01.779208",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,43 @@
from frappe import _
from frappe.custom.doctype.property_setter.property_setter import make_property_setter
from frappe.model.document import Document
from frappe.utils import cint
from frappe.utils import cint, nowdate

from erpnext.stock.utils import check_pending_reposting


class AccountsSettings(Document):
@frappe.whitelist()
def validate_access_key(self):
if self.service_provider == "exchangerate.host":
if not self.access_key:
frappe.throw(_("Access Key is required for exchangerate.host"))
else:
import requests

# Validate access key
api_url = "https://api.exchangerate.host/convert"
response = requests.get(
api_url,
params={
"access_key": self.access_key,
"transaction_date": nowdate(),
"amount": 1,
"from": "USD",
"to": "INR",
},
)
# exchangerate.host return 200 for all requests. Can't rely on it to raise exception
if not response.json()["success"]:
frappe.throw(
title=_("Service Provider Error"),
msg=_("Currency exchange rate serivce provider: {0} returned Error. {1}").format(
frappe.bold(self.service_provider), response.json()
),
exc=frappe.ValidationError,
)
frappe.msgprint(msg=_("Success"), title=_("Access Key Validation"))

def on_update(self):
frappe.clear_cache()

Expand Down
24 changes: 21 additions & 3 deletions erpnext/setup/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,30 @@ def get_exchange_rate(from_currency, to_currency, transaction_date=None, args=No
if not value:
import requests

api_url = f"https://api.frankfurter.app/{transaction_date}"
response = requests.get(api_url, params={"from": from_currency, "to": to_currency})
if currency_settings.service_provider == "exchangerate.host":
api_url = "https://api.exchangerate.host/convert"
response = requests.get(
api_url,
params={
"access_key": currency_settings.access_key,
"transaction_date": transaction_date,
"amount": 1,
"from": from_currency,
"to": to_currency,
},
)
# exchangerate.host return 200 for all requests. Can't rely on it to raise exception
value = response.json()["result"]
if not response.json()["success"]:
raise frappe.ValidationError

else:
api_url = f"https://api.frankfurter.app/{transaction_date}"
response = requests.get(api_url, params={"from": from_currency, "to": to_currency})
value = response.json()["rates"][to_currency]

# expire in 6 hours
response.raise_for_status()
value = response.json()["rates"][to_currency]
cache.setex(name=key, time=21600, value=flt(value))
return flt(value)
except Exception:
Expand Down
Loading