From 8eb2f6791054a317edf77460d5e893c23c9ceaca Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 20 Feb 2024 18:10:34 +0530 Subject: [PATCH 1/4] fix: Issues regarding asset cancellation and deletion (cherry picked from commit 17f85de6fb6fbcd26993768b9fd29822189626d2) # Conflicts: # erpnext/assets/doctype/asset/depreciation.py # erpnext/assets/doctype/asset_capitalization/asset_capitalization.py --- erpnext/assets/doctype/asset/depreciation.py | 8 +++-- .../asset_capitalization.js | 2 +- .../asset_capitalization.py | 5 +++ .../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, 42 insertions(+), 21 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 dbb18b543f..7422e56112 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -561,13 +561,17 @@ 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) +<<<<<<< HEAD +======= + if not asset_depr_schedule_doc or not asset_depr_schedule_doc.get("depreciation_schedule"): + continue +>>>>>>> 17f85de6fb (fix: Issues regarding asset cancellation and deletion) 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 66014904cc..ca1d616be3 100644 --- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py @@ -138,6 +138,7 @@ class AssetCapitalization(StockController): "Repost Item Valuation", "Serial and Batch Bundle", "Asset", + "Asset Movement", ) self.cancel_target_asset() self.update_stock_ledger() @@ -147,6 +148,10 @@ 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) +<<<<<<< HEAD +======= + asset_doc.db_set("capitalized_in", None) +>>>>>>> 17f85de6fb (fix: Issues regarding asset cancellation and deletion) 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 27ac9d52f6..91ee53a796 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 4825e7648f..56fdfcc036 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -355,3 +355,5 @@ erpnext.patches.v14_0.update_total_asset_cost_field 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`) + """ + ) From ee2d108bef460437cd35bac53749cb9196a4ad39 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 20 Feb 2024 18:40:39 +0530 Subject: [PATCH 2/4] fix: removed unwanted patch (cherry picked from commit 85471533e9fa59b76d81613fad242e5365cbc9f7) --- erpnext/patches.txt | 1 - .../patches/v15_0/delete_orphaned_asset_movement_item_records.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 56fdfcc036..b93b6cf769 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -355,5 +355,4 @@ erpnext.patches.v14_0.update_total_asset_cost_field 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 index 910504ed23..a1d7dc9b3d 100644 --- a/erpnext/patches/v15_0/delete_orphaned_asset_movement_item_records.py +++ b/erpnext/patches/v15_0/delete_orphaned_asset_movement_item_records.py @@ -2,6 +2,7 @@ import frappe def execute(): + # nosemgrep frappe.db.sql( """ DELETE FROM `tabAsset Movement Item` From a0c0ab7709baff88fe78373d261734f4183d8bd4 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 21 Feb 2024 11:37:47 +0530 Subject: [PATCH 3/4] fix: resolved conflict --- erpnext/assets/doctype/asset/depreciation.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index 7422e56112..42a93a85e3 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -561,11 +561,8 @@ 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) -<<<<<<< HEAD -======= if not asset_depr_schedule_doc or not asset_depr_schedule_doc.get("depreciation_schedule"): continue ->>>>>>> 17f85de6fb (fix: Issues regarding asset cancellation and deletion) for schedule_idx, schedule in enumerate(asset_depr_schedule_doc.get("depreciation_schedule")): if schedule.schedule_date == date and schedule.journal_entry: From 692867427cf5624b154f3e32170a2ca74f32b453 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 21 Feb 2024 11:38:21 +0530 Subject: [PATCH 4/4] fix: resolved conflict --- .../doctype/asset_capitalization/asset_capitalization.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py index ca1d616be3..e27a492fa6 100644 --- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py @@ -148,10 +148,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) -<<<<<<< HEAD -======= asset_doc.db_set("capitalized_in", None) ->>>>>>> 17f85de6fb (fix: Issues regarding asset cancellation and deletion) if asset_doc.docstatus == 1: asset_doc.cancel()