Skip to content

Commit

Permalink
Merge pull request #37385 from ruthra-kumar/multiple_currency_exchang…
Browse files Browse the repository at this point in the history
…e_provider

refactor: multiple service providers for Currency Exchange rates
  • Loading branch information
ruthra-kumar authored Oct 7, 2023
2 parents c86cd99 + 22fb656 commit fd8543e
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 24 deletions.
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
33 changes: 32 additions & 1 deletion erpnext/accounts/doctype/accounts_settings/accounts_settings.py
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

0 comments on commit fd8543e

Please sign in to comment.