mirror of
https://github.com/frappe/erpnext.git
synced 2026-03-19 06:52:12 +00:00
Merge pull request #41997 from frappe/mergify/bp/version-15-hotfix/pr-41844
refactor: allow foreign currency advance accounts (backport #41844)
This commit is contained in:
@@ -76,7 +76,6 @@ class PaymentEntry(AccountsController):
|
||||
self.setup_party_account_field()
|
||||
self.set_missing_values()
|
||||
self.set_liability_account()
|
||||
self.validate_advance_account_currency()
|
||||
self.set_missing_ref_details(force=True)
|
||||
self.validate_payment_type()
|
||||
self.validate_party_details()
|
||||
@@ -163,22 +162,6 @@ class PaymentEntry(AccountsController):
|
||||
alert=True,
|
||||
)
|
||||
|
||||
def validate_advance_account_currency(self):
|
||||
if self.book_advance_payments_in_separate_party_account is True:
|
||||
company_currency = frappe.get_cached_value("Company", self.company, "default_currency")
|
||||
if self.payment_type == "Receive" and self.paid_from_account_currency != company_currency:
|
||||
frappe.throw(
|
||||
_("Booking advances in foreign currency account: {0} ({1}) is not yet supported.").format(
|
||||
frappe.bold(self.paid_from), frappe.bold(self.paid_from_account_currency)
|
||||
)
|
||||
)
|
||||
if self.payment_type == "Pay" and self.paid_to_account_currency != company_currency:
|
||||
frappe.throw(
|
||||
_("Booking advances in foreign currency account: {0} ({1}) is not yet supported.").format(
|
||||
frappe.bold(self.paid_to), frappe.bold(self.paid_to_account_currency)
|
||||
)
|
||||
)
|
||||
|
||||
def on_cancel(self):
|
||||
self.ignore_linked_doctypes = (
|
||||
"GL Entry",
|
||||
@@ -1266,7 +1249,7 @@ class PaymentEntry(AccountsController):
|
||||
|
||||
dr_or_cr, account = self.get_dr_and_account_for_advances(invoice)
|
||||
args_dict["account"] = account
|
||||
args_dict[dr_or_cr] = invoice.allocated_amount
|
||||
args_dict[dr_or_cr] = self.calculate_base_allocated_amount_for_reference(invoice)
|
||||
args_dict[dr_or_cr + "_in_account_currency"] = invoice.allocated_amount
|
||||
args_dict.update(
|
||||
{
|
||||
@@ -1285,7 +1268,7 @@ class PaymentEntry(AccountsController):
|
||||
args_dict[dr_or_cr + "_in_account_currency"] = 0
|
||||
dr_or_cr = "debit" if dr_or_cr == "credit" else "credit"
|
||||
args_dict["account"] = self.party_account
|
||||
args_dict[dr_or_cr] = invoice.allocated_amount
|
||||
args_dict[dr_or_cr] = self.calculate_base_allocated_amount_for_reference(invoice)
|
||||
args_dict[dr_or_cr + "_in_account_currency"] = invoice.allocated_amount
|
||||
args_dict.update(
|
||||
{
|
||||
|
||||
@@ -476,7 +476,7 @@ class TestSubscription(FrappeTestCase):
|
||||
start_date="2021-01-01",
|
||||
submit_invoice=0,
|
||||
generate_new_invoices_past_due_date=1,
|
||||
party="_Test Subscription Customer",
|
||||
party="_Test Subscription Customer John Doe",
|
||||
)
|
||||
|
||||
# create invoices for the first two moths
|
||||
@@ -565,10 +565,16 @@ def create_parties():
|
||||
if not frappe.db.exists("Customer", "_Test Subscription Customer"):
|
||||
customer = frappe.new_doc("Customer")
|
||||
customer.customer_name = "_Test Subscription Customer"
|
||||
customer.billing_currency = "USD"
|
||||
customer.default_currency = "USD"
|
||||
customer.append("accounts", {"company": "_Test Company", "account": "_Test Receivable USD - _TC"})
|
||||
customer.insert()
|
||||
|
||||
if not frappe.db.exists("Customer", "_Test Subscription Customer John Doe"):
|
||||
customer = frappe.new_doc("Customer")
|
||||
customer.customer_name = "_Test Subscription Customer John Doe"
|
||||
customer.append("accounts", {"company": "_Test Company", "account": "_Test Receivable - _TC"})
|
||||
customer.insert()
|
||||
|
||||
|
||||
def reset_settings():
|
||||
settings = frappe.get_single("Subscription Settings")
|
||||
|
||||
@@ -138,6 +138,7 @@ class Supplier(TransactionBase):
|
||||
validate_party_accounts(self)
|
||||
self.validate_internal_supplier()
|
||||
self.add_role_for_user()
|
||||
self.validate_currency_for_receivable_payable_and_advance_account()
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_supplier_group_details(self):
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
"doctype": "Supplier",
|
||||
"supplier_name": "_Test Supplier USD",
|
||||
"supplier_group": "_Test Supplier Group",
|
||||
"default_currency": "USD",
|
||||
"accounts": [{
|
||||
"company": "_Test Company",
|
||||
"account": "_Test Payable USD - _TC"
|
||||
|
||||
@@ -1430,10 +1430,13 @@ class AccountsController(TransactionBase):
|
||||
if d.exchange_gain_loss and (
|
||||
(d.reference_doctype, d.reference_name, str(d.idx)) not in booked
|
||||
):
|
||||
if self.payment_type == "Receive":
|
||||
party_account = self.paid_from
|
||||
elif self.payment_type == "Pay":
|
||||
party_account = self.paid_to
|
||||
if self.book_advance_payments_in_separate_party_account:
|
||||
party_account = d.account
|
||||
else:
|
||||
if self.payment_type == "Receive":
|
||||
party_account = self.paid_from
|
||||
elif self.payment_type == "Pay":
|
||||
party_account = self.paid_to
|
||||
|
||||
dr_or_cr = "debit" if d.exchange_gain_loss > 0 else "credit"
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ from frappe.utils import add_days, getdate, nowdate
|
||||
|
||||
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
|
||||
from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_entry
|
||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||
from erpnext.accounts.party import get_party_account
|
||||
from erpnext.stock.doctype.item.test_item import create_item
|
||||
@@ -55,6 +56,7 @@ class TestAccountsController(FrappeTestCase):
|
||||
40 series - Company default Cost center is unset
|
||||
50 series - Journals against Journals
|
||||
60 series - Journals against Payment Entries
|
||||
70 series - Advances in Separate party account. Both Party and Advance account are in Foreign currency.
|
||||
90 series - Dimension inheritence
|
||||
"""
|
||||
|
||||
@@ -114,47 +116,102 @@ class TestAccountsController(FrappeTestCase):
|
||||
self.supplier = make_supplier("_Test MC Supplier USD", "USD")
|
||||
|
||||
def create_account(self):
|
||||
account_name = "Debtors USD"
|
||||
if not frappe.db.get_value(
|
||||
"Account", filters={"account_name": account_name, "company": self.company}
|
||||
):
|
||||
acc = frappe.new_doc("Account")
|
||||
acc.account_name = account_name
|
||||
acc.parent_account = "Accounts Receivable - " + self.company_abbr
|
||||
acc.company = self.company
|
||||
acc.account_currency = "USD"
|
||||
acc.account_type = "Receivable"
|
||||
acc.insert()
|
||||
else:
|
||||
name = frappe.db.get_value(
|
||||
"Account",
|
||||
filters={"account_name": account_name, "company": self.company},
|
||||
fieldname="name",
|
||||
pluck=True,
|
||||
)
|
||||
acc = frappe.get_doc("Account", name)
|
||||
self.debtors_usd = acc.name
|
||||
accounts = [
|
||||
frappe._dict(
|
||||
{
|
||||
"attribute_name": "debtors_usd",
|
||||
"name": "Debtors USD",
|
||||
"account_type": "Receivable",
|
||||
"account_currency": "USD",
|
||||
"parent_account": "Accounts Receivable - " + self.company_abbr,
|
||||
}
|
||||
),
|
||||
frappe._dict(
|
||||
{
|
||||
"attribute_name": "creditors_usd",
|
||||
"name": "Creditors USD",
|
||||
"account_type": "Payable",
|
||||
"account_currency": "USD",
|
||||
"parent_account": "Accounts Payable - " + self.company_abbr,
|
||||
}
|
||||
),
|
||||
# Advance accounts under Asset and Liability header
|
||||
frappe._dict(
|
||||
{
|
||||
"attribute_name": "advance_received_usd",
|
||||
"name": "Advance Received USD",
|
||||
"account_type": "Receivable",
|
||||
"account_currency": "USD",
|
||||
"parent_account": "Current Liabilities - " + self.company_abbr,
|
||||
}
|
||||
),
|
||||
frappe._dict(
|
||||
{
|
||||
"attribute_name": "advance_paid_usd",
|
||||
"name": "Advance Paid USD",
|
||||
"account_type": "Payable",
|
||||
"account_currency": "USD",
|
||||
"parent_account": "Current Assets - " + self.company_abbr,
|
||||
}
|
||||
),
|
||||
]
|
||||
|
||||
account_name = "Creditors USD"
|
||||
if not frappe.db.get_value(
|
||||
"Account", filters={"account_name": account_name, "company": self.company}
|
||||
):
|
||||
acc = frappe.new_doc("Account")
|
||||
acc.account_name = account_name
|
||||
acc.parent_account = "Accounts Payable - " + self.company_abbr
|
||||
acc.company = self.company
|
||||
acc.account_currency = "USD"
|
||||
acc.account_type = "Payable"
|
||||
acc.insert()
|
||||
else:
|
||||
name = frappe.db.get_value(
|
||||
"Account",
|
||||
filters={"account_name": account_name, "company": self.company},
|
||||
fieldname="name",
|
||||
pluck=True,
|
||||
)
|
||||
acc = frappe.get_doc("Account", name)
|
||||
self.creditors_usd = acc.name
|
||||
for x in accounts:
|
||||
if not frappe.db.get_value("Account", filters={"account_name": x.name, "company": self.company}):
|
||||
acc = frappe.new_doc("Account")
|
||||
acc.account_name = x.name
|
||||
acc.parent_account = x.parent_account
|
||||
acc.company = self.company
|
||||
acc.account_currency = x.account_currency
|
||||
acc.account_type = x.account_type
|
||||
acc.insert()
|
||||
else:
|
||||
name = frappe.db.get_value(
|
||||
"Account",
|
||||
filters={"account_name": x.name, "company": self.company},
|
||||
fieldname="name",
|
||||
pluck=True,
|
||||
)
|
||||
acc = frappe.get_doc("Account", name)
|
||||
setattr(self, x.attribute_name, acc.name)
|
||||
|
||||
def setup_advance_accounts_in_party_master(self):
|
||||
company = frappe.get_doc("Company", self.company)
|
||||
company.book_advance_payments_in_separate_party_account = 1
|
||||
company.save()
|
||||
|
||||
customer = frappe.get_doc("Customer", self.customer)
|
||||
customer.append(
|
||||
"accounts",
|
||||
{
|
||||
"company": self.company,
|
||||
"account": self.debtors_usd,
|
||||
"advance_account": self.advance_received_usd,
|
||||
},
|
||||
)
|
||||
customer.save()
|
||||
|
||||
supplier = frappe.get_doc("Supplier", self.supplier)
|
||||
supplier.append(
|
||||
"accounts",
|
||||
{
|
||||
"company": self.company,
|
||||
"account": self.creditors_usd,
|
||||
"advance_account": self.advance_paid_usd,
|
||||
},
|
||||
)
|
||||
supplier.save()
|
||||
|
||||
def remove_advance_accounts_from_party_master(self):
|
||||
company = frappe.get_doc("Company", self.company)
|
||||
company.book_advance_payments_in_separate_party_account = 0
|
||||
company.save()
|
||||
customer = frappe.get_doc("Customer", self.customer)
|
||||
customer.accounts = []
|
||||
customer.save()
|
||||
supplier = frappe.get_doc("Supplier", self.supplier)
|
||||
supplier.accounts = []
|
||||
supplier.save()
|
||||
|
||||
def create_sales_invoice(
|
||||
self,
|
||||
@@ -218,6 +275,48 @@ class TestAccountsController(FrappeTestCase):
|
||||
payment.posting_date = posting_date
|
||||
return payment
|
||||
|
||||
def create_purchase_invoice(
|
||||
self,
|
||||
qty=1,
|
||||
rate=1,
|
||||
conversion_rate=80,
|
||||
posting_date=None,
|
||||
do_not_save=False,
|
||||
do_not_submit=False,
|
||||
):
|
||||
"""
|
||||
Helper function to populate default values in purchase invoice
|
||||
"""
|
||||
if posting_date is None:
|
||||
posting_date = nowdate()
|
||||
|
||||
pinv = make_purchase_invoice(
|
||||
posting_date=posting_date,
|
||||
qty=qty,
|
||||
rate=rate,
|
||||
company=self.company,
|
||||
supplier=self.supplier,
|
||||
item_code=self.item,
|
||||
item_name=self.item,
|
||||
cost_center=self.cost_center,
|
||||
warehouse=self.warehouse,
|
||||
parent_cost_center=self.cost_center,
|
||||
update_stock=0,
|
||||
currency="USD",
|
||||
conversion_rate=conversion_rate,
|
||||
is_pos=0,
|
||||
is_return=0,
|
||||
income_account=self.income_account,
|
||||
expense_account=self.expense_account,
|
||||
do_not_save=True,
|
||||
)
|
||||
pinv.credit_to = self.creditors_usd
|
||||
if not do_not_save:
|
||||
pinv.save()
|
||||
if not do_not_submit:
|
||||
pinv.submit()
|
||||
return pinv
|
||||
|
||||
def clear_old_entries(self):
|
||||
doctype_list = [
|
||||
"GL Entry",
|
||||
@@ -1698,3 +1797,123 @@ class TestAccountsController(FrappeTestCase):
|
||||
# Exchange Gain/Loss Journal should've been cancelled
|
||||
exc_je_for_je1 = self.get_journals_for(je1.doctype, je1.name)
|
||||
self.assertEqual(exc_je_for_je1, [])
|
||||
|
||||
def test_70_advance_payment_against_sales_invoice_in_foreign_currency(self):
|
||||
"""
|
||||
Customer advance booked under Liability
|
||||
"""
|
||||
self.setup_advance_accounts_in_party_master()
|
||||
|
||||
adv = self.create_payment_entry(amount=1, source_exc_rate=83)
|
||||
adv.save() # explicit 'save' is needed to trigger set_liability_account()
|
||||
self.assertEqual(adv.paid_from, self.advance_received_usd)
|
||||
adv.submit()
|
||||
|
||||
si = self.create_sales_invoice(qty=1, conversion_rate=80, rate=1, do_not_submit=True)
|
||||
si.debit_to = self.debtors_usd
|
||||
si.save().submit()
|
||||
self.assert_ledger_outstanding(si.doctype, si.name, 80.0, 1.0)
|
||||
|
||||
pr = self.create_payment_reconciliation()
|
||||
pr.receivable_payable_account = self.debtors_usd
|
||||
pr.default_advance_account = self.advance_received_usd
|
||||
pr.get_unreconciled_entries()
|
||||
self.assertEqual(pr.invoices[0].invoice_number, si.name)
|
||||
self.assertEqual(pr.payments[0].reference_name, adv.name)
|
||||
|
||||
# Allocate and Reconcile
|
||||
invoices = [x.as_dict() for x in pr.invoices]
|
||||
payments = [x.as_dict() for x in pr.payments]
|
||||
pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
|
||||
pr.reconcile()
|
||||
self.assertEqual(len(pr.invoices), 0)
|
||||
self.assertEqual(len(pr.payments), 0)
|
||||
self.assert_ledger_outstanding(si.doctype, si.name, 0.0, 0.0)
|
||||
|
||||
# Exc Gain/Loss journal should've been creatad
|
||||
exc_je_for_si = self.get_journals_for(si.doctype, si.name)
|
||||
exc_je_for_adv = self.get_journals_for(adv.doctype, adv.name)
|
||||
self.assertEqual(len(exc_je_for_si), 1)
|
||||
self.assertEqual(len(exc_je_for_adv), 1)
|
||||
self.assertEqual(exc_je_for_si, exc_je_for_adv)
|
||||
|
||||
adv.reload()
|
||||
adv.cancel()
|
||||
si.reload()
|
||||
self.assert_ledger_outstanding(si.doctype, si.name, 80.0, 1.0)
|
||||
# Exc Gain/Loss journal should've been cancelled
|
||||
exc_je_for_si = self.get_journals_for(si.doctype, si.name)
|
||||
exc_je_for_adv = self.get_journals_for(adv.doctype, adv.name)
|
||||
self.assertEqual(len(exc_je_for_si), 0)
|
||||
self.assertEqual(len(exc_je_for_adv), 0)
|
||||
|
||||
self.remove_advance_accounts_from_party_master()
|
||||
|
||||
def test_71_advance_payment_against_purchase_invoice_in_foreign_currency(self):
|
||||
"""
|
||||
Supplier advance booked under Asset
|
||||
"""
|
||||
self.setup_advance_accounts_in_party_master()
|
||||
|
||||
usd_amount = 1
|
||||
inr_amount = 85
|
||||
exc_rate = 85
|
||||
adv = create_payment_entry(
|
||||
company=self.company,
|
||||
payment_type="Pay",
|
||||
party_type="Supplier",
|
||||
party=self.supplier,
|
||||
paid_from=self.cash,
|
||||
paid_to=self.advance_paid_usd,
|
||||
paid_amount=inr_amount,
|
||||
)
|
||||
adv.source_exchange_rate = 1
|
||||
adv.target_exchange_rate = exc_rate
|
||||
adv.received_amount = usd_amount
|
||||
adv.paid_amount = exc_rate * usd_amount
|
||||
adv.posting_date = nowdate()
|
||||
adv.save()
|
||||
# Make sure that advance account is still set
|
||||
self.assertEqual(adv.paid_to, self.advance_paid_usd)
|
||||
adv.submit()
|
||||
|
||||
pi = self.create_purchase_invoice(qty=1, conversion_rate=83, rate=1)
|
||||
self.assertEqual(pi.credit_to, self.creditors_usd)
|
||||
self.assert_ledger_outstanding(pi.doctype, pi.name, 83.0, 1.0)
|
||||
|
||||
pr = self.create_payment_reconciliation()
|
||||
pr.party_type = "Supplier"
|
||||
pr.party = self.supplier
|
||||
pr.receivable_payable_account = self.creditors_usd
|
||||
pr.default_advance_account = self.advance_paid_usd
|
||||
pr.get_unreconciled_entries()
|
||||
self.assertEqual(pr.invoices[0].invoice_number, pi.name)
|
||||
self.assertEqual(pr.payments[0].reference_name, adv.name)
|
||||
|
||||
# Allocate and Reconcile
|
||||
invoices = [x.as_dict() for x in pr.invoices]
|
||||
payments = [x.as_dict() for x in pr.payments]
|
||||
pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
|
||||
pr.reconcile()
|
||||
self.assertEqual(len(pr.invoices), 0)
|
||||
self.assertEqual(len(pr.payments), 0)
|
||||
self.assert_ledger_outstanding(pi.doctype, pi.name, 0.0, 0.0)
|
||||
|
||||
# Exc Gain/Loss journal should've been creatad
|
||||
exc_je_for_pi = self.get_journals_for(pi.doctype, pi.name)
|
||||
exc_je_for_adv = self.get_journals_for(adv.doctype, adv.name)
|
||||
self.assertEqual(len(exc_je_for_pi), 1)
|
||||
self.assertEqual(len(exc_je_for_adv), 1)
|
||||
self.assertEqual(exc_je_for_pi, exc_je_for_adv)
|
||||
|
||||
adv.reload()
|
||||
adv.cancel()
|
||||
pi.reload()
|
||||
self.assert_ledger_outstanding(pi.doctype, pi.name, 83.0, 1.0)
|
||||
# Exc Gain/Loss journal should've been cancelled
|
||||
exc_je_for_pi = self.get_journals_for(pi.doctype, pi.name)
|
||||
exc_je_for_adv = self.get_journals_for(adv.doctype, adv.name)
|
||||
self.assertEqual(len(exc_je_for_pi), 0)
|
||||
self.assertEqual(len(exc_je_for_adv), 0)
|
||||
|
||||
self.remove_advance_accounts_from_party_master()
|
||||
|
||||
@@ -144,6 +144,7 @@ class Customer(TransactionBase):
|
||||
self.validate_default_bank_account()
|
||||
self.validate_internal_customer()
|
||||
self.add_role_for_user()
|
||||
self.validate_currency_for_receivable_payable_and_advance_account()
|
||||
|
||||
# set loyalty program tier
|
||||
if frappe.db.exists("Customer", self.name):
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
"customer_type": "Individual",
|
||||
"doctype": "Customer",
|
||||
"territory": "_Test Territory",
|
||||
"default_currency": "USD",
|
||||
"accounts": [{
|
||||
"company": "_Test Company",
|
||||
"account": "_Test Receivable USD - _TC"
|
||||
|
||||
@@ -38,6 +38,53 @@ class CustomerGroup(NestedSet):
|
||||
def validate(self):
|
||||
if not self.parent_customer_group:
|
||||
self.parent_customer_group = get_root_of("Customer Group")
|
||||
self.validate_currency_for_receivable_and_advance_account()
|
||||
|
||||
def validate_currency_for_receivable_and_advance_account(self):
|
||||
for x in self.accounts:
|
||||
company_default_currency = frappe.get_cached_value("Company", x.company, "default_currency")
|
||||
receivable_account_currency = None
|
||||
advance_account_currency = None
|
||||
|
||||
if x.account:
|
||||
receivable_account_currency = frappe.get_cached_value(
|
||||
"Account", x.account, "account_currency"
|
||||
)
|
||||
|
||||
if x.advance_account:
|
||||
advance_account_currency = frappe.get_cached_value(
|
||||
"Account", x.advance_account, "account_currency"
|
||||
)
|
||||
|
||||
if receivable_account_currency and receivable_account_currency != company_default_currency:
|
||||
frappe.throw(
|
||||
_("Receivable Account: {0} must be in Company default currency: {1}").format(
|
||||
frappe.bold(x.account),
|
||||
frappe.bold(company_default_currency),
|
||||
)
|
||||
)
|
||||
|
||||
if advance_account_currency and advance_account_currency != company_default_currency:
|
||||
frappe.throw(
|
||||
_("Advance Account: {0} must be in Company default currency: {1}").format(
|
||||
frappe.bold(x.advance_account), frappe.bold(company_default_currency)
|
||||
)
|
||||
)
|
||||
|
||||
if (
|
||||
receivable_account_currency
|
||||
and advance_account_currency
|
||||
and receivable_account_currency != advance_account_currency
|
||||
):
|
||||
frappe.throw(
|
||||
_(
|
||||
"Both Receivable Account: {0} and Advance Account: {1} must be of same currency for company: {2}"
|
||||
).format(
|
||||
frappe.bold(x.account),
|
||||
frappe.bold(x.advance_account),
|
||||
frappe.bold(x.company),
|
||||
)
|
||||
)
|
||||
|
||||
def on_update(self):
|
||||
self.validate_name_with_customer()
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils.nestedset import NestedSet, get_root_of
|
||||
|
||||
|
||||
@@ -32,6 +33,51 @@ class SupplierGroup(NestedSet):
|
||||
def validate(self):
|
||||
if not self.parent_supplier_group:
|
||||
self.parent_supplier_group = get_root_of("Supplier Group")
|
||||
self.validate_currency_for_payable_and_advance_account()
|
||||
|
||||
def validate_currency_for_payable_and_advance_account(self):
|
||||
for x in self.accounts:
|
||||
company_default_currency = frappe.get_cached_value("Company", x.company, "default_currency")
|
||||
payable_account_currency = None
|
||||
advance_account_currency = None
|
||||
|
||||
if x.account:
|
||||
payable_account_currency = frappe.get_cached_value("Account", x.account, "account_currency")
|
||||
|
||||
if x.advance_account:
|
||||
advance_account_currency = frappe.get_cached_value(
|
||||
"Account", x.advance_account, "account_currency"
|
||||
)
|
||||
|
||||
if payable_account_currency and payable_account_currency != company_default_currency:
|
||||
frappe.throw(
|
||||
_("Payable Account: {0} must be in Company default currency: {1}").format(
|
||||
frappe.bold(x.account),
|
||||
frappe.bold(company_default_currency),
|
||||
)
|
||||
)
|
||||
|
||||
if advance_account_currency and advance_account_currency != company_default_currency:
|
||||
frappe.throw(
|
||||
_("Advance Account: {0} must be in Company default currency: {1}").format(
|
||||
frappe.bold(x.advance_account), frappe.bold(company_default_currency)
|
||||
)
|
||||
)
|
||||
|
||||
if (
|
||||
payable_account_currency
|
||||
and advance_account_currency
|
||||
and payable_account_currency != advance_account_currency
|
||||
):
|
||||
frappe.throw(
|
||||
_(
|
||||
"Both Payable Account: {0} and Advance Account: {1} must be of same currency for company: {2}"
|
||||
).format(
|
||||
frappe.bold(x.account),
|
||||
frappe.bold(x.advance_account),
|
||||
frappe.bold(x.company),
|
||||
)
|
||||
)
|
||||
|
||||
def on_update(self):
|
||||
NestedSet.on_update(self)
|
||||
|
||||
@@ -168,6 +168,69 @@ class TransactionBase(StatusUpdater):
|
||||
if len(child_table_values) > 1:
|
||||
self.set(default_field, None)
|
||||
|
||||
def validate_currency_for_receivable_payable_and_advance_account(self):
|
||||
if self.doctype in ["Customer", "Supplier"]:
|
||||
account_type = "Receivable" if self.doctype == "Customer" else "Payable"
|
||||
for x in self.accounts:
|
||||
company_default_currency = frappe.get_cached_value("Company", x.company, "default_currency")
|
||||
receivable_payable_account_currency = None
|
||||
advance_account_currency = None
|
||||
|
||||
if x.account:
|
||||
receivable_payable_account_currency = frappe.get_cached_value(
|
||||
"Account", x.account, "account_currency"
|
||||
)
|
||||
|
||||
if x.advance_account:
|
||||
advance_account_currency = frappe.get_cached_value(
|
||||
"Account", x.advance_account, "account_currency"
|
||||
)
|
||||
if receivable_payable_account_currency and (
|
||||
receivable_payable_account_currency != self.default_currency
|
||||
and receivable_payable_account_currency != company_default_currency
|
||||
):
|
||||
frappe.throw(
|
||||
_(
|
||||
"{0} Account: {1} ({2}) must be in either customer billing currency: {3} or Company default currency: {4}"
|
||||
).format(
|
||||
account_type,
|
||||
frappe.bold(x.account),
|
||||
frappe.bold(receivable_payable_account_currency),
|
||||
frappe.bold(self.default_currency),
|
||||
frappe.bold(company_default_currency),
|
||||
)
|
||||
)
|
||||
|
||||
if advance_account_currency and (
|
||||
advance_account_currency != self.default_currency
|
||||
and advance_account_currency != company_default_currency
|
||||
):
|
||||
frappe.throw(
|
||||
_(
|
||||
"Advance Account: {0} must be in either customer billing currency: {1} or Company default currency: {2}"
|
||||
).format(
|
||||
frappe.bold(x.advance_account),
|
||||
frappe.bold(self.default_currency),
|
||||
frappe.bold(company_default_currency),
|
||||
)
|
||||
)
|
||||
|
||||
if (
|
||||
receivable_payable_account_currency
|
||||
and advance_account_currency
|
||||
and receivable_payable_account_currency != advance_account_currency
|
||||
):
|
||||
frappe.throw(
|
||||
_(
|
||||
"Both {0} Account: {1} and Advance Account: {2} must be of same currency for company: {3}"
|
||||
).format(
|
||||
account_type,
|
||||
frappe.bold(x.account),
|
||||
frappe.bold(x.advance_account),
|
||||
frappe.bold(x.company),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def delete_events(ref_type, ref_name):
|
||||
events = (
|
||||
|
||||
Reference in New Issue
Block a user