From f5efb2057c6ba2284f84b3694da4d6e8fba2dcf4 Mon Sep 17 00:00:00 2001 From: Anand Baburajan Date: Tue, 31 Jan 2023 11:00:06 +0530 Subject: [PATCH] fix: manual depr entry not updating asset value [v13] (#33890) fix: asset value for manual depr entries --- .../doctype/journal_entry/journal_entry.py | 67 +++++++++++++--- erpnext/assets/doctype/asset/asset.js | 40 ++++++---- erpnext/assets/doctype/asset/asset.json | 8 +- erpnext/assets/doctype/asset/asset.py | 69 +++++++++++++---- erpnext/assets/doctype/asset/depreciation.py | 14 +--- erpnext/assets/doctype/asset/test_asset.py | 31 ++++++++ .../doctype/asset_repair/test_asset_repair.py | 13 ++-- .../asset_value_adjustment.js | 2 +- .../asset_value_adjustment.py | 16 ++-- .../test_asset_value_adjustment.py | 8 +- .../fixed_asset_register.py | 76 ++++++++++++++----- erpnext/patches.txt | 1 + ...ate_asset_value_for_manual_depr_entries.py | 38 ++++++++++ 13 files changed, 290 insertions(+), 93 deletions(-) create mode 100644 erpnext/patches/v13_0/update_asset_value_for_manual_depr_entries.py diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 73e673ea38b2..a8b8ec6d12e0 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -87,6 +87,7 @@ def on_submit(self): self.check_credit_limit() self.make_gl_entries() self.update_advance_paid() + self.update_asset_value() self.update_expense_claim() self.update_inter_company_jv() self.update_invoice_discounting() @@ -235,6 +236,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" @@ -293,19 +322,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 ( diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index 587cb147b791..a4a9d6c8bc8c 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -201,7 +201,7 @@ frappe.ui.form.on('Asset', { }) }, - setup_chart: function(frm) { + setup_chart: async function(frm) { if(frm.doc.finance_books.length > 1) { return } @@ -219,20 +219,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); diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json index 8132dbd411a6..511afdf08540 100644 --- a/erpnext/assets/doctype/asset/asset.json +++ b/erpnext/assets/doctype/asset/asset.json @@ -504,9 +504,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-17 00:28:37.789345", + "modified": "2023-01-31 01:03:09.467817", "modified_by": "Administrator", "module": "Assets", "name": "Asset", diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index eb8ae92548f2..549241b8f10c 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -556,7 +556,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")) @@ -581,9 +583,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 = [ @@ -638,15 +637,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""" @@ -677,6 +681,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) @@ -686,6 +701,24 @@ def get_default_finance_book_idx(self): if d.finance_book == self.default_finance_book: return cint(d.idx) - 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 + def validate_make_gl_entry(self): purchase_document = self.get_purchase_document() if not purchase_document: @@ -850,7 +883,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: @@ -1003,7 +1035,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 @@ -1070,6 +1102,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) diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index 3f3fcf249c95..e83b9b2080a0 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -469,18 +469,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 ( diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 35b2750ed213..625a45b50989 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -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, update_maintenance_status from erpnext.assets.doctype.asset.depreciation import ( @@ -1410,6 +1411,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"): diff --git a/erpnext/assets/doctype/asset_repair/test_asset_repair.py b/erpnext/assets/doctype/asset_repair/test_asset_repair.py index 4e7cf78090b1..e33e800221c7 100644 --- a/erpnext/assets/doctype/asset_repair/test_asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/test_asset_repair.py @@ -6,6 +6,7 @@ import frappe from frappe.utils import flt, nowdate +from erpnext.assets.doctype.asset.asset import get_asset_value_after_depreciation from erpnext.assets.doctype.asset.test_asset import ( create_asset, create_asset_data, @@ -105,20 +106,20 @@ def test_serialized_item_consumption(self): def test_increase_in_asset_value_due_to_stock_consumption(self): asset = create_asset(calculate_depreciation=1, submit=1) - initial_asset_value = get_asset_value(asset) + initial_asset_value = get_asset_value_after_depreciation(asset.name) asset_repair = create_asset_repair(asset=asset, stock_consumption=1, submit=1) asset.reload() - increase_in_asset_value = get_asset_value(asset) - initial_asset_value + increase_in_asset_value = get_asset_value_after_depreciation(asset.name) - initial_asset_value self.assertEqual(asset_repair.stock_items[0].total_value, increase_in_asset_value) def test_increase_in_asset_value_due_to_repair_cost_capitalisation(self): asset = create_asset(calculate_depreciation=1, submit=1) - initial_asset_value = get_asset_value(asset) + initial_asset_value = get_asset_value_after_depreciation(asset.name) asset_repair = create_asset_repair(asset=asset, capitalize_repair_cost=1, submit=1) asset.reload() - increase_in_asset_value = get_asset_value(asset) - initial_asset_value + increase_in_asset_value = get_asset_value_after_depreciation(asset.name) - initial_asset_value self.assertEqual(asset_repair.repair_cost, increase_in_asset_value) def test_purchase_invoice(self): @@ -143,10 +144,6 @@ def test_increase_in_asset_life(self): ) -def get_asset_value(asset): - return asset.finance_books[0].value_after_depreciation - - def num_of_depreciations(asset): return asset.finance_books[0].total_number_of_depreciations diff --git a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.js b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.js index 36f510b18ee3..ae0e1bda0204 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.js +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.js @@ -47,7 +47,7 @@ frappe.ui.form.on('Asset Value Adjustment', { set_current_asset_value: function(frm) { if (frm.doc.asset) { frm.call({ - method: "erpnext.assets.doctype.asset_value_adjustment.asset_value_adjustment.get_current_asset_value", + method: "erpnext.assets.doctype.asset.asset.get_asset_value_after_depreciation", args: { asset: frm.doc.asset, finance_book: frm.doc.finance_book diff --git a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py index 9953c61a8110..710c6cfacf32 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py @@ -10,7 +10,10 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( get_checks_for_pl_and_bs_accounts, ) -from erpnext.assets.doctype.asset.asset import get_depreciation_amount +from erpnext.assets.doctype.asset.asset import ( + get_asset_value_after_depreciation, + get_depreciation_amount, +) from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts from erpnext.regional.india.utils import ( get_depreciation_amount as get_depreciation_amount_for_india, @@ -45,7 +48,7 @@ def set_difference_amount(self): def set_current_asset_value(self): if not self.current_asset_value and self.asset: - self.current_asset_value = get_current_asset_value(self.asset, self.finance_book) + self.current_asset_value = get_asset_value_after_depreciation(self.asset, self.finance_book) def make_depreciation_entry(self): asset = frappe.get_doc("Asset", self.asset) @@ -148,12 +151,3 @@ def reschedule_depreciations(self, asset_value): for asset_data in asset.schedules: if not asset_data.journal_entry: asset_data.db_update() - - -@frappe.whitelist() -def get_current_asset_value(asset, finance_book=None): - cond = {"parent": asset, "parenttype": "Asset"} - if finance_book: - cond.update({"finance_book": finance_book}) - - return frappe.db.get_value("Asset Finance Book", cond, "value_after_depreciation") diff --git a/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.py b/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.py index ebeb174d1353..c79443b3a252 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.py @@ -6,10 +6,8 @@ import frappe from frappe.utils import add_days, get_last_day, nowdate +from erpnext.assets.doctype.asset.asset import get_asset_value_after_depreciation from erpnext.assets.doctype.asset.test_asset import create_asset_data -from erpnext.assets.doctype.asset_value_adjustment.asset_value_adjustment import ( - get_current_asset_value, -) from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt @@ -43,7 +41,7 @@ def test_current_asset_value(self): ) asset_doc.submit() - current_value = get_current_asset_value(asset_doc.name) + current_value = get_asset_value_after_depreciation(asset_doc.name) self.assertEqual(current_value, 100000.0) def test_asset_depreciation_value_adjustment(self): @@ -73,7 +71,7 @@ def test_asset_depreciation_value_adjustment(self): ) asset_doc.submit() - current_value = get_current_asset_value(asset_doc.name) + current_value = get_asset_value_after_depreciation(asset_doc.name) adj_doc = make_asset_value_adjustment( asset=asset_doc.name, current_asset_value=current_value, new_asset_value=50000.0 ) diff --git a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py index dd5dfca8a224..5bfd4840d73d 100644 --- a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py +++ b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py @@ -4,13 +4,16 @@ import frappe from frappe import _ -from frappe.utils import cstr, flt, formatdate, getdate +from frappe.query_builder.functions import Sum +from frappe.utils import cstr, formatdate, getdate from erpnext.accounts.report.financial_statements import ( get_fiscal_year_data, get_period_list, validate_fiscal_year, ) +from erpnext.assets.doctype.asset.asset import get_asset_value_after_depreciation +from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts def execute(filters=None): @@ -85,6 +88,7 @@ def get_data(filters): "asset_name", "status", "department", + "company", "cost_center", "calculate_depreciation", "purchase_receipt", @@ -98,8 +102,25 @@ def get_data(filters): ] assets_record = frappe.db.get_all("Asset", filters=conditions, fields=fields) + finance_book_filter = ("is", "not set") + if filters.finance_book: + finance_book_filter = ("=", filters.finance_book) + + assets_linked_to_fb = frappe.db.get_all( + doctype="Asset Finance Book", + filters={"finance_book": finance_book_filter}, + pluck="parent", + ) + for asset in assets_record: - asset_value = get_asset_value(asset, filters.finance_book) + if filters.finance_book: + if asset.asset_id not in assets_linked_to_fb: + continue + else: + if asset.calculate_depreciation and asset.asset_id not in assets_linked_to_fb: + continue + + asset_value = get_asset_value_after_depreciation(asset.asset_id, filters.finance_book) row = { "asset_id": asset.asset_id, "asset_name": asset.asset_name, @@ -110,7 +131,7 @@ def get_data(filters): or pi_supplier_map.get(asset.purchase_invoice), "gross_purchase_amount": asset.gross_purchase_amount, "opening_accumulated_depreciation": asset.opening_accumulated_depreciation, - "depreciated_amount": depreciation_amount_map.get(asset.asset_id) or 0.0, + "depreciated_amount": get_depreciation_amount_of_asset(asset, depreciation_amount_map, filters), "available_for_use_date": asset.available_for_use_date, "location": asset.location, "asset_category": asset.asset_category, @@ -122,21 +143,6 @@ def get_data(filters): return data -def get_asset_value(asset, finance_book=None): - if not asset.calculate_depreciation: - return flt(asset.gross_purchase_amount) - flt(asset.opening_accumulated_depreciation) - - finance_book_filter = ["finance_book", "is", "not set"] - if finance_book: - finance_book_filter = ["finance_book", "=", finance_book] - - return frappe.db.get_value( - doctype="Asset Finance Book", - filters=[["parent", "=", asset.asset_id], finance_book_filter], - fieldname="value_after_depreciation", - ) - - def prepare_chart_data(data, filters): labels_values_map = {} date_field = frappe.scrub(filters.date_based_on) @@ -182,6 +188,15 @@ def prepare_chart_data(data, filters): } +def get_depreciation_amount_of_asset(asset, depreciation_amount_map, filters): + if asset.calculate_depreciation: + depr_amount = depreciation_amount_map.get(asset.asset_id) or 0.0 + else: + depr_amount = get_manual_depreciation_amount_of_asset(asset, filters) + + return depr_amount + + def get_finance_book_value_map(filters): date = filters.to_date if filters.filter_based_on == "Date Range" else filters.year_end_date @@ -201,6 +216,31 @@ def get_finance_book_value_map(filters): ) +def get_manual_depreciation_amount_of_asset(asset, filters): + date = filters.to_date if filters.filter_based_on == "Date Range" else filters.year_end_date + + (_, _, depreciation_expense_account) = get_depreciation_accounts(asset) + + gle = frappe.qb.DocType("GL Entry") + + result = ( + frappe.qb.from_(gle) + .select(Sum(gle.debit)) + .where(gle.against_voucher == asset.asset_id) + .where(gle.account == depreciation_expense_account) + .where(gle.debit != 0) + .where(gle.is_cancelled == 0) + .where(gle.posting_date <= date) + ).run() + + if result and result[0] and result[0][0]: + depr_amount = result[0][0] + else: + depr_amount = 0 + + return depr_amount + + def get_purchase_receipt_supplier_map(): return frappe._dict( frappe.db.sql( diff --git a/erpnext/patches.txt b/erpnext/patches.txt index f49e06675dd7..ecbf1f8000cb 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -375,3 +375,4 @@ erpnext.patches.v13_0.show_hr_payroll_deprecation_warning erpnext.patches.v13_0.create_accounting_dimensions_for_asset_repair execute:frappe.db.set_value("Naming Series", "Naming Series", {"select_doc_for_series": "", "set_options": "", "prefix": "", "current_value": 0, "user_must_always_select": 0}) erpnext.patches.v13_0.update_schedule_type_in_loans +erpnext.patches.v13_0.update_asset_value_for_manual_depr_entries diff --git a/erpnext/patches/v13_0/update_asset_value_for_manual_depr_entries.py b/erpnext/patches/v13_0/update_asset_value_for_manual_depr_entries.py new file mode 100644 index 000000000000..5d7b5cf19c18 --- /dev/null +++ b/erpnext/patches/v13_0/update_asset_value_for_manual_depr_entries.py @@ -0,0 +1,38 @@ +import frappe +from frappe.query_builder.functions import IfNull, Sum + + +def execute(): + asset = frappe.qb.DocType("Asset") + gle = frappe.qb.DocType("GL Entry") + aca = frappe.qb.DocType("Asset Category Account") + company = frappe.qb.DocType("Company") + + asset_total_depr_value_map = ( + frappe.qb.from_(gle) + .join(asset) + .on(gle.against_voucher == asset.name) + .join(aca) + .on((aca.parent == asset.asset_category) & (aca.company_name == asset.company)) + .join(company) + .on(company.name == asset.company) + .select(Sum(gle.debit).as_("value"), asset.name.as_("asset_name")) + .where( + gle.account == IfNull(aca.depreciation_expense_account, company.depreciation_expense_account) + ) + .where(gle.debit != 0) + .where(gle.is_cancelled == 0) + .where(asset.docstatus == 1) + .where(asset.calculate_depreciation == 0) + .groupby(asset.name) + ) + + frappe.qb.update(asset).join(asset_total_depr_value_map).on( + asset_total_depr_value_map.asset_name == asset.name + ).set( + asset.value_after_depreciation, asset.value_after_depreciation - asset_total_depr_value_map.value + ).where( + asset.docstatus == 1 + ).where( + asset.calculate_depreciation == 0 + ).run()