Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: value of depreciable assets not updating after manual depr entry [v14] #35010

Merged
merged 7 commits into from
Apr 25, 2023
2 changes: 1 addition & 1 deletion erpnext/accounts/doctype/account/test_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ def _make_test_records(verbose=None):
# 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],
Expand Down
2 changes: 1 addition & 1 deletion erpnext/accounts/doctype/journal_entry/journal_entry.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ frappe.provide("erpnext.journal_entry");
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', 'Asset Movement'];
},

refresh: function(frm) {
Expand Down
71 changes: 42 additions & 29 deletions erpnext/accounts/doctype/journal_entry/journal_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ def validate(self):
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()
Expand Down Expand Up @@ -130,6 +131,13 @@ def validate_inter_company_accounts(self):
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:
Expand Down Expand Up @@ -233,25 +241,30 @@ def apply_tax_withholding(self):
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()

Expand Down Expand Up @@ -316,35 +329,35 @@ def unlink_asset_reference(self):
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:
fb_idx = None
for s in asset.get("schedules"):
if s.journal_entry == self.name:
s.db_set("journal_entry", None)

idx = cint(s.finance_book_id) or 1
finance_books = asset.get("finance_books")[idx - 1]
finance_books.value_after_depreciation += s.depreciation_amount
finance_books.db_update()

asset.set_status()

fb_idx = cint(s.finance_book_id) or 1
break
if not fb_idx:
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 (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,28 +114,6 @@ def get_assets(filters):
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, `tabDepreciation Schedule` ds
where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s and a.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
Expand All @@ -160,7 +138,7 @@ def get_assets(filters):
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,
Expand Down
1 change: 1 addition & 0 deletions erpnext/assets/doctype/asset/depreciation.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ def make_depreciation_entry(asset_name, date=None):
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()
Expand Down
62 changes: 59 additions & 3 deletions erpnext/assets/doctype/asset/test_asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -1453,7 +1453,7 @@ def test_manual_depreciation_for_existing_asset(self):
)

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
Expand All @@ -1466,12 +1466,68 @@ def test_manual_depreciation_for_existing_asset(self):
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():
Expand Down
Loading