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

feat: currency exchange settings #27318

Merged
merged 27 commits into from
Jan 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ff19113
feat: currency exchange settings
rtdany10 Sep 2, 2021
e093863
feat: fetch api details from settings
rtdany10 Sep 3, 2021
d8b8032
feat: init CES default values
rtdany10 Sep 3, 2021
d56c8d4
Merge branch 'develop' into currency-exchange-settings
rtdany10 Sep 3, 2021
a86d9c9
chore: code clean up
rtdany10 Sep 3, 2021
227466c
chore: clean up layout and code
rtdany10 Sep 4, 2021
06340ad
feat: button to restore default settings
rtdany10 Sep 4, 2021
c8d313b
Merge branch 'develop' into currency-exchange-settings
rtdany10 Sep 4, 2021
f460229
Merge branch 'develop' into currency-exchange-settings
rtdany10 Sep 5, 2021
882da2f
Merge branch 'develop' into currency-exchange-settings
rtdany10 Oct 27, 2021
d869b39
Merge branch 'frappe:develop' into currency-exchange-settings
rtdany10 Nov 3, 2021
7291d9f
feat: option for preconfigured selectable service providers
rtdany10 Nov 3, 2021
08b2735
fix: make fields editable only when service provider is custom
rtdany10 Nov 4, 2021
e65a76b
chore: clean up
rtdany10 Nov 4, 2021
1f8be84
fix : remove mutable data structures from argument defaults
rtdany10 Nov 4, 2021
4a0f217
fix: pre-commit issues
rtdany10 Nov 4, 2021
4716523
fix: sider issues
rtdany10 Nov 4, 2021
01e7076
Merge branch 'develop' into currency-exchange-settings
rtdany10 Nov 6, 2021
e50893e
fix: eslint brace style issue
rtdany10 Nov 13, 2021
3f8ad54
Merge branch 'develop' into currency-exchange-settings
rtdany10 Nov 13, 2021
0931d17
Merge branch 'develop' into currency-exchange-settings
deepeshgarg007 Nov 23, 2021
0592096
Merge branch 'develop' into currency-exchange-settings
rtdany10 Dec 7, 2021
c68b2c3
Merge branch 'develop' into currency-exchange-settings
rtdany10 Dec 18, 2021
e2dab6f
fix: Cleanup and fixes
deepeshgarg007 Jan 10, 2022
3fdd47e
Merge branch 'develop' of https://github.com/frappe/erpnext into curr…
deepeshgarg007 Jan 10, 2022
ca5ea5f
fix: test cases
deepeshgarg007 Jan 10, 2022
93d784d
Merge branch 'develop' of https://github.com/frappe/erpnext into curr…
deepeshgarg007 Jan 10, 2022
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
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt

frappe.ui.form.on('Currency Exchange Settings', {
service_provider: function(frm) {
if (frm.doc.service_provider == "exchangerate.host") {
let result = ['result'];
let params = {
date: '{transaction_date}',
from: '{from_currency}',
to: '{to_currency}'
};
add_param(frm, "https://api.exchangerate.host/convert", params, result);
} else if (frm.doc.service_provider == "frankfurter.app") {
let result = ['rates', '{to_currency}'];
let params = {
base: '{from_currency}',
symbols: '{to_currency}'
};
add_param(frm, "https://frankfurter.app/{transaction_date}", params, result);
}
}
});


function add_param(frm, api, params, result) {
var row;
frm.clear_table("req_params");
frm.clear_table("result_key");

frm.doc.api_endpoint = api;

$.each(params, function(key, value) {
row = frm.add_child("req_params");
row.key = key;
row.value = value;
});

$.each(result, function(key, value) {
row = frm.add_child("result_key");
row.key = value;
});

frm.refresh_fields();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
{
"actions": [],
"creation": "2022-01-10 13:03:26.237081",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"api_details_section",
"service_provider",
"api_endpoint",
"url",
"column_break_3",
"help",
"section_break_2",
"req_params",
"column_break_4",
"result_key"
],
"fields": [
{
"fieldname": "api_details_section",
"fieldtype": "Section Break",
"label": "API Details"
},
{
"fieldname": "api_endpoint",
"fieldtype": "Data",
"in_list_view": 1,
"label": "API Endpoint",
"read_only_depends_on": "eval: doc.service_provider != \"Custom\"",
"reqd": 1
},
{
"fieldname": "url",
"fieldtype": "Data",
"label": "Example URL",
"read_only": 1
},
{
"fieldname": "column_break_3",
"fieldtype": "Column Break"
},
{
"fieldname": "help",
"fieldtype": "HTML",
"label": "Help",
"options": "<h3>Currency Exchange Settings Help</h3>\n<p>There are 3 variables that could be used within the endpoint, result key and in values of the parameter.</p>\n<p>Exchange rate between {from_currency} and {to_currency} on {transaction_date} is fetched by the API.</p>\n<p>Example: If your endpoint is exchange.com/2021-08-01, then, you will have to input exchange.com/{transaction_date}</p>"
},
{
"fieldname": "section_break_2",
"fieldtype": "Section Break",
"label": "Request Parameters"
},
{
"fieldname": "req_params",
"fieldtype": "Table",
"label": "Parameters",
"options": "Currency Exchange Settings Details",
"read_only_depends_on": "eval: doc.service_provider != \"Custom\"",
"reqd": 1
},
{
"fieldname": "column_break_4",
"fieldtype": "Column Break"
},
{
"fieldname": "result_key",
"fieldtype": "Table",
"label": "Result Key",
"options": "Currency Exchange Settings Result",
"read_only_depends_on": "eval: doc.service_provider != \"Custom\"",
"reqd": 1
},
{
"fieldname": "service_provider",
"fieldtype": "Select",
"label": "Service Provider",
"options": "frankfurter.app\nexchangerate.host\nCustom",
"reqd": 1
}
],
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2022-01-10 15:51:14.521174",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Currency Exchange Settings",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"role": "System Manager",
"share": 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,
"print": 1,
"read": 1,
"role": "Accounts User",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"track_changes": 1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt

import frappe
import requests
from frappe import _
from frappe.model.document import Document
from frappe.utils import nowdate


class CurrencyExchangeSettings(Document):
def validate(self):
self.set_parameters_and_result()
response, value = self.validate_parameters()
self.validate_result(response, value)

def set_parameters_and_result(self):
if self.service_provider == 'exchangerate.host':
self.set('result_key', [])
self.set('req_params', [])

self.api_endpoint = "https://api.exchangerate.host/convert"
self.append('result_key', {'key': 'result'})
self.append('req_params', {'key': 'date', 'value': '{transaction_date}'})
self.append('req_params', {'key': 'from', 'value': '{from_currency}'})
self.append('req_params', {'key': 'to', 'value': '{to_currency}'})
elif self.service_provider == 'frankfurter.app':
self.set('result_key', [])
self.set('req_params', [])

self.api_endpoint = "https://frankfurter.app/{transaction_date}"
self.append('result_key', {'key': 'rates'})
self.append('result_key', {'key': '{to_currency}'})
self.append('req_params', {'key': 'base', 'value': '{from_currency}'})
self.append('req_params', {'key': 'symbols', 'value': '{to_currency}'})

def validate_parameters(self):
if frappe.flags.in_test:
return None, None

params = {}
for row in self.req_params:
params[row.key] = row.value.format(
transaction_date=nowdate(),
to_currency='INR',
from_currency='USD'
)

api_url = self.api_endpoint.format(
transaction_date=nowdate(),
to_currency='INR',
from_currency='USD'
)

try:
response = requests.get(api_url, params=params)
except requests.exceptions.RequestException as e:
frappe.throw("Error: " + str(e))

response.raise_for_status()
value = response.json()

return response, value

def validate_result(self, response, value):
if frappe.flags.in_test:
return

try:
for key in self.result_key:
value = value[str(key.key).format(
transaction_date=nowdate(),
to_currency='INR',
from_currency='USD'
)]
except Exception:
frappe.throw("Invalid result key. Response: " + response.text)
if not isinstance(value, (int, float)):
frappe.throw(_("Returned exchange rate is neither integer not float."))

self.url = response.url
frappe.msgprint("Exchange rate of USD to INR is " + str(value))
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt

# import frappe
import unittest


class TestCurrencyExchangeSettings(unittest.TestCase):
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"actions": [],
"creation": "2021-09-02 14:54:49.033512",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"key",
"value"
],
"fields": [
{
"fieldname": "key",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Key",
"reqd": 1
},
{
"fieldname": "value",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Value",
"reqd": 1
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2021-11-03 19:14:55.889037",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Currency Exchange Settings Details",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt

# import frappe
from frappe.model.document import Document


class CurrencyExchangeSettingsDetails(Document):
pass
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"actions": [],
"creation": "2021-09-03 13:17:22.088259",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"key"
],
"fields": [
{
"fieldname": "key",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Key",
"reqd": 1
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2021-11-03 19:14:40.054245",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Currency Exchange Settings Result",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt

# import frappe
from frappe.model.document import Document


class CurrencyExchangeSettingsResult(Document):
pass
1 change: 1 addition & 0 deletions erpnext/patches.txt
Original file line number Diff line number Diff line change
Expand Up @@ -323,3 +323,4 @@ execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings'
erpnext.patches.v14_0.set_payroll_cost_centers
erpnext.patches.v13_0.agriculture_deprecation_warning
erpnext.patches.v14_0.delete_agriculture_doctypes
erpnext.patches.v13_0.update_exchange_rate_settings
10 changes: 10 additions & 0 deletions erpnext/patches/v13_0/update_exchange_rate_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import frappe

from erpnext.setup.install import setup_currency_exchange


def execute():
frappe.reload_doc("accounts", "doctype", "currency_exchange_settings")
frappe.reload_doc("accounts", "doctype", "currency_exchange_settings_result")
frappe.reload_doc("accounts", "doctype", "currency_exchange_settings_details")
setup_currency_exchange()
Loading