diff --git a/erpnext/assets/doctype/asset_category/asset_category.py b/erpnext/assets/doctype/asset_category/asset_category.py
index 16e564ad1bd..2edf71099af 100644
--- a/erpnext/assets/doctype/asset_category/asset_category.py
+++ b/erpnext/assets/doctype/asset_category/asset_category.py
@@ -31,7 +31,7 @@ class AssetCategory(Document):
self.validate_finance_books()
self.validate_account_types()
self.validate_account_currency()
- self.valide_cwip_account()
+ self.validate_accounts()
def validate_finance_books(self):
for d in self.finance_books:
@@ -97,11 +97,21 @@ class AssetCategory(Document):
title=_("Invalid Account"),
)
- def valide_cwip_account(self):
+ def validate_accounts(self):
+ self.validate_duplicate_rows()
+ self.validate_cwip_accounts()
+ self.validate_depreciation_accounts()
+
+ def validate_duplicate_rows(self):
+ companies = {row.company_name for row in self.accounts}
+ if len(companies) != len(self.accounts):
+ frappe.throw(_("Cannot set multiple account rows for the same company"))
+
+ def validate_cwip_accounts(self):
if self.enable_cwip_accounting:
missing_cwip_accounts_for_company = []
for d in self.accounts:
- if not d.capital_work_in_progress_account and not frappe.db.get_value(
+ if not d.capital_work_in_progress_account and not frappe.get_cached_value(
"Company", d.company_name, "capital_work_in_progress_account"
):
missing_cwip_accounts_for_company.append(get_link_to_form("Company", d.company_name))
@@ -115,6 +125,40 @@ class AssetCategory(Document):
)
frappe.throw(msg, title=_("Missing Account"))
+ def validate_depreciation_accounts(self):
+ depreciation_account_map = {
+ "accumulated_depreciation_account": "Accumulated Depreciation Account",
+ "depreciation_expense_account": "Depreciation Expense Account",
+ }
+ missing_depreciation_account_msg = []
+ for row in self.accounts:
+ if not has_depreciable_asset(self.name, row.company_name):
+ continue
+ default_accounts = frappe.get_cached_value(
+ "Company",
+ row.company_name,
+ ["accumulated_depreciation_account", "depreciation_expense_account"],
+ as_dict=True,
+ )
+ for fieldname, label in depreciation_account_map.items():
+ if not row.get(fieldname) and not default_accounts.get(fieldname):
+ missing_depreciation_account_msg.append(
+ _("Row #{0}: Missing {1} for company {2}.").format(
+ row.idx,
+ label,
+ get_link_to_form("Company", row.company_name),
+ )
+ )
+ if missing_depreciation_account_msg:
+ msg = _(
+ "Since there are active depreciable assets under this category, the following accounts are required.
"
+ )
+ msg += _(
+ "You can either configure default depreciation accounts in the Company or set the required accounts in the following rows:
"
+ )
+ msg += "
".join(missing_depreciation_account_msg)
+ frappe.throw(msg, title=_("Missing Accounts"))
+
def get_asset_category_account(
fieldname, item=None, asset=None, account=None, asset_category=None, company=None
@@ -138,3 +182,17 @@ def get_asset_category_account(
)
return account
+
+
+def has_depreciable_asset(asset_category, company):
+ return bool(
+ frappe.db.count(
+ "Asset",
+ {
+ "calculate_depreciation": 1,
+ "asset_category": asset_category,
+ "company": company,
+ "status": ["in", ("Submitted", "Partially Depreciated")],
+ },
+ )
+ )