From 5a274176d3faf6a114a80d34a842abd63ef0428b Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Tue, 1 Nov 2022 11:45:17 +0530 Subject: [PATCH 01/49] feat: add asset_depreciation_schedule --- .../asset_depreciation_schedule/__init__.py | 0 .../asset_depreciation_schedule.js | 8 + .../asset_depreciation_schedule.json | 165 ++++++++++++++++++ .../asset_depreciation_schedule.py | 8 + .../test_asset_depreciation_schedule.py | 9 + 5 files changed, 190 insertions(+) create mode 100644 erpnext/assets/doctype/asset_depreciation_schedule/__init__.py create mode 100644 erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js create mode 100644 erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json create mode 100644 erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py create mode 100644 erpnext/assets/doctype/asset_depreciation_schedule/test_asset_depreciation_schedule.py diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/__init__.py b/erpnext/assets/doctype/asset_depreciation_schedule/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js new file mode 100644 index 0000000000..9d41de381e --- /dev/null +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js @@ -0,0 +1,8 @@ +// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Asset Depreciation Schedule', { + // refresh: function(frm) { + + // } +}); diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json new file mode 100644 index 0000000000..06eced229f --- /dev/null +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json @@ -0,0 +1,165 @@ +{ + "actions": [], + "allow_rename": 1, + "autoname": "naming_series:", + "creation": "2022-10-31 15:03:35.424877", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "asset", + "column_break_2", + "naming_series", + "depreciation_details_section", + "finance_book", + "depreciation_method", + "rate_of_depreciation", + "column_break_8", + "total_number_of_depreciations", + "frequency_of_depreciation_months", + "depreciation_schedule_section", + "depreciation_schedule", + "details_section", + "notes", + "column_break_15", + "status", + "amended_from" + ], + "fields": [ + { + "fieldname": "asset", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Asset", + "options": "Asset", + "reqd": 1 + }, + { + "fieldname": "naming_series", + "fieldtype": "Select", + "label": "Naming Series", + "options": "ACC-ADS-.YYYY.-" + }, + { + "fieldname": "amended_from", + "fieldtype": "Link", + "label": "Amended From", + "no_copy": 1, + "options": "Asset Depreciation Schedule", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "column_break_2", + "fieldtype": "Column Break" + }, + { + "collapsible": 1, + "fieldname": "depreciation_details_section", + "fieldtype": "Section Break", + "label": "Depreciation Details" + }, + { + "fieldname": "finance_book", + "fieldtype": "Link", + "label": "Finance Book", + "options": "Finance Book", + "read_only": 1 + }, + { + "fieldname": "depreciation_method", + "fieldtype": "Select", + "label": "Depreciation Method", + "options": "\nStraight Line\nDouble Declining Balance\nWritten Down Value\nManual", + "read_only": 1 + }, + { + "depends_on": "eval:doc.depreciation_method == 'Written Down Value'", + "description": "In Percentage", + "fieldname": "rate_of_depreciation", + "fieldtype": "Percent", + "label": "Rate of Depreciation", + "read_only": 1 + }, + { + "fieldname": "column_break_8", + "fieldtype": "Column Break" + }, + { + "depends_on": "total_number_of_depreciations", + "fieldname": "total_number_of_depreciations", + "fieldtype": "Int", + "label": "Total Number of Depreciations", + "read_only": 1 + }, + { + "depends_on": "frequency_of_depreciation_months", + "fieldname": "frequency_of_depreciation_months", + "fieldtype": "Int", + "label": "Frequency of Depreciation (Months)", + "read_only": 1 + }, + { + "fieldname": "depreciation_schedule_section", + "fieldtype": "Section Break", + "label": "Depreciation Schedule" + }, + { + "fieldname": "depreciation_schedule", + "fieldtype": "Table", + "label": "Depreciation Schedule", + "options": "Depreciation Schedule" + }, + { + "collapsible": 1, + "collapsible_depends_on": "notes", + "fieldname": "details_section", + "fieldtype": "Section Break", + "label": "Details" + }, + { + "fieldname": "notes", + "fieldtype": "Small Text", + "label": "Notes" + }, + { + "fieldname": "status", + "fieldtype": "Select", + "hidden": 1, + "label": "Status", + "options": "Draft\nActive\nCancelled", + "read_only": 1 + }, + { + "fieldname": "column_break_15", + "fieldtype": "Column Break" + } + ], + "in_create": 1, + "index_web_pages_for_search": 1, + "is_submittable": 1, + "links": [], + "modified": "2022-11-01 11:44:15.256470", + "modified_by": "Administrator", + "module": "Assets", + "name": "Asset Depreciation Schedule", + "naming_rule": "By \"Naming Series\" field", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py new file mode 100644 index 0000000000..625c3bdb1f --- /dev/null +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -0,0 +1,8 @@ +# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + +class AssetDepreciationSchedule(Document): + pass diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/test_asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/test_asset_depreciation_schedule.py new file mode 100644 index 0000000000..21de8cde51 --- /dev/null +++ b/erpnext/assets/doctype/asset_depreciation_schedule/test_asset_depreciation_schedule.py @@ -0,0 +1,9 @@ +# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt + +# import frappe +from frappe.tests.utils import FrappeTestCase + + +class TestAssetDepreciationSchedule(FrappeTestCase): + pass From 710d2452b7c32fbf50bc7b594e0f2388a81cc0be Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Fri, 11 Nov 2022 16:20:17 +0530 Subject: [PATCH 02/49] feat: moving, refactoring and adding functions to asset_depreciation_schedule --- erpnext/assets/doctype/asset/asset.json | 7 +- erpnext/assets/doctype/asset/asset.py | 38 +- erpnext/assets/doctype/asset/test_asset.py | 4 +- .../asset_depreciation_schedule.json | 26 +- .../asset_depreciation_schedule.py | 326 +++++++++++++++++- .../asset_value_adjustment.py | 4 +- 6 files changed, 360 insertions(+), 45 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json index f0505ff983..9af03ca0e7 100644 --- a/erpnext/assets/doctype/asset/asset.json +++ b/erpnext/assets/doctype/asset/asset.json @@ -508,9 +508,14 @@ "group": "Value", "link_doctype": "Asset Value Adjustment", "link_fieldname": "asset" + }, + { + "group": "Depreciation", + "link_doctype": "Asset Depreciation Schedule", + "link_fieldname": "asset" } ], - "modified": "2022-07-20 10:15:12.887372", + "modified": "2022-11-01 15:25:27.669803", "modified_by": "Administrator", "module": "Assets", "name": "Asset", diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index ca6be9b57b..449723b0aa 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -15,6 +15,7 @@ from frappe.utils import ( flt, get_datetime, get_last_day, + is_last_day_of_the_month, getdate, month_diff, nowdate, @@ -27,6 +28,10 @@ from erpnext.assets.doctype.asset.depreciation import ( get_depreciation_accounts, get_disposal_account_and_cost_center, ) +from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( + make_draft_asset_depreciation_schedules, + modify_draft_asset_depreciation_schedules, +) from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account from erpnext.controllers.accounts_controller import AccountsController @@ -40,6 +45,7 @@ class Asset(AccountsController): self.set_missing_values() if not self.split_from: self.prepare_depreciation_data() + modify_draft_asset_depreciation_schedules(self) self.validate_gross_and_purchase_amount() if self.get("schedules"): self.validate_expected_value_after_useful_life() @@ -62,6 +68,10 @@ class Asset(AccountsController): make_reverse_gl_entries(voucher_type="Asset", voucher_no=self.name) self.db_set("booked_fixed_asset", 0) + def after_insert(self): + if not self.split_from: + make_draft_asset_depreciation_schedules(self) + def validate_asset_and_reference(self): if self.purchase_invoice or self.purchase_receipt: reference_doc = "Purchase Invoice" if self.purchase_invoice else "Purchase Receipt" @@ -83,8 +93,6 @@ class Asset(AccountsController): if self.calculate_depreciation: self.value_after_depreciation = 0 self.set_depreciation_rate() - self.make_depreciation_schedule(date_of_disposal) - self.set_accumulated_depreciation(date_of_disposal, date_of_return) else: self.finance_books = [] self.value_after_depreciation = flt(self.gross_purchase_amount) - flt( @@ -1072,32 +1080,6 @@ def get_total_days(date, frequency): return date_diff(date, period_start_date) -def is_last_day_of_the_month(date): - last_day_of_the_month = get_last_day(date) - - return getdate(last_day_of_the_month) == getdate(date) - - -@erpnext.allow_regional -def get_depreciation_amount(asset, depreciable_value, row): - if row.depreciation_method in ("Straight Line", "Manual"): - # if the Depreciation Schedule is being prepared for the first time - if not asset.flags.increase_in_asset_life: - depreciation_amount = ( - flt(asset.gross_purchase_amount) - flt(row.expected_value_after_useful_life) - ) / flt(row.total_number_of_depreciations) - - # if the Depreciation Schedule is being modified after Asset Repair - else: - depreciation_amount = ( - flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life) - ) / (date_diff(asset.to_date, asset.available_for_use_date) / 365) - else: - depreciation_amount = flt(depreciable_value * (flt(row.rate_of_depreciation) / 100)) - - return depreciation_amount - - @frappe.whitelist() def split_asset(asset_name, split_qty): asset = frappe.get_doc("Asset", asset_name) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 370b13bb98..7084ea58f8 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -865,7 +865,9 @@ class TestDepreciationBasics(AssetSetup): def test_get_depreciation_amount(self): """Tests if get_depreciation_amount() returns the right value.""" - from erpnext.assets.doctype.asset.asset import get_depreciation_amount + from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( + get_depreciation_amount + ) asset = create_asset(item_code="Macbook Pro", available_for_use_date="2019-12-31") diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json index 06eced229f..49bd2e7faa 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json @@ -8,15 +8,15 @@ "engine": "InnoDB", "field_order": [ "asset", - "column_break_2", "naming_series", - "depreciation_details_section", + "column_break_2", "finance_book", + "depreciation_details_section", "depreciation_method", - "rate_of_depreciation", - "column_break_8", "total_number_of_depreciations", - "frequency_of_depreciation_months", + "column_break_8", + "frequency_of_depreciation", + "rate_of_depreciation", "depreciation_schedule_section", "depreciation_schedule", "details_section", @@ -92,13 +92,6 @@ "label": "Total Number of Depreciations", "read_only": 1 }, - { - "depends_on": "frequency_of_depreciation_months", - "fieldname": "frequency_of_depreciation_months", - "fieldtype": "Int", - "label": "Frequency of Depreciation (Months)", - "read_only": 1 - }, { "fieldname": "depreciation_schedule_section", "fieldtype": "Section Break", @@ -133,13 +126,20 @@ { "fieldname": "column_break_15", "fieldtype": "Column Break" + }, + { + "depends_on": "frequency_of_depreciation", + "fieldname": "frequency_of_depreciation", + "fieldtype": "Int", + "label": "Frequency of Depreciation (Months)", + "read_only": 1 } ], "in_create": 1, "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2022-11-01 11:44:15.256470", + "modified": "2022-11-01 17:23:33.873283", "modified_by": "Administrator", "module": "Assets", "name": "Asset Depreciation Schedule", diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 625c3bdb1f..1a545dd81a 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -1,8 +1,332 @@ # Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -# import frappe +import frappe +from frappe.utils import ( + add_days, + add_months, + cint, + date_diff, + flt, + get_last_day, + is_last_day_of_the_month +) from frappe.model.document import Document +import erpnext + + class AssetDepreciationSchedule(Document): pass + + +def make_draft_asset_depreciation_schedules(asset): + for row in asset.get("finance_books"): + asset_depr_schedule = frappe.new_doc("Asset Depreciation Schedule") + + prepare_draft_asset_depreciation_schedule_data(asset_depr_schedule, asset, row) + + +def modify_draft_asset_depreciation_schedules(asset): + for row in asset.get("finance_books"): + asset_depr_schedule_name = get_draft_asset_depreciation_schedule_name(asset.name, row) + + if not asset_depr_schedule_name: + return + + asset_depr_schedule = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) + + prepare_draft_asset_depreciation_schedule_data(asset_depr_schedule, asset, row) + + +def prepare_draft_asset_depreciation_schedule_data(asset_depr_schedule, asset, row): + set_draft_asset_depreciation_schedule_details(asset_depr_schedule, asset.name, row) + make_depreciation_schedule(asset_depr_schedule, asset, row) + set_accumulated_depreciation(asset_depr_schedule, asset, row) + + asset_depr_schedule.save() + + +def set_draft_asset_depreciation_schedule_details(asset_depr_schedule, asset_name, row): + asset_depr_schedule.asset = asset_name + asset_depr_schedule.finance_book = row.finance_book + asset_depr_schedule.depreciation_method = row.depreciation_method + asset_depr_schedule.total_number_of_depreciations = row.total_number_of_depreciations + asset_depr_schedule.frequency_of_depreciation = row.frequency_of_depreciation + asset_depr_schedule.rate_of_depreciation = row.rate_of_depreciation + asset_depr_schedule.status = "Draft" + + +def make_new_active_asset_depreciation_schedules_from_existing( + asset, date_of_disposal=None, date_of_return=None +): + for row in asset.get("finance_books"): + old_asset_depr_schedule_name = get_active_asset_depreciation_schedule(asset.name, row) + + if not old_asset_depr_schedule_name: + return + + old_asset_depr_schedule = frappe.get_doc( + "Asset Depreciation Schedule", + old_asset_depr_schedule_name + ) + + asset_depr_schedule = frappe.copy_doc(old_asset_depr_schedule, ignore_no_copy=False) + + make_depreciation_schedule(asset_depr_schedule, asset, row, date_of_disposal) + set_accumulated_depreciation(asset_depr_schedule, asset, row, date_of_disposal, date_of_return) + + asset_depr_schedule.save() + + +def make_depreciation_schedule(asset_depr_schedule, asset, row, date_of_disposal): + if row.depreciation_method != "Manual" and not asset_depr_schedule.get("depreciation_schedule"): + asset_depr_schedule.depreciation_schedule = [] + + if not asset.available_for_use_date: + return + + start = clear_depreciation_schedule(asset_depr_schedule) + + _make_depreciation_schedule(asset_depr_schedule, asset, row, start, date_of_disposal) + + +def get_draft_asset_depreciation_schedule_name(asset_name, finance_book): + return frappe.db.get_value( + "Asset Depreciation Schedule", + {"asset": asset_name, "finance_book": finance_book, "status": "Draft", "docstatus": 0}, + ) + + +def get_active_asset_depreciation_schedule(asset_name, finance_book): + return frappe.db.get_value( + "Asset Depreciation Schedule", + {"asset": asset_name, "finance_book": finance_book, "status": "Active", "docstatus": 1}, + ) + + +def clear_depreciation_schedule(asset_depr_schedule): + start = [] + num_of_depreciations_completed = 0 + depr_schedule = [] + + for schedule in asset_depr_schedule.get("depreciation_schedule"): + if len(start) != 0: + break + + if schedule.journal_entry: + num_of_depreciations_completed += 1 + depr_schedule.append(schedule) + else: + start.append(num_of_depreciations_completed) + num_of_depreciations_completed = 0 + + # to update start when all the schedule rows corresponding to the FB are linked with JEs + if len(start) == 0: + start.append(num_of_depreciations_completed) + + # when the Depreciation Schedule is being created for the first time + if start == []: + start = [0] + else: + asset_depr_schedule.depreciation_schedule = depr_schedule + + return start + + +def _make_depreciation_schedule(asset_depr_schedule, asset, row, start, date_of_disposal): + asset.validate_asset_finance_books(row) + + value_after_depreciation = asset._get_value_after_depreciation(row) + row.value_after_depreciation = value_after_depreciation + + number_of_pending_depreciations = cint(row.total_number_of_depreciations) - cint( + asset.number_of_depreciations_booked + ) + + has_pro_rata = asset.check_is_pro_rata(row) + if has_pro_rata: + number_of_pending_depreciations += 1 + + skip_row = False + should_get_last_day = is_last_day_of_the_month(row.depreciation_start_date) + + for n in range(start[row.idx - 1], number_of_pending_depreciations): + # If depreciation is already completed (for double declining balance) + if skip_row: + continue + + depreciation_amount = get_depreciation_amount(asset, value_after_depreciation, row) + + if not has_pro_rata or n < cint(number_of_pending_depreciations) - 1: + schedule_date = add_months( + row.depreciation_start_date, n * cint(row.frequency_of_depreciation) + ) + + if should_get_last_day: + schedule_date = get_last_day(schedule_date) + + # schedule date will be a year later from start date + # so monthly schedule date is calculated by removing 11 months from it + monthly_schedule_date = add_months(schedule_date, -row.frequency_of_depreciation + 1) + + # if asset is being sold or scrapped + if date_of_disposal: + from_date = asset.get_from_date(row.finance_book) + depreciation_amount, days, months = asset.get_pro_rata_amt( + row, depreciation_amount, from_date, date_of_disposal + ) + + if depreciation_amount > 0: + add_depr_schedule_row( + asset_depr_schedule, + date_of_disposal, + depreciation_amount, + row.depreciation_method, + row.finance_book, + row.idx, + ) + + break + + # For first row + if has_pro_rata and not asset.opening_accumulated_depreciation and n == 0: + from_date = add_days( + asset.available_for_use_date, -1 + ) # needed to calc depr amount for available_for_use_date too + depreciation_amount, days, months = asset.get_pro_rata_amt( + row, depreciation_amount, from_date, row.depreciation_start_date + ) + + # For first depr schedule date will be the start date + # so monthly schedule date is calculated by removing + # month difference between use date and start date + monthly_schedule_date = add_months(row.depreciation_start_date, -months + 1) + + # For last row + elif has_pro_rata and n == cint(number_of_pending_depreciations) - 1: + if not asset.flags.increase_in_asset_life: + # In case of increase_in_asset_life, the asset.to_date is already set on asset_repair submission + asset.to_date = add_months( + asset.available_for_use_date, + (n + asset.number_of_depreciations_booked) * cint(row.frequency_of_depreciation), + ) + + depreciation_amount_without_pro_rata = depreciation_amount + + depreciation_amount, days, months = asset.get_pro_rata_amt( + row, depreciation_amount, schedule_date, asset.to_date + ) + + depreciation_amount = asset.get_adjusted_depreciation_amount( + depreciation_amount_without_pro_rata, depreciation_amount, row.finance_book + ) + + monthly_schedule_date = add_months(schedule_date, 1) + schedule_date = add_days(schedule_date, days) + last_schedule_date = schedule_date + + if not depreciation_amount: + continue + value_after_depreciation -= flt(depreciation_amount, asset.precision("gross_purchase_amount")) + + # Adjust depreciation amount in the last period based on the expected value after useful life + if row.expected_value_after_useful_life and ( + ( + n == cint(number_of_pending_depreciations) - 1 + and value_after_depreciation != row.expected_value_after_useful_life + ) + or value_after_depreciation < row.expected_value_after_useful_life + ): + depreciation_amount += value_after_depreciation - row.expected_value_after_useful_life + skip_row = True + + if depreciation_amount > 0: + add_depr_schedule_row( + asset_depr_schedule, + schedule_date, + depreciation_amount, + row.depreciation_method, + row.finance_book, + row.idx, + ) + + +@erpnext.allow_regional +def get_depreciation_amount(asset, depreciable_value, row): + if row.depreciation_method in ("Straight Line", "Manual"): + # if the Depreciation Schedule is being prepared for the first time + if not asset.flags.increase_in_asset_life: + depreciation_amount = ( + flt(asset.gross_purchase_amount) - flt(row.expected_value_after_useful_life) + ) / flt(row.total_number_of_depreciations) + + # if the Depreciation Schedule is being modified after Asset Repair + else: + depreciation_amount = ( + flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life) + ) / (date_diff(asset.to_date, asset.available_for_use_date) / 365) + else: + depreciation_amount = flt(depreciable_value * (flt(row.rate_of_depreciation) / 100)) + + return depreciation_amount + + +def add_depr_schedule_row( + asset_depr_schedule, + schedule_date, + depreciation_amount, + depreciation_method, + finance_book, + finance_book_id +): + asset_depr_schedule.append( + "depreciation_schedule", + { + "schedule_date": schedule_date, + "depreciation_amount": depreciation_amount, + "depreciation_method": depreciation_method, + "finance_book": finance_book, + "finance_book_id": finance_book_id, + }, + ) + + +def set_accumulated_depreciation( + asset_depr_schedule, asset, row, date_of_disposal, date_of_return, ignore_booked_entry=False +): + straight_line_idx = [ + d.idx for d in asset_depr_schedule.get("depreciation_schedule") + if d.depreciation_method == "Straight Line" + ] + finance_books = [] + + for i, d in enumerate(asset_depr_schedule.get("depreciation_schedule")): + if ignore_booked_entry and d.journal_entry: + continue + + if int(d.finance_book_id) not in finance_books: + accumulated_depreciation = flt(asset.opening_accumulated_depreciation) + value_after_depreciation = flt(asset.get_value_after_depreciation(d.finance_book_id)) + finance_books.append(int(d.finance_book_id)) + + depreciation_amount = flt(d.depreciation_amount, d.precision("depreciation_amount")) + value_after_depreciation -= flt(depreciation_amount) + + # for the last row, if depreciation method = Straight Line + if ( + straight_line_idx + and i == max(straight_line_idx) - 1 + and not date_of_disposal + and not date_of_return + ): + depreciation_amount += flt( + value_after_depreciation - flt(row.expected_value_after_useful_life), + d.precision("depreciation_amount"), + ) + + d.depreciation_amount = depreciation_amount + accumulated_depreciation += d.depreciation_amount + d.accumulated_depreciation_amount = flt( + accumulated_depreciation, d.precision("accumulated_depreciation_amount") + ) 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 84aa8fa023..ae6e2b426e 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,9 @@ from frappe.utils import cint, date_diff, flt, formatdate, getdate 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_depreciation_schedule.asset_depreciation_schedule import ( + get_depreciation_amount +) from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts From 97ab7bd36bb9ffb1b488edcddf512164020710c7 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Fri, 11 Nov 2022 16:27:29 +0530 Subject: [PATCH 03/49] chore: remove some unwanted functions in asset --- erpnext/assets/doctype/asset/asset.py | 144 +------------------------- 1 file changed, 1 insertion(+), 143 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 449723b0aa..f55dceddf0 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -89,7 +89,7 @@ class Asset(AccountsController): _("Purchase Invoice cannot be made against an existing asset {0}").format(self.name) ) - def prepare_depreciation_data(self, date_of_disposal=None, date_of_return=None): + def prepare_depreciation_data(self): if self.calculate_depreciation: self.value_after_depreciation = 0 self.set_depreciation_rate() @@ -231,148 +231,6 @@ class Asset(AccountsController): self.get_depreciation_rate(d, on_validate=True), d.precision("rate_of_depreciation") ) - def make_depreciation_schedule(self, date_of_disposal): - if "Manual" not in [d.depreciation_method for d in self.finance_books] and not self.get( - "schedules" - ): - self.schedules = [] - - if not self.available_for_use_date: - return - - start = self.clear_depreciation_schedule() - - for finance_book in self.get("finance_books"): - self._make_depreciation_schedule(finance_book, start, 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) - finance_book.value_after_depreciation = value_after_depreciation - - number_of_pending_depreciations = cint(finance_book.total_number_of_depreciations) - cint( - self.number_of_depreciations_booked - ) - - has_pro_rata = self.check_is_pro_rata(finance_book) - if has_pro_rata: - number_of_pending_depreciations += 1 - - skip_row = False - should_get_last_day = is_last_day_of_the_month(finance_book.depreciation_start_date) - - for n in range(start[finance_book.idx - 1], number_of_pending_depreciations): - # If depreciation is already completed (for double declining balance) - if skip_row: - continue - - depreciation_amount = get_depreciation_amount(self, value_after_depreciation, finance_book) - - if not has_pro_rata or n < cint(number_of_pending_depreciations) - 1: - schedule_date = add_months( - finance_book.depreciation_start_date, n * cint(finance_book.frequency_of_depreciation) - ) - - if should_get_last_day: - schedule_date = get_last_day(schedule_date) - - # schedule date will be a year later from start date - # so monthly schedule date is calculated by removing 11 months from it - monthly_schedule_date = add_months(schedule_date, -finance_book.frequency_of_depreciation + 1) - - # if asset is being sold - if date_of_disposal: - from_date = self.get_from_date(finance_book.finance_book) - depreciation_amount, days, months = self.get_pro_rata_amt( - finance_book, depreciation_amount, from_date, date_of_disposal - ) - - if depreciation_amount > 0: - self._add_depreciation_row( - date_of_disposal, - depreciation_amount, - finance_book.depreciation_method, - finance_book.finance_book, - finance_book.idx, - ) - - break - - # For first row - if has_pro_rata and not self.opening_accumulated_depreciation and n == 0: - from_date = add_days( - self.available_for_use_date, -1 - ) # needed to calc depr amount for available_for_use_date too - depreciation_amount, days, months = self.get_pro_rata_amt( - finance_book, depreciation_amount, from_date, finance_book.depreciation_start_date - ) - - # For first depr schedule date will be the start date - # so monthly schedule date is calculated by removing month difference between use date and start date - monthly_schedule_date = add_months(finance_book.depreciation_start_date, -months + 1) - - # For last row - elif has_pro_rata and n == cint(number_of_pending_depreciations) - 1: - if not self.flags.increase_in_asset_life: - # In case of increase_in_asset_life, the self.to_date is already set on asset_repair submission - self.to_date = add_months( - self.available_for_use_date, - (n + self.number_of_depreciations_booked) * cint(finance_book.frequency_of_depreciation), - ) - - depreciation_amount_without_pro_rata = depreciation_amount - - depreciation_amount, days, months = self.get_pro_rata_amt( - finance_book, depreciation_amount, schedule_date, self.to_date - ) - - depreciation_amount = self.get_adjusted_depreciation_amount( - depreciation_amount_without_pro_rata, depreciation_amount, finance_book.finance_book - ) - - monthly_schedule_date = add_months(schedule_date, 1) - schedule_date = add_days(schedule_date, days) - last_schedule_date = schedule_date - - if not depreciation_amount: - continue - value_after_depreciation -= flt(depreciation_amount, self.precision("gross_purchase_amount")) - - # Adjust depreciation amount in the last period based on the expected value after useful life - if finance_book.expected_value_after_useful_life and ( - ( - n == cint(number_of_pending_depreciations) - 1 - and value_after_depreciation != finance_book.expected_value_after_useful_life - ) - or value_after_depreciation < finance_book.expected_value_after_useful_life - ): - depreciation_amount += value_after_depreciation - finance_book.expected_value_after_useful_life - skip_row = True - - if depreciation_amount > 0: - self._add_depreciation_row( - schedule_date, - depreciation_amount, - finance_book.depreciation_method, - finance_book.finance_book, - finance_book.idx, - ) - - def _add_depreciation_row( - self, schedule_date, depreciation_amount, depreciation_method, finance_book, finance_book_id - ): - self.append( - "schedules", - { - "schedule_date": schedule_date, - "depreciation_amount": depreciation_amount, - "depreciation_method": depreciation_method, - "finance_book": finance_book, - "finance_book_id": finance_book_id, - }, - ) - def _get_value_after_depreciation(self, finance_book): # value_after_depreciation - current Asset value if self.docstatus == 1 and finance_book.value_after_depreciation: From ed495dc846d6f1f0939103d18be850dd0285c9c6 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Mon, 14 Nov 2022 12:45:49 +0530 Subject: [PATCH 04/49] chore: add convert_draft_asset_depreciation_schedules_into_active and fix some bugs --- erpnext/assets/doctype/asset/asset.py | 41 +------------------ .../asset_depreciation_schedule.py | 33 +++++++++++++-- 2 files changed, 31 insertions(+), 43 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index f55dceddf0..5fe756859f 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -31,6 +31,7 @@ from erpnext.assets.doctype.asset.depreciation import ( from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( make_draft_asset_depreciation_schedules, modify_draft_asset_depreciation_schedules, + convert_draft_asset_depreciation_schedules_into_active, ) from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account from erpnext.controllers.accounts_controller import AccountsController @@ -58,6 +59,7 @@ class Asset(AccountsController): self.make_asset_movement() if not self.booked_fixed_asset and self.validate_make_gl_entry(): self.make_gl_entries() + convert_draft_asset_depreciation_schedules_into_active(self) def on_cancel(self): self.validate_cancellation() @@ -407,45 +409,6 @@ class Asset(AccountsController): if len(self.finance_books) == 1: return True - def set_accumulated_depreciation( - self, date_of_sale=None, date_of_return=None, ignore_booked_entry=False - ): - straight_line_idx = [ - d.idx for d in self.get("schedules") if d.depreciation_method == "Straight Line" - ] - finance_books = [] - - for i, d in enumerate(self.get("schedules")): - if ignore_booked_entry and d.journal_entry: - continue - - 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)) - finance_books.append(int(d.finance_book_id)) - - depreciation_amount = flt(d.depreciation_amount, d.precision("depreciation_amount")) - value_after_depreciation -= flt(depreciation_amount) - - # for the last row, if depreciation method = Straight Line - if ( - straight_line_idx - and i == max(straight_line_idx) - 1 - and not date_of_sale - and not date_of_return - ): - book = self.get("finance_books")[cint(d.finance_book_id) - 1] - depreciation_amount += flt( - value_after_depreciation - flt(book.expected_value_after_useful_life), - d.precision("depreciation_amount"), - ) - - d.depreciation_amount = depreciation_amount - accumulated_depreciation += d.depreciation_amount - d.accumulated_depreciation_amount = flt( - 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) diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 1a545dd81a..27920e3933 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -29,7 +29,9 @@ def make_draft_asset_depreciation_schedules(asset): def modify_draft_asset_depreciation_schedules(asset): for row in asset.get("finance_books"): - asset_depr_schedule_name = get_draft_asset_depreciation_schedule_name(asset.name, row) + asset_depr_schedule_name = get_draft_asset_depreciation_schedule_name( + asset.name, row.finance_book + ) if not asset_depr_schedule_name: return @@ -57,11 +59,29 @@ def set_draft_asset_depreciation_schedule_details(asset_depr_schedule, asset_nam asset_depr_schedule.status = "Draft" +def convert_draft_asset_depreciation_schedules_into_active(asset): + for row in asset.get("finance_books"): + asset_depr_schedule_name = get_draft_asset_depreciation_schedule_name( + asset.name, row.finance_book + ) + + if not asset_depr_schedule_name: + return + + asset_depr_schedule = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) + + asset_depr_schedule.status = "Active" + + asset_depr_schedule.submit() + + def make_new_active_asset_depreciation_schedules_from_existing( asset, date_of_disposal=None, date_of_return=None ): for row in asset.get("finance_books"): - old_asset_depr_schedule_name = get_active_asset_depreciation_schedule(asset.name, row) + old_asset_depr_schedule_name = get_active_asset_depreciation_schedule( + asset.name, row.finance_book + ) if not old_asset_depr_schedule_name: return @@ -79,7 +99,7 @@ def make_new_active_asset_depreciation_schedules_from_existing( asset_depr_schedule.save() -def make_depreciation_schedule(asset_depr_schedule, asset, row, date_of_disposal): +def make_depreciation_schedule(asset_depr_schedule, asset, row, date_of_disposal=None): if row.depreciation_method != "Manual" and not asset_depr_schedule.get("depreciation_schedule"): asset_depr_schedule.depreciation_schedule = [] @@ -293,7 +313,12 @@ def add_depr_schedule_row( def set_accumulated_depreciation( - asset_depr_schedule, asset, row, date_of_disposal, date_of_return, ignore_booked_entry=False + asset_depr_schedule, + asset, + row, + date_of_disposal=None, + date_of_return=None, + ignore_booked_entry=False ): straight_line_idx = [ d.idx for d in asset_depr_schedule.get("depreciation_schedule") From ca3581d05531b2dba59db73a08a8076857b293d1 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Mon, 14 Nov 2022 12:47:48 +0530 Subject: [PATCH 05/49] chore: rename modify_draft_asset_depreciation_schedules --- erpnext/assets/doctype/asset/asset.py | 4 ++-- .../asset_depreciation_schedule.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 5fe756859f..85b309fad4 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -30,8 +30,8 @@ from erpnext.assets.doctype.asset.depreciation import ( ) from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( make_draft_asset_depreciation_schedules, - modify_draft_asset_depreciation_schedules, convert_draft_asset_depreciation_schedules_into_active, + update_draft_asset_depreciation_schedules, ) from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account from erpnext.controllers.accounts_controller import AccountsController @@ -46,7 +46,7 @@ class Asset(AccountsController): self.set_missing_values() if not self.split_from: self.prepare_depreciation_data() - modify_draft_asset_depreciation_schedules(self) + update_draft_asset_depreciation_schedules(self) self.validate_gross_and_purchase_amount() if self.get("schedules"): self.validate_expected_value_after_useful_life() diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 27920e3933..7bb8b0e01d 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -27,7 +27,7 @@ def make_draft_asset_depreciation_schedules(asset): prepare_draft_asset_depreciation_schedule_data(asset_depr_schedule, asset, row) -def modify_draft_asset_depreciation_schedules(asset): +def update_draft_asset_depreciation_schedules(asset): for row in asset.get("finance_books"): asset_depr_schedule_name = get_draft_asset_depreciation_schedule_name( asset.name, row.finance_book From ffd41703dee89032d065dad9e10e03ae2506480e Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Mon, 14 Nov 2022 14:36:10 +0530 Subject: [PATCH 06/49] chore: add expected_value_after_useful_life in depr schedule --- .../asset_depreciation_schedule.json | 13 +++++++++++-- .../asset_depreciation_schedule.py | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json index 49bd2e7faa..83ed089de8 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json @@ -14,9 +14,10 @@ "depreciation_details_section", "depreciation_method", "total_number_of_depreciations", + "rate_of_depreciation", "column_break_8", "frequency_of_depreciation", - "rate_of_depreciation", + "expected_value_after_useful_life", "depreciation_schedule_section", "depreciation_schedule", "details_section", @@ -133,13 +134,21 @@ "fieldtype": "Int", "label": "Frequency of Depreciation (Months)", "read_only": 1 + }, + { + "default": "0", + "fieldname": "expected_value_after_useful_life", + "fieldtype": "Currency", + "label": "Expected Value After Useful Life", + "options": "Company:company:default_currency", + "read_only": 1 } ], "in_create": 1, "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2022-11-01 17:23:33.873283", + "modified": "2022-11-14 14:33:53.360643", "modified_by": "Administrator", "module": "Assets", "name": "Asset Depreciation Schedule", diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 7bb8b0e01d..f04a9fdd24 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -56,6 +56,7 @@ def set_draft_asset_depreciation_schedule_details(asset_depr_schedule, asset_nam asset_depr_schedule.total_number_of_depreciations = row.total_number_of_depreciations asset_depr_schedule.frequency_of_depreciation = row.frequency_of_depreciation asset_depr_schedule.rate_of_depreciation = row.rate_of_depreciation + asset_depr_schedule.expected_value_after_useful_life = row.expected_value_after_useful_life asset_depr_schedule.status = "Draft" From 417180e6ba7e9dd6ef6f35911c05f72b80063f1c Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Mon, 14 Nov 2022 17:51:11 +0530 Subject: [PATCH 07/49] chore: refactor some functions to use new depr schedule --- erpnext/assets/doctype/asset/asset.py | 101 +++++++----------- .../asset_depreciation_schedule.py | 23 ++-- 2 files changed, 47 insertions(+), 77 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 85b309fad4..b8f368a2e6 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -30,6 +30,7 @@ from erpnext.assets.doctype.asset.depreciation import ( ) from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( make_draft_asset_depreciation_schedules, + get_asset_depreciation_schedule_name, convert_draft_asset_depreciation_schedules_into_active, update_draft_asset_depreciation_schedules, ) @@ -48,8 +49,7 @@ class Asset(AccountsController): self.prepare_depreciation_data() update_draft_asset_depreciation_schedules(self) self.validate_gross_and_purchase_amount() - if self.get("schedules"): - self.validate_expected_value_after_useful_life() + self.validate_expected_value_after_useful_life() self.status = self.get_status() @@ -244,57 +244,17 @@ class Asset(AccountsController): return value_after_depreciation - # depreciation schedules need to be cleared before modification due to increase in asset life/asset sales - # JE: Journal Entry, FB: Finance Book - def clear_depreciation_schedule(self): - start = [] - num_of_depreciations_completed = 0 - depr_schedule = [] - - for schedule in self.get("schedules"): - # to update start when there are JEs linked with all the schedule rows corresponding to an FB - if len(start) == (int(schedule.finance_book_id) - 2): - start.append(num_of_depreciations_completed) - num_of_depreciations_completed = 0 - - # to ensure that start will only be updated once for each FB - if len(start) == (int(schedule.finance_book_id) - 1): - if schedule.journal_entry: - num_of_depreciations_completed += 1 - depr_schedule.append(schedule) - else: - start.append(num_of_depreciations_completed) - num_of_depreciations_completed = 0 - - # to update start when all the schedule rows corresponding to the last FB are linked with JEs - if len(start) == (len(self.finance_books) - 1): - start.append(num_of_depreciations_completed) - - # when the Depreciation Schedule is being created for the first time - if start == []: - start = [0] * len(self.finance_books) - else: - self.schedules = depr_schedule - - return start - def get_from_date(self, finance_book): - if not self.get("schedules"): + asset_depr_schedule_name = get_asset_depreciation_schedule_name( + self.name, finance_book + ) + + if not asset_depr_schedule_name: return self.available_for_use_date - if len(self.finance_books) == 1: - return self.schedules[-1].schedule_date + asset_depr_schedule = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) - from_date = "" - for schedule in self.get("schedules"): - if schedule.finance_book == finance_book: - from_date = schedule.schedule_date - - if from_date: - return from_date - - # since depr for available_for_use_date is not yet booked - return add_days(self.available_for_use_date, -1) + return asset_depr_schedule.get("depreciation_schedule")[-1].schedule_date # if it returns True, depreciation_amount will not be equal for the first and last rows def check_is_pro_rata(self, row): @@ -398,26 +358,29 @@ class Asset(AccountsController): return depreciation_amount_for_last_row def get_depreciation_amount_for_first_row(self, finance_book): - if self.has_only_one_finance_book(): - return self.schedules[0].depreciation_amount - else: - for schedule in self.schedules: - if schedule.finance_book == finance_book: - return schedule.depreciation_amount + asset_depr_schedule_name = get_asset_depreciation_schedule_name(self.name, finance_book) - def has_only_one_finance_book(self): - if len(self.finance_books) == 1: - return True + asset_depr_schedule = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) + + return asset_depr_schedule.get("depreciation_schedule")[0].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"): + asset_depr_schedule_name = get_asset_depreciation_schedule_name( + self.name, row.finance_book + ) + + if not asset_depr_schedule_name: + return + + asset_depr_schedule = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) + accumulated_depreciation_after_full_schedule = [ d.accumulated_depreciation_amount - for d in self.get("schedules") - if cint(d.finance_book_id) == row.idx + for d in asset_depr_schedule.get("depreciation_schedule") ] if accumulated_depreciation_after_full_schedule: @@ -466,10 +429,20 @@ class Asset(AccountsController): 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) + for row in self.get("finance_books"): + asset_depr_schedule_name = get_asset_depreciation_schedule_name( + self.name, row.finance_book + ) + + if not asset_depr_schedule_name: + return + + asset_depr_schedule = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) + + for d in asset_depr_schedule.get("depreciation_schedule"): + 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", diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index f04a9fdd24..ae3707b82f 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -29,7 +29,7 @@ def make_draft_asset_depreciation_schedules(asset): def update_draft_asset_depreciation_schedules(asset): for row in asset.get("finance_books"): - asset_depr_schedule_name = get_draft_asset_depreciation_schedule_name( + asset_depr_schedule_name = get_asset_depreciation_schedule_name( asset.name, row.finance_book ) @@ -62,7 +62,7 @@ def set_draft_asset_depreciation_schedule_details(asset_depr_schedule, asset_nam def convert_draft_asset_depreciation_schedules_into_active(asset): for row in asset.get("finance_books"): - asset_depr_schedule_name = get_draft_asset_depreciation_schedule_name( + asset_depr_schedule_name = get_asset_depreciation_schedule_name( asset.name, row.finance_book ) @@ -80,7 +80,7 @@ def make_new_active_asset_depreciation_schedules_from_existing( asset, date_of_disposal=None, date_of_return=None ): for row in asset.get("finance_books"): - old_asset_depr_schedule_name = get_active_asset_depreciation_schedule( + old_asset_depr_schedule_name = get_asset_depreciation_schedule_name( asset.name, row.finance_book ) @@ -112,17 +112,14 @@ def make_depreciation_schedule(asset_depr_schedule, asset, row, date_of_disposal _make_depreciation_schedule(asset_depr_schedule, asset, row, start, date_of_disposal) -def get_draft_asset_depreciation_schedule_name(asset_name, finance_book): +def get_asset_depreciation_schedule_name(asset_name, finance_book): return frappe.db.get_value( - "Asset Depreciation Schedule", - {"asset": asset_name, "finance_book": finance_book, "status": "Draft", "docstatus": 0}, - ) - - -def get_active_asset_depreciation_schedule(asset_name, finance_book): - return frappe.db.get_value( - "Asset Depreciation Schedule", - {"asset": asset_name, "finance_book": finance_book, "status": "Active", "docstatus": 1}, + doctype="Asset Depreciation Schedule", + filters=[ + ["asset", "=", asset_name], + ["finance_book", "=", finance_book], + ["docstatus", "<", 2], + ] ) From 76f28de7eb11652ca6006d1346dd51ad7a701936 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Wed, 23 Nov 2022 18:04:54 +0530 Subject: [PATCH 08/49] chore: refactor more functions to use new depr schedule --- erpnext/assets/doctype/asset/asset.py | 26 +-- erpnext/assets/doctype/asset/depreciation.py | 46 +++-- .../asset_depreciation_schedule.py | 184 ++++++++++-------- .../doctype/asset_repair/asset_repair.py | 13 +- 4 files changed, 149 insertions(+), 120 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index b8f368a2e6..6a248b0f8f 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -8,15 +8,14 @@ import math import frappe from frappe import _ from frappe.utils import ( - add_days, add_months, cint, date_diff, flt, get_datetime, get_last_day, - is_last_day_of_the_month, getdate, + is_last_day_of_the_month, month_diff, nowdate, today, @@ -28,13 +27,13 @@ from erpnext.assets.doctype.asset.depreciation import ( get_depreciation_accounts, get_disposal_account_and_cost_center, ) +from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - make_draft_asset_depreciation_schedules, - get_asset_depreciation_schedule_name, convert_draft_asset_depreciation_schedules_into_active, + get_asset_depreciation_schedule, + make_draft_asset_depreciation_schedules, update_draft_asset_depreciation_schedules, ) -from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account from erpnext.controllers.accounts_controller import AccountsController @@ -245,9 +244,7 @@ class Asset(AccountsController): return value_after_depreciation def get_from_date(self, finance_book): - asset_depr_schedule_name = get_asset_depreciation_schedule_name( - self.name, finance_book - ) + asset_depr_schedule_name = get_asset_depreciation_schedule(self.name, finance_book) if not asset_depr_schedule_name: return self.available_for_use_date @@ -358,7 +355,7 @@ class Asset(AccountsController): return depreciation_amount_for_last_row def get_depreciation_amount_for_first_row(self, finance_book): - asset_depr_schedule_name = get_asset_depreciation_schedule_name(self.name, finance_book) + asset_depr_schedule_name = get_asset_depreciation_schedule(self.name, finance_book) asset_depr_schedule = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) @@ -369,9 +366,7 @@ class Asset(AccountsController): def validate_expected_value_after_useful_life(self): for row in self.get("finance_books"): - asset_depr_schedule_name = get_asset_depreciation_schedule_name( - self.name, row.finance_book - ) + asset_depr_schedule_name = get_asset_depreciation_schedule(self.name, row.finance_book) if not asset_depr_schedule_name: return @@ -379,8 +374,7 @@ class Asset(AccountsController): asset_depr_schedule = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) accumulated_depreciation_after_full_schedule = [ - d.accumulated_depreciation_amount - for d in asset_depr_schedule.get("depreciation_schedule") + d.accumulated_depreciation_amount for d in asset_depr_schedule.get("depreciation_schedule") ] if accumulated_depreciation_after_full_schedule: @@ -430,9 +424,7 @@ class Asset(AccountsController): def delete_depreciation_entries(self): for row in self.get("finance_books"): - asset_depr_schedule_name = get_asset_depreciation_schedule_name( - self.name, row.finance_book - ) + asset_depr_schedule_name = get_asset_depreciation_schedule(self.name, row.finance_book) if not asset_depr_schedule_name: return diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index 97941706aa..49f167ef1c 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -10,6 +10,9 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( get_checks_for_pl_and_bs_accounts, ) from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry +from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( + make_temp_asset_depreciation_schedule, +) def post_depreciation_entries(date=None, commit=True): @@ -499,24 +502,27 @@ def get_disposal_account_and_cost_center(company): def get_value_after_depreciation_on_disposal_date(asset, disposal_date, finance_book=None): asset_doc = frappe.get_doc("Asset", asset) - if asset_doc.calculate_depreciation: - asset_doc.prepare_depreciation_data(getdate(disposal_date)) - - finance_book_id = 1 - if finance_book: - for fb in asset_doc.finance_books: - if fb.finance_book == finance_book: - finance_book_id = fb.idx - break - - asset_schedules = [ - sch for sch in asset_doc.schedules if cint(sch.finance_book_id) == finance_book_id - ] - accumulated_depr_amount = asset_schedules[-1].accumulated_depreciation_amount - - return flt( - flt(asset_doc.gross_purchase_amount) - accumulated_depr_amount, - asset_doc.precision("gross_purchase_amount"), - ) - else: + if not asset_doc.calculate_depreciation: return flt(asset_doc.value_after_depreciation) + + idx = 1 + if finance_book: + for d in asset.finance_books: + if d.finance_book == finance_book: + idx = d.idx + break + + row = asset_doc.finance_books[idx - 1] + + temp_asset_depreciation_schedule = make_temp_asset_depreciation_schedule( + asset_doc, row, getdate(disposal_date) + ) + + depr_schedule = temp_asset_depreciation_schedule.get("depreciation_schedule") + + accumulated_depr_amount = depr_schedule[-1].accumulated_depreciation_amount + + return flt( + flt(asset_doc.gross_purchase_amount) - accumulated_depr_amount, + asset_doc.precision("gross_purchase_amount"), + ) diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index ae3707b82f..9df4241b57 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -2,6 +2,7 @@ # For license information, please see license.txt import frappe +from frappe.model.document import Document from frappe.utils import ( add_days, add_months, @@ -9,9 +10,8 @@ from frappe.utils import ( date_diff, flt, get_last_day, - is_last_day_of_the_month + is_last_day_of_the_month, ) -from frappe.model.document import Document import erpnext @@ -20,37 +20,47 @@ class AssetDepreciationSchedule(Document): pass -def make_draft_asset_depreciation_schedules(asset): - for row in asset.get("finance_books"): +def make_draft_asset_depreciation_schedules(asset_doc, date_of_disposal=None, date_of_return=None): + for row in asset_doc.get("finance_books"): asset_depr_schedule = frappe.new_doc("Asset Depreciation Schedule") - prepare_draft_asset_depreciation_schedule_data(asset_depr_schedule, asset, row) - - -def update_draft_asset_depreciation_schedules(asset): - for row in asset.get("finance_books"): - asset_depr_schedule_name = get_asset_depreciation_schedule_name( - asset.name, row.finance_book + prepare_draft_asset_depreciation_schedule_data( + asset_depr_schedule, asset_doc, row, date_of_disposal, date_of_return ) + asset_depr_schedule.insert() + + +def update_draft_asset_depreciation_schedules( + asset_doc, date_of_disposal=None, date_of_return=None +): + for row in asset_doc.get("finance_books"): + asset_depr_schedule_name = get_asset_depreciation_schedule(asset_doc.name, row.finance_book) + if not asset_depr_schedule_name: return asset_depr_schedule = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) - prepare_draft_asset_depreciation_schedule_data(asset_depr_schedule, asset, row) + prepare_draft_asset_depreciation_schedule_data( + asset_depr_schedule, asset_doc, row, date_of_disposal, date_of_return + ) + + asset_depr_schedule.save() -def prepare_draft_asset_depreciation_schedule_data(asset_depr_schedule, asset, row): - set_draft_asset_depreciation_schedule_details(asset_depr_schedule, asset.name, row) - make_depreciation_schedule(asset_depr_schedule, asset, row) - set_accumulated_depreciation(asset_depr_schedule, asset, row) - - asset_depr_schedule.save() +def prepare_draft_asset_depreciation_schedule_data( + asset_depr_schedule, asset_doc, row, date_of_disposal, date_of_return +): + set_draft_asset_depreciation_schedule_details(asset_depr_schedule, asset_doc.name, row) + make_depreciation_schedule(asset_depr_schedule, asset_doc, row, date_of_disposal) + set_accumulated_depreciation( + asset_depr_schedule, asset_doc, row, date_of_disposal, date_of_return + ) -def set_draft_asset_depreciation_schedule_details(asset_depr_schedule, asset_name, row): - asset_depr_schedule.asset = asset_name +def set_draft_asset_depreciation_schedule_details(asset_depr_schedule, asset, row): + asset_depr_schedule.asset = asset asset_depr_schedule.finance_book = row.finance_book asset_depr_schedule.depreciation_method = row.depreciation_method asset_depr_schedule.total_number_of_depreciations = row.total_number_of_depreciations @@ -60,11 +70,9 @@ def set_draft_asset_depreciation_schedule_details(asset_depr_schedule, asset_nam asset_depr_schedule.status = "Draft" -def convert_draft_asset_depreciation_schedules_into_active(asset): - for row in asset.get("finance_books"): - asset_depr_schedule_name = get_asset_depreciation_schedule_name( - asset.name, row.finance_book - ) +def convert_draft_asset_depreciation_schedules_into_active(asset_doc): + for row in asset_doc.get("finance_books"): + asset_depr_schedule_name = get_asset_depreciation_schedule(asset_doc.name, row.finance_book) if not asset_depr_schedule_name: return @@ -77,50 +85,63 @@ def convert_draft_asset_depreciation_schedules_into_active(asset): def make_new_active_asset_depreciation_schedules_from_existing( - asset, date_of_disposal=None, date_of_return=None + asset_doc, date_of_disposal=None, date_of_return=None, notes=None ): - for row in asset.get("finance_books"): - old_asset_depr_schedule_name = get_asset_depreciation_schedule_name( - asset.name, row.finance_book - ) + for row in asset_doc.get("finance_books"): + old_asset_depr_schedule_name = get_asset_depreciation_schedule(asset_doc.name, row.finance_book) if not old_asset_depr_schedule_name: return old_asset_depr_schedule = frappe.get_doc( - "Asset Depreciation Schedule", - old_asset_depr_schedule_name + "Asset Depreciation Schedule", old_asset_depr_schedule_name ) asset_depr_schedule = frappe.copy_doc(old_asset_depr_schedule, ignore_no_copy=False) - make_depreciation_schedule(asset_depr_schedule, asset, row, date_of_disposal) - set_accumulated_depreciation(asset_depr_schedule, asset, row, date_of_disposal, date_of_return) + make_depreciation_schedule(asset_depr_schedule, asset_doc, row, date_of_disposal) + set_accumulated_depreciation( + asset_depr_schedule, asset_doc, row, date_of_disposal, date_of_return + ) - asset_depr_schedule.save() + asset_depr_schedule.notes = notes + + asset_depr_schedule.submit() -def make_depreciation_schedule(asset_depr_schedule, asset, row, date_of_disposal=None): +def make_temp_asset_depreciation_schedule( + asset_doc, row, date_of_disposal=None, date_of_return=None +): + asset_depr_schedule = frappe.new_doc("Asset Depreciation Schedule") + + prepare_draft_asset_depreciation_schedule_data( + asset_depr_schedule, asset_doc, row, date_of_disposal, date_of_return + ) + + return asset_depr_schedule + + +def get_asset_depreciation_schedule(asset, finance_book): + return frappe.db.get_value( + doctype="Asset Depreciation Schedule", + filters=[ + ["asset", "=", asset], + ["finance_book", "=", finance_book], + ["docstatus", "<", 2], + ], + ) + + +def make_depreciation_schedule(asset_depr_schedule, asset_doc, row, date_of_disposal): if row.depreciation_method != "Manual" and not asset_depr_schedule.get("depreciation_schedule"): asset_depr_schedule.depreciation_schedule = [] - if not asset.available_for_use_date: + if not asset_doc.available_for_use_date: return start = clear_depreciation_schedule(asset_depr_schedule) - _make_depreciation_schedule(asset_depr_schedule, asset, row, start, date_of_disposal) - - -def get_asset_depreciation_schedule_name(asset_name, finance_book): - return frappe.db.get_value( - doctype="Asset Depreciation Schedule", - filters=[ - ["asset", "=", asset_name], - ["finance_book", "=", finance_book], - ["docstatus", "<", 2], - ] - ) + _make_depreciation_schedule(asset_depr_schedule, asset_doc, row, start, date_of_disposal) def clear_depreciation_schedule(asset_depr_schedule): @@ -152,17 +173,17 @@ def clear_depreciation_schedule(asset_depr_schedule): return start -def _make_depreciation_schedule(asset_depr_schedule, asset, row, start, date_of_disposal): - asset.validate_asset_finance_books(row) +def _make_depreciation_schedule(asset_depr_schedule, asset_doc, row, start, date_of_disposal): + asset_doc.validate_asset_finance_books(row) - value_after_depreciation = asset._get_value_after_depreciation(row) + value_after_depreciation = asset_doc._get_value_after_depreciation(row) row.value_after_depreciation = value_after_depreciation number_of_pending_depreciations = cint(row.total_number_of_depreciations) - cint( - asset.number_of_depreciations_booked + asset_doc.number_of_depreciations_booked ) - has_pro_rata = asset.check_is_pro_rata(row) + has_pro_rata = asset_doc.check_is_pro_rata(row) if has_pro_rata: number_of_pending_depreciations += 1 @@ -174,12 +195,10 @@ def _make_depreciation_schedule(asset_depr_schedule, asset, row, start, date_of_ if skip_row: continue - depreciation_amount = get_depreciation_amount(asset, value_after_depreciation, row) + depreciation_amount = get_depreciation_amount(asset_doc, value_after_depreciation, row) if not has_pro_rata or n < cint(number_of_pending_depreciations) - 1: - schedule_date = add_months( - row.depreciation_start_date, n * cint(row.frequency_of_depreciation) - ) + schedule_date = add_months(row.depreciation_start_date, n * cint(row.frequency_of_depreciation)) if should_get_last_day: schedule_date = get_last_day(schedule_date) @@ -190,8 +209,8 @@ def _make_depreciation_schedule(asset_depr_schedule, asset, row, start, date_of_ # if asset is being sold or scrapped if date_of_disposal: - from_date = asset.get_from_date(row.finance_book) - depreciation_amount, days, months = asset.get_pro_rata_amt( + from_date = asset_doc.get_from_date(row.finance_book) + depreciation_amount, days, months = asset_doc.get_pro_rata_amt( row, depreciation_amount, from_date, date_of_disposal ) @@ -208,11 +227,11 @@ def _make_depreciation_schedule(asset_depr_schedule, asset, row, start, date_of_ break # For first row - if has_pro_rata and not asset.opening_accumulated_depreciation and n == 0: + if has_pro_rata and not asset_doc.opening_accumulated_depreciation and n == 0: from_date = add_days( - asset.available_for_use_date, -1 + asset_doc.available_for_use_date, -1 ) # needed to calc depr amount for available_for_use_date too - depreciation_amount, days, months = asset.get_pro_rata_amt( + depreciation_amount, days, months = asset_doc.get_pro_rata_amt( row, depreciation_amount, from_date, row.depreciation_start_date ) @@ -223,20 +242,20 @@ def _make_depreciation_schedule(asset_depr_schedule, asset, row, start, date_of_ # For last row elif has_pro_rata and n == cint(number_of_pending_depreciations) - 1: - if not asset.flags.increase_in_asset_life: + if not asset_doc.flags.increase_in_asset_life: # In case of increase_in_asset_life, the asset.to_date is already set on asset_repair submission - asset.to_date = add_months( - asset.available_for_use_date, - (n + asset.number_of_depreciations_booked) * cint(row.frequency_of_depreciation), + asset_doc.to_date = add_months( + asset_doc.available_for_use_date, + (n + asset_doc.number_of_depreciations_booked) * cint(row.frequency_of_depreciation), ) depreciation_amount_without_pro_rata = depreciation_amount - depreciation_amount, days, months = asset.get_pro_rata_amt( - row, depreciation_amount, schedule_date, asset.to_date + depreciation_amount, days, months = asset_doc.get_pro_rata_amt( + row, depreciation_amount, schedule_date, asset_doc.to_date ) - depreciation_amount = asset.get_adjusted_depreciation_amount( + depreciation_amount = asset_doc.get_adjusted_depreciation_amount( depreciation_amount_without_pro_rata, depreciation_amount, row.finance_book ) @@ -246,7 +265,9 @@ def _make_depreciation_schedule(asset_depr_schedule, asset, row, start, date_of_ if not depreciation_amount: continue - value_after_depreciation -= flt(depreciation_amount, asset.precision("gross_purchase_amount")) + value_after_depreciation -= flt( + depreciation_amount, asset_doc.precision("gross_purchase_amount") + ) # Adjust depreciation amount in the last period based on the expected value after useful life if row.expected_value_after_useful_life and ( @@ -271,19 +292,19 @@ def _make_depreciation_schedule(asset_depr_schedule, asset, row, start, date_of_ @erpnext.allow_regional -def get_depreciation_amount(asset, depreciable_value, row): +def get_depreciation_amount(asset_doc, depreciable_value, row): if row.depreciation_method in ("Straight Line", "Manual"): # if the Depreciation Schedule is being prepared for the first time - if not asset.flags.increase_in_asset_life: + if not asset_doc.flags.increase_in_asset_life: depreciation_amount = ( - flt(asset.gross_purchase_amount) - flt(row.expected_value_after_useful_life) + flt(asset_doc.gross_purchase_amount) - flt(row.expected_value_after_useful_life) ) / flt(row.total_number_of_depreciations) # if the Depreciation Schedule is being modified after Asset Repair else: depreciation_amount = ( flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life) - ) / (date_diff(asset.to_date, asset.available_for_use_date) / 365) + ) / (date_diff(asset_doc.to_date, asset_doc.available_for_use_date) / 365) else: depreciation_amount = flt(depreciable_value * (flt(row.rate_of_depreciation) / 100)) @@ -296,7 +317,7 @@ def add_depr_schedule_row( depreciation_amount, depreciation_method, finance_book, - finance_book_id + finance_book_id, ): asset_depr_schedule.append( "depreciation_schedule", @@ -312,14 +333,15 @@ def add_depr_schedule_row( def set_accumulated_depreciation( asset_depr_schedule, - asset, + asset_doc, row, date_of_disposal=None, date_of_return=None, - ignore_booked_entry=False + ignore_booked_entry=False, ): straight_line_idx = [ - d.idx for d in asset_depr_schedule.get("depreciation_schedule") + d.idx + for d in asset_depr_schedule.get("depreciation_schedule") if d.depreciation_method == "Straight Line" ] finance_books = [] @@ -329,8 +351,8 @@ def set_accumulated_depreciation( continue if int(d.finance_book_id) not in finance_books: - accumulated_depreciation = flt(asset.opening_accumulated_depreciation) - value_after_depreciation = flt(asset.get_value_after_depreciation(d.finance_book_id)) + accumulated_depreciation = flt(asset_doc.opening_accumulated_depreciation) + value_after_depreciation = flt(asset_doc.get_value_after_depreciation(d.finance_book_id)) finance_books.append(int(d.finance_book_id)) depreciation_amount = flt(d.depreciation_amount, d.precision("depreciation_amount")) diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py index d5913c5946..ca6225f94e 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/asset_repair.py @@ -8,6 +8,9 @@ from frappe.utils import add_months, cint, flt, getdate, time_diff_in_hours import erpnext from erpnext.accounts.general_ledger import make_gl_entries from erpnext.assets.doctype.asset.asset import get_asset_account +from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( + get_asset_depreciation_schedule, +) from erpnext.controllers.accounts_controller import AccountsController @@ -279,8 +282,11 @@ class AssetRepair(AccountsController): asset.number_of_depreciations_booked ) + asset_depr_schedule = get_asset_depreciation_schedule(asset.name, row.finance_book) + depr_schedule = asset_depr_schedule.get("depreciation_schedule") + # the Schedule Date in the final row of the old Depreciation Schedule - last_schedule_date = asset.schedules[len(asset.schedules) - 1].schedule_date + last_schedule_date = asset_depr_schedule[len(asset_depr_schedule) - 1].schedule_date # the Schedule Date in the final row of the new Depreciation Schedule asset.to_date = add_months(last_schedule_date, extra_months) @@ -310,8 +316,11 @@ class AssetRepair(AccountsController): asset.number_of_depreciations_booked ) + asset_depr_schedule = get_asset_depreciation_schedule(asset.name, row.finance_book) + depr_schedule = asset_depr_schedule.get("depreciation_schedule") + # the Schedule Date in the final row of the modified Depreciation Schedule - last_schedule_date = asset.schedules[len(asset.schedules) - 1].schedule_date + last_schedule_date = asset_depr_schedule[len(asset_depr_schedule) - 1].schedule_date # the Schedule Date in the final row of the original Depreciation Schedule asset.to_date = add_months(last_schedule_date, -extra_months) From 7db66b0916f5f37d110878adae462c060872bf3c Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Thu, 24 Nov 2022 13:02:48 +0530 Subject: [PATCH 09/49] chore: renaming some functions and variables, and partially refactoring AssetValueAdjustment --- erpnext/assets/doctype/asset/asset.py | 32 ++--- erpnext/assets/doctype/asset/depreciation.py | 4 +- .../asset_depreciation_schedule.py | 118 ++++++++++-------- .../asset_value_adjustment.py | 20 +-- 4 files changed, 96 insertions(+), 78 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 6a248b0f8f..e3e8a132c7 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -29,6 +29,7 @@ from erpnext.assets.doctype.asset.depreciation import ( ) from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( + cancel_asset_depreciation_schedules, convert_draft_asset_depreciation_schedules_into_active, get_asset_depreciation_schedule, make_draft_asset_depreciation_schedules, @@ -64,6 +65,7 @@ class Asset(AccountsController): self.validate_cancellation() self.cancel_movement_entries() self.delete_depreciation_entries() + cancel_asset_depreciation_schedules(self) self.set_status() self.ignore_linked_doctypes = ("GL Entry", "Stock Ledger Entry") make_reverse_gl_entries(voucher_type="Asset", voucher_no=self.name) @@ -244,14 +246,14 @@ class Asset(AccountsController): return value_after_depreciation def get_from_date(self, finance_book): - asset_depr_schedule_name = get_asset_depreciation_schedule(self.name, finance_book) + asset_depr_schedule = get_asset_depreciation_schedule(self.name, finance_book) - if not asset_depr_schedule_name: + if not asset_depr_schedule: return self.available_for_use_date - asset_depr_schedule = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) + asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule) - return asset_depr_schedule.get("depreciation_schedule")[-1].schedule_date + return asset_depr_schedule_doc.get("depreciation_schedule")[-1].schedule_date # if it returns True, depreciation_amount will not be equal for the first and last rows def check_is_pro_rata(self, row): @@ -355,26 +357,26 @@ class Asset(AccountsController): return depreciation_amount_for_last_row def get_depreciation_amount_for_first_row(self, finance_book): - asset_depr_schedule_name = get_asset_depreciation_schedule(self.name, finance_book) + asset_depr_schedule = get_asset_depreciation_schedule(self.name, finance_book) - asset_depr_schedule = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) + asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule) - return asset_depr_schedule.get("depreciation_schedule")[0].depreciation_amount + return asset_depr_schedule_doc.get("depreciation_schedule")[0].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"): - asset_depr_schedule_name = get_asset_depreciation_schedule(self.name, row.finance_book) + asset_depr_schedule = get_asset_depreciation_schedule(self.name, row.finance_book) - if not asset_depr_schedule_name: + if not asset_depr_schedule: return - asset_depr_schedule = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) + asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule) accumulated_depreciation_after_full_schedule = [ - d.accumulated_depreciation_amount for d in asset_depr_schedule.get("depreciation_schedule") + d.accumulated_depreciation_amount for d in asset_depr_schedule_doc.get("depreciation_schedule") ] if accumulated_depreciation_after_full_schedule: @@ -424,14 +426,14 @@ class Asset(AccountsController): def delete_depreciation_entries(self): for row in self.get("finance_books"): - asset_depr_schedule_name = get_asset_depreciation_schedule(self.name, row.finance_book) + asset_depr_schedule = get_asset_depreciation_schedule(self.name, row.finance_book) - if not asset_depr_schedule_name: + if not asset_depr_schedule: return - asset_depr_schedule = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) + asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule) - for d in asset_depr_schedule.get("depreciation_schedule"): + for d in asset_depr_schedule_doc.get("depreciation_schedule"): if d.journal_entry: frappe.get_doc("Journal Entry", d.journal_entry).cancel() d.db_set("journal_entry", None) diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index 49f167ef1c..664838dee6 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -11,7 +11,7 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( ) from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - make_temp_asset_depreciation_schedule, + get_temp_asset_depreciation_schedule_doc, ) @@ -514,7 +514,7 @@ def get_value_after_depreciation_on_disposal_date(asset, disposal_date, finance_ row = asset_doc.finance_books[idx - 1] - temp_asset_depreciation_schedule = make_temp_asset_depreciation_schedule( + temp_asset_depreciation_schedule = get_temp_asset_depreciation_schedule_doc( asset_doc, row, getdate(disposal_date) ) diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 9df4241b57..144b94dfbc 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -22,52 +22,52 @@ class AssetDepreciationSchedule(Document): def make_draft_asset_depreciation_schedules(asset_doc, date_of_disposal=None, date_of_return=None): for row in asset_doc.get("finance_books"): - asset_depr_schedule = frappe.new_doc("Asset Depreciation Schedule") + asset_depr_schedule_doc = frappe.new_doc("Asset Depreciation Schedule") prepare_draft_asset_depreciation_schedule_data( - asset_depr_schedule, asset_doc, row, date_of_disposal, date_of_return + asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return ) - asset_depr_schedule.insert() + asset_depr_schedule_doc.insert() def update_draft_asset_depreciation_schedules( asset_doc, date_of_disposal=None, date_of_return=None ): for row in asset_doc.get("finance_books"): - asset_depr_schedule_name = get_asset_depreciation_schedule(asset_doc.name, row.finance_book) + asset_depr_schedule = get_asset_depreciation_schedule(asset_doc.name, row.finance_book) - if not asset_depr_schedule_name: + if not asset_depr_schedule: return - asset_depr_schedule = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) + asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule) prepare_draft_asset_depreciation_schedule_data( - asset_depr_schedule, asset_doc, row, date_of_disposal, date_of_return + asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return ) - asset_depr_schedule.save() + asset_depr_schedule_doc.save() def prepare_draft_asset_depreciation_schedule_data( - asset_depr_schedule, asset_doc, row, date_of_disposal, date_of_return + asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return ): - set_draft_asset_depreciation_schedule_details(asset_depr_schedule, asset_doc.name, row) - make_depreciation_schedule(asset_depr_schedule, asset_doc, row, date_of_disposal) + set_draft_asset_depreciation_schedule_details(asset_depr_schedule_doc, asset_doc.name, row) + make_depreciation_schedule(asset_depr_schedule_doc, asset_doc, row, date_of_disposal) set_accumulated_depreciation( - asset_depr_schedule, asset_doc, row, date_of_disposal, date_of_return + asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return ) -def set_draft_asset_depreciation_schedule_details(asset_depr_schedule, asset, row): - asset_depr_schedule.asset = asset - asset_depr_schedule.finance_book = row.finance_book - asset_depr_schedule.depreciation_method = row.depreciation_method - asset_depr_schedule.total_number_of_depreciations = row.total_number_of_depreciations - asset_depr_schedule.frequency_of_depreciation = row.frequency_of_depreciation - asset_depr_schedule.rate_of_depreciation = row.rate_of_depreciation - asset_depr_schedule.expected_value_after_useful_life = row.expected_value_after_useful_life - asset_depr_schedule.status = "Draft" +def set_draft_asset_depreciation_schedule_details(asset_depr_schedule_doc, asset, row): + asset_depr_schedule_doc.asset = asset + asset_depr_schedule_doc.finance_book = row.finance_book + asset_depr_schedule_doc.depreciation_method = row.depreciation_method + asset_depr_schedule_doc.total_number_of_depreciations = row.total_number_of_depreciations + asset_depr_schedule_doc.frequency_of_depreciation = row.frequency_of_depreciation + asset_depr_schedule_doc.rate_of_depreciation = row.rate_of_depreciation + asset_depr_schedule_doc.expected_value_after_useful_life = row.expected_value_after_useful_life + asset_depr_schedule_doc.status = "Draft" def convert_draft_asset_depreciation_schedules_into_active(asset_doc): @@ -84,41 +84,55 @@ def convert_draft_asset_depreciation_schedules_into_active(asset_doc): asset_depr_schedule.submit() -def make_new_active_asset_depreciation_schedules_from_existing( +def make_new_active_asset_depreciation_schedules_and_cancel_old_ones( asset_doc, date_of_disposal=None, date_of_return=None, notes=None ): for row in asset_doc.get("finance_books"): - old_asset_depr_schedule_name = get_asset_depreciation_schedule(asset_doc.name, row.finance_book) + old_asset_depr_schedule = get_asset_depreciation_schedule(asset_doc.name, row.finance_book) - if not old_asset_depr_schedule_name: + if not old_asset_depr_schedule: return - old_asset_depr_schedule = frappe.get_doc( - "Asset Depreciation Schedule", old_asset_depr_schedule_name + old_asset_depr_schedule_doc = frappe.get_doc( + "Asset Depreciation Schedule", old_asset_depr_schedule ) - asset_depr_schedule = frappe.copy_doc(old_asset_depr_schedule, ignore_no_copy=False) + asset_depr_schedule_doc = frappe.copy_doc(old_asset_depr_schedule_doc, ignore_no_copy=False) - make_depreciation_schedule(asset_depr_schedule, asset_doc, row, date_of_disposal) + old_asset_depr_schedule.cancel() + + make_depreciation_schedule(asset_depr_schedule_doc, asset_doc, row, date_of_disposal) set_accumulated_depreciation( - asset_depr_schedule, asset_doc, row, date_of_disposal, date_of_return + asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return ) - asset_depr_schedule.notes = notes + asset_depr_schedule_doc.notes = notes - asset_depr_schedule.submit() + asset_depr_schedule_doc.submit() -def make_temp_asset_depreciation_schedule( +def get_temp_asset_depreciation_schedule_doc( asset_doc, row, date_of_disposal=None, date_of_return=None ): - asset_depr_schedule = frappe.new_doc("Asset Depreciation Schedule") + asset_depr_schedule_doc = frappe.new_doc("Asset Depreciation Schedule") prepare_draft_asset_depreciation_schedule_data( - asset_depr_schedule, asset_doc, row, date_of_disposal, date_of_return + asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return ) - return asset_depr_schedule + return asset_depr_schedule_doc + + +def cancel_asset_depreciation_schedules(asset_doc): + for row in asset_doc.get("finance_books"): + asset_depr_schedule = get_asset_depreciation_schedule(asset_doc.name, row.finance_book) + + if not asset_depr_schedule: + return + + asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule) + + asset_depr_schedule_doc.cancel() def get_asset_depreciation_schedule(asset, finance_book): @@ -132,24 +146,26 @@ def get_asset_depreciation_schedule(asset, finance_book): ) -def make_depreciation_schedule(asset_depr_schedule, asset_doc, row, date_of_disposal): - if row.depreciation_method != "Manual" and not asset_depr_schedule.get("depreciation_schedule"): - asset_depr_schedule.depreciation_schedule = [] +def make_depreciation_schedule(asset_depr_schedule_doc, asset_doc, row, date_of_disposal): + if row.depreciation_method != "Manual" and not asset_depr_schedule_doc.get( + "depreciation_schedule" + ): + asset_depr_schedule_doc.depreciation_schedule = [] if not asset_doc.available_for_use_date: return - start = clear_depreciation_schedule(asset_depr_schedule) + start = clear_depreciation_schedule(asset_depr_schedule_doc) - _make_depreciation_schedule(asset_depr_schedule, asset_doc, row, start, date_of_disposal) + _make_depreciation_schedule(asset_depr_schedule_doc, asset_doc, row, start, date_of_disposal) -def clear_depreciation_schedule(asset_depr_schedule): +def clear_depreciation_schedule(asset_depr_schedule_doc): start = [] num_of_depreciations_completed = 0 depr_schedule = [] - for schedule in asset_depr_schedule.get("depreciation_schedule"): + for schedule in asset_depr_schedule_doc.get("depreciation_schedule"): if len(start) != 0: break @@ -168,12 +184,12 @@ def clear_depreciation_schedule(asset_depr_schedule): if start == []: start = [0] else: - asset_depr_schedule.depreciation_schedule = depr_schedule + asset_depr_schedule_doc.depreciation_schedule = depr_schedule return start -def _make_depreciation_schedule(asset_depr_schedule, asset_doc, row, start, date_of_disposal): +def _make_depreciation_schedule(asset_depr_schedule_doc, asset_doc, row, start, date_of_disposal): asset_doc.validate_asset_finance_books(row) value_after_depreciation = asset_doc._get_value_after_depreciation(row) @@ -216,7 +232,7 @@ def _make_depreciation_schedule(asset_depr_schedule, asset_doc, row, start, date if depreciation_amount > 0: add_depr_schedule_row( - asset_depr_schedule, + asset_depr_schedule_doc, date_of_disposal, depreciation_amount, row.depreciation_method, @@ -282,7 +298,7 @@ def _make_depreciation_schedule(asset_depr_schedule, asset_doc, row, start, date if depreciation_amount > 0: add_depr_schedule_row( - asset_depr_schedule, + asset_depr_schedule_doc, schedule_date, depreciation_amount, row.depreciation_method, @@ -312,14 +328,14 @@ def get_depreciation_amount(asset_doc, depreciable_value, row): def add_depr_schedule_row( - asset_depr_schedule, + asset_depr_schedule_doc, schedule_date, depreciation_amount, depreciation_method, finance_book, finance_book_id, ): - asset_depr_schedule.append( + asset_depr_schedule_doc.append( "depreciation_schedule", { "schedule_date": schedule_date, @@ -332,7 +348,7 @@ def add_depr_schedule_row( def set_accumulated_depreciation( - asset_depr_schedule, + asset_depr_schedule_doc, asset_doc, row, date_of_disposal=None, @@ -341,12 +357,12 @@ def set_accumulated_depreciation( ): straight_line_idx = [ d.idx - for d in asset_depr_schedule.get("depreciation_schedule") + for d in asset_depr_schedule_doc.get("depreciation_schedule") if d.depreciation_method == "Straight Line" ] finance_books = [] - for i, d in enumerate(asset_depr_schedule.get("depreciation_schedule")): + for i, d in enumerate(asset_depr_schedule_doc.get("depreciation_schedule")): if ignore_booked_entry and d.journal_entry: continue 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 ae6e2b426e..e61c8f7e83 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py @@ -10,10 +10,11 @@ from frappe.utils import cint, date_diff, flt, formatdate, getdate from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( get_checks_for_pl_and_bs_accounts, ) -from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_depreciation_amount -) from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts +from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( + get_asset_depreciation_schedule, + get_depreciation_amount, +) class AssetValueAdjustment(Document): @@ -114,20 +115,19 @@ class AssetValueAdjustment(Document): for d in asset.finance_books: d.value_after_depreciation = asset_value + asset_depr_schedule = get_asset_depreciation_schedule(asset.name, d.finance_book) + depr_schedule = asset_depr_schedule.get("depreciation_schedule") + if d.depreciation_method in ("Straight Line", "Manual"): - end_date = max(s.schedule_date for s in asset.schedules if cint(s.finance_book_id) == d.idx) + end_date = max(s.schedule_date for s in depr_schedule) total_days = date_diff(end_date, self.date) rate_per_day = flt(d.value_after_depreciation) / flt(total_days) from_date = self.date else: - no_of_depreciations = len( - [ - s.name for s in asset.schedules if (cint(s.finance_book_id) == d.idx and not s.journal_entry) - ] - ) + no_of_depreciations = len([s.name for s in depr_schedule if not s.journal_entry]) value_after_depreciation = d.value_after_depreciation - for data in asset.schedules: + for data in depr_schedule: if cint(data.finance_book_id) == d.idx and not data.journal_entry: if d.depreciation_method in ("Straight Line", "Manual"): days = date_diff(data.schedule_date, from_date) From f35b19eac3db13bb7a29ea8d6b2cbb0f03de1001 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Thu, 24 Nov 2022 15:33:21 +0530 Subject: [PATCH 10/49] chore: renaming functions and variables again, and continuing refactoring AssetValueAdjustment --- erpnext/assets/doctype/asset/asset.py | 33 ++++---- erpnext/assets/doctype/asset/depreciation.py | 10 +-- erpnext/assets/doctype/asset/test_asset.py | 16 ++-- .../asset_depreciation_schedule.py | 76 ++++++++++--------- .../doctype/asset_repair/asset_repair.py | 12 ++- .../asset_value_adjustment.py | 34 ++++++--- 6 files changed, 99 insertions(+), 82 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index e3e8a132c7..39557849ec 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -29,11 +29,12 @@ from erpnext.assets.doctype.asset.depreciation import ( ) from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - cancel_asset_depreciation_schedules, - convert_draft_asset_depreciation_schedules_into_active, - get_asset_depreciation_schedule, - make_draft_asset_depreciation_schedules, - update_draft_asset_depreciation_schedules, + cancel_asset_depr_schedules, + convert_draft_asset_depr_schedules_into_active, + get_asset_depr_schedule, + get_depr_schedule_from_asset_depr_schedule_of_asset, + make_draft_asset_depr_schedules, + update_draft_asset_depr_schedules, ) from erpnext.controllers.accounts_controller import AccountsController @@ -47,7 +48,7 @@ class Asset(AccountsController): self.set_missing_values() if not self.split_from: self.prepare_depreciation_data() - update_draft_asset_depreciation_schedules(self) + update_draft_asset_depr_schedules(self) self.validate_gross_and_purchase_amount() self.validate_expected_value_after_useful_life() @@ -59,13 +60,13 @@ class Asset(AccountsController): self.make_asset_movement() if not self.booked_fixed_asset and self.validate_make_gl_entry(): self.make_gl_entries() - convert_draft_asset_depreciation_schedules_into_active(self) + convert_draft_asset_depr_schedules_into_active(self) def on_cancel(self): self.validate_cancellation() self.cancel_movement_entries() self.delete_depreciation_entries() - cancel_asset_depreciation_schedules(self) + cancel_asset_depr_schedules(self) self.set_status() self.ignore_linked_doctypes = ("GL Entry", "Stock Ledger Entry") make_reverse_gl_entries(voucher_type="Asset", voucher_no=self.name) @@ -73,7 +74,7 @@ class Asset(AccountsController): def after_insert(self): if not self.split_from: - make_draft_asset_depreciation_schedules(self) + make_draft_asset_depr_schedules(self) def validate_asset_and_reference(self): if self.purchase_invoice or self.purchase_receipt: @@ -246,7 +247,7 @@ class Asset(AccountsController): return value_after_depreciation def get_from_date(self, finance_book): - asset_depr_schedule = get_asset_depreciation_schedule(self.name, finance_book) + asset_depr_schedule = get_asset_depr_schedule(self.name, finance_book) if not asset_depr_schedule: return self.available_for_use_date @@ -357,18 +358,16 @@ class Asset(AccountsController): return depreciation_amount_for_last_row def get_depreciation_amount_for_first_row(self, finance_book): - asset_depr_schedule = get_asset_depreciation_schedule(self.name, finance_book) - - asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule) - - return asset_depr_schedule_doc.get("depreciation_schedule")[0].depreciation_amount + return get_depr_schedule_from_asset_depr_schedule_of_asset(self.name, finance_book)[ + 0 + ].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"): - asset_depr_schedule = get_asset_depreciation_schedule(self.name, row.finance_book) + asset_depr_schedule = get_asset_depr_schedule(self.name, row.finance_book) if not asset_depr_schedule: return @@ -426,7 +425,7 @@ class Asset(AccountsController): def delete_depreciation_entries(self): for row in self.get("finance_books"): - asset_depr_schedule = get_asset_depreciation_schedule(self.name, row.finance_book) + asset_depr_schedule = get_asset_depr_schedule(self.name, row.finance_book) if not asset_depr_schedule: return diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index 664838dee6..39ebc8d664 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -11,7 +11,7 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( ) from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_temp_asset_depreciation_schedule_doc, + get_temp_asset_depr_schedule_doc, ) @@ -514,13 +514,13 @@ def get_value_after_depreciation_on_disposal_date(asset, disposal_date, finance_ row = asset_doc.finance_books[idx - 1] - temp_asset_depreciation_schedule = get_temp_asset_depreciation_schedule_doc( + temp_asset_depreciation_schedule = get_temp_asset_depr_schedule_doc( asset_doc, row, getdate(disposal_date) ) - depr_schedule = temp_asset_depreciation_schedule.get("depreciation_schedule") - - accumulated_depr_amount = depr_schedule[-1].accumulated_depreciation_amount + accumulated_depr_amount = temp_asset_depreciation_schedule.get("depreciation_schedule")[ + -1 + ].accumulated_depreciation_amount return flt( flt(asset_doc.gross_purchase_amount) - accumulated_depr_amount, diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index e25d890ad0..5ef81238af 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -882,7 +882,7 @@ class TestDepreciationBasics(AssetSetup): """Tests if get_depreciation_amount() returns the right value.""" from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_depreciation_amount + get_depreciation_amount, ) asset = create_asset(item_code="Macbook Pro", available_for_use_date="2019-12-31") @@ -902,8 +902,8 @@ class TestDepreciationBasics(AssetSetup): depreciation_amount = get_depreciation_amount(asset, 100000, asset.finance_books[0]) self.assertEqual(depreciation_amount, 30000) - def test_make_depreciation_schedule(self): - """Tests if make_depreciation_schedule() returns the right values.""" + def test_make_depr_schedule(self): + """Tests if make_depr_schedule() returns the right values.""" asset = create_asset( item_code="Macbook Pro", @@ -1194,8 +1194,8 @@ class TestDepreciationBasics(AssetSetup): depr_expense_account.parent_account = "Expenses - _TC" depr_expense_account.save() - def test_clear_depreciation_schedule(self): - """Tests if clear_depreciation_schedule() works as expected.""" + def test_clear_depr_schedule(self): + """Tests if clear_depr_schedule() works as expected.""" asset = create_asset( item_code="Macbook Pro", @@ -1211,11 +1211,11 @@ class TestDepreciationBasics(AssetSetup): post_depreciation_entries(date="2021-06-01") asset.load_from_db() - asset.clear_depreciation_schedule() + asset.clear_depr_schedule() self.assertEqual(len(asset.schedules), 1) - def test_clear_depreciation_schedule_for_multiple_finance_books(self): + def test_clear_depr_schedule_for_multiple_finance_books(self): asset = create_asset(item_code="Macbook Pro", available_for_use_date="2019-12-31", do_not_save=1) asset.calculate_depreciation = 1 @@ -1254,7 +1254,7 @@ class TestDepreciationBasics(AssetSetup): post_depreciation_entries(date="2020-04-01") asset.load_from_db() - asset.clear_depreciation_schedule() + asset.clear_depr_schedule() self.assertEqual(len(asset.schedules), 6) diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 144b94dfbc..43f7b4adf7 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -20,46 +20,44 @@ class AssetDepreciationSchedule(Document): pass -def make_draft_asset_depreciation_schedules(asset_doc, date_of_disposal=None, date_of_return=None): +def make_draft_asset_depr_schedules(asset_doc, date_of_disposal=None, date_of_return=None): for row in asset_doc.get("finance_books"): asset_depr_schedule_doc = frappe.new_doc("Asset Depreciation Schedule") - prepare_draft_asset_depreciation_schedule_data( + prepare_draft_asset_depr_schedule_data( asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return ) asset_depr_schedule_doc.insert() -def update_draft_asset_depreciation_schedules( - asset_doc, date_of_disposal=None, date_of_return=None -): +def update_draft_asset_depr_schedules(asset_doc, date_of_disposal=None, date_of_return=None): for row in asset_doc.get("finance_books"): - asset_depr_schedule = get_asset_depreciation_schedule(asset_doc.name, row.finance_book) + asset_depr_schedule = get_asset_depr_schedule(asset_doc.name, row.finance_book) if not asset_depr_schedule: return asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule) - prepare_draft_asset_depreciation_schedule_data( + prepare_draft_asset_depr_schedule_data( asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return ) asset_depr_schedule_doc.save() -def prepare_draft_asset_depreciation_schedule_data( +def prepare_draft_asset_depr_schedule_data( asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return ): - set_draft_asset_depreciation_schedule_details(asset_depr_schedule_doc, asset_doc.name, row) - make_depreciation_schedule(asset_depr_schedule_doc, asset_doc, row, date_of_disposal) + set_draft_asset_depr_schedule_details(asset_depr_schedule_doc, asset_doc.name, row) + make_depr_schedule(asset_depr_schedule_doc, asset_doc, row, date_of_disposal) set_accumulated_depreciation( asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return ) -def set_draft_asset_depreciation_schedule_details(asset_depr_schedule_doc, asset, row): +def set_draft_asset_depr_schedule_details(asset_depr_schedule_doc, asset, row): asset_depr_schedule_doc.asset = asset asset_depr_schedule_doc.finance_book = row.finance_book asset_depr_schedule_doc.depreciation_method = row.depreciation_method @@ -70,9 +68,9 @@ def set_draft_asset_depreciation_schedule_details(asset_depr_schedule_doc, asset asset_depr_schedule_doc.status = "Draft" -def convert_draft_asset_depreciation_schedules_into_active(asset_doc): +def convert_draft_asset_depr_schedules_into_active(asset_doc): for row in asset_doc.get("finance_books"): - asset_depr_schedule_name = get_asset_depreciation_schedule(asset_doc.name, row.finance_book) + asset_depr_schedule_name = get_asset_depr_schedule(asset_doc.name, row.finance_book) if not asset_depr_schedule_name: return @@ -84,48 +82,48 @@ def convert_draft_asset_depreciation_schedules_into_active(asset_doc): asset_depr_schedule.submit() -def make_new_active_asset_depreciation_schedules_and_cancel_old_ones( +def make_new_active_asset_depr_schedules_and_cancel_current_ones( asset_doc, date_of_disposal=None, date_of_return=None, notes=None ): for row in asset_doc.get("finance_books"): - old_asset_depr_schedule = get_asset_depreciation_schedule(asset_doc.name, row.finance_book) + current_asset_depr_schedule = get_asset_depr_schedule(asset_doc.name, row.finance_book) - if not old_asset_depr_schedule: + if not current_asset_depr_schedule: return - old_asset_depr_schedule_doc = frappe.get_doc( - "Asset Depreciation Schedule", old_asset_depr_schedule + current_asset_depr_schedule_doc = frappe.get_doc( + "Asset Depreciation Schedule", current_asset_depr_schedule ) - asset_depr_schedule_doc = frappe.copy_doc(old_asset_depr_schedule_doc, ignore_no_copy=False) + new_asset_depr_schedule_doc = frappe.copy_doc( + current_asset_depr_schedule_doc, ignore_no_copy=False + ) - old_asset_depr_schedule.cancel() + current_asset_depr_schedule_doc.cancel() - make_depreciation_schedule(asset_depr_schedule_doc, asset_doc, row, date_of_disposal) + make_depr_schedule(new_asset_depr_schedule_doc, asset_doc, row, date_of_disposal) set_accumulated_depreciation( - asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return + new_asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return ) - asset_depr_schedule_doc.notes = notes + new_asset_depr_schedule_doc.notes = notes - asset_depr_schedule_doc.submit() + new_asset_depr_schedule_doc.submit() -def get_temp_asset_depreciation_schedule_doc( - asset_doc, row, date_of_disposal=None, date_of_return=None -): +def get_temp_asset_depr_schedule_doc(asset_doc, row, date_of_disposal=None, date_of_return=None): asset_depr_schedule_doc = frappe.new_doc("Asset Depreciation Schedule") - prepare_draft_asset_depreciation_schedule_data( + prepare_draft_asset_depr_schedule_data( asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return ) return asset_depr_schedule_doc -def cancel_asset_depreciation_schedules(asset_doc): +def cancel_asset_depr_schedules(asset_doc): for row in asset_doc.get("finance_books"): - asset_depr_schedule = get_asset_depreciation_schedule(asset_doc.name, row.finance_book) + asset_depr_schedule = get_asset_depr_schedule(asset_doc.name, row.finance_book) if not asset_depr_schedule: return @@ -135,7 +133,7 @@ def cancel_asset_depreciation_schedules(asset_doc): asset_depr_schedule_doc.cancel() -def get_asset_depreciation_schedule(asset, finance_book): +def get_asset_depr_schedule(asset, finance_book): return frappe.db.get_value( doctype="Asset Depreciation Schedule", filters=[ @@ -146,7 +144,13 @@ def get_asset_depreciation_schedule(asset, finance_book): ) -def make_depreciation_schedule(asset_depr_schedule_doc, asset_doc, row, date_of_disposal): +def get_depr_schedule_from_asset_depr_schedule_of_asset(asset, finance_book): + asset_depr_schedule = get_asset_depr_schedule(asset, finance_book) + asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule) + return asset_depr_schedule_doc.get("depreciation_schedule") + + +def make_depr_schedule(asset_depr_schedule_doc, asset_doc, row, date_of_disposal): if row.depreciation_method != "Manual" and not asset_depr_schedule_doc.get( "depreciation_schedule" ): @@ -155,12 +159,12 @@ def make_depreciation_schedule(asset_depr_schedule_doc, asset_doc, row, date_of_ if not asset_doc.available_for_use_date: return - start = clear_depreciation_schedule(asset_depr_schedule_doc) + start = clear_depr_schedule(asset_depr_schedule_doc) - _make_depreciation_schedule(asset_depr_schedule_doc, asset_doc, row, start, date_of_disposal) + _make_depr_schedule(asset_depr_schedule_doc, asset_doc, row, start, date_of_disposal) -def clear_depreciation_schedule(asset_depr_schedule_doc): +def clear_depr_schedule(asset_depr_schedule_doc): start = [] num_of_depreciations_completed = 0 depr_schedule = [] @@ -189,7 +193,7 @@ def clear_depreciation_schedule(asset_depr_schedule_doc): return start -def _make_depreciation_schedule(asset_depr_schedule_doc, asset_doc, row, start, date_of_disposal): +def _make_depr_schedule(asset_depr_schedule_doc, asset_doc, row, start, date_of_disposal): asset_doc.validate_asset_finance_books(row) value_after_depreciation = asset_doc._get_value_after_depreciation(row) diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py index ca6225f94e..962e7fb58d 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/asset_repair.py @@ -9,7 +9,7 @@ import erpnext from erpnext.accounts.general_ledger import make_gl_entries from erpnext.assets.doctype.asset.asset import get_asset_account from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_asset_depreciation_schedule, + get_depr_schedule_from_asset_depr_schedule_of_asset, ) from erpnext.controllers.accounts_controller import AccountsController @@ -282,11 +282,10 @@ class AssetRepair(AccountsController): asset.number_of_depreciations_booked ) - asset_depr_schedule = get_asset_depreciation_schedule(asset.name, row.finance_book) - depr_schedule = asset_depr_schedule.get("depreciation_schedule") + depr_schedule = get_depr_schedule_from_asset_depr_schedule_of_asset(asset.name, row.finance_book) # the Schedule Date in the final row of the old Depreciation Schedule - last_schedule_date = asset_depr_schedule[len(asset_depr_schedule) - 1].schedule_date + last_schedule_date = depr_schedule[len(depr_schedule) - 1].schedule_date # the Schedule Date in the final row of the new Depreciation Schedule asset.to_date = add_months(last_schedule_date, extra_months) @@ -316,11 +315,10 @@ class AssetRepair(AccountsController): asset.number_of_depreciations_booked ) - asset_depr_schedule = get_asset_depreciation_schedule(asset.name, row.finance_book) - depr_schedule = asset_depr_schedule.get("depreciation_schedule") + depr_schedule = get_depr_schedule_from_asset_depr_schedule_of_asset(asset.name, row.finance_book) # the Schedule Date in the final row of the modified Depreciation Schedule - last_schedule_date = asset_depr_schedule[len(asset_depr_schedule) - 1].schedule_date + last_schedule_date = depr_schedule[len(depr_schedule) - 1].schedule_date # the Schedule Date in the final row of the original Depreciation Schedule asset.to_date = add_months(last_schedule_date, -extra_months) 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 e61c8f7e83..bba61e646e 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py @@ -5,15 +5,16 @@ import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import cint, date_diff, flt, formatdate, getdate +from frappe.utils import date_diff, flt, formatdate, getdate from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( get_checks_for_pl_and_bs_accounts, ) from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_asset_depreciation_schedule, + get_asset_depr_schedule, get_depreciation_amount, + set_accumulated_depreciation, ) @@ -115,8 +116,17 @@ class AssetValueAdjustment(Document): for d in asset.finance_books: d.value_after_depreciation = asset_value - asset_depr_schedule = get_asset_depreciation_schedule(asset.name, d.finance_book) - depr_schedule = asset_depr_schedule.get("depreciation_schedule") + current_asset_depr_schedule = get_asset_depr_schedule(asset.name, d.finance_book) + + current_asset_depr_schedule_doc = frappe.get_doc( + "Asset Depreciation Schedule", current_asset_depr_schedule + ) + + new_asset_depr_schedule_doc = frappe.copy_doc( + current_asset_depr_schedule_doc, ignore_no_copy=False + ) + + depr_schedule = new_asset_depr_schedule_doc.get("depreciation_schedule") if d.depreciation_method in ("Straight Line", "Manual"): end_date = max(s.schedule_date for s in depr_schedule) @@ -128,7 +138,7 @@ class AssetValueAdjustment(Document): value_after_depreciation = d.value_after_depreciation for data in depr_schedule: - if cint(data.finance_book_id) == d.idx and not data.journal_entry: + if not data.journal_entry: if d.depreciation_method in ("Straight Line", "Manual"): days = date_diff(data.schedule_date, from_date) depreciation_amount = days * rate_per_day @@ -142,10 +152,16 @@ class AssetValueAdjustment(Document): d.db_update() - asset.set_accumulated_depreciation(ignore_booked_entry=True) - for asset_data in asset.schedules: - if not asset_data.journal_entry: - asset_data.db_update() + set_accumulated_depreciation(new_asset_depr_schedule_doc, asset, d, ignore_booked_entry=True) + for asset_data in depr_schedule: + if not asset_data.journal_entry: + asset_data.db_update() + + current_asset_depr_schedule_doc.cancel() + + new_asset_depr_schedule_doc.notes = "Asset value adjustment" + + new_asset_depr_schedule_doc.submit() @frappe.whitelist() From de17367a367681ebf124fccadaf184dbb523ee7d Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Thu, 24 Nov 2022 16:16:36 +0530 Subject: [PATCH 11/49] chore: finish refactoring asset_value_adjustment --- .../asset_value_adjustment/asset_value_adjustment.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) 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 bba61e646e..b6c4a3d210 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py @@ -117,7 +117,6 @@ class AssetValueAdjustment(Document): d.value_after_depreciation = asset_value current_asset_depr_schedule = get_asset_depr_schedule(asset.name, d.finance_book) - current_asset_depr_schedule_doc = frappe.get_doc( "Asset Depreciation Schedule", current_asset_depr_schedule ) @@ -125,6 +124,10 @@ class AssetValueAdjustment(Document): new_asset_depr_schedule_doc = frappe.copy_doc( current_asset_depr_schedule_doc, ignore_no_copy=False ) + new_asset_depr_schedule_doc.notes = "Asset value adjustment" + + current_asset_depr_schedule_doc.cancel() + new_asset_depr_schedule_doc.insert() depr_schedule = new_asset_depr_schedule_doc.get("depreciation_schedule") @@ -157,10 +160,6 @@ class AssetValueAdjustment(Document): if not asset_data.journal_entry: asset_data.db_update() - current_asset_depr_schedule_doc.cancel() - - new_asset_depr_schedule_doc.notes = "Asset value adjustment" - new_asset_depr_schedule_doc.submit() From 4e63ba3ac6cfa30304a57de05c3bd733d07ec4ff Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Thu, 24 Nov 2022 17:39:11 +0530 Subject: [PATCH 12/49] chore: refactor schedules in journal_entry --- .../doctype/journal_entry/journal_entry.py | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index de012b28ec..90fbd55cff 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -6,7 +6,7 @@ import json import frappe from frappe import _, msgprint, scrub -from frappe.utils import cint, cstr, flt, fmt_money, formatdate, get_link_to_form, nowdate +from frappe.utils import cstr, flt, fmt_money, formatdate, get_link_to_form, nowdate import erpnext from erpnext.accounts.deferred_revenue import get_deferred_booking_accounts @@ -23,6 +23,9 @@ from erpnext.accounts.utils import ( get_stock_accounts, get_stock_and_account_balance, ) +from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( + get_depr_schedule_from_asset_depr_schedule_of_asset, +) from erpnext.controllers.accounts_controller import AccountsController @@ -286,16 +289,18 @@ class JournalEntry(AccountsController): for d in self.get("accounts"): if d.reference_type == "Asset" and 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) + for row in asset.get("finance_books"): + depr_schedule = get_depr_schedule_from_asset_depr_schedule_of_asset( + asset.name, row.finance_book + ) + for s in depr_schedule: + 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() + row.value_after_depreciation += s.depreciation_amount + row.db_update() - asset.set_status() + asset.set_status() def unlink_inter_company_jv(self): if ( From 7d09440579da5865f8b6832829527b3aeab92f85 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Fri, 25 Nov 2022 16:49:44 +0530 Subject: [PATCH 13/49] chore: more refactoring --- .../doctype/sales_invoice/sales_invoice.py | 3 +- erpnext/assets/doctype/asset/asset.js | 25 --------- erpnext/assets/doctype/asset/asset.json | 17 +----- erpnext/assets/doctype/asset/asset.py | 24 +++++---- erpnext/assets/doctype/asset/depreciation.py | 53 +++++++++++-------- .../asset_capitalization.py | 3 +- .../asset_depreciation_schedule.js | 25 +++++++-- .../asset_depreciation_schedule.json | 11 +++- .../asset_depreciation_schedule.py | 47 ++++++++-------- .../asset_value_adjustment.py | 6 +-- 10 files changed, 108 insertions(+), 106 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 62cf0dcfeb..a99e92d9e0 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1189,8 +1189,7 @@ class SalesInvoice(SellingController): else: if asset.calculate_depreciation: - depreciate_asset(asset, self.posting_date) - asset.reload() + depreciate_asset(asset, self.posting_date, notes="Sell asset") fixed_asset_gl_entries = get_gl_entries_on_asset_disposal( asset, item.base_net_amount, item.finance_book, self.get("doctype"), self.get("name") diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index 7e54219740..4c393f0d4b 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -76,7 +76,6 @@ frappe.ui.form.on('Asset', { refresh: function(frm) { frappe.ui.form.trigger("Asset", "is_existing_asset"); frm.toggle_display("next_depreciation_date", frm.doc.docstatus < 1); - frm.events.make_schedules_editable(frm); if (frm.doc.docstatus==1) { if (in_list(["Submitted", "Partially Depreciated", "Fully Depreciated"], frm.doc.status)) { @@ -512,30 +511,6 @@ frappe.ui.form.on('Asset Finance Book', { } }); -frappe.ui.form.on('Depreciation Schedule', { - make_depreciation_entry: function(frm, cdt, cdn) { - var row = locals[cdt][cdn]; - if (!row.journal_entry) { - frappe.call({ - method: "erpnext.assets.doctype.asset.depreciation.make_depreciation_entry", - args: { - "asset_name": frm.doc.name, - "date": row.schedule_date - }, - callback: function(r) { - frappe.model.sync(r.message); - frm.refresh(); - } - }) - } - }, - - depreciation_amount: function(frm, cdt, cdn) { - erpnext.asset.set_accumulated_depreciation(frm); - } - -}) - erpnext.asset.set_accumulated_depreciation = function(frm) { if(frm.doc.depreciation_method != "Manual") return; diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json index 9af03ca0e7..4bac3031e8 100644 --- a/erpnext/assets/doctype/asset/asset.json +++ b/erpnext/assets/doctype/asset/asset.json @@ -52,8 +52,6 @@ "column_break_24", "frequency_of_depreciation", "next_depreciation_date", - "section_break_14", - "schedules", "insurance_details", "policy_number", "insurer", @@ -307,19 +305,6 @@ "label": "Next Depreciation Date", "no_copy": 1 }, - { - "depends_on": "calculate_depreciation", - "fieldname": "section_break_14", - "fieldtype": "Section Break", - "label": "Depreciation Schedule" - }, - { - "fieldname": "schedules", - "fieldtype": "Table", - "label": "Depreciation Schedule", - "no_copy": 1, - "options": "Depreciation Schedule" - }, { "collapsible": 1, "fieldname": "insurance_details", @@ -515,7 +500,7 @@ "link_fieldname": "asset" } ], - "modified": "2022-11-01 15:25:27.669803", + "modified": "2022-11-25 12:47:19.689702", "modified_by": "Administrator", "module": "Assets", "name": "Asset", diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 39557849ec..75c4809081 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -31,7 +31,7 @@ from erpnext.assets.doctype.asset_category.asset_category import get_asset_categ from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( cancel_asset_depr_schedules, convert_draft_asset_depr_schedules_into_active, - get_asset_depr_schedule, + get_asset_depr_schedule_name, get_depr_schedule_from_asset_depr_schedule_of_asset, make_draft_asset_depr_schedules, update_draft_asset_depr_schedules, @@ -247,12 +247,12 @@ class Asset(AccountsController): return value_after_depreciation def get_from_date(self, finance_book): - asset_depr_schedule = get_asset_depr_schedule(self.name, finance_book) + asset_depr_schedule_name = get_asset_depr_schedule_name(self.name, finance_book) - if not asset_depr_schedule: + if not asset_depr_schedule_name: return self.available_for_use_date - asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule) + asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) return asset_depr_schedule_doc.get("depreciation_schedule")[-1].schedule_date @@ -367,12 +367,14 @@ class Asset(AccountsController): def validate_expected_value_after_useful_life(self): for row in self.get("finance_books"): - asset_depr_schedule = get_asset_depr_schedule(self.name, row.finance_book) + asset_depr_schedule_name = get_asset_depr_schedule_name(self.name, row.finance_book) - if not asset_depr_schedule: + if not asset_depr_schedule_name: return - asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule) + asset_depr_schedule_doc = frappe.get_doc( + "Asset Depreciation Schedule", asset_depr_schedule_name + ) accumulated_depreciation_after_full_schedule = [ d.accumulated_depreciation_amount for d in asset_depr_schedule_doc.get("depreciation_schedule") @@ -425,12 +427,14 @@ class Asset(AccountsController): def delete_depreciation_entries(self): for row in self.get("finance_books"): - asset_depr_schedule = get_asset_depr_schedule(self.name, row.finance_book) + asset_depr_schedule_name = get_asset_depr_schedule_name(self.name, row.finance_book) - if not asset_depr_schedule: + if not asset_depr_schedule_name: return - asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule) + asset_depr_schedule_doc = frappe.get_doc( + "Asset Depreciation Schedule", asset_depr_schedule_name + ) for d in asset_depr_schedule_doc.get("depreciation_schedule"): if d.journal_entry: diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index 39ebc8d664..a912a93ac5 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -11,7 +11,9 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( ) from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( + get_asset_depr_schedule_name, get_temp_asset_depr_schedule_doc, + make_new_active_asset_depr_schedules_and_cancel_current_ones, ) @@ -25,7 +27,7 @@ def post_depreciation_entries(date=None, commit=True): if not date: date = today() for asset in get_depreciable_assets(date): - make_depreciation_entry(asset, date) + make_depreciation_entry_for_all_asset_depr_schedules(asset, date) if commit: frappe.db.commit() @@ -41,13 +43,23 @@ def get_depreciable_assets(date): ) +def make_depreciation_entry_for_all_asset_depr_schedules(asset_doc, date=None): + for row in asset_doc.get("finance_books"): + asset_depr_schedule_name = get_asset_depr_schedule_name(asset_doc.name, row.finance_book) + make_depreciation_entry(asset_depr_schedule_name, date) + + @frappe.whitelist() -def make_depreciation_entry(asset_name, date=None): +def make_depreciation_entry(asset_depr_schedule_name, date=None): frappe.has_permission("Journal Entry", throw=True) if not date: date = today() + asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) + + asset_name = asset_depr_schedule_doc.asset + asset = frappe.get_doc("Asset", asset_name) ( fixed_asset_account, @@ -63,14 +75,14 @@ def make_depreciation_entry(asset_name, date=None): accounting_dimensions = get_checks_for_pl_and_bs_accounts() - for d in asset.get("schedules"): + for d in asset_depr_schedule_doc.get("depreciation_schedule"): if not d.journal_entry and getdate(d.schedule_date) <= getdate(date): je = frappe.new_doc("Journal Entry") je.voucher_type = "Depreciation Entry" je.naming_series = depreciation_series je.posting_date = d.schedule_date je.company = asset.company - je.finance_book = d.finance_book + je.finance_book = asset_depr_schedule_doc.finance_book je.remark = "Depreciation Entry against {0} worth {1}".format(asset_name, d.depreciation_amount) credit_account, debit_account = get_credit_and_debit_accounts( @@ -121,14 +133,14 @@ def make_depreciation_entry(asset_name, date=None): d.db_set("journal_entry", je.name) - idx = cint(d.finance_book_id) - finance_books = asset.get("finance_books")[idx - 1] - finance_books.value_after_depreciation -= d.depreciation_amount - finance_books.db_update() + idx = cint(asset_depr_schedule_doc.finance_book_id) + row = asset.get("finance_books")[idx - 1] + row.value_after_depreciation -= d.depreciation_amount + row.db_update() asset.set_status() - return asset + return asset_depr_schedule_doc def get_depreciation_accounts(asset): @@ -202,8 +214,7 @@ def scrap_asset(asset_name): date = today() - depreciate_asset(asset, date) - asset.reload() + depreciate_asset(asset, date, notes="Scrap asset") depreciation_series = frappe.get_cached_value( "Company", asset.company, "series_for_depreciation_entry" @@ -247,22 +258,20 @@ def restore_asset(asset_name): asset.set_status() -def depreciate_asset(asset, date): - asset.flags.ignore_validate_update_after_submit = True - asset.prepare_depreciation_data(date_of_disposal=date) - asset.save() +def depreciate_asset(asset, date, notes): + make_new_active_asset_depr_schedules_and_cancel_current_ones( + asset, date_of_disposal=date, notes=notes + ) - make_depreciation_entry(asset.name, date) + make_depreciation_entry_for_all_asset_depr_schedules(asset, date) -def reset_depreciation_schedule(asset, date): - asset.flags.ignore_validate_update_after_submit = True - - # recreate original depreciation schedule of the asset - asset.prepare_depreciation_data(date_of_return=date) +def reset_depreciation_schedule(asset, date, notes): + make_new_active_asset_depr_schedules_and_cancel_current_ones( + asset, date_of_return=date, notes=notes + ) modify_depreciation_schedule_for_asset_repairs(asset) - asset.save() def modify_depreciation_schedule_for_asset_repairs(asset): diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py index 08355f047e..0787894dfd 100644 --- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py @@ -427,8 +427,7 @@ class AssetCapitalization(StockController): asset = self.get_asset(item) if asset.calculate_depreciation: - depreciate_asset(asset, self.posting_date) - asset.reload() + depreciate_asset(asset, self.posting_date, notes="TODO") fixed_asset_gl_entries = get_gl_entries_on_asset_disposal( asset, diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js index 9d41de381e..15e06e9a6f 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js @@ -1,8 +1,25 @@ // Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors // For license information, please see license.txt -frappe.ui.form.on('Asset Depreciation Schedule', { - // refresh: function(frm) { +frappe.ui.form.on('Depreciation Schedule', { + make_depreciation_entry: function(frm, cdt, cdn) { + var row = locals[cdt][cdn]; + if (!row.journal_entry) { + frappe.call({ + method: "erpnext.assets.doctype.asset.depreciation.make_depreciation_entry", + args: { + "asset_depr_schedule_name": frm.doc.name, + "date": row.schedule_date + }, + callback: function(r) { + frappe.model.sync(r.message); + frm.refresh(); + } + }) + } + }, - // } -}); + depreciation_amount: function(frm, cdt, cdn) { + erpnext.asset.set_accumulated_depreciation(frm); + } +}) \ No newline at end of file diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json index 83ed089de8..c5f7ca67b6 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json @@ -11,6 +11,7 @@ "naming_series", "column_break_2", "finance_book", + "finance_book_id", "depreciation_details_section", "depreciation_method", "total_number_of_depreciations", @@ -142,13 +143,21 @@ "label": "Expected Value After Useful Life", "options": "Company:company:default_currency", "read_only": 1 + }, + { + "fieldname": "finance_book_id", + "fieldtype": "Data", + "hidden": 1, + "label": "Finance Book Id", + "print_hide": 1, + "read_only": 1 } ], "in_create": 1, "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2022-11-14 14:33:53.360643", + "modified": "2022-11-25 14:31:52.668821", "modified_by": "Administrator", "module": "Assets", "name": "Asset Depreciation Schedule", diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 43f7b4adf7..6e78d7116b 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -33,12 +33,12 @@ def make_draft_asset_depr_schedules(asset_doc, date_of_disposal=None, date_of_re def update_draft_asset_depr_schedules(asset_doc, date_of_disposal=None, date_of_return=None): for row in asset_doc.get("finance_books"): - asset_depr_schedule = get_asset_depr_schedule(asset_doc.name, row.finance_book) + asset_depr_schedule_name = get_asset_depr_schedule_name(asset_doc.name, row.finance_book) - if not asset_depr_schedule: + if not asset_depr_schedule_name: return - asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule) + asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) prepare_draft_asset_depr_schedule_data( asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return @@ -57,9 +57,10 @@ def prepare_draft_asset_depr_schedule_data( ) -def set_draft_asset_depr_schedule_details(asset_depr_schedule_doc, asset, row): - asset_depr_schedule_doc.asset = asset +def set_draft_asset_depr_schedule_details(asset_depr_schedule_doc, asset_name, row): + asset_depr_schedule_doc.asset = asset_name asset_depr_schedule_doc.finance_book = row.finance_book + asset_depr_schedule_doc.finance_book_id = row.idx asset_depr_schedule_doc.depreciation_method = row.depreciation_method asset_depr_schedule_doc.total_number_of_depreciations = row.total_number_of_depreciations asset_depr_schedule_doc.frequency_of_depreciation = row.frequency_of_depreciation @@ -70,29 +71,29 @@ def set_draft_asset_depr_schedule_details(asset_depr_schedule_doc, asset, row): def convert_draft_asset_depr_schedules_into_active(asset_doc): for row in asset_doc.get("finance_books"): - asset_depr_schedule_name = get_asset_depr_schedule(asset_doc.name, row.finance_book) + asset_depr_schedule_name = get_asset_depr_schedule_name(asset_doc.name, row.finance_book) if not asset_depr_schedule_name: return - asset_depr_schedule = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) + asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) - asset_depr_schedule.status = "Active" + asset_depr_schedule_doc.status = "Active" - asset_depr_schedule.submit() + asset_depr_schedule_doc.submit() def make_new_active_asset_depr_schedules_and_cancel_current_ones( asset_doc, date_of_disposal=None, date_of_return=None, notes=None ): for row in asset_doc.get("finance_books"): - current_asset_depr_schedule = get_asset_depr_schedule(asset_doc.name, row.finance_book) + current_asset_depr_schedule_name = get_asset_depr_schedule_name(asset_doc.name, row.finance_book) - if not current_asset_depr_schedule: + if not current_asset_depr_schedule_name: return current_asset_depr_schedule_doc = frappe.get_doc( - "Asset Depreciation Schedule", current_asset_depr_schedule + "Asset Depreciation Schedule", current_asset_depr_schedule_name ) new_asset_depr_schedule_doc = frappe.copy_doc( @@ -123,30 +124,34 @@ def get_temp_asset_depr_schedule_doc(asset_doc, row, date_of_disposal=None, date def cancel_asset_depr_schedules(asset_doc): for row in asset_doc.get("finance_books"): - asset_depr_schedule = get_asset_depr_schedule(asset_doc.name, row.finance_book) + asset_depr_schedule_name = get_asset_depr_schedule_name(asset_doc.name, row.finance_book) - if not asset_depr_schedule: + if not asset_depr_schedule_name: return - asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule) + asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) asset_depr_schedule_doc.cancel() -def get_asset_depr_schedule(asset, finance_book): +def get_asset_depr_schedule_name(asset_name, finance_book): + 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 Depreciation Schedule", filters=[ - ["asset", "=", asset], - ["finance_book", "=", finance_book], + ["asset", "=", asset_name], + finance_book_filter, ["docstatus", "<", 2], ], ) -def get_depr_schedule_from_asset_depr_schedule_of_asset(asset, finance_book): - asset_depr_schedule = get_asset_depr_schedule(asset, finance_book) - asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule) +def get_depr_schedule_from_asset_depr_schedule_of_asset(asset_name, finance_book): + asset_depr_schedule_name = get_asset_depr_schedule_name(asset_name, finance_book) + asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) return asset_depr_schedule_doc.get("depreciation_schedule") 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 b6c4a3d210..4783565323 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py @@ -12,7 +12,7 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( ) from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_asset_depr_schedule, + get_asset_depr_schedule_name, get_depreciation_amount, set_accumulated_depreciation, ) @@ -116,9 +116,9 @@ class AssetValueAdjustment(Document): for d in asset.finance_books: d.value_after_depreciation = asset_value - current_asset_depr_schedule = get_asset_depr_schedule(asset.name, d.finance_book) + current_asset_depr_schedule_name = get_asset_depr_schedule_name(asset.name, d.finance_book) current_asset_depr_schedule_doc = frappe.get_doc( - "Asset Depreciation Schedule", current_asset_depr_schedule + "Asset Depreciation Schedule", current_asset_depr_schedule_name ) new_asset_depr_schedule_doc = frappe.copy_doc( From 96ede2fcf9f213cf1dd0877c8a5a1392d3dbce89 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Tue, 29 Nov 2022 21:30:23 +0530 Subject: [PATCH 14/49] fix: bug in new depr schedule --- erpnext/assets/doctype/asset/asset.py | 10 - .../asset_depreciation_schedule.py | 34 +- .../depreciation_schedule.json | 394 ++++-------------- 3 files changed, 101 insertions(+), 337 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 75c4809081..118bd02fe2 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -246,16 +246,6 @@ class Asset(AccountsController): return value_after_depreciation - def get_from_date(self, finance_book): - asset_depr_schedule_name = get_asset_depr_schedule_name(self.name, finance_book) - - if not asset_depr_schedule_name: - return self.available_for_use_date - - asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) - - return asset_depr_schedule_doc.get("depreciation_schedule")[-1].schedule_date - # if it returns True, depreciation_amount will not be equal for the first and last rows def check_is_pro_rata(self, row): has_pro_rata = False diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 6e78d7116b..2480c0303f 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -96,11 +96,7 @@ def make_new_active_asset_depr_schedules_and_cancel_current_ones( "Asset Depreciation Schedule", current_asset_depr_schedule_name ) - new_asset_depr_schedule_doc = frappe.copy_doc( - current_asset_depr_schedule_doc, ignore_no_copy=False - ) - - current_asset_depr_schedule_doc.cancel() + new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc) make_depr_schedule(new_asset_depr_schedule_doc, asset_doc, row, date_of_disposal) set_accumulated_depreciation( @@ -109,6 +105,8 @@ def make_new_active_asset_depr_schedules_and_cancel_current_ones( new_asset_depr_schedule_doc.notes = notes + current_asset_depr_schedule_doc.cancel() + new_asset_depr_schedule_doc.submit() @@ -170,30 +168,19 @@ def make_depr_schedule(asset_depr_schedule_doc, asset_doc, row, date_of_disposal def clear_depr_schedule(asset_depr_schedule_doc): - start = [] + start = 0 num_of_depreciations_completed = 0 depr_schedule = [] for schedule in asset_depr_schedule_doc.get("depreciation_schedule"): - if len(start) != 0: - break - if schedule.journal_entry: num_of_depreciations_completed += 1 depr_schedule.append(schedule) else: - start.append(num_of_depreciations_completed) - num_of_depreciations_completed = 0 + start = num_of_depreciations_completed + break - # to update start when all the schedule rows corresponding to the FB are linked with JEs - if len(start) == 0: - start.append(num_of_depreciations_completed) - - # when the Depreciation Schedule is being created for the first time - if start == []: - start = [0] - else: - asset_depr_schedule_doc.depreciation_schedule = depr_schedule + asset_depr_schedule_doc.depreciation_schedule = depr_schedule return start @@ -215,7 +202,7 @@ def _make_depr_schedule(asset_depr_schedule_doc, asset_doc, row, start, date_of_ skip_row = False should_get_last_day = is_last_day_of_the_month(row.depreciation_start_date) - for n in range(start[row.idx - 1], number_of_pending_depreciations): + for n in range(start, number_of_pending_depreciations): # If depreciation is already completed (for double declining balance) if skip_row: continue @@ -234,7 +221,10 @@ def _make_depr_schedule(asset_depr_schedule_doc, asset_doc, row, start, date_of_ # if asset is being sold or scrapped if date_of_disposal: - from_date = asset_doc.get_from_date(row.finance_book) + from_date = asset_doc.available_for_use_date + if asset_depr_schedule_doc.depreciation_schedule: + from_date = asset_depr_schedule_doc.depreciation_schedule[-1].schedule_date + depreciation_amount, days, months = asset_doc.get_pro_rata_amt( row, depreciation_amount, from_date, date_of_disposal ) diff --git a/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.json b/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.json index 35a2c9dd7f..1a669f9de1 100644 --- a/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.json +++ b/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.json @@ -1,318 +1,102 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 1, - "autoname": "", - "beta": 0, - "creation": "2016-03-02 15:11:01.278862", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Document", - "editable_grid": 1, - "engine": "InnoDB", + "actions": [], + "allow_rename": 1, + "creation": "2016-03-02 15:11:01.278862", + "doctype": "DocType", + "document_type": "Document", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "finance_book", + "schedule_date", + "depreciation_amount", + "column_break_3", + "accumulated_depreciation_amount", + "journal_entry", + "make_depreciation_entry", + "finance_book_id", + "depreciation_method" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "finance_book", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Finance Book", - "length": 0, - "no_copy": 0, - "options": "Finance Book", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "fieldname": "finance_book", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Finance Book", + "options": "Finance Book", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "schedule_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Schedule Date", - "length": 0, - "no_copy": 1, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "fieldname": "schedule_date", + "fieldtype": "Date", + "in_list_view": 1, + "label": "Schedule Date", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "depreciation_amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Depreciation Amount", - "length": 0, - "no_copy": 1, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "fieldname": "depreciation_amount", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Depreciation Amount", + "options": "Company:company:default_currency", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_3", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "fieldname": "column_break_3", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "accumulated_depreciation_amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Accumulated Depreciation Amount", - "length": 0, - "no_copy": 1, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "fieldname": "accumulated_depreciation_amount", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Accumulated Depreciation Amount", + "options": "Company:company:default_currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.docstatus==1", - "fieldname": "journal_entry", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Journal Entry", - "length": 0, - "no_copy": 1, - "options": "Journal Entry", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "depends_on": "eval:doc.docstatus==1", + "fieldname": "journal_entry", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Journal Entry", + "options": "Journal Entry", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:(doc.docstatus==1 && !doc.journal_entry && doc.schedule_date <= get_today())", - "fieldname": "make_depreciation_entry", - "fieldtype": "Button", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Make Depreciation Entry", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "depends_on": "eval:(doc.docstatus==1 && !doc.journal_entry && doc.schedule_date <= get_today())", + "fieldname": "make_depreciation_entry", + "fieldtype": "Button", + "label": "Make Depreciation Entry" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "finance_book_id", - "fieldtype": "Data", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Finance Book Id", - "length": 0, - "no_copy": 1, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "fieldname": "finance_book_id", + "fieldtype": "Data", + "hidden": 1, + "label": "Finance Book Id", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "depreciation_method", - "fieldtype": "Select", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Depreciation Method", - "length": 0, - "no_copy": 1, - "options": "\nStraight Line\nDouble Declining Balance\nWritten Down Value\nManual", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 + "fieldname": "depreciation_method", + "fieldtype": "Select", + "hidden": 1, + "label": "Depreciation Method", + "options": "\nStraight Line\nDouble Declining Balance\nWritten Down Value\nManual", + "print_hide": 1, + "read_only": 1 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 1, - "max_attachments": 0, - "modified": "2018-05-10 15:12:41.679436", - "modified_by": "Administrator", - "module": "Assets", - "name": "Depreciation Schedule", - "name_case": "", - "owner": "Administrator", - "permissions": [], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 0, - "track_seen": 0 + ], + "istable": 1, + "links": [], + "modified": "2022-11-29 18:27:05.748012", + "modified_by": "Administrator", + "module": "Assets", + "name": "Depreciation Schedule", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "states": [] } \ No newline at end of file From f20238fa3e472cbb359f888fd1757b2732e0d042 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Thu, 1 Dec 2022 15:15:32 +0530 Subject: [PATCH 15/49] chore: use make_new_active_asset_depr_schedules_and_cancel_current_ones instead of prepare_depreciation_data --- .../doctype/sales_invoice/sales_invoice.py | 4 ++-- erpnext/assets/doctype/asset/depreciation.py | 18 +++++++++--------- .../asset_capitalization.py | 13 ++++++++----- .../asset_depreciation_schedule.py | 2 +- .../doctype/asset_repair/asset_repair.py | 15 +++++++-------- 5 files changed, 27 insertions(+), 25 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index a99e92d9e0..6e87415644 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1185,11 +1185,11 @@ class SalesInvoice(SellingController): if asset.calculate_depreciation: posting_date = frappe.db.get_value("Sales Invoice", self.return_against, "posting_date") reverse_depreciation_entry_made_after_disposal(asset, posting_date) - reset_depreciation_schedule(asset, self.posting_date) + reset_depreciation_schedule(asset, self.posting_date, "Return asset") else: if asset.calculate_depreciation: - depreciate_asset(asset, self.posting_date, notes="Sell asset") + depreciate_asset(asset, self.posting_date, "Sell asset") fixed_asset_gl_entries = get_gl_entries_on_asset_disposal( asset, item.base_net_amount, item.finance_book, self.get("doctype"), self.get("name") diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index a912a93ac5..ba4c7b01fb 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -214,7 +214,7 @@ def scrap_asset(asset_name): date = today() - depreciate_asset(asset, date, notes="Scrap asset") + depreciate_asset(asset, date, "Scrap asset") depreciation_series = frappe.get_cached_value( "Company", asset.company, "series_for_depreciation_entry" @@ -246,7 +246,7 @@ def restore_asset(asset_name): asset = frappe.get_doc("Asset", asset_name) reverse_depreciation_entry_made_after_disposal(asset, asset.disposal_date) - reset_depreciation_schedule(asset, asset.disposal_date) + reset_depreciation_schedule(asset, asset.disposal_date, "Restore asset") je = asset.journal_entry_for_scrap @@ -258,20 +258,20 @@ def restore_asset(asset_name): asset.set_status() -def depreciate_asset(asset, date, notes): +def depreciate_asset(asset_doc, date, notes): make_new_active_asset_depr_schedules_and_cancel_current_ones( - asset, date_of_disposal=date, notes=notes + asset_doc, notes, date_of_disposal=date ) - make_depreciation_entry_for_all_asset_depr_schedules(asset, date) + make_depreciation_entry_for_all_asset_depr_schedules(asset_doc, date) -def reset_depreciation_schedule(asset, date, notes): +def reset_depreciation_schedule(asset_doc, date, notes): make_new_active_asset_depr_schedules_and_cancel_current_ones( - asset, date_of_return=date, notes=notes + asset_doc, notes, date_of_return=date ) - modify_depreciation_schedule_for_asset_repairs(asset) + modify_depreciation_schedule_for_asset_repairs(asset_doc) def modify_depreciation_schedule_for_asset_repairs(asset): @@ -283,7 +283,7 @@ def modify_depreciation_schedule_for_asset_repairs(asset): if repair.increase_in_asset_life: asset_repair = frappe.get_doc("Asset Repair", repair.name) asset_repair.modify_depreciation_schedule() - asset.prepare_depreciation_data() + make_new_active_asset_depr_schedules_and_cancel_current_ones(asset, "Asset Repair TODO") def reverse_depreciation_entry_made_after_disposal(asset, date): diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py index 0787894dfd..22459c44ef 100644 --- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py @@ -19,6 +19,9 @@ from erpnext.assets.doctype.asset.depreciation import ( reverse_depreciation_entry_made_after_disposal, ) from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account +from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( + make_new_active_asset_depr_schedules_and_cancel_current_ones, +) from erpnext.assets.doctype.asset_value_adjustment.asset_value_adjustment import ( get_current_asset_value, ) @@ -427,7 +430,7 @@ class AssetCapitalization(StockController): asset = self.get_asset(item) if asset.calculate_depreciation: - depreciate_asset(asset, self.posting_date, notes="TODO") + depreciate_asset(asset, self.posting_date, "Asset Capitalization TODO") fixed_asset_gl_entries = get_gl_entries_on_asset_disposal( asset, @@ -512,9 +515,9 @@ class AssetCapitalization(StockController): asset_doc.purchase_date = self.posting_date asset_doc.gross_purchase_amount = total_target_asset_value asset_doc.purchase_receipt_amount = total_target_asset_value - asset_doc.prepare_depreciation_data() - asset_doc.flags.ignore_validate_update_after_submit = True - asset_doc.save() + make_new_active_asset_depr_schedules_and_cancel_current_ones( + asset_doc, "Asset Capitalization TODO" + ) elif self.docstatus == 2: for item in self.asset_items: asset = self.get_asset(item) @@ -523,7 +526,7 @@ class AssetCapitalization(StockController): if asset.calculate_depreciation: reverse_depreciation_entry_made_after_disposal(asset, self.posting_date) - reset_depreciation_schedule(asset, self.posting_date) + reset_depreciation_schedule(asset, self.posting_date, "Asset Capitalization TODO") def get_asset(self, item): asset = frappe.get_doc("Asset", item.asset) diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 2480c0303f..ed104c63de 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -84,7 +84,7 @@ def convert_draft_asset_depr_schedules_into_active(asset_doc): def make_new_active_asset_depr_schedules_and_cancel_current_ones( - asset_doc, date_of_disposal=None, date_of_return=None, notes=None + asset_doc, notes, date_of_disposal=None, date_of_return=None ): for row in asset_doc.get("finance_books"): current_asset_depr_schedule_name = get_asset_depr_schedule_name(asset_doc.name, row.finance_book) diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py index 962e7fb58d..33530bd89b 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/asset_repair.py @@ -10,6 +10,7 @@ from erpnext.accounts.general_ledger import make_gl_entries from erpnext.assets.doctype.asset.asset import get_asset_account from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( get_depr_schedule_from_asset_depr_schedule_of_asset, + make_new_active_asset_depr_schedules_and_cancel_current_ones, ) from erpnext.controllers.accounts_controller import AccountsController @@ -54,10 +55,9 @@ class AssetRepair(AccountsController): and self.increase_in_asset_life ): self.modify_depreciation_schedule() - - self.asset_doc.flags.ignore_validate_update_after_submit = True - self.asset_doc.prepare_depreciation_data() - self.asset_doc.save() + make_new_active_asset_depr_schedules_and_cancel_current_ones( + self.asset_doc, "Asset Repair submit TODO" + ) def before_cancel(self): self.asset_doc = frappe.get_doc("Asset", self.asset) @@ -75,10 +75,9 @@ class AssetRepair(AccountsController): and self.increase_in_asset_life ): self.revert_depreciation_schedule_on_cancellation() - - self.asset_doc.flags.ignore_validate_update_after_submit = True - self.asset_doc.prepare_depreciation_data() - self.asset_doc.save() + make_new_active_asset_depr_schedules_and_cancel_current_ones( + self.asset_doc, "Asset Repair cancel TODO" + ) def check_repair_status(self): if self.repair_status == "Pending": From ca8c82749263c0229e9ffa74fcb2debbfc7d164a Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Sun, 4 Dec 2022 19:22:58 +0530 Subject: [PATCH 16/49] chore: refactor schedules in split_asset functions --- erpnext/assets/doctype/asset/asset.py | 80 +++++++++++-------- .../asset_depreciation_schedule.py | 11 ++- 2 files changed, 55 insertions(+), 36 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 118bd02fe2..553e037916 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -34,6 +34,7 @@ from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_sched get_asset_depr_schedule_name, get_depr_schedule_from_asset_depr_schedule_of_asset, make_draft_asset_depr_schedules, + make_new_active_asset_depr_schedules_and_cancel_current_ones, update_draft_asset_depr_schedules, ) from erpnext.controllers.accounts_controller import AccountsController @@ -895,34 +896,35 @@ def update_existing_asset(asset, remaining_qty): }, ) - for finance_book in asset.get("finance_books"): + for row in asset.get("finance_books"): value_after_depreciation = flt( - (finance_book.value_after_depreciation * remaining_qty) / asset.asset_quantity + (row.value_after_depreciation * remaining_qty) / asset.asset_quantity ) expected_value_after_useful_life = flt( - (finance_book.expected_value_after_useful_life * remaining_qty) / asset.asset_quantity + (row.expected_value_after_useful_life * remaining_qty) / asset.asset_quantity ) frappe.db.set_value( - "Asset Finance Book", finance_book.name, "value_after_depreciation", value_after_depreciation + "Asset Finance Book", row.name, "value_after_depreciation", value_after_depreciation ) frappe.db.set_value( "Asset Finance Book", - finance_book.name, + row.name, "expected_value_after_useful_life", expected_value_after_useful_life, ) - accumulated_depreciation = 0 + accumulated_depreciation = 0 + depr_schedule = get_depr_schedule_from_asset_depr_schedule_of_asset(asset.name, row.finance_book) - for term in asset.get("schedules"): - depreciation_amount = flt((term.depreciation_amount * remaining_qty) / asset.asset_quantity) - frappe.db.set_value( - "Depreciation Schedule", term.name, "depreciation_amount", depreciation_amount - ) - accumulated_depreciation += depreciation_amount - frappe.db.set_value( - "Depreciation Schedule", term.name, "accumulated_depreciation_amount", accumulated_depreciation - ) + for term in depr_schedule: + depreciation_amount = flt((term.depreciation_amount * remaining_qty) / asset.asset_quantity) + frappe.db.set_value( + "Depreciation Schedule", term.name, "depreciation_amount", depreciation_amount + ) + accumulated_depreciation += depreciation_amount + frappe.db.set_value( + "Depreciation Schedule", term.name, "accumulated_depreciation_amount", accumulated_depreciation + ) def create_new_asset_after_split(asset, split_qty): @@ -936,31 +938,41 @@ def create_new_asset_after_split(asset, split_qty): new_asset.opening_accumulated_depreciation = opening_accumulated_depreciation new_asset.asset_quantity = split_qty new_asset.split_from = asset.name - accumulated_depreciation = 0 - for finance_book in new_asset.get("finance_books"): - finance_book.value_after_depreciation = flt( - (finance_book.value_after_depreciation * split_qty) / asset.asset_quantity + for row in new_asset.get("finance_books"): + row.value_after_depreciation = flt( + (row.value_after_depreciation * split_qty) / asset.asset_quantity ) - finance_book.expected_value_after_useful_life = flt( - (finance_book.expected_value_after_useful_life * split_qty) / asset.asset_quantity + row.expected_value_after_useful_life = flt( + (row.expected_value_after_useful_life * split_qty) / asset.asset_quantity ) - for term in new_asset.get("schedules"): - depreciation_amount = flt((term.depreciation_amount * split_qty) / asset.asset_quantity) - term.depreciation_amount = depreciation_amount - accumulated_depreciation += depreciation_amount - term.accumulated_depreciation_amount = accumulated_depreciation - new_asset.submit() - new_asset.set_status() - for term in new_asset.get("schedules"): - # Update references in JV - if term.journal_entry: - add_reference_in_jv_on_split( - term.journal_entry, new_asset.name, asset.name, term.depreciation_amount - ) + make_new_active_asset_depr_schedules_and_cancel_current_ones( + new_asset, "create_new_asset_after_split TODO", submit=False + ) + + for row in new_asset.get("finance_books"): + accumulated_depreciation = 0 + + depr_schedule = get_depr_schedule_from_asset_depr_schedule_of_asset( + new_asset.name, row.finance_book + ) + + for term in depr_schedule: + depreciation_amount = flt((term.depreciation_amount * split_qty) / asset.asset_quantity) + term.depreciation_amount = depreciation_amount + accumulated_depreciation += depreciation_amount + term.accumulated_depreciation_amount = accumulated_depreciation + + # Update references in JV + if term.journal_entry: + add_reference_in_jv_on_split( + term.journal_entry, new_asset.name, asset.name, term.depreciation_amount + ) + + new_asset.set_status() return new_asset diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index ed104c63de..89c9c1a84f 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -84,7 +84,7 @@ def convert_draft_asset_depr_schedules_into_active(asset_doc): def make_new_active_asset_depr_schedules_and_cancel_current_ones( - asset_doc, notes, date_of_disposal=None, date_of_return=None + asset_doc, notes, submit=True, date_of_disposal=None, date_of_return=None ): for row in asset_doc.get("finance_books"): current_asset_depr_schedule_name = get_asset_depr_schedule_name(asset_doc.name, row.finance_book) @@ -107,7 +107,10 @@ def make_new_active_asset_depr_schedules_and_cancel_current_ones( current_asset_depr_schedule_doc.cancel() - new_asset_depr_schedule_doc.submit() + new_asset_depr_schedule_doc.insert() + + if submit: + new_asset_depr_schedule_doc.submit() def get_temp_asset_depr_schedule_doc(asset_doc, row, date_of_disposal=None, date_of_return=None): @@ -149,6 +152,10 @@ def get_asset_depr_schedule_name(asset_name, finance_book): def get_depr_schedule_from_asset_depr_schedule_of_asset(asset_name, finance_book): asset_depr_schedule_name = get_asset_depr_schedule_name(asset_name, finance_book) + + if not asset_depr_schedule_name: + return + asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) return asset_depr_schedule_doc.get("depreciation_schedule") From 83ed93fbb61e9888cd2b6e7d5820b6bc284abb69 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Sun, 4 Dec 2022 22:45:48 +0530 Subject: [PATCH 17/49] chore: refactor chart and manual set_accumulated_depreciation logic --- erpnext/assets/doctype/asset/asset.js | 35 ++++++++++--------- .../asset_depreciation_schedule.js | 14 +++++++- .../asset_depreciation_schedule.json | 11 +++++- .../asset_depreciation_schedule.py | 1 + 4 files changed, 42 insertions(+), 19 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index 4c393f0d4b..f937993f41 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -187,7 +187,11 @@ frappe.ui.form.on('Asset', { }) }, - setup_chart: function(frm) { + setup_chart: async function(frm) { + if(frm.doc.finance_books.length > 1) { + return + } + var x_intervals = [frm.doc.purchase_date]; var asset_values = [frm.doc.gross_purchase_amount]; var last_depreciation_date = frm.doc.purchase_date; @@ -201,7 +205,19 @@ frappe.ui.form.on('Asset', { flt(frm.doc.opening_accumulated_depreciation)); } - $.each(frm.doc.schedules || [], function(i, v) { + let depr_schedule = []; + + if (frm.doc.finance_books.length == 1) { + depr_schedule = (await frappe.call( + "erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule.get_depr_schedule_from_asset_depr_schedule_of_asset", + { + asset_name: frm.doc.name, + finance_book: frm.doc.finance_books[0].finance_book || null + } + )).message; + } + + $.each(depr_schedule || [], 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) { @@ -265,10 +281,6 @@ frappe.ui.form.on('Asset', { // frm.toggle_reqd("next_depreciation_date", (!frm.doc.is_existing_asset && frm.doc.calculate_depreciation)); }, - opening_accumulated_depreciation: function(frm) { - erpnext.asset.set_accumulated_depreciation(frm); - }, - make_schedules_editable: function(frm) { if (frm.doc.finance_books) { var is_editable = frm.doc.finance_books.filter(d => d.depreciation_method == "Manual").length > 0 @@ -511,17 +523,6 @@ frappe.ui.form.on('Asset Finance Book', { } }); -erpnext.asset.set_accumulated_depreciation = function(frm) { - if(frm.doc.depreciation_method != "Manual") return; - - var accumulated_depreciation = flt(frm.doc.opening_accumulated_depreciation); - $.each(frm.doc.schedules || [], function(i, row) { - accumulated_depreciation += flt(row.depreciation_amount); - frappe.model.set_value(row.doctype, row.name, - "accumulated_depreciation_amount", accumulated_depreciation); - }) -}; - erpnext.asset.scrap_asset = function(frm) { frappe.confirm(__("Do you really want to scrap this asset?"), function () { frappe.call({ diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js index 15e06e9a6f..fdebbb17c3 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js @@ -1,5 +1,6 @@ // Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors // For license information, please see license.txt +frappe.provide("erpnext.asset"); frappe.ui.form.on('Depreciation Schedule', { make_depreciation_entry: function(frm, cdt, cdn) { @@ -22,4 +23,15 @@ frappe.ui.form.on('Depreciation Schedule', { depreciation_amount: function(frm, cdt, cdn) { erpnext.asset.set_accumulated_depreciation(frm); } -}) \ No newline at end of file +}); + +erpnext.asset.set_accumulated_depreciation = function(frm) { + if(frm.doc.depreciation_method != "Manual") return; + + var accumulated_depreciation = flt(frm.doc.opening_accumulated_depreciation); + $.each(frm.doc.schedules || [], function(i, row) { + accumulated_depreciation += flt(row.depreciation_amount); + frappe.model.set_value(row.doctype, row.name, + "accumulated_depreciation_amount", accumulated_depreciation); + }) +}; diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json index c5f7ca67b6..d39f30f943 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json @@ -10,6 +10,7 @@ "asset", "naming_series", "column_break_2", + "opening_accumulated_depreciation", "finance_book", "finance_book_id", "depreciation_details_section", @@ -151,7 +152,15 @@ "label": "Finance Book Id", "print_hide": 1, "read_only": 1 - } + }, + { + "depends_on": "opening_accumulated_depreciation", + "fieldname": "opening_accumulated_depreciation", + "fieldtype": "Currency", + "label": "Opening Accumulated Depreciation", + "read_only": 1, + "options": "Company:company:default_currency" + } ], "in_create": 1, "index_web_pages_for_search": 1, diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 89c9c1a84f..8d854dcad9 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -150,6 +150,7 @@ def get_asset_depr_schedule_name(asset_name, finance_book): ) +@frappe.whitelist() def get_depr_schedule_from_asset_depr_schedule_of_asset(asset_name, finance_book): asset_depr_schedule_name = get_asset_depr_schedule_name(asset_name, finance_book) From 8365d6bdb721db616b8a270f16957c4b2ab23bb7 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Tue, 6 Dec 2022 17:58:38 +0530 Subject: [PATCH 18/49] fix: refactor reverse_depreciation_entry_made_after_disposal and fix fb bug --- erpnext/assets/doctype/asset/asset.js | 12 ------ erpnext/assets/doctype/asset/depreciation.py | 40 +++++++++----------- 2 files changed, 18 insertions(+), 34 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index f937993f41..aa73a224e2 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -281,17 +281,6 @@ frappe.ui.form.on('Asset', { // frm.toggle_reqd("next_depreciation_date", (!frm.doc.is_existing_asset && frm.doc.calculate_depreciation)); }, - make_schedules_editable: function(frm) { - if (frm.doc.finance_books) { - var is_editable = frm.doc.finance_books.filter(d => d.depreciation_method == "Manual").length > 0 - ? true : false; - - frm.toggle_enable("schedules", is_editable); - frm.fields_dict["schedules"].grid.toggle_enable("schedule_date", is_editable); - frm.fields_dict["schedules"].grid.toggle_enable("depreciation_amount", is_editable); - } - }, - make_sales_invoice: function(frm) { frappe.call({ args: { @@ -487,7 +476,6 @@ frappe.ui.form.on('Asset Finance Book', { depreciation_method: function(frm, cdt, cdn) { const row = locals[cdt][cdn]; frm.events.set_depreciation_rate(frm, row); - frm.events.make_schedules_editable(frm); }, expected_value_after_useful_life: function(frm, cdt, cdn) { diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index ba4c7b01fb..9bc3a488c8 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -12,6 +12,7 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( get_asset_depr_schedule_name, + get_depr_schedule_from_asset_depr_schedule_of_asset, get_temp_asset_depr_schedule_doc, make_new_active_asset_depr_schedules_and_cancel_current_ones, ) @@ -287,31 +288,26 @@ def modify_depreciation_schedule_for_asset_repairs(asset): def reverse_depreciation_entry_made_after_disposal(asset, date): - row = -1 - finance_book = asset.get("schedules")[0].get("finance_book") - for schedule in asset.get("schedules"): - if schedule.finance_book != finance_book: - row = 0 - finance_book = schedule.finance_book - else: - row += 1 + for row in asset.get("finance_books"): + depr_schedule = get_depr_schedule_from_asset_depr_schedule_of_asset(asset, row.finance_book) - if schedule.schedule_date == date: - if not disposal_was_made_on_original_schedule_date( - asset, schedule, row, date - ) or disposal_happens_in_the_future(date): + for schedule_idx, schedule in enumerate(depr_schedule): + if schedule.schedule_date == date: + if not disposal_was_made_on_original_schedule_date( + asset, schedule, schedule_idx, date + ) or disposal_happens_in_the_future(date): - reverse_journal_entry = make_reverse_journal_entry(schedule.journal_entry) - reverse_journal_entry.posting_date = nowdate() - frappe.flags.is_reverse_depr_entry = True - reverse_journal_entry.submit() + reverse_journal_entry = make_reverse_journal_entry(schedule.journal_entry) + reverse_journal_entry.posting_date = nowdate() + frappe.flags.is_reverse_depr_entry = True + reverse_journal_entry.submit() - frappe.flags.is_reverse_depr_entry = False - asset.flags.ignore_validate_update_after_submit = True - schedule.journal_entry = None - depreciation_amount = get_depreciation_amount_in_je(reverse_journal_entry) - asset.finance_books[0].value_after_depreciation += depreciation_amount - asset.save() + frappe.flags.is_reverse_depr_entry = False + asset.flags.ignore_validate_update_after_submit = True + schedule.journal_entry = None + depreciation_amount = get_depreciation_amount_in_je(reverse_journal_entry) + row.value_after_depreciation += depreciation_amount + asset.save() def get_depreciation_amount_in_je(journal_entry): From e7d404a30ae56eb50699755cddf9365f7d8dffc6 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Tue, 6 Dec 2022 21:33:20 +0530 Subject: [PATCH 19/49] chore: remove finance_book and finance_book_id from depreciation_schedule and refactor some functions --- erpnext/assets/doctype/asset/depreciation.py | 17 +++++---- .../asset_depreciation_schedule.py | 35 ++++++------------- .../asset_value_adjustment.py | 2 +- .../depreciation_schedule.json | 20 +---------- 4 files changed, 21 insertions(+), 53 deletions(-) diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index 9bc3a488c8..3530fbd6de 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -294,7 +294,7 @@ def reverse_depreciation_entry_made_after_disposal(asset, date): for schedule_idx, schedule in enumerate(depr_schedule): if schedule.schedule_date == date: if not disposal_was_made_on_original_schedule_date( - asset, schedule, schedule_idx, date + schedule_idx, row, date ) or disposal_happens_in_the_future(date): reverse_journal_entry = make_reverse_journal_entry(schedule.journal_entry) @@ -318,15 +318,14 @@ def get_depreciation_amount_in_je(journal_entry): # if the invoice had been posted on the date the depreciation was initially supposed to happen, the depreciation shouldn't be undone -def disposal_was_made_on_original_schedule_date(asset, schedule, row, posting_date_of_disposal): - for finance_book in asset.get("finance_books"): - if schedule.finance_book == finance_book.finance_book: - orginal_schedule_date = add_months( - finance_book.depreciation_start_date, row * cint(finance_book.frequency_of_depreciation) - ) +def disposal_was_made_on_original_schedule_date(schedule_idx, row, posting_date_of_disposal): + orginal_schedule_date = add_months( + row.depreciation_start_date, schedule_idx * cint(row.frequency_of_depreciation) + ) + + if orginal_schedule_date == posting_date_of_disposal: + return True - if orginal_schedule_date == posting_date_of_disposal: - return True return False diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 8d854dcad9..35c461a972 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -50,17 +50,18 @@ def update_draft_asset_depr_schedules(asset_doc, date_of_disposal=None, date_of_ def prepare_draft_asset_depr_schedule_data( asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return ): - set_draft_asset_depr_schedule_details(asset_depr_schedule_doc, asset_doc.name, row) + set_draft_asset_depr_schedule_details(asset_depr_schedule_doc, asset_doc, row) make_depr_schedule(asset_depr_schedule_doc, asset_doc, row, date_of_disposal) - set_accumulated_depreciation( - asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return - ) + set_accumulated_depreciation(asset_depr_schedule_doc, row, date_of_disposal, date_of_return) -def set_draft_asset_depr_schedule_details(asset_depr_schedule_doc, asset_name, row): - asset_depr_schedule_doc.asset = asset_name +def set_draft_asset_depr_schedule_details(asset_depr_schedule_doc, asset_doc, row): + asset_depr_schedule_doc.asset = asset_doc.name asset_depr_schedule_doc.finance_book = row.finance_book asset_depr_schedule_doc.finance_book_id = row.idx + asset_depr_schedule_doc.opening_accumulated_depreciation = ( + asset_doc.opening_accumulated_depreciation + ) asset_depr_schedule_doc.depreciation_method = row.depreciation_method asset_depr_schedule_doc.total_number_of_depreciations = row.total_number_of_depreciations asset_depr_schedule_doc.frequency_of_depreciation = row.frequency_of_depreciation @@ -99,9 +100,7 @@ def make_new_active_asset_depr_schedules_and_cancel_current_ones( new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc) make_depr_schedule(new_asset_depr_schedule_doc, asset_doc, row, date_of_disposal) - set_accumulated_depreciation( - new_asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return - ) + set_accumulated_depreciation(new_asset_depr_schedule_doc, row, date_of_disposal, date_of_return) new_asset_depr_schedule_doc.notes = notes @@ -243,8 +242,6 @@ def _make_depr_schedule(asset_depr_schedule_doc, asset_doc, row, start, date_of_ date_of_disposal, depreciation_amount, row.depreciation_method, - row.finance_book, - row.idx, ) break @@ -309,8 +306,6 @@ def _make_depr_schedule(asset_depr_schedule_doc, asset_doc, row, start, date_of_ schedule_date, depreciation_amount, row.depreciation_method, - row.finance_book, - row.idx, ) @@ -339,8 +334,6 @@ def add_depr_schedule_row( schedule_date, depreciation_amount, depreciation_method, - finance_book, - finance_book_id, ): asset_depr_schedule_doc.append( "depreciation_schedule", @@ -348,15 +341,12 @@ def add_depr_schedule_row( "schedule_date": schedule_date, "depreciation_amount": depreciation_amount, "depreciation_method": depreciation_method, - "finance_book": finance_book, - "finance_book_id": finance_book_id, }, ) def set_accumulated_depreciation( asset_depr_schedule_doc, - asset_doc, row, date_of_disposal=None, date_of_return=None, @@ -367,17 +357,14 @@ def set_accumulated_depreciation( for d in asset_depr_schedule_doc.get("depreciation_schedule") if d.depreciation_method == "Straight Line" ] - finance_books = [] + + accumulated_depreciation = flt(asset_depr_schedule_doc.opening_accumulated_depreciation) + value_after_depreciation = flt(row.value_after_depreciation) for i, d in enumerate(asset_depr_schedule_doc.get("depreciation_schedule")): if ignore_booked_entry and d.journal_entry: continue - if int(d.finance_book_id) not in finance_books: - accumulated_depreciation = flt(asset_doc.opening_accumulated_depreciation) - value_after_depreciation = flt(asset_doc.get_value_after_depreciation(d.finance_book_id)) - finance_books.append(int(d.finance_book_id)) - depreciation_amount = flt(d.depreciation_amount, d.precision("depreciation_amount")) value_after_depreciation -= flt(depreciation_amount) 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 4783565323..d1538097b4 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py @@ -155,7 +155,7 @@ class AssetValueAdjustment(Document): d.db_update() - set_accumulated_depreciation(new_asset_depr_schedule_doc, asset, d, ignore_booked_entry=True) + set_accumulated_depreciation(new_asset_depr_schedule_doc, d, ignore_booked_entry=True) for asset_data in depr_schedule: if not asset_data.journal_entry: asset_data.db_update() diff --git a/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.json b/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.json index 1a669f9de1..882c4bf00b 100644 --- a/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.json +++ b/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.json @@ -7,25 +7,15 @@ "editable_grid": 1, "engine": "InnoDB", "field_order": [ - "finance_book", "schedule_date", "depreciation_amount", "column_break_3", "accumulated_depreciation_amount", "journal_entry", "make_depreciation_entry", - "finance_book_id", "depreciation_method" ], "fields": [ - { - "fieldname": "finance_book", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Finance Book", - "options": "Finance Book", - "read_only": 1 - }, { "fieldname": "schedule_date", "fieldtype": "Date", @@ -69,14 +59,6 @@ "fieldtype": "Button", "label": "Make Depreciation Entry" }, - { - "fieldname": "finance_book_id", - "fieldtype": "Data", - "hidden": 1, - "label": "Finance Book Id", - "print_hide": 1, - "read_only": 1 - }, { "fieldname": "depreciation_method", "fieldtype": "Select", @@ -89,7 +71,7 @@ ], "istable": 1, "links": [], - "modified": "2022-11-29 18:27:05.748012", + "modified": "2022-12-06 20:35:50.264281", "modified_by": "Administrator", "module": "Assets", "name": "Depreciation Schedule", From 2cd42dbb1001cd17363eb3aa5598c25d5e2ef98b Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Tue, 6 Dec 2022 23:16:02 +0530 Subject: [PATCH 20/49] chore: refactor get_finance_book_value_map --- .../fixed_asset_register.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) 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 6b14dce084..f45b40bded 100644 --- a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py +++ b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py @@ -176,15 +176,17 @@ def get_finance_book_value_map(filters): return frappe._dict( frappe.db.sql( """ Select - parent, SUM(depreciation_amount) - FROM `tabDepreciation Schedule` + ads.name, SUM(depreciation_amount) + FROM `tabAsset Depreciation Schedule` ads, `tabDepreciation Schedule` ds WHERE - parentfield='schedules' - AND schedule_date<=%s - AND journal_entry IS NOT NULL - AND ifnull(finance_book, '')=%s - GROUP BY parent""", - (date, cstr(filters.finance_book or "")), + ds.parent = ads.name + AND ifnull(ads.finance_book, '')=%s + AND ads.docstatus=1 + AND ds.parentfield='depreciation_schedule' + AND ds.schedule_date<=%s + AND ds.journal_entry IS NOT NULL + GROUP BY ads.name""", + (cstr(filters.finance_book or ""), date), ) ) From 18fc2b5695cb8b350e3541bb4587f1ec095b984b Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Tue, 6 Dec 2022 23:34:56 +0530 Subject: [PATCH 21/49] chore: fix bug in unlink_asset_reference --- erpnext/accounts/doctype/journal_entry/journal_entry.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 90fbd55cff..ac7b026580 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -293,6 +293,10 @@ class JournalEntry(AccountsController): depr_schedule = get_depr_schedule_from_asset_depr_schedule_of_asset( asset.name, row.finance_book ) + + if not depr_schedule: + return + for s in depr_schedule: if s.journal_entry == self.name: s.db_set("journal_entry", None) From 1fd73af744b33617517cb39a297eeca97e4250f4 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Fri, 9 Dec 2022 00:28:34 +0530 Subject: [PATCH 22/49] chore: refactor some reports --- .../asset_depreciations_and_balances.py | 4 ++-- .../report/fixed_asset_register/fixed_asset_register.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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 ad9b1ba58e..43b95dca80 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 @@ -131,8 +131,8 @@ def get_assets(filters): 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, '') != '' + 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, 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 f45b40bded..bb50df0ba2 100644 --- a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py +++ b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py @@ -176,7 +176,7 @@ def get_finance_book_value_map(filters): return frappe._dict( frappe.db.sql( """ Select - ads.name, SUM(depreciation_amount) + ads.asset, SUM(depreciation_amount) FROM `tabAsset Depreciation Schedule` ads, `tabDepreciation Schedule` ds WHERE ds.parent = ads.name @@ -185,7 +185,7 @@ def get_finance_book_value_map(filters): AND ds.parentfield='depreciation_schedule' AND ds.schedule_date<=%s AND ds.journal_entry IS NOT NULL - GROUP BY ads.name""", + GROUP BY ads.asset""", (cstr(filters.finance_book or ""), date), ) ) From 187e1a324a5a24f4b3927e1a223344fc9ce8963b Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Fri, 9 Dec 2022 00:46:56 +0530 Subject: [PATCH 23/49] chore: refactor get_depreciable_assets --- erpnext/assets/doctype/asset/depreciation.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index 3530fbd6de..a7b5b60647 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -36,9 +36,11 @@ def post_depreciation_entries(date=None, commit=True): def get_depreciable_assets(date): return frappe.db.sql_list( """select distinct a.name - from tabAsset a, `tabDepreciation Schedule` ds - where a.name = ds.parent and a.docstatus=1 and ds.schedule_date<=%s and a.calculate_depreciation = 1 + from tabAsset a, `tabAsset Depreciation Schedule` ads, `tabDepreciation Schedule` ds + where a.name = ads.asset and ads.name = ds.parent and a.docstatus=1 and ads.docstatus=1 and a.status in ('Submitted', 'Partially Depreciated') + and a.calculate_depreciation = 1 + and ds.schedule_date<=%s and ifnull(ds.journal_entry, '')=''""", date, ) From 77dc8e7966f772e5e09512a32e7c7cccf2c7c849 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Fri, 9 Dec 2022 00:58:19 +0530 Subject: [PATCH 24/49] fix: bug in posting depr entries --- erpnext/assets/doctype/asset/depreciation.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index a7b5b60647..bc5b8a990e 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -27,8 +27,8 @@ def post_depreciation_entries(date=None, commit=True): if not date: date = today() - for asset in get_depreciable_assets(date): - make_depreciation_entry_for_all_asset_depr_schedules(asset, date) + for asset_name in get_depreciable_assets(date): + make_depreciation_entry_for_all_asset_depr_schedules(asset_name, date) if commit: frappe.db.commit() @@ -46,7 +46,9 @@ def get_depreciable_assets(date): ) -def make_depreciation_entry_for_all_asset_depr_schedules(asset_doc, date=None): +def make_depreciation_entry_for_all_asset_depr_schedules(asset_name, date=None): + asset_doc = frappe.get_doc("Asset", asset_name) + for row in asset_doc.get("finance_books"): asset_depr_schedule_name = get_asset_depr_schedule_name(asset_doc.name, row.finance_book) make_depreciation_entry(asset_depr_schedule_name, date) From 16365bfca3716b535a60eedf0ff07291c6c54d00 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Fri, 9 Dec 2022 14:04:00 +0530 Subject: [PATCH 25/49] chore: more refactoring --- .../doctype/journal_entry/journal_entry.py | 3 --- erpnext/assets/doctype/asset/asset.py | 23 ++++--------------- .../asset_depreciation_schedule.py | 1 + 3 files changed, 5 insertions(+), 22 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index ac7b026580..7d5ac258a5 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -294,9 +294,6 @@ class JournalEntry(AccountsController): asset.name, row.finance_book ) - if not depr_schedule: - return - for s in depr_schedule: if s.journal_entry == self.name: s.db_set("journal_entry", None) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 553e037916..d01b179f61 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -31,7 +31,6 @@ from erpnext.assets.doctype.asset_category.asset_category import get_asset_categ from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( cancel_asset_depr_schedules, convert_draft_asset_depr_schedules_into_active, - get_asset_depr_schedule_name, get_depr_schedule_from_asset_depr_schedule_of_asset, make_draft_asset_depr_schedules, make_new_active_asset_depr_schedules_and_cancel_current_ones, @@ -358,17 +357,10 @@ class Asset(AccountsController): def validate_expected_value_after_useful_life(self): for row in self.get("finance_books"): - asset_depr_schedule_name = get_asset_depr_schedule_name(self.name, row.finance_book) - - if not asset_depr_schedule_name: - return - - asset_depr_schedule_doc = frappe.get_doc( - "Asset Depreciation Schedule", asset_depr_schedule_name - ) + depr_schedule = get_depr_schedule_from_asset_depr_schedule_of_asset(self.name, row.finance_book) accumulated_depreciation_after_full_schedule = [ - d.accumulated_depreciation_amount for d in asset_depr_schedule_doc.get("depreciation_schedule") + d.accumulated_depreciation_amount for d in depr_schedule ] if accumulated_depreciation_after_full_schedule: @@ -418,16 +410,9 @@ class Asset(AccountsController): def delete_depreciation_entries(self): for row in self.get("finance_books"): - asset_depr_schedule_name = get_asset_depr_schedule_name(self.name, row.finance_book) + depr_schedule = get_depr_schedule_from_asset_depr_schedule_of_asset(self.name, row.finance_book) - if not asset_depr_schedule_name: - return - - asset_depr_schedule_doc = frappe.get_doc( - "Asset Depreciation Schedule", asset_depr_schedule_name - ) - - for d in asset_depr_schedule_doc.get("depreciation_schedule"): + for d in depr_schedule.get("depreciation_schedule"): if d.journal_entry: frappe.get_doc("Journal Entry", d.journal_entry).cancel() d.db_set("journal_entry", None) diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 35c461a972..9f4047dcf7 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -157,6 +157,7 @@ def get_depr_schedule_from_asset_depr_schedule_of_asset(asset_name, finance_book return asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) + return asset_depr_schedule_doc.get("depreciation_schedule") From 90e1b9cb3d0da3f66baf366a9890d919ba21b363 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Fri, 9 Dec 2022 16:18:40 +0530 Subject: [PATCH 26/49] chore: fix asset depr schedule notes --- .../doctype/sales_invoice/sales_invoice.py | 5 ++++- erpnext/assets/doctype/asset/asset.py | 6 +++--- erpnext/assets/doctype/asset/depreciation.py | 12 ++++++++--- .../asset_capitalization.py | 16 ++++++++++---- .../asset_depreciation_schedule.json | 21 +++++++------------ .../doctype/asset_repair/asset_repair.py | 10 +++++---- .../asset_value_adjustment.py | 5 ++--- 7 files changed, 44 insertions(+), 31 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 6e87415644..85ed78407b 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1189,7 +1189,10 @@ class SalesInvoice(SellingController): else: if asset.calculate_depreciation: - depreciate_asset(asset, self.posting_date, "Sell asset") + notes = _( + "This schedule was created when the Asset {0} was sold through Sales Invoice {1}." + ).format(asset.name, self.get("name")) + depreciate_asset(asset, self.posting_date, notes) fixed_asset_gl_entries = get_gl_entries_on_asset_disposal( asset, item.base_net_amount, item.finance_book, self.get("doctype"), self.get("name") diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index d01b179f61..0b37b8941b 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -352,13 +352,13 @@ class Asset(AccountsController): 0 ].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"): depr_schedule = get_depr_schedule_from_asset_depr_schedule_of_asset(self.name, row.finance_book) + if not depr_schedule: + continue + accumulated_depreciation_after_full_schedule = [ d.accumulated_depreciation_amount for d in depr_schedule ] diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index bc5b8a990e..22c65fd400 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -219,8 +219,6 @@ def scrap_asset(asset_name): date = today() - depreciate_asset(asset, date, "Scrap asset") - depreciation_series = frappe.get_cached_value( "Company", asset.company, "series_for_depreciation_entry" ) @@ -239,6 +237,11 @@ def scrap_asset(asset_name): je.flags.ignore_permissions = True je.submit() + notes = _( + "This schedule was created when the Asset {0} was scrapped through Journal Entry {1}." + ).format(asset.name, je.name) + depreciate_asset(asset, date, notes) + frappe.db.set_value("Asset", asset_name, "disposal_date", date) frappe.db.set_value("Asset", asset_name, "journal_entry_for_scrap", je.name) asset.set_status("Scrapped") @@ -288,7 +291,10 @@ def modify_depreciation_schedule_for_asset_repairs(asset): if repair.increase_in_asset_life: asset_repair = frappe.get_doc("Asset Repair", repair.name) asset_repair.modify_depreciation_schedule() - make_new_active_asset_depr_schedules_and_cancel_current_ones(asset, "Asset Repair TODO") + notes = _( + "This schedule was created when the Asset {0} went through the Asset Repair {1}." + ).format(asset.name, repair.name) + make_new_active_asset_depr_schedules_and_cancel_current_ones(asset, notes) def reverse_depreciation_entry_made_after_disposal(asset, date): diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py index 22459c44ef..96c01a5d8a 100644 --- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py @@ -430,7 +430,11 @@ class AssetCapitalization(StockController): asset = self.get_asset(item) if asset.calculate_depreciation: - depreciate_asset(asset, self.posting_date, "Asset Capitalization TODO") + notes = _( + "This schedule was created when the Asset {0} was consumed through Asset Capitalization {1}." + ).format(asset.name, self.get("name")) + depreciate_asset(asset, self.posting_date, notes) + asset.reload() fixed_asset_gl_entries = get_gl_entries_on_asset_disposal( asset, @@ -515,9 +519,10 @@ class AssetCapitalization(StockController): asset_doc.purchase_date = self.posting_date asset_doc.gross_purchase_amount = total_target_asset_value asset_doc.purchase_receipt_amount = total_target_asset_value - make_new_active_asset_depr_schedules_and_cancel_current_ones( - asset_doc, "Asset Capitalization TODO" + notes = _("This schedule was created when the Asset Capitalization {0} was submitted.").format( + self.name ) + make_new_active_asset_depr_schedules_and_cancel_current_ones(asset_doc, notes) elif self.docstatus == 2: for item in self.asset_items: asset = self.get_asset(item) @@ -526,7 +531,10 @@ class AssetCapitalization(StockController): if asset.calculate_depreciation: reverse_depreciation_entry_made_after_disposal(asset, self.posting_date) - reset_depreciation_schedule(asset, self.posting_date, "Asset Capitalization TODO") + notes = _( + "This schedule was created when the Asset Capitalization {0} was cancelled." + ).format(self.name) + reset_depreciation_schedule(asset, self.posting_date, notes) def get_asset(self, item): asset = frappe.get_doc("Asset", item.asset) diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json index d39f30f943..0fea6a5b19 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json @@ -24,7 +24,6 @@ "depreciation_schedule", "details_section", "notes", - "column_break_15", "status", "amended_from" ], @@ -126,10 +125,6 @@ "options": "Draft\nActive\nCancelled", "read_only": 1 }, - { - "fieldname": "column_break_15", - "fieldtype": "Column Break" - }, { "depends_on": "frequency_of_depreciation", "fieldname": "frequency_of_depreciation", @@ -154,19 +149,19 @@ "read_only": 1 }, { - "depends_on": "opening_accumulated_depreciation", - "fieldname": "opening_accumulated_depreciation", - "fieldtype": "Currency", - "label": "Opening Accumulated Depreciation", - "read_only": 1, - "options": "Company:company:default_currency" - } + "depends_on": "opening_accumulated_depreciation", + "fieldname": "opening_accumulated_depreciation", + "fieldtype": "Currency", + "label": "Opening Accumulated Depreciation", + "options": "Company:company:default_currency", + "read_only": 1 + } ], "in_create": 1, "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2022-11-25 14:31:52.668821", + "modified": "2022-12-09 15:14:20.562294", "modified_by": "Administrator", "module": "Assets", "name": "Asset Depreciation Schedule", diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py index 33530bd89b..d3f74b08b2 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/asset_repair.py @@ -55,9 +55,10 @@ class AssetRepair(AccountsController): and self.increase_in_asset_life ): self.modify_depreciation_schedule() - make_new_active_asset_depr_schedules_and_cancel_current_ones( - self.asset_doc, "Asset Repair submit TODO" + notes = _("This schedule was created when the Asset Repair {0} was submitted.").format( + self.name ) + make_new_active_asset_depr_schedules_and_cancel_current_ones(self.asset_doc, notes) def before_cancel(self): self.asset_doc = frappe.get_doc("Asset", self.asset) @@ -75,9 +76,10 @@ class AssetRepair(AccountsController): and self.increase_in_asset_life ): self.revert_depreciation_schedule_on_cancellation() - make_new_active_asset_depr_schedules_and_cancel_current_ones( - self.asset_doc, "Asset Repair cancel TODO" + notes = _("This schedule was created when the Asset Repair {0} was cancelled.").format( + self.name ) + make_new_active_asset_depr_schedules_and_cancel_current_ones(self.asset_doc, notes) def check_repair_status(self): if self.repair_status == "Pending": 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 d1538097b4..9caca33c30 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py @@ -121,9 +121,8 @@ class AssetValueAdjustment(Document): "Asset Depreciation Schedule", current_asset_depr_schedule_name ) - new_asset_depr_schedule_doc = frappe.copy_doc( - current_asset_depr_schedule_doc, ignore_no_copy=False - ) + new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc) + new_asset_depr_schedule_doc.notes = "Asset value adjustment" current_asset_depr_schedule_doc.cancel() From ec6505d747bcbb2af63bcccd7559328fc9a97bb7 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Mon, 12 Dec 2022 16:35:30 +0530 Subject: [PATCH 27/49] chore: fix some bugs, refactor some functions, add proper notes --- .../doctype/sales_invoice/sales_invoice.py | 7 +- erpnext/assets/doctype/asset/asset.py | 74 ++++++++++++------- erpnext/assets/doctype/asset/depreciation.py | 13 ++-- .../asset_capitalization.py | 20 +++-- .../asset_depreciation_schedule.py | 45 ++++------- .../doctype/asset_repair/asset_repair.py | 20 ++--- 6 files changed, 100 insertions(+), 79 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 85ed78407b..f470fe6496 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1190,8 +1190,11 @@ class SalesInvoice(SellingController): else: if asset.calculate_depreciation: notes = _( - "This schedule was created when the Asset {0} was sold through Sales Invoice {1}." - ).format(asset.name, self.get("name")) + "This schedule was created when Asset {0} was sold through Sales Invoice {1}." + ).format( + get_link_to_form(asset.doctype, asset.name), + get_link_to_form(self.doctype, self.get("name")), + ) depreciate_asset(asset, self.posting_date, notes) fixed_asset_gl_entries = get_gl_entries_on_asset_disposal( diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 0b37b8941b..a9fed1c254 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -14,6 +14,7 @@ from frappe.utils import ( flt, get_datetime, get_last_day, + get_link_to_form, getdate, is_last_day_of_the_month, month_diff, @@ -31,9 +32,10 @@ from erpnext.assets.doctype.asset_category.asset_category import get_asset_categ from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( cancel_asset_depr_schedules, convert_draft_asset_depr_schedules_into_active, + get_asset_depr_schedule_doc_of_asset, get_depr_schedule_from_asset_depr_schedule_of_asset, make_draft_asset_depr_schedules, - make_new_active_asset_depr_schedules_and_cancel_current_ones, + set_draft_asset_depr_schedule_details, update_draft_asset_depr_schedules, ) from erpnext.controllers.accounts_controller import AccountsController @@ -48,7 +50,6 @@ class Asset(AccountsController): self.set_missing_values() if not self.split_from: self.prepare_depreciation_data() - update_draft_asset_depr_schedules(self) self.validate_gross_and_purchase_amount() self.validate_expected_value_after_useful_life() @@ -97,6 +98,7 @@ class Asset(AccountsController): if self.calculate_depreciation: self.value_after_depreciation = 0 self.set_depreciation_rate() + update_draft_asset_depr_schedules(self) else: self.finance_books = [] self.value_after_depreciation = flt(self.gross_purchase_amount) - flt( @@ -858,12 +860,12 @@ def split_asset(asset_name, split_qty): remaining_qty = asset.asset_quantity - split_qty new_asset = create_new_asset_after_split(asset, split_qty) - update_existing_asset(asset, remaining_qty) + update_existing_asset(asset, remaining_qty, new_asset.name) return new_asset -def update_existing_asset(asset, remaining_qty): +def update_existing_asset(asset, remaining_qty, new_asset_name): remaining_gross_purchase_amount = flt( (asset.gross_purchase_amount * remaining_qty) / asset.asset_quantity ) @@ -898,18 +900,31 @@ def update_existing_asset(asset, remaining_qty): expected_value_after_useful_life, ) - accumulated_depreciation = 0 - depr_schedule = get_depr_schedule_from_asset_depr_schedule_of_asset(asset.name, row.finance_book) + current_asset_depr_schedule_doc = get_asset_depr_schedule_doc_of_asset( + asset.name, row.finance_book + ) + new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc) - for term in depr_schedule: + set_draft_asset_depr_schedule_details(new_asset_depr_schedule_doc, asset, row) + + accumulated_depreciation = 0 + + for term in new_asset_depr_schedule_doc.get("depreciation_schedule"): depreciation_amount = flt((term.depreciation_amount * remaining_qty) / asset.asset_quantity) - frappe.db.set_value( - "Depreciation Schedule", term.name, "depreciation_amount", depreciation_amount - ) + term.depreciation_amount = depreciation_amount accumulated_depreciation += depreciation_amount - frappe.db.set_value( - "Depreciation Schedule", term.name, "accumulated_depreciation_amount", accumulated_depreciation - ) + term.accumulated_depreciation_amount = accumulated_depreciation + + notes = _( + "This schedule was created when Asset {0} was updated after being split into new Asset {1}." + ).format( + get_link_to_form(asset.doctype, asset.name), get_link_to_form(asset.doctype, new_asset_name) + ) + new_asset_depr_schedule_doc.notes = notes + + current_asset_depr_schedule_doc.cancel() + + new_asset_depr_schedule_doc.submit() def create_new_asset_after_split(asset, split_qty): @@ -932,33 +947,42 @@ def create_new_asset_after_split(asset, split_qty): (row.expected_value_after_useful_life * split_qty) / asset.asset_quantity ) - new_asset.submit() + current_asset_depr_schedule_doc = get_asset_depr_schedule_doc_of_asset( + asset.name, row.finance_book + ) + new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc) - make_new_active_asset_depr_schedules_and_cancel_current_ones( - new_asset, "create_new_asset_after_split TODO", submit=False - ) + set_draft_asset_depr_schedule_details(new_asset_depr_schedule_doc, new_asset, row) - for row in new_asset.get("finance_books"): accumulated_depreciation = 0 - depr_schedule = get_depr_schedule_from_asset_depr_schedule_of_asset( - new_asset.name, row.finance_book - ) - - for term in depr_schedule: + for term in new_asset_depr_schedule_doc.get("depreciation_schedule"): depreciation_amount = flt((term.depreciation_amount * split_qty) / asset.asset_quantity) term.depreciation_amount = depreciation_amount accumulated_depreciation += depreciation_amount term.accumulated_depreciation_amount = accumulated_depreciation + notes = _("This schedule was created when new Asset {0} was split from Asset {1}.").format( + get_link_to_form(new_asset.doctype, new_asset.name), get_link_to_form(asset.doctype, asset.name) + ) + new_asset_depr_schedule_doc.notes = notes + + new_asset_depr_schedule_doc.insert() + + new_asset.submit() + new_asset.set_status() + + for row in new_asset.get("finance_books"): + depr_schedule = get_depr_schedule_from_asset_depr_schedule_of_asset( + new_asset.name, row.finance_book + ) + for term in depr_schedule: # Update references in JV if term.journal_entry: add_reference_in_jv_on_split( term.journal_entry, new_asset.name, asset.name, term.depreciation_amount ) - new_asset.set_status() - return new_asset diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index 22c65fd400..b7d5511640 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -4,7 +4,7 @@ import frappe from frappe import _ -from frappe.utils import add_months, cint, flt, getdate, nowdate, today +from frappe.utils import add_months, cint, flt, get_link_to_form, getdate, nowdate, today from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( get_checks_for_pl_and_bs_accounts, @@ -238,8 +238,8 @@ def scrap_asset(asset_name): je.submit() notes = _( - "This schedule was created when the Asset {0} was scrapped through Journal Entry {1}." - ).format(asset.name, je.name) + "This schedule was created when Asset {0} was scrapped through Journal Entry {1}." + ).format(get_link_to_form(asset.doctype, asset.name), get_link_to_form(je.doctype, je.name)) depreciate_asset(asset, date, notes) frappe.db.set_value("Asset", asset_name, "disposal_date", date) @@ -291,9 +291,10 @@ def modify_depreciation_schedule_for_asset_repairs(asset): if repair.increase_in_asset_life: asset_repair = frappe.get_doc("Asset Repair", repair.name) asset_repair.modify_depreciation_schedule() - notes = _( - "This schedule was created when the Asset {0} went through the Asset Repair {1}." - ).format(asset.name, repair.name) + notes = _("This schedule was created when Asset {0} went through Asset Repair {1}.").format( + get_link_to_form(asset.doctype, asset.name), + get_link_to_form(asset_repair.doctype, asset_repair.name), + ) make_new_active_asset_depr_schedules_and_cancel_current_ones(asset, notes) diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py index 96c01a5d8a..26bac86094 100644 --- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py @@ -7,7 +7,7 @@ import frappe # import erpnext from frappe import _ -from frappe.utils import cint, flt +from frappe.utils import cint, flt, get_link_to_form from six import string_types import erpnext @@ -431,8 +431,10 @@ class AssetCapitalization(StockController): if asset.calculate_depreciation: notes = _( - "This schedule was created when the Asset {0} was consumed through Asset Capitalization {1}." - ).format(asset.name, self.get("name")) + "This schedule was created when Asset {0} was consumed when Asset Capitalization {1} was submitted." + ).format( + get_link_to_form(asset.doctype, asset.name), get_link_to_form(self.doctype, self.get("name")) + ) depreciate_asset(asset, self.posting_date, notes) asset.reload() @@ -519,8 +521,10 @@ class AssetCapitalization(StockController): asset_doc.purchase_date = self.posting_date asset_doc.gross_purchase_amount = total_target_asset_value asset_doc.purchase_receipt_amount = total_target_asset_value - notes = _("This schedule was created when the Asset Capitalization {0} was submitted.").format( - self.name + notes = _( + "This schedule was created when target Asset {0} was updated when Asset Capitalization {1} was submitted." + ).format( + get_link_to_form(asset_doc.doctype, asset_doc.name), get_link_to_form(self.doctype, self.name) ) make_new_active_asset_depr_schedules_and_cancel_current_ones(asset_doc, notes) elif self.docstatus == 2: @@ -532,8 +536,10 @@ class AssetCapitalization(StockController): if asset.calculate_depreciation: reverse_depreciation_entry_made_after_disposal(asset, self.posting_date) notes = _( - "This schedule was created when the Asset Capitalization {0} was cancelled." - ).format(self.name) + "This schedule was created when Asset {0} was restored when Asset Capitalization {1} was cancelled." + ).format( + get_link_to_form(asset.doctype, asset.name), get_link_to_form(self.doctype, self.name) + ) reset_depreciation_schedule(asset, self.posting_date, notes) def get_asset(self, item): diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 9f4047dcf7..61e8ba2941 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -33,12 +33,7 @@ def make_draft_asset_depr_schedules(asset_doc, date_of_disposal=None, date_of_re def update_draft_asset_depr_schedules(asset_doc, date_of_disposal=None, date_of_return=None): for row in asset_doc.get("finance_books"): - asset_depr_schedule_name = get_asset_depr_schedule_name(asset_doc.name, row.finance_book) - - if not asset_depr_schedule_name: - return - - asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) + asset_depr_schedule_doc = get_asset_depr_schedule_doc_of_asset(asset_doc.name, row.finance_book) prepare_draft_asset_depr_schedule_data( asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return @@ -72,12 +67,7 @@ def set_draft_asset_depr_schedule_details(asset_depr_schedule_doc, asset_doc, ro def convert_draft_asset_depr_schedules_into_active(asset_doc): for row in asset_doc.get("finance_books"): - asset_depr_schedule_name = get_asset_depr_schedule_name(asset_doc.name, row.finance_book) - - if not asset_depr_schedule_name: - return - - asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) + asset_depr_schedule_doc = get_asset_depr_schedule_doc_of_asset(asset_doc.name, row.finance_book) asset_depr_schedule_doc.status = "Active" @@ -85,16 +75,11 @@ def convert_draft_asset_depr_schedules_into_active(asset_doc): def make_new_active_asset_depr_schedules_and_cancel_current_ones( - asset_doc, notes, submit=True, date_of_disposal=None, date_of_return=None + asset_doc, notes, date_of_disposal=None, date_of_return=None ): for row in asset_doc.get("finance_books"): - current_asset_depr_schedule_name = get_asset_depr_schedule_name(asset_doc.name, row.finance_book) - - if not current_asset_depr_schedule_name: - return - - current_asset_depr_schedule_doc = frappe.get_doc( - "Asset Depreciation Schedule", current_asset_depr_schedule_name + current_asset_depr_schedule_doc = get_asset_depr_schedule_doc_of_asset( + asset_doc.name, row.finance_book ) new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc) @@ -106,10 +91,7 @@ def make_new_active_asset_depr_schedules_and_cancel_current_ones( current_asset_depr_schedule_doc.cancel() - new_asset_depr_schedule_doc.insert() - - if submit: - new_asset_depr_schedule_doc.submit() + new_asset_depr_schedule_doc.submit() def get_temp_asset_depr_schedule_doc(asset_doc, row, date_of_disposal=None, date_of_return=None): @@ -124,12 +106,9 @@ def get_temp_asset_depr_schedule_doc(asset_doc, row, date_of_disposal=None, date def cancel_asset_depr_schedules(asset_doc): for row in asset_doc.get("finance_books"): - asset_depr_schedule_name = get_asset_depr_schedule_name(asset_doc.name, row.finance_book) + asset_depr_schedule_doc = get_asset_depr_schedule_doc_of_asset(asset_doc.name, row.finance_book) - if not asset_depr_schedule_name: - return - - asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) + asset_depr_schedule_doc.status = "Cancelled" asset_depr_schedule_doc.cancel() @@ -151,6 +130,12 @@ def get_asset_depr_schedule_name(asset_name, finance_book): @frappe.whitelist() def get_depr_schedule_from_asset_depr_schedule_of_asset(asset_name, finance_book): + asset_depr_schedule_doc = get_asset_depr_schedule_doc_of_asset(asset_name, finance_book) + + return asset_depr_schedule_doc.get("depreciation_schedule") + + +def get_asset_depr_schedule_doc_of_asset(asset_name, finance_book): asset_depr_schedule_name = get_asset_depr_schedule_name(asset_name, finance_book) if not asset_depr_schedule_name: @@ -158,7 +143,7 @@ def get_depr_schedule_from_asset_depr_schedule_of_asset(asset_name, finance_book asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) - return asset_depr_schedule_doc.get("depreciation_schedule") + return asset_depr_schedule_doc def make_depr_schedule(asset_depr_schedule_doc, asset_doc, row, date_of_disposal): diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py index d3f74b08b2..31fd0f64e8 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/asset_repair.py @@ -3,7 +3,7 @@ import frappe from frappe import _ -from frappe.utils import add_months, cint, flt, getdate, time_diff_in_hours +from frappe.utils import add_months, cint, flt, get_link_to_form, getdate, time_diff_in_hours import erpnext from erpnext.accounts.general_ledger import make_gl_entries @@ -55,10 +55,11 @@ class AssetRepair(AccountsController): and self.increase_in_asset_life ): self.modify_depreciation_schedule() - notes = _("This schedule was created when the Asset Repair {0} was submitted.").format( - self.name - ) - make_new_active_asset_depr_schedules_and_cancel_current_ones(self.asset_doc, notes) + + notes = _("This schedule was created when Asset Repair {0} was submitted.").format( + get_link_to_form(self.doctype, self.name) + ) + make_new_active_asset_depr_schedules_and_cancel_current_ones(self.asset_doc, notes) def before_cancel(self): self.asset_doc = frappe.get_doc("Asset", self.asset) @@ -76,10 +77,11 @@ class AssetRepair(AccountsController): and self.increase_in_asset_life ): self.revert_depreciation_schedule_on_cancellation() - notes = _("This schedule was created when the Asset Repair {0} was cancelled.").format( - self.name - ) - make_new_active_asset_depr_schedules_and_cancel_current_ones(self.asset_doc, notes) + + notes = _("This schedule was created when Asset Repair {0} was cancelled.").format( + get_link_to_form(self.doctype, self.name) + ) + make_new_active_asset_depr_schedules_and_cancel_current_ones(self.asset_doc, notes) def check_repair_status(self): if self.repair_status == "Pending": From b997d1eb8773cd9bd5b5f45c3db1c2be3bff4409 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Mon, 12 Dec 2022 17:25:38 +0530 Subject: [PATCH 28/49] chore: add some validation, shorten some function names --- .../doctype/journal_entry/journal_entry.py | 6 ++-- erpnext/assets/doctype/asset/asset.js | 2 +- erpnext/assets/doctype/asset/asset.py | 26 ++++++---------- erpnext/assets/doctype/asset/depreciation.py | 4 +-- .../asset_depreciation_schedule.py | 30 ++++++++++++------- .../doctype/asset_repair/asset_repair.py | 6 ++-- 6 files changed, 37 insertions(+), 37 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index e661d0b69c..2bbfe34bea 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -24,7 +24,7 @@ from erpnext.accounts.utils import ( get_stock_and_account_balance, ) from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_depr_schedule_from_asset_depr_schedule_of_asset, + get_depr_schedule, ) from erpnext.controllers.accounts_controller import AccountsController @@ -287,9 +287,7 @@ class JournalEntry(AccountsController): if d.reference_type == "Asset" and d.reference_name: asset = frappe.get_doc("Asset", d.reference_name) for row in asset.get("finance_books"): - depr_schedule = get_depr_schedule_from_asset_depr_schedule_of_asset( - asset.name, row.finance_book - ) + depr_schedule = get_depr_schedule(asset.name, row.finance_book) for s in depr_schedule: if s.journal_entry == self.name: diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index aa73a224e2..aa3af3beaf 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -209,7 +209,7 @@ frappe.ui.form.on('Asset', { if (frm.doc.finance_books.length == 1) { depr_schedule = (await frappe.call( - "erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule.get_depr_schedule_from_asset_depr_schedule_of_asset", + "erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule.get_depr_schedule", { asset_name: frm.doc.name, finance_book: frm.doc.finance_books[0].finance_book || null diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index a9fed1c254..47f88b0ae3 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -32,8 +32,8 @@ from erpnext.assets.doctype.asset_category.asset_category import get_asset_categ from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( cancel_asset_depr_schedules, convert_draft_asset_depr_schedules_into_active, - get_asset_depr_schedule_doc_of_asset, - get_depr_schedule_from_asset_depr_schedule_of_asset, + get_asset_depr_schedule_doc, + get_depr_schedule, make_draft_asset_depr_schedules, set_draft_asset_depr_schedule_details, update_draft_asset_depr_schedules, @@ -50,6 +50,7 @@ class Asset(AccountsController): self.set_missing_values() if not self.split_from: self.prepare_depreciation_data() + update_draft_asset_depr_schedules(self) self.validate_gross_and_purchase_amount() self.validate_expected_value_after_useful_life() @@ -98,7 +99,6 @@ class Asset(AccountsController): if self.calculate_depreciation: self.value_after_depreciation = 0 self.set_depreciation_rate() - update_draft_asset_depr_schedules(self) else: self.finance_books = [] self.value_after_depreciation = flt(self.gross_purchase_amount) - flt( @@ -350,13 +350,11 @@ class Asset(AccountsController): return depreciation_amount_for_last_row def get_depreciation_amount_for_first_row(self, finance_book): - return get_depr_schedule_from_asset_depr_schedule_of_asset(self.name, finance_book)[ - 0 - ].depreciation_amount + return get_depr_schedule(self.name, finance_book)[0].depreciation_amount def validate_expected_value_after_useful_life(self): for row in self.get("finance_books"): - depr_schedule = get_depr_schedule_from_asset_depr_schedule_of_asset(self.name, row.finance_book) + depr_schedule = get_depr_schedule(self.name, row.finance_book) if not depr_schedule: continue @@ -412,7 +410,7 @@ class Asset(AccountsController): def delete_depreciation_entries(self): for row in self.get("finance_books"): - depr_schedule = get_depr_schedule_from_asset_depr_schedule_of_asset(self.name, row.finance_book) + depr_schedule = get_depr_schedule(self.name, row.finance_book) for d in depr_schedule.get("depreciation_schedule"): if d.journal_entry: @@ -900,9 +898,7 @@ def update_existing_asset(asset, remaining_qty, new_asset_name): expected_value_after_useful_life, ) - current_asset_depr_schedule_doc = get_asset_depr_schedule_doc_of_asset( - asset.name, row.finance_book - ) + current_asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset.name, row.finance_book) new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc) set_draft_asset_depr_schedule_details(new_asset_depr_schedule_doc, asset, row) @@ -947,9 +943,7 @@ def create_new_asset_after_split(asset, split_qty): (row.expected_value_after_useful_life * split_qty) / asset.asset_quantity ) - current_asset_depr_schedule_doc = get_asset_depr_schedule_doc_of_asset( - asset.name, row.finance_book - ) + current_asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset.name, row.finance_book) new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc) set_draft_asset_depr_schedule_details(new_asset_depr_schedule_doc, new_asset, row) @@ -973,9 +967,7 @@ def create_new_asset_after_split(asset, split_qty): new_asset.set_status() for row in new_asset.get("finance_books"): - depr_schedule = get_depr_schedule_from_asset_depr_schedule_of_asset( - new_asset.name, row.finance_book - ) + depr_schedule = get_depr_schedule(new_asset.name, row.finance_book) for term in depr_schedule: # Update references in JV if term.journal_entry: diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index b7d5511640..514fd86d68 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -12,7 +12,7 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( get_asset_depr_schedule_name, - get_depr_schedule_from_asset_depr_schedule_of_asset, + get_depr_schedule, get_temp_asset_depr_schedule_doc, make_new_active_asset_depr_schedules_and_cancel_current_ones, ) @@ -300,7 +300,7 @@ def modify_depreciation_schedule_for_asset_repairs(asset): def reverse_depreciation_entry_made_after_disposal(asset, date): for row in asset.get("finance_books"): - depr_schedule = get_depr_schedule_from_asset_depr_schedule_of_asset(asset, row.finance_book) + depr_schedule = get_depr_schedule(asset, row.finance_book) for schedule_idx, schedule in enumerate(depr_schedule): if schedule.schedule_date == date: diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 61e8ba2941..71ce99237d 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -2,6 +2,7 @@ # For license information, please see license.txt import frappe +from frappe import _ from frappe.model.document import Document from frappe.utils import ( add_days, @@ -17,7 +18,18 @@ import erpnext class AssetDepreciationSchedule(Document): - pass + def validate(self): + self.validate_another_asset_depr_schedule_does_not_exist() + + def validate_another_asset_depr_schedule_does_not_exist(self): + asset_depr_schedule_name = get_asset_depr_schedule_name(self.asset, self.finance_book) + + if asset_depr_schedule_name: + frappe.throw( + _("Asset Depreciation Schedule for Asset {0} and Finance Book {1} already exists.").format( + self.asset, self.finance_book + ) + ) def make_draft_asset_depr_schedules(asset_doc, date_of_disposal=None, date_of_return=None): @@ -33,7 +45,7 @@ def make_draft_asset_depr_schedules(asset_doc, date_of_disposal=None, date_of_re def update_draft_asset_depr_schedules(asset_doc, date_of_disposal=None, date_of_return=None): for row in asset_doc.get("finance_books"): - asset_depr_schedule_doc = get_asset_depr_schedule_doc_of_asset(asset_doc.name, row.finance_book) + asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_doc.name, row.finance_book) prepare_draft_asset_depr_schedule_data( asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return @@ -67,7 +79,7 @@ def set_draft_asset_depr_schedule_details(asset_depr_schedule_doc, asset_doc, ro def convert_draft_asset_depr_schedules_into_active(asset_doc): for row in asset_doc.get("finance_books"): - asset_depr_schedule_doc = get_asset_depr_schedule_doc_of_asset(asset_doc.name, row.finance_book) + asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_doc.name, row.finance_book) asset_depr_schedule_doc.status = "Active" @@ -78,9 +90,7 @@ def make_new_active_asset_depr_schedules_and_cancel_current_ones( asset_doc, notes, date_of_disposal=None, date_of_return=None ): for row in asset_doc.get("finance_books"): - current_asset_depr_schedule_doc = get_asset_depr_schedule_doc_of_asset( - asset_doc.name, row.finance_book - ) + current_asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_doc.name, row.finance_book) new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc) @@ -106,7 +116,7 @@ def get_temp_asset_depr_schedule_doc(asset_doc, row, date_of_disposal=None, date def cancel_asset_depr_schedules(asset_doc): for row in asset_doc.get("finance_books"): - asset_depr_schedule_doc = get_asset_depr_schedule_doc_of_asset(asset_doc.name, row.finance_book) + asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_doc.name, row.finance_book) asset_depr_schedule_doc.status = "Cancelled" @@ -129,13 +139,13 @@ def get_asset_depr_schedule_name(asset_name, finance_book): @frappe.whitelist() -def get_depr_schedule_from_asset_depr_schedule_of_asset(asset_name, finance_book): - asset_depr_schedule_doc = get_asset_depr_schedule_doc_of_asset(asset_name, finance_book) +def get_depr_schedule(asset_name, finance_book): + asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_name, finance_book) return asset_depr_schedule_doc.get("depreciation_schedule") -def get_asset_depr_schedule_doc_of_asset(asset_name, finance_book): +def get_asset_depr_schedule_doc(asset_name, finance_book): asset_depr_schedule_name = get_asset_depr_schedule_name(asset_name, finance_book) if not asset_depr_schedule_name: diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py index 31fd0f64e8..2396df93a3 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/asset_repair.py @@ -9,7 +9,7 @@ import erpnext from erpnext.accounts.general_ledger import make_gl_entries from erpnext.assets.doctype.asset.asset import get_asset_account from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_depr_schedule_from_asset_depr_schedule_of_asset, + get_depr_schedule, make_new_active_asset_depr_schedules_and_cancel_current_ones, ) from erpnext.controllers.accounts_controller import AccountsController @@ -285,7 +285,7 @@ class AssetRepair(AccountsController): asset.number_of_depreciations_booked ) - depr_schedule = get_depr_schedule_from_asset_depr_schedule_of_asset(asset.name, row.finance_book) + depr_schedule = get_depr_schedule(asset.name, row.finance_book) # the Schedule Date in the final row of the old Depreciation Schedule last_schedule_date = depr_schedule[len(depr_schedule) - 1].schedule_date @@ -318,7 +318,7 @@ class AssetRepair(AccountsController): asset.number_of_depreciations_booked ) - depr_schedule = get_depr_schedule_from_asset_depr_schedule_of_asset(asset.name, row.finance_book) + depr_schedule = get_depr_schedule(asset.name, row.finance_book) # the Schedule Date in the final row of the modified Depreciation Schedule last_schedule_date = depr_schedule[len(depr_schedule) - 1].schedule_date From 1ea2ba0dea352110cc495c630de36876bd165d68 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Mon, 12 Dec 2022 17:31:57 +0530 Subject: [PATCH 29/49] chore: handle some cases where asset_depr_schedule doesn't exist --- .../asset_depreciation_schedule.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 71ce99237d..b01f23929a 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -47,6 +47,9 @@ def update_draft_asset_depr_schedules(asset_doc, date_of_disposal=None, date_of_ for row in asset_doc.get("finance_books"): asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_doc.name, row.finance_book) + if not asset_depr_schedule_doc: + continue + prepare_draft_asset_depr_schedule_data( asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return ) @@ -142,6 +145,9 @@ def get_asset_depr_schedule_name(asset_name, finance_book): def get_depr_schedule(asset_name, finance_book): asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_name, finance_book) + if not asset_depr_schedule_doc: + return + return asset_depr_schedule_doc.get("depreciation_schedule") From 28d4942d6cda0db750421230c647b672b4848a0c Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Mon, 12 Dec 2022 18:19:34 +0530 Subject: [PATCH 30/49] chore: fix validation and add make_schedules_editable --- .../asset_depreciation_schedule.js | 14 ++++++++++ .../asset_depreciation_schedule.py | 26 ++++++++++++++----- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js index fdebbb17c3..c28b2b3b6a 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js @@ -2,6 +2,20 @@ // For license information, please see license.txt frappe.provide("erpnext.asset"); +frappe.ui.form.on('Asset Depreciation Schedule', { + onload: function(frm) { + frm.events.make_schedules_editable(frm); + }, + + make_schedules_editable: function(frm) { + var is_editable = frm.doc.depreciation_method == "Manual" ? true : false; + + frm.toggle_enable("depreciation_schedule", is_editable); + frm.fields_dict["depreciation_schedule"].grid.toggle_enable("schedule_date", is_editable); + frm.fields_dict["depreciation_schedule"].grid.toggle_enable("depreciation_amount", is_editable); + } +}); + frappe.ui.form.on('Depreciation Schedule', { make_depreciation_entry: function(frm, cdt, cdn) { var row = locals[cdt][cdn]; diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index b01f23929a..2cdea574dd 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -22,14 +22,28 @@ class AssetDepreciationSchedule(Document): self.validate_another_asset_depr_schedule_does_not_exist() def validate_another_asset_depr_schedule_does_not_exist(self): - asset_depr_schedule_name = get_asset_depr_schedule_name(self.asset, self.finance_book) + finance_book_filter = ["finance_book", "is", "not set"] + if self.finance_book: + finance_book_filter = ["finance_book", "=", self.finance_book] - if asset_depr_schedule_name: - frappe.throw( - _("Asset Depreciation Schedule for Asset {0} and Finance Book {1} already exists.").format( - self.asset, self.finance_book + num_asset_depr_schedules = frappe.db.count( + "Asset Depreciation Schedule", + [ + ["asset", "=", self.asset], + finance_book_filter, + ["docstatus", "<", 2], + ], + ) + + if num_asset_depr_schedules == 1: + asset_depr_schedule_name = get_asset_depr_schedule_name(self.asset, self.finance_book) + + if self.name != asset_depr_schedule_name: + frappe.throw( + _("Asset Depreciation Schedule for Asset {0} and Finance Book {1} already exists.").format( + self.asset, self.finance_book + ) ) - ) def make_draft_asset_depr_schedules(asset_doc, date_of_disposal=None, date_of_return=None): From df134c7c5b73178cf4f771a5d35d463a8fa23fa5 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Tue, 13 Dec 2022 16:26:33 +0530 Subject: [PATCH 31/49] chore: fixing some tests --- .../doctype/sales_invoice/sales_invoice.py | 8 +- erpnext/assets/doctype/asset/asset.py | 36 ++---- erpnext/assets/doctype/asset/depreciation.py | 19 ++- erpnext/assets/doctype/asset/test_asset.py | 108 +++++++++++------- .../asset_depreciation_schedule.py | 66 ++++++++--- 5 files changed, 145 insertions(+), 92 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 9430f6a294..4168f01859 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1185,7 +1185,13 @@ class SalesInvoice(SellingController): if asset.calculate_depreciation: posting_date = frappe.db.get_value("Sales Invoice", self.return_against, "posting_date") reverse_depreciation_entry_made_after_disposal(asset, posting_date) - reset_depreciation_schedule(asset, self.posting_date, "Return asset") + notes = _( + "This schedule was created when Asset {0} was returned after being sold through Sales Invoice {1}." + ).format( + get_link_to_form(asset.doctype, asset.name), + get_link_to_form(self.doctype, self.get("name")), + ) + reset_depreciation_schedule(asset, self.posting_date, notes) else: if asset.calculate_depreciation: diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 47f88b0ae3..cb97ccce01 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -35,6 +35,7 @@ from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_sched get_asset_depr_schedule_doc, get_depr_schedule, make_draft_asset_depr_schedules, + make_draft_asset_depr_schedules_if_not_present, set_draft_asset_depr_schedule_details, update_draft_asset_depr_schedules, ) @@ -62,7 +63,9 @@ class Asset(AccountsController): self.make_asset_movement() if not self.booked_fixed_asset and self.validate_make_gl_entry(): self.make_gl_entries() - convert_draft_asset_depr_schedules_into_active(self) + if not self.split_from: + make_draft_asset_depr_schedules_if_not_present(self) + convert_draft_asset_depr_schedules_into_active(self) def on_cancel(self): self.validate_cancellation() @@ -332,26 +335,6 @@ class Asset(AccountsController): ).format(row.idx) ) - # to ensure that final accumulated depreciation amount is accurate - def get_adjusted_depreciation_amount( - self, depreciation_amount_without_pro_rata, depreciation_amount_for_last_row, finance_book - ): - if not self.opening_accumulated_depreciation: - depreciation_amount_for_first_row = self.get_depreciation_amount_for_first_row(finance_book) - - if ( - depreciation_amount_for_first_row + depreciation_amount_for_last_row - != depreciation_amount_without_pro_rata - ): - depreciation_amount_for_last_row = ( - depreciation_amount_without_pro_rata - depreciation_amount_for_first_row - ) - - return depreciation_amount_for_last_row - - def get_depreciation_amount_for_first_row(self, finance_book): - return get_depr_schedule(self.name, finance_book)[0].depreciation_amount - def validate_expected_value_after_useful_life(self): for row in self.get("finance_books"): depr_schedule = get_depr_schedule(self.name, row.finance_book) @@ -412,7 +395,7 @@ class Asset(AccountsController): for row in self.get("finance_books"): depr_schedule = get_depr_schedule(self.name, row.finance_book) - for d in depr_schedule.get("depreciation_schedule"): + for d in depr_schedule: if d.journal_entry: frappe.get_doc("Journal Entry", d.journal_entry).cancel() d.db_set("journal_entry", None) @@ -943,6 +926,10 @@ def create_new_asset_after_split(asset, split_qty): (row.expected_value_after_useful_life * split_qty) / asset.asset_quantity ) + new_asset.submit() + new_asset.set_status() + + for row in new_asset.get("finance_books"): current_asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset.name, row.finance_book) new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc) @@ -961,10 +948,7 @@ def create_new_asset_after_split(asset, split_qty): ) new_asset_depr_schedule_doc.notes = notes - new_asset_depr_schedule_doc.insert() - - new_asset.submit() - new_asset.set_status() + new_asset_depr_schedule_doc.submit() for row in new_asset.get("finance_books"): depr_schedule = get_depr_schedule(new_asset.name, row.finance_book) diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index 514fd86d68..d7d248089a 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -28,7 +28,10 @@ def post_depreciation_entries(date=None, commit=True): if not date: date = today() for asset_name in get_depreciable_assets(date): - make_depreciation_entry_for_all_asset_depr_schedules(asset_name, date) + asset_doc = frappe.get_doc("Asset", asset_name) + + make_depreciation_entry_for_all_asset_depr_schedules(asset_doc, date) + if commit: frappe.db.commit() @@ -46,9 +49,7 @@ def get_depreciable_assets(date): ) -def make_depreciation_entry_for_all_asset_depr_schedules(asset_name, date=None): - asset_doc = frappe.get_doc("Asset", asset_name) - +def make_depreciation_entry_for_all_asset_depr_schedules(asset_doc, date=None): for row in asset_doc.get("finance_books"): asset_depr_schedule_name = get_asset_depr_schedule_name(asset_doc.name, row.finance_book) make_depreciation_entry(asset_depr_schedule_name, date) @@ -240,6 +241,7 @@ def scrap_asset(asset_name): notes = _( "This schedule was created when Asset {0} was scrapped through Journal Entry {1}." ).format(get_link_to_form(asset.doctype, asset.name), get_link_to_form(je.doctype, je.name)) + depreciate_asset(asset, date, notes) frappe.db.set_value("Asset", asset_name, "disposal_date", date) @@ -254,10 +256,15 @@ def restore_asset(asset_name): asset = frappe.get_doc("Asset", asset_name) reverse_depreciation_entry_made_after_disposal(asset, asset.disposal_date) - reset_depreciation_schedule(asset, asset.disposal_date, "Restore asset") je = asset.journal_entry_for_scrap + notes = _( + "This schedule was created when Asset {0} was restored after being scrapped by Journal Entry {1}." + ).format(get_link_to_form(asset.doctype, asset.name), get_link_to_form(je.doctype, je.name)) + + reset_depreciation_schedule(asset, asset.disposal_date, notes) + asset.db_set("disposal_date", None) asset.db_set("journal_entry_for_scrap", None) @@ -300,7 +307,7 @@ def modify_depreciation_schedule_for_asset_repairs(asset): def reverse_depreciation_entry_made_after_disposal(asset, date): for row in asset.get("finance_books"): - depr_schedule = get_depr_schedule(asset, row.finance_book) + depr_schedule = get_depr_schedule(asset.name, row.finance_book) for schedule_idx, schedule in enumerate(depr_schedule): if schedule.schedule_date == date: diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 60324ea73d..8835b32bcc 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -27,6 +27,11 @@ from erpnext.assets.doctype.asset.depreciation import ( restore_asset, scrap_asset, ) +from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( + clear_depr_schedule, + get_asset_depr_schedule_doc, + get_depr_schedule, +) from erpnext.stock.doctype.purchase_receipt.purchase_receipt import ( make_purchase_invoice as make_invoice, ) @@ -379,20 +384,23 @@ class TestAsset(AssetSetup): new_asset = split_asset(asset.name, 2) asset.load_from_db() + depr_schedule_of_asset = get_depr_schedule(asset.name) + depr_schedule_of_new_asset = get_depr_schedule(new_asset.name) + self.assertEqual(new_asset.asset_quantity, 2) self.assertEqual(new_asset.gross_purchase_amount, 24000) self.assertEqual(new_asset.opening_accumulated_depreciation, 4000) self.assertEqual(new_asset.split_from, asset.name) - self.assertEqual(new_asset.schedules[0].depreciation_amount, 4000) - self.assertEqual(new_asset.schedules[1].depreciation_amount, 4000) + self.assertEqual(depr_schedule_of_new_asset[0].depreciation_amount, 4000) + self.assertEqual(depr_schedule_of_new_asset[1].depreciation_amount, 4000) self.assertEqual(asset.asset_quantity, 8) self.assertEqual(asset.gross_purchase_amount, 96000) self.assertEqual(asset.opening_accumulated_depreciation, 16000) - self.assertEqual(asset.schedules[0].depreciation_amount, 16000) - self.assertEqual(asset.schedules[1].depreciation_amount, 16000) + self.assertEqual(depr_schedule_of_asset[0].depreciation_amount, 16000) + self.assertEqual(depr_schedule_of_asset[1].depreciation_amount, 16000) - journal_entry = asset.schedules[0].journal_entry + journal_entry = depr_schedule_of_asset[0].journal_entry jv = frappe.get_doc("Journal Entry", journal_entry) self.assertEqual(jv.accounts[0].credit_in_account_currency, 16000) @@ -629,7 +637,7 @@ class TestDepreciationMethods(AssetSetup): schedules = [ [cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] - for d in asset.get("schedules") + for d in get_depr_schedule(asset.name) ] self.assertEqual(schedules, expected_schedules) @@ -651,7 +659,7 @@ class TestDepreciationMethods(AssetSetup): expected_schedules = [["2032-12-31", 30000.0, 77095.89], ["2033-06-06", 12904.11, 90000.0]] schedules = [ [cstr(d.schedule_date), flt(d.depreciation_amount, 2), d.accumulated_depreciation_amount] - for d in asset.get("schedules") + for d in get_depr_schedule(asset.name) ] self.assertEqual(schedules, expected_schedules) @@ -678,7 +686,7 @@ class TestDepreciationMethods(AssetSetup): schedules = [ [cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] - for d in asset.get("schedules") + for d in get_depr_schedule(asset.name) ] self.assertEqual(schedules, expected_schedules) @@ -703,7 +711,7 @@ class TestDepreciationMethods(AssetSetup): schedules = [ [cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] - for d in asset.get("schedules") + for d in get_depr_schedule(asset.name) ] self.assertEqual(schedules, expected_schedules) @@ -733,7 +741,7 @@ class TestDepreciationMethods(AssetSetup): flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2), ] - for d in asset.get("schedules") + for d in get_depr_schedule(asset.name) ] self.assertEqual(schedules, expected_schedules) @@ -765,7 +773,7 @@ class TestDepreciationMethods(AssetSetup): flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2), ] - for d in asset.get("schedules") + for d in get_depr_schedule(asset.name) ] self.assertEqual(schedules, expected_schedules) @@ -798,7 +806,7 @@ class TestDepreciationMethods(AssetSetup): flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2), ] - for d in asset.get("schedules") + for d in get_depr_schedule(asset.name) ] self.assertEqual(schedules, expected_schedules) @@ -831,7 +839,7 @@ class TestDepreciationMethods(AssetSetup): flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2), ] - for d in asset.get("schedules") + for d in get_depr_schedule(asset.name) ] self.assertEqual(schedules, expected_schedules) @@ -854,7 +862,7 @@ class TestDepreciationBasics(AssetSetup): ["2022-12-31", 30000, 90000], ] - for i, schedule in enumerate(asset.schedules): + for i, schedule in enumerate(get_depr_schedule(asset.name)): self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) self.assertEqual(expected_values[i][1], schedule.depreciation_amount) self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) @@ -877,7 +885,7 @@ class TestDepreciationBasics(AssetSetup): ["2023-01-01", 15000, 90000], ] - for i, schedule in enumerate(asset.schedules): + for i, schedule in enumerate(get_depr_schedule(asset.name)): self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) self.assertEqual(expected_values[i][1], schedule.depreciation_amount) self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) @@ -922,7 +930,7 @@ class TestDepreciationBasics(AssetSetup): expected_values = [["2020-12-31", 30000.0], ["2021-12-31", 30000.0], ["2022-12-31", 30000.0]] - for i, schedule in enumerate(asset.schedules): + for i, schedule in enumerate(get_depr_schedule(asset.name)): self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) self.assertEqual(expected_values[i][1], schedule.depreciation_amount) @@ -942,7 +950,7 @@ class TestDepreciationBasics(AssetSetup): expected_values = [30000.0, 60000.0, 90000.0] - for i, schedule in enumerate(asset.schedules): + for i, schedule in enumerate(get_depr_schedule(asset.name)): self.assertEqual(expected_values[i], schedule.accumulated_depreciation_amount) def test_check_is_pro_rata(self): @@ -1122,9 +1130,9 @@ class TestDepreciationBasics(AssetSetup): post_depreciation_entries(date="2021-06-01") asset.load_from_db() - self.assertTrue(asset.schedules[0].journal_entry) - self.assertFalse(asset.schedules[1].journal_entry) - self.assertFalse(asset.schedules[2].journal_entry) + self.assertTrue(get_depr_schedule(asset.name)[0].journal_entry) + self.assertFalse(get_depr_schedule(asset.name)[1].journal_entry) + self.assertFalse(get_depr_schedule(asset.name)[2].journal_entry) def test_depr_entry_posting_when_depr_expense_account_is_an_expense_account(self): """Tests if the Depreciation Expense Account gets debited and the Accumulated Depreciation Account gets credited when the former's an Expense Account.""" @@ -1143,7 +1151,7 @@ class TestDepreciationBasics(AssetSetup): post_depreciation_entries(date="2021-06-01") asset.load_from_db() - je = frappe.get_doc("Journal Entry", asset.schedules[0].journal_entry) + je = frappe.get_doc("Journal Entry", get_depr_schedule(asset.name)[0].journal_entry) accounting_entries = [ {"account": entry.account, "debit": entry.debit, "credit": entry.credit} for entry in je.accounts @@ -1179,7 +1187,7 @@ class TestDepreciationBasics(AssetSetup): post_depreciation_entries(date="2021-06-01") asset.load_from_db() - je = frappe.get_doc("Journal Entry", asset.schedules[0].journal_entry) + je = frappe.get_doc("Journal Entry", get_depr_schedule(asset.name)[0].journal_entry) accounting_entries = [ {"account": entry.account, "debit": entry.debit, "credit": entry.credit} for entry in je.accounts @@ -1215,9 +1223,11 @@ class TestDepreciationBasics(AssetSetup): post_depreciation_entries(date="2021-06-01") asset.load_from_db() - asset.clear_depr_schedule() + asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset.name) - self.assertEqual(len(asset.schedules), 1) + clear_depr_schedule(asset_depr_schedule_doc) + + self.assertEqual(len(asset_depr_schedule_doc.get("depreciation_schedule")), 1) def test_clear_depr_schedule_for_multiple_finance_books(self): asset = create_asset(item_code="Macbook Pro", available_for_use_date="2019-12-31", do_not_save=1) @@ -1226,6 +1236,7 @@ class TestDepreciationBasics(AssetSetup): asset.append( "finance_books", { + "finance_book": "Test Finance Book 1", "depreciation_method": "Straight Line", "frequency_of_depreciation": 1, "total_number_of_depreciations": 3, @@ -1236,6 +1247,7 @@ class TestDepreciationBasics(AssetSetup): asset.append( "finance_books", { + "finance_book": "Test Finance Book 2", "depreciation_method": "Straight Line", "frequency_of_depreciation": 1, "total_number_of_depreciations": 6, @@ -1246,6 +1258,7 @@ class TestDepreciationBasics(AssetSetup): asset.append( "finance_books", { + "finance_book": "Test Finance Book 3", "depreciation_method": "Straight Line", "frequency_of_depreciation": 12, "total_number_of_depreciations": 3, @@ -1258,15 +1271,17 @@ class TestDepreciationBasics(AssetSetup): post_depreciation_entries(date="2020-04-01") asset.load_from_db() - asset.clear_depr_schedule() + asset_depr_schedule_doc_1 = get_asset_depr_schedule_doc(asset.name, "Test Finance Book 1") + clear_depr_schedule(asset_depr_schedule_doc_1) + self.assertEqual(len(asset_depr_schedule_doc_1.get("depreciation_schedule")), 3) - self.assertEqual(len(asset.schedules), 6) + asset_depr_schedule_doc_2 = get_asset_depr_schedule_doc(asset.name, "Test Finance Book 2") + clear_depr_schedule(asset_depr_schedule_doc_2) + self.assertEqual(len(asset_depr_schedule_doc_2.get("depreciation_schedule")), 3) - for schedule in asset.schedules: - if schedule.idx <= 3: - self.assertEqual(schedule.finance_book_id, "1") - else: - self.assertEqual(schedule.finance_book_id, "2") + asset_depr_schedule_doc_3 = get_asset_depr_schedule_doc(asset.name, "Test Finance Book 3") + clear_depr_schedule(asset_depr_schedule_doc_3) + self.assertEqual(len(asset_depr_schedule_doc_3.get("depreciation_schedule")), 0) def test_depreciation_schedules_are_set_up_for_multiple_finance_books(self): asset = create_asset(item_code="Macbook Pro", available_for_use_date="2019-12-31", do_not_save=1) @@ -1275,6 +1290,7 @@ class TestDepreciationBasics(AssetSetup): asset.append( "finance_books", { + "finance_book": "Test Finance Book 1", "depreciation_method": "Straight Line", "frequency_of_depreciation": 12, "total_number_of_depreciations": 3, @@ -1285,6 +1301,7 @@ class TestDepreciationBasics(AssetSetup): asset.append( "finance_books", { + "finance_book": "Test Finance Book 2", "depreciation_method": "Straight Line", "frequency_of_depreciation": 12, "total_number_of_depreciations": 6, @@ -1294,13 +1311,11 @@ class TestDepreciationBasics(AssetSetup): ) asset.save() - self.assertEqual(len(asset.schedules), 9) + asset_depr_schedule_doc_1 = get_asset_depr_schedule_doc(asset.name, "Test Finance Book 1") + self.assertEqual(len(asset_depr_schedule_doc_1.get("depreciation_schedule")), 3) - for schedule in asset.schedules: - if schedule.idx <= 3: - self.assertEqual(schedule.finance_book_id, 1) - else: - self.assertEqual(schedule.finance_book_id, 2) + asset_depr_schedule_doc_2 = get_asset_depr_schedule_doc(asset.name, "Test Finance Book 2") + self.assertEqual(len(asset_depr_schedule_doc_2.get("depreciation_schedule")), 6) def test_depreciation_entry_cancellation(self): asset = create_asset( @@ -1320,12 +1335,12 @@ class TestDepreciationBasics(AssetSetup): asset.load_from_db() # cancel depreciation entry - depr_entry = asset.get("schedules")[0].journal_entry + depr_entry = get_depr_schedule(asset.name)[0].journal_entry self.assertTrue(depr_entry) frappe.get_doc("Journal Entry", depr_entry).cancel() asset.load_from_db() - depr_entry = asset.get("schedules")[0].journal_entry + depr_entry = get_depr_schedule(asset.name)[0].journal_entry self.assertFalse(depr_entry) def test_asset_expected_value_after_useful_life(self): @@ -1340,7 +1355,7 @@ class TestDepreciationBasics(AssetSetup): ) accumulated_depreciation_after_full_schedule = max( - d.accumulated_depreciation_amount for d in asset.get("schedules") + d.accumulated_depreciation_amount for d in get_depr_schedule(asset.name) ) asset_value_after_full_schedule = flt(asset.gross_purchase_amount) - flt( @@ -1371,7 +1386,7 @@ class TestDepreciationBasics(AssetSetup): asset.load_from_db() # check depreciation entry series - self.assertEqual(asset.get("schedules")[0].journal_entry[:4], "DEPR") + self.assertEqual(get_depr_schedule(asset.name)[0].journal_entry[:4], "DEPR") expected_gle = ( ("_Test Accumulated Depreciations - _TC", 0.0, 30000.0), @@ -1441,7 +1456,7 @@ class TestDepreciationBasics(AssetSetup): "2020-07-15", ] - for i, schedule in enumerate(asset.schedules): + for i, schedule in enumerate(get_depr_schedule(asset.name)): self.assertEqual(getdate(expected_dates[i]), getdate(schedule.schedule_date)) @@ -1455,6 +1470,15 @@ def create_asset_data(): if not frappe.db.exists("Location", "Test Location"): frappe.get_doc({"doctype": "Location", "location_name": "Test Location"}).insert() + if not frappe.db.exists("Finance Book", "Test Finance Book 1"): + frappe.get_doc({"doctype": "Finance Book", "finance_book_name": "Test Finance Book 1"}).insert() + + if not frappe.db.exists("Finance Book", "Test Finance Book 2"): + frappe.get_doc({"doctype": "Finance Book", "finance_book_name": "Test Finance Book 2"}).insert() + + if not frappe.db.exists("Finance Book", "Test Finance Book 3"): + frappe.get_doc({"doctype": "Finance Book", "finance_book_name": "Test Finance Book 3"}).insert() + def create_asset(**args): args = frappe._dict(args) diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 2cdea574dd..42b7b4b9ee 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -46,33 +46,41 @@ class AssetDepreciationSchedule(Document): ) -def make_draft_asset_depr_schedules(asset_doc, date_of_disposal=None, date_of_return=None): +def make_draft_asset_depr_schedules_if_not_present(asset_doc): for row in asset_doc.get("finance_books"): - asset_depr_schedule_doc = frappe.new_doc("Asset Depreciation Schedule") + asset_depr_schedule_name = get_asset_depr_schedule_name(asset_doc.name, row.finance_book) - prepare_draft_asset_depr_schedule_data( - asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return - ) - - asset_depr_schedule_doc.insert() + if not asset_depr_schedule_name: + make_draft_asset_depr_schedule(asset_doc, row) -def update_draft_asset_depr_schedules(asset_doc, date_of_disposal=None, date_of_return=None): +def make_draft_asset_depr_schedules(asset_doc): + for row in asset_doc.get("finance_books"): + make_draft_asset_depr_schedule(asset_doc, row) + + +def make_draft_asset_depr_schedule(asset_doc, row): + asset_depr_schedule_doc = frappe.new_doc("Asset Depreciation Schedule") + + prepare_draft_asset_depr_schedule_data(asset_depr_schedule_doc, asset_doc, row) + + asset_depr_schedule_doc.insert() + + +def update_draft_asset_depr_schedules(asset_doc): for row in asset_doc.get("finance_books"): asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_doc.name, row.finance_book) if not asset_depr_schedule_doc: continue - prepare_draft_asset_depr_schedule_data( - asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return - ) + prepare_draft_asset_depr_schedule_data(asset_depr_schedule_doc, asset_doc, row) asset_depr_schedule_doc.save() def prepare_draft_asset_depr_schedule_data( - asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return + asset_depr_schedule_doc, asset_doc, row, date_of_disposal=None, date_of_return=None ): set_draft_asset_depr_schedule_details(asset_depr_schedule_doc, asset_doc, row) make_depr_schedule(asset_depr_schedule_doc, asset_doc, row, date_of_disposal) @@ -140,7 +148,7 @@ def cancel_asset_depr_schedules(asset_doc): asset_depr_schedule_doc.cancel() -def get_asset_depr_schedule_name(asset_name, finance_book): +def get_asset_depr_schedule_name(asset_name, finance_book=None): finance_book_filter = ["finance_book", "is", "not set"] if finance_book: finance_book_filter = ["finance_book", "=", finance_book] @@ -156,7 +164,7 @@ def get_asset_depr_schedule_name(asset_name, finance_book): @frappe.whitelist() -def get_depr_schedule(asset_name, finance_book): +def get_depr_schedule(asset_name, finance_book=None): asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_name, finance_book) if not asset_depr_schedule_doc: @@ -165,7 +173,7 @@ def get_depr_schedule(asset_name, finance_book): return asset_depr_schedule_doc.get("depreciation_schedule") -def get_asset_depr_schedule_doc(asset_name, finance_book): +def get_asset_depr_schedule_doc(asset_name, finance_book=None): asset_depr_schedule_name = get_asset_depr_schedule_name(asset_name, finance_book) if not asset_depr_schedule_name: @@ -291,8 +299,8 @@ def _make_depr_schedule(asset_depr_schedule_doc, asset_doc, row, start, date_of_ row, depreciation_amount, schedule_date, asset_doc.to_date ) - depreciation_amount = asset_doc.get_adjusted_depreciation_amount( - depreciation_amount_without_pro_rata, depreciation_amount, row.finance_book + depreciation_amount = get_adjusted_depreciation_amount( + asset_depr_schedule_doc, depreciation_amount_without_pro_rata, depreciation_amount ) monthly_schedule_date = add_months(schedule_date, 1) @@ -325,6 +333,30 @@ def _make_depr_schedule(asset_depr_schedule_doc, asset_doc, row, start, date_of_ ) +# to ensure that final accumulated depreciation amount is accurate +def get_adjusted_depreciation_amount( + asset_depr_schedule_doc, depreciation_amount_without_pro_rata, depreciation_amount_for_last_row +): + if not asset_depr_schedule_doc.opening_accumulated_depreciation: + depreciation_amount_for_first_row = get_depreciation_amount_for_first_row( + asset_depr_schedule_doc + ) + + if ( + depreciation_amount_for_first_row + depreciation_amount_for_last_row + != depreciation_amount_without_pro_rata + ): + depreciation_amount_for_last_row = ( + depreciation_amount_without_pro_rata - depreciation_amount_for_first_row + ) + + return depreciation_amount_for_last_row + + +def get_depreciation_amount_for_first_row(asset_depr_schedule_doc): + return asset_depr_schedule_doc.get("depreciation_schedule")[0].depreciation_amount + + @erpnext.allow_regional def get_depreciation_amount(asset_doc, depreciable_value, row): if row.depreciation_method in ("Straight Line", "Manual"): From 22ef342ac7f87cc94da7ca8d0739a5ce7c3ebef2 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Tue, 13 Dec 2022 20:48:34 +0530 Subject: [PATCH 32/49] chore: fixing all tests --- .../doctype/sales_invoice/sales_invoice.py | 2 + .../sales_invoice/test_sales_invoice.py | 9 +++-- erpnext/assets/doctype/asset/depreciation.py | 35 ++++++++++++------ .../asset_capitalization.py | 2 + .../test_asset_capitalization.py | 7 +++- .../asset_depreciation_schedule.py | 37 +++++++++++++++---- .../doctype/asset_repair/asset_repair.py | 4 ++ .../doctype/asset_repair/test_asset_repair.py | 5 ++- .../asset_value_adjustment.py | 13 +++++-- 9 files changed, 87 insertions(+), 27 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 4168f01859..31cf1206ce 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1192,6 +1192,7 @@ class SalesInvoice(SellingController): get_link_to_form(self.doctype, self.get("name")), ) reset_depreciation_schedule(asset, self.posting_date, notes) + asset.reload() else: if asset.calculate_depreciation: @@ -1202,6 +1203,7 @@ class SalesInvoice(SellingController): get_link_to_form(self.doctype, self.get("name")), ) depreciate_asset(asset, self.posting_date, notes) + asset.reload() fixed_asset_gl_entries = get_gl_entries_on_asset_disposal( asset, item.base_net_amount, item.finance_book, self.get("doctype"), self.get("name") diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 855380ef25..363ca16e99 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -21,6 +21,9 @@ from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_inter_comp from erpnext.accounts.utils import PaymentEntryUnlinkError from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries from erpnext.assets.doctype.asset.test_asset import create_asset, create_asset_data +from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( + get_depr_schedule, +) from erpnext.controllers.accounts_controller import update_invoice_status from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_data from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency @@ -2774,7 +2777,7 @@ class TestSalesInvoice(unittest.TestCase): ["2021-09-30", 5041.1, 26407.22], ] - for i, schedule in enumerate(asset.schedules): + for i, schedule in enumerate(get_depr_schedule(asset.name)): self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) self.assertEqual(expected_values[i][1], schedule.depreciation_amount) self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) @@ -2805,7 +2808,7 @@ class TestSalesInvoice(unittest.TestCase): expected_values = [["2020-12-31", 30000, 30000], ["2021-12-31", 30000, 60000]] - for i, schedule in enumerate(asset.schedules): + for i, schedule in enumerate(get_depr_schedule(asset.name)): self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) self.assertEqual(expected_values[i][1], schedule.depreciation_amount) self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) @@ -2834,7 +2837,7 @@ class TestSalesInvoice(unittest.TestCase): ["2025-06-06", 18633.88, 100000.0, False], ] - for i, schedule in enumerate(asset.schedules): + for i, schedule in enumerate(get_depr_schedule(asset.name)): self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) self.assertEqual(expected_values[i][1], schedule.depreciation_amount) self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index d7d248089a..4278658fd2 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -11,8 +11,8 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( ) from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( + get_asset_depr_schedule_doc, get_asset_depr_schedule_name, - get_depr_schedule, get_temp_asset_depr_schedule_doc, make_new_active_asset_depr_schedules_and_cancel_current_ones, ) @@ -220,6 +220,13 @@ def scrap_asset(asset_name): date = today() + notes = _("This schedule was created when Asset {0} was scrapped.").format( + get_link_to_form(asset.doctype, asset.name) + ) + + depreciate_asset(asset, date, notes) + asset.reload() + depreciation_series = frappe.get_cached_value( "Company", asset.company, "series_for_depreciation_entry" ) @@ -238,12 +245,6 @@ def scrap_asset(asset_name): je.flags.ignore_permissions = True je.submit() - notes = _( - "This schedule was created when Asset {0} was scrapped through Journal Entry {1}." - ).format(get_link_to_form(asset.doctype, asset.name), get_link_to_form(je.doctype, je.name)) - - depreciate_asset(asset, date, notes) - frappe.db.set_value("Asset", asset_name, "disposal_date", date) frappe.db.set_value("Asset", asset_name, "journal_entry_for_scrap", je.name) asset.set_status("Scrapped") @@ -259,9 +260,9 @@ def restore_asset(asset_name): je = asset.journal_entry_for_scrap - notes = _( - "This schedule was created when Asset {0} was restored after being scrapped by Journal Entry {1}." - ).format(get_link_to_form(asset.doctype, asset.name), get_link_to_form(je.doctype, je.name)) + notes = _("This schedule was created when Asset {0} was restored.").format( + get_link_to_form(asset.doctype, asset.name) + ) reset_depreciation_schedule(asset, asset.disposal_date, notes) @@ -274,20 +275,28 @@ def restore_asset(asset_name): def depreciate_asset(asset_doc, date, notes): + asset_doc.flags.ignore_validate_update_after_submit = True + make_new_active_asset_depr_schedules_and_cancel_current_ones( asset_doc, notes, date_of_disposal=date ) + asset_doc.save() + make_depreciation_entry_for_all_asset_depr_schedules(asset_doc, date) def reset_depreciation_schedule(asset_doc, date, notes): + asset_doc.flags.ignore_validate_update_after_submit = True + make_new_active_asset_depr_schedules_and_cancel_current_ones( asset_doc, notes, date_of_return=date ) modify_depreciation_schedule_for_asset_repairs(asset_doc) + asset_doc.save() + def modify_depreciation_schedule_for_asset_repairs(asset): asset_repairs = frappe.get_all( @@ -307,9 +316,9 @@ def modify_depreciation_schedule_for_asset_repairs(asset): def reverse_depreciation_entry_made_after_disposal(asset, date): for row in asset.get("finance_books"): - depr_schedule = get_depr_schedule(asset.name, row.finance_book) + asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset.name, row.finance_book) - for schedule_idx, schedule in enumerate(depr_schedule): + for schedule_idx, schedule in enumerate(asset_depr_schedule_doc.get("depreciation_schedule")): if schedule.schedule_date == date: if not disposal_was_made_on_original_schedule_date( schedule_idx, row, date @@ -321,10 +330,12 @@ def reverse_depreciation_entry_made_after_disposal(asset, date): reverse_journal_entry.submit() frappe.flags.is_reverse_depr_entry = False + asset_depr_schedule_doc.flags.ignore_validate_update_after_submit = True asset.flags.ignore_validate_update_after_submit = True schedule.journal_entry = None depreciation_amount = get_depreciation_amount_in_je(reverse_journal_entry) row.value_after_depreciation += depreciation_amount + asset_depr_schedule_doc.save() asset.save() diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py index 26bac86094..7d3b645be7 100644 --- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py @@ -527,6 +527,8 @@ class AssetCapitalization(StockController): get_link_to_form(asset_doc.doctype, asset_doc.name), get_link_to_form(self.doctype, self.name) ) make_new_active_asset_depr_schedules_and_cancel_current_ones(asset_doc, notes) + asset_doc.flags.ignore_validate_update_after_submit = True + asset_doc.save() elif self.docstatus == 2: for item in self.asset_items: asset = self.get_asset(item) diff --git a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py index 86861f0b16..e99e71b0ac 100644 --- a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py @@ -12,6 +12,9 @@ from erpnext.assets.doctype.asset.test_asset import ( create_asset_data, set_depreciation_settings_in_company, ) +from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( + get_depr_schedule, +) from erpnext.stock.doctype.item.test_item import create_item @@ -283,7 +286,9 @@ class TestAssetCapitalization(unittest.TestCase): self.assertEqual(consumed_asset.status, "Decapitalized") consumed_depreciation_schedule = [ - d for d in consumed_asset.schedules if getdate(d.schedule_date) == getdate(capitalization_date) + d + for d in get_depr_schedule(consumed_asset.name) + if getdate(d.schedule_date) == getdate(capitalization_date) ] self.assertTrue( consumed_depreciation_schedule and consumed_depreciation_schedule[0].journal_entry diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 42b7b4b9ee..0d3241b760 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -80,10 +80,17 @@ def update_draft_asset_depr_schedules(asset_doc): def prepare_draft_asset_depr_schedule_data( - asset_depr_schedule_doc, asset_doc, row, date_of_disposal=None, date_of_return=None + asset_depr_schedule_doc, + asset_doc, + row, + date_of_disposal=None, + date_of_return=None, + update_asset_finance_book_row=True, ): set_draft_asset_depr_schedule_details(asset_depr_schedule_doc, asset_doc, row) - make_depr_schedule(asset_depr_schedule_doc, asset_doc, row, date_of_disposal) + make_depr_schedule( + asset_depr_schedule_doc, asset_doc, row, date_of_disposal, update_asset_finance_book_row + ) set_accumulated_depreciation(asset_depr_schedule_doc, row, date_of_disposal, date_of_return) @@ -129,11 +136,18 @@ def make_new_active_asset_depr_schedules_and_cancel_current_ones( new_asset_depr_schedule_doc.submit() -def get_temp_asset_depr_schedule_doc(asset_doc, row, date_of_disposal=None, date_of_return=None): +def get_temp_asset_depr_schedule_doc( + asset_doc, row, date_of_disposal=None, date_of_return=None, update_asset_finance_book_row=False +): asset_depr_schedule_doc = frappe.new_doc("Asset Depreciation Schedule") prepare_draft_asset_depr_schedule_data( - asset_depr_schedule_doc, asset_doc, row, date_of_disposal, date_of_return + asset_depr_schedule_doc, + asset_doc, + row, + date_of_disposal, + date_of_return, + update_asset_finance_book_row, ) return asset_depr_schedule_doc @@ -184,7 +198,9 @@ def get_asset_depr_schedule_doc(asset_name, finance_book=None): return asset_depr_schedule_doc -def make_depr_schedule(asset_depr_schedule_doc, asset_doc, row, date_of_disposal): +def make_depr_schedule( + asset_depr_schedule_doc, asset_doc, row, date_of_disposal, update_asset_finance_book_row=True +): if row.depreciation_method != "Manual" and not asset_depr_schedule_doc.get( "depreciation_schedule" ): @@ -195,7 +211,9 @@ def make_depr_schedule(asset_depr_schedule_doc, asset_doc, row, date_of_disposal start = clear_depr_schedule(asset_depr_schedule_doc) - _make_depr_schedule(asset_depr_schedule_doc, asset_doc, row, start, date_of_disposal) + _make_depr_schedule( + asset_depr_schedule_doc, asset_doc, row, start, date_of_disposal, update_asset_finance_book_row + ) def clear_depr_schedule(asset_depr_schedule_doc): @@ -216,12 +234,17 @@ def clear_depr_schedule(asset_depr_schedule_doc): return start -def _make_depr_schedule(asset_depr_schedule_doc, asset_doc, row, start, date_of_disposal): +def _make_depr_schedule( + asset_depr_schedule_doc, asset_doc, row, start, date_of_disposal, update_asset_finance_book_row +): asset_doc.validate_asset_finance_books(row) value_after_depreciation = asset_doc._get_value_after_depreciation(row) row.value_after_depreciation = value_after_depreciation + if update_asset_finance_book_row: + row.db_update() + number_of_pending_depreciations = cint(row.total_number_of_depreciations) - cint( asset_doc.number_of_depreciations_booked ) diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py index 2396df93a3..6239915232 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/asset_repair.py @@ -59,7 +59,9 @@ class AssetRepair(AccountsController): notes = _("This schedule was created when Asset Repair {0} was submitted.").format( get_link_to_form(self.doctype, self.name) ) + self.asset_doc.flags.ignore_validate_update_after_submit = True make_new_active_asset_depr_schedules_and_cancel_current_ones(self.asset_doc, notes) + self.asset_doc.save() def before_cancel(self): self.asset_doc = frappe.get_doc("Asset", self.asset) @@ -81,7 +83,9 @@ class AssetRepair(AccountsController): notes = _("This schedule was created when Asset Repair {0} was cancelled.").format( get_link_to_form(self.doctype, self.name) ) + self.asset_doc.flags.ignore_validate_update_after_submit = True make_new_active_asset_depr_schedules_and_cancel_current_ones(self.asset_doc, notes) + self.asset_doc.save() def check_repair_status(self): if self.repair_status == "Pending": diff --git a/erpnext/assets/doctype/asset_repair/test_asset_repair.py b/erpnext/assets/doctype/asset_repair/test_asset_repair.py index 6e06f52ac6..4579b4d56a 100644 --- a/erpnext/assets/doctype/asset_repair/test_asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/test_asset_repair.py @@ -12,6 +12,9 @@ from erpnext.assets.doctype.asset.test_asset import ( create_asset_data, set_depreciation_settings_in_company, ) +from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( + get_depr_schedule, +) from erpnext.stock.doctype.item.test_item import create_item @@ -238,7 +241,7 @@ class TestAssetRepair(unittest.TestCase): self.assertEqual((initial_num_of_depreciations + 1), num_of_depreciations(asset)) self.assertEqual( - asset.schedules[-1].accumulated_depreciation_amount, + get_depr_schedule(asset.name)[-1].accumulated_depreciation_amount, asset.finance_books[0].value_after_depreciation, ) 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 9caca33c30..0248a37030 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py @@ -5,7 +5,7 @@ import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import date_diff, flt, formatdate, getdate +from frappe.utils import date_diff, flt, formatdate, get_link_to_form, getdate from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( get_checks_for_pl_and_bs_accounts, @@ -123,9 +123,16 @@ class AssetValueAdjustment(Document): new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc) - new_asset_depr_schedule_doc.notes = "Asset value adjustment" - current_asset_depr_schedule_doc.cancel() + + notes = _( + "This schedule was created when Asset {0} was adjusted through Asset Value Adjustment {1}." + ).format( + get_link_to_form(asset.doctype, asset.name), + get_link_to_form(self.get("doctype"), self.get("name")), + ) + new_asset_depr_schedule_doc.notes = notes + new_asset_depr_schedule_doc.insert() depr_schedule = new_asset_depr_schedule_doc.get("depreciation_schedule") From c99cd74a15e3a126b68719c26def4be6f209b435 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Wed, 14 Dec 2022 13:20:37 +0530 Subject: [PATCH 33/49] chore: handle some error cases and add empty patch file --- .../asset_depreciation_schedule.py | 16 +++++++++++++--- erpnext/patches.txt | 1 + ...e_asset_depreciation_schedules_from_assets.py | 5 +++++ 3 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 0d3241b760..986acc09d4 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -113,9 +113,9 @@ def convert_draft_asset_depr_schedules_into_active(asset_doc): for row in asset_doc.get("finance_books"): asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_doc.name, row.finance_book) - asset_depr_schedule_doc.status = "Active" - - asset_depr_schedule_doc.submit() + if asset_depr_schedule_doc.status == "Draft": + asset_depr_schedule_doc.status = "Active" + asset_depr_schedule_doc.submit() def make_new_active_asset_depr_schedules_and_cancel_current_ones( @@ -124,6 +124,13 @@ def make_new_active_asset_depr_schedules_and_cancel_current_ones( for row in asset_doc.get("finance_books"): current_asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_doc.name, row.finance_book) + if not current_asset_depr_schedule_doc: + frappe.throw( + _("Asset Depreciation Schedule not found for Asset {0} and Finance Book {1}").format( + asset_doc.name, row.finance_book + ) + ) + new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc) make_depr_schedule(new_asset_depr_schedule_doc, asset_doc, row, date_of_disposal) @@ -157,6 +164,9 @@ def cancel_asset_depr_schedules(asset_doc): for row in asset_doc.get("finance_books"): asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_doc.name, row.finance_book) + if not asset_depr_schedule_doc: + continue + asset_depr_schedule_doc.status = "Cancelled" asset_depr_schedule_doc.cancel() diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 0aad1d34e5..622fda42d8 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -268,6 +268,7 @@ erpnext.patches.v13_0.show_hr_payroll_deprecation_warning erpnext.patches.v13_0.reset_corrupt_defaults erpnext.patches.v13_0.create_accounting_dimensions_for_asset_repair erpnext.patches.v15_0.delete_taxjar_doctypes +erpnext.patches.v15_0.create_asset_depreciation_schedules_from_assets [post_model_sync] execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings') diff --git a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py new file mode 100644 index 0000000000..3e646b487f --- /dev/null +++ b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py @@ -0,0 +1,5 @@ +# import frappe + + +def execute(): + pass From 7f5e761c041310e7dd53ebc12e81b70d69042f7b Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Thu, 15 Dec 2022 13:13:04 +0530 Subject: [PATCH 34/49] chore: add patch --- .../asset_depreciation_schedule.json | 4 +- .../asset_depreciation_schedule.py | 4 +- ...sset_depreciation_schedules_from_assets.py | 89 ++++++++++++++++++- 3 files changed, 92 insertions(+), 5 deletions(-) diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json index 0fea6a5b19..199f73f508 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json @@ -142,7 +142,7 @@ }, { "fieldname": "finance_book_id", - "fieldtype": "Data", + "fieldtype": "Int", "hidden": 1, "label": "Finance Book Id", "print_hide": 1, @@ -161,7 +161,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2022-12-09 15:14:20.562294", + "modified": "2022-12-15 13:01:02.984906", "modified_by": "Administrator", "module": "Assets", "name": "Asset Depreciation Schedule", diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 986acc09d4..5639d3db97 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -167,7 +167,9 @@ def cancel_asset_depr_schedules(asset_doc): if not asset_depr_schedule_doc: continue - asset_depr_schedule_doc.status = "Cancelled" + frappe.db.set_value( + "Asset Depreciation Schedule", asset_depr_schedule_doc.name, "status", "Cancelled" + ) asset_depr_schedule_doc.cancel() diff --git a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py index 3e646b487f..11064a9c84 100644 --- a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py +++ b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py @@ -1,5 +1,90 @@ -# import frappe +import frappe def execute(): - pass + assets = get_details_of_depreciable_assets() + + for asset in assets: + finance_book_rows = get_details_of_asset_finance_books_rows(asset.name) + + for fb_row in finance_book_rows: + asset_depr_schedule_doc = frappe.new_doc("Asset Depreciation Schedule") + + asset_depr_schedule_doc.asset = asset.name + asset_depr_schedule_doc.finance_book = fb_row.finance_book + asset_depr_schedule_doc.finance_book_id = fb_row.idx + asset_depr_schedule_doc.opening_accumulated_depreciation = ( + asset.opening_accumulated_depreciation + ) + asset_depr_schedule_doc.depreciation_method = fb_row.depreciation_method + asset_depr_schedule_doc.total_number_of_depreciations = fb_row.total_number_of_depreciations + asset_depr_schedule_doc.frequency_of_depreciation = fb_row.frequency_of_depreciation + asset_depr_schedule_doc.rate_of_depreciation = fb_row.rate_of_depreciation + asset_depr_schedule_doc.expected_value_after_useful_life = ( + fb_row.expected_value_after_useful_life + ) + asset_depr_schedule_doc.status = "Draft" + + asset_depr_schedule_doc.insert() + + update_depreciation_schedules(asset.name, asset_depr_schedule_doc.name, fb_row.idx) + + if asset.docstatus == 1: + asset_depr_schedule_doc.status = "Active" + asset_depr_schedule_doc.submit() + elif asset.docstatus == 2: + asset_depr_schedule_doc.status = "Cancelled" + asset_depr_schedule_doc.submit() + asset_depr_schedule_doc.cancel() + + +def get_details_of_depreciable_assets(): + asset = frappe.qb.DocType("Asset") + + records = ( + frappe.qb.from_(asset) + .select(asset.name, asset.opening_accumulated_depreciation, asset.docstatus) + .where(asset.calculate_depreciation == 1) + ).run(as_dict=True) + + return records + + +def get_details_of_asset_finance_books_rows(asset_name): + afb = frappe.qb.DocType("Asset Finance Book") + + records = ( + frappe.qb.from_(afb) + .select( + afb.finance_book, + afb.idx, + afb.depreciation_method, + afb.total_number_of_depreciations, + afb.frequency_of_depreciation, + afb.rate_of_depreciation, + afb.expected_value_after_useful_life, + ) + .where((afb.parenttype == "Asset") & (afb.parent == asset_name)) + ).run(as_dict=True) + + return records + + +def update_depreciation_schedules(asset_name, asset_depr_schedule_name, fb_row_idx): + ds = frappe.qb.DocType("Depreciation Schedule") + + depr_schedules = ( + frappe.qb.from_(ds) + .select(ds.name) + .where((ds.parent == asset_name) & (int(ds.finance_book_id) == fb_row_idx)) + ).run(as_dict=True) + + for idx, depr_schedule in enumerate(depr_schedules, start=1): + ( + frappe.qb.update(ds) + .set(ds.idx, idx) + .set(ds.parent, asset_depr_schedule_name) + .set(ds.parentfield, "depreciation_schedule") + .set(ds.parenttype, "Asset Depreciation Schedule") + .where(ds.parent == depr_schedule.name) + ).run() From a358f777746c8acf83b40e6a53d1c3144ab7ae0f Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Thu, 15 Dec 2022 14:50:53 +0530 Subject: [PATCH 35/49] chore: move patch to post_model_sync and cancel asset depr schedule properly --- .../asset_depreciation_schedule.py | 1 + erpnext/patches.txt | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 5639d3db97..05784e77e7 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -170,6 +170,7 @@ def cancel_asset_depr_schedules(asset_doc): frappe.db.set_value( "Asset Depreciation Schedule", asset_depr_schedule_doc.name, "status", "Cancelled" ) + asset_depr_schedule_doc.reload() asset_depr_schedule_doc.cancel() diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 622fda42d8..59d76b115c 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -268,7 +268,6 @@ erpnext.patches.v13_0.show_hr_payroll_deprecation_warning erpnext.patches.v13_0.reset_corrupt_defaults erpnext.patches.v13_0.create_accounting_dimensions_for_asset_repair erpnext.patches.v15_0.delete_taxjar_doctypes -erpnext.patches.v15_0.create_asset_depreciation_schedules_from_assets [post_model_sync] execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings') @@ -319,4 +318,5 @@ erpnext.patches.v13_0.update_schedule_type_in_loans erpnext.patches.v14_0.create_accounting_dimensions_for_asset_capitalization erpnext.patches.v14_0.update_partial_tds_fields erpnext.patches.v14_0.create_incoterms_and_migrate_shipment -erpnext.patches.v14_0.setup_clear_repost_logs \ No newline at end of file +erpnext.patches.v14_0.setup_clear_repost_logs +erpnext.patches.v15_0.create_asset_depreciation_schedules_from_assets \ No newline at end of file From 3e91a56c19c70a962e92e3f5360a2c0d31c4ad05 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Fri, 23 Dec 2022 11:01:18 +0530 Subject: [PATCH 36/49] chore: only consider draft and active assets in patch, and allow asset depr schedule to be manually createed --- .../asset_depreciation_schedule.json | 22 ++++++++++++++++--- ...sset_depreciation_schedules_from_assets.py | 11 ++++------ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json index 199f73f508..14e849b7dd 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json @@ -157,11 +157,10 @@ "read_only": 1 } ], - "in_create": 1, "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2022-12-15 13:01:02.984906", + "modified": "2022-12-15 16:28:44.585745", "modified_by": "Administrator", "module": "Assets", "name": "Asset Depreciation Schedule", @@ -169,6 +168,8 @@ "owner": "Administrator", "permissions": [ { + "amend": 1, + "cancel": 1, "create": 1, "delete": 1, "email": 1, @@ -176,8 +177,23 @@ "print": 1, "read": 1, "report": 1, - "role": "System Manager", + "role": "Accounts User", "share": 1, + "submit": 1, + "write": 1 + }, + { + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Quality Manager", + "share": 1, + "submit": 1, "write": 1 } ], diff --git a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py index 11064a9c84..14d3689791 100644 --- a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py +++ b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py @@ -2,7 +2,7 @@ import frappe def execute(): - assets = get_details_of_depreciable_assets() + assets = get_details_of_draft_or_submitted_depreciable_assets() for asset in assets: finance_book_rows = get_details_of_asset_finance_books_rows(asset.name) @@ -32,19 +32,16 @@ def execute(): if asset.docstatus == 1: asset_depr_schedule_doc.status = "Active" asset_depr_schedule_doc.submit() - elif asset.docstatus == 2: - asset_depr_schedule_doc.status = "Cancelled" - asset_depr_schedule_doc.submit() - asset_depr_schedule_doc.cancel() -def get_details_of_depreciable_assets(): +def get_details_of_draft_or_submitted_depreciable_assets(): asset = frappe.qb.DocType("Asset") records = ( frappe.qb.from_(asset) .select(asset.name, asset.opening_accumulated_depreciation, asset.docstatus) .where(asset.calculate_depreciation == 1) + .where(asset.docstatus < 2) ).run(as_dict=True) return records @@ -76,7 +73,7 @@ def update_depreciation_schedules(asset_name, asset_depr_schedule_name, fb_row_i depr_schedules = ( frappe.qb.from_(ds) .select(ds.name) - .where((ds.parent == asset_name) & (int(ds.finance_book_id) == fb_row_idx)) + .where((ds.parent == asset_name) & (ds.finance_book_id == str(fb_row_idx))) ).run(as_dict=True) for idx, depr_schedule in enumerate(depr_schedules, start=1): From 03662be150e4756e03e3a3ffc2453ccd36d911f1 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Sun, 25 Dec 2022 18:05:19 +0530 Subject: [PATCH 37/49] chore: have different functions for draft. active and cancelled depr schedules --- .../doctype/journal_entry/journal_entry.py | 4 +- .../sales_invoice/test_sales_invoice.py | 8 +- erpnext/assets/doctype/asset/asset.js | 2 +- erpnext/assets/doctype/asset/asset.py | 18 ++-- erpnext/assets/doctype/asset/depreciation.py | 12 ++- erpnext/assets/doctype/asset/test_asset.py | 78 ++++++++++------- .../test_asset_capitalization.py | 4 +- .../asset_depreciation_schedule.py | 85 +++++++++++++------ .../doctype/asset_repair/asset_repair.py | 6 +- .../doctype/asset_repair/test_asset_repair.py | 4 +- .../asset_value_adjustment.py | 10 ++- 11 files changed, 146 insertions(+), 85 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 2bbfe34bea..b9463bc210 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -24,7 +24,7 @@ from erpnext.accounts.utils import ( get_stock_and_account_balance, ) from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_depr_schedule, + get_cancelled_depr_schedule, ) from erpnext.controllers.accounts_controller import AccountsController @@ -287,7 +287,7 @@ class JournalEntry(AccountsController): if d.reference_type == "Asset" and d.reference_name: asset = frappe.get_doc("Asset", d.reference_name) for row in asset.get("finance_books"): - depr_schedule = get_depr_schedule(asset.name, row.finance_book) + depr_schedule = get_cancelled_depr_schedule(asset.name, row.finance_book) for s in depr_schedule: if s.journal_entry == self.name: diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 363ca16e99..22a317c1be 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -22,7 +22,7 @@ from erpnext.accounts.utils import PaymentEntryUnlinkError from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries from erpnext.assets.doctype.asset.test_asset import create_asset, create_asset_data from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_depr_schedule, + get_draft_or_active_depr_schedule, ) from erpnext.controllers.accounts_controller import update_invoice_status from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_data @@ -2777,7 +2777,7 @@ class TestSalesInvoice(unittest.TestCase): ["2021-09-30", 5041.1, 26407.22], ] - for i, schedule in enumerate(get_depr_schedule(asset.name)): + for i, schedule in enumerate(get_draft_or_active_depr_schedule(asset.name)): self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) self.assertEqual(expected_values[i][1], schedule.depreciation_amount) self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) @@ -2808,7 +2808,7 @@ class TestSalesInvoice(unittest.TestCase): expected_values = [["2020-12-31", 30000, 30000], ["2021-12-31", 30000, 60000]] - for i, schedule in enumerate(get_depr_schedule(asset.name)): + for i, schedule in enumerate(get_draft_or_active_depr_schedule(asset.name)): self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) self.assertEqual(expected_values[i][1], schedule.depreciation_amount) self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) @@ -2837,7 +2837,7 @@ class TestSalesInvoice(unittest.TestCase): ["2025-06-06", 18633.88, 100000.0, False], ] - for i, schedule in enumerate(get_depr_schedule(asset.name)): + for i, schedule in enumerate(get_draft_or_active_depr_schedule(asset.name)): self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) self.assertEqual(expected_values[i][1], schedule.depreciation_amount) self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index aa3af3beaf..9754ab3e79 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -209,7 +209,7 @@ frappe.ui.form.on('Asset', { if (frm.doc.finance_books.length == 1) { depr_schedule = (await frappe.call( - "erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule.get_depr_schedule", + "erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule.get_draft_or_active_depr_schedule", { asset_name: frm.doc.name, finance_book: frm.doc.finance_books[0].finance_book || null diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index cb97ccce01..b9274b14d4 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -32,8 +32,8 @@ from erpnext.assets.doctype.asset_category.asset_category import get_asset_categ from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( cancel_asset_depr_schedules, convert_draft_asset_depr_schedules_into_active, - get_asset_depr_schedule_doc, - get_depr_schedule, + get_draft_or_active_asset_depr_schedule_doc, + get_draft_or_active_depr_schedule, make_draft_asset_depr_schedules, make_draft_asset_depr_schedules_if_not_present, set_draft_asset_depr_schedule_details, @@ -337,7 +337,7 @@ class Asset(AccountsController): def validate_expected_value_after_useful_life(self): for row in self.get("finance_books"): - depr_schedule = get_depr_schedule(self.name, row.finance_book) + depr_schedule = get_draft_or_active_depr_schedule(self.name, row.finance_book) if not depr_schedule: continue @@ -393,7 +393,7 @@ class Asset(AccountsController): def delete_depreciation_entries(self): for row in self.get("finance_books"): - depr_schedule = get_depr_schedule(self.name, row.finance_book) + depr_schedule = get_draft_or_active_depr_schedule(self.name, row.finance_book) for d in depr_schedule: if d.journal_entry: @@ -881,7 +881,9 @@ def update_existing_asset(asset, remaining_qty, new_asset_name): expected_value_after_useful_life, ) - current_asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset.name, row.finance_book) + current_asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc( + asset.name, row.finance_book + ) new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc) set_draft_asset_depr_schedule_details(new_asset_depr_schedule_doc, asset, row) @@ -930,7 +932,9 @@ def create_new_asset_after_split(asset, split_qty): new_asset.set_status() for row in new_asset.get("finance_books"): - current_asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset.name, row.finance_book) + current_asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc( + asset.name, row.finance_book + ) new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc) set_draft_asset_depr_schedule_details(new_asset_depr_schedule_doc, new_asset, row) @@ -951,7 +955,7 @@ def create_new_asset_after_split(asset, split_qty): new_asset_depr_schedule_doc.submit() for row in new_asset.get("finance_books"): - depr_schedule = get_depr_schedule(new_asset.name, row.finance_book) + depr_schedule = get_draft_or_active_depr_schedule(new_asset.name, row.finance_book) for term in depr_schedule: # Update references in JV if term.journal_entry: diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index 4278658fd2..3a3123fb16 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -11,8 +11,8 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( ) from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_asset_depr_schedule_doc, - get_asset_depr_schedule_name, + get_draft_or_active_asset_depr_schedule_doc, + get_draft_or_active_asset_depr_schedule_name, get_temp_asset_depr_schedule_doc, make_new_active_asset_depr_schedules_and_cancel_current_ones, ) @@ -51,7 +51,9 @@ def get_depreciable_assets(date): def make_depreciation_entry_for_all_asset_depr_schedules(asset_doc, date=None): for row in asset_doc.get("finance_books"): - asset_depr_schedule_name = get_asset_depr_schedule_name(asset_doc.name, row.finance_book) + asset_depr_schedule_name = get_draft_or_active_asset_depr_schedule_name( + asset_doc.name, row.finance_book + ) make_depreciation_entry(asset_depr_schedule_name, date) @@ -316,7 +318,9 @@ def modify_depreciation_schedule_for_asset_repairs(asset): def reverse_depreciation_entry_made_after_disposal(asset, date): for row in asset.get("finance_books"): - asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset.name, row.finance_book) + asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc( + asset.name, row.finance_book + ) for schedule_idx, schedule in enumerate(asset_depr_schedule_doc.get("depreciation_schedule")): if schedule.schedule_date == date: diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 8835b32bcc..f6da9d3902 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -29,8 +29,8 @@ from erpnext.assets.doctype.asset.depreciation import ( ) from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( clear_depr_schedule, - get_asset_depr_schedule_doc, - get_depr_schedule, + get_draft_or_active_asset_depr_schedule_doc, + get_draft_or_active_depr_schedule, ) from erpnext.stock.doctype.purchase_receipt.purchase_receipt import ( make_purchase_invoice as make_invoice, @@ -384,8 +384,8 @@ class TestAsset(AssetSetup): new_asset = split_asset(asset.name, 2) asset.load_from_db() - depr_schedule_of_asset = get_depr_schedule(asset.name) - depr_schedule_of_new_asset = get_depr_schedule(new_asset.name) + depr_schedule_of_asset = get_draft_or_active_depr_schedule(asset.name) + depr_schedule_of_new_asset = get_draft_or_active_depr_schedule(new_asset.name) self.assertEqual(new_asset.asset_quantity, 2) self.assertEqual(new_asset.gross_purchase_amount, 24000) @@ -637,7 +637,7 @@ class TestDepreciationMethods(AssetSetup): schedules = [ [cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] - for d in get_depr_schedule(asset.name) + for d in get_draft_or_active_depr_schedule(asset.name) ] self.assertEqual(schedules, expected_schedules) @@ -659,7 +659,7 @@ class TestDepreciationMethods(AssetSetup): expected_schedules = [["2032-12-31", 30000.0, 77095.89], ["2033-06-06", 12904.11, 90000.0]] schedules = [ [cstr(d.schedule_date), flt(d.depreciation_amount, 2), d.accumulated_depreciation_amount] - for d in get_depr_schedule(asset.name) + for d in get_draft_or_active_depr_schedule(asset.name) ] self.assertEqual(schedules, expected_schedules) @@ -686,7 +686,7 @@ class TestDepreciationMethods(AssetSetup): schedules = [ [cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] - for d in get_depr_schedule(asset.name) + for d in get_draft_or_active_depr_schedule(asset.name) ] self.assertEqual(schedules, expected_schedules) @@ -711,7 +711,7 @@ class TestDepreciationMethods(AssetSetup): schedules = [ [cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] - for d in get_depr_schedule(asset.name) + for d in get_draft_or_active_depr_schedule(asset.name) ] self.assertEqual(schedules, expected_schedules) @@ -741,7 +741,7 @@ class TestDepreciationMethods(AssetSetup): flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2), ] - for d in get_depr_schedule(asset.name) + for d in get_draft_or_active_depr_schedule(asset.name) ] self.assertEqual(schedules, expected_schedules) @@ -773,7 +773,7 @@ class TestDepreciationMethods(AssetSetup): flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2), ] - for d in get_depr_schedule(asset.name) + for d in get_draft_or_active_depr_schedule(asset.name) ] self.assertEqual(schedules, expected_schedules) @@ -806,7 +806,7 @@ class TestDepreciationMethods(AssetSetup): flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2), ] - for d in get_depr_schedule(asset.name) + for d in get_draft_or_active_depr_schedule(asset.name) ] self.assertEqual(schedules, expected_schedules) @@ -839,7 +839,7 @@ class TestDepreciationMethods(AssetSetup): flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2), ] - for d in get_depr_schedule(asset.name) + for d in get_draft_or_active_depr_schedule(asset.name) ] self.assertEqual(schedules, expected_schedules) @@ -862,7 +862,7 @@ class TestDepreciationBasics(AssetSetup): ["2022-12-31", 30000, 90000], ] - for i, schedule in enumerate(get_depr_schedule(asset.name)): + for i, schedule in enumerate(get_draft_or_active_depr_schedule(asset.name)): self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) self.assertEqual(expected_values[i][1], schedule.depreciation_amount) self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) @@ -885,7 +885,7 @@ class TestDepreciationBasics(AssetSetup): ["2023-01-01", 15000, 90000], ] - for i, schedule in enumerate(get_depr_schedule(asset.name)): + for i, schedule in enumerate(get_draft_or_active_depr_schedule(asset.name)): self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) self.assertEqual(expected_values[i][1], schedule.depreciation_amount) self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) @@ -930,7 +930,7 @@ class TestDepreciationBasics(AssetSetup): expected_values = [["2020-12-31", 30000.0], ["2021-12-31", 30000.0], ["2022-12-31", 30000.0]] - for i, schedule in enumerate(get_depr_schedule(asset.name)): + for i, schedule in enumerate(get_draft_or_active_depr_schedule(asset.name)): self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) self.assertEqual(expected_values[i][1], schedule.depreciation_amount) @@ -950,7 +950,7 @@ class TestDepreciationBasics(AssetSetup): expected_values = [30000.0, 60000.0, 90000.0] - for i, schedule in enumerate(get_depr_schedule(asset.name)): + for i, schedule in enumerate(get_draft_or_active_depr_schedule(asset.name)): self.assertEqual(expected_values[i], schedule.accumulated_depreciation_amount) def test_check_is_pro_rata(self): @@ -1130,9 +1130,9 @@ class TestDepreciationBasics(AssetSetup): post_depreciation_entries(date="2021-06-01") asset.load_from_db() - self.assertTrue(get_depr_schedule(asset.name)[0].journal_entry) - self.assertFalse(get_depr_schedule(asset.name)[1].journal_entry) - self.assertFalse(get_depr_schedule(asset.name)[2].journal_entry) + self.assertTrue(get_draft_or_active_depr_schedule(asset.name)[0].journal_entry) + self.assertFalse(get_draft_or_active_depr_schedule(asset.name)[1].journal_entry) + self.assertFalse(get_draft_or_active_depr_schedule(asset.name)[2].journal_entry) def test_depr_entry_posting_when_depr_expense_account_is_an_expense_account(self): """Tests if the Depreciation Expense Account gets debited and the Accumulated Depreciation Account gets credited when the former's an Expense Account.""" @@ -1151,7 +1151,9 @@ class TestDepreciationBasics(AssetSetup): post_depreciation_entries(date="2021-06-01") asset.load_from_db() - je = frappe.get_doc("Journal Entry", get_depr_schedule(asset.name)[0].journal_entry) + je = frappe.get_doc( + "Journal Entry", get_draft_or_active_depr_schedule(asset.name)[0].journal_entry + ) accounting_entries = [ {"account": entry.account, "debit": entry.debit, "credit": entry.credit} for entry in je.accounts @@ -1187,7 +1189,9 @@ class TestDepreciationBasics(AssetSetup): post_depreciation_entries(date="2021-06-01") asset.load_from_db() - je = frappe.get_doc("Journal Entry", get_depr_schedule(asset.name)[0].journal_entry) + je = frappe.get_doc( + "Journal Entry", get_draft_or_active_depr_schedule(asset.name)[0].journal_entry + ) accounting_entries = [ {"account": entry.account, "debit": entry.debit, "credit": entry.credit} for entry in je.accounts @@ -1223,7 +1227,7 @@ class TestDepreciationBasics(AssetSetup): post_depreciation_entries(date="2021-06-01") asset.load_from_db() - asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset.name) + asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc(asset.name) clear_depr_schedule(asset_depr_schedule_doc) @@ -1271,15 +1275,21 @@ class TestDepreciationBasics(AssetSetup): post_depreciation_entries(date="2020-04-01") asset.load_from_db() - asset_depr_schedule_doc_1 = get_asset_depr_schedule_doc(asset.name, "Test Finance Book 1") + asset_depr_schedule_doc_1 = get_draft_or_active_asset_depr_schedule_doc( + asset.name, "Test Finance Book 1" + ) clear_depr_schedule(asset_depr_schedule_doc_1) self.assertEqual(len(asset_depr_schedule_doc_1.get("depreciation_schedule")), 3) - asset_depr_schedule_doc_2 = get_asset_depr_schedule_doc(asset.name, "Test Finance Book 2") + asset_depr_schedule_doc_2 = get_draft_or_active_asset_depr_schedule_doc( + asset.name, "Test Finance Book 2" + ) clear_depr_schedule(asset_depr_schedule_doc_2) self.assertEqual(len(asset_depr_schedule_doc_2.get("depreciation_schedule")), 3) - asset_depr_schedule_doc_3 = get_asset_depr_schedule_doc(asset.name, "Test Finance Book 3") + asset_depr_schedule_doc_3 = get_draft_or_active_asset_depr_schedule_doc( + asset.name, "Test Finance Book 3" + ) clear_depr_schedule(asset_depr_schedule_doc_3) self.assertEqual(len(asset_depr_schedule_doc_3.get("depreciation_schedule")), 0) @@ -1311,10 +1321,14 @@ class TestDepreciationBasics(AssetSetup): ) asset.save() - asset_depr_schedule_doc_1 = get_asset_depr_schedule_doc(asset.name, "Test Finance Book 1") + asset_depr_schedule_doc_1 = get_draft_or_active_asset_depr_schedule_doc( + asset.name, "Test Finance Book 1" + ) self.assertEqual(len(asset_depr_schedule_doc_1.get("depreciation_schedule")), 3) - asset_depr_schedule_doc_2 = get_asset_depr_schedule_doc(asset.name, "Test Finance Book 2") + asset_depr_schedule_doc_2 = get_draft_or_active_asset_depr_schedule_doc( + asset.name, "Test Finance Book 2" + ) self.assertEqual(len(asset_depr_schedule_doc_2.get("depreciation_schedule")), 6) def test_depreciation_entry_cancellation(self): @@ -1335,12 +1349,12 @@ class TestDepreciationBasics(AssetSetup): asset.load_from_db() # cancel depreciation entry - depr_entry = get_depr_schedule(asset.name)[0].journal_entry + depr_entry = get_draft_or_active_depr_schedule(asset.name)[0].journal_entry self.assertTrue(depr_entry) frappe.get_doc("Journal Entry", depr_entry).cancel() asset.load_from_db() - depr_entry = get_depr_schedule(asset.name)[0].journal_entry + depr_entry = get_draft_or_active_depr_schedule(asset.name)[0].journal_entry self.assertFalse(depr_entry) def test_asset_expected_value_after_useful_life(self): @@ -1355,7 +1369,7 @@ class TestDepreciationBasics(AssetSetup): ) accumulated_depreciation_after_full_schedule = max( - d.accumulated_depreciation_amount for d in get_depr_schedule(asset.name) + d.accumulated_depreciation_amount for d in get_draft_or_active_depr_schedule(asset.name) ) asset_value_after_full_schedule = flt(asset.gross_purchase_amount) - flt( @@ -1386,7 +1400,7 @@ class TestDepreciationBasics(AssetSetup): asset.load_from_db() # check depreciation entry series - self.assertEqual(get_depr_schedule(asset.name)[0].journal_entry[:4], "DEPR") + self.assertEqual(get_draft_or_active_depr_schedule(asset.name)[0].journal_entry[:4], "DEPR") expected_gle = ( ("_Test Accumulated Depreciations - _TC", 0.0, 30000.0), @@ -1456,7 +1470,7 @@ class TestDepreciationBasics(AssetSetup): "2020-07-15", ] - for i, schedule in enumerate(get_depr_schedule(asset.name)): + for i, schedule in enumerate(get_draft_or_active_depr_schedule(asset.name)): self.assertEqual(getdate(expected_dates[i]), getdate(schedule.schedule_date)) diff --git a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py index e99e71b0ac..abbbd209a7 100644 --- a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py @@ -13,7 +13,7 @@ from erpnext.assets.doctype.asset.test_asset import ( set_depreciation_settings_in_company, ) from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_depr_schedule, + get_draft_or_active_depr_schedule, ) from erpnext.stock.doctype.item.test_item import create_item @@ -287,7 +287,7 @@ class TestAssetCapitalization(unittest.TestCase): consumed_depreciation_schedule = [ d - for d in get_depr_schedule(consumed_asset.name) + for d in get_draft_or_active_depr_schedule(consumed_asset.name) if getdate(d.schedule_date) == getdate(capitalization_date) ] self.assertTrue( diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 05784e77e7..47965cf6aa 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -35,20 +35,19 @@ class AssetDepreciationSchedule(Document): ], ) - if num_asset_depr_schedules == 1: - asset_depr_schedule_name = get_asset_depr_schedule_name(self.asset, self.finance_book) - - if self.name != asset_depr_schedule_name: - frappe.throw( - _("Asset Depreciation Schedule for Asset {0} and Finance Book {1} already exists.").format( - self.asset, self.finance_book - ) + if num_asset_depr_schedules > 1: + frappe.throw( + _("Asset Depreciation Schedule for Asset {0} and Finance Book {1} already exists.").format( + self.asset, self.finance_book ) + ) def make_draft_asset_depr_schedules_if_not_present(asset_doc): for row in asset_doc.get("finance_books"): - asset_depr_schedule_name = get_asset_depr_schedule_name(asset_doc.name, row.finance_book) + asset_depr_schedule_name = get_draft_or_active_asset_depr_schedule_name( + asset_doc.name, row.finance_book + ) if not asset_depr_schedule_name: make_draft_asset_depr_schedule(asset_doc, row) @@ -69,7 +68,9 @@ def make_draft_asset_depr_schedule(asset_doc, row): def update_draft_asset_depr_schedules(asset_doc): for row in asset_doc.get("finance_books"): - asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_doc.name, row.finance_book) + asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc( + asset_doc.name, row.finance_book + ) if not asset_depr_schedule_doc: continue @@ -111,7 +112,9 @@ def set_draft_asset_depr_schedule_details(asset_depr_schedule_doc, asset_doc, ro def convert_draft_asset_depr_schedules_into_active(asset_doc): for row in asset_doc.get("finance_books"): - asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_doc.name, row.finance_book) + asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc( + asset_doc.name, row.finance_book + ) if asset_depr_schedule_doc.status == "Draft": asset_depr_schedule_doc.status = "Active" @@ -122,7 +125,9 @@ def make_new_active_asset_depr_schedules_and_cancel_current_ones( asset_doc, notes, date_of_disposal=None, date_of_return=None ): for row in asset_doc.get("finance_books"): - current_asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_doc.name, row.finance_book) + current_asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc( + asset_doc.name, row.finance_book + ) if not current_asset_depr_schedule_doc: frappe.throw( @@ -162,20 +167,17 @@ def get_temp_asset_depr_schedule_doc( def cancel_asset_depr_schedules(asset_doc): for row in asset_doc.get("finance_books"): - asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_doc.name, row.finance_book) + asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc( + asset_doc.name, row.finance_book + ) if not asset_depr_schedule_doc: continue - frappe.db.set_value( - "Asset Depreciation Schedule", asset_depr_schedule_doc.name, "status", "Cancelled" - ) - asset_depr_schedule_doc.reload() - asset_depr_schedule_doc.cancel() -def get_asset_depr_schedule_name(asset_name, finance_book=None): +def get_draft_or_active_asset_depr_schedule_name(asset_name, finance_book=None): finance_book_filter = ["finance_book", "is", "not set"] if finance_book: finance_book_filter = ["finance_book", "=", finance_book] @@ -185,14 +187,29 @@ def get_asset_depr_schedule_name(asset_name, finance_book=None): filters=[ ["asset", "=", asset_name], finance_book_filter, - ["docstatus", "<", 2], + ["status", "in", ["Draft", "Active"]], + ], + ) + + +def get_cancelled_asset_depr_schedule_name(asset_name, finance_book=None): + 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 Depreciation Schedule", + filters=[ + ["asset", "=", asset_name], + finance_book_filter, + ["docstatus", "=", "2"], ], ) @frappe.whitelist() -def get_depr_schedule(asset_name, finance_book=None): - asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_name, finance_book) +def get_draft_or_active_depr_schedule(asset_name, finance_book=None): + asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc(asset_name, finance_book) if not asset_depr_schedule_doc: return @@ -200,8 +217,28 @@ def get_depr_schedule(asset_name, finance_book=None): return asset_depr_schedule_doc.get("depreciation_schedule") -def get_asset_depr_schedule_doc(asset_name, finance_book=None): - asset_depr_schedule_name = get_asset_depr_schedule_name(asset_name, finance_book) +def get_cancelled_depr_schedule(asset_name, finance_book=None): + asset_depr_schedule_doc = get_cancelled_asset_depr_schedule_doc(asset_name, finance_book) + + if not asset_depr_schedule_doc: + return + + return asset_depr_schedule_doc.get("depreciation_schedule") + + +def get_draft_or_active_asset_depr_schedule_doc(asset_name, finance_book=None): + asset_depr_schedule_name = get_draft_or_active_asset_depr_schedule_name(asset_name, finance_book) + + if not asset_depr_schedule_name: + return + + asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) + + return asset_depr_schedule_doc + + +def get_cancelled_asset_depr_schedule_doc(asset_name, finance_book=None): + asset_depr_schedule_name = get_cancelled_asset_depr_schedule_name(asset_name, finance_book) if not asset_depr_schedule_name: return diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py index 6239915232..c5036fa9e2 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/asset_repair.py @@ -9,7 +9,7 @@ import erpnext from erpnext.accounts.general_ledger import make_gl_entries from erpnext.assets.doctype.asset.asset import get_asset_account from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_depr_schedule, + get_draft_or_active_depr_schedule, make_new_active_asset_depr_schedules_and_cancel_current_ones, ) from erpnext.controllers.accounts_controller import AccountsController @@ -289,7 +289,7 @@ class AssetRepair(AccountsController): asset.number_of_depreciations_booked ) - depr_schedule = get_depr_schedule(asset.name, row.finance_book) + depr_schedule = get_draft_or_active_depr_schedule(asset.name, row.finance_book) # the Schedule Date in the final row of the old Depreciation Schedule last_schedule_date = depr_schedule[len(depr_schedule) - 1].schedule_date @@ -322,7 +322,7 @@ class AssetRepair(AccountsController): asset.number_of_depreciations_booked ) - depr_schedule = get_depr_schedule(asset.name, row.finance_book) + depr_schedule = get_draft_or_active_depr_schedule(asset.name, row.finance_book) # the Schedule Date in the final row of the modified Depreciation Schedule last_schedule_date = depr_schedule[len(depr_schedule) - 1].schedule_date diff --git a/erpnext/assets/doctype/asset_repair/test_asset_repair.py b/erpnext/assets/doctype/asset_repair/test_asset_repair.py index 4579b4d56a..8ba3c0eda0 100644 --- a/erpnext/assets/doctype/asset_repair/test_asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/test_asset_repair.py @@ -13,7 +13,7 @@ from erpnext.assets.doctype.asset.test_asset import ( set_depreciation_settings_in_company, ) from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_depr_schedule, + get_draft_or_active_depr_schedule, ) from erpnext.stock.doctype.item.test_item import create_item @@ -241,7 +241,7 @@ class TestAssetRepair(unittest.TestCase): self.assertEqual((initial_num_of_depreciations + 1), num_of_depreciations(asset)) self.assertEqual( - get_depr_schedule(asset.name)[-1].accumulated_depreciation_amount, + get_draft_or_active_depr_schedule(asset.name)[-1].accumulated_depreciation_amount, asset.finance_books[0].value_after_depreciation, ) 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 0248a37030..3ead832ee2 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py @@ -12,8 +12,8 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( ) from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_asset_depr_schedule_name, get_depreciation_amount, + get_draft_or_active_asset_depr_schedule_doc, set_accumulated_depreciation, ) @@ -116,12 +116,13 @@ class AssetValueAdjustment(Document): for d in asset.finance_books: d.value_after_depreciation = asset_value - current_asset_depr_schedule_name = get_asset_depr_schedule_name(asset.name, d.finance_book) - current_asset_depr_schedule_doc = frappe.get_doc( - "Asset Depreciation Schedule", current_asset_depr_schedule_name + current_asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc( + asset.name, d.finance_book ) new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc) + new_asset_depr_schedule_doc.status = "Draft" + new_asset_depr_schedule_doc.docstatus = 0 current_asset_depr_schedule_doc.cancel() @@ -166,6 +167,7 @@ class AssetValueAdjustment(Document): if not asset_data.journal_entry: asset_data.db_update() + new_asset_depr_schedule_doc.status = "Active" new_asset_depr_schedule_doc.submit() From 6d791cabd15f9cd6737b220c7305c0ec5ea67646 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Mon, 26 Dec 2022 22:13:11 +0530 Subject: [PATCH 38/49] chore: more refactoring --- .../doctype/journal_entry/journal_entry.py | 4 +- .../asset_depreciation_schedule.json | 3 +- .../asset_depreciation_schedule.py | 42 ++++++++++++------- .../asset_value_adjustment.py | 1 - ...sset_depreciation_schedules_from_assets.py | 1 - 5 files changed, 32 insertions(+), 19 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index b9463bc210..d69777a21a 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -24,7 +24,7 @@ from erpnext.accounts.utils import ( get_stock_and_account_balance, ) from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_cancelled_depr_schedule, + get_draft_or_active_depr_schedule, ) from erpnext.controllers.accounts_controller import AccountsController @@ -287,7 +287,7 @@ class JournalEntry(AccountsController): if d.reference_type == "Asset" and d.reference_name: asset = frappe.get_doc("Asset", d.reference_name) for row in asset.get("finance_books"): - depr_schedule = get_cancelled_depr_schedule(asset.name, row.finance_book) + depr_schedule = get_draft_or_active_depr_schedule(asset.name, row.finance_book) for s in depr_schedule: if s.journal_entry == self.name: diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json index 14e849b7dd..f6f594c51e 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json @@ -157,10 +157,11 @@ "read_only": 1 } ], + "in_create": 1, "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2022-12-15 16:28:44.585745", + "modified": "2022-12-26 20:32:43.342271", "modified_by": "Administrator", "module": "Assets", "name": "Asset Depreciation Schedule", diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 47965cf6aa..d004bdbf61 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -42,6 +42,12 @@ class AssetDepreciationSchedule(Document): ) ) + def on_submit(self): + self.db_set("status", "Active") + + def on_cancel(self): + self.db_set("status", "Cancelled") + def make_draft_asset_depr_schedules_if_not_present(asset_doc): for row in asset_doc.get("finance_books"): @@ -121,6 +127,18 @@ def convert_draft_asset_depr_schedules_into_active(asset_doc): asset_depr_schedule_doc.submit() +def cancel_asset_depr_schedules(asset_doc): + for row in asset_doc.get("finance_books"): + asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc( + asset_doc.name, row.finance_book + ) + + if not asset_depr_schedule_doc: + continue + + asset_depr_schedule_doc.cancel() + + def make_new_active_asset_depr_schedules_and_cancel_current_ones( asset_doc, notes, date_of_disposal=None, date_of_return=None ): @@ -165,18 +183,6 @@ def get_temp_asset_depr_schedule_doc( return asset_depr_schedule_doc -def cancel_asset_depr_schedules(asset_doc): - for row in asset_doc.get("finance_books"): - asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc( - asset_doc.name, row.finance_book - ) - - if not asset_depr_schedule_doc: - continue - - asset_depr_schedule_doc.cancel() - - def get_draft_or_active_asset_depr_schedule_name(asset_name, finance_book=None): finance_book_filter = ["finance_book", "is", "not set"] if finance_book: @@ -197,15 +203,23 @@ def get_cancelled_asset_depr_schedule_name(asset_name, finance_book=None): if finance_book: finance_book_filter = ["finance_book", "=", finance_book] - return frappe.db.get_value( + cancelled_asset_depr_schedule_names = frappe.db.get_all( doctype="Asset Depreciation Schedule", filters=[ ["asset", "=", asset_name], finance_book_filter, - ["docstatus", "=", "2"], + ["status", "=", "Cancelled"], ], + order_by="creation desc", + limit=1, + pluck="name", ) + if cancelled_asset_depr_schedule_names: + return cancelled_asset_depr_schedule_names[0] + + return + @frappe.whitelist() def get_draft_or_active_depr_schedule(asset_name, finance_book=None): 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 3ead832ee2..90ecfec5af 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py @@ -167,7 +167,6 @@ class AssetValueAdjustment(Document): if not asset_data.journal_entry: asset_data.db_update() - new_asset_depr_schedule_doc.status = "Active" new_asset_depr_schedule_doc.submit() diff --git a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py index 14d3689791..8dcbb2a1cc 100644 --- a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py +++ b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py @@ -30,7 +30,6 @@ def execute(): update_depreciation_schedules(asset.name, asset_depr_schedule_doc.name, fb_row.idx) if asset.docstatus == 1: - asset_depr_schedule_doc.status = "Active" asset_depr_schedule_doc.submit() From 482116db9f926ff88d9a874302b96c8591d8e2e4 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Tue, 27 Dec 2022 10:03:32 +0530 Subject: [PATCH 39/49] chore: improve tests --- erpnext/assets/doctype/asset/test_asset.py | 40 +++++++++++++++++-- .../test_asset_capitalization.py | 15 ++++++- .../asset_depreciation_schedule.py | 4 +- .../doctype/asset_repair/test_asset_repair.py | 14 ++++++- .../test_asset_value_adjustment.py | 12 ++++++ 5 files changed, 77 insertions(+), 8 deletions(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index f6da9d3902..b0a8653eca 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -210,6 +210,9 @@ class TestAsset(AssetSetup): submit=1, ) + first_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset.name) + self.assertEquals(first_asset_depr_schedule.status, "Active") + post_depreciation_entries(date=add_months(purchase_date, 2)) asset.load_from_db() @@ -221,6 +224,11 @@ class TestAsset(AssetSetup): scrap_asset(asset.name) asset.load_from_db() + first_asset_depr_schedule.load_from_db() + + second_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset.name) + self.assertEquals(second_asset_depr_schedule.status, "Active") + self.assertEquals(first_asset_depr_schedule.status, "Cancelled") accumulated_depr_amount = flt( asset.gross_purchase_amount - asset.finance_books[0].value_after_depreciation, @@ -261,6 +269,11 @@ class TestAsset(AssetSetup): self.assertSequenceEqual(gle, expected_gle) restore_asset(asset.name) + second_asset_depr_schedule.load_from_db() + + third_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset.name) + self.assertEquals(third_asset_depr_schedule.status, "Active") + self.assertEquals(second_asset_depr_schedule.status, "Cancelled") asset.load_from_db() self.assertFalse(asset.journal_entry_for_scrap) @@ -288,6 +301,9 @@ class TestAsset(AssetSetup): submit=1, ) + first_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset.name) + self.assertEquals(first_asset_depr_schedule.status, "Active") + post_depreciation_entries(date=add_months(purchase_date, 2)) si = make_sales_invoice(asset=asset.name, item_code="Macbook Pro", company="_Test Company") @@ -299,6 +315,12 @@ class TestAsset(AssetSetup): self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Sold") + first_asset_depr_schedule.load_from_db() + + second_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset.name) + self.assertEquals(second_asset_depr_schedule.status, "Active") + self.assertEquals(first_asset_depr_schedule.status, "Cancelled") + pro_rata_amount, _, _ = asset.get_pro_rata_amt( asset.finance_books[0], 9000, get_last_day(add_months(purchase_date, 1)), date ) @@ -375,6 +397,9 @@ class TestAsset(AssetSetup): submit=1, ) + first_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset.name) + self.assertEquals(first_asset_depr_schedule.status, "Active") + post_depreciation_entries(date="2021-01-01") self.assertEqual(asset.asset_quantity, 10) @@ -383,9 +408,18 @@ class TestAsset(AssetSetup): new_asset = split_asset(asset.name, 2) asset.load_from_db() + first_asset_depr_schedule.load_from_db() - depr_schedule_of_asset = get_draft_or_active_depr_schedule(asset.name) - depr_schedule_of_new_asset = get_draft_or_active_depr_schedule(new_asset.name) + second_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset.name) + first_asset_depr_schedule_of_new_asset = get_draft_or_active_asset_depr_schedule_doc( + new_asset.name + ) + self.assertEquals(second_asset_depr_schedule.status, "Active") + self.assertEquals(first_asset_depr_schedule_of_new_asset.status, "Active") + self.assertEquals(first_asset_depr_schedule.status, "Cancelled") + + depr_schedule_of_asset = second_asset_depr_schedule.get("depreciation_schedule") + depr_schedule_of_new_asset = first_asset_depr_schedule_of_new_asset.get("depreciation_schedule") self.assertEqual(new_asset.asset_quantity, 2) self.assertEqual(new_asset.gross_purchase_amount, 24000) @@ -1351,9 +1385,9 @@ class TestDepreciationBasics(AssetSetup): # cancel depreciation entry depr_entry = get_draft_or_active_depr_schedule(asset.name)[0].journal_entry self.assertTrue(depr_entry) + frappe.get_doc("Journal Entry", depr_entry).cancel() - asset.load_from_db() depr_entry = get_draft_or_active_depr_schedule(asset.name)[0].journal_entry self.assertFalse(depr_entry) diff --git a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py index abbbd209a7..897c678c08 100644 --- a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py @@ -13,7 +13,7 @@ from erpnext.assets.doctype.asset.test_asset import ( set_depreciation_settings_in_company, ) from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_draft_or_active_depr_schedule, + get_draft_or_active_asset_depr_schedule_doc, ) from erpnext.stock.doctype.item.test_item import create_item @@ -256,6 +256,9 @@ class TestAssetCapitalization(unittest.TestCase): submit=1, ) + first_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(consumed_asset.name) + self.assertEquals(first_asset_depr_schedule.status, "Active") + # Create and submit Asset Captitalization asset_capitalization = create_asset_capitalization( entry_type="Decapitalization", @@ -285,9 +288,17 @@ class TestAssetCapitalization(unittest.TestCase): consumed_asset.reload() self.assertEqual(consumed_asset.status, "Decapitalized") + first_asset_depr_schedule.load_from_db() + + second_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(consumed_asset.name) + self.assertEquals(second_asset_depr_schedule.status, "Active") + self.assertEquals(first_asset_depr_schedule.status, "Cancelled") + + depr_schedule_of_consumed_asset = second_asset_depr_schedule.get("depreciation_schedule") + consumed_depreciation_schedule = [ d - for d in get_draft_or_active_depr_schedule(consumed_asset.name) + for d in depr_schedule_of_consumed_asset if getdate(d.schedule_date) == getdate(capitalization_date) ] self.assertTrue( diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index d004bdbf61..7a35013929 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -122,8 +122,10 @@ def convert_draft_asset_depr_schedules_into_active(asset_doc): asset_doc.name, row.finance_book ) + if not asset_depr_schedule_doc: + continue + if asset_depr_schedule_doc.status == "Draft": - asset_depr_schedule_doc.status = "Active" asset_depr_schedule_doc.submit() diff --git a/erpnext/assets/doctype/asset_repair/test_asset_repair.py b/erpnext/assets/doctype/asset_repair/test_asset_repair.py index 8ba3c0eda0..8618392ea2 100644 --- a/erpnext/assets/doctype/asset_repair/test_asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/test_asset_repair.py @@ -13,7 +13,7 @@ from erpnext.assets.doctype.asset.test_asset import ( set_depreciation_settings_in_company, ) from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_draft_or_active_depr_schedule, + get_draft_or_active_asset_depr_schedule_doc, ) from erpnext.stock.doctype.item.test_item import create_item @@ -235,13 +235,23 @@ class TestAssetRepair(unittest.TestCase): def test_increase_in_asset_life(self): asset = create_asset(calculate_depreciation=1, submit=1) + + first_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset.name) + self.assertEquals(first_asset_depr_schedule.status, "Active") + initial_num_of_depreciations = num_of_depreciations(asset) create_asset_repair(asset=asset, capitalize_repair_cost=1, submit=1) + asset.reload() + first_asset_depr_schedule.load_from_db() + + second_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset.name) + self.assertEquals(second_asset_depr_schedule.status, "Active") + self.assertEquals(first_asset_depr_schedule.status, "Cancelled") self.assertEqual((initial_num_of_depreciations + 1), num_of_depreciations(asset)) self.assertEqual( - get_draft_or_active_depr_schedule(asset.name)[-1].accumulated_depreciation_amount, + second_asset_depr_schedule.get("depreciation_schedule")[-1].accumulated_depreciation_amount, asset.finance_books[0].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 62c636624c..780c9db02b 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 @@ -7,6 +7,9 @@ import frappe from frappe.utils import add_days, get_last_day, nowdate from erpnext.assets.doctype.asset.test_asset import create_asset_data +from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( + get_draft_or_active_asset_depr_schedule_doc, +) from erpnext.assets.doctype.asset_value_adjustment.asset_value_adjustment import ( get_current_asset_value, ) @@ -73,12 +76,21 @@ class TestAssetValueAdjustment(unittest.TestCase): ) asset_doc.submit() + first_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset_doc.name) + self.assertEquals(first_asset_depr_schedule.status, "Active") + current_value = get_current_asset_value(asset_doc.name) adj_doc = make_asset_value_adjustment( asset=asset_doc.name, current_asset_value=current_value, new_asset_value=50000.0 ) adj_doc.submit() + first_asset_depr_schedule.load_from_db() + + second_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset_doc.name) + self.assertEquals(second_asset_depr_schedule.status, "Active") + self.assertEquals(first_asset_depr_schedule.status, "Cancelled") + expected_gle = ( ("_Test Accumulated Depreciations - _TC", 0.0, 50000.0), ("_Test Depreciations - _TC", 50000.0, 0.0), From 57adcc0b031eb9ceeff6eda050c7a7c90add1e93 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Tue, 27 Dec 2022 12:10:52 +0530 Subject: [PATCH 40/49] chore: move patch to pre_model_sync --- erpnext/patches.txt | 4 ++-- .../v15_0/create_asset_depreciation_schedules_from_assets.py | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index ddceb3acfb..74f866e20e 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -268,6 +268,7 @@ erpnext.patches.v13_0.show_hr_payroll_deprecation_warning erpnext.patches.v13_0.reset_corrupt_defaults erpnext.patches.v13_0.create_accounting_dimensions_for_asset_repair erpnext.patches.v15_0.delete_taxjar_doctypes +erpnext.patches.v15_0.create_asset_depreciation_schedules_from_assets [post_model_sync] execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings') @@ -319,5 +320,4 @@ erpnext.patches.v14_0.create_accounting_dimensions_for_asset_capitalization erpnext.patches.v14_0.update_partial_tds_fields erpnext.patches.v14_0.create_incoterms_and_migrate_shipment erpnext.patches.v14_0.setup_clear_repost_logs -erpnext.patches.v14_0.create_accounting_dimensions_for_payment_request -erpnext.patches.v15_0.create_asset_depreciation_schedules_from_assets \ No newline at end of file +erpnext.patches.v14_0.create_accounting_dimensions_for_payment_request \ No newline at end of file diff --git a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py index 8dcbb2a1cc..e77e5262bb 100644 --- a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py +++ b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py @@ -2,6 +2,8 @@ import frappe def execute(): + frappe.reload_doc("asset", "doctype", "Asset Depreciation Schedule") + assets = get_details_of_draft_or_submitted_depreciable_assets() for asset in assets: From c916fb0513e8da5b526ea4b4a6cae444c8a22039 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Tue, 27 Dec 2022 12:15:18 +0530 Subject: [PATCH 41/49] chore: fix module name in patch --- erpnext/patches.txt | 2 +- .../v15_0/create_asset_depreciation_schedules_from_assets.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 74f866e20e..ba92e9084f 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -268,7 +268,7 @@ erpnext.patches.v13_0.show_hr_payroll_deprecation_warning erpnext.patches.v13_0.reset_corrupt_defaults erpnext.patches.v13_0.create_accounting_dimensions_for_asset_repair erpnext.patches.v15_0.delete_taxjar_doctypes -erpnext.patches.v15_0.create_asset_depreciation_schedules_from_assets +erpnext.patches.v15_0.create_asset_depreciation_schedules_from_assets #03 [post_model_sync] execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings') diff --git a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py index e77e5262bb..02ffa70888 100644 --- a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py +++ b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py @@ -2,7 +2,7 @@ import frappe def execute(): - frappe.reload_doc("asset", "doctype", "Asset Depreciation Schedule") + frappe.reload_doc("assets", "doctype", "Asset Depreciation Schedule") assets = get_details_of_draft_or_submitted_depreciable_assets() From 97f85882022a1e50b47900afcd3fd43aa6eece26 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Tue, 27 Dec 2022 12:15:37 +0530 Subject: [PATCH 42/49] chore: fix patch name --- erpnext/patches.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index ba92e9084f..74f866e20e 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -268,7 +268,7 @@ erpnext.patches.v13_0.show_hr_payroll_deprecation_warning erpnext.patches.v13_0.reset_corrupt_defaults erpnext.patches.v13_0.create_accounting_dimensions_for_asset_repair erpnext.patches.v15_0.delete_taxjar_doctypes -erpnext.patches.v15_0.create_asset_depreciation_schedules_from_assets #03 +erpnext.patches.v15_0.create_asset_depreciation_schedules_from_assets [post_model_sync] execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings') From 21a09e74313d91a1abce6bd6dc9fb764ffd784af Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Tue, 27 Dec 2022 13:03:19 +0530 Subject: [PATCH 43/49] chore: fix patch --- .../v15_0/create_asset_depreciation_schedules_from_assets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py index 02ffa70888..749225c858 100644 --- a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py +++ b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py @@ -84,5 +84,5 @@ def update_depreciation_schedules(asset_name, asset_depr_schedule_name, fb_row_i .set(ds.parent, asset_depr_schedule_name) .set(ds.parentfield, "depreciation_schedule") .set(ds.parenttype, "Asset Depreciation Schedule") - .where(ds.parent == depr_schedule.name) + .where(ds.name == depr_schedule.name) ).run() From 7c5168eeac60789aedae8a0ef3ee7fc35b4095e9 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Mon, 2 Jan 2023 17:07:28 +0530 Subject: [PATCH 44/49] chore: allow manually submitting and cancelling asset depr schedule --- .../doctype/journal_entry/journal_entry.py | 2 +- erpnext/assets/doctype/asset/asset.py | 3 +- .../asset_depreciation_schedule.json | 10 +++--- .../asset_depreciation_schedule.py | 34 ++++++++++++++++++- .../asset_value_adjustment.py | 1 + 5 files changed, 41 insertions(+), 9 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index d69777a21a..f592a43a40 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -289,7 +289,7 @@ class JournalEntry(AccountsController): for row in asset.get("finance_books"): depr_schedule = get_draft_or_active_depr_schedule(asset.name, row.finance_book) - for s in depr_schedule: + for s in depr_schedule or []: if s.journal_entry == self.name: s.db_set("journal_entry", None) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index b9274b14d4..c2bfb12336 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -395,7 +395,7 @@ class Asset(AccountsController): for row in self.get("finance_books"): depr_schedule = get_draft_or_active_depr_schedule(self.name, row.finance_book) - for d in depr_schedule: + for d in depr_schedule or []: if d.journal_entry: frappe.get_doc("Journal Entry", d.journal_entry).cancel() d.db_set("journal_entry", None) @@ -903,6 +903,7 @@ def update_existing_asset(asset, remaining_qty, new_asset_name): ) new_asset_depr_schedule_doc.notes = notes + current_asset_depr_schedule_doc.flags.should_not_cancel_depreciation_entries = True current_asset_depr_schedule_doc.cancel() new_asset_depr_schedule_doc.submit() diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json index f6f594c51e..af09cda8fb 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json @@ -65,8 +65,7 @@ "fieldname": "finance_book", "fieldtype": "Link", "label": "Finance Book", - "options": "Finance Book", - "read_only": 1 + "options": "Finance Book" }, { "fieldname": "depreciation_method", @@ -115,7 +114,8 @@ { "fieldname": "notes", "fieldtype": "Small Text", - "label": "Notes" + "label": "Notes", + "read_only": 1 }, { "fieldname": "status", @@ -133,7 +133,6 @@ "read_only": 1 }, { - "default": "0", "fieldname": "expected_value_after_useful_life", "fieldtype": "Currency", "label": "Expected Value After Useful Life", @@ -157,11 +156,10 @@ "read_only": 1 } ], - "in_create": 1, "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2022-12-26 20:32:43.342271", + "modified": "2023-01-02 15:38:30.766779", "modified_by": "Administrator", "module": "Assets", "name": "Asset Depreciation Schedule", diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 7a35013929..2076976cfe 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -18,6 +18,12 @@ import erpnext class AssetDepreciationSchedule(Document): + def before_save(self): + if not self.finance_book_id: + self.prepare_draft_asset_depr_schedule_data_from_asset_name_and_fb_name( + self.asset, self.finance_book + ) + def validate(self): self.validate_another_asset_depr_schedule_does_not_exist() @@ -45,9 +51,33 @@ class AssetDepreciationSchedule(Document): def on_submit(self): self.db_set("status", "Active") + def before_cancel(self): + if not self.flags.should_not_cancel_depreciation_entries: + self.cancel_depreciation_entries() + + def cancel_depreciation_entries(self): + for d in self.get("depreciation_schedule"): + if d.journal_entry: + frappe.get_doc("Journal Entry", d.journal_entry).cancel() + def on_cancel(self): self.db_set("status", "Cancelled") + def prepare_draft_asset_depr_schedule_data_from_asset_name_and_fb_name(self, asset_name, fb_name): + asset_doc = frappe.get_doc("Asset", asset_name) + + finance_book_filter = ["finance_book", "is", "not set"] + if fb_name: + finance_book_filter = ["finance_book", "=", fb_name] + + asset_finance_book_name = frappe.db.get_value( + doctype="Asset Finance Book", + filters=[["parent", "=", asset_name], finance_book_filter], + ) + asset_finance_book_doc = frappe.get_doc("Asset Finance Book", asset_finance_book_name) + + prepare_draft_asset_depr_schedule_data(self, asset_doc, asset_finance_book_doc) + def make_draft_asset_depr_schedules_if_not_present(asset_doc): for row in asset_doc.get("finance_books"): @@ -138,7 +168,8 @@ def cancel_asset_depr_schedules(asset_doc): if not asset_depr_schedule_doc: continue - asset_depr_schedule_doc.cancel() + if asset_depr_schedule_doc.status == "Active": + asset_depr_schedule_doc.cancel() def make_new_active_asset_depr_schedules_and_cancel_current_ones( @@ -163,6 +194,7 @@ def make_new_active_asset_depr_schedules_and_cancel_current_ones( new_asset_depr_schedule_doc.notes = notes + current_asset_depr_schedule_doc.flags.should_not_cancel_depreciation_entries = True current_asset_depr_schedule_doc.cancel() new_asset_depr_schedule_doc.submit() 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 90ecfec5af..fe4b7f9dca 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py @@ -124,6 +124,7 @@ class AssetValueAdjustment(Document): new_asset_depr_schedule_doc.status = "Draft" new_asset_depr_schedule_doc.docstatus = 0 + current_asset_depr_schedule_doc.flags.should_not_cancel_depreciation_entries = True current_asset_depr_schedule_doc.cancel() notes = _( From 357c17214d5058581db4ce5a1156cf501e350648 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Mon, 2 Jan 2023 20:32:29 +0530 Subject: [PATCH 45/49] chore: fix patch --- .../v15_0/create_asset_depreciation_schedules_from_assets.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py index 749225c858..9ec7537a88 100644 --- a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py +++ b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py @@ -62,7 +62,7 @@ def get_details_of_asset_finance_books_rows(asset_name): afb.rate_of_depreciation, afb.expected_value_after_useful_life, ) - .where((afb.parenttype == "Asset") & (afb.parent == asset_name)) + .where(afb.parent == asset_name) ).run(as_dict=True) return records @@ -75,6 +75,7 @@ def update_depreciation_schedules(asset_name, asset_depr_schedule_name, fb_row_i frappe.qb.from_(ds) .select(ds.name) .where((ds.parent == asset_name) & (ds.finance_book_id == str(fb_row_idx))) + .orderby(ds.idx) ).run(as_dict=True) for idx, depr_schedule in enumerate(depr_schedules, start=1): From e501c2db51db4caed2e8c3fcb3fcd42e871b7aad Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Mon, 2 Jan 2023 21:11:53 +0530 Subject: [PATCH 46/49] chore: just testing patch --- erpnext/patches.txt | 4 ++-- .../v15_0/create_asset_depreciation_schedules_from_assets.py | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 74f866e20e..ddceb3acfb 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -268,7 +268,6 @@ erpnext.patches.v13_0.show_hr_payroll_deprecation_warning erpnext.patches.v13_0.reset_corrupt_defaults erpnext.patches.v13_0.create_accounting_dimensions_for_asset_repair erpnext.patches.v15_0.delete_taxjar_doctypes -erpnext.patches.v15_0.create_asset_depreciation_schedules_from_assets [post_model_sync] execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings') @@ -320,4 +319,5 @@ erpnext.patches.v14_0.create_accounting_dimensions_for_asset_capitalization erpnext.patches.v14_0.update_partial_tds_fields erpnext.patches.v14_0.create_incoterms_and_migrate_shipment erpnext.patches.v14_0.setup_clear_repost_logs -erpnext.patches.v14_0.create_accounting_dimensions_for_payment_request \ No newline at end of file +erpnext.patches.v14_0.create_accounting_dimensions_for_payment_request +erpnext.patches.v15_0.create_asset_depreciation_schedules_from_assets \ No newline at end of file diff --git a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py index 9ec7537a88..c281b77987 100644 --- a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py +++ b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py @@ -2,8 +2,6 @@ import frappe def execute(): - frappe.reload_doc("assets", "doctype", "Asset Depreciation Schedule") - assets = get_details_of_draft_or_submitted_depreciable_assets() for asset in assets: From 7b6b5ae581f581bd9b1b2fa4382a7008e2c8a7a2 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Tue, 3 Jan 2023 09:21:08 +0530 Subject: [PATCH 47/49] chore: refactoring patch --- erpnext/patches.txt | 4 ++-- ...sset_depreciation_schedules_from_assets.py | 21 +++++++------------ 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index ddceb3acfb..74f866e20e 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -268,6 +268,7 @@ erpnext.patches.v13_0.show_hr_payroll_deprecation_warning erpnext.patches.v13_0.reset_corrupt_defaults erpnext.patches.v13_0.create_accounting_dimensions_for_asset_repair erpnext.patches.v15_0.delete_taxjar_doctypes +erpnext.patches.v15_0.create_asset_depreciation_schedules_from_assets [post_model_sync] execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings') @@ -319,5 +320,4 @@ erpnext.patches.v14_0.create_accounting_dimensions_for_asset_capitalization erpnext.patches.v14_0.update_partial_tds_fields erpnext.patches.v14_0.create_incoterms_and_migrate_shipment erpnext.patches.v14_0.setup_clear_repost_logs -erpnext.patches.v14_0.create_accounting_dimensions_for_payment_request -erpnext.patches.v15_0.create_asset_depreciation_schedules_from_assets \ No newline at end of file +erpnext.patches.v14_0.create_accounting_dimensions_for_payment_request \ No newline at end of file diff --git a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py index c281b77987..1da05346f7 100644 --- a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py +++ b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py @@ -1,7 +1,13 @@ import frappe +from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( + set_draft_asset_depr_schedule_details, +) + def execute(): + frappe.reload_doc("assets", "doctype", "Asset Depreciation Schedule") + assets = get_details_of_draft_or_submitted_depreciable_assets() for asset in assets: @@ -10,20 +16,7 @@ def execute(): for fb_row in finance_book_rows: asset_depr_schedule_doc = frappe.new_doc("Asset Depreciation Schedule") - asset_depr_schedule_doc.asset = asset.name - asset_depr_schedule_doc.finance_book = fb_row.finance_book - asset_depr_schedule_doc.finance_book_id = fb_row.idx - asset_depr_schedule_doc.opening_accumulated_depreciation = ( - asset.opening_accumulated_depreciation - ) - asset_depr_schedule_doc.depreciation_method = fb_row.depreciation_method - asset_depr_schedule_doc.total_number_of_depreciations = fb_row.total_number_of_depreciations - asset_depr_schedule_doc.frequency_of_depreciation = fb_row.frequency_of_depreciation - asset_depr_schedule_doc.rate_of_depreciation = fb_row.rate_of_depreciation - asset_depr_schedule_doc.expected_value_after_useful_life = ( - fb_row.expected_value_after_useful_life - ) - asset_depr_schedule_doc.status = "Draft" + set_draft_asset_depr_schedule_details(asset_depr_schedule_doc, asset, fb_row) asset_depr_schedule_doc.insert() From adb5249257b1b6e39b794df2938c5eab794062fb Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Tue, 3 Jan 2023 13:03:12 +0530 Subject: [PATCH 48/49] chore: fix patch --- .../v15_0/create_asset_depreciation_schedules_from_assets.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py index 1da05346f7..5dc3cdde6f 100644 --- a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py +++ b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py @@ -20,11 +20,11 @@ def execute(): asset_depr_schedule_doc.insert() - update_depreciation_schedules(asset.name, asset_depr_schedule_doc.name, fb_row.idx) - if asset.docstatus == 1: asset_depr_schedule_doc.submit() + update_depreciation_schedules(asset.name, asset_depr_schedule_doc.name, fb_row.idx) + def get_details_of_draft_or_submitted_depreciable_assets(): asset = frappe.qb.DocType("Asset") From 312e51e8b23ca946a2971b676d084182bc0968cd Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Tue, 3 Jan 2023 15:09:04 +0530 Subject: [PATCH 49/49] chore: more refactoring and adding test for duplicate asset_depr_schedule --- .../doctype/journal_entry/journal_entry.py | 4 +- .../sales_invoice/test_sales_invoice.py | 8 +- erpnext/assets/doctype/asset/asset.js | 3 +- erpnext/assets/doctype/asset/asset.py | 18 +-- erpnext/assets/doctype/asset/depreciation.py | 12 +- erpnext/assets/doctype/asset/test_asset.py | 94 ++++++++-------- .../test_asset_capitalization.py | 6 +- .../asset_depreciation_schedule.py | 106 ++++++------------ .../test_asset_depreciation_schedule.py | 22 +++- .../doctype/asset_repair/asset_repair.py | 6 +- .../doctype/asset_repair/test_asset_repair.py | 6 +- .../asset_value_adjustment.py | 6 +- .../test_asset_value_adjustment.py | 6 +- 13 files changed, 135 insertions(+), 162 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 29f9892a45..af2f6b6841 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -24,7 +24,7 @@ from erpnext.accounts.utils import ( get_stock_and_account_balance, ) from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_draft_or_active_depr_schedule, + get_depr_schedule, ) from erpnext.controllers.accounts_controller import AccountsController @@ -287,7 +287,7 @@ class JournalEntry(AccountsController): if d.reference_type == "Asset" and d.reference_name: asset = frappe.get_doc("Asset", d.reference_name) for row in asset.get("finance_books"): - depr_schedule = get_draft_or_active_depr_schedule(asset.name, row.finance_book) + depr_schedule = get_depr_schedule(asset.name, "Active", row.finance_book) for s in depr_schedule or []: if s.journal_entry == self.name: diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 22a317c1be..e96847e1b6 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -22,7 +22,7 @@ from erpnext.accounts.utils import PaymentEntryUnlinkError from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries from erpnext.assets.doctype.asset.test_asset import create_asset, create_asset_data from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_draft_or_active_depr_schedule, + get_depr_schedule, ) from erpnext.controllers.accounts_controller import update_invoice_status from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_data @@ -2777,7 +2777,7 @@ class TestSalesInvoice(unittest.TestCase): ["2021-09-30", 5041.1, 26407.22], ] - for i, schedule in enumerate(get_draft_or_active_depr_schedule(asset.name)): + for i, schedule in enumerate(get_depr_schedule(asset.name, "Active")): self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) self.assertEqual(expected_values[i][1], schedule.depreciation_amount) self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) @@ -2808,7 +2808,7 @@ class TestSalesInvoice(unittest.TestCase): expected_values = [["2020-12-31", 30000, 30000], ["2021-12-31", 30000, 60000]] - for i, schedule in enumerate(get_draft_or_active_depr_schedule(asset.name)): + for i, schedule in enumerate(get_depr_schedule(asset.name, "Active")): self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) self.assertEqual(expected_values[i][1], schedule.depreciation_amount) self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) @@ -2837,7 +2837,7 @@ class TestSalesInvoice(unittest.TestCase): ["2025-06-06", 18633.88, 100000.0, False], ] - for i, schedule in enumerate(get_draft_or_active_depr_schedule(asset.name)): + for i, schedule in enumerate(get_depr_schedule(asset.name, "Active")): self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) self.assertEqual(expected_values[i][1], schedule.depreciation_amount) self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index 9754ab3e79..b8185c929e 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -209,9 +209,10 @@ frappe.ui.form.on('Asset', { if (frm.doc.finance_books.length == 1) { depr_schedule = (await frappe.call( - "erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule.get_draft_or_active_depr_schedule", + "erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule.get_depr_schedule", { asset_name: frm.doc.name, + status: frm.doc.docstatus ? "Active" : "Draft", finance_book: frm.doc.finance_books[0].finance_book || null } )).message; diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index c2bfb12336..df05d5e632 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -32,8 +32,8 @@ from erpnext.assets.doctype.asset_category.asset_category import get_asset_categ from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( cancel_asset_depr_schedules, convert_draft_asset_depr_schedules_into_active, - get_draft_or_active_asset_depr_schedule_doc, - get_draft_or_active_depr_schedule, + get_asset_depr_schedule_doc, + get_depr_schedule, make_draft_asset_depr_schedules, make_draft_asset_depr_schedules_if_not_present, set_draft_asset_depr_schedule_details, @@ -337,7 +337,7 @@ class Asset(AccountsController): def validate_expected_value_after_useful_life(self): for row in self.get("finance_books"): - depr_schedule = get_draft_or_active_depr_schedule(self.name, row.finance_book) + depr_schedule = get_depr_schedule(self.name, "Draft", row.finance_book) if not depr_schedule: continue @@ -393,7 +393,7 @@ class Asset(AccountsController): def delete_depreciation_entries(self): for row in self.get("finance_books"): - depr_schedule = get_draft_or_active_depr_schedule(self.name, row.finance_book) + depr_schedule = get_depr_schedule(self.name, "Active", row.finance_book) for d in depr_schedule or []: if d.journal_entry: @@ -881,8 +881,8 @@ def update_existing_asset(asset, remaining_qty, new_asset_name): expected_value_after_useful_life, ) - current_asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc( - asset.name, row.finance_book + current_asset_depr_schedule_doc = get_asset_depr_schedule_doc( + asset.name, "Active", row.finance_book ) new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc) @@ -933,8 +933,8 @@ def create_new_asset_after_split(asset, split_qty): new_asset.set_status() for row in new_asset.get("finance_books"): - current_asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc( - asset.name, row.finance_book + current_asset_depr_schedule_doc = get_asset_depr_schedule_doc( + asset.name, "Active", row.finance_book ) new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc) @@ -956,7 +956,7 @@ def create_new_asset_after_split(asset, split_qty): new_asset_depr_schedule_doc.submit() for row in new_asset.get("finance_books"): - depr_schedule = get_draft_or_active_depr_schedule(new_asset.name, row.finance_book) + depr_schedule = get_depr_schedule(new_asset.name, "Active", row.finance_book) for term in depr_schedule: # Update references in JV if term.journal_entry: diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index 3a3123fb16..7686c348a6 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -11,8 +11,8 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( ) from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_draft_or_active_asset_depr_schedule_doc, - get_draft_or_active_asset_depr_schedule_name, + get_asset_depr_schedule_doc, + get_asset_depr_schedule_name, get_temp_asset_depr_schedule_doc, make_new_active_asset_depr_schedules_and_cancel_current_ones, ) @@ -51,8 +51,8 @@ def get_depreciable_assets(date): def make_depreciation_entry_for_all_asset_depr_schedules(asset_doc, date=None): for row in asset_doc.get("finance_books"): - asset_depr_schedule_name = get_draft_or_active_asset_depr_schedule_name( - asset_doc.name, row.finance_book + asset_depr_schedule_name = get_asset_depr_schedule_name( + asset_doc.name, "Active", row.finance_book ) make_depreciation_entry(asset_depr_schedule_name, date) @@ -318,9 +318,7 @@ def modify_depreciation_schedule_for_asset_repairs(asset): def reverse_depreciation_entry_made_after_disposal(asset, date): for row in asset.get("finance_books"): - asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc( - asset.name, row.finance_book - ) + asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset.name, "Active", row.finance_book) for schedule_idx, schedule in enumerate(asset_depr_schedule_doc.get("depreciation_schedule")): if schedule.schedule_date == date: diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index b0a8653eca..d61ef8ecf8 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -29,8 +29,8 @@ from erpnext.assets.doctype.asset.depreciation import ( ) from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( clear_depr_schedule, - get_draft_or_active_asset_depr_schedule_doc, - get_draft_or_active_depr_schedule, + get_asset_depr_schedule_doc, + get_depr_schedule, ) from erpnext.stock.doctype.purchase_receipt.purchase_receipt import ( make_purchase_invoice as make_invoice, @@ -210,7 +210,7 @@ class TestAsset(AssetSetup): submit=1, ) - first_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset.name) + first_asset_depr_schedule = get_asset_depr_schedule_doc(asset.name, "Active") self.assertEquals(first_asset_depr_schedule.status, "Active") post_depreciation_entries(date=add_months(purchase_date, 2)) @@ -226,7 +226,7 @@ class TestAsset(AssetSetup): asset.load_from_db() first_asset_depr_schedule.load_from_db() - second_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset.name) + second_asset_depr_schedule = get_asset_depr_schedule_doc(asset.name, "Active") self.assertEquals(second_asset_depr_schedule.status, "Active") self.assertEquals(first_asset_depr_schedule.status, "Cancelled") @@ -271,7 +271,7 @@ class TestAsset(AssetSetup): restore_asset(asset.name) second_asset_depr_schedule.load_from_db() - third_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset.name) + third_asset_depr_schedule = get_asset_depr_schedule_doc(asset.name, "Active") self.assertEquals(third_asset_depr_schedule.status, "Active") self.assertEquals(second_asset_depr_schedule.status, "Cancelled") @@ -301,7 +301,7 @@ class TestAsset(AssetSetup): submit=1, ) - first_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset.name) + first_asset_depr_schedule = get_asset_depr_schedule_doc(asset.name, "Active") self.assertEquals(first_asset_depr_schedule.status, "Active") post_depreciation_entries(date=add_months(purchase_date, 2)) @@ -317,7 +317,7 @@ class TestAsset(AssetSetup): first_asset_depr_schedule.load_from_db() - second_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset.name) + second_asset_depr_schedule = get_asset_depr_schedule_doc(asset.name, "Active") self.assertEquals(second_asset_depr_schedule.status, "Active") self.assertEquals(first_asset_depr_schedule.status, "Cancelled") @@ -397,7 +397,7 @@ class TestAsset(AssetSetup): submit=1, ) - first_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset.name) + first_asset_depr_schedule = get_asset_depr_schedule_doc(asset.name, "Active") self.assertEquals(first_asset_depr_schedule.status, "Active") post_depreciation_entries(date="2021-01-01") @@ -410,10 +410,8 @@ class TestAsset(AssetSetup): asset.load_from_db() first_asset_depr_schedule.load_from_db() - second_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset.name) - first_asset_depr_schedule_of_new_asset = get_draft_or_active_asset_depr_schedule_doc( - new_asset.name - ) + second_asset_depr_schedule = get_asset_depr_schedule_doc(asset.name, "Active") + first_asset_depr_schedule_of_new_asset = get_asset_depr_schedule_doc(new_asset.name, "Active") self.assertEquals(second_asset_depr_schedule.status, "Active") self.assertEquals(first_asset_depr_schedule_of_new_asset.status, "Active") self.assertEquals(first_asset_depr_schedule.status, "Cancelled") @@ -671,7 +669,7 @@ class TestDepreciationMethods(AssetSetup): schedules = [ [cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] - for d in get_draft_or_active_depr_schedule(asset.name) + for d in get_depr_schedule(asset.name, "Draft") ] self.assertEqual(schedules, expected_schedules) @@ -693,7 +691,7 @@ class TestDepreciationMethods(AssetSetup): expected_schedules = [["2032-12-31", 30000.0, 77095.89], ["2033-06-06", 12904.11, 90000.0]] schedules = [ [cstr(d.schedule_date), flt(d.depreciation_amount, 2), d.accumulated_depreciation_amount] - for d in get_draft_or_active_depr_schedule(asset.name) + for d in get_depr_schedule(asset.name, "Draft") ] self.assertEqual(schedules, expected_schedules) @@ -720,7 +718,7 @@ class TestDepreciationMethods(AssetSetup): schedules = [ [cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] - for d in get_draft_or_active_depr_schedule(asset.name) + for d in get_depr_schedule(asset.name, "Draft") ] self.assertEqual(schedules, expected_schedules) @@ -745,7 +743,7 @@ class TestDepreciationMethods(AssetSetup): schedules = [ [cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] - for d in get_draft_or_active_depr_schedule(asset.name) + for d in get_depr_schedule(asset.name, "Draft") ] self.assertEqual(schedules, expected_schedules) @@ -775,7 +773,7 @@ class TestDepreciationMethods(AssetSetup): flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2), ] - for d in get_draft_or_active_depr_schedule(asset.name) + for d in get_depr_schedule(asset.name, "Draft") ] self.assertEqual(schedules, expected_schedules) @@ -807,7 +805,7 @@ class TestDepreciationMethods(AssetSetup): flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2), ] - for d in get_draft_or_active_depr_schedule(asset.name) + for d in get_depr_schedule(asset.name, "Draft") ] self.assertEqual(schedules, expected_schedules) @@ -840,7 +838,7 @@ class TestDepreciationMethods(AssetSetup): flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2), ] - for d in get_draft_or_active_depr_schedule(asset.name) + for d in get_depr_schedule(asset.name, "Draft") ] self.assertEqual(schedules, expected_schedules) @@ -873,7 +871,7 @@ class TestDepreciationMethods(AssetSetup): flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2), ] - for d in get_draft_or_active_depr_schedule(asset.name) + for d in get_depr_schedule(asset.name, "Draft") ] self.assertEqual(schedules, expected_schedules) @@ -896,7 +894,7 @@ class TestDepreciationBasics(AssetSetup): ["2022-12-31", 30000, 90000], ] - for i, schedule in enumerate(get_draft_or_active_depr_schedule(asset.name)): + for i, schedule in enumerate(get_depr_schedule(asset.name, "Active")): self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) self.assertEqual(expected_values[i][1], schedule.depreciation_amount) self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) @@ -919,7 +917,7 @@ class TestDepreciationBasics(AssetSetup): ["2023-01-01", 15000, 90000], ] - for i, schedule in enumerate(get_draft_or_active_depr_schedule(asset.name)): + for i, schedule in enumerate(get_depr_schedule(asset.name, "Active")): self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) self.assertEqual(expected_values[i][1], schedule.depreciation_amount) self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) @@ -964,7 +962,7 @@ class TestDepreciationBasics(AssetSetup): expected_values = [["2020-12-31", 30000.0], ["2021-12-31", 30000.0], ["2022-12-31", 30000.0]] - for i, schedule in enumerate(get_draft_or_active_depr_schedule(asset.name)): + for i, schedule in enumerate(get_depr_schedule(asset.name, "Draft")): self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) self.assertEqual(expected_values[i][1], schedule.depreciation_amount) @@ -984,7 +982,7 @@ class TestDepreciationBasics(AssetSetup): expected_values = [30000.0, 60000.0, 90000.0] - for i, schedule in enumerate(get_draft_or_active_depr_schedule(asset.name)): + for i, schedule in enumerate(get_depr_schedule(asset.name, "Draft")): self.assertEqual(expected_values[i], schedule.accumulated_depreciation_amount) def test_check_is_pro_rata(self): @@ -1164,9 +1162,11 @@ class TestDepreciationBasics(AssetSetup): post_depreciation_entries(date="2021-06-01") asset.load_from_db() - self.assertTrue(get_draft_or_active_depr_schedule(asset.name)[0].journal_entry) - self.assertFalse(get_draft_or_active_depr_schedule(asset.name)[1].journal_entry) - self.assertFalse(get_draft_or_active_depr_schedule(asset.name)[2].journal_entry) + depr_schedule = get_depr_schedule(asset.name, "Active") + + self.assertTrue(depr_schedule[0].journal_entry) + self.assertFalse(depr_schedule[1].journal_entry) + self.assertFalse(depr_schedule[2].journal_entry) def test_depr_entry_posting_when_depr_expense_account_is_an_expense_account(self): """Tests if the Depreciation Expense Account gets debited and the Accumulated Depreciation Account gets credited when the former's an Expense Account.""" @@ -1185,9 +1185,7 @@ class TestDepreciationBasics(AssetSetup): post_depreciation_entries(date="2021-06-01") asset.load_from_db() - je = frappe.get_doc( - "Journal Entry", get_draft_or_active_depr_schedule(asset.name)[0].journal_entry - ) + je = frappe.get_doc("Journal Entry", get_depr_schedule(asset.name, "Active")[0].journal_entry) accounting_entries = [ {"account": entry.account, "debit": entry.debit, "credit": entry.credit} for entry in je.accounts @@ -1223,9 +1221,7 @@ class TestDepreciationBasics(AssetSetup): post_depreciation_entries(date="2021-06-01") asset.load_from_db() - je = frappe.get_doc( - "Journal Entry", get_draft_or_active_depr_schedule(asset.name)[0].journal_entry - ) + je = frappe.get_doc("Journal Entry", get_depr_schedule(asset.name, "Active")[0].journal_entry) accounting_entries = [ {"account": entry.account, "debit": entry.debit, "credit": entry.credit} for entry in je.accounts @@ -1261,7 +1257,7 @@ class TestDepreciationBasics(AssetSetup): post_depreciation_entries(date="2021-06-01") asset.load_from_db() - asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc(asset.name) + asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset.name, "Active") clear_depr_schedule(asset_depr_schedule_doc) @@ -1309,20 +1305,20 @@ class TestDepreciationBasics(AssetSetup): post_depreciation_entries(date="2020-04-01") asset.load_from_db() - asset_depr_schedule_doc_1 = get_draft_or_active_asset_depr_schedule_doc( - asset.name, "Test Finance Book 1" + asset_depr_schedule_doc_1 = get_asset_depr_schedule_doc( + asset.name, "Active", "Test Finance Book 1" ) clear_depr_schedule(asset_depr_schedule_doc_1) self.assertEqual(len(asset_depr_schedule_doc_1.get("depreciation_schedule")), 3) - asset_depr_schedule_doc_2 = get_draft_or_active_asset_depr_schedule_doc( - asset.name, "Test Finance Book 2" + asset_depr_schedule_doc_2 = get_asset_depr_schedule_doc( + asset.name, "Active", "Test Finance Book 2" ) clear_depr_schedule(asset_depr_schedule_doc_2) self.assertEqual(len(asset_depr_schedule_doc_2.get("depreciation_schedule")), 3) - asset_depr_schedule_doc_3 = get_draft_or_active_asset_depr_schedule_doc( - asset.name, "Test Finance Book 3" + asset_depr_schedule_doc_3 = get_asset_depr_schedule_doc( + asset.name, "Active", "Test Finance Book 3" ) clear_depr_schedule(asset_depr_schedule_doc_3) self.assertEqual(len(asset_depr_schedule_doc_3.get("depreciation_schedule")), 0) @@ -1355,13 +1351,13 @@ class TestDepreciationBasics(AssetSetup): ) asset.save() - asset_depr_schedule_doc_1 = get_draft_or_active_asset_depr_schedule_doc( - asset.name, "Test Finance Book 1" + asset_depr_schedule_doc_1 = get_asset_depr_schedule_doc( + asset.name, "Draft", "Test Finance Book 1" ) self.assertEqual(len(asset_depr_schedule_doc_1.get("depreciation_schedule")), 3) - asset_depr_schedule_doc_2 = get_draft_or_active_asset_depr_schedule_doc( - asset.name, "Test Finance Book 2" + asset_depr_schedule_doc_2 = get_asset_depr_schedule_doc( + asset.name, "Draft", "Test Finance Book 2" ) self.assertEqual(len(asset_depr_schedule_doc_2.get("depreciation_schedule")), 6) @@ -1383,12 +1379,12 @@ class TestDepreciationBasics(AssetSetup): asset.load_from_db() # cancel depreciation entry - depr_entry = get_draft_or_active_depr_schedule(asset.name)[0].journal_entry + depr_entry = get_depr_schedule(asset.name, "Active")[0].journal_entry self.assertTrue(depr_entry) frappe.get_doc("Journal Entry", depr_entry).cancel() - depr_entry = get_draft_or_active_depr_schedule(asset.name)[0].journal_entry + depr_entry = get_depr_schedule(asset.name, "Active")[0].journal_entry self.assertFalse(depr_entry) def test_asset_expected_value_after_useful_life(self): @@ -1403,7 +1399,7 @@ class TestDepreciationBasics(AssetSetup): ) accumulated_depreciation_after_full_schedule = max( - d.accumulated_depreciation_amount for d in get_draft_or_active_depr_schedule(asset.name) + d.accumulated_depreciation_amount for d in get_depr_schedule(asset.name, "Draft") ) asset_value_after_full_schedule = flt(asset.gross_purchase_amount) - flt( @@ -1434,7 +1430,7 @@ class TestDepreciationBasics(AssetSetup): asset.load_from_db() # check depreciation entry series - self.assertEqual(get_draft_or_active_depr_schedule(asset.name)[0].journal_entry[:4], "DEPR") + self.assertEqual(get_depr_schedule(asset.name, "Active")[0].journal_entry[:4], "DEPR") expected_gle = ( ("_Test Accumulated Depreciations - _TC", 0.0, 30000.0), @@ -1504,7 +1500,7 @@ class TestDepreciationBasics(AssetSetup): "2020-07-15", ] - for i, schedule in enumerate(get_draft_or_active_depr_schedule(asset.name)): + for i, schedule in enumerate(get_depr_schedule(asset.name, "Active")): self.assertEqual(getdate(expected_dates[i]), getdate(schedule.schedule_date)) diff --git a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py index 897c678c08..4d519a60be 100644 --- a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py @@ -13,7 +13,7 @@ from erpnext.assets.doctype.asset.test_asset import ( set_depreciation_settings_in_company, ) from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_draft_or_active_asset_depr_schedule_doc, + get_asset_depr_schedule_doc, ) from erpnext.stock.doctype.item.test_item import create_item @@ -256,7 +256,7 @@ class TestAssetCapitalization(unittest.TestCase): submit=1, ) - first_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(consumed_asset.name) + first_asset_depr_schedule = get_asset_depr_schedule_doc(consumed_asset.name, "Active") self.assertEquals(first_asset_depr_schedule.status, "Active") # Create and submit Asset Captitalization @@ -290,7 +290,7 @@ class TestAssetCapitalization(unittest.TestCase): first_asset_depr_schedule.load_from_db() - second_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(consumed_asset.name) + second_asset_depr_schedule = get_asset_depr_schedule_doc(consumed_asset.name, "Active") self.assertEquals(second_asset_depr_schedule.status, "Active") self.assertEquals(first_asset_depr_schedule.status, "Cancelled") diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 2076976cfe..1446a6e7a2 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -32,7 +32,7 @@ class AssetDepreciationSchedule(Document): if self.finance_book: finance_book_filter = ["finance_book", "=", self.finance_book] - num_asset_depr_schedules = frappe.db.count( + asset_depr_schedule = frappe.db.exists( "Asset Depreciation Schedule", [ ["asset", "=", self.asset], @@ -41,12 +41,19 @@ class AssetDepreciationSchedule(Document): ], ) - if num_asset_depr_schedules > 1: - frappe.throw( - _("Asset Depreciation Schedule for Asset {0} and Finance Book {1} already exists.").format( - self.asset, self.finance_book + if asset_depr_schedule and asset_depr_schedule != self.name: + if self.finance_book: + frappe.throw( + _( + "Asset Depreciation Schedule {0} for Asset {1} and Finance Book {2} already exists." + ).format(asset_depr_schedule, self.asset, self.finance_book) + ) + else: + frappe.throw( + _("Asset Depreciation Schedule {0} for Asset {1} already exists.").format( + asset_depr_schedule, self.asset + ) ) - ) def on_submit(self): self.db_set("status", "Active") @@ -81,11 +88,15 @@ class AssetDepreciationSchedule(Document): def make_draft_asset_depr_schedules_if_not_present(asset_doc): for row in asset_doc.get("finance_books"): - asset_depr_schedule_name = get_draft_or_active_asset_depr_schedule_name( - asset_doc.name, row.finance_book + draft_asset_depr_schedule_name = get_asset_depr_schedule_name( + asset_doc.name, "Draft", row.finance_book ) - if not asset_depr_schedule_name: + active_asset_depr_schedule_name = get_asset_depr_schedule_name( + asset_doc.name, "Active", row.finance_book + ) + + if not draft_asset_depr_schedule_name and not active_asset_depr_schedule_name: make_draft_asset_depr_schedule(asset_doc, row) @@ -104,9 +115,7 @@ def make_draft_asset_depr_schedule(asset_doc, row): def update_draft_asset_depr_schedules(asset_doc): for row in asset_doc.get("finance_books"): - asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc( - asset_doc.name, row.finance_book - ) + asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_doc.name, "Draft", row.finance_book) if not asset_depr_schedule_doc: continue @@ -148,36 +157,30 @@ def set_draft_asset_depr_schedule_details(asset_depr_schedule_doc, asset_doc, ro def convert_draft_asset_depr_schedules_into_active(asset_doc): for row in asset_doc.get("finance_books"): - asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc( - asset_doc.name, row.finance_book - ) + asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_doc.name, "Draft", row.finance_book) if not asset_depr_schedule_doc: continue - if asset_depr_schedule_doc.status == "Draft": - asset_depr_schedule_doc.submit() + asset_depr_schedule_doc.submit() def cancel_asset_depr_schedules(asset_doc): for row in asset_doc.get("finance_books"): - asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc( - asset_doc.name, row.finance_book - ) + asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_doc.name, "Active", row.finance_book) if not asset_depr_schedule_doc: continue - if asset_depr_schedule_doc.status == "Active": - asset_depr_schedule_doc.cancel() + asset_depr_schedule_doc.cancel() def make_new_active_asset_depr_schedules_and_cancel_current_ones( asset_doc, notes, date_of_disposal=None, date_of_return=None ): for row in asset_doc.get("finance_books"): - current_asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc( - asset_doc.name, row.finance_book + current_asset_depr_schedule_doc = get_asset_depr_schedule_doc( + asset_doc.name, "Active", row.finance_book ) if not current_asset_depr_schedule_doc: @@ -217,7 +220,7 @@ def get_temp_asset_depr_schedule_doc( return asset_depr_schedule_doc -def get_draft_or_active_asset_depr_schedule_name(asset_name, finance_book=None): +def get_asset_depr_schedule_name(asset_name, status, finance_book=None): finance_book_filter = ["finance_book", "is", "not set"] if finance_book: finance_book_filter = ["finance_book", "=", finance_book] @@ -227,37 +230,14 @@ def get_draft_or_active_asset_depr_schedule_name(asset_name, finance_book=None): filters=[ ["asset", "=", asset_name], finance_book_filter, - ["status", "in", ["Draft", "Active"]], + ["status", "=", status], ], ) -def get_cancelled_asset_depr_schedule_name(asset_name, finance_book=None): - finance_book_filter = ["finance_book", "is", "not set"] - if finance_book: - finance_book_filter = ["finance_book", "=", finance_book] - - cancelled_asset_depr_schedule_names = frappe.db.get_all( - doctype="Asset Depreciation Schedule", - filters=[ - ["asset", "=", asset_name], - finance_book_filter, - ["status", "=", "Cancelled"], - ], - order_by="creation desc", - limit=1, - pluck="name", - ) - - if cancelled_asset_depr_schedule_names: - return cancelled_asset_depr_schedule_names[0] - - return - - @frappe.whitelist() -def get_draft_or_active_depr_schedule(asset_name, finance_book=None): - asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc(asset_name, finance_book) +def get_depr_schedule(asset_name, status, finance_book=None): + asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_name, status, finance_book) if not asset_depr_schedule_doc: return @@ -265,28 +245,8 @@ def get_draft_or_active_depr_schedule(asset_name, finance_book=None): return asset_depr_schedule_doc.get("depreciation_schedule") -def get_cancelled_depr_schedule(asset_name, finance_book=None): - asset_depr_schedule_doc = get_cancelled_asset_depr_schedule_doc(asset_name, finance_book) - - if not asset_depr_schedule_doc: - return - - return asset_depr_schedule_doc.get("depreciation_schedule") - - -def get_draft_or_active_asset_depr_schedule_doc(asset_name, finance_book=None): - asset_depr_schedule_name = get_draft_or_active_asset_depr_schedule_name(asset_name, finance_book) - - if not asset_depr_schedule_name: - return - - asset_depr_schedule_doc = frappe.get_doc("Asset Depreciation Schedule", asset_depr_schedule_name) - - return asset_depr_schedule_doc - - -def get_cancelled_asset_depr_schedule_doc(asset_name, finance_book=None): - asset_depr_schedule_name = get_cancelled_asset_depr_schedule_name(asset_name, finance_book) +def get_asset_depr_schedule_doc(asset_name, status, finance_book=None): + asset_depr_schedule_name = get_asset_depr_schedule_name(asset_name, status, finance_book) if not asset_depr_schedule_name: return diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/test_asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/test_asset_depreciation_schedule.py index 21de8cde51..024121d394 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/test_asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/test_asset_depreciation_schedule.py @@ -1,9 +1,27 @@ # Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -# import frappe +import frappe from frappe.tests.utils import FrappeTestCase +from erpnext.assets.doctype.asset.test_asset import create_asset, create_asset_data +from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( + get_asset_depr_schedule_doc, +) + class TestAssetDepreciationSchedule(FrappeTestCase): - pass + def setUp(self): + create_asset_data() + + def test_throw_error_if_another_asset_depr_schedule_exist(self): + asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, submit=1) + + first_asset_depr_schedule = get_asset_depr_schedule_doc(asset.name, "Active") + self.assertEquals(first_asset_depr_schedule.status, "Active") + + second_asset_depr_schedule = frappe.get_doc( + {"doctype": "Asset Depreciation Schedule", "asset": asset.name, "finance_book": None} + ) + + self.assertRaises(frappe.ValidationError, second_asset_depr_schedule.insert) diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py index c5036fa9e2..b8cd115872 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/asset_repair.py @@ -9,7 +9,7 @@ import erpnext from erpnext.accounts.general_ledger import make_gl_entries from erpnext.assets.doctype.asset.asset import get_asset_account from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_draft_or_active_depr_schedule, + get_depr_schedule, make_new_active_asset_depr_schedules_and_cancel_current_ones, ) from erpnext.controllers.accounts_controller import AccountsController @@ -289,7 +289,7 @@ class AssetRepair(AccountsController): asset.number_of_depreciations_booked ) - depr_schedule = get_draft_or_active_depr_schedule(asset.name, row.finance_book) + depr_schedule = get_depr_schedule(asset.name, "Active", row.finance_book) # the Schedule Date in the final row of the old Depreciation Schedule last_schedule_date = depr_schedule[len(depr_schedule) - 1].schedule_date @@ -322,7 +322,7 @@ class AssetRepair(AccountsController): asset.number_of_depreciations_booked ) - depr_schedule = get_draft_or_active_depr_schedule(asset.name, row.finance_book) + depr_schedule = get_depr_schedule(asset.name, "Active", row.finance_book) # the Schedule Date in the final row of the modified Depreciation Schedule last_schedule_date = depr_schedule[len(depr_schedule) - 1].schedule_date diff --git a/erpnext/assets/doctype/asset_repair/test_asset_repair.py b/erpnext/assets/doctype/asset_repair/test_asset_repair.py index 8618392ea2..ff72aa94b9 100644 --- a/erpnext/assets/doctype/asset_repair/test_asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/test_asset_repair.py @@ -13,7 +13,7 @@ from erpnext.assets.doctype.asset.test_asset import ( set_depreciation_settings_in_company, ) from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_draft_or_active_asset_depr_schedule_doc, + get_asset_depr_schedule_doc, ) from erpnext.stock.doctype.item.test_item import create_item @@ -236,7 +236,7 @@ class TestAssetRepair(unittest.TestCase): def test_increase_in_asset_life(self): asset = create_asset(calculate_depreciation=1, submit=1) - first_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset.name) + first_asset_depr_schedule = get_asset_depr_schedule_doc(asset.name, "Active") self.assertEquals(first_asset_depr_schedule.status, "Active") initial_num_of_depreciations = num_of_depreciations(asset) @@ -245,7 +245,7 @@ class TestAssetRepair(unittest.TestCase): asset.reload() first_asset_depr_schedule.load_from_db() - second_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset.name) + second_asset_depr_schedule = get_asset_depr_schedule_doc(asset.name, "Active") self.assertEquals(second_asset_depr_schedule.status, "Active") self.assertEquals(first_asset_depr_schedule.status, "Cancelled") 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 fe4b7f9dca..262d552997 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py @@ -12,8 +12,8 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( ) from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( + get_asset_depr_schedule_doc, get_depreciation_amount, - get_draft_or_active_asset_depr_schedule_doc, set_accumulated_depreciation, ) @@ -116,8 +116,8 @@ class AssetValueAdjustment(Document): for d in asset.finance_books: d.value_after_depreciation = asset_value - current_asset_depr_schedule_doc = get_draft_or_active_asset_depr_schedule_doc( - asset.name, d.finance_book + current_asset_depr_schedule_doc = get_asset_depr_schedule_doc( + asset.name, "Active", d.finance_book ) new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc) 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 780c9db02b..03dcea96c5 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 @@ -8,7 +8,7 @@ from frappe.utils import add_days, get_last_day, nowdate from erpnext.assets.doctype.asset.test_asset import create_asset_data from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( - get_draft_or_active_asset_depr_schedule_doc, + get_asset_depr_schedule_doc, ) from erpnext.assets.doctype.asset_value_adjustment.asset_value_adjustment import ( get_current_asset_value, @@ -76,7 +76,7 @@ class TestAssetValueAdjustment(unittest.TestCase): ) asset_doc.submit() - first_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset_doc.name) + first_asset_depr_schedule = get_asset_depr_schedule_doc(asset_doc.name, "Active") self.assertEquals(first_asset_depr_schedule.status, "Active") current_value = get_current_asset_value(asset_doc.name) @@ -87,7 +87,7 @@ class TestAssetValueAdjustment(unittest.TestCase): first_asset_depr_schedule.load_from_db() - second_asset_depr_schedule = get_draft_or_active_asset_depr_schedule_doc(asset_doc.name) + second_asset_depr_schedule = get_asset_depr_schedule_doc(asset_doc.name, "Active") self.assertEquals(second_asset_depr_schedule.status, "Active") self.assertEquals(first_asset_depr_schedule.status, "Cancelled")