diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index bc75afd462d..e32d98fd07b 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -802,15 +802,33 @@ frappe.ui.form.on("Asset Finance Book", { }); erpnext.asset.scrap_asset = function (frm) { - frappe.confirm(__("Do you really want to scrap this asset?"), function () { - frappe.call({ - args: { - asset_name: frm.doc.name, + var scrap_dialog = new frappe.ui.Dialog({ + title: __("Enter date to scrap asset"), + fields: [ + { + label: __("Select the date"), + fieldname: "scrap_date", + fieldtype: "Date", + reqd: 1, }, - method: "erpnext.assets.doctype.asset.depreciation.scrap_asset", - callback: (r) => frm.reload_doc(), - }); + ], + size: "medium", + primary_action_label: "Submit", + primary_action(values) { + frappe.call({ + args: { + asset_name: frm.doc.name, + scrap_date: values.scrap_date, + }, + method: "erpnext.assets.doctype.asset.depreciation.scrap_asset", + callback: function (r) { + frm.reload_doc(); + scrap_dialog.hide(); + }, + }); + }, }); + scrap_dialog.show(); }; erpnext.asset.restore_asset = function (frm) { diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index f06abaa1202..5bf0386d3a3 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -431,7 +431,7 @@ def get_comma_separated_links(names, doctype): @frappe.whitelist() -def scrap_asset(asset_name): +def scrap_asset(asset_name, scrap_date=None): asset = frappe.get_doc("Asset", asset_name) if asset.docstatus != 1: @@ -439,7 +439,11 @@ def scrap_asset(asset_name): elif asset.status in ("Cancelled", "Sold", "Scrapped", "Capitalized", "Decapitalized"): frappe.throw(_("Asset {0} cannot be scrapped, as it is already {1}").format(asset.name, asset.status)) - date = today() + today_date = getdate(today()) + date = getdate(scrap_date) or today_date + purchase_date = getdate(asset.purchase_date) + + validate_scrap_date(date, today_date, purchase_date, asset.calculate_depreciation, asset_name) notes = _("This schedule was created when Asset {0} was scrapped.").format( get_link_to_form(asset.doctype, asset.name) @@ -473,6 +477,36 @@ def scrap_asset(asset_name): frappe.msgprint(_("Asset scrapped via Journal Entry {0}").format(je.name)) +def validate_scrap_date(scrap_date, today_date, purchase_date, calculate_depreciation, asset_name): + if scrap_date > today_date: + frappe.throw(_("Future date is not allowed")) + elif scrap_date < purchase_date: + frappe.throw(_("Scrap date cannot be before purchase date")) + + if calculate_depreciation: + asset_depreciation_schedules = frappe.db.get_all( + "Asset Depreciation Schedule", filters={"asset": asset_name, "docstatus": 1}, fields=["name"] + ) + + for depreciation_schedule in asset_depreciation_schedules: + last_booked_depreciation_date = frappe.db.get_value( + "Depreciation Schedule", + { + "parent": depreciation_schedule["name"], + "docstatus": 1, + "journal_entry": ["!=", ""], + }, + "schedule_date", + order_by="schedule_date desc", + ) + if ( + last_booked_depreciation_date + and scrap_date < last_booked_depreciation_date + and scrap_date > purchase_date + ): + frappe.throw(_("Asset cannot be scrapped before the last depreciation entry.")) + + @frappe.whitelist() def restore_asset(asset_name): 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 a4e192d65aa..4271540c33b 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -15,6 +15,7 @@ from frappe.utils import ( is_last_day_of_the_month, nowdate, ) +from frappe.utils.data import add_to_date from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice @@ -219,6 +220,31 @@ class TestAsset(AssetSetup): ) self.assertEqual(accumulated_depr_amount, 18000.0) + asset_depreciation = frappe.db.get_value( + "Asset Depreciation Schedule", {"asset": asset.name, "docstatus": 1}, "name" + ) + last_booked_depreciation_date = frappe.db.get_value( + "Depreciation Schedule", + { + "parent": asset_depreciation, + "docstatus": 1, + "journal_entry": ["!=", ""], + }, + "schedule_date", + order_by="schedule_date desc", + ) + + before_purchase_date = add_to_date(asset.purchase_date, days=-1) + future_date = add_to_date(nowdate(), days=1) + if last_booked_depreciation_date: + before_last_booked_depreciation_date = add_to_date(last_booked_depreciation_date, days=-1) + + self.assertRaises(frappe.ValidationError, scrap_asset, asset.name, scrap_date=before_purchase_date) + self.assertRaises(frappe.ValidationError, scrap_asset, asset.name, scrap_date=future_date) + self.assertRaises( + frappe.ValidationError, scrap_asset, asset.name, scrap_date=before_last_booked_depreciation_date + ) + scrap_asset(asset.name) asset.load_from_db() first_asset_depr_schedule.load_from_db()