feat: Asset Capitalization
- manual selection of entry type
- GLE cleanup with smaller functions
- GLE considering periodical inventory
- test cases
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index 132840e..e7af9bd 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -1425,6 +1425,16 @@
 			"depreciation_expense_account": "_Test Depreciations - _TC",
 		},
 	)
+	asset_category.append(
+		"accounts",
+		{
+			"company_name": "_Test Company with perpetual inventory",
+			"fixed_asset_account": "_Test Fixed Asset - TCP1",
+			"accumulated_depreciation_account": "_Test Accumulated Depreciations - TCP1",
+			"depreciation_expense_account": "_Test Depreciations - TCP1",
+		},
+	)
+
 	asset_category.insert()
 
 
diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js
index d135e60..9c7f70b 100644
--- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js
+++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js
@@ -27,7 +27,11 @@
 		me.setup_warehouse_query();
 
 		me.frm.set_query("target_item_code", function() {
-			return erpnext.queries.item();
+			if (me.frm.doc.entry_type == "Capitalization") {
+				return erpnext.queries.item({"is_stock_item": 0, "is_fixed_asset": 1});
+			} else {
+				return erpnext.queries.item({"is_stock_item": 1, "is_fixed_asset": 0});
+			}
 		});
 
 		me.frm.set_query("target_asset", function() {
@@ -410,5 +414,4 @@
 	}
 };
 
-//$.extend(cur_frm.cscript, new erpnext.assets.AssetCapitalization({frm: cur_frm}));
 cur_frm.cscript = new erpnext.assets.AssetCapitalization({frm: cur_frm});
diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.json b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.json
index d7e6b54..d1be575 100644
--- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.json
+++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.json
@@ -8,29 +8,28 @@
  "engine": "InnoDB",
  "field_order": [
   "title",
+  "naming_series",
+  "entry_type",
   "target_item_code",
   "target_item_name",
   "target_is_fixed_asset",
   "target_has_batch_no",
   "target_has_serial_no",
-  "entry_type",
-  "finance_book",
-  "naming_series",
   "column_break_9",
+  "target_asset",
+  "target_asset_name",
+  "target_warehouse",
+  "target_qty",
+  "target_stock_uom",
+  "target_batch_no",
+  "target_serial_no",
+  "column_break_5",
   "company",
+  "finance_book",
   "posting_date",
   "posting_time",
   "set_posting_time",
   "amended_from",
-  "target_item_details_section",
-  "target_asset",
-  "target_asset_name",
-  "target_warehouse",
-  "target_batch_no",
-  "target_serial_no",
-  "column_break_5",
-  "target_qty",
-  "target_stock_uom",
   "section_break_16",
   "stock_items",
   "stock_items_total",
@@ -86,16 +85,17 @@
    "fieldtype": "Column Break"
   },
   {
-   "depends_on": "eval:!doc.target_item_code || doc.target_is_fixed_asset",
+   "depends_on": "eval:doc.entry_type=='Capitalization'",
    "fieldname": "target_asset",
    "fieldtype": "Link",
    "in_standard_filter": 1,
    "label": "Target Asset",
+   "mandatory_depends_on": "eval:doc.entry_type=='Capitalization'",
    "no_copy": 1,
    "options": "Asset"
   },
   {
-   "depends_on": "target_asset",
+   "depends_on": "eval:doc.entry_type=='Capitalization'",
    "fetch_from": "target_asset.asset_name",
    "fieldname": "target_asset_name",
    "fieldtype": "Data",
@@ -170,15 +170,11 @@
    "options": "Asset Capitalization Stock Item"
   },
   {
-   "fieldname": "target_item_details_section",
-   "fieldtype": "Section Break",
-   "label": "Target Item Details"
-  },
-  {
-   "depends_on": "eval:!doc.target_is_fixed_asset",
+   "depends_on": "eval:doc.entry_type=='Decapitalization'",
    "fieldname": "target_warehouse",
    "fieldtype": "Link",
    "label": "Target Warehouse",
+   "mandatory_depends_on": "eval:doc.entry_type=='Decapitalization'",
    "options": "Warehouse"
   },
   {
@@ -240,13 +236,14 @@
    "options": "Asset Capitalization Asset Item"
   },
   {
+   "default": "Capitalization",
    "fieldname": "entry_type",
    "fieldtype": "Select",
    "in_list_view": 1,
    "in_standard_filter": 1,
    "label": "Entry Type",
-   "options": "\nCapitalization\nDecapitalization",
-   "read_only": 1
+   "options": "Capitalization\nDecapitalization",
+   "reqd": 1
   },
   {
    "fieldname": "stock_items_total",
@@ -337,7 +334,7 @@
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2021-09-15 15:41:27.917458",
+ "modified": "2022-09-12 15:09:40.771332",
  "modified_by": "Administrator",
  "module": "Assets",
  "name": "Asset Capitalization",
@@ -377,6 +374,7 @@
  ],
  "sort_field": "modified",
  "sort_order": "DESC",
+ "states": [],
  "title_field": "title",
  "track_changes": 1,
  "track_seen": 1
diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
index a8f2d79..2e6f0ad 100644
--- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
+++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
@@ -10,9 +10,9 @@
 from frappe.utils import cint, flt
 from six import string_types
 
+import erpnext
 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 erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
@@ -32,16 +32,26 @@
 from erpnext.stock.stock_ledger import get_previous_sle
 from erpnext.stock.utils import get_incoming_rate
 
-force_fields = ['target_item_name', 'target_asset_name', 'item_name', 'asset_name',
-	'target_is_fixed_asset', 'target_has_serial_no', 'target_has_batch_no',
-	'target_stock_uom', 'stock_uom', 'target_fixed_asset_account', 'fixed_asset_account']
+force_fields = [
+	"target_item_name",
+	"target_asset_name",
+	"item_name",
+	"asset_name",
+	"target_is_fixed_asset",
+	"target_has_serial_no",
+	"target_has_batch_no",
+	"target_stock_uom",
+	"stock_uom",
+	"target_fixed_asset_account",
+	"fixed_asset_account",
+	"valuation_rate",
+]
 
 
 class AssetCapitalization(StockController):
 	def validate(self):
 		self.validate_posting_time()
 		self.set_missing_values(for_validate=True)
-		self.set_entry_type()
 		self.validate_target_item()
 		self.validate_target_asset()
 		self.validate_consumed_stock_item()
@@ -58,14 +68,13 @@
 	def on_submit(self):
 		self.update_stock_ledger()
 		self.make_gl_entries()
+		self.update_target_asset()
 
 	def on_cancel(self):
-		self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry', 'Repost Item Valuation')
+		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"
+		self.update_target_asset()
 
 	def set_title(self):
 		self.title = self.target_asset_name or self.target_item_name or self.target_item_code
@@ -90,7 +99,7 @@
 			args.update(d.as_dict())
 			args.doctype = self.doctype
 			args.name = self.name
-			consumed_stock_item_details = get_consumed_stock_item_details(args, get_valuation_rate=False)
+			consumed_stock_item_details = get_consumed_stock_item_details(args)
 			for k, v in consumed_stock_item_details.items():
 				if d.meta.has_field(k) and (not d.get(k) or k in force_fields):
 					d.set(k, v)
@@ -100,8 +109,8 @@
 			args.update(d.as_dict())
 			args.doctype = self.doctype
 			args.name = self.name
-			args.finance_book = d.get('finance_book') or self.get('finance_book')
-			consumed_asset_details = get_consumed_asset_details(args, get_asset_value=False)
+			args.finance_book = d.get("finance_book") or self.get("finance_book")
+			consumed_asset_details = get_consumed_asset_details(args)
 			for k, v in consumed_asset_details.items():
 				if d.meta.has_field(k) and (not d.get(k) or k in force_fields):
 					d.set(k, v)
@@ -120,8 +129,14 @@
 		target_item = frappe.get_cached_doc("Item", self.target_item_code)
 
 		if not target_item.is_fixed_asset and not target_item.is_stock_item:
-			frappe.throw(_("Target Item {0} is neither a Fixed Asset nor a Stock Item")
-				.format(target_item.name))
+			frappe.throw(
+				_("Target Item {0} is neither a Fixed Asset nor a Stock Item").format(target_item.name)
+			)
+
+		if self.entry_type == "Capitalization" and not target_item.is_fixed_asset:
+			frappe.throw(_("Target Item {0} must be a Fixed Asset item").format(target_item.name))
+		elif self.entry_type == "Decapitalization" and not target_item.is_stock_item:
+			frappe.throw(_("Target Item {0} must be a Stock Item").format(target_item.name))
 
 		if target_item.is_fixed_asset:
 			self.target_qty = 1
@@ -144,14 +159,13 @@
 		self.validate_item(target_item)
 
 	def validate_target_asset(self):
-		if self.target_is_fixed_asset and not self.target_asset:
-			frappe.throw(_("Target Asset is mandatory for Capitalization"))
-
 		if self.target_asset:
 			target_asset = self.get_asset_for_validation(self.target_asset)
 
 			if target_asset.item_code != self.target_item_code:
-				frappe.throw(_("Asset {0} does not belong to Item {1}").format(self.target_asset, self.target_item_code))
+				frappe.throw(
+					_("Asset {0} does not belong to Item {1}").format(self.target_asset, self.target_item_code)
+				)
 
 			self.validate_asset(target_asset)
 
@@ -172,8 +186,11 @@
 		for d in self.asset_items:
 			if d.asset:
 				if d.asset == self.target_asset:
-					frappe.throw(_("Row #{0}: Consumed Asset {1} cannot be the same as the Target Asset")
-						.format(d.idx, d.asset))
+					frappe.throw(
+						_("Row #{0}: Consumed Asset {1} cannot be the same as the Target Asset").format(
+							d.idx, d.asset
+						)
+					)
 
 				asset = self.get_asset_for_validation(d.asset)
 				self.validate_asset(asset)
@@ -198,18 +215,21 @@
 				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'):
+		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'):
+		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)
 
 	def get_asset_for_validation(self, asset):
-		return frappe.db.get_value("Asset", asset, ["name", "item_code", "company", "status", "docstatus"], as_dict=1)
+		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", "Capitalized", "Decapitalized"):
@@ -225,7 +245,7 @@
 
 	@frappe.whitelist()
 	def set_warehouse_details(self):
-		for d in self.get('stock_items'):
+		for d in self.get("stock_items"):
 			if d.item_code and d.warehouse:
 				args = self.get_args_for_incoming_rate(d)
 				warehouse_details = get_warehouse_details(args)
@@ -233,27 +253,30 @@
 
 	@frappe.whitelist()
 	def set_asset_values(self):
-		for d in self.get('asset_items'):
+		for d in self.get("asset_items"):
 			if d.asset:
-				finance_book = d.get('finance_book') or self.get('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)
+				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({
-			"item_code": item.item_code,
-			"warehouse": item.warehouse,
-			"posting_date": self.posting_date,
-			"posting_time": self.posting_time,
-			"qty": -1 * flt(item.stock_qty),
-			"serial_no": item.serial_no,
-			"batch_no": item.batch_no,
-			"voucher_type": self.doctype,
-			"voucher_no": self.name,
-			"company": self.company,
-			"allow_zero_valuation": cint(item.get('allow_zero_valuation_rate')),
-		})
+		return frappe._dict(
+			{
+				"item_code": item.item_code,
+				"warehouse": item.warehouse,
+				"posting_date": self.posting_date,
+				"posting_time": self.posting_time,
+				"qty": -1 * flt(item.stock_qty),
+				"serial_no": item.serial_no,
+				"batch_no": item.batch_no,
+				"voucher_type": self.doctype,
+				"voucher_no": self.name,
+				"company": self.company,
+				"allow_zero_valuation": cint(item.get("allow_zero_valuation_rate")),
+			}
+		)
 
 	def calculate_totals(self):
 		self.stock_items_total = 0
@@ -261,45 +284,51 @@
 		self.service_items_total = 0
 
 		for d in self.stock_items:
-			d.amount = flt(flt(d.stock_qty) * flt(d.valuation_rate), d.precision('amount'))
+			d.amount = flt(flt(d.stock_qty) * flt(d.valuation_rate), d.precision("amount"))
 			self.stock_items_total += d.amount
 
 		for d in self.asset_items:
-			d.asset_value = flt(flt(d.asset_value), d.precision('asset_value'))
+			d.asset_value = flt(flt(d.asset_value), d.precision("asset_value"))
 			self.asset_items_total += d.asset_value
 
 		for d in self.service_items:
-			d.amount = flt(flt(d.qty) * flt(d.rate), d.precision('amount'))
+			d.amount = flt(flt(d.qty) * flt(d.rate), d.precision("amount"))
 			self.service_items_total += d.amount
 
-		self.stock_items_total = flt(self.stock_items_total, self.precision('stock_items_total'))
-		self.asset_items_total = flt(self.asset_items_total, self.precision('asset_items_total'))
-		self.service_items_total = flt(self.service_items_total, self.precision('service_items_total'))
+		self.stock_items_total = flt(self.stock_items_total, self.precision("stock_items_total"))
+		self.asset_items_total = flt(self.asset_items_total, self.precision("asset_items_total"))
+		self.service_items_total = flt(self.service_items_total, self.precision("service_items_total"))
 
 		self.total_value = self.stock_items_total + self.asset_items_total + self.service_items_total
-		self.total_value = flt(self.total_value, self.precision('total_value'))
+		self.total_value = flt(self.total_value, self.precision("total_value"))
 
-		self.target_qty = flt(self.target_qty, self.precision('target_qty'))
+		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),
-			})
+			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)
-			})
+		if self.entry_type == "Decapitalization" and not self.target_is_fixed_asset:
+			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
@@ -312,139 +341,183 @@
 	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 not gl_entries:
+				gl_entries = self.get_gl_entries()
+
 			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):
+	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)
+		self.warehouse_account = warehouse_account
+		if not self.warehouse_account:
+			self.warehouse_account = get_warehouse_account_map(self.company)
 
 		precision = self.get_debit_field_precision()
-		sle_map = self.get_stock_ledger_details()
+		self.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_account = self.get_target_account()
 		target_against = set()
 
+		self.get_gl_entries_for_consumed_stock_items(
+			gl_entries, target_account, target_against, precision
+		)
+		self.get_gl_entries_for_consumed_asset_items(
+			gl_entries, target_account, target_against, precision
+		)
+		self.get_gl_entries_for_consumed_service_items(
+			gl_entries, target_account, target_against, precision
+		)
+
+		self.get_gl_entries_for_target_item(gl_entries, target_against, precision)
+		return gl_entries
+
+	def get_target_account(self):
+		if self.target_is_fixed_asset:
+			return self.target_fixed_asset_account
+		else:
+			return self.warehouse_account[self.target_warehouse]["account"]
+
+	def get_gl_entries_for_consumed_stock_items(
+		self, gl_entries, target_account, target_against, precision
+	):
 		# Consumed Stock Items
-		total_consumed_stock_value = 0
 		for item_row in self.stock_items:
-			sle_list = sle_map.get(item_row.name)
+			sle_list = self.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"]
+					if erpnext.is_perpetual_inventory_enabled(self.company):
+						account = self.warehouse_account[sle.warehouse]["account"]
+					else:
+						account = self.get_company_default("default_expense_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,
+							},
+							self.warehouse_account[sle.warehouse]["account_currency"],
+							item=item_row,
+						)
+					)
 
-					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))
-
+	def get_gl_entries_for_consumed_asset_items(
+		self, gl_entries, target_account, target_against, precision
+	):
 		# 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)
+			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))
+				target_against.add(gle["account"])
+
+	def get_gl_entries_for_consumed_service_items(
+		self, gl_entries, target_account, target_against, precision
+	):
+		# Service Expenses
+		for item_row in self.service_items:
+			expense_amount = flt(item_row.amount, precision)
+			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,
+				)
+			)
+
+	def get_gl_entries_for_target_item(self, gl_entries, target_against, precision):
+		if self.target_is_fixed_asset:
+			# Capitalization
+			gl_entries.append(
+				self.get_gl_dict(
+					{
+						"account": self.target_fixed_asset_account,
+						"against": ", ".join(target_against),
+						"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
+						"debit": flt(self.total_value, precision),
+						"cost_center": self.get("cost_center"),
+					},
+					item=self,
+				)
+			)
+		else:
+			# Target Stock Item
+			sle_list = self.sle_map.get(self.name)
+			for sle in sle_list:
+				stock_value_difference = flt(sle.stock_value_difference, precision)
+				account = self.warehouse_account[sle.warehouse]["account"]
+
+				gl_entries.append(
+					self.get_gl_dict(
+						{
+							"account": account,
+							"against": ", ".join(target_against),
+							"cost_center": self.cost_center,
+							"project": self.get("project"),
+							"remarks": self.get("remarks") or "Accounting Entry for Stock",
+							"debit": stock_value_difference,
+						},
+						self.warehouse_account[sle.warehouse]["account_currency"],
+						item=self,
+					)
+				)
+
+	def update_target_asset(self):
+		total_target_asset_value = flt(self.total_value, self.precision("total_value"))
+		if self.docstatus == 1 and self.entry_type == "Capitalization":
+			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()
+		elif self.docstatus == 2:
+			for item in self.asset_items:
+				asset = self.get_asset(item)
+				asset.db_set("disposal_date", None)
 				self.set_consumed_asset_status(asset)
 
 				if asset.calculate_depreciation:
 					self.reverse_depreciation_entry_made_after_disposal(asset)
 					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)
@@ -489,16 +562,12 @@
 	item_defaults = get_item_defaults(item.name, company)
 	item_group_defaults = get_item_group_defaults(item.name, company)
 	brand_defaults = get_brand_defaults(item.name, company)
-	out.cost_center = get_default_cost_center(frappe._dict({'item_code': item.name, 'company': company}),
-		item_defaults, item_group_defaults, brand_defaults)
-
-	# Set Entry Type
-	if not item_code:
-		out.entry_type = ""
-	elif out.target_is_fixed_asset:
-		out.entry_type = "Capitalization"
-	else:
-		out.entry_type = "Decapitalization"
+	out.cost_center = get_default_cost_center(
+		frappe._dict({"item_code": item.name, "company": company}),
+		item_defaults,
+		item_group_defaults,
+		brand_defaults,
+	)
 
 	return out
 
@@ -510,7 +579,7 @@
 	# Get Asset Details
 	asset_details = frappe._dict()
 	if asset:
-		asset_details = frappe.db.get_value("Asset", asset, ['asset_name', 'item_code'], as_dict=1)
+		asset_details = frappe.db.get_value("Asset", asset, ["asset_name", "item_code"], as_dict=1)
 		if not asset_details:
 			frappe.throw(_("Asset {0} does not exist").format(asset))
 
@@ -521,8 +590,9 @@
 	out.asset_name = asset_details.asset_name
 
 	if asset_details.item_code:
-		out.target_fixed_asset_account = get_asset_category_account('fixed_asset_account', item=asset_details.item_code,
-			company=company)
+		out.target_fixed_asset_account = get_asset_category_account(
+			"fixed_asset_account", item=asset_details.item_code, company=company
+		)
 	else:
 		out.target_fixed_asset_account = None
 
@@ -530,7 +600,7 @@
 
 
 @frappe.whitelist()
-def get_consumed_stock_item_details(args, get_valuation_rate=True):
+def get_consumed_stock_item_details(args):
 	if isinstance(args, string_types):
 		args = json.loads(args)
 
@@ -554,24 +624,29 @@
 	item_defaults = get_item_defaults(item.name, args.company)
 	item_group_defaults = get_item_group_defaults(item.name, args.company)
 	brand_defaults = get_brand_defaults(item.name, args.company)
-	out.cost_center = get_default_cost_center(args, item_defaults, item_group_defaults, brand_defaults)
+	out.cost_center = get_default_cost_center(
+		args, item_defaults, item_group_defaults, brand_defaults
+	)
 
-	if get_valuation_rate:
-		if args.item_code and out.warehouse:
-			incoming_rate_args = frappe._dict({
-				'item_code': args.item_code,
-				'warehouse': out.warehouse,
-				'posting_date': args.posting_date,
-				'posting_time': args.posting_time,
-				'qty': -1 * flt(out.stock_qty),
+	if args.item_code and out.warehouse:
+		incoming_rate_args = frappe._dict(
+			{
+				"item_code": args.item_code,
+				"warehouse": out.warehouse,
+				"posting_date": args.posting_date,
+				"posting_time": args.posting_time,
+				"qty": -1 * flt(out.stock_qty),
 				"voucher_type": args.doctype,
 				"voucher_no": args.name,
 				"company": args.company,
-			})
-			out.update(get_warehouse_details(incoming_rate_args))
-		else:
-			out.valuation_rate = 0
-			out.actual_qty = 0
+				"serial_no": args.serial_no,
+				"batch_no": args.batch_no,
+			}
+		)
+		out.update(get_warehouse_details(incoming_rate_args))
+	else:
+		out.valuation_rate = 0
+		out.actual_qty = 0
 
 	return out
 
@@ -587,13 +662,13 @@
 	if args.warehouse and args.item_code:
 		out = {
 			"actual_qty": get_previous_sle(args).get("qty_after_transaction") or 0,
-			"valuation_rate": get_incoming_rate(args, raise_error_if_no_rate=False)
+			"valuation_rate": get_incoming_rate(args, raise_error_if_no_rate=False),
 		}
 	return out
 
 
 @frappe.whitelist()
-def get_consumed_asset_details(args, get_asset_value=True):
+def get_consumed_asset_details(args):
 	if isinstance(args, string_types):
 		args = json.loads(args)
 
@@ -602,7 +677,9 @@
 
 	asset_details = frappe._dict()
 	if args.asset:
-		asset_details = frappe.db.get_value("Asset", args.asset, ['asset_name', 'item_code', 'item_name'], as_dict=1)
+		asset_details = frappe.db.get_value(
+			"Asset", args.asset, ["asset_name", "item_code", "item_name"], as_dict=1
+		)
 		if not asset_details:
 			frappe.throw(_("Asset {0} does not exist").format(args.asset))
 
@@ -610,19 +687,22 @@
 	out.asset_name = asset_details.asset_name
 	out.item_name = asset_details.item_name
 
-	if get_asset_value:
-		if args.asset:
-			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
+	if args.asset:
+		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
 	if asset_details.item_code:
-		out.fixed_asset_account = get_asset_category_account('fixed_asset_account', item=asset_details.item_code,
-			company=args.company)
+		out.fixed_asset_account = get_asset_category_account(
+			"fixed_asset_account", item=asset_details.item_code, company=args.company
+		)
 	else:
 		out.fixed_asset_account = None
 
@@ -632,7 +712,9 @@
 		item_defaults = get_item_defaults(item.name, args.company)
 		item_group_defaults = get_item_group_defaults(item.name, args.company)
 		brand_defaults = get_brand_defaults(item.name, args.company)
-		out.cost_center = get_default_cost_center(args, item_defaults, item_group_defaults, brand_defaults)
+		out.cost_center = get_default_cost_center(
+			args, item_defaults, item_group_defaults, brand_defaults
+		)
 
 	return out
 
@@ -657,7 +739,11 @@
 	item_group_defaults = get_item_group_defaults(item.name, args.company)
 	brand_defaults = get_brand_defaults(item.name, args.company)
 
-	out.expense_account = get_default_expense_account(args, item_defaults, item_group_defaults, brand_defaults)
-	out.cost_center = get_default_cost_center(args, item_defaults, item_group_defaults, brand_defaults)
+	out.expense_account = get_default_expense_account(
+		args, item_defaults, item_group_defaults, brand_defaults
+	)
+	out.cost_center = get_default_cost_center(
+		args, item_defaults, item_group_defaults, brand_defaults
+	)
 
 	return out
diff --git a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py
index 7046de6..86861f0 100644
--- a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py
+++ b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py
@@ -22,9 +22,12 @@
 		create_asset_capitalization_data()
 		frappe.db.sql("delete from `tabTax Rule`")
 
-	def test_capitalization(self):
+	def test_capitalization_with_perpetual_inventory(self):
+		company = "_Test Company with perpetual inventory"
+		set_depreciation_settings_in_company(company=company)
+
 		# Variables
-		consumed_asset_value = 100_000
+		consumed_asset_value = 100000
 
 		stock_rate = 1000
 		stock_qty = 2
@@ -34,23 +37,39 @@
 		service_qty = 2
 		service_amount = 1000
 
-		total_amount = 103_000
+		total_amount = 103000
 
 		# Create assets
-		target_asset = create_asset(asset_name='Asset Capitalization Target Asset', submit=1)
-		consumed_asset = create_asset(asset_name='Asset Capitalization Consumable Asset', asset_value=consumed_asset_value,
-			submit=1)
+		target_asset = create_asset(
+			asset_name="Asset Capitalization Target Asset",
+			submit=1,
+			warehouse="Stores - TCP1",
+			company=company,
+		)
+		consumed_asset = create_asset(
+			asset_name="Asset Capitalization Consumable Asset",
+			asset_value=consumed_asset_value,
+			submit=1,
+			warehouse="Stores - TCP1",
+			company=company,
+		)
 
 		# Create and submit Asset Captitalization
-		asset_capitalization = create_asset_capitalization(target_asset=target_asset.name,
-			stock_qty=stock_qty, stock_rate=stock_rate,
+		asset_capitalization = create_asset_capitalization(
+			entry_type="Capitalization",
+			target_asset=target_asset.name,
+			stock_qty=stock_qty,
+			stock_rate=stock_rate,
 			consumed_asset=consumed_asset.name,
-			service_qty=service_qty, service_rate=service_rate,
-			service_expense_account='Expenses Included In Asset Valuation - _TC',
-			submit=1)
+			service_qty=service_qty,
+			service_rate=service_rate,
+			service_expense_account="Expenses Included In Asset Valuation - TCP1",
+			company=company,
+			submit=1,
+		)
 
 		# Test Asset Capitalization values
-		self.assertEqual(asset_capitalization.entry_type, 'Capitalization')
+		self.assertEqual(asset_capitalization.entry_type, "Capitalization")
 		self.assertEqual(asset_capitalization.target_qty, 1)
 
 		self.assertEqual(asset_capitalization.stock_items[0].valuation_rate, stock_rate)
@@ -72,13 +91,13 @@
 		self.assertEqual(target_asset.purchase_receipt_amount, total_amount)
 
 		# Test Consumed Asset values
-		self.assertEqual(consumed_asset.db_get('status'), 'Capitalized')
+		self.assertEqual(consumed_asset.db_get("status"), "Capitalized")
 
 		# Test General Ledger Entries
 		expected_gle = {
-			'_Test Fixed Asset - _TC': 3000,
-			'Expenses Included In Asset Valuation - _TC': -1000,
-			'Stock In Hand - _TC' : -2000
+			"_Test Fixed Asset - TCP1": 3000,
+			"Expenses Included In Asset Valuation - TCP1": -1000,
+			"_Test Warehouse - TCP1": -2000,
 		}
 		actual_gle = get_actual_gle_dict(asset_capitalization.name)
 
@@ -86,25 +105,121 @@
 
 		# Test Stock Ledger Entries
 		expected_sle = {
-			('Capitalization Source Stock Item', '_Test Warehouse - _TC'): {
-				'actual_qty': -stock_qty, 'stock_value_difference': -stock_amount
+			("Capitalization Source Stock Item", "_Test Warehouse - TCP1"): {
+				"actual_qty": -stock_qty,
+				"stock_value_difference": -stock_amount,
 			}
 		}
 		actual_sle = get_actual_sle_dict(asset_capitalization.name)
-
 		self.assertEqual(actual_sle, expected_sle)
 
 		# Cancel Asset Capitalization and make test entries and status are reversed
 		asset_capitalization.cancel()
-		self.assertEqual(consumed_asset.db_get('status'), 'Submitted')
+		self.assertEqual(consumed_asset.db_get("status"), "Submitted")
+		self.assertFalse(get_actual_gle_dict(asset_capitalization.name))
+		self.assertFalse(get_actual_sle_dict(asset_capitalization.name))
+
+	def test_capitalization_with_periodical_inventory(self):
+		company = "_Test Company"
+		# Variables
+		consumed_asset_value = 100000
+
+		stock_rate = 1000
+		stock_qty = 2
+		stock_amount = 2000
+
+		service_rate = 500
+		service_qty = 2
+		service_amount = 1000
+
+		total_amount = 103000
+
+		# Create assets
+		target_asset = create_asset(
+			asset_name="Asset Capitalization Target Asset",
+			submit=1,
+			warehouse="Stores - _TC",
+			company=company,
+		)
+		consumed_asset = create_asset(
+			asset_name="Asset Capitalization Consumable Asset",
+			asset_value=consumed_asset_value,
+			submit=1,
+			warehouse="Stores - _TC",
+			company=company,
+		)
+
+		# Create and submit Asset Captitalization
+		asset_capitalization = create_asset_capitalization(
+			entry_type="Capitalization",
+			target_asset=target_asset.name,
+			stock_qty=stock_qty,
+			stock_rate=stock_rate,
+			consumed_asset=consumed_asset.name,
+			service_qty=service_qty,
+			service_rate=service_rate,
+			service_expense_account="Expenses Included In Asset Valuation - _TC",
+			company=company,
+			submit=1,
+		)
+
+		# Test Asset Capitalization values
+		self.assertEqual(asset_capitalization.entry_type, "Capitalization")
+		self.assertEqual(asset_capitalization.target_qty, 1)
+
+		self.assertEqual(asset_capitalization.stock_items[0].valuation_rate, stock_rate)
+		self.assertEqual(asset_capitalization.stock_items[0].amount, stock_amount)
+		self.assertEqual(asset_capitalization.stock_items_total, stock_amount)
+
+		self.assertEqual(asset_capitalization.asset_items[0].asset_value, consumed_asset_value)
+		self.assertEqual(asset_capitalization.asset_items_total, consumed_asset_value)
+
+		self.assertEqual(asset_capitalization.service_items[0].amount, service_amount)
+		self.assertEqual(asset_capitalization.service_items_total, service_amount)
+
+		self.assertEqual(asset_capitalization.total_value, total_amount)
+		self.assertEqual(asset_capitalization.target_incoming_rate, total_amount)
+
+		# Test Target Asset values
+		target_asset.reload()
+		self.assertEqual(target_asset.gross_purchase_amount, total_amount)
+		self.assertEqual(target_asset.purchase_receipt_amount, total_amount)
+
+		# Test Consumed Asset values
+		self.assertEqual(consumed_asset.db_get("status"), "Capitalized")
+
+		# Test General Ledger Entries
+		default_expense_account = frappe.db.get_value("Company", company, "default_expense_account")
+		expected_gle = {
+			"_Test Fixed Asset - _TC": 3000,
+			"Expenses Included In Asset Valuation - _TC": -1000,
+			default_expense_account: -2000,
+		}
+		actual_gle = get_actual_gle_dict(asset_capitalization.name)
+
+		self.assertEqual(actual_gle, expected_gle)
+
+		# Test Stock Ledger Entries
+		expected_sle = {
+			("Capitalization Source Stock Item", "_Test Warehouse - _TC"): {
+				"actual_qty": -stock_qty,
+				"stock_value_difference": -stock_amount,
+			}
+		}
+		actual_sle = get_actual_sle_dict(asset_capitalization.name)
+		self.assertEqual(actual_sle, expected_sle)
+
+		# Cancel Asset Capitalization and make test entries and status are reversed
+		asset_capitalization.cancel()
+		self.assertEqual(consumed_asset.db_get("status"), "Submitted")
 		self.assertFalse(get_actual_gle_dict(asset_capitalization.name))
 		self.assertFalse(get_actual_sle_dict(asset_capitalization.name))
 
 	def test_decapitalization_with_depreciation(self):
 		# Variables
-		purchase_date = '2020-01-01'
-		depreciation_start_date = '2020-12-31'
-		capitalization_date = '2021-06-30'
+		purchase_date = "2020-01-01"
+		depreciation_start_date = "2020-12-31"
+		capitalization_date = "2021-06-30"
 
 		total_number_of_depreciations = 3
 		expected_value_after_useful_life = 10_000
@@ -126,29 +241,38 @@
 
 		# Create assets
 		consumed_asset = create_depreciation_asset(
-			asset_name='Asset Capitalization Consumable Asset',
+			asset_name="Asset Capitalization Consumable Asset",
 			asset_value=consumed_asset_purchase_value,
 			purchase_date=purchase_date,
 			depreciation_start_date=depreciation_start_date,
-			depreciation_method='Straight Line',
+			depreciation_method="Straight Line",
 			total_number_of_depreciations=total_number_of_depreciations,
 			frequency_of_depreciation=12,
 			expected_value_after_useful_life=expected_value_after_useful_life,
-			submit=1)
+			company="_Test Company with perpetual inventory",
+			submit=1,
+		)
 
 		# Create and submit Asset Captitalization
 		asset_capitalization = create_asset_capitalization(
+			entry_type="Decapitalization",
 			posting_date=capitalization_date,  # half a year
 			target_item_code="Capitalization Target Stock Item",
 			target_qty=target_qty,
 			consumed_asset=consumed_asset.name,
-			submit=1)
+			company="_Test Company with perpetual inventory",
+			submit=1,
+		)
 
 		# Test Asset Capitalization values
-		self.assertEqual(asset_capitalization.entry_type, 'Decapitalization')
+		self.assertEqual(asset_capitalization.entry_type, "Decapitalization")
 
-		self.assertEqual(asset_capitalization.asset_items[0].current_asset_value, consumed_asset_current_value)
-		self.assertEqual(asset_capitalization.asset_items[0].asset_value, consumed_asset_value_before_disposal)
+		self.assertEqual(
+			asset_capitalization.asset_items[0].current_asset_value, consumed_asset_current_value
+		)
+		self.assertEqual(
+			asset_capitalization.asset_items[0].asset_value, consumed_asset_value_before_disposal
+		)
 		self.assertEqual(asset_capitalization.asset_items_total, consumed_asset_value_before_disposal)
 
 		self.assertEqual(asset_capitalization.total_value, consumed_asset_value_before_disposal)
@@ -156,38 +280,45 @@
 
 		# Test Consumed Asset values
 		consumed_asset.reload()
-		self.assertEqual(consumed_asset.status, 'Decapitalized')
+		self.assertEqual(consumed_asset.status, "Decapitalized")
 
-		consumed_depreciation_schedule = [d for d in consumed_asset.schedules
-			if getdate(d.schedule_date) == getdate(capitalization_date)]
-		self.assertTrue(consumed_depreciation_schedule and consumed_depreciation_schedule[0].journal_entry)
-		self.assertEqual(consumed_depreciation_schedule[0].depreciation_amount, depreciation_before_disposal_amount)
+		consumed_depreciation_schedule = [
+			d for d in consumed_asset.schedules if getdate(d.schedule_date) == getdate(capitalization_date)
+		]
+		self.assertTrue(
+			consumed_depreciation_schedule and consumed_depreciation_schedule[0].journal_entry
+		)
+		self.assertEqual(
+			consumed_depreciation_schedule[0].depreciation_amount, depreciation_before_disposal_amount
+		)
 
 		# Test General Ledger Entries
 		expected_gle = {
-			'Stock In Hand - _TC': consumed_asset_value_before_disposal,
-			'_Test Accumulated Depreciations - _TC': accumulated_depreciation,
-			'_Test Fixed Asset - _TC': -consumed_asset_purchase_value,
+			"_Test Warehouse - TCP1": consumed_asset_value_before_disposal,
+			"_Test Accumulated Depreciations - TCP1": accumulated_depreciation,
+			"_Test Fixed Asset - TCP1": -consumed_asset_purchase_value,
 		}
 		actual_gle = get_actual_gle_dict(asset_capitalization.name)
-
 		self.assertEqual(actual_gle, expected_gle)
 
 		# Cancel Asset Capitalization and make test entries and status are reversed
 		asset_capitalization.reload()
 		asset_capitalization.cancel()
-		self.assertEqual(consumed_asset.db_get('status'), 'Partially Depreciated')
+		self.assertEqual(consumed_asset.db_get("status"), "Partially Depreciated")
 		self.assertFalse(get_actual_gle_dict(asset_capitalization.name))
 		self.assertFalse(get_actual_sle_dict(asset_capitalization.name))
 
 
 def create_asset_capitalization_data():
-	create_item("Capitalization Target Stock Item",
-		is_stock_item=1, is_fixed_asset=0, is_purchase_item=0)
-	create_item("Capitalization Source Stock Item",
-		is_stock_item=1, is_fixed_asset=0, is_purchase_item=0)
-	create_item("Capitalization Source Service Item",
-		is_stock_item=0, is_fixed_asset=0, is_purchase_item=0)
+	create_item(
+		"Capitalization Target Stock Item", is_stock_item=1, is_fixed_asset=0, is_purchase_item=0
+	)
+	create_item(
+		"Capitalization Source Stock Item", is_stock_item=1, is_fixed_asset=0, is_purchase_item=0
+	)
+	create_item(
+		"Capitalization Source Service Item", is_stock_item=0, is_fixed_asset=0, is_purchase_item=0
+	)
 
 
 def create_asset_capitalization(**args):
@@ -204,43 +335,55 @@
 	source_warehouse = args.source_warehouse or warehouse
 
 	asset_capitalization = frappe.new_doc("Asset Capitalization")
-	asset_capitalization.update({
-		"company": company,
-		"posting_date": args.posting_date or now.strftime('%Y-%m-%d'),
-		"posting_time": args.posting_time or now.strftime('%H:%M:%S.%f'),
-		"target_item_code": target_item_code,
-		"target_asset": target_asset.name,
-		"target_warehouse": target_warehouse,
-		"target_qty": flt(args.target_qty) or 1,
-		"target_batch_no": args.target_batch_no,
-		"target_serial_no": args.target_serial_no,
-		"finance_book": args.finance_book
-	})
+	asset_capitalization.update(
+		{
+			"entry_type": args.entry_type or "Capitalization",
+			"company": company,
+			"posting_date": args.posting_date or now.strftime("%Y-%m-%d"),
+			"posting_time": args.posting_time or now.strftime("%H:%M:%S.%f"),
+			"target_item_code": target_item_code,
+			"target_asset": target_asset.name,
+			"target_warehouse": target_warehouse,
+			"target_qty": flt(args.target_qty) or 1,
+			"target_batch_no": args.target_batch_no,
+			"target_serial_no": args.target_serial_no,
+			"finance_book": args.finance_book,
+		}
+	)
 
 	if args.posting_date or args.posting_time:
 		asset_capitalization.set_posting_time = 1
 
 	if flt(args.stock_rate):
-		asset_capitalization.append("stock_items", {
-			"item_code": args.stock_item or "Capitalization Source Stock Item",
-			"warehouse": source_warehouse,
-			"stock_qty": flt(args.stock_qty) or 1,
-			"batch_no": args.stock_batch_no,
-			"serial_no": args.stock_serial_no,
-		})
+		asset_capitalization.append(
+			"stock_items",
+			{
+				"item_code": args.stock_item or "Capitalization Source Stock Item",
+				"warehouse": source_warehouse,
+				"stock_qty": flt(args.stock_qty) or 1,
+				"batch_no": args.stock_batch_no,
+				"serial_no": args.stock_serial_no,
+			},
+		)
 
 	if args.consumed_asset:
-		asset_capitalization.append("asset_items", {
-			"asset": args.consumed_asset,
-		})
+		asset_capitalization.append(
+			"asset_items",
+			{
+				"asset": args.consumed_asset,
+			},
+		)
 
 	if flt(args.service_rate):
-		asset_capitalization.append("service_items", {
-			"item_code": args.service_item or "Capitalization Source Service Item",
-			"expense_account": args.service_expense_account,
-			"qty": flt(args.service_qty) or 1,
-			"rate": flt(args.service_rate)
-		})
+		asset_capitalization.append(
+			"service_items",
+			{
+				"item_code": args.service_item or "Capitalization Source Service Item",
+				"expense_account": args.service_expense_account,
+				"qty": flt(args.service_qty) or 1,
+				"rate": flt(args.service_rate),
+			},
+		)
 
 	if args.submit:
 		create_stock_reconciliation(asset_capitalization, stock_rate=args.stock_rate)
@@ -255,17 +398,23 @@
 
 def create_stock_reconciliation(asset_capitalization, stock_rate=0):
 	from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import (
+		EmptyStockReconciliationItemsError,
 		create_stock_reconciliation,
 	)
-	if not asset_capitalization.get('stock_items'):
+
+	if not asset_capitalization.get("stock_items"):
 		return
 
-	return create_stock_reconciliation(
-		item_code=asset_capitalization.stock_items[0].item_code,
-		warehouse=asset_capitalization.stock_items[0].warehouse,
-		qty=flt(asset_capitalization.stock_items[0].stock_qty),
-		rate=flt(stock_rate),
-		company=asset_capitalization.company)
+	try:
+		create_stock_reconciliation(
+			item_code=asset_capitalization.stock_items[0].item_code,
+			warehouse=asset_capitalization.stock_items[0].warehouse,
+			qty=flt(asset_capitalization.stock_items[0].stock_qty),
+			rate=flt(stock_rate),
+			company=asset_capitalization.company,
+		)
+	except EmptyStockReconciliationItemsError:
+		pass
 
 
 def create_depreciation_asset(**args):
@@ -281,15 +430,15 @@
 	asset.asset_name = args.asset_name or asset.item_code
 	asset.location = args.location or "Test Location"
 
-	asset.purchase_date = args.purchase_date or '2020-01-01'
+	asset.purchase_date = args.purchase_date or "2020-01-01"
 	asset.available_for_use_date = args.available_for_use_date or asset.purchase_date
 
 	asset.gross_purchase_amount = args.asset_value or 100000
 	asset.purchase_receipt_amount = asset.gross_purchase_amount
 
-	finance_book = asset.append('finance_books')
-	finance_book.depreciation_start_date = args.depreciation_start_date or '2020-12-31'
-	finance_book.depreciation_method = args.depreciation_method or 'Straight Line'
+	finance_book = asset.append("finance_books")
+	finance_book.depreciation_start_date = args.depreciation_start_date or "2020-12-31"
+	finance_book.depreciation_method = args.depreciation_method or "Straight Line"
 	finance_book.total_number_of_depreciations = cint(args.total_number_of_depreciations) or 3
 	finance_book.frequency_of_depreciation = cint(args.frequency_of_depreciation) or 12
 	finance_book.expected_value_after_useful_life = flt(args.expected_value_after_useful_life)
@@ -305,17 +454,23 @@
 
 
 def get_actual_gle_dict(name):
-	return dict(frappe.db.sql("""
+	return dict(
+		frappe.db.sql(
+			"""
 		select account, sum(debit-credit) as diff
 		from `tabGL Entry`
 		where voucher_type = 'Asset Capitalization' and voucher_no = %s
 		group by account
 		having diff != 0
-	""", name))
+	""",
+			name,
+		)
+	)
 
 
 def get_actual_sle_dict(name):
-	sles = frappe.db.sql("""
+	sles = frappe.db.sql(
+		"""
 		select
 			item_code, warehouse,
 			sum(actual_qty) as actual_qty,
@@ -324,12 +479,16 @@
 		where voucher_type = 'Asset Capitalization' and voucher_no = %s
 		group by item_code, warehouse
 		having actual_qty != 0
-	""", name, as_dict=1)
+	""",
+		name,
+		as_dict=1,
+	)
 
 	sle_dict = {}
 	for d in sles:
 		sle_dict[(d.item_code, d.warehouse)] = {
-			'actual_qty': d.actual_qty, 'stock_value_difference': d.stock_value_difference
+			"actual_qty": d.actual_qty,
+			"stock_value_difference": d.stock_value_difference,
 		}
 
 	return sle_dict
diff --git a/erpnext/assets/doctype/asset_repair/test_asset_repair.py b/erpnext/assets/doctype/asset_repair/test_asset_repair.py
index 6e06f52..2786349 100644
--- a/erpnext/assets/doctype/asset_repair/test_asset_repair.py
+++ b/erpnext/assets/doctype/asset_repair/test_asset_repair.py
@@ -129,18 +129,6 @@
 	def test_gl_entries_with_perpetual_inventory(self):
 		set_depreciation_settings_in_company(company="_Test Company with perpetual inventory")
 
-		asset_category = frappe.get_doc("Asset Category", "Computers")
-		asset_category.append(
-			"accounts",
-			{
-				"company_name": "_Test Company with perpetual inventory",
-				"fixed_asset_account": "_Test Fixed Asset - TCP1",
-				"accumulated_depreciation_account": "_Test Accumulated Depreciations - TCP1",
-				"depreciation_expense_account": "_Test Depreciations - TCP1",
-			},
-		)
-		asset_category.save()
-
 		asset_repair = create_asset_repair(
 			capitalize_repair_cost=1,
 			stock_consumption=1,
diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
index 191c03f..4e76ae7 100644
--- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
@@ -727,7 +727,12 @@
 	sr.set_posting_time = 1
 	sr.company = args.company or "_Test Company"
 	sr.expense_account = args.expense_account or (
-		"Stock Adjustment - _TC" if frappe.get_all("Stock Ledger Entry") else "Temporary Opening - _TC"
+		(
+			frappe.get_cached_value("Company", sr.company, "stock_adjustment_account")
+			or "Stock Adjustment - _TC"
+		)
+		if frappe.get_all("Stock Ledger Entry", {"company": sr.company})
+		else "Temporary Opening - _TC"
 	)
 	sr.cost_center = (
 		args.cost_center