[fix] added validation to match account currency with existing gle and test case
This commit is contained in:
parent
248c867a2c
commit
4945b94950
@ -6,12 +6,10 @@ import frappe
|
|||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import flt, fmt_money, getdate, formatdate
|
from frappe.utils import flt, fmt_money, getdate, formatdate
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from erpnext.accounts.party import get_party_account_currency
|
from erpnext.accounts.party import validate_party_gle_currency, get_party_account_currency
|
||||||
from erpnext.accounts.utils import get_account_currency
|
from erpnext.accounts.utils import get_account_currency
|
||||||
|
from erpnext.setup.doctype.company.company import get_company_currency
|
||||||
class CustomerFrozen(frappe.ValidationError): pass
|
from erpnext.exceptions import InvalidAccountCurrency, CustomerFrozen
|
||||||
class InvalidCurrency(frappe.ValidationError): pass
|
|
||||||
class InvalidAccountCurrency(frappe.ValidationError): pass
|
|
||||||
|
|
||||||
class GLEntry(Document):
|
class GLEntry(Document):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
@ -103,16 +101,16 @@ class GLEntry(Document):
|
|||||||
frappe.throw("{0} {1} is frozen".format(self.party_type, self.party), CustomerFrozen)
|
frappe.throw("{0} {1} is frozen".format(self.party_type, self.party), CustomerFrozen)
|
||||||
|
|
||||||
def validate_currency(self):
|
def validate_currency(self):
|
||||||
company_currency = frappe.db.get_value("Company", self.company, "default_currency")
|
company_currency = get_company_currency(self.company)
|
||||||
account_currency = get_account_currency(self.account)
|
account_currency = get_account_currency(self.account)
|
||||||
|
|
||||||
if not self.account_currency:
|
if not self.account_currency:
|
||||||
self.account_currency = company_currency
|
self.account_currency = company_currency
|
||||||
|
|
||||||
if account_currency != self.account_currency:
|
if account_currency != self.account_currency:
|
||||||
frappe.throw(_("Accounting Entry for {0} can only be made in currency: {1}")
|
frappe.throw(_("Accounting Entry for {0} can only be made in currency: {1}")
|
||||||
.format(self.account, (account_currency or company_currency)), InvalidAccountCurrency)
|
.format(self.account, (account_currency or company_currency)), InvalidAccountCurrency)
|
||||||
|
|
||||||
|
|
||||||
if self.party_type and self.party:
|
if self.party_type and self.party:
|
||||||
party_account_currency = get_party_account_currency(self.party_type, self.party, self.company)
|
party_account_currency = get_party_account_currency(self.party_type, self.party, self.company)
|
||||||
|
|
||||||
@ -120,6 +118,8 @@ class GLEntry(Document):
|
|||||||
frappe.throw(_("Accounting Entry for {0}: {1} can only be made in currency: {2}")
|
frappe.throw(_("Accounting Entry for {0}: {1} can only be made in currency: {2}")
|
||||||
.format(self.party_type, self.party, party_account_currency), InvalidAccountCurrency)
|
.format(self.party_type, self.party, party_account_currency), InvalidAccountCurrency)
|
||||||
|
|
||||||
|
validate_party_gle_currency(self.party_type, self.party, self.company)
|
||||||
|
|
||||||
def validate_balance_type(account, adv_adj=False):
|
def validate_balance_type(account, adv_adj=False):
|
||||||
if not adv_adj and account:
|
if not adv_adj and account:
|
||||||
balance_must_be = frappe.db.get_value("Account", account, "balance_must_be")
|
balance_must_be = frappe.db.get_value("Account", account, "balance_must_be")
|
||||||
|
@ -5,6 +5,7 @@ from __future__ import unicode_literals
|
|||||||
import unittest, frappe
|
import unittest, frappe
|
||||||
from frappe.utils import flt
|
from frappe.utils import flt
|
||||||
from erpnext.accounts.utils import get_actual_expense, BudgetError, get_fiscal_year
|
from erpnext.accounts.utils import get_actual_expense, BudgetError, get_fiscal_year
|
||||||
|
from erpnext.exceptions import InvalidAccountCurrency
|
||||||
|
|
||||||
|
|
||||||
class TestJournalEntry(unittest.TestCase):
|
class TestJournalEntry(unittest.TestCase):
|
||||||
@ -202,8 +203,6 @@ class TestJournalEntry(unittest.TestCase):
|
|||||||
for i, gle in enumerate(gl_entries):
|
for i, gle in enumerate(gl_entries):
|
||||||
self.assertEquals(expected_values[gle.account][field], gle[field])
|
self.assertEquals(expected_values[gle.account][field], gle[field])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# cancel
|
# cancel
|
||||||
jv.cancel()
|
jv.cancel()
|
||||||
|
|
||||||
@ -212,6 +211,40 @@ class TestJournalEntry(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertFalse(gle)
|
self.assertFalse(gle)
|
||||||
|
|
||||||
|
def test_disallow_change_in_account_currency_for_a_party(self):
|
||||||
|
# create jv in USD
|
||||||
|
jv = make_journal_entry("_Test Bank USD - _TC",
|
||||||
|
"_Test Receivable USD - _TC", 100, save=False)
|
||||||
|
|
||||||
|
jv.accounts[1].update({
|
||||||
|
"party_type": "Customer",
|
||||||
|
"party": "_Test Customer USD"
|
||||||
|
})
|
||||||
|
|
||||||
|
jv.submit()
|
||||||
|
|
||||||
|
# create jv in USD, but account currency in INR
|
||||||
|
jv = make_journal_entry("_Test Bank - _TC",
|
||||||
|
"_Test Receivable - _TC", 100, save=False)
|
||||||
|
|
||||||
|
jv.accounts[1].update({
|
||||||
|
"party_type": "Customer",
|
||||||
|
"party": "_Test Customer USD"
|
||||||
|
})
|
||||||
|
|
||||||
|
self.assertRaises(InvalidAccountCurrency, jv.submit)
|
||||||
|
|
||||||
|
# back in USD
|
||||||
|
jv = make_journal_entry("_Test Bank USD - _TC",
|
||||||
|
"_Test Receivable USD - _TC", 100, save=False)
|
||||||
|
|
||||||
|
jv.accounts[1].update({
|
||||||
|
"party_type": "Customer",
|
||||||
|
"party": "_Test Customer USD"
|
||||||
|
})
|
||||||
|
|
||||||
|
jv.submit()
|
||||||
|
|
||||||
def make_journal_entry(account1, account2, amount, cost_center=None, exchange_rate=1, save=True, submit=False):
|
def make_journal_entry(account1, account2, amount, cost_center=None, exchange_rate=1, save=True, submit=False):
|
||||||
jv = frappe.new_doc("Journal Entry")
|
jv = frappe.new_doc("Journal Entry")
|
||||||
jv.posting_date = "2013-02-14"
|
jv.posting_date = "2013-02-14"
|
||||||
@ -231,7 +264,7 @@ def make_journal_entry(account1, account2, amount, cost_center=None, exchange_ra
|
|||||||
"cost_center": cost_center,
|
"cost_center": cost_center,
|
||||||
"credit_in_account_currency": amount if amount > 0 else 0,
|
"credit_in_account_currency": amount if amount > 0 else 0,
|
||||||
"debit_in_account_currency": abs(amount) if amount < 0 else 0,
|
"debit_in_account_currency": abs(amount) if amount < 0 else 0,
|
||||||
exchange_rate: exchange_rate
|
"exchange_rate": exchange_rate
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
if save or submit:
|
if save or submit:
|
||||||
|
@ -10,7 +10,7 @@ from frappe.utils import cint
|
|||||||
import frappe.defaults
|
import frappe.defaults
|
||||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory, \
|
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory, \
|
||||||
test_records as pr_test_records
|
test_records as pr_test_records
|
||||||
from erpnext.controllers.accounts_controller import InvalidCurrency
|
from erpnext.exceptions import InvalidCurrency
|
||||||
|
|
||||||
test_dependencies = ["Item", "Cost Center"]
|
test_dependencies = ["Item", "Cost Center"]
|
||||||
test_ignore = ["Serial No"]
|
test_ignore = ["Serial No"]
|
||||||
|
@ -7,8 +7,7 @@ import unittest, copy
|
|||||||
from frappe.utils import nowdate, add_days, flt
|
from frappe.utils import nowdate, add_days, flt
|
||||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
|
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
|
||||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
|
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
|
||||||
from erpnext.controllers.accounts_controller import InvalidCurrency
|
from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency
|
||||||
from erpnext.accounts.doctype.gl_entry.gl_entry import InvalidAccountCurrency
|
|
||||||
|
|
||||||
class TestSalesInvoice(unittest.TestCase):
|
class TestSalesInvoice(unittest.TestCase):
|
||||||
def make(self):
|
def make(self):
|
||||||
|
@ -10,6 +10,7 @@ from frappe.defaults import get_user_permissions
|
|||||||
from frappe.utils import add_days, getdate, formatdate, get_first_day, date_diff
|
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.address.address import get_address_display
|
||||||
from erpnext.utilities.doctype.contact.contact import get_contact_details
|
from erpnext.utilities.doctype.contact.contact import get_contact_details
|
||||||
|
from erpnext.exceptions import InvalidAccountCurrency
|
||||||
|
|
||||||
class DuplicatePartyAccountError(frappe.ValidationError): pass
|
class DuplicatePartyAccountError(frappe.ValidationError): pass
|
||||||
|
|
||||||
@ -191,6 +192,25 @@ def get_party_account_currency(party_type, party, company):
|
|||||||
|
|
||||||
return frappe.local_cache("party_account_currency", (party_type, party, company), generator)
|
return frappe.local_cache("party_account_currency", (party_type, party, company), generator)
|
||||||
|
|
||||||
|
def get_party_gle_currency(party_type, party, company):
|
||||||
|
def generator():
|
||||||
|
existing_gle_currency = frappe.db.sql("""select account_currency from `tabGL Entry`
|
||||||
|
where docstatus=1 and company=%(company)s and party_type=%(party_type)s and party=%(party)s
|
||||||
|
limit 1""", { "company": company, "party_type": party_type, "party": party })
|
||||||
|
|
||||||
|
return existing_gle_currency[0][0] if existing_gle_currency else None
|
||||||
|
|
||||||
|
return frappe.local_cache("party_gle_currency", (party_type, party, company), generator)
|
||||||
|
|
||||||
|
def validate_party_gle_currency(party_type, party, company):
|
||||||
|
"""Validate party account currency with existing GL Entry's currency"""
|
||||||
|
party_account_currency = get_party_account_currency(party_type, party, company)
|
||||||
|
existing_gle_currency = get_party_gle_currency(party_type, party, company)
|
||||||
|
|
||||||
|
if existing_gle_currency and party_account_currency != existing_gle_currency:
|
||||||
|
frappe.throw(_("Accounting Entry for {0}: {1} can only be made in currency: {2}")
|
||||||
|
.format(party_type, party, existing_gle_currency), InvalidAccountCurrency)
|
||||||
|
|
||||||
def validate_party_accounts(doc):
|
def validate_party_accounts(doc):
|
||||||
companies = []
|
companies = []
|
||||||
|
|
||||||
|
@ -10,13 +10,11 @@ from erpnext.accounts.utils import get_fiscal_year, validate_fiscal_year, get_ac
|
|||||||
from erpnext.utilities.transaction_base import TransactionBase
|
from erpnext.utilities.transaction_base import TransactionBase
|
||||||
from erpnext.controllers.recurring_document import convert_to_recurring, validate_recurring_document
|
from erpnext.controllers.recurring_document import convert_to_recurring, validate_recurring_document
|
||||||
from erpnext.controllers.sales_and_purchase_return import validate_return
|
from erpnext.controllers.sales_and_purchase_return import validate_return
|
||||||
from erpnext.accounts.party import get_party_account_currency
|
from erpnext.accounts.party import get_party_account_currency, validate_party_gle_currency
|
||||||
|
from erpnext.exceptions import CustomerFrozen, InvalidCurrency
|
||||||
|
|
||||||
force_item_fields = ("item_group", "barcode", "brand", "stock_uom")
|
force_item_fields = ("item_group", "barcode", "brand", "stock_uom")
|
||||||
|
|
||||||
class CustomerFrozen(frappe.ValidationError): pass
|
|
||||||
class InvalidCurrency(frappe.ValidationError): pass
|
|
||||||
|
|
||||||
class AccountsController(TransactionBase):
|
class AccountsController(TransactionBase):
|
||||||
def __init__(self, arg1, arg2=None):
|
def __init__(self, arg1, arg2=None):
|
||||||
super(AccountsController, self).__init__(arg1, arg2)
|
super(AccountsController, self).__init__(arg1, arg2)
|
||||||
|
7
erpnext/exceptions.py
Normal file
7
erpnext/exceptions.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
# accounts
|
||||||
|
class CustomerFrozen(frappe.ValidationError): pass
|
||||||
|
class InvalidAccountCurrency(frappe.ValidationError): pass
|
||||||
|
class InvalidCurrency(frappe.ValidationError): pass
|
@ -7,7 +7,7 @@ import frappe
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from frappe.test_runner import make_test_records
|
from frappe.test_runner import make_test_records
|
||||||
from erpnext.controllers.accounts_controller import CustomerFrozen
|
from erpnext.exceptions import CustomerFrozen
|
||||||
|
|
||||||
test_ignore = ["Price List"]
|
test_ignore = ["Price List"]
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@ import frappe.permissions
|
|||||||
import unittest
|
import unittest
|
||||||
from erpnext.selling.doctype.sales_order.sales_order \
|
from erpnext.selling.doctype.sales_order.sales_order \
|
||||||
import make_material_request, make_delivery_note, make_sales_invoice, WarehouseRequired
|
import make_material_request, make_delivery_note, make_sales_invoice, WarehouseRequired
|
||||||
|
from erpnext.accounts.doctype.journal_entry.test_journal_entry \
|
||||||
|
import make_journal_entry
|
||||||
|
|
||||||
from frappe.tests.test_permissions import set_user_permission_doctypes
|
from frappe.tests.test_permissions import set_user_permission_doctypes
|
||||||
|
|
||||||
|
@ -257,3 +257,7 @@ def get_name_with_abbr(name, company):
|
|||||||
parts.append(company_abbr)
|
parts.append(company_abbr)
|
||||||
|
|
||||||
return " - ".join(parts)
|
return " - ".join(parts)
|
||||||
|
|
||||||
|
def get_company_currency(company):
|
||||||
|
return frappe.local_cache("company_currency", company,
|
||||||
|
lambda: frappe.db.get_value("Company", company, "default_currency"))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user