From 1609933748a12412a03137021a4e830945a374f2 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 3 Sep 2015 16:03:07 +0530 Subject: [PATCH] Test cases for multi currency --- erpnext/accounts/party.py | 45 +++++++++++++------ .../buying/doctype/supplier/test_records.json | 2 +- erpnext/selling/doctype/customer/customer.js | 16 ++++--- .../selling/doctype/customer/test_customer.py | 14 +++++- .../doctype/customer/test_records.json | 2 +- erpnext/setup/doctype/company/company.py | 10 +---- 6 files changed, 59 insertions(+), 30 deletions(-) diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index 4a19645bec0..09f9b6ab236 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -11,6 +11,9 @@ from frappe.utils import add_days, getdate, formatdate, get_first_day, date_diff from erpnext.utilities.doctype.address.address import get_address_display from erpnext.utilities.doctype.contact.contact import get_contact_details +class InvalidCurrency(frappe.ValidationError): pass +class InvalidAccountCurrency(frappe.ValidationError): pass + @frappe.whitelist() def get_party_details(party=None, account=None, party_type="Customer", company=None, posting_date=None, price_list=None, currency=None, doctype=None): @@ -149,36 +152,52 @@ def validate_accounting_currency(party): if not party.party_account_currency: if party.default_currency: party.party_account_currency = party.default_currency - else: - party.party_account_currency = company_currency + elif len(set(company_currency.values())) == 1: + party.party_account_currency = company_currency.values()[0] party_account_currency_in_db = frappe.db.get_value(party.doctype, party.name, "party_account_currency") - if party_account_currency_in_db and party_account_currency_in_db != party.party_account_currency: + if party_account_currency_in_db != party.party_account_currency: existing_gle = frappe.db.get_value("GL Entry", {"party_type": party.doctype, "party": party.name}, ["name", "account_currency"], as_dict=1) if existing_gle: - frappe.throw(_("Accounting Currency cannot be changed, as GL Entry exists for this {0}") - .format(party.doctype)) + if party_account_currency_in_db: + frappe.throw(_("Accounting Currency cannot be changed, as GL Entry exists for this {0}") + .format(party.doctype), InvalidCurrency) + else: + party.party_account_currency = existing_gle.account_currency def validate_party_account(party): company_currency = get_company_currency() - - if party.party_account_currency != company_currency: - party_account_defined_for_companies = [d.company for d in party.get("accounts")] - all_companies = [d.name for d in frappe.get_list("Company")] - party_account_required_for_companies = list(set(all_companies) - set(party_account_defined_for_companies)) + if party.party_account_currency: + companies_with_different_currency = [] + for company, currency in company_currency.items(): + if currency != party.party_account_currency: + companies_with_different_currency.append(company) - if party_account_required_for_companies: + for d in party.get("accounts"): + if d.company in companies_with_different_currency: + companies_with_different_currency.remove(d.company) + + selected_account_currency = frappe.db.get_value("Account", d.account, "account_currency") + if selected_account_currency != party.party_account_currency: + frappe.throw(_("Account {0} is invalid, account currency must be {1}") + .format(d.account, selected_account_currency), InvalidAccountCurrency) + + if companies_with_different_currency: frappe.msgprint(_("Please mention Default {0} Account for the following companies, as accounting currency is different from company's default currency: {1}") .format( "Receivable" if party.doctype=="Customer" else "Payable", - "\n" + "\n".join(party_account_required_for_companies) + "\n" + "\n".join(companies_with_different_currency) ) ) def get_company_currency(): - return frappe.db.sql("select default_currency from tabCompany limit 1")[0][0] + company_currency = frappe._dict() + for d in frappe.get_all("Company", fields=["name", "default_currency"]): + company_currency.setdefault(d.name, d.default_currency) + + return company_currency @frappe.whitelist() def get_party_account(company, party, party_type): diff --git a/erpnext/buying/doctype/supplier/test_records.json b/erpnext/buying/doctype/supplier/test_records.json index 82e0a447bb7..6d01dffb614 100644 --- a/erpnext/buying/doctype/supplier/test_records.json +++ b/erpnext/buying/doctype/supplier/test_records.json @@ -13,7 +13,7 @@ "doctype": "Supplier", "supplier_name": "_Test Supplier USD", "supplier_type": "_Test Supplier Type", - "default_currency": "USD", + "party_account_currency": "USD", "accounts": [{ "company": "_Test Company", "account": "_Test Payable USD - _TC" diff --git a/erpnext/selling/doctype/customer/customer.js b/erpnext/selling/doctype/customer/customer.js index ab23d73ae8c..9325e72ae7d 100644 --- a/erpnext/selling/doctype/customer/customer.js +++ b/erpnext/selling/doctype/customer/customer.js @@ -100,11 +100,17 @@ cur_frm.fields_dict['default_price_list'].get_query = function(doc, cdt, cdn) { cur_frm.fields_dict['accounts'].grid.get_field('account').get_query = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; + var filters = { + 'account_type': 'Receivable', + 'company': d.company, + "is_group": 0 + }; + + if(doc.party_account_currency) { + $.extend(filters, {"account_currency": doc.party_account_currency}); + } + return { - filters: { - 'account_type': 'Receivable', - 'company': d.company, - "is_group": 0 - } + filters: filters } } diff --git a/erpnext/selling/doctype/customer/test_customer.py b/erpnext/selling/doctype/customer/test_customer.py index dca4bb76fb8..a0a1501a467 100644 --- a/erpnext/selling/doctype/customer/test_customer.py +++ b/erpnext/selling/doctype/customer/test_customer.py @@ -8,6 +8,8 @@ import unittest from frappe.test_runner import make_test_records from erpnext.controllers.accounts_controller import CustomerFrozen +from erpnext.accounts.party import InvalidCurrency +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice test_ignore = ["Price List"] @@ -77,4 +79,14 @@ class TestCustomer(unittest.TestCase): frappe.db.set_value("Customer", "_Test Customer", "is_frozen", 0) - so.save() \ No newline at end of file + so.save() + + def test_multi_currency(self): + customer = frappe.get_doc("Customer", "_Test Customer USD") + + create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC", + currency="USD", conversion_rate=50) + + customer.party_account_currency = "EUR" + self.assertRaises(InvalidCurrency, customer.save) + \ No newline at end of file diff --git a/erpnext/selling/doctype/customer/test_records.json b/erpnext/selling/doctype/customer/test_records.json index 5c0bbd92463..060633ec4f6 100644 --- a/erpnext/selling/doctype/customer/test_records.json +++ b/erpnext/selling/doctype/customer/test_records.json @@ -33,7 +33,7 @@ "customer_type": "Individual", "doctype": "Customer", "territory": "_Test Territory", - "default_currency": "USD", + "party_account_currency": "USD", "accounts": [{ "company": "_Test Company", "account": "_Test Receivable USD - _TC" diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index 72c6cdd52b5..804dc4deb93 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -52,15 +52,7 @@ class Company(Document): if self.default_currency and self.previous_default_currency and \ self.default_currency != self.previous_default_currency and \ self.check_if_transactions_exist(): - frappe.throw(_("Cannot change company's default currency, because there are existing transactions. Transactions must be cancelled to change the default currency.")) - - if self.default_currency: - currency_in_other_companies = frappe.db.sql("""select default_currency from tabCompany - where name!=%s limit 1""", self.name) - - if currency_in_other_companies and self.default_currency != currency_in_other_companies[0][0]: - frappe.throw(_("Currency must be same for all Companies")) - + frappe.throw(_("Cannot change company's default currency, because there are existing transactions. Transactions must be cancelled to change the default currency.")) def on_update(self): if not frappe.db.sql("""select name from tabAccount