From 06936cf1c024ffa4ed471790b8859aeadc5c5575 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 16 Mar 2022 09:02:04 +0530 Subject: [PATCH] fix: Validate income/expense account in sales and purchase invoice --- .../accounts/doctype/purchase_invoice/purchase_invoice.py | 6 ++++++ erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 7 +++++++ erpnext/controllers/accounts_controller.py | 6 +++--- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 2c3156175f..7654aa44dc 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -32,6 +32,7 @@ from erpnext.accounts.utils import get_account_currency, get_fiscal_year from erpnext.assets.doctype.asset.asset import get_asset_account, is_cwip_accounting_enabled from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account from erpnext.buying.utils import check_on_hold_or_closed_status +from erpnext.controllers.accounts_controller import validate_account_head from erpnext.controllers.buying_controller import BuyingController from erpnext.stock import get_warehouse_account_map from erpnext.stock.doctype.purchase_receipt.purchase_receipt import ( @@ -107,6 +108,7 @@ class PurchaseInvoice(BuyingController): self.validate_uom_is_integer("uom", "qty") self.validate_uom_is_integer("stock_uom", "stock_qty") self.set_expense_account(for_validate=True) + self.validate_expense_account() self.set_against_expense_account() self.validate_write_off_account() self.validate_multiple_billing("Purchase Receipt", "pr_detail", "amount", "items") @@ -311,6 +313,10 @@ class PurchaseInvoice(BuyingController): elif not item.expense_account and for_validate: throw(_("Expense account is mandatory for item {0}").format(item.item_code or item.item_name)) + def validate_expense_account(self): + for item in self.get('items'): + validate_account_head(item.idx, item.expense_account, self.company, 'Expense') + def set_against_expense_account(self): against_accounts = [] for item in self.get("items"): diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 862ac81ff3..5aabc21c14 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -37,6 +37,7 @@ from erpnext.assets.doctype.asset.depreciation import ( get_gl_entries_on_asset_regain, make_depreciation_entry, ) +from erpnext.controllers.accounts_controller import validate_account_head from erpnext.controllers.selling_controller import SellingController from erpnext.projects.doctype.timesheet.timesheet import get_projectwise_timesheet_data from erpnext.setup.doctype.company.company import update_company_current_month_sales @@ -108,6 +109,8 @@ class SalesInvoice(SellingController): self.validate_fixed_asset() self.set_income_account_for_fixed_assets() self.validate_item_cost_centers() + self.validate_income_account() + validate_inter_company_party(self.doctype, self.customer, self.company, self.inter_company_invoice_reference) if cint(self.is_pos): @@ -175,6 +178,10 @@ class SalesInvoice(SellingController): if cost_center_company != self.company: frappe.throw(_("Row #{0}: Cost Center {1} does not belong to company {2}").format(frappe.bold(item.idx), frappe.bold(item.cost_center), frappe.bold(self.company))) + def validate_income_account(self): + for item in self.get('items'): + validate_account_head(item.idx, item.income_account, self.company, 'Income') + def set_tax_withholding(self): tax_withholding_details = get_party_tax_withholding_details(self) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index a94af10cde..34ff45708b 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1566,12 +1566,12 @@ def validate_taxes_and_charges(tax): tax.rate = None -def validate_account_head(idx, account, company): +def validate_account_head(idx, account, company, context=''): account_company = frappe.get_cached_value('Account', account, 'company') if account_company != company: - frappe.throw(_('Row {0}: Account {1} does not belong to Company {2}') - .format(idx, frappe.bold(account), frappe.bold(company)), title=_('Invalid Account')) + frappe.throw(_('Row {0}: {3} Account {1} does not belong to Company {2}') + .format(idx, frappe.bold(account), frappe.bold(company), context), title=_('Invalid Account')) def validate_cost_center(tax, doc):