From 3eb5cb14d127909d68e8511b504f6e65d24e5df7 Mon Sep 17 00:00:00 2001 From: tunde Date: Thu, 8 Jun 2017 14:23:49 +0100 Subject: [PATCH 1/8] calls erpnext.setup.utils.get_exchange_rate instead of get_average_exchange_rate --- erpnext/accounts/doctype/payment_entry/payment_entry.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index 2eef79cd761..345210de528 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -317,10 +317,12 @@ frappe.ui.form.on('Payment Entry', { frm.set_value("source_exchange_rate", 1); } else if (frm.doc.paid_from){ if (in_list(["Internal Transfer", "Pay"], frm.doc.payment_type)) { + var company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency; frappe.call({ - method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_average_exchange_rate", + method: "erpnext.setup.utils.get_exchange_rate", args: { - account: frm.doc.paid_from + from_currency: frm.doc.paid_from_account_currency, + to_currency: company_currency }, callback: function(r, rt) { frm.set_value("source_exchange_rate", r.message); From 88f1d316d853a1083e9d8d14bb83c9a69729d796 Mon Sep 17 00:00:00 2001 From: tunde Date: Thu, 8 Jun 2017 19:44:26 +0100 Subject: [PATCH 2/8] adds new tests that verify that `get_exchange_rate` returns the latest exchange rate --- .../test_currency_exchange.py | 37 ++++++++++++++++--- .../currency_exchange/test_records.json | 14 +++++++ 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py b/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py index 181f07257b3..d4c9df380f3 100644 --- a/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py +++ b/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py @@ -6,15 +6,42 @@ from __future__ import unicode_literals import frappe, unittest test_records = frappe.get_test_records('Currency Exchange') + +def save_new_records(test_records): + for record in test_records: + kwargs = dict( + doctype=record.get("doctype"), + docname=record.get("date") + '-' + record.get("from_currency") + '-' + record.get("to_currency"), + fieldname="exchange_rate", + value=record.get("exchange_rate"), + ) + + try: + frappe.set_value(**kwargs) + except frappe.DoesNotExistError: + curr_exchange = frappe.new_doc(record.get("doctype")) + curr_exchange.date = record["date"] + curr_exchange.from_currency = record["from_currency"] + curr_exchange.to_currency = record["to_currency"] + curr_exchange.exchange_rate = record["exchange_rate"] + curr_exchange.insert() + + class TestCurrencyExchange(unittest.TestCase): def test_exchnage_rate(self): from erpnext.setup.utils import get_exchange_rate - - # Exchange rate as on 15th Jan, 2016, should be fetched from Currency Exchange record - exchange_rate = get_exchange_rate("USD", "INR", "2016-01-15") + + save_new_records(test_records) + + exchange_rate = get_exchange_rate("USD", "INR", "2016-01-01") self.assertEqual(exchange_rate, 60.0) + + exchange_rate = get_exchange_rate("USD", "INR", "2016-01-15") + self.assertEqual(exchange_rate, 65.1) + + exchange_rate = get_exchange_rate("USD", "INR", "2016-01-30") + self.assertEqual(exchange_rate, 62.9) # Exchange rate as on 15th Dec, 2015, should be fetched from fixer.io exchange_rate = get_exchange_rate("USD", "INR", "2015-12-15") - self.assertFalse(exchange_rate==60) - \ No newline at end of file + self.assertFalse(exchange_rate==60) \ No newline at end of file diff --git a/erpnext/setup/doctype/currency_exchange/test_records.json b/erpnext/setup/doctype/currency_exchange/test_records.json index 23edd8a7994..d2f658b443c 100644 --- a/erpnext/setup/doctype/currency_exchange/test_records.json +++ b/erpnext/setup/doctype/currency_exchange/test_records.json @@ -19,5 +19,19 @@ "exchange_rate": 0.0167, "from_currency": "INR", "to_currency": "USD" + }, + { + "doctype": "Currency Exchange", + "date": "2016-01-10", + "exchange_rate": 65.1, + "from_currency": "USD", + "to_currency": "INR" + }, + { + "doctype": "Currency Exchange", + "date": "2016-01-30", + "exchange_rate": 62.9, + "from_currency": "USD", + "to_currency": "INR" } ] \ No newline at end of file From 6148fe0909f1f5b8a2e131dc7e2a3a0bf5d79465 Mon Sep 17 00:00:00 2001 From: tunde Date: Thu, 8 Jun 2017 20:50:11 +0100 Subject: [PATCH 3/8] adds test case to confirm that latest exchange rate is automatically selected --- .../payment_entry/test_payment_entry.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py index 8be5f6d847e..8dcee9a0433 100644 --- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py @@ -112,6 +112,29 @@ class TestPaymentEntry(unittest.TestCase): outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount")) self.assertEqual(outstanding_amount, 80) + + def test_payment_entry_retrieves_last_exchange_rate(self): + pe = frappe.new_doc("Payment Entry") + pe.payment_type = "Pay" + pe.company = "_Test Company" + pe.posting_date = "2016-01-10" + pe.paid_from = "_Test Bank USD - _TC" + pe.paid_to = "_Test Bank - _TC" + pe.paid_amount = 100 + pe.reference_no = "3" + pe.reference_date = nowdate() + pe.party_type = "Supplier" + pe.party = "_Test Supplier USD" + + pe.setup_party_account_field() + pe.set_missing_values() + pe.set_exchange_rate() + pe.set_amounts() + + self.assertEqual( + pe.source_exchange_rate, 65.1, + "{0} is not equal to {1}".format(pe.source_exchange_rate, 65.1) + ) def test_internal_transfer_usd_to_inr(self): pe = frappe.new_doc("Payment Entry") From 9b827e5b953710b8f16f477a550bf26a85a00f41 Mon Sep 17 00:00:00 2001 From: tunde Date: Thu, 8 Jun 2017 20:54:01 +0100 Subject: [PATCH 4/8] makes `set_exchange_rate` retrieve the latest exchange rate not average for "pay" and "internal transfer" payment entries --- erpnext/accounts/doctype/payment_entry/payment_entry.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index d42bcd57c90..79b46c83169 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -149,8 +149,6 @@ class PaymentEntry(AccountsController): if self.paid_from and not self.source_exchange_rate: if self.paid_from_account_currency == self.company_currency: self.source_exchange_rate = 1 - elif self.payment_type in ("Pay", "Internal Transfer"): - self.source_exchange_rate = get_average_exchange_rate(self.paid_from) else: self.source_exchange_rate = get_exchange_rate(self.paid_from_account_currency, self.company_currency, self.posting_date) From 0a5db528b1fedc50740bbcaa7ae8f8815b0f1283 Mon Sep 17 00:00:00 2001 From: tunde Date: Fri, 9 Jun 2017 08:14:10 +0100 Subject: [PATCH 5/8] makes sure latest test fixtures for currency exchange is retrieved before running test --- .../accounts/doctype/payment_entry/test_payment_entry.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py index 8dcee9a0433..ccf114fa731 100644 --- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py @@ -114,6 +114,11 @@ class TestPaymentEntry(unittest.TestCase): self.assertEqual(outstanding_amount, 80) def test_payment_entry_retrieves_last_exchange_rate(self): + from erpnext.setup.doctype.currency_exchange.test_currency_exchange import test_records, save_new_records + + test_records = test_records + save_new_records(test_records) + pe = frappe.new_doc("Payment Entry") pe.payment_type = "Pay" pe.company = "_Test Company" @@ -122,7 +127,7 @@ class TestPaymentEntry(unittest.TestCase): pe.paid_to = "_Test Bank - _TC" pe.paid_amount = 100 pe.reference_no = "3" - pe.reference_date = nowdate() + pe.reference_date = "2016-01-10" pe.party_type = "Supplier" pe.party = "_Test Supplier USD" From 5127da952e36c5ac2224c45bb6f74fc62008f7ce Mon Sep 17 00:00:00 2001 From: tunde Date: Fri, 9 Jun 2017 15:01:12 +0100 Subject: [PATCH 6/8] changes expected payment_account in test case according to the fact that exchange rate should return latest saved rate --- .../accounts/doctype/payment_request/test_payment_request.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/payment_request/test_payment_request.py b/erpnext/accounts/doctype/payment_request/test_payment_request.py index bf3e24fe7af..06231ebbd3b 100644 --- a/erpnext/accounts/doctype/payment_request/test_payment_request.py +++ b/erpnext/accounts/doctype/payment_request/test_payment_request.py @@ -87,8 +87,8 @@ class TestPaymentRequest(unittest.TestCase): expected_gle = dict((d[0], d) for d in [ ["_Test Receivable USD - _TC", 0, 5000, si_usd.name], - [pr.payment_account, 6000.0, 0, None], - ["_Test Exchange Gain/Loss - _TC", 0, 1000, None] + [pr.payment_account, 6290.0, 0, None], + ["_Test Exchange Gain/Loss - _TC", 0, 1290, None] ]) gl_entries = frappe.db.sql("""select account, debit, credit, against_voucher From 3514332cd8f52dca1e4db8cd2ecd22c18712cd4b Mon Sep 17 00:00:00 2001 From: tunde Date: Wed, 14 Jun 2017 11:59:43 +0100 Subject: [PATCH 7/8] changes `journal_entry.get_exchange_rate` to return exchange rate at date not average exchange rate --- erpnext/accounts/doctype/journal_entry/journal_entry.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 34d9de70646..d5a1d627528 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -871,14 +871,9 @@ def get_exchange_rate(posting_date, account=None, account_currency=None, company if reference_type in ("Sales Invoice", "Purchase Invoice") and reference_name: exchange_rate = frappe.db.get_value(reference_type, reference_name, "conversion_rate") - elif account_details and account_details.account_type == "Bank" and \ - ((account_details.root_type == "Asset" and flt(credit) > 0) or - (account_details.root_type == "Liability" and debit)): - exchange_rate = get_average_exchange_rate(account) - # The date used to retreive the exchange rate here is the date passed # in as an argument to this function. - if not exchange_rate and account_currency and posting_date: + elif account_currency and posting_date: exchange_rate = get_exchange_rate(account_currency, company_currency, posting_date) else: exchange_rate = 1 From 2153399c391b7289012a0bd560ebd00de15ca7ab Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 15 Jun 2017 12:30:58 +0530 Subject: [PATCH 8/8] Create journal_entry.py --- erpnext/accounts/doctype/journal_entry/journal_entry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index d5a1d627528..a3de8da9a29 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -873,7 +873,7 @@ def get_exchange_rate(posting_date, account=None, account_currency=None, company # The date used to retreive the exchange rate here is the date passed # in as an argument to this function. - elif account_currency and posting_date: + elif (not exchange_rate or exchange_rate==1) and account_currency and posting_date: exchange_rate = get_exchange_rate(account_currency, company_currency, posting_date) else: exchange_rate = 1