Merge branch 'develop' into bank-trans-party-automatch
diff --git a/CODEOWNERS b/CODEOWNERS
index c4ea163..7f8c4d1 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -3,13 +3,13 @@
 # These owners will be the default owners for everything in
 # the repo. Unless a later match takes precedence,
 
-erpnext/accounts/               @nextchamp-saqib @deepeshgarg007 @ruthra-kumar
+erpnext/accounts/               @deepeshgarg007 @ruthra-kumar
 erpnext/assets/                 @anandbaburajan @deepeshgarg007
-erpnext/loan_management/        @nextchamp-saqib @deepeshgarg007
-erpnext/regional                @nextchamp-saqib @deepeshgarg007 @ruthra-kumar
-erpnext/selling                 @nextchamp-saqib @deepeshgarg007 @ruthra-kumar
-erpnext/support/                @nextchamp-saqib @deepeshgarg007
-pos*                            @nextchamp-saqib
+erpnext/loan_management/        @deepeshgarg007
+erpnext/regional                @deepeshgarg007 @ruthra-kumar
+erpnext/selling                 @deepeshgarg007 @ruthra-kumar
+erpnext/support/                @deepeshgarg007
+pos*                            
 
 erpnext/buying/                 @rohitwaghchaure @s-aga-r
 erpnext/maintenance/            @rohitwaghchaure @s-aga-r
@@ -18,12 +18,8 @@
 erpnext/stock/                  @rohitwaghchaure @s-aga-r
 erpnext/subcontracting          @rohitwaghchaure @s-aga-r
 
-erpnext/crm/                    @NagariaHussain
-erpnext/education/              @rutwikhdev
-erpnext/projects/               @ruchamahabal
+erpnext/controllers/            @deepeshgarg007 @rohitwaghchaure
+erpnext/patches/                @deepeshgarg007 
 
-erpnext/controllers/            @deepeshgarg007 @nextchamp-saqib @rohitwaghchaure
-erpnext/patches/                @deepeshgarg007 @nextchamp-saqib
-
-.github/                        @ankush
+.github/                        @deepeshgarg007
 pyproject.toml                  @ankush
diff --git a/erpnext/accounts/doctype/account/account.json b/erpnext/accounts/doctype/account/account.json
index d2659d4..e79fb66 100644
--- a/erpnext/accounts/doctype/account/account.json
+++ b/erpnext/accounts/doctype/account/account.json
@@ -18,7 +18,6 @@
   "root_type",
   "report_type",
   "account_currency",
-  "inter_company_account",
   "column_break1",
   "parent_account",
   "account_type",
@@ -34,15 +33,11 @@
   {
    "fieldname": "properties",
    "fieldtype": "Section Break",
-   "oldfieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "oldfieldtype": "Section Break"
   },
   {
    "fieldname": "column_break0",
    "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "50%"
   },
   {
@@ -53,9 +48,7 @@
    "no_copy": 1,
    "oldfieldname": "account_name",
    "oldfieldtype": "Data",
-   "reqd": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "reqd": 1
   },
   {
    "fieldname": "account_number",
@@ -63,17 +56,13 @@
    "in_list_view": 1,
    "in_standard_filter": 1,
    "label": "Account Number",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "default": "0",
    "fieldname": "is_group",
    "fieldtype": "Check",
-   "label": "Is Group",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Is Group"
   },
   {
    "fieldname": "company",
@@ -85,9 +74,7 @@
    "options": "Company",
    "read_only": 1,
    "remember_last_selected_value": 1,
-   "reqd": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "reqd": 1
   },
   {
    "fieldname": "root_type",
@@ -95,9 +82,7 @@
    "in_standard_filter": 1,
    "label": "Root Type",
    "options": "\nAsset\nLiability\nIncome\nExpense\nEquity",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "report_type",
@@ -105,32 +90,18 @@
    "in_standard_filter": 1,
    "label": "Report Type",
    "options": "\nBalance Sheet\nProfit and Loss",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "depends_on": "eval:doc.is_group==0",
    "fieldname": "account_currency",
    "fieldtype": "Link",
    "label": "Currency",
-   "options": "Currency",
-   "show_days": 1,
-   "show_seconds": 1
-  },
-  {
-   "default": "0",
-   "fieldname": "inter_company_account",
-   "fieldtype": "Check",
-   "label": "Inter Company Account",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Currency"
   },
   {
    "fieldname": "column_break1",
    "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "50%"
   },
   {
@@ -142,9 +113,7 @@
    "oldfieldtype": "Link",
    "options": "Account",
    "reqd": 1,
-   "search_index": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "search_index": 1
   },
   {
    "description": "Setting Account Type helps in selecting this Account in transactions.",
@@ -154,9 +123,7 @@
    "label": "Account Type",
    "oldfieldname": "account_type",
    "oldfieldtype": "Select",
-   "options": "\nAccumulated Depreciation\nAsset Received But Not Billed\nBank\nCash\nChargeable\nCapital Work in Progress\nCost of Goods Sold\nDepreciation\nEquity\nExpense Account\nExpenses Included In Asset Valuation\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nPayable\nReceivable\nRound Off\nStock\nStock Adjustment\nStock Received But Not Billed\nService Received But Not Billed\nTax\nTemporary",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "\nAccumulated Depreciation\nAsset Received But Not Billed\nBank\nCash\nChargeable\nCapital Work in Progress\nCost of Goods Sold\nDepreciation\nEquity\nExpense Account\nExpenses Included In Asset Valuation\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nPayable\nReceivable\nRound Off\nStock\nStock Adjustment\nStock Received But Not Billed\nService Received But Not Billed\nTax\nTemporary"
   },
   {
    "description": "Rate at which this tax is applied",
@@ -164,9 +131,7 @@
    "fieldtype": "Float",
    "label": "Rate",
    "oldfieldname": "tax_rate",
-   "oldfieldtype": "Currency",
-   "show_days": 1,
-   "show_seconds": 1
+   "oldfieldtype": "Currency"
   },
   {
    "description": "If the account is frozen, entries are allowed to restricted users.",
@@ -175,17 +140,13 @@
    "label": "Frozen",
    "oldfieldname": "freeze_account",
    "oldfieldtype": "Select",
-   "options": "No\nYes",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "No\nYes"
   },
   {
    "fieldname": "balance_must_be",
    "fieldtype": "Select",
    "label": "Balance must be",
-   "options": "\nDebit\nCredit",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "\nDebit\nCredit"
   },
   {
    "fieldname": "lft",
@@ -194,9 +155,7 @@
    "label": "Lft",
    "print_hide": 1,
    "read_only": 1,
-   "search_index": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "search_index": 1
   },
   {
    "fieldname": "rgt",
@@ -205,9 +164,7 @@
    "label": "Rgt",
    "print_hide": 1,
    "read_only": 1,
-   "search_index": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "search_index": 1
   },
   {
    "fieldname": "old_parent",
@@ -215,33 +172,27 @@
    "hidden": 1,
    "label": "Old Parent",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "default": "0",
    "depends_on": "eval:(doc.report_type == 'Profit and Loss' && !doc.is_group)",
    "fieldname": "include_in_gross",
    "fieldtype": "Check",
-   "label": "Include in gross",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Include in gross"
   },
   {
    "default": "0",
    "fieldname": "disabled",
    "fieldtype": "Check",
-   "label": "Disable",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Disable"
   }
  ],
  "icon": "fa fa-money",
  "idx": 1,
  "is_tree": 1,
  "links": [],
- "modified": "2020-06-11 15:15:54.338622",
+ "modified": "2023-04-11 16:08:46.983677",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Account",
@@ -301,5 +252,6 @@
  "show_name_in_global_search": 1,
  "sort_field": "modified",
  "sort_order": "ASC",
+ "states": [],
  "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
index 259612e..ed62669 100644
--- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
+++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
@@ -186,6 +186,7 @@
   },
   {
    "default": "0",
+   "description": "Payment Terms from orders will be fetched into the invoices as is",
    "fieldname": "automatically_fetch_payment_terms",
    "fieldtype": "Check",
    "label": "Automatically Fetch Payment Terms from Order"
@@ -389,7 +390,7 @@
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2023-04-04 16:20:41.330039",
+ "modified": "2023-04-14 17:22:03.680886",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Accounts Settings",
diff --git a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py
index 2cc5378..f7297d1 100644
--- a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py
@@ -287,10 +287,6 @@
 		jv.submit()
 
 	def test_inter_company_jv(self):
-		frappe.db.set_value("Account", "Sales Expenses - _TC", "inter_company_account", 1)
-		frappe.db.set_value("Account", "Buildings - _TC", "inter_company_account", 1)
-		frappe.db.set_value("Account", "Sales Expenses - _TC1", "inter_company_account", 1)
-		frappe.db.set_value("Account", "Buildings - _TC1", "inter_company_account", 1)
 		jv = make_journal_entry(
 			"Sales Expenses - _TC",
 			"Buildings - _TC",
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index f8969b8..ed6d0a7 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -970,29 +970,47 @@
 				},
 				callback: function(r, rt) {
 					if(r.message) {
-						var write_off_row = $.map(frm.doc["deductions"] || [], function(t) {
+						const write_off_row = $.map(frm.doc["deductions"] || [], function(t) {
 							return t.account==r.message[account] ? t : null; });
 
-						var row = [];
-
-						var difference_amount = flt(frm.doc.difference_amount,
+						const difference_amount = flt(frm.doc.difference_amount,
 							precision("difference_amount"));
 
-						if (!write_off_row.length && difference_amount) {
-							row = frm.add_child("deductions");
-							row.account = r.message[account];
-							row.cost_center = r.message["cost_center"];
-						} else {
-							row = write_off_row[0];
-						}
+						const add_deductions = (details) => {
+							if (!write_off_row.length && difference_amount) {
+								row = frm.add_child("deductions");
+								row.account = details[account];
+								row.cost_center = details["cost_center"];
+							} else {
+								row = write_off_row[0];
+							}
 
-						if (row) {
-							row.amount = flt(row.amount) + difference_amount;
-						} else {
-							frappe.msgprint(__("No gain or loss in the exchange rate"))
-						}
+							if (row) {
+								row.amount = flt(row.amount) + difference_amount;
+							} else {
+								frappe.msgprint(__("No gain or loss in the exchange rate"))
+							}
+							refresh_field("deductions");
+						};
 
-						refresh_field("deductions");
+						if (!r.message[account]) {
+							frappe.prompt({
+								label: __("Please Specify Account"),
+								fieldname: account,
+								fieldtype: "Link",
+								options: "Account",
+								get_query: () => ({
+									filters: {
+										company: frm.doc.company,
+									}
+								})
+							}, (values) => {
+								const details = Object.assign({}, r.message, values);
+								add_deductions(details);
+							}, __(frappe.unscrub(account)));
+						} else {
+							add_deductions(r.message);
+						}
 
 						frm.events.set_unallocated_amount(frm);
 					}
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index c34bddd..3583dc7 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -1594,17 +1594,7 @@
 @frappe.whitelist()
 def get_company_defaults(company):
 	fields = ["write_off_account", "exchange_gain_loss_account", "cost_center"]
-	ret = frappe.get_cached_value("Company", company, fields, as_dict=1)
-
-	for fieldname in fields:
-		if not ret[fieldname]:
-			frappe.throw(
-				_("Please set default {0} in Company {1}").format(
-					frappe.get_meta("Company").get_label(fieldname), company
-				)
-			)
-
-	return ret
+	return frappe.get_cached_value("Company", company, fields, as_dict=1)
 
 
 def get_outstanding_on_journal_entry(name):
@@ -1764,7 +1754,12 @@
 	if doc.doctype == "Purchase Invoice" and doc.invoice_is_blocked():
 		frappe.msgprint(_("{0} is on hold till {1}").format(doc.name, doc.release_date))
 	else:
-		if doc.doctype in ("Sales Invoice", "Purchase Invoice") and frappe.get_cached_value(
+		if doc.doctype in (
+			"Sales Invoice",
+			"Purchase Invoice",
+			"Purchase Order",
+			"Sales Order",
+		) and frappe.get_cached_value(
 			"Payment Terms Template",
 			doc.payment_terms_template,
 			"allocate_payment_based_on_payment_terms",
diff --git a/erpnext/accounts/report/general_ledger/test_general_ledger.py b/erpnext/accounts/report/general_ledger/test_general_ledger.py
index c563785..a8c362e 100644
--- a/erpnext/accounts/report/general_ledger/test_general_ledger.py
+++ b/erpnext/accounts/report/general_ledger/test_general_ledger.py
@@ -24,7 +24,6 @@
 				"root_type": "Asset",
 				"report_type": "Balance Sheet",
 				"account_currency": "USD",
-				"inter_company_account": 0,
 				"parent_account": "Bank Accounts - _TC",
 				"account_type": "Bank",
 				"doctype": "Account",
diff --git a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.js b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.js
index 06989a9..65a4226 100644
--- a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.js
+++ b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.js
@@ -24,7 +24,7 @@
 			"label": __("Period Based On"),
 			"fieldtype": "Select",
 			"options": ["Fiscal Year", "Date Range"],
-			"default": ["Fiscal Year"],
+			"default": "Fiscal Year",
 			"reqd": 1
 		},
 		{
@@ -76,12 +76,6 @@
 			options: "Asset Category"
 		},
 		{
-			fieldname:"finance_book",
-			label: __("Finance Book"),
-			fieldtype: "Link",
-			options: "Finance Book"
-		},
-		{
 			fieldname:"cost_center",
 			label: __("Cost Center"),
 			fieldtype: "Link",
@@ -96,8 +90,20 @@
 			reqd: 1
 		},
 		{
-			fieldname:"is_existing_asset",
-			label: __("Is Existing Asset"),
+			fieldname:"finance_book",
+			label: __("Finance Book"),
+			fieldtype: "Link",
+			options: "Finance Book",
+			depends_on: "eval: doc.only_depreciable_assets == 1",
+		},
+		{
+			fieldname:"only_depreciable_assets",
+			label: __("Only depreciable assets"),
+			fieldtype: "Check"
+		},
+		{
+			fieldname:"only_existing_assets",
+			label: __("Only existing assets"),
 			fieldtype: "Check"
 		},
 	]
diff --git a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py
index 59d43b1..5fbcbe2 100644
--- a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py
+++ b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py
@@ -45,8 +45,10 @@
 		filters.year_end_date = getdate(fiscal_year.year_end_date)
 
 		conditions[date_field] = ["between", [filters.year_start_date, filters.year_end_date]]
-	if filters.get("is_existing_asset"):
-		conditions["is_existing_asset"] = filters.get("is_existing_asset")
+	if filters.get("only_depreciable_assets"):
+		conditions["calculate_depreciation"] = filters.get("only_depreciable_assets")
+	if filters.get("only_existing_assets"):
+		conditions["is_existing_asset"] = filters.get("only_existing_assets")
 	if filters.get("asset_category"):
 		conditions["asset_category"] = filters.get("asset_category")
 	if filters.get("cost_center"):
@@ -102,19 +104,18 @@
 		]
 		assets_record = frappe.db.get_all("Asset", filters=conditions, fields=fields)
 
-	assets_linked_to_fb = frappe.db.get_all(
-		doctype="Asset Finance Book",
-		filters={"finance_book": filters.finance_book or ("is", "not set")},
-		pluck="parent",
-	)
+	assets_linked_to_fb = None
+
+	if filters.only_depreciable_assets:
+		assets_linked_to_fb = frappe.db.get_all(
+			doctype="Asset Finance Book",
+			filters={"finance_book": filters.finance_book or ("is", "not set")},
+			pluck="parent",
+		)
 
 	for asset in assets_record:
-		if filters.finance_book:
-			if asset.asset_id not in assets_linked_to_fb:
-				continue
-		else:
-			if asset.calculate_depreciation and asset.asset_id not in assets_linked_to_fb:
-				continue
+		if assets_linked_to_fb and asset.asset_id not in assets_linked_to_fb:
+			continue
 
 		asset_value = get_asset_value_after_depreciation(asset.asset_id, filters.finance_book)
 		row = {
@@ -172,11 +173,11 @@
 			"datasets": [
 				{
 					"name": _("Asset Value"),
-					"values": [d.get("asset_value") for d in labels_values_map.values()],
+					"values": [flt(d.get("asset_value"), 2) for d in labels_values_map.values()],
 				},
 				{
 					"name": _("Depreciatied Amount"),
-					"values": [d.get("depreciated_amount") for d in labels_values_map.values()],
+					"values": [flt(d.get("depreciated_amount"), 2) for d in labels_values_map.values()],
 				},
 			],
 		},
@@ -312,7 +313,7 @@
 
 	return [
 		{
-			"label": _("Asset Id"),
+			"label": _("Asset ID"),
 			"fieldtype": "Link",
 			"fieldname": "asset_id",
 			"options": "Asset",
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index a347323..c741622 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -273,8 +273,8 @@
 		self.validate_payment_schedule_dates()
 		self.set_due_date()
 		self.set_payment_schedule()
-		self.validate_payment_schedule_amount()
 		if not self.get("ignore_default_payment_terms_template"):
+			self.validate_payment_schedule_amount()
 			self.validate_due_date()
 		self.validate_advance_entries()
 
@@ -515,7 +515,6 @@
 				parent_dict.update({"customer": parent_dict.get("party_name")})
 
 			self.pricing_rules = []
-			basic_item_details_map = {}
 
 			for item in self.get("items"):
 				if item.get("item_code"):
@@ -535,17 +534,7 @@
 					if self.get("is_subcontracted"):
 						args["is_subcontracted"] = self.is_subcontracted
 
-					basic_details = basic_item_details_map.get(item.item_code)
-					ret, basic_item_details = get_item_details(
-						args,
-						self,
-						for_validate=True,
-						overwrite_warehouse=False,
-						return_basic_details=True,
-						basic_details=basic_details,
-					)
-
-					basic_item_details_map.setdefault(item.item_code, basic_item_details)
+					ret = get_item_details(args, self, for_validate=True, overwrite_warehouse=False)
 
 					for fieldname, value in ret.items():
 						if item.meta.get_field(fieldname) and value is not None:
@@ -1618,6 +1607,7 @@
 
 		base_grand_total = self.get("base_rounded_total") or self.base_grand_total
 		grand_total = self.get("rounded_total") or self.grand_total
+		automatically_fetch_payment_terms = 0
 
 		if self.doctype in ("Sales Invoice", "Purchase Invoice"):
 			base_grand_total = base_grand_total - flt(self.base_write_off_amount)
@@ -1663,19 +1653,20 @@
 				)
 				self.append("payment_schedule", data)
 
-		for d in self.get("payment_schedule"):
-			if d.invoice_portion:
-				d.payment_amount = flt(
-					grand_total * flt(d.invoice_portion / 100), d.precision("payment_amount")
-				)
-				d.base_payment_amount = flt(
-					base_grand_total * flt(d.invoice_portion / 100), d.precision("base_payment_amount")
-				)
-				d.outstanding = d.payment_amount
-			elif not d.invoice_portion:
-				d.base_payment_amount = flt(
-					d.payment_amount * self.get("conversion_rate"), d.precision("base_payment_amount")
-				)
+		if not automatically_fetch_payment_terms:
+			for d in self.get("payment_schedule"):
+				if d.invoice_portion:
+					d.payment_amount = flt(
+						grand_total * flt(d.invoice_portion / 100), d.precision("payment_amount")
+					)
+					d.base_payment_amount = flt(
+						base_grand_total * flt(d.invoice_portion / 100), d.precision("base_payment_amount")
+					)
+					d.outstanding = d.payment_amount
+				elif not d.invoice_portion:
+					d.base_payment_amount = flt(
+						d.payment_amount * self.get("conversion_rate"), d.precision("base_payment_amount")
+					)
 
 	def get_order_details(self):
 		if self.doctype == "Sales Invoice":
@@ -1728,6 +1719,10 @@
 				"invoice_portion": schedule.invoice_portion,
 				"mode_of_payment": schedule.mode_of_payment,
 				"description": schedule.description,
+				"payment_amount": schedule.payment_amount,
+				"base_payment_amount": schedule.base_payment_amount,
+				"outstanding": schedule.outstanding,
+				"paid_amount": schedule.paid_amount,
 			}
 
 			if schedule.discount_type == "Percentage":
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 1e4fabe..479fef7 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -859,6 +859,8 @@
 
 def future_sle_exists(args, sl_entries=None):
 	key = (args.voucher_type, args.voucher_no)
+	if not hasattr(frappe.local, "future_sle"):
+		frappe.local.future_sle = {}
 
 	if validate_future_sle_not_exists(args, key, sl_entries):
 		return False
@@ -892,6 +894,9 @@
 	)
 
 	for d in data:
+		if key not in frappe.local.future_sle:
+			frappe.local.future_sle[key] = frappe._dict({})
+
 		frappe.local.future_sle[key][(d.item_code, d.warehouse)] = d.total_row
 
 	return len(data)
@@ -903,6 +908,9 @@
 		item_key = (args.get("item_code"), args.get("warehouse"))
 
 	if not sl_entries and hasattr(frappe.local, "future_sle"):
+		if key not in frappe.local.future_sle:
+			return False
+
 		if not frappe.local.future_sle.get(key) or (
 			item_key and item_key not in frappe.local.future_sle.get(key)
 		):
@@ -910,11 +918,8 @@
 
 
 def get_cached_data(args, key):
-	if not hasattr(frappe.local, "future_sle"):
-		frappe.local.future_sle = {}
-
 	if key not in frappe.local.future_sle:
-		frappe.local.future_sle[key] = frappe._dict({})
+		return False
 
 	if args.get("item_code"):
 		item_key = (args.get("item_code"), args.get("warehouse"))
diff --git a/erpnext/crm/doctype/lead/lead.json b/erpnext/crm/doctype/lead/lead.json
index 077e7fa..0cb8824 100644
--- a/erpnext/crm/doctype/lead/lead.json
+++ b/erpnext/crm/doctype/lead/lead.json
@@ -2,6 +2,7 @@
  "actions": [],
  "allow_events_in_timeline": 1,
  "allow_import": 1,
+ "allow_rename": 1,
  "autoname": "naming_series:",
  "creation": "2022-02-08 13:14:41.083327",
  "doctype": "DocType",
@@ -515,7 +516,7 @@
  "idx": 5,
  "image_field": "image",
  "links": [],
- "modified": "2023-01-24 18:20:05.044791",
+ "modified": "2023-04-14 18:20:05.044791",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "Lead",
@@ -582,4 +583,4 @@
  "states": [],
  "subject_field": "title",
  "title_field": "title"
-}
\ No newline at end of file
+}
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 0bd4d91..1675e2c 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -1920,7 +1920,7 @@
 	}
 
 	prompt_user_for_reference_date(){
-		var me = this;
+		let me = this;
 		frappe.prompt({
 			label: __("Cheque/Reference Date"),
 			fieldname: "reference_date",
@@ -1947,7 +1947,7 @@
 		let has_payment_schedule = this.frm.doc.payment_schedule && this.frm.doc.payment_schedule.length;
 		if(!is_eligible || !has_payment_schedule) return false;
 
-		let has_discount = this.frm.doc.payment_schedule.some(row => row.discount_date);
+		let has_discount = this.frm.doc.payment_schedule.some(row => row.discount);
 		return has_discount;
 	}
 
diff --git a/erpnext/selling/workspace/selling/selling.json b/erpnext/selling/workspace/selling/selling.json
index 45e160d..180a3d7 100644
--- a/erpnext/selling/workspace/selling/selling.json
+++ b/erpnext/selling/workspace/selling/selling.json
@@ -704,7 +704,7 @@
    "type": "Link"
   }
  ],
- "modified": "2022-04-26 13:29:55.087240",
+ "modified": "2023-04-16 13:29:55.087240",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Selling",
diff --git a/erpnext/setup/setup_wizard/data/country_wise_tax.json b/erpnext/setup/setup_wizard/data/country_wise_tax.json
index 5750914..3532d6b 100644
--- a/erpnext/setup/setup_wizard/data/country_wise_tax.json
+++ b/erpnext/setup/setup_wizard/data/country_wise_tax.json
@@ -581,6 +581,11 @@
 						"title": "Bauleistungen nach § 13b UStG",
 						"is_default": 0,
 						"taxes": []
+					},
+					{
+						"title": "Nullsteuersatz nach § 12 Abs. 3 UStG",
+						"is_default": 0,
+						"taxes": []
 					}
 				],
 				"purchase_tax_templates": [
@@ -1339,6 +1344,11 @@
 						"title": "Bauleistungen nach § 13b UStG",
 						"is_default": 0,
 						"taxes": []
+					},
+					{
+						"title": "Nullsteuersatz nach § 12 Abs. 3 UStG",
+						"is_default": 0,
+						"taxes": []
 					}
 				],
 				"purchase_tax_templates": [
@@ -2097,6 +2107,11 @@
 						"title": "Bauleistungen nach § 13b UStG",
 						"is_default": 0,
 						"taxes": []
+					},
+					{
+						"title": "Nullsteuersatz nach § 12 Abs. 3 UStG",
+						"is_default": 0,
+						"taxes": []
 					}
 				],
 				"purchase_tax_templates": [
@@ -2849,6 +2864,11 @@
 						"title": "Bauleistungen nach § 13b UStG",
 						"is_default": 0,
 						"taxes": []
+					},
+					{
+						"title": "Nullsteuersatz nach § 12 Abs. 3 UStG",
+						"is_default": 0,
+						"taxes": []
 					}
 				],
 				"purchase_tax_templates": [
diff --git a/erpnext/stock/doctype/serial_no/serial_no.json b/erpnext/stock/doctype/serial_no/serial_no.json
index 6e1e0d4..7989b1a 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.json
+++ b/erpnext/stock/doctype/serial_no/serial_no.json
@@ -410,10 +410,10 @@
    "fieldtype": "Link",
    "label": "Company",
    "options": "Company",
-   "read_only": 1,
    "remember_last_selected_value": 1,
    "reqd": 1,
-   "search_index": 1
+   "search_index": 1,
+   "set_only_once": 1
   },
   {
    "fieldname": "status",
@@ -433,7 +433,7 @@
  "icon": "fa fa-barcode",
  "idx": 1,
  "links": [],
- "modified": "2021-12-23 10:44:30.299450",
+ "modified": "2023-04-14 15:58:46.139887",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Serial No",
@@ -461,7 +461,6 @@
    "read": 1,
    "report": 1,
    "role": "Stock Manager",
-   "set_user_permissions": 1,
    "write": 1
   },
   {
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
index 482b103..3fd4cec 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
@@ -5,7 +5,7 @@
 
 import frappe
 from frappe import _, bold, msgprint
-from frappe.query_builder.functions import Sum
+from frappe.query_builder.functions import CombineDatetime, Sum
 from frappe.utils import cint, cstr, flt
 
 import erpnext
@@ -571,22 +571,33 @@
 			self._cancel()
 
 	def recalculate_current_qty(self, item_code, batch_no):
+		from erpnext.stock.stock_ledger import get_valuation_rate
+
+		sl_entries = []
 		for row in self.items:
 			if not (row.item_code == item_code and row.batch_no == batch_no):
 				continue
 
-			row.current_qty = get_batch_qty_for_stock_reco(item_code, row.warehouse, batch_no)
+			current_qty = get_batch_qty_for_stock_reco(
+				item_code, row.warehouse, batch_no, self.posting_date, self.posting_time, self.name
+			)
 
-			qty, val_rate = get_stock_balance(
-				item_code,
-				row.warehouse,
-				self.posting_date,
-				self.posting_time,
-				with_valuation_rate=True,
+			precesion = row.precision("current_qty")
+			if flt(current_qty, precesion) == flt(row.current_qty, precesion):
+				continue
+
+			val_rate = get_valuation_rate(
+				item_code, row.warehouse, self.doctype, self.name, company=self.company, batch_no=batch_no
 			)
 
 			row.current_valuation_rate = val_rate
+			if not row.current_qty and current_qty:
+				sle = self.get_sle_for_items(row)
+				sle.actual_qty = current_qty * -1
+				sle.valuation_rate = val_rate
+				sl_entries.append(sle)
 
+			row.current_qty = current_qty
 			row.db_set(
 				{
 					"current_qty": row.current_qty,
@@ -595,8 +606,13 @@
 				}
 			)
 
+		if sl_entries:
+			self.make_sl_entries(sl_entries)
 
-def get_batch_qty_for_stock_reco(item_code, warehouse, batch_no):
+
+def get_batch_qty_for_stock_reco(
+	item_code, warehouse, batch_no, posting_date, posting_time, voucher_no
+):
 	ledger = frappe.qb.DocType("Stock Ledger Entry")
 
 	query = (
@@ -610,6 +626,12 @@
 			& (ledger.docstatus == 1)
 			& (ledger.is_cancelled == 0)
 			& (ledger.batch_no == batch_no)
+			& (ledger.posting_date <= posting_date)
+			& (
+				CombineDatetime(ledger.posting_date, ledger.posting_time)
+				<= CombineDatetime(posting_date, posting_time)
+			)
+			& (ledger.voucher_no != voucher_no)
 		)
 		.groupby(ledger.batch_no)
 	)
diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
index eaea301..7d59441 100644
--- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
@@ -676,6 +676,79 @@
 		self.assertEqual(flt(sl_entry.actual_qty), 1.0)
 		self.assertEqual(flt(sl_entry.qty_after_transaction), 1.0)
 
+	def test_backdated_stock_reco_entry(self):
+		from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
+
+		item_code = self.make_item(
+			"Test New Batch Item ABCV",
+			{
+				"is_stock_item": 1,
+				"has_batch_no": 1,
+				"batch_number_series": "BNS9.####",
+				"create_new_batch": 1,
+			},
+		).name
+
+		warehouse = "_Test Warehouse - _TC"
+
+		# Added 100 Qty, Balace Qty 100
+		se1 = make_stock_entry(
+			item_code=item_code, posting_time="09:00:00", target=warehouse, qty=100, basic_rate=700
+		)
+
+		# Removed 50 Qty, Balace Qty 50
+		se2 = make_stock_entry(
+			item_code=item_code,
+			batch_no=se1.items[0].batch_no,
+			posting_time="10:00:00",
+			source=warehouse,
+			qty=50,
+			basic_rate=700,
+		)
+
+		# Stock Reco for 100, Balace Qty 100
+		stock_reco = create_stock_reconciliation(
+			item_code=item_code,
+			posting_time="11:00:00",
+			warehouse=warehouse,
+			batch_no=se1.items[0].batch_no,
+			qty=100,
+			rate=100,
+		)
+
+		# Removed 50 Qty, Balace Qty 50
+		make_stock_entry(
+			item_code=item_code,
+			batch_no=se1.items[0].batch_no,
+			posting_time="12:00:00",
+			source=warehouse,
+			qty=50,
+			basic_rate=700,
+		)
+
+		self.assertFalse(frappe.db.exists("Repost Item Valuation", {"voucher_no": stock_reco.name}))
+
+		# Cancel the backdated Stock Entry se2,
+		# Since Stock Reco entry in the future the Balace Qty should remain as it's (50)
+
+		se2.cancel()
+
+		self.assertTrue(frappe.db.exists("Repost Item Valuation", {"voucher_no": stock_reco.name}))
+
+		self.assertEqual(
+			frappe.db.get_value("Repost Item Valuation", {"voucher_no": stock_reco.name}, "status"),
+			"Completed",
+		)
+
+		sle = frappe.get_all(
+			"Stock Ledger Entry",
+			filters={"item_code": item_code, "warehouse": warehouse, "is_cancelled": 0},
+			fields=["qty_after_transaction"],
+			order_by="posting_time desc, creation desc",
+		)
+
+		self.assertEqual(flt(sle[0].qty_after_transaction), flt(50.0))
+
 
 def create_batch_item_with_batch(item_name, batch_id):
 	batch_item_doc = create_item(item_name, is_stock_item=1)
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 2cf3797..ce85702 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -35,14 +35,7 @@
 
 
 @frappe.whitelist()
-def get_item_details(
-	args,
-	doc=None,
-	for_validate=False,
-	overwrite_warehouse=True,
-	return_basic_details=False,
-	basic_details=None,
-):
+def get_item_details(args, doc=None, for_validate=False, overwrite_warehouse=True):
 	"""
 	args = {
 	        "item_code": "",
@@ -80,12 +73,7 @@
 		if doc.get("doctype") == "Purchase Invoice":
 			args["bill_date"] = doc.get("bill_date")
 
-	if not basic_details:
-		out = get_basic_details(args, item, overwrite_warehouse)
-	else:
-		out = basic_details
-
-	basic_details = out.copy()
+	out = get_basic_details(args, item, overwrite_warehouse)
 
 	get_item_tax_template(args, item, out)
 	out["item_tax_rate"] = get_item_tax_map(
@@ -154,11 +142,7 @@
 		out.amount = flt(args.qty) * flt(out.rate)
 
 	out = remove_standard_fields(out)
-
-	if return_basic_details:
-		return out, basic_details
-	else:
-		return out
+	return out
 
 
 def remove_standard_fields(details):
diff --git a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js
index 58a043e..752e464 100644
--- a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js
+++ b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js
@@ -11,6 +11,13 @@
 			"options": "Company",
 			"reqd": 1,
 			"default": frappe.defaults.get_user_default("Company")
+		},
+		{
+			"fieldname":"show_disabled_warehouses",
+			"label": __("Show Disabled Warehouses"),
+			"fieldtype": "Check",
+			"default": 0
+
 		}
 	],
 	"initial_depth": 3,
diff --git a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.py b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.py
index d364b57..a0e9944 100644
--- a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.py
+++ b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.py
@@ -11,6 +11,7 @@
 class StockBalanceFilter(TypedDict):
 	company: Optional[str]
 	warehouse: Optional[str]
+	show_disabled_warehouses: Optional[int]
 
 
 SLEntry = Dict[str, Any]
@@ -18,7 +19,7 @@
 
 def execute(filters=None):
 	columns, data = [], []
-	columns = get_columns()
+	columns = get_columns(filters)
 	data = get_data(filters)
 
 	return columns, data
@@ -42,10 +43,14 @@
 
 
 def get_warehouses(report_filters: StockBalanceFilter):
+	filters = {"company": report_filters.company, "disabled": 0}
+	if report_filters.get("show_disabled_warehouses"):
+		filters["disabled"] = ("in", [0, report_filters.show_disabled_warehouses])
+
 	return frappe.get_all(
 		"Warehouse",
-		fields=["name", "parent_warehouse", "is_group"],
-		filters={"company": report_filters.company},
+		fields=["name", "parent_warehouse", "is_group", "disabled"],
+		filters=filters,
 		order_by="lft",
 	)
 
@@ -90,8 +95,8 @@
 		update_balance(warehouse, warehouse.stock_balance)
 
 
-def get_columns():
-	return [
+def get_columns(filters: StockBalanceFilter) -> List[Dict]:
+	columns = [
 		{
 			"label": _("Warehouse"),
 			"fieldname": "name",
@@ -101,3 +106,15 @@
 		},
 		{"label": _("Stock Balance"), "fieldname": "stock_balance", "fieldtype": "Float", "width": 150},
 	]
+
+	if filters.get("show_disabled_warehouses"):
+		columns.append(
+			{
+				"label": _("Warehouse Disabled?"),
+				"fieldname": "disabled",
+				"fieldtype": "Check",
+				"width": 200,
+			}
+		)
+
+	return columns
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index c954bef..b638f08 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -545,6 +545,14 @@
 			self.get_dynamic_incoming_outgoing_rate(sle)
 
 		if (
+			sle.voucher_type == "Stock Reconciliation"
+			and sle.batch_no
+			and sle.voucher_detail_no
+			and sle.actual_qty < 0
+		):
+			self.reset_actual_qty_for_stock_reco(sle)
+
+		if (
 			sle.voucher_type in ["Purchase Receipt", "Purchase Invoice"]
 			and sle.voucher_detail_no
 			and sle.actual_qty < 0
@@ -605,6 +613,16 @@
 		if not self.args.get("sle_id"):
 			self.update_outgoing_rate_on_transaction(sle)
 
+	def reset_actual_qty_for_stock_reco(self, sle):
+		current_qty = frappe.get_cached_value(
+			"Stock Reconciliation Item", sle.voucher_detail_no, "current_qty"
+		)
+
+		if current_qty:
+			sle.actual_qty = current_qty * -1
+		elif current_qty == 0:
+			sle.is_cancelled = 1
+
 	def validate_negative_stock(self, sle):
 		"""
 		validate negative stock for entries current datetime onwards
@@ -1369,12 +1387,8 @@
 
 def regenerate_sle_for_batch_stock_reco(detail):
 	doc = frappe.get_cached_doc("Stock Reconciliation", detail.voucher_no)
-	doc.docstatus = 2
-	doc.update_stock_ledger()
-
 	doc.recalculate_current_qty(detail.item_code, detail.batch_no)
-	doc.docstatus = 1
-	doc.update_stock_ledger()
+	doc.repost_future_sle_and_gle()
 
 
 def get_stock_reco_qty_shift(args):
@@ -1400,34 +1414,52 @@
 	return stock_reco_qty_shift
 
 
-def get_next_stock_reco(args):
+def get_next_stock_reco(kwargs):
 	"""Returns next nearest stock reconciliaton's details."""
 
-	return frappe.db.sql(
-		"""
-		select
-			name, posting_date, posting_time, creation, voucher_no, item_code, batch_no, actual_qty
-		from
-			`tabStock Ledger Entry`
-		where
-			item_code = %(item_code)s
-			and warehouse = %(warehouse)s
-			and voucher_type = 'Stock Reconciliation'
-			and voucher_no != %(voucher_no)s
-			and is_cancelled = 0
-			and (timestamp(posting_date, posting_time) > timestamp(%(posting_date)s, %(posting_time)s)
-				or (
-					timestamp(posting_date, posting_time) = timestamp(%(posting_date)s, %(posting_time)s)
-					and creation > %(creation)s
+	sle = frappe.qb.DocType("Stock Ledger Entry")
+
+	query = (
+		frappe.qb.from_(sle)
+		.select(
+			sle.name,
+			sle.posting_date,
+			sle.posting_time,
+			sle.creation,
+			sle.voucher_no,
+			sle.item_code,
+			sle.batch_no,
+			sle.actual_qty,
+		)
+		.where(
+			(sle.item_code == kwargs.get("item_code"))
+			& (sle.warehouse == kwargs.get("warehouse"))
+			& (sle.voucher_type == "Stock Reconciliation")
+			& (sle.voucher_no != kwargs.get("voucher_no"))
+			& (sle.is_cancelled == 0)
+			& (
+				(
+					CombineDatetime(sle.posting_date, sle.posting_time)
+					> CombineDatetime(kwargs.get("posting_date"), kwargs.get("posting_time"))
+					| (
+						(
+							CombineDatetime(sle.posting_date, sle.posting_time)
+							== CombineDatetime(kwargs.get("posting_date"), kwargs.get("posting_time"))
+						)
+						& (sle.creation > kwargs.get("creation"))
+					)
 				)
 			)
-		order by timestamp(posting_date, posting_time) asc, creation asc
-		limit 1
-	""",
-		args,
-		as_dict=1,
+		)
+		.orderby(CombineDatetime(sle.posting_date, sle.posting_time))
+		.orderby(sle.creation)
 	)
 
+	if kwargs.get("batch_no"):
+		query.where(sle.batch_no == kwargs.get("batch_no"))
+
+	return query.run(as_dict=True)
+
 
 def get_datetime_limit_condition(detail):
 	return f"""