From 17f85de6fb6fbcd26993768b9fd29822189626d2 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 20 Feb 2024 18:10:34 +0530 Subject: [PATCH] fix: Issues regarding asset cancellation and deletion --- erpnext/assets/doctype/asset/depreciation.py | 5 ++- .../asset_capitalization.js | 2 +- .../asset_capitalization.py | 3 +- .../asset_depreciation_schedule.py | 33 +++++++++---------- erpnext/controllers/buying_controller.py | 3 +- erpnext/patches.txt | 2 ++ ...te_orphaned_asset_movement_item_records.py | 10 ++++++ 7 files changed, 35 insertions(+), 23 deletions(-) create mode 100644 erpnext/patches/v15_0/delete_orphaned_asset_movement_item_records.py diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index df4593bb69..191675c2ab 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -561,15 +561,14 @@ def modify_depreciation_schedule_for_asset_repairs(asset, notes): 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, "Active", row.finance_book) - if not asset_depr_schedule_doc: + if not asset_depr_schedule_doc or not asset_depr_schedule_doc.get("depreciation_schedule"): continue for schedule_idx, schedule in enumerate(asset_depr_schedule_doc.get("depreciation_schedule")): - if schedule.schedule_date == date: + if schedule.schedule_date == date and schedule.journal_entry: if not disposal_was_made_on_original_schedule_date( schedule_idx, row, date ) or disposal_happens_in_the_future(date): - reverse_journal_entry = make_reverse_journal_entry(schedule.journal_entry) reverse_journal_entry.posting_date = nowdate() diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js index 2f0de97939..110f2c4f2a 100644 --- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js +++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js @@ -6,7 +6,7 @@ frappe.provide("erpnext.assets"); erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.stock.StockController { setup() { - this.frm.ignore_doctypes_on_cancel_all = ['Serial and Batch Bundle']; + this.frm.ignore_doctypes_on_cancel_all = ['Serial and Batch Bundle', 'Asset Movement']; this.setup_posting_date_time_check(); } diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py index 5e251a5658..c3a79cdf83 100644 --- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py @@ -137,6 +137,7 @@ class AssetCapitalization(StockController): "Repost Item Valuation", "Serial and Batch Bundle", "Asset", + "Asset Movement", ) self.cancel_target_asset() self.update_stock_ledger() @@ -146,7 +147,7 @@ class AssetCapitalization(StockController): def cancel_target_asset(self): if self.entry_type == "Capitalization" and self.target_asset: asset_doc = frappe.get_doc("Asset", self.target_asset) - frappe.db.set_value("Asset", self.target_asset, "capitalized_in", None) + asset_doc.db_set("capitalized_in", None) if asset_doc.docstatus == 1: asset_doc.cancel() 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 146c03e8c3..77469df895 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -418,14 +418,13 @@ class AssetDepreciationSchedule(Document): ) # 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(final_number_of_depreciations) - 1 - and value_after_depreciation != row.expected_value_after_useful_life + if ( + n == cint(final_number_of_depreciations) - 1 + and flt(value_after_depreciation) != flt(row.expected_value_after_useful_life) + ) or flt(value_after_depreciation) < flt(row.expected_value_after_useful_life): + depreciation_amount += flt(value_after_depreciation) - flt( + 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 flt(depreciation_amount, asset_doc.precision("gross_purchase_amount")) > 0: @@ -813,15 +812,11 @@ def make_draft_asset_depr_schedules_if_not_present(asset_doc): asset_depr_schedules_names = [] for row in asset_doc.get("finance_books"): - draft_asset_depr_schedule_name = get_asset_depr_schedule_name( - asset_doc.name, "Draft", row.finance_book + asset_depr_schedule = get_asset_depr_schedule_name( + asset_doc.name, ["Draft", "Active"], row.finance_book ) - 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: + if not asset_depr_schedule: name = make_draft_asset_depr_schedule(asset_doc, row) asset_depr_schedules_names.append(name) @@ -997,16 +992,20 @@ def get_asset_depr_schedule_doc(asset_name, status, 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: + if finance_book is None: + finance_book_filter = ["finance_book", "is", "not set"] + else: finance_book_filter = ["finance_book", "=", finance_book] + if isinstance(status, str): + status = [status] + return frappe.db.get_value( doctype="Asset Depreciation Schedule", filters=[ ["asset", "=", asset_name], finance_book_filter, - ["status", "=", status], + ["status", "in", status], ], ) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index fb680100b7..94eae67360 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -824,7 +824,8 @@ class BuyingController(SubcontractingController): if self.doctype == "Purchase Invoice" and not self.get("update_stock"): return - frappe.db.sql("delete from `tabAsset Movement` where reference_name=%s", self.name) + asset_movement = frappe.db.get_value("Asset Movement", {"reference_name": self.name}, "name") + frappe.delete_doc("Asset Movement", asset_movement, force=1) def validate_schedule_date(self): if not self.get("items"): diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 4ead7e71f0..cd1e467738 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -357,3 +357,5 @@ erpnext.patches.v15_0.create_advance_payment_status erpnext.patches.v14_0.migrate_gl_to_payment_ledger erpnext.stock.doctype.delivery_note.patches.drop_unused_return_against_index # 2023-12-20 erpnext.patches.v14_0.set_maintain_stock_for_bom_item +erpnext.patches.v15_0.set_difference_amount_in_asset_value_adjustment +erpnext.patches.v15_0.delete_orphaned_asset_movement_item_records \ No newline at end of file diff --git a/erpnext/patches/v15_0/delete_orphaned_asset_movement_item_records.py b/erpnext/patches/v15_0/delete_orphaned_asset_movement_item_records.py new file mode 100644 index 0000000000..910504ed23 --- /dev/null +++ b/erpnext/patches/v15_0/delete_orphaned_asset_movement_item_records.py @@ -0,0 +1,10 @@ +import frappe + + +def execute(): + frappe.db.sql( + """ + DELETE FROM `tabAsset Movement Item` + WHERE parent NOT IN (SELECT name FROM `tabAsset Movement`) + """ + )