Skip to content

Commit

Permalink
fix: manual depr entry not updating asset value [v14] (#33788)
Browse files Browse the repository at this point in the history
* fix: get value_after_depreciation functions and manual depr entry not updating asset value

* fix: reflect manual depr entry in chart and fixed asset register

* fix: add linked JEs in asset connections

* chore: add test

* chore: add patch and fix some things

* chore: get depreciation_expense_account properly

* chore: fix patch

* chore: fix patch

* chore: fix patch again

* chore: rename var in patch

* fix: filter assets with finance books properly

* chore: refactor get_value_after_depreciation

* chore: use dict format for filters in assets_linked_to_fb

* chore: refactor update_asset_value

* chore: sort manual depr entries
  • Loading branch information
anandbaburajan authored Jan 31, 2023
1 parent 868c8d6 commit f487eae
Show file tree
Hide file tree
Showing 14 changed files with 300 additions and 102 deletions.
67 changes: 58 additions & 9 deletions erpnext/accounts/doctype/journal_entry/journal_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ def on_submit(self):
self.check_credit_limit()
self.make_gl_entries()
self.update_advance_paid()
self.update_asset_value()
self.update_inter_company_jv()
self.update_invoice_discounting()

Expand Down Expand Up @@ -225,6 +226,34 @@ def apply_tax_withholding(self):
for d in to_remove:
self.remove(d)

def update_asset_value(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
):
processed_assets.append(d.reference_name)

asset = frappe.db.get_value(
"Asset", d.reference_name, ["calculate_depreciation", "value_after_depreciation"], as_dict=1
)

if asset.calculate_depreciation:
continue

depr_value = d.debit or d.credit

frappe.db.set_value(
"Asset",
d.reference_name,
"value_after_depreciation",
asset.value_after_depreciation - depr_value,
)

def update_inter_company_jv(self):
if (
self.voucher_type == "Inter Company Journal Entry"
Expand Down Expand Up @@ -283,19 +312,39 @@ def unlink_advance_entry_reference(self):
d.db_update()

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:
if (
d.reference_type == "Asset" and d.reference_name and d.reference_name not in processed_assets
):
processed_assets.append(d.reference_name)

asset = frappe.get_doc("Asset", d.reference_name)
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()
if asset.calculate_depreciation:
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()
asset.set_status()
else:
depr_value = d.debit or d.credit

frappe.db.set_value(
"Asset",
d.reference_name,
"value_after_depreciation",
asset.value_after_depreciation + depr_value,
)

def unlink_inter_company_jv(self):
if (
Expand Down
40 changes: 27 additions & 13 deletions erpnext/assets/doctype/asset/asset.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ frappe.ui.form.on('Asset', {
})
},

setup_chart: function(frm) {
setup_chart: async function(frm) {
if(frm.doc.finance_books.length > 1) {
return
}
Expand All @@ -223,20 +223,34 @@ frappe.ui.form.on('Asset', {
flt(frm.doc.opening_accumulated_depreciation));
}

$.each(frm.doc.schedules || [], function(i, v) {
x_intervals.push(v.schedule_date);
var asset_value = flt(frm.doc.gross_purchase_amount) - flt(v.accumulated_depreciation_amount);
if(v.journal_entry) {
last_depreciation_date = v.schedule_date;
asset_values.push(asset_value);
} else {
if (in_list(["Scrapped", "Sold"], frm.doc.status)) {
asset_values.push(null);
if(frm.doc.calculate_depreciation) {
$.each(frm.doc.schedules || [], function(i, v) {
x_intervals.push(v.schedule_date);
var asset_value = flt(frm.doc.gross_purchase_amount) - flt(v.accumulated_depreciation_amount);
if(v.journal_entry) {
last_depreciation_date = v.schedule_date;
asset_values.push(asset_value);
} else {
asset_values.push(asset_value)
if (in_list(["Scrapped", "Sold"], frm.doc.status)) {
asset_values.push(null);
} else {
asset_values.push(asset_value)
}
}
}
});
});
} else {
let depr_entries = (await frappe.call({
method: "get_manual_depreciation_entries",
doc: frm.doc,
})).message;

$.each(depr_entries || [], function(i, v) {
x_intervals.push(v.posting_date);
last_depreciation_date = v.posting_date;
let last_asset_value = asset_values[asset_values.length - 1]
asset_values.push(last_asset_value - v.value);
});
}

if(in_list(["Scrapped", "Sold"], frm.doc.status)) {
x_intervals.push(frm.doc.disposal_date);
Expand Down
8 changes: 7 additions & 1 deletion erpnext/assets/doctype/asset/asset.json
Original file line number Diff line number Diff line change
Expand Up @@ -519,9 +519,15 @@
"group": "Value",
"link_doctype": "Asset Value Adjustment",
"link_fieldname": "asset"
},
{
"group": "Journal Entry",
"link_doctype": "Journal Entry",
"link_fieldname": "reference_name",
"table_fieldname": "accounts"
}
],
"modified": "2023-01-16 23:35:37.423100",
"modified": "2023-01-25 17:45:48.649543",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset",
Expand Down
74 changes: 56 additions & 18 deletions erpnext/assets/doctype/asset/asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ def make_depreciation_schedule(self, date_of_disposal):
def _make_depreciation_schedule(self, finance_book, start, date_of_disposal):
self.validate_asset_finance_books(finance_book)

value_after_depreciation = self._get_value_after_depreciation(finance_book)
value_after_depreciation = self._get_value_after_depreciation_for_making_schedule(finance_book)
finance_book.value_after_depreciation = value_after_depreciation

number_of_pending_depreciations = cint(finance_book.total_number_of_depreciations) - cint(
Expand Down Expand Up @@ -377,8 +377,7 @@ def sort_depreciation_schedule(self):
for idx, s in enumerate(self.schedules, 1):
s.idx = idx

def _get_value_after_depreciation(self, finance_book):
# value_after_depreciation - current Asset value
def _get_value_after_depreciation_for_making_schedule(self, finance_book):
if self.docstatus == 1 and finance_book.value_after_depreciation:
value_after_depreciation = flt(finance_book.value_after_depreciation)
else:
Expand Down Expand Up @@ -567,7 +566,9 @@ def set_accumulated_depreciation(

if int(d.finance_book_id) not in finance_books:
accumulated_depreciation = flt(self.opening_accumulated_depreciation)
value_after_depreciation = flt(self.get_value_after_depreciation(d.finance_book_id))
value_after_depreciation = flt(
self.get("finance_books")[cint(d.finance_book_id) - 1].value_after_depreciation
)
finance_books.append(int(d.finance_book_id))

depreciation_amount = flt(d.depreciation_amount, d.precision("depreciation_amount"))
Expand All @@ -592,9 +593,6 @@ def set_accumulated_depreciation(
accumulated_depreciation, d.precision("accumulated_depreciation_amount")
)

def get_value_after_depreciation(self, idx):
return flt(self.get("finance_books")[cint(idx) - 1].value_after_depreciation)

def validate_expected_value_after_useful_life(self):
for row in self.get("finance_books"):
accumulated_depreciation_after_full_schedule = [
Expand Down Expand Up @@ -649,15 +647,20 @@ def cancel_movement_entries(self):
movement.cancel()

def delete_depreciation_entries(self):
for d in self.get("schedules"):
if d.journal_entry:
frappe.get_doc("Journal Entry", d.journal_entry).cancel()
d.db_set("journal_entry", None)

self.db_set(
"value_after_depreciation",
(flt(self.gross_purchase_amount) - flt(self.opening_accumulated_depreciation)),
)
if self.calculate_depreciation:
for d in self.get("schedules"):
if d.journal_entry:
frappe.get_doc("Journal Entry", d.journal_entry).cancel()
else:
depr_entries = self.get_manual_depreciation_entries()

for depr_entry in depr_entries or []:
frappe.get_doc("Journal Entry", depr_entry.name).cancel()

self.db_set(
"value_after_depreciation",
(flt(self.gross_purchase_amount) - flt(self.opening_accumulated_depreciation)),
)

def set_status(self, status=None):
"""Get and update status"""
Expand Down Expand Up @@ -688,6 +691,17 @@ def get_status(self):
status = "Cancelled"
return status

def get_value_after_depreciation(self, finance_book=None):
if not self.calculate_depreciation:
return self.value_after_depreciation

if not finance_book:
return self.get("finance_books")[0].value_after_depreciation

for row in self.get("finance_books"):
if finance_book == row.finance_book:
return row.value_after_depreciation

def get_default_finance_book_idx(self):
if not self.get("default_finance_book") and self.company:
self.default_finance_book = erpnext.get_default_finance_book(self.company)
Expand Down Expand Up @@ -813,6 +827,24 @@ def make_gl_entries(self):
make_gl_entries(gl_entries)
self.db_set("booked_fixed_asset", 1)

@frappe.whitelist()
def get_manual_depreciation_entries(self):
(_, _, depreciation_expense_account) = get_depreciation_accounts(self)

gle = frappe.qb.DocType("GL Entry")

records = (
frappe.qb.from_(gle)
.select(gle.voucher_no.as_("name"), gle.debit.as_("value"), gle.posting_date)
.where(gle.against_voucher == self.name)
.where(gle.account == depreciation_expense_account)
.where(gle.debit != 0)
.where(gle.is_cancelled == 0)
.orderby(gle.posting_date)
).run(as_dict=True)

return records

@frappe.whitelist()
def get_depreciation_rate(self, args, on_validate=False):
if isinstance(args, str):
Expand Down Expand Up @@ -857,7 +889,6 @@ def update_maintenance_status():


def make_post_gl_entry():

asset_categories = frappe.db.get_all("Asset Category", fields=["name", "enable_cwip_accounting"])

for asset_category in asset_categories:
Expand Down Expand Up @@ -1010,7 +1041,7 @@ def make_journal_entry(asset_name):
depreciation_expense_account,
) = get_depreciation_accounts(asset)

depreciation_cost_center, depreciation_series = frappe.db.get_value(
depreciation_cost_center, depreciation_series = frappe.get_cached_value(
"Company", asset.company, ["depreciation_cost_center", "series_for_depreciation_entry"]
)
depreciation_cost_center = asset.cost_center or depreciation_cost_center
Expand Down Expand Up @@ -1075,6 +1106,13 @@ def is_cwip_accounting_enabled(asset_category):
return cint(frappe.db.get_value("Asset Category", asset_category, "enable_cwip_accounting"))


@frappe.whitelist()
def get_asset_value_after_depreciation(asset_name, finance_book=None):
asset = frappe.get_doc("Asset", asset_name)

return asset.get_value_after_depreciation(finance_book)


def get_total_days(date, frequency):
period_start_date = add_months(date, cint(frequency) * -1)

Expand Down
14 changes: 2 additions & 12 deletions erpnext/assets/doctype/asset/depreciation.py
Original file line number Diff line number Diff line change
Expand Up @@ -494,18 +494,8 @@ def get_asset_details(asset, finance_book=None):
disposal_account, depreciation_cost_center = get_disposal_account_and_cost_center(asset.company)
depreciation_cost_center = asset.cost_center or depreciation_cost_center

idx = 1
if finance_book:
for d in asset.finance_books:
if d.finance_book == finance_book:
idx = d.idx
break

value_after_depreciation = (
asset.finance_books[idx - 1].value_after_depreciation
if asset.calculate_depreciation
else asset.value_after_depreciation
)
value_after_depreciation = asset.get_value_after_depreciation(finance_book)

accumulated_depr_amount = flt(asset.gross_purchase_amount) - flt(value_after_depreciation)

return (
Expand Down
31 changes: 31 additions & 0 deletions erpnext/assets/doctype/asset/test_asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
nowdate,
)

from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
from erpnext.assets.doctype.asset.asset import (
make_sales_invoice,
Expand Down Expand Up @@ -1442,6 +1443,36 @@ def test_depreciation_on_final_day_of_the_month(self):
for i, schedule in enumerate(asset.schedules):
self.assertEqual(getdate(expected_dates[i]), getdate(schedule.schedule_date))

def test_manual_depreciation_for_existing_asset(self):
asset = create_asset(
item_code="Macbook Pro",
is_existing_asset=1,
purchase_date="2020-01-30",
available_for_use_date="2020-01-30",
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 create_asset_data():
if not frappe.db.exists("Asset Category", "Computers"):
Expand Down
Loading

0 comments on commit f487eae

Please sign in to comment.