fix: value of depreciable assets not updating after manual depr entry [develop] (#35020)
* fix: value of depreciable assets not updating after manual depr entry
* chore: add asset depr schedule to jv's ignore_doctypes_on_cancel_all
diff --git a/erpnext/accounts/doctype/account/test_account.py b/erpnext/accounts/doctype/account/test_account.py
index f9c9173..3a360c4 100644
--- a/erpnext/accounts/doctype/account/test_account.py
+++ b/erpnext/accounts/doctype/account/test_account.py
@@ -297,7 +297,7 @@
# fixed asset depreciation
["_Test Fixed Asset", "Current Assets", 0, "Fixed Asset", None],
["_Test Accumulated Depreciations", "Current Assets", 0, "Accumulated Depreciation", None],
- ["_Test Depreciations", "Expenses", 0, None, None],
+ ["_Test Depreciations", "Expenses", 0, "Depreciation", None],
["_Test Gain/Loss on Asset Disposal", "Expenses", 0, None, None],
# Receivable / Payable Account
["_Test Receivable", "Current Assets", 0, "Receivable", None],
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.js b/erpnext/accounts/doctype/journal_entry/journal_entry.js
index 089f20b..b31cc32 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.js
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.js
@@ -8,7 +8,7 @@
frappe.ui.form.on("Journal Entry", {
setup: function(frm) {
frm.add_fetch("bank_account", "account", "account");
- frm.ignore_doctypes_on_cancel_all = ['Sales Invoice', 'Purchase Invoice', 'Journal Entry', "Repost Payment Ledger"];
+ frm.ignore_doctypes_on_cancel_all = ['Sales Invoice', 'Purchase Invoice', 'Journal Entry', "Repost Payment Ledger", 'Asset Depreciation Schedule'];
},
refresh: function(frm) {
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 0f8ae4f..34a753f 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -69,6 +69,7 @@
self.validate_empty_accounts_table()
self.set_account_and_party_balance()
self.validate_inter_company_accounts()
+ self.validate_depr_entry_voucher_type()
if self.docstatus == 0:
self.apply_tax_withholding()
@@ -130,6 +131,13 @@
if self.total_credit != doc.total_debit or self.total_debit != doc.total_credit:
frappe.throw(_("Total Credit/ Debit Amount should be same as linked Journal Entry"))
+ def validate_depr_entry_voucher_type(self):
+ if (
+ any(d.account_type == "Depreciation" for d in self.get("accounts"))
+ and self.voucher_type != "Depreciation Entry"
+ ):
+ frappe.throw(_("Journal Entry type should be set as Depreciation Entry for asset depreciation"))
+
def validate_stock_accounts(self):
stock_accounts = get_stock_accounts(self.company, self.doctype, self.name)
for account in stock_accounts:
@@ -233,25 +241,30 @@
self.remove(d)
def update_asset_value(self):
- if self.voucher_type != "Depreciation Entry":
+ if self.flags.planned_depr_entry or self.voucher_type != "Depreciation Entry":
return
- processed_assets = []
-
for d in self.get("accounts"):
if (
- d.reference_type == "Asset" and d.reference_name and d.reference_name not in processed_assets
+ d.reference_type == "Asset"
+ and d.reference_name
+ and d.account_type == "Depreciation"
+ and d.debit
):
- processed_assets.append(d.reference_name)
-
asset = frappe.get_doc("Asset", d.reference_name)
if asset.calculate_depreciation:
- continue
-
- depr_value = d.debit or d.credit
-
- asset.db_set("value_after_depreciation", asset.value_after_depreciation - depr_value)
+ fb_idx = 1
+ if self.finance_book:
+ for fb_row in asset.get("finance_books"):
+ if fb_row.finance_book == self.finance_book:
+ fb_idx = fb_row.idx
+ break
+ fb_row = asset.get("finance_books")[fb_idx - 1]
+ fb_row.value_after_depreciation -= d.debit
+ fb_row.db_update()
+ else:
+ asset.db_set("value_after_depreciation", asset.value_after_depreciation - d.debit)
asset.set_status()
@@ -316,42 +329,47 @@
if self.voucher_type != "Depreciation Entry":
return
- processed_assets = []
-
for d in self.get("accounts"):
if (
- d.reference_type == "Asset" and d.reference_name and d.reference_name not in processed_assets
+ d.reference_type == "Asset"
+ and d.reference_name
+ and d.account_type == "Depreciation"
+ and d.debit
):
- processed_assets.append(d.reference_name)
-
asset = frappe.get_doc("Asset", d.reference_name)
if asset.calculate_depreciation:
je_found = False
- for row in asset.get("finance_books"):
+ for fb_row in asset.get("finance_books"):
if je_found:
break
- depr_schedule = get_depr_schedule(asset.name, "Active", row.finance_book)
+ depr_schedule = get_depr_schedule(asset.name, "Active", fb_row.finance_book)
for s in depr_schedule or []:
if s.journal_entry == self.name:
s.db_set("journal_entry", None)
- row.value_after_depreciation += s.depreciation_amount
- row.db_update()
-
- asset.set_status()
+ fb_row.value_after_depreciation += d.debit
+ fb_row.db_update()
je_found = True
break
+ if not je_found:
+ fb_idx = 1
+ if self.finance_book:
+ for fb_row in asset.get("finance_books"):
+ if fb_row.finance_book == self.finance_book:
+ fb_idx = fb_row.idx
+ break
+
+ fb_row = asset.get("finance_books")[fb_idx - 1]
+ fb_row.value_after_depreciation += d.debit
+ fb_row.db_update()
else:
- depr_value = d.debit or d.credit
-
- asset.db_set("value_after_depreciation", asset.value_after_depreciation + depr_value)
-
- asset.set_status()
+ asset.db_set("value_after_depreciation", asset.value_after_depreciation + d.debit)
+ asset.set_status()
def unlink_inter_company_jv(self):
if (
diff --git a/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py b/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py
index 5827697..d67eee3 100644
--- a/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py
+++ b/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py
@@ -114,28 +114,6 @@
sum(results.depreciation_eliminated_during_the_period) as depreciation_eliminated_during_the_period,
sum(results.depreciation_amount_during_the_period) as depreciation_amount_during_the_period
from (SELECT a.asset_category,
- ifnull(sum(case when ds.schedule_date < %(from_date)s and (ifnull(a.disposal_date, 0) = 0 or a.disposal_date >= %(from_date)s) then
- ds.depreciation_amount
- else
- 0
- end), 0) as accumulated_depreciation_as_on_from_date,
- ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 and a.disposal_date >= %(from_date)s
- and a.disposal_date <= %(to_date)s and ds.schedule_date <= a.disposal_date then
- ds.depreciation_amount
- else
- 0
- end), 0) as depreciation_eliminated_during_the_period,
- ifnull(sum(case when ds.schedule_date >= %(from_date)s and ds.schedule_date <= %(to_date)s
- and (ifnull(a.disposal_date, 0) = 0 or ds.schedule_date <= a.disposal_date) then
- ds.depreciation_amount
- else
- 0
- end), 0) as depreciation_amount_during_the_period
- from `tabAsset` a, `tabAsset Depreciation Schedule` ads, `tabDepreciation Schedule` ds
- where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s and ads.asset = a.name and ads.docstatus=1 and ads.name = ds.parent and ifnull(ds.journal_entry, '') != ''
- group by a.asset_category
- union
- SELECT a.asset_category,
ifnull(sum(case when gle.posting_date < %(from_date)s and (ifnull(a.disposal_date, 0) = 0 or a.disposal_date >= %(from_date)s) then
gle.debit
else
@@ -160,7 +138,7 @@
aca.parent = a.asset_category and aca.company_name = %(company)s
join `tabCompany` company on
company.name = %(company)s
- where a.docstatus=1 and a.company=%(company)s and a.calculate_depreciation=0 and a.purchase_date <= %(to_date)s and gle.debit != 0 and gle.is_cancelled = 0 and gle.account = ifnull(aca.depreciation_expense_account, company.depreciation_expense_account)
+ where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s and gle.debit != 0 and gle.is_cancelled = 0 and gle.account = ifnull(aca.depreciation_expense_account, company.depreciation_expense_account)
group by a.asset_category
union
SELECT a.asset_category,
diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py
index 028e3d6..f23ae2f 100644
--- a/erpnext/assets/doctype/asset/depreciation.py
+++ b/erpnext/assets/doctype/asset/depreciation.py
@@ -157,6 +157,7 @@
je.append("accounts", debit_entry)
je.flags.ignore_permissions = True
+ je.flags.planned_depr_entry = True
je.save()
if not je.meta.get_workflow():
je.submit()
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index cde0280..203612f 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -1511,7 +1511,7 @@
)
self.assertEqual(asset.status, "Submitted")
- self.assertEqual(asset.get("value_after_depreciation"), 100000)
+ self.assertEqual(asset.get_value_after_depreciation(), 100000)
jv = make_journal_entry(
"_Test Depreciations - _TC", "_Test Accumulated Depreciations - _TC", 100, save=False
@@ -1524,12 +1524,68 @@
jv.submit()
asset.reload()
- self.assertEqual(asset.get("value_after_depreciation"), 99900)
+ self.assertEqual(asset.get_value_after_depreciation(), 99900)
jv.cancel()
asset.reload()
- self.assertEqual(asset.get("value_after_depreciation"), 100000)
+ self.assertEqual(asset.get_value_after_depreciation(), 100000)
+
+ def test_manual_depreciation_for_depreciable_asset(self):
+ asset = create_asset(
+ item_code="Macbook Pro",
+ calculate_depreciation=1,
+ purchase_date="2020-01-30",
+ available_for_use_date="2020-01-30",
+ expected_value_after_useful_life=10000,
+ total_number_of_depreciations=10,
+ frequency_of_depreciation=1,
+ submit=1,
+ )
+
+ self.assertEqual(asset.status, "Submitted")
+ self.assertEqual(asset.get_value_after_depreciation(), 100000)
+
+ jv = make_journal_entry(
+ "_Test Depreciations - _TC", "_Test Accumulated Depreciations - _TC", 100, save=False
+ )
+ for d in jv.accounts:
+ d.reference_type = "Asset"
+ d.reference_name = asset.name
+ jv.voucher_type = "Depreciation Entry"
+ jv.insert()
+ jv.submit()
+
+ asset.reload()
+ self.assertEqual(asset.get_value_after_depreciation(), 99900)
+
+ jv.cancel()
+
+ asset.reload()
+ self.assertEqual(asset.get_value_after_depreciation(), 100000)
+
+ def test_manual_depreciation_with_incorrect_jv_voucher_type(self):
+ asset = create_asset(
+ item_code="Macbook Pro",
+ calculate_depreciation=1,
+ purchase_date="2020-01-30",
+ available_for_use_date="2020-01-30",
+ expected_value_after_useful_life=10000,
+ total_number_of_depreciations=10,
+ frequency_of_depreciation=1,
+ submit=1,
+ )
+
+ jv = make_journal_entry(
+ "_Test Depreciations - _TC", "_Test Accumulated Depreciations - _TC", 100, save=False
+ )
+ for d in jv.accounts:
+ d.reference_type = "Asset"
+ d.reference_name = asset.name
+ d.account_type = "Depreciation"
+ jv.voucher_type = "Journal Entry"
+
+ self.assertRaises(frappe.ValidationError, jv.insert)
def create_asset_data():