fix: incorrect schedule in asset value adjustment (#36747)

diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index 2060c6c..ce894eb 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -56,7 +56,6 @@
 
 	def on_submit(self):
 		self.validate_in_use_date()
-		self.set_status()
 		self.make_asset_movement()
 		if not self.booked_fixed_asset and self.validate_make_gl_entry():
 			self.make_gl_entries()
@@ -72,6 +71,7 @@
 						"Asset Depreciation Schedules created:<br>{0}<br><br>Please check, edit if needed, and submit the Asset."
 					).format(asset_depr_schedules_links)
 				)
+		self.set_status()
 		add_asset_activity(self.name, _("Asset submitted"))
 
 	def on_cancel(self):
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index cd66f1d..90eae2d 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -19,6 +19,7 @@
 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
 from erpnext.assets.doctype.asset.asset import (
+	get_asset_value_after_depreciation,
 	make_sales_invoice,
 	split_asset,
 	update_maintenance_status,
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 39ebd4e..2b4b248 100644
--- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py
+++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py
@@ -107,7 +107,7 @@
 			have_asset_details_been_modified, not_manual_depr_or_have_manual_depr_details_been_modified
 		):
 			self.make_depr_schedule(asset_doc, row, date_of_disposal, update_asset_finance_book_row)
-			self.set_accumulated_depreciation(row, date_of_disposal, date_of_return)
+			self.set_accumulated_depreciation(asset_doc, row, date_of_disposal, date_of_return)
 
 	def have_asset_details_been_modified(self, asset_doc):
 		return (
@@ -157,7 +157,12 @@
 		self.status = "Draft"
 
 	def make_depr_schedule(
-		self, asset_doc, row, date_of_disposal, update_asset_finance_book_row=True
+		self,
+		asset_doc,
+		row,
+		date_of_disposal,
+		update_asset_finance_book_row=True,
+		value_after_depreciation=None,
 	):
 		if not self.get("depreciation_schedule"):
 			self.depreciation_schedule = []
@@ -167,7 +172,9 @@
 
 		start = self.clear_depr_schedule()
 
-		self._make_depr_schedule(asset_doc, row, start, date_of_disposal, update_asset_finance_book_row)
+		self._make_depr_schedule(
+			asset_doc, row, start, date_of_disposal, update_asset_finance_book_row, value_after_depreciation
+		)
 
 	def clear_depr_schedule(self):
 		start = 0
@@ -187,23 +194,30 @@
 		return start
 
 	def _make_depr_schedule(
-		self, asset_doc, row, start, date_of_disposal, update_asset_finance_book_row
+		self,
+		asset_doc,
+		row,
+		start,
+		date_of_disposal,
+		update_asset_finance_book_row,
+		value_after_depreciation,
 	):
 		asset_doc.validate_asset_finance_books(row)
 
-		value_after_depreciation = _get_value_after_depreciation_for_making_schedule(asset_doc, row)
+		if not value_after_depreciation:
+			value_after_depreciation = _get_value_after_depreciation_for_making_schedule(asset_doc, 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(
+		final_number_of_depreciations = cint(row.total_number_of_depreciations) - cint(
 			self.number_of_depreciations_booked
 		)
 
 		has_pro_rata = _check_is_pro_rata(asset_doc, row)
 		if has_pro_rata:
-			number_of_pending_depreciations += 1
+			final_number_of_depreciations += 1
 
 		has_wdv_or_dd_non_yearly_pro_rata = False
 		if (
@@ -219,7 +233,9 @@
 
 		depreciation_amount = 0
 
-		for n in range(start, number_of_pending_depreciations):
+		number_of_pending_depreciations = final_number_of_depreciations - start
+
+		for n in range(start, final_number_of_depreciations):
 			# If depreciation is already completed (for double declining balance)
 			if skip_row:
 				continue
@@ -236,10 +252,11 @@
 				n,
 				prev_depreciation_amount,
 				has_wdv_or_dd_non_yearly_pro_rata,
+				number_of_pending_depreciations,
 			)
 
 			if not has_pro_rata or (
-				n < (cint(number_of_pending_depreciations) - 1) or number_of_pending_depreciations == 2
+				n < (cint(final_number_of_depreciations) - 1) or final_number_of_depreciations == 2
 			):
 				schedule_date = add_months(
 					row.depreciation_start_date, n * cint(row.frequency_of_depreciation)
@@ -310,7 +327,7 @@
 				)
 
 			# For last row
-			elif has_pro_rata and n == cint(number_of_pending_depreciations) - 1:
+			elif has_pro_rata and n == cint(final_number_of_depreciations) - 1:
 				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_doc.to_date = add_months(
@@ -343,7 +360,7 @@
 			# 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
+					n == cint(final_number_of_depreciations) - 1
 					and value_after_depreciation != row.expected_value_after_useful_life
 				)
 				or value_after_depreciation < row.expected_value_after_useful_life
@@ -392,6 +409,7 @@
 
 	def set_accumulated_depreciation(
 		self,
+		asset_doc,
 		row,
 		date_of_disposal=None,
 		date_of_return=None,
@@ -403,13 +421,21 @@
 			if self.depreciation_method == "Straight Line" or self.depreciation_method == "Manual"
 		]
 
-		accumulated_depreciation = flt(self.opening_accumulated_depreciation)
+		accumulated_depreciation = None
 		value_after_depreciation = flt(row.value_after_depreciation)
 
 		for i, d in enumerate(self.get("depreciation_schedule")):
 			if ignore_booked_entry and d.journal_entry:
 				continue
 
+			if not accumulated_depreciation:
+				if i > 0 and asset_doc.flags.decrease_in_asset_value_due_to_value_adjustment:
+					accumulated_depreciation = self.get("depreciation_schedule")[
+						i - 1
+					].accumulated_depreciation_amount
+				else:
+					accumulated_depreciation = flt(self.opening_accumulated_depreciation)
+
 			depreciation_amount = flt(d.depreciation_amount, d.precision("depreciation_amount"))
 			value_after_depreciation -= flt(depreciation_amount)
 
@@ -507,9 +533,12 @@
 	schedule_idx=0,
 	prev_depreciation_amount=0,
 	has_wdv_or_dd_non_yearly_pro_rata=False,
+	number_of_pending_depreciations=0,
 ):
 	if fb_row.depreciation_method in ("Straight Line", "Manual"):
-		return get_straight_line_or_manual_depr_amount(asset, fb_row, schedule_idx)
+		return get_straight_line_or_manual_depr_amount(
+			asset, fb_row, schedule_idx, number_of_pending_depreciations
+		)
 	else:
 		rate_of_depreciation = get_updated_rate_of_depreciation_for_wdv_and_dd(
 			asset, depreciable_value, fb_row
@@ -529,7 +558,9 @@
 	return fb_row.rate_of_depreciation
 
 
-def get_straight_line_or_manual_depr_amount(asset, row, schedule_idx):
+def get_straight_line_or_manual_depr_amount(
+	asset, row, schedule_idx, number_of_pending_depreciations
+):
 	# if the Depreciation Schedule is being modified after Asset Repair due to increase in asset life and value
 	if asset.flags.increase_in_asset_life:
 		return (flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life)) / (
@@ -540,6 +571,36 @@
 		return (flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life)) / flt(
 			row.total_number_of_depreciations
 		)
+	# if the Depreciation Schedule is being modified after Asset Value Adjustment due to decrease in asset value
+	elif asset.flags.decrease_in_asset_value_due_to_value_adjustment:
+		if row.daily_depreciation:
+			daily_depr_amount = (
+				flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life)
+			) / date_diff(
+				add_months(
+					row.depreciation_start_date,
+					flt(row.total_number_of_depreciations - asset.number_of_depreciations_booked)
+					* row.frequency_of_depreciation,
+				),
+				add_months(
+					row.depreciation_start_date,
+					flt(
+						row.total_number_of_depreciations
+						- asset.number_of_depreciations_booked
+						- number_of_pending_depreciations
+					)
+					* row.frequency_of_depreciation,
+				),
+			)
+			to_date = add_months(row.depreciation_start_date, schedule_idx * row.frequency_of_depreciation)
+			from_date = add_months(
+				row.depreciation_start_date, (schedule_idx - 1) * row.frequency_of_depreciation
+			)
+			return daily_depr_amount * date_diff(to_date, from_date)
+		else:
+			return (
+				flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life)
+			) / number_of_pending_depreciations
 	# if the Depreciation Schedule is being prepared for the first time
 	else:
 		if row.daily_depreciation:
@@ -669,7 +730,12 @@
 
 
 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,
+	date_of_disposal=None,
+	date_of_return=None,
+	value_after_depreciation=None,
+	ignore_booked_entry=False,
 ):
 	for row in asset_doc.get("finance_books"):
 		current_asset_depr_schedule_doc = get_asset_depr_schedule_doc(
@@ -695,8 +761,12 @@
 			row.rate_of_depreciation = new_rate_of_depreciation
 			new_asset_depr_schedule_doc.rate_of_depreciation = new_rate_of_depreciation
 
-		new_asset_depr_schedule_doc.make_depr_schedule(asset_doc, row, date_of_disposal)
-		new_asset_depr_schedule_doc.set_accumulated_depreciation(row, date_of_disposal, date_of_return)
+		new_asset_depr_schedule_doc.make_depr_schedule(
+			asset_doc, row, date_of_disposal, value_after_depreciation=value_after_depreciation
+		)
+		new_asset_depr_schedule_doc.set_accumulated_depreciation(
+			asset_doc, row, date_of_disposal, date_of_return, ignore_booked_entry
+		)
 
 		new_asset_depr_schedule_doc.notes = notes
 
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 823b6e9..9be7243 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, get_link_to_form, getdate
+from frappe.utils import flt, formatdate, get_link_to_form, getdate
 
 from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
 	get_checks_for_pl_and_bs_accounts,
@@ -14,8 +14,7 @@
 from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts
 from erpnext.assets.doctype.asset_activity.asset_activity import add_asset_activity
 from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
-	get_asset_depr_schedule_doc,
-	get_depreciation_amount,
+	make_new_active_asset_depr_schedules_and_cancel_current_ones,
 )
 
 
@@ -27,7 +26,7 @@
 
 	def on_submit(self):
 		self.make_depreciation_entry()
-		self.reschedule_depreciations(self.new_asset_value)
+		self.update_asset(self.new_asset_value)
 		add_asset_activity(
 			self.asset,
 			_("Asset's value adjusted after submission of Asset Value Adjustment {0}").format(
@@ -36,7 +35,7 @@
 		)
 
 	def on_cancel(self):
-		self.reschedule_depreciations(self.current_asset_value)
+		self.update_asset(self.current_asset_value)
 		add_asset_activity(
 			self.asset,
 			_("Asset's value adjusted after cancellation of Asset Value Adjustment {0}").format(
@@ -124,73 +123,33 @@
 
 		self.db_set("journal_entry", je.name)
 
-	def reschedule_depreciations(self, asset_value):
+	def update_asset(self, asset_value):
 		asset = frappe.get_doc("Asset", self.asset)
-		country = frappe.get_value("Company", self.company, "country")
 
-		for d in asset.finance_books:
-			d.value_after_depreciation = asset_value
+		if not asset.calculate_depreciation:
+			asset.value_after_depreciation = asset_value
+			asset.save()
+			return
 
-			current_asset_depr_schedule_doc = get_asset_depr_schedule_doc(
-				asset.name, "Active", d.finance_book
+		asset.flags.decrease_in_asset_value_due_to_value_adjustment = True
+
+		if self.docstatus == 1:
+			notes = _(
+				"This schedule was created when Asset {0} was adjusted through Asset Value Adjustment {1}."
+			).format(
+				get_link_to_form("Asset", asset.name),
+				get_link_to_form(self.get("doctype"), self.get("name")),
+			)
+		elif self.docstatus == 2:
+			notes = _(
+				"This schedule was created when Asset {0}'s Asset Value Adjustment {1} was cancelled."
+			).format(
+				get_link_to_form("Asset", asset.name),
+				get_link_to_form(self.get("doctype"), self.get("name")),
 			)
 
-			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.flags.should_not_cancel_depreciation_entries = True
-			current_asset_depr_schedule_doc.cancel()
-
-			if self.docstatus == 1:
-				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")),
-				)
-			elif self.docstatus == 2:
-				notes = _(
-					"This schedule was created when Asset {0}'s Asset Value Adjustment {1} was cancelled."
-				).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")
-
-			if d.depreciation_method in ("Straight Line", "Manual"):
-				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 - d.expected_value_after_useful_life) / flt(
-					total_days
-				)
-				from_date = self.date
-			else:
-				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 depr_schedule:
-				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
-						from_date = data.schedule_date
-					else:
-						depreciation_amount = get_depreciation_amount(asset, value_after_depreciation, d)
-
-					if depreciation_amount:
-						value_after_depreciation -= flt(depreciation_amount)
-						data.depreciation_amount = depreciation_amount
-
-			d.db_update()
-
-			new_asset_depr_schedule_doc.set_accumulated_depreciation(d, ignore_booked_entry=True)
-			for asset_data in depr_schedule:
-				if not asset_data.journal_entry:
-					asset_data.db_update()
-
-			new_asset_depr_schedule_doc.submit()
+		make_new_active_asset_depr_schedules_and_cancel_current_ones(
+			asset, notes, value_after_depreciation=asset_value, ignore_booked_entry=True
+		)
+		asset.flags.ignore_validate_update_after_submit = True
+		asset.save()
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 0b3dcba..5d49759 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
@@ -4,9 +4,10 @@
 import unittest
 
 import frappe
-from frappe.utils import add_days, get_last_day, nowdate
+from frappe.utils import add_days, cstr, get_last_day, getdate, nowdate
 
 from erpnext.assets.doctype.asset.asset import get_asset_value_after_depreciation
+from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries
 from erpnext.assets.doctype.asset.test_asset import create_asset_data
 from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
 	get_asset_depr_schedule_doc,
@@ -49,27 +50,23 @@
 
 	def test_asset_depreciation_value_adjustment(self):
 		pr = make_purchase_receipt(
-			item_code="Macbook Pro", qty=1, rate=100000.0, location="Test Location"
+			item_code="Macbook Pro", qty=1, rate=120000.0, location="Test Location"
 		)
 
 		asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, "name")
 		asset_doc = frappe.get_doc("Asset", asset_name)
 		asset_doc.calculate_depreciation = 1
+		asset_doc.available_for_use_date = "2023-01-15"
+		asset_doc.purchase_date = "2023-01-15"
 
-		month_end_date = get_last_day(nowdate())
-		purchase_date = nowdate() if nowdate() != month_end_date else add_days(nowdate(), -15)
-
-		asset_doc.available_for_use_date = purchase_date
-		asset_doc.purchase_date = purchase_date
-		asset_doc.calculate_depreciation = 1
 		asset_doc.append(
 			"finance_books",
 			{
 				"expected_value_after_useful_life": 200,
 				"depreciation_method": "Straight Line",
-				"total_number_of_depreciations": 3,
-				"frequency_of_depreciation": 10,
-				"depreciation_start_date": month_end_date,
+				"total_number_of_depreciations": 12,
+				"frequency_of_depreciation": 1,
+				"depreciation_start_date": "2023-01-31",
 			},
 		)
 		asset_doc.submit()
@@ -77,9 +74,15 @@
 		first_asset_depr_schedule = get_asset_depr_schedule_doc(asset_doc.name, "Active")
 		self.assertEquals(first_asset_depr_schedule.status, "Active")
 
+		post_depreciation_entries(getdate("2023-08-21"))
+
 		current_value = get_asset_value_after_depreciation(asset_doc.name)
+
 		adj_doc = make_asset_value_adjustment(
-			asset=asset_doc.name, current_asset_value=current_value, new_asset_value=50000.0
+			asset=asset_doc.name,
+			current_asset_value=current_value,
+			new_asset_value=50000.0,
+			date="2023-08-21",
 		)
 		adj_doc.submit()
 
@@ -90,8 +93,8 @@
 		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),
+			("_Test Accumulated Depreciations - _TC", 0.0, 4625.29),
+			("_Test Depreciations - _TC", 4625.29, 0.0),
 		)
 
 		gle = frappe.db.sql(
@@ -103,6 +106,29 @@
 
 		self.assertSequenceEqual(gle, expected_gle)
 
+		expected_schedules = [
+			["2023-01-31", 5474.73, 5474.73],
+			["2023-02-28", 9983.33, 15458.06],
+			["2023-03-31", 9983.33, 25441.39],
+			["2023-04-30", 9983.33, 35424.72],
+			["2023-05-31", 9983.33, 45408.05],
+			["2023-06-30", 9983.33, 55391.38],
+			["2023-07-31", 9983.33, 65374.71],
+			["2023-08-31", 8300.0, 73674.71],
+			["2023-09-30", 8300.0, 81974.71],
+			["2023-10-31", 8300.0, 90274.71],
+			["2023-11-30", 8300.0, 98574.71],
+			["2023-12-31", 8300.0, 106874.71],
+			["2024-01-15", 8300.0, 115174.71],
+		]
+
+		schedules = [
+			[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount]
+			for d in second_asset_depr_schedule.get("depreciation_schedule")
+		]
+
+		self.assertEqual(schedules, expected_schedules)
+
 
 def make_asset_value_adjustment(**args):
 	args = frappe._dict(args)
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 7b7c53e..b396b27 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -759,7 +759,7 @@
 				"company": self.company,
 				"supplier": self.supplier,
 				"purchase_date": self.posting_date,
-				"calculate_depreciation": 1,
+				"calculate_depreciation": 0,
 				"purchase_receipt_amount": purchase_amount,
 				"gross_purchase_amount": purchase_amount,
 				"asset_quantity": row.qty if is_grouped_asset else 0,