feat(Asset Capitalization): Submission and Cancellation
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index ec249c2..3af7b24 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -37,7 +37,6 @@
 	get_disposal_account_and_cost_center,
 	get_gl_entries_on_asset_disposal,
 	get_gl_entries_on_asset_regain,
-	post_depreciation_entries,
 )
 from erpnext.controllers.selling_controller import SellingController
 from erpnext.healthcare.utils import manage_invoice_submit_cancel
@@ -166,7 +165,7 @@
 					if self.update_stock:
 						frappe.throw(_("'Update Stock' cannot be checked for fixed asset sale"))
 
-					elif asset.status in ("Scrapped", "Cancelled") or (asset.status == "Sold" and not self.is_return):
+					elif asset.status in ("Scrapped", "Cancelled", "Capitalized", "Decapitalized") or (asset.status == "Sold" and not self.is_return):
 						frappe.throw(_("Row #{0}: Asset {1} cannot be submitted, it is already {2}").format(d.idx, d.asset, asset.status))
 
 	def validate_item_cost_centers(self):
@@ -1007,77 +1006,6 @@
 		self.check_finance_books(item, asset)
 		return asset
 
-	def check_finance_books(self, item, asset):
-		if (len(asset.finance_books) > 1 and not item.finance_book
-			and asset.finance_books[0].finance_book):
-			frappe.throw(_("Select finance book for the item {0} at row {1}")
-				.format(item.item_code, item.idx))
-
-	def depreciate_asset(self, asset):
-		asset.flags.ignore_validate_update_after_submit = True
-		asset.prepare_depreciation_data(self.posting_date)
-		asset.save()
-
-		post_depreciation_entries(self.posting_date)
-
-	def reset_depreciation_schedule(self, asset):
-		asset.flags.ignore_validate_update_after_submit = True
-
-		# recreate original depreciation schedule of the asset
-		asset.prepare_depreciation_data()
-
-		self.modify_depreciation_schedule_for_asset_repairs(asset)
-		asset.save()
-
-		self.delete_depreciation_entry_made_after_sale(asset)
-
-	def modify_depreciation_schedule_for_asset_repairs(self, asset):
-		asset_repairs = frappe.get_all(
-			'Asset Repair',
-			filters = {'asset': asset.name},
-			fields = ['name', 'increase_in_asset_life']
-		)
-
-		for repair in asset_repairs:
-			if repair.increase_in_asset_life:
-				asset_repair = frappe.get_doc('Asset Repair', repair.name)
-				asset_repair.modify_depreciation_schedule()
-				asset.prepare_depreciation_data()
-
-	def delete_depreciation_entry_made_after_sale(self, asset):
-		from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry
-
-		posting_date_of_original_invoice = self.get_posting_date_of_sales_invoice()
-
-		row = -1
-		finance_book = asset.get('schedules')[0].get('finance_book')
-		for schedule in asset.get('schedules'):
-			if schedule.finance_book != finance_book:
-				row = 0
-				finance_book = schedule.finance_book
-			else:
-				row += 1
-
-			if schedule.schedule_date == posting_date_of_original_invoice:
-				if not self.sale_was_made_on_original_schedule_date(asset, schedule, row, posting_date_of_original_invoice):
-					reverse_journal_entry = make_reverse_journal_entry(schedule.journal_entry)
-					reverse_journal_entry.posting_date = nowdate()
-					reverse_journal_entry.submit()
-
-	def get_posting_date_of_sales_invoice(self):
-		return frappe.db.get_value('Sales Invoice', self.return_against, 'posting_date')
-
-	# if the invoice had been posted on the date the depreciation was initially supposed to happen, the depreciation shouldn't be undone
-	def sale_was_made_on_original_schedule_date(self, asset, schedule, row, posting_date_of_original_invoice):
-		for finance_book in asset.get('finance_books'):
-			if schedule.finance_book == finance_book.finance_book:
-				orginal_schedule_date = add_months(finance_book.depreciation_start_date,
-					row * cint(finance_book.frequency_of_depreciation))
-
-				if orginal_schedule_date == posting_date_of_original_invoice:
-					return True
-		return False
-
 	@property
 	def enable_discount_accounting(self):
 		if not hasattr(self, "_enable_discount_accounting"):
diff --git a/erpnext/assets/doctype/asset/asset_list.js b/erpnext/assets/doctype/asset/asset_list.js
index 4302cb2..3d00eb7 100644
--- a/erpnext/assets/doctype/asset/asset_list.js
+++ b/erpnext/assets/doctype/asset/asset_list.js
@@ -10,6 +10,9 @@
 		} else if (doc.status === "Sold") {
 			return [__("Sold"), "green", "status,=,Sold"];
 
+		} else if (["Capitalized", "Decapitalized"].includes(doc.status)) {
+			return [__(doc.status), "grey", "status,=," + doc.status];
+
 		} else if (doc.status === "Scrapped") {
 			return [__("Scrapped"), "grey", "status,=,Scrapped"];
 
diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py
index 6097910..58d4bb5 100644
--- a/erpnext/assets/doctype/asset/depreciation.py
+++ b/erpnext/assets/doctype/asset/depreciation.py
@@ -13,7 +13,7 @@
 )
 
 
-def post_depreciation_entries(date=None):
+def post_depreciation_entries(date=None, commit=True):
 	# Return if automatic booking of asset depreciation is disabled
 	if not cint(frappe.db.get_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically")):
 		return
@@ -22,7 +22,8 @@
 		date = today()
 	for asset in get_depreciable_assets(date):
 		make_depreciation_entry(asset, date)
-		frappe.db.commit()
+		if commit:
+			frappe.db.commit()
 
 def get_depreciable_assets(date):
 	return frappe.db.sql_list("""select a.name
@@ -140,7 +141,7 @@
 
 	if asset.docstatus != 1:
 		frappe.throw(_("Asset {0} must be submitted").format(asset.name))
-	elif asset.status in ("Cancelled", "Sold", "Scrapped"):
+	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))
 
 	depreciation_series = frappe.get_cached_value('Company',  asset.company,  "series_for_depreciation_entry")
@@ -269,3 +270,25 @@
 		frappe.throw(_("Please set 'Asset Depreciation Cost Center' in Company {0}").format(company))
 
 	return disposal_account, depreciation_cost_center
+
+
+@frappe.whitelist()
+def get_value_after_depreciation_on_disposal_date(asset, disposal_date, finance_book=None):
+	asset_doc = frappe.get_doc("Asset", asset)
+
+	if asset_doc.calculate_depreciation:
+		asset_doc.prepare_depreciation_data(getdate(disposal_date))
+
+		finance_book_id = 1
+		if finance_book:
+			for fb in asset_doc.finance_books:
+				if fb.finance_book == finance_book:
+					finance_book_id = fb.idx
+					break
+
+		asset_schedules = [sch for sch in asset_doc.schedules if cint(sch.finance_book_id) == finance_book_id]
+		accumulated_depr_amount = asset_schedules[-1].accumulated_depreciation_amount
+
+		return flt(flt(asset_doc.gross_purchase_amount) - accumulated_depr_amount, asset_doc.precision('gross_purchase_amount'))
+	else:
+		return flt(asset_doc.value_after_depreciation)
diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js
index b0f7712..4f8c95e 100644
--- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js
+++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js
@@ -15,6 +15,10 @@
 
 	refresh() {
 		erpnext.hide_company();
+		this.show_general_ledger();
+		if (this.frm.doc.stock_items || !this.frm.doc.target_is_fixed_asset) {
+			this.show_stock_ledger();
+		}
 	}
 
 	setup_queries() {
@@ -33,7 +37,7 @@
 				filters['item_code'] = me.frm.doc.target_item_code;
 			}
 
-			filters['status'] = ["not in", ["Draft", "Scrapped", "Sold"]]
+			filters['status'] = ["not in", ["Draft", "Scrapped", "Sold", "Capitalized", "Decapitalized"]]
 			filters['docstatus'] = 1;
 
 			return {
@@ -43,7 +47,7 @@
 
 		me.frm.set_query("asset", "asset_items", function() {
 			var filters = {
-				'status': ["not in", ["Draft", "Scrapped", "Sold"]],
+				'status': ["not in", ["Draft", "Scrapped", "Sold", "Capitalized", "Decapitalized"]],
 				'docstatus': 1
 			}
 
@@ -127,6 +131,7 @@
 	posting_date() {
 		if (this.frm.doc.posting_date) {
 			this.get_all_item_warehouse_details();
+			this.get_all_asset_values();
 		}
 	}
 
diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
index b29decb..e50ddfa 100644
--- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
+++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
@@ -2,8 +2,9 @@
 # For license information, please see license.txt
 
 import frappe
+# import erpnext
 from frappe import _
-from erpnext.controllers.accounts_controller import AccountsController
+from erpnext.controllers.stock_controller import StockController
 from frappe.utils import cint, flt
 from erpnext.stock.get_item_details import get_item_warehouse, get_default_expense_account, get_default_cost_center
 from erpnext.stock.doctype.item.item import get_item_defaults
@@ -13,6 +14,9 @@
 from erpnext.stock.stock_ledger import get_previous_sle
 from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
 from erpnext.assets.doctype.asset_value_adjustment.asset_value_adjustment import get_current_asset_value
+from erpnext.stock import get_warehouse_account_map
+from erpnext.assets.doctype.asset.depreciation import get_gl_entries_on_asset_disposal, get_gl_entries_on_asset_regain,\
+	get_value_after_depreciation_on_disposal_date
 from six import string_types
 import json
 
@@ -21,7 +25,7 @@
 	'target_stock_uom', 'stock_uom', 'target_fixed_asset_account', 'fixed_asset_account']
 
 
-class AssetCapitalization(AccountsController):
+class AssetCapitalization(StockController):
 	def validate(self):
 		self.validate_posting_time()
 		self.set_missing_values(for_validate=True)
@@ -36,6 +40,18 @@
 		self.calculate_totals()
 		self.set_title()
 
+	def before_submit(self):
+		self.validate_source_mandatory()
+
+	def on_submit(self):
+		self.update_stock_ledger()
+		self.make_gl_entries()
+
+	def on_cancel(self):
+		self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry', 'Repost Item Valuation')
+		self.update_stock_ledger()
+		self.make_gl_entries()
+
 	def set_entry_type(self):
 		self.entry_type = "Capitalization" if self.target_is_fixed_asset else "Decapitalization"
 
@@ -104,11 +120,15 @@
 			self.target_warehouse = None
 		if not target_item.is_fixed_asset:
 			self.target_asset = None
+			self.target_fixed_asset_account = None
 		if not target_item.has_batch_no:
 			self.target_batch_no = None
 		if not target_item.has_serial_no:
 			self.target_serial_no = ""
 
+		if target_item.is_stock_item and not self.target_warehouse:
+			frappe.throw(_("Target Warehouse is mandatory for Decapitalization"))
+
 		self.validate_item(target_item)
 
 	def validate_target_asset(self):
@@ -165,6 +185,13 @@
 			if not d.cost_center:
 				d.cost_center = frappe.get_cached_value("Company", self.company, "cost_center")
 
+	def validate_source_mandatory(self):
+		if not self.target_is_fixed_asset and not self.get('asset_items'):
+			frappe.throw(_("Consumed Asset Items is mandatory for Decapitalization"))
+
+		if not self.get('stock_items') and not self.get('asset_items'):
+			frappe.throw(_("Consumed Stock Items or Consumed Asset Items is mandatory for Capitalization"))
+
 	def validate_item(self, item):
 		from erpnext.stock.doctype.item.item import validate_end_of_life
 		validate_end_of_life(item.name, item.end_of_life, item.disabled)
@@ -173,7 +200,7 @@
 		return frappe.db.get_value("Asset", asset, ["name", "item_code", "company", "status", "docstatus"], as_dict=1)
 
 	def validate_asset(self, asset):
-		if asset.status in ("Draft", "Scrapped", "Sold"):
+		if asset.status in ("Draft", "Scrapped", "Sold", "Capitalized", "Decapitalized"):
 			frappe.throw(_("Asset {0} is {1}").format(asset.name, asset.status))
 
 		if asset.docstatus == 0:
@@ -196,7 +223,10 @@
 	def set_asset_values(self):
 		for d in self.asset_items:
 			if d.asset:
-				d.asset_value = flt(get_current_asset_value(d.asset, d.get('finance_book') or self.finance_book))
+				finance_book = d.get('finance_book') or self.get('finance_book')
+				d.current_asset_value = flt(get_current_asset_value(d.asset, finance_book=finance_book))
+				d.asset_value = get_value_after_depreciation_on_disposal_date(d.asset, self.posting_date,
+					finance_book=finance_book)
 
 	def get_args_for_incoming_rate(self, item):
 		return frappe._dict({
@@ -240,6 +270,180 @@
 		self.target_qty = flt(self.target_qty, self.precision('target_qty'))
 		self.target_incoming_rate = self.total_value / self.target_qty
 
+	def update_stock_ledger(self):
+		sl_entries = []
+
+		for d in self.stock_items:
+			sle = self.get_sl_entries(d, {
+				"actual_qty": -flt(d.stock_qty),
+			})
+			sl_entries.append(sle)
+
+		if not frappe.db.get_value("Item", self.target_item_code, "is_fixed_asset", cache=1):
+			sle = self.get_sl_entries(self, {
+				"item_code": self.target_item_code,
+				"warehouse": self.target_warehouse,
+				"batch_no": self.target_batch_no,
+				"serial_no": self.target_serial_no,
+				"actual_qty": flt(self.target_qty),
+				"incoming_rate": flt(self.target_incoming_rate)
+			})
+			sl_entries.append(sle)
+
+		# reverse sl entries if cancel
+		if self.docstatus == 2:
+			sl_entries.reverse()
+
+		if sl_entries:
+			self.make_sl_entries(sl_entries)
+
+	def make_gl_entries(self, gl_entries=None, from_repost=False):
+		from erpnext.accounts.general_ledger import make_gl_entries, make_reverse_gl_entries
+
+		if not gl_entries:
+			gl_entries = self.get_gl_entries()
+
+		if self.docstatus == 1:
+			if gl_entries:
+				make_gl_entries(gl_entries, from_repost=from_repost)
+		elif self.docstatus == 2:
+			make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
+
+	def get_gl_entries(self, warehouse_account=None, default_expense_account=None, default_cost_center=None):
+		# Stock GL Entries
+		gl_entries = []
+
+		if not warehouse_account:
+			warehouse_account = get_warehouse_account_map(self.company)
+
+		precision = self.get_debit_field_precision()
+		sle_map = self.get_stock_ledger_details()
+
+		if self.target_is_fixed_asset:
+			target_account = self.target_fixed_asset_account
+		else:
+			target_account = warehouse_account[self.target_warehouse]["account"]
+
+		target_against = set()
+
+		# Consumed Stock Items
+		total_consumed_stock_value = 0
+		for item_row in self.stock_items:
+			sle_list = sle_map.get(item_row.name)
+			if sle_list:
+				for sle in sle_list:
+					stock_value_difference = flt(sle.stock_value_difference, precision)
+					total_consumed_stock_value += -1 * sle.stock_value_difference
+
+					account = warehouse_account[sle.warehouse]["account"]
+					target_against.add(account)
+
+					gl_entries.append(self.get_gl_dict({
+						"account": account,
+						"against": target_account,
+						"cost_center": item_row.cost_center,
+						"project": item_row.get('project') or self.get('project'),
+						"remarks": self.get("remarks") or "Accounting Entry for Stock",
+						"credit": -1 * stock_value_difference,
+					}, warehouse_account[sle.warehouse]["account_currency"], item=item_row))
+
+		# Consumed Assets
+		for item in self.asset_items:
+			asset = self.get_asset(item)
+
+			if self.docstatus == 2:
+				fixed_asset_gl_entries = get_gl_entries_on_asset_regain(asset,
+					item.asset_value, item.get('finance_book') or self.get('finance_book'))
+				asset.db_set("disposal_date", None)
+
+				self.set_consumed_asset_status(asset)
+
+				if asset.calculate_depreciation:
+					self.reset_depreciation_schedule(asset)
+			else:
+				if asset.calculate_depreciation:
+					self.depreciate_asset(asset)
+
+				asset.reload()
+				fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(asset,
+					item.asset_value, item.get('finance_book') or self.get('finance_book'))
+				asset.db_set("disposal_date", self.posting_date)
+
+				self.set_consumed_asset_status(asset)
+
+			for gle in fixed_asset_gl_entries:
+				gle["against"] = target_account
+				gl_entries.append(self.get_gl_dict(gle, item=item))
+
+		# Service Expenses
+		total_service_expenses = 0
+		for item_row in self.service_items:
+			expense_amount = flt(item_row.amount, precision)
+			total_service_expenses += expense_amount
+			target_against.add(item_row.expense_account)
+
+			gl_entries.append(self.get_gl_dict({
+				"account": item_row.expense_account,
+				"against": target_account,
+				"cost_center": item_row.cost_center,
+				"project": item_row.get('project') or self.get('project'),
+				"remarks": self.get("remarks") or "Accounting Entry for Stock",
+				"credit": expense_amount,
+			}, item=item_row))
+
+		target_against = ", ".join(target_against)
+		total_target_stock_value = 0
+		total_target_asset_value = 0
+
+		if self.target_is_fixed_asset:
+			# Target Asset Item
+			total_target_asset_value = flt(self.total_value, precision)
+			gl_entries.append(self.get_gl_dict({
+				"account": self.target_fixed_asset_account,
+				"against": target_against,
+				"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
+				"debit": total_target_asset_value,
+				"cost_center": self.get('cost_center')
+			}, item=self))
+
+			if self.docstatus == 1:
+				asset_doc = frappe.get_doc("Asset", self.target_asset)
+				asset_doc.purchase_date = self.posting_date
+				asset_doc.gross_purchase_amount = total_target_asset_value
+				asset_doc.purchase_receipt_amount = total_target_asset_value
+				asset_doc.prepare_depreciation_data()
+				asset_doc.flags.ignore_validate_update_after_submit = True
+				asset_doc.save()
+		else:
+			# Target Stock Item
+			sle_list = sle_map.get(self.name)
+			for sle in sle_list:
+				stock_value_difference = flt(sle.stock_value_difference, precision)
+				total_target_stock_value += sle.stock_value_difference
+				account = warehouse_account[sle.warehouse]["account"]
+
+				gl_entries.append(self.get_gl_dict({
+					"account": account,
+					"against": target_against,
+					"cost_center": self.cost_center,
+					"project": self.get('project'),
+					"remarks": self.get("remarks") or "Accounting Entry for Stock",
+					"debit": stock_value_difference,
+				}, warehouse_account[sle.warehouse]["account_currency"], item=self))
+
+		return gl_entries
+
+	def get_asset(self, item):
+		asset = frappe.get_doc("Asset", item.asset)
+		self.check_finance_books(item, asset)
+		return asset
+
+	def set_consumed_asset_status(self, asset):
+		if self.docstatus == 1:
+			asset.set_status("Capitalized" if self.target_is_fixed_asset else "Decapitalized")
+		else:
+			asset.set_status()
+
 
 @frappe.whitelist()
 def get_target_item_details(item_code=None, company=None):
@@ -395,8 +599,11 @@
 
 	if get_asset_value:
 		if args.asset:
-			out.asset_value = flt(get_current_asset_value(args.asset, finance_book=args.finance_book))
+			out.current_asset_value = flt(get_current_asset_value(args.asset, finance_book=args.finance_book))
+			out.asset_value = get_value_after_depreciation_on_disposal_date(args.asset, args.posting_date,
+				finance_book=args.finance_book)
 		else:
+			out.current_asset_value = 0
 			out.asset_value = 0
 
 	# Account
diff --git a/erpnext/assets/doctype/asset_capitalization_asset_item/asset_capitalization_asset_item.json b/erpnext/assets/doctype/asset_capitalization_asset_item/asset_capitalization_asset_item.json
index a5f8202..ebaaffb 100644
--- a/erpnext/assets/doctype/asset_capitalization_asset_item/asset_capitalization_asset_item.json
+++ b/erpnext/assets/doctype/asset_capitalization_asset_item/asset_capitalization_asset_item.json
@@ -12,6 +12,7 @@
   "item_code",
   "item_name",
   "section_break_6",
+  "current_asset_value",
   "asset_value",
   "column_break_9",
   "accounting_dimensions_section",
@@ -102,12 +103,20 @@
    "fieldtype": "Link",
    "label": "Finance Book",
    "options": "Finance Book"
+  },
+  {
+   "fieldname": "current_asset_value",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Current Asset Value",
+   "options": "Company:company:default_currency",
+   "read_only": 1
   }
  ],
  "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2021-09-08 23:42:25.143272",
+ "modified": "2021-09-12 14:30:02.915132",
  "modified_by": "Administrator",
  "module": "Assets",
  "name": "Asset Capitalization Asset Item",
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index b90db05..930dca8 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -54,6 +54,7 @@
 	get_item_tax_map,
 	get_item_warehouse,
 )
+from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries
 from erpnext.utilities.transaction_base import TransactionBase
 
 
@@ -1457,6 +1458,86 @@
 		jv.save()
 		jv.submit()
 
+	def check_finance_books(self, item, asset):
+		if (len(asset.finance_books) > 1 and not item.get('finance_book') and not self.get('finance_book')
+			and asset.finance_books[0].finance_book):
+			frappe.throw(_("Select finance book for the item {0} at row {1}")
+				.format(item.item_code, item.idx))
+
+	def depreciate_asset(self, asset):
+		asset.flags.ignore_validate_update_after_submit = True
+		asset.prepare_depreciation_data(self.posting_date)
+		asset.save()
+
+		post_depreciation_entries(self.posting_date, commit=False)
+
+	def reset_depreciation_schedule(self, asset):
+		asset.flags.ignore_validate_update_after_submit = True
+
+		# recreate original depreciation schedule of the asset
+		asset.prepare_depreciation_data()
+
+		self.modify_depreciation_schedule_for_asset_repairs(asset)
+		asset.save()
+
+		self.delete_depreciation_entry_made_after_disposal(asset)
+
+	def modify_depreciation_schedule_for_asset_repairs(self, asset):
+		asset_repairs = frappe.get_all(
+			'Asset Repair',
+			filters={'asset': asset.name},
+			fields=['name', 'increase_in_asset_life']
+		)
+
+		for repair in asset_repairs:
+			if repair.increase_in_asset_life:
+				asset_repair = frappe.get_doc('Asset Repair', repair.name)
+				asset_repair.modify_depreciation_schedule()
+				asset.prepare_depreciation_data()
+
+	def delete_depreciation_entry_made_after_disposal(self, asset):
+		from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry
+
+		posting_date_of_original_invoice = self.get_posting_date_of_disposal_entry()
+
+		row = -1
+		finance_book = asset.get('schedules')[0].get('finance_book')
+		for schedule in asset.get('schedules'):
+			if schedule.finance_book != finance_book:
+				row = 0
+				finance_book = schedule.finance_book
+			else:
+				row += 1
+
+			if schedule.schedule_date == posting_date_of_original_invoice:
+				if not self.disposal_was_made_on_original_schedule_date(asset, schedule, row,
+					posting_date_of_original_invoice):
+					reverse_journal_entry = make_reverse_journal_entry(schedule.journal_entry)
+					reverse_journal_entry.posting_date = nowdate()
+
+					for d in reverse_journal_entry.accounts:
+						d.reference_type = "Asset"
+						d.reference_name = asset.name
+
+					reverse_journal_entry.submit()
+
+	def get_posting_date_of_disposal_entry(self):
+		if self.doctype == "Sales Invoice" and self.return_against:
+			return frappe.db.get_value('Sales Invoice', self.return_against, 'posting_date')
+		else:
+			return self.posting_date
+
+	# if the invoice had been posted on the date the depreciation was initially supposed to happen, the depreciation shouldn't be undone
+	def disposal_was_made_on_original_schedule_date(self, asset, schedule, row, posting_date_of_original_disposal):
+		for finance_book in asset.get('finance_books'):
+			if schedule.finance_book == finance_book.finance_book:
+				orginal_schedule_date = add_months(finance_book.depreciation_start_date,
+					row * cint(finance_book.frequency_of_depreciation))
+
+				if orginal_schedule_date == posting_date_of_original_disposal:
+					return True
+		return False
+
 @frappe.whitelist()
 def get_tax_rate(account_head):
 	return frappe.db.get_value("Account", account_head, ["tax_rate", "account_name"], as_dict=True)