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
This commit is contained in:
parent
04902e1b60
commit
ca388ed9cd
@ -297,7 +297,7 @@ def _make_test_records(verbose=None):
|
|||||||
# fixed asset depreciation
|
# fixed asset depreciation
|
||||||
["_Test Fixed Asset", "Current Assets", 0, "Fixed Asset", None],
|
["_Test Fixed Asset", "Current Assets", 0, "Fixed Asset", None],
|
||||||
["_Test Accumulated Depreciations", "Current Assets", 0, "Accumulated Depreciation", 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],
|
["_Test Gain/Loss on Asset Disposal", "Expenses", 0, None, None],
|
||||||
# Receivable / Payable Account
|
# Receivable / Payable Account
|
||||||
["_Test Receivable", "Current Assets", 0, "Receivable", None],
|
["_Test Receivable", "Current Assets", 0, "Receivable", None],
|
||||||
|
|||||||
@ -8,7 +8,7 @@ frappe.provide("erpnext.journal_entry");
|
|||||||
frappe.ui.form.on("Journal Entry", {
|
frappe.ui.form.on("Journal Entry", {
|
||||||
setup: function(frm) {
|
setup: function(frm) {
|
||||||
frm.add_fetch("bank_account", "account", "account");
|
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) {
|
refresh: function(frm) {
|
||||||
|
|||||||
@ -69,6 +69,7 @@ class JournalEntry(AccountsController):
|
|||||||
self.validate_empty_accounts_table()
|
self.validate_empty_accounts_table()
|
||||||
self.set_account_and_party_balance()
|
self.set_account_and_party_balance()
|
||||||
self.validate_inter_company_accounts()
|
self.validate_inter_company_accounts()
|
||||||
|
self.validate_depr_entry_voucher_type()
|
||||||
|
|
||||||
if self.docstatus == 0:
|
if self.docstatus == 0:
|
||||||
self.apply_tax_withholding()
|
self.apply_tax_withholding()
|
||||||
@ -130,6 +131,13 @@ class JournalEntry(AccountsController):
|
|||||||
if self.total_credit != doc.total_debit or self.total_debit != doc.total_credit:
|
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"))
|
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):
|
def validate_stock_accounts(self):
|
||||||
stock_accounts = get_stock_accounts(self.company, self.doctype, self.name)
|
stock_accounts = get_stock_accounts(self.company, self.doctype, self.name)
|
||||||
for account in stock_accounts:
|
for account in stock_accounts:
|
||||||
@ -233,25 +241,30 @@ class JournalEntry(AccountsController):
|
|||||||
self.remove(d)
|
self.remove(d)
|
||||||
|
|
||||||
def update_asset_value(self):
|
def update_asset_value(self):
|
||||||
if self.voucher_type != "Depreciation Entry":
|
if self.flags.planned_depr_entry or self.voucher_type != "Depreciation Entry":
|
||||||
return
|
return
|
||||||
|
|
||||||
processed_assets = []
|
|
||||||
|
|
||||||
for d in self.get("accounts"):
|
for d in self.get("accounts"):
|
||||||
if (
|
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)
|
asset = frappe.get_doc("Asset", d.reference_name)
|
||||||
|
|
||||||
if asset.calculate_depreciation:
|
if asset.calculate_depreciation:
|
||||||
continue
|
fb_idx = 1
|
||||||
|
if self.finance_book:
|
||||||
depr_value = d.debit or d.credit
|
for fb_row in asset.get("finance_books"):
|
||||||
|
if fb_row.finance_book == self.finance_book:
|
||||||
asset.db_set("value_after_depreciation", asset.value_after_depreciation - depr_value)
|
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()
|
asset.set_status()
|
||||||
|
|
||||||
@ -316,41 +329,46 @@ class JournalEntry(AccountsController):
|
|||||||
if self.voucher_type != "Depreciation Entry":
|
if self.voucher_type != "Depreciation Entry":
|
||||||
return
|
return
|
||||||
|
|
||||||
processed_assets = []
|
|
||||||
|
|
||||||
for d in self.get("accounts"):
|
for d in self.get("accounts"):
|
||||||
if (
|
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)
|
asset = frappe.get_doc("Asset", d.reference_name)
|
||||||
|
|
||||||
if asset.calculate_depreciation:
|
if asset.calculate_depreciation:
|
||||||
je_found = False
|
je_found = False
|
||||||
|
|
||||||
for row in asset.get("finance_books"):
|
for fb_row in asset.get("finance_books"):
|
||||||
if je_found:
|
if je_found:
|
||||||
break
|
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 []:
|
for s in depr_schedule or []:
|
||||||
if s.journal_entry == self.name:
|
if s.journal_entry == self.name:
|
||||||
s.db_set("journal_entry", None)
|
s.db_set("journal_entry", None)
|
||||||
|
|
||||||
row.value_after_depreciation += s.depreciation_amount
|
fb_row.value_after_depreciation += d.debit
|
||||||
row.db_update()
|
fb_row.db_update()
|
||||||
|
|
||||||
asset.set_status()
|
|
||||||
|
|
||||||
je_found = True
|
je_found = True
|
||||||
break
|
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:
|
else:
|
||||||
depr_value = d.debit or d.credit
|
asset.db_set("value_after_depreciation", asset.value_after_depreciation + d.debit)
|
||||||
|
|
||||||
asset.db_set("value_after_depreciation", asset.value_after_depreciation + depr_value)
|
|
||||||
|
|
||||||
asset.set_status()
|
asset.set_status()
|
||||||
|
|
||||||
def unlink_inter_company_jv(self):
|
def unlink_inter_company_jv(self):
|
||||||
|
|||||||
@ -114,28 +114,6 @@ def get_assets(filters):
|
|||||||
sum(results.depreciation_eliminated_during_the_period) as depreciation_eliminated_during_the_period,
|
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
|
sum(results.depreciation_amount_during_the_period) as depreciation_amount_during_the_period
|
||||||
from (SELECT a.asset_category,
|
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
|
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
|
gle.debit
|
||||||
else
|
else
|
||||||
@ -160,7 +138,7 @@ def get_assets(filters):
|
|||||||
aca.parent = a.asset_category and aca.company_name = %(company)s
|
aca.parent = a.asset_category and aca.company_name = %(company)s
|
||||||
join `tabCompany` company on
|
join `tabCompany` company on
|
||||||
company.name = %(company)s
|
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
|
group by a.asset_category
|
||||||
union
|
union
|
||||||
SELECT a.asset_category,
|
SELECT a.asset_category,
|
||||||
|
|||||||
@ -157,6 +157,7 @@ def make_depreciation_entry(asset_depr_schedule_name, date=None):
|
|||||||
je.append("accounts", debit_entry)
|
je.append("accounts", debit_entry)
|
||||||
|
|
||||||
je.flags.ignore_permissions = True
|
je.flags.ignore_permissions = True
|
||||||
|
je.flags.planned_depr_entry = True
|
||||||
je.save()
|
je.save()
|
||||||
if not je.meta.get_workflow():
|
if not je.meta.get_workflow():
|
||||||
je.submit()
|
je.submit()
|
||||||
|
|||||||
@ -1511,7 +1511,7 @@ class TestDepreciationBasics(AssetSetup):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(asset.status, "Submitted")
|
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(
|
jv = make_journal_entry(
|
||||||
"_Test Depreciations - _TC", "_Test Accumulated Depreciations - _TC", 100, save=False
|
"_Test Depreciations - _TC", "_Test Accumulated Depreciations - _TC", 100, save=False
|
||||||
@ -1524,12 +1524,68 @@ class TestDepreciationBasics(AssetSetup):
|
|||||||
jv.submit()
|
jv.submit()
|
||||||
|
|
||||||
asset.reload()
|
asset.reload()
|
||||||
self.assertEqual(asset.get("value_after_depreciation"), 99900)
|
self.assertEqual(asset.get_value_after_depreciation(), 99900)
|
||||||
|
|
||||||
jv.cancel()
|
jv.cancel()
|
||||||
|
|
||||||
asset.reload()
|
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():
|
def create_asset_data():
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user