fix: incorrect depr schedule and posting dates on selling of existing assets [dev] (#35398)

* fix: calc depr amount properly on selling of existing assets and fix incorrect posting dates

* chore: get number_of_depreciations_booked properly

* chore: fix test_gle_made_by_asset_sale_for_existing_asset
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index e16b1b1..7454332 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -1180,7 +1180,12 @@
 
 					if self.is_return:
 						fixed_asset_gl_entries = get_gl_entries_on_asset_regain(
-							asset, item.base_net_amount, item.finance_book, self.get("doctype"), self.get("name")
+							asset,
+							item.base_net_amount,
+							item.finance_book,
+							self.get("doctype"),
+							self.get("name"),
+							self.get("posting_date"),
 						)
 						asset.db_set("disposal_date", None)
 
@@ -1208,7 +1213,12 @@
 							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")
+							asset,
+							item.base_net_amount,
+							item.finance_book,
+							self.get("doctype"),
+							self.get("name"),
+							self.get("posting_date"),
 						)
 						asset.db_set("disposal_date", self.posting_date)
 
diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py
index f23ae2f..c64b917 100644
--- a/erpnext/assets/doctype/asset/depreciation.py
+++ b/erpnext/assets/doctype/asset/depreciation.py
@@ -307,7 +307,7 @@
 	je.company = asset.company
 	je.remark = "Scrap Entry for asset {0}".format(asset_name)
 
-	for entry in get_gl_entries_on_asset_disposal(asset):
+	for entry in get_gl_entries_on_asset_disposal(asset, date):
 		entry.update({"reference_type": "Asset", "reference_name": asset_name})
 		je.append("accounts", entry)
 
@@ -434,8 +434,11 @@
 
 
 def get_gl_entries_on_asset_regain(
-	asset, selling_amount=0, finance_book=None, voucher_type=None, voucher_no=None
+	asset, selling_amount=0, finance_book=None, voucher_type=None, voucher_no=None, date=None
 ):
+	if not date:
+		date = getdate()
+
 	(
 		fixed_asset_account,
 		asset,
@@ -453,7 +456,7 @@
 				"debit_in_account_currency": asset.gross_purchase_amount,
 				"debit": asset.gross_purchase_amount,
 				"cost_center": depreciation_cost_center,
-				"posting_date": getdate(),
+				"posting_date": date,
 			},
 			item=asset,
 		),
@@ -463,7 +466,7 @@
 				"credit_in_account_currency": accumulated_depr_amount,
 				"credit": accumulated_depr_amount,
 				"cost_center": depreciation_cost_center,
-				"posting_date": getdate(),
+				"posting_date": date,
 			},
 			item=asset,
 		),
@@ -472,7 +475,7 @@
 	profit_amount = abs(flt(value_after_depreciation)) - abs(flt(selling_amount))
 	if profit_amount:
 		get_profit_gl_entries(
-			asset, profit_amount, gl_entries, disposal_account, depreciation_cost_center
+			asset, profit_amount, gl_entries, disposal_account, depreciation_cost_center, date
 		)
 
 	if voucher_type and voucher_no:
@@ -484,8 +487,11 @@
 
 
 def get_gl_entries_on_asset_disposal(
-	asset, selling_amount=0, finance_book=None, voucher_type=None, voucher_no=None
+	asset, selling_amount=0, finance_book=None, voucher_type=None, voucher_no=None, date=None
 ):
+	if not date:
+		date = getdate()
+
 	(
 		fixed_asset_account,
 		asset,
@@ -503,7 +509,7 @@
 				"credit_in_account_currency": asset.gross_purchase_amount,
 				"credit": asset.gross_purchase_amount,
 				"cost_center": depreciation_cost_center,
-				"posting_date": getdate(),
+				"posting_date": date,
 			},
 			item=asset,
 		),
@@ -513,7 +519,7 @@
 				"debit_in_account_currency": accumulated_depr_amount,
 				"debit": accumulated_depr_amount,
 				"cost_center": depreciation_cost_center,
-				"posting_date": getdate(),
+				"posting_date": date,
 			},
 			item=asset,
 		),
@@ -522,7 +528,7 @@
 	profit_amount = flt(selling_amount) - flt(value_after_depreciation)
 	if profit_amount:
 		get_profit_gl_entries(
-			asset, profit_amount, gl_entries, disposal_account, depreciation_cost_center
+			asset, profit_amount, gl_entries, disposal_account, depreciation_cost_center, date
 		)
 
 	if voucher_type and voucher_no:
@@ -556,8 +562,11 @@
 
 
 def get_profit_gl_entries(
-	asset, profit_amount, gl_entries, disposal_account, depreciation_cost_center
+	asset, profit_amount, gl_entries, disposal_account, depreciation_cost_center, date=None
 ):
+	if not date:
+		date = getdate()
+
 	debit_or_credit = "debit" if profit_amount < 0 else "credit"
 	gl_entries.append(
 		asset.get_gl_dict(
@@ -566,7 +575,7 @@
 				"cost_center": depreciation_cost_center,
 				debit_or_credit: abs(profit_amount),
 				debit_or_credit + "_in_account_currency": abs(profit_amount),
-				"posting_date": getdate(),
+				"posting_date": date,
 			},
 			item=asset,
 		)
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index f3a9ba0..c64f296 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -356,6 +356,83 @@
 		si.cancel()
 		self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Partially Depreciated")
 
+	def test_gle_made_by_asset_sale_for_existing_asset(self):
+		from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
+
+		asset = create_asset(
+			calculate_depreciation=1,
+			available_for_use_date="2020-04-01",
+			purchase_date="2020-04-01",
+			expected_value_after_useful_life=0,
+			total_number_of_depreciations=5,
+			number_of_depreciations_booked=2,
+			frequency_of_depreciation=12,
+			depreciation_start_date="2023-03-31",
+			opening_accumulated_depreciation=24000,
+			gross_purchase_amount=60000,
+			submit=1,
+		)
+
+		expected_depr_values = [
+			["2023-03-31", 12000, 36000],
+			["2024-03-31", 12000, 48000],
+			["2025-03-31", 12000, 60000],
+		]
+
+		first_asset_depr_schedule = get_depr_schedule(asset.name, "Active")
+
+		for i, schedule in enumerate(first_asset_depr_schedule):
+			self.assertEqual(getdate(expected_depr_values[i][0]), schedule.schedule_date)
+			self.assertEqual(expected_depr_values[i][1], schedule.depreciation_amount)
+			self.assertEqual(expected_depr_values[i][2], schedule.accumulated_depreciation_amount)
+
+		post_depreciation_entries(date="2023-03-31")
+
+		si = create_sales_invoice(
+			item_code="Macbook Pro", asset=asset.name, qty=1, rate=40000, posting_date=getdate("2023-05-23")
+		)
+		asset.load_from_db()
+
+		self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Sold")
+
+		expected_values = [["2023-03-31", 12000, 36000], ["2023-05-23", 1742.47, 37742.47]]
+
+		second_asset_depr_schedule = get_depr_schedule(asset.name, "Active")
+
+		for i, schedule in enumerate(second_asset_depr_schedule):
+			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)
+			self.assertTrue(schedule.journal_entry)
+
+		expected_gle = (
+			(
+				"_Test Accumulated Depreciations - _TC",
+				37742.47,
+				0.0,
+			),
+			(
+				"_Test Fixed Asset - _TC",
+				0.0,
+				60000.0,
+			),
+			(
+				"_Test Gain/Loss on Asset Disposal - _TC",
+				0.0,
+				17742.47,
+			),
+			("Debtors - _TC", 40000.0, 0.0),
+		)
+
+		gle = frappe.db.sql(
+			"""select account, debit, credit from `tabGL Entry`
+			where voucher_type='Sales Invoice' and voucher_no = %s
+			order by account""",
+			si.name,
+		)
+
+		self.assertSequenceEqual(gle, expected_gle)
+
 	def test_asset_with_maintenance_required_status_after_sale(self):
 		asset = create_asset(
 			calculate_depreciation=1,
diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
index 5b910db..789ca6c 100644
--- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
+++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
@@ -443,6 +443,7 @@
 				item.get("finance_book") or self.get("finance_book"),
 				self.get("doctype"),
 				self.get("name"),
+				self.get("posting_date"),
 			)
 
 			asset.db_set("disposal_date", self.posting_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 ad5ec3d..8b359cd 100644
--- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py
+++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py
@@ -252,7 +252,10 @@
 
 			# if asset is being sold or scrapped
 			if date_of_disposal:
-				from_date = asset_doc.available_for_use_date
+				from_date = add_months(
+					getdate(asset_doc.available_for_use_date),
+					(asset_doc.number_of_depreciations_booked * row.frequency_of_depreciation),
+				)
 				if self.depreciation_schedule:
 					from_date = self.depreciation_schedule[-1].schedule_date