[fix] Remove party_account_currency from Customer and Supplier, and use currency derived from get_party_account
This commit is contained in:
parent
d3cf4f1264
commit
b20baf894f
@ -3,11 +3,10 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
from frappe.utils import flt, fmt_money, getdate, formatdate
|
||||
from frappe import _
|
||||
|
||||
from frappe.utils import flt, fmt_money, getdate, formatdate
|
||||
from frappe.model.document import Document
|
||||
from erpnext.accounts.party import get_party_account_currency
|
||||
|
||||
class CustomerFrozen(frappe.ValidationError): pass
|
||||
class InvalidCurrency(frappe.ValidationError): pass
|
||||
@ -101,7 +100,7 @@ class GLEntry(Document):
|
||||
if not frozen_accounts_modifier in frappe.get_roles():
|
||||
if frappe.db.get_value(self.party_type, self.party, "is_frozen"):
|
||||
frappe.throw("{0} {1} is frozen".format(self.party_type, self.party), CustomerFrozen)
|
||||
|
||||
|
||||
def validate_currency(self):
|
||||
company_currency = frappe.db.get_value("Company", self.company, "default_currency")
|
||||
account_currency = frappe.db.get_value("Account", self.account, "account_currency") or company_currency
|
||||
@ -111,15 +110,14 @@ class GLEntry(Document):
|
||||
if account_currency != self.account_currency:
|
||||
frappe.throw(_("Accounting Entry for {0} can only be made in currency: {1}")
|
||||
.format(self.account, (account_currency or company_currency)), InvalidAccountCurrency)
|
||||
|
||||
|
||||
|
||||
|
||||
if self.party_type and self.party:
|
||||
party_account_currency = frappe.db.get_value(self.party_type, self.party, "party_account_currency") \
|
||||
or company_currency
|
||||
party_account_currency = get_party_account_currency(self.party_type, self.party, self.company)
|
||||
|
||||
if party_account_currency != self.account_currency:
|
||||
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)
|
||||
|
||||
def validate_balance_type(account, adv_adj=False):
|
||||
if not adv_adj and account:
|
||||
@ -159,7 +157,7 @@ def update_outstanding_amt(account, party_type, party, against_voucher_type, aga
|
||||
where against_voucher_type=%s and against_voucher=%s
|
||||
and account = %s {0}""".format(party_condition),
|
||||
(against_voucher_type, against_voucher, account))[0][0] or 0.0)
|
||||
|
||||
|
||||
if against_voucher_type == 'Purchase Invoice':
|
||||
bal = -bal
|
||||
elif against_voucher_type == "Journal Entry":
|
||||
|
@ -7,6 +7,7 @@ from frappe.utils import cstr, flt, fmt_money, formatdate
|
||||
from frappe import msgprint, _, scrub
|
||||
from erpnext.controllers.accounts_controller import AccountsController
|
||||
from erpnext.accounts.utils import get_balance_on
|
||||
from erpnext.accounts.party import get_party_account_currency
|
||||
from erpnext.setup.utils import get_company_currency
|
||||
|
||||
|
||||
@ -212,7 +213,7 @@ class JournalEntry(AccountsController):
|
||||
if cstr(order.status) == "Stopped":
|
||||
frappe.throw(_("{0} {1} is stopped").format(reference_type, reference_name))
|
||||
|
||||
party_account_currency = frappe.db.get_value(party_type, party, "party_account_currency")
|
||||
party_account_currency = get_party_account_currency(party_type, party, self.company)
|
||||
if party_account_currency == self.company_currency:
|
||||
voucher_total = order.base_grand_total
|
||||
else:
|
||||
@ -609,7 +610,7 @@ def get_payment_entry_from_sales_order(sales_order):
|
||||
jv = get_payment_entry(so)
|
||||
jv.remark = 'Advance payment received against Sales Order {0}.'.format(so.name)
|
||||
|
||||
party_account = get_party_account(so.company, so.customer, "Customer")
|
||||
party_account = get_party_account("Customer", so.customer, so.company)
|
||||
party_account_currency = frappe.db.get_value("Account", party_account, "account_currency")
|
||||
|
||||
exchange_rate = get_exchange_rate(party_account, party_account_currency, so.company)
|
||||
@ -660,7 +661,7 @@ def get_payment_entry_from_purchase_order(purchase_order):
|
||||
jv = get_payment_entry(po)
|
||||
jv.remark = 'Advance payment made against Purchase Order {0}.'.format(po.name)
|
||||
|
||||
party_account = get_party_account(po.company, po.supplier, "Supplier")
|
||||
party_account = get_party_account("Supplier", po.supplier, po.company)
|
||||
party_account_currency = frappe.db.get_value("Account", party_account, "account_currency")
|
||||
|
||||
exchange_rate = get_exchange_rate(party_account, party_account_currency, po.company)
|
||||
@ -779,7 +780,7 @@ def get_party_account_and_balance(company, party_type, party):
|
||||
frappe.msgprint(_("No Permission"), raise_exception=1)
|
||||
|
||||
from erpnext.accounts.party import get_party_account
|
||||
account = get_party_account(company, party, party_type)
|
||||
account = get_party_account(party_type, party, company)
|
||||
|
||||
account_balance = get_balance_on(account=account)
|
||||
party_balance = get_balance_on(party_type=party_type, party=party)
|
||||
|
@ -66,7 +66,7 @@ class PurchaseInvoice(BuyingController):
|
||||
|
||||
def set_missing_values(self, for_validate=False):
|
||||
if not self.credit_to:
|
||||
self.credit_to = get_party_account(self.company, self.supplier, "Supplier")
|
||||
self.credit_to = get_party_account("Supplier", self.supplier, self.company)
|
||||
if not self.due_date:
|
||||
self.due_date = get_due_date(self.posting_date, "Supplier", self.supplier, self.company)
|
||||
|
||||
@ -91,7 +91,7 @@ class PurchaseInvoice(BuyingController):
|
||||
throw(_("Conversion rate cannot be 0 or 1"))
|
||||
|
||||
def validate_credit_to_acc(self):
|
||||
account = frappe.db.get_value("Account", self.credit_to,
|
||||
account = frappe.db.get_value("Account", self.credit_to,
|
||||
["account_type", "report_type", "account_currency"], as_dict=True)
|
||||
|
||||
if account.report_type != "Balance Sheet":
|
||||
@ -99,7 +99,7 @@ class PurchaseInvoice(BuyingController):
|
||||
|
||||
if self.supplier and account.account_type != "Payable":
|
||||
frappe.throw(_("Credit To account must be a Payable account"))
|
||||
|
||||
|
||||
self.party_account_currency = account.account_currency
|
||||
|
||||
def check_for_stopped_status(self):
|
||||
@ -251,7 +251,7 @@ class PurchaseInvoice(BuyingController):
|
||||
expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
|
||||
|
||||
gl_entries = []
|
||||
|
||||
|
||||
# parent's gl entry
|
||||
if self.base_grand_total:
|
||||
gl_entries.append(
|
||||
@ -273,9 +273,9 @@ class PurchaseInvoice(BuyingController):
|
||||
for tax in self.get("taxes"):
|
||||
if tax.category in ("Total", "Valuation and Total") and flt(tax.base_tax_amount_after_discount_amount):
|
||||
account_currency = frappe.db.get_value("Account", tax.account_head, "account_currency")
|
||||
|
||||
|
||||
dr_or_cr = "debit" if tax.add_deduct_tax == "Add" else "credit"
|
||||
|
||||
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": tax.account_head,
|
||||
@ -364,7 +364,7 @@ class PurchaseInvoice(BuyingController):
|
||||
# and the amount that is paid
|
||||
if self.write_off_account and flt(self.write_off_amount):
|
||||
write_off_account_currency = frappe.db.get_value("Account", self.write_off_account, "account_currency")
|
||||
|
||||
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": self.credit_to,
|
||||
|
@ -186,7 +186,7 @@ class SalesInvoice(SellingController):
|
||||
pos = self.set_pos_fields(for_validate)
|
||||
|
||||
if not self.debit_to:
|
||||
self.debit_to = get_party_account(self.company, self.customer, "Customer")
|
||||
self.debit_to = get_party_account("Customer", self.customer, self.company)
|
||||
if not self.due_date and self.customer:
|
||||
self.due_date = get_due_date(self.posting_date, "Customer", self.customer, self.company)
|
||||
|
||||
|
@ -142,7 +142,7 @@ def set_account_and_due_date(party, account, party_type, company, posting_date,
|
||||
}
|
||||
|
||||
if party:
|
||||
account = get_party_account(company, party, party_type)
|
||||
account = get_party_account(party_type, party, company)
|
||||
|
||||
account_fieldname = "debit_to" if party_type=="Customer" else "credit_to"
|
||||
|
||||
@ -153,44 +153,6 @@ def set_account_and_due_date(party, account, party_type, company, posting_date,
|
||||
}
|
||||
return out
|
||||
|
||||
def validate_accounting_currency(party):
|
||||
party_account_currency_in_db = frappe.db.get_value(party.doctype, party.name, "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:
|
||||
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:
|
||||
companies_with_different_currency = []
|
||||
for company, currency in company_currency.items():
|
||||
if currency != party.party_account_currency:
|
||||
companies_with_different_currency.append(company)
|
||||
|
||||
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(companies_with_different_currency)
|
||||
)
|
||||
)
|
||||
|
||||
def get_company_currency():
|
||||
company_currency = frappe._dict()
|
||||
for d in frappe.get_all("Company", fields=["name", "default_currency"]):
|
||||
@ -199,13 +161,13 @@ def get_company_currency():
|
||||
return company_currency
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_party_account(company, party, party_type):
|
||||
def get_party_account(party_type, party, company):
|
||||
"""Returns the account for the given `party`.
|
||||
Will first search in party (Customer / Supplier) record, if not found,
|
||||
will search in group (Customer Group / Supplier Type),
|
||||
finally will return default."""
|
||||
if not company:
|
||||
frappe.throw(_("Please select company first."))
|
||||
frappe.throw(_("Please select a Company"))
|
||||
|
||||
if party:
|
||||
account = frappe.db.get_value("Party Account",
|
||||
@ -223,6 +185,13 @@ def get_party_account(company, party, party_type):
|
||||
|
||||
return account
|
||||
|
||||
def get_party_account_currency(party_type, party, company):
|
||||
def generator():
|
||||
party_account = get_party_account(party_type, party, company)
|
||||
return frappe.db.get_value("Account", party_account, "account_currency")
|
||||
|
||||
return frappe.local_cache("party_account_currency", (party_type, party, company), generator)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_due_date(posting_date, party_type, party, company):
|
||||
"""Set Due Date = Posting Date + Credit Days"""
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,6 @@ from frappe import msgprint, _
|
||||
from frappe.model.naming import make_autoname
|
||||
from erpnext.utilities.address_and_contact import load_address_and_contact
|
||||
from erpnext.utilities.transaction_base import TransactionBase
|
||||
from erpnext.accounts.party import validate_accounting_currency, validate_party_account
|
||||
|
||||
class Supplier(TransactionBase):
|
||||
def get_feed(self):
|
||||
@ -45,9 +44,6 @@ class Supplier(TransactionBase):
|
||||
if frappe.defaults.get_global_default('supp_master_name') == 'Naming Series':
|
||||
if not self.naming_series:
|
||||
msgprint(_("Series is mandatory"), raise_exception=1)
|
||||
|
||||
validate_accounting_currency(self)
|
||||
validate_party_account(self)
|
||||
|
||||
def get_contacts(self,nm):
|
||||
if nm:
|
||||
@ -96,14 +92,14 @@ def get_dashboard_info(supplier):
|
||||
billing_this_year = frappe.db.sql("""
|
||||
select sum(ifnull(credit_in_account_currency, 0)) - sum(ifnull(debit_in_account_currency, 0))
|
||||
from `tabGL Entry`
|
||||
where voucher_type='Purchase Invoice' and party_type = 'Supplier'
|
||||
and party=%s and fiscal_year = %s""",
|
||||
where voucher_type='Purchase Invoice' and party_type = 'Supplier'
|
||||
and party=%s and fiscal_year = %s""",
|
||||
(supplier, frappe.db.get_default("fiscal_year")))
|
||||
|
||||
|
||||
total_unpaid = frappe.db.sql("""select sum(outstanding_amount)
|
||||
from `tabPurchase Invoice`
|
||||
where supplier=%s and docstatus = 1""", supplier)
|
||||
|
||||
|
||||
|
||||
out["billing_this_year"] = billing_this_year[0][0] if billing_this_year else 0
|
||||
out["total_unpaid"] = total_unpaid[0][0] if total_unpaid else 0
|
||||
|
@ -1,22 +1,21 @@
|
||||
[
|
||||
{
|
||||
"doctype": "Supplier",
|
||||
"supplier_name": "_Test Supplier",
|
||||
"doctype": "Supplier",
|
||||
"supplier_name": "_Test Supplier",
|
||||
"supplier_type": "_Test Supplier Type"
|
||||
},
|
||||
{
|
||||
"doctype": "Supplier",
|
||||
"supplier_name": "_Test Supplier 1",
|
||||
"doctype": "Supplier",
|
||||
"supplier_name": "_Test Supplier 1",
|
||||
"supplier_type": "_Test Supplier Type"
|
||||
},
|
||||
{
|
||||
"doctype": "Supplier",
|
||||
"supplier_name": "_Test Supplier USD",
|
||||
"doctype": "Supplier",
|
||||
"supplier_name": "_Test Supplier USD",
|
||||
"supplier_type": "_Test Supplier Type",
|
||||
"party_account_currency": "USD",
|
||||
"accounts": [{
|
||||
"company": "_Test Company",
|
||||
"account": "_Test Payable USD - _TC"
|
||||
}]
|
||||
}
|
||||
]
|
||||
]
|
||||
|
@ -10,6 +10,7 @@ from erpnext.accounts.utils import get_fiscal_year, validate_fiscal_year
|
||||
from erpnext.utilities.transaction_base import TransactionBase
|
||||
from erpnext.controllers.recurring_document import convert_to_recurring, validate_recurring_document
|
||||
from erpnext.controllers.sales_and_purchase_return import validate_return
|
||||
from erpnext.accounts.party import get_party_account_currency
|
||||
|
||||
force_item_fields = ("item_group", "barcode", "brand", "stock_uom")
|
||||
|
||||
@ -427,8 +428,7 @@ class AccountsController(TransactionBase):
|
||||
if self.get("currency"):
|
||||
party_type, party = self.get_party()
|
||||
if party_type and party:
|
||||
party_account_currency = frappe.db.get_value(party_type, party, "party_account_currency") \
|
||||
or self.company_currency
|
||||
party_account_currency = get_party_account_currency(party_type, party, self.company)
|
||||
|
||||
if party_account_currency != self.company_currency and self.currency != party_account_currency:
|
||||
frappe.throw(_("Accounting Entry for {0}: {1} can only be made in currency: {2}")
|
||||
|
@ -7,8 +7,8 @@ from frappe.utils import cstr, cint
|
||||
from frappe import msgprint, _
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
from erpnext.setup.utils import get_exchange_rate
|
||||
|
||||
from erpnext.utilities.transaction_base import TransactionBase
|
||||
from erpnext.accounts.party import get_party_account_currency
|
||||
|
||||
subject_field = "title"
|
||||
sender_field = "contact_email"
|
||||
@ -180,9 +180,10 @@ def get_item_details(item_code):
|
||||
def make_quotation(source_name, target_doc=None):
|
||||
def set_missing_values(source, target):
|
||||
quotation = frappe.get_doc(target)
|
||||
|
||||
|
||||
company_currency = frappe.db.get_value("Company", quotation.company, "default_currency")
|
||||
party_account_currency = frappe.db.get_value("Customer", quotation.customer, "party_account_currency")
|
||||
party_account_currency = get_party_account_currency("Customer", quotation.customer, quotation.company)
|
||||
|
||||
if company_currency == party_account_currency:
|
||||
exchange_rate = 1
|
||||
else:
|
||||
@ -190,7 +191,7 @@ def make_quotation(source_name, target_doc=None):
|
||||
|
||||
quotation.currency = party_account_currency or company_currency
|
||||
quotation.conversion_rate = exchange_rate
|
||||
|
||||
|
||||
quotation.run_method("set_missing_values")
|
||||
quotation.run_method("calculate_taxes_and_totals")
|
||||
|
||||
|
@ -63,56 +63,3 @@ def execute():
|
||||
where
|
||||
company=%s
|
||||
""", (company.default_currency, company.name))
|
||||
|
||||
# Set party account if default currency of party other than company's default currency
|
||||
for dt in ("Customer", "Supplier"):
|
||||
parties = frappe.get_all(dt, filters={"docstatus": 0})
|
||||
for p in parties:
|
||||
party = frappe.get_doc(dt, p.name)
|
||||
party_accounts = []
|
||||
|
||||
for company in company_list:
|
||||
# Get party GL Entries
|
||||
party_gle = frappe.db.get_value("GL Entry", {"party_type": dt, "party": p.name,
|
||||
"company": company.name}, ["account", "account_currency", "name"], as_dict=True)
|
||||
|
||||
# set party account currency
|
||||
if party_gle:
|
||||
party.party_account_currency = party_gle.account_currency
|
||||
elif not party.party_account_currency:
|
||||
party.party_account_currency = company.default_currency
|
||||
|
||||
# Add default receivable /payable account if not exists
|
||||
# and currency is other than company currency
|
||||
if party.party_account_currency and party.party_account_currency != company.default_currency:
|
||||
party_account_exists_for_company = False
|
||||
for d in party.get("accounts"):
|
||||
if d.company == company.name:
|
||||
account_currency = frappe.db.get_value("Account", d.account, "account_currency")
|
||||
if account_currency == party.party_account_currency:
|
||||
party_accounts.append({
|
||||
"company": d.company,
|
||||
"account": d.account
|
||||
})
|
||||
party_account_exists_for_company = True
|
||||
break
|
||||
|
||||
if not party_account_exists_for_company:
|
||||
party_account = None
|
||||
if party_gle:
|
||||
party_account = party_gle.account
|
||||
else:
|
||||
default_receivable_account_currency = frappe.db.get_value("Account",
|
||||
company.default_receivable_account, "account_currency")
|
||||
if default_receivable_account_currency != company.default_currency:
|
||||
party_account = company.default_receivable_account
|
||||
|
||||
if party_account:
|
||||
party_accounts.append({
|
||||
"company": company.name,
|
||||
"account": party_account
|
||||
})
|
||||
|
||||
party.set("accounts", party_accounts)
|
||||
party.flags.ignore_mandatory = True
|
||||
party.save()
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -10,7 +10,6 @@ from frappe.utils import flt
|
||||
|
||||
from erpnext.utilities.transaction_base import TransactionBase
|
||||
from erpnext.utilities.address_and_contact import load_address_and_contact
|
||||
from erpnext.accounts.party import validate_accounting_currency, validate_party_account
|
||||
from frappe.desk.reportview import build_match_conditions
|
||||
|
||||
class Customer(TransactionBase):
|
||||
@ -33,8 +32,6 @@ class Customer(TransactionBase):
|
||||
|
||||
def validate(self):
|
||||
self.flags.is_new_doc = self.is_new()
|
||||
validate_accounting_currency(self)
|
||||
validate_party_account(self)
|
||||
|
||||
def update_lead_status(self):
|
||||
if self.lead_name:
|
||||
|
@ -33,7 +33,6 @@
|
||||
"customer_type": "Individual",
|
||||
"doctype": "Customer",
|
||||
"territory": "_Test Territory",
|
||||
"party_account_currency": "USD",
|
||||
"accounts": [{
|
||||
"company": "_Test Company",
|
||||
"account": "_Test Receivable USD - _TC"
|
||||
|
Loading…
x
Reference in New Issue
Block a user