Merge pull request #37194 from GursheenK/editable-purchase-invoice

feat: editable purchase invoice 
diff --git a/erpnext/accounts/doctype/bank_account/bank_account.json b/erpnext/accounts/doctype/bank_account/bank_account.json
index 41d7947..32f1c67 100644
--- a/erpnext/accounts/doctype/bank_account/bank_account.json
+++ b/erpnext/accounts/doctype/bank_account/bank_account.json
@@ -13,6 +13,7 @@
   "account_type",
   "account_subtype",
   "column_break_7",
+  "disabled",
   "is_default",
   "is_company_account",
   "company",
@@ -199,10 +200,16 @@
    "fieldtype": "Data",
    "in_global_search": 1,
    "label": "Branch Code"
+  },
+  {
+   "default": "0",
+   "fieldname": "disabled",
+   "fieldtype": "Check",
+   "label": "Disabled"
   }
  ],
  "links": [],
- "modified": "2022-05-04 15:49:42.620630",
+ "modified": "2023-09-22 21:31:34.763977",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Bank Account",
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index 794a4ef..0203c45 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -154,6 +154,12 @@
 		frm.events.set_dynamic_labels(frm);
 		frm.events.show_general_ledger(frm);
 		erpnext.accounts.ledger_preview.show_accounting_ledger_preview(frm);
+		if(frm.doc.references.find((elem) => {return elem.exchange_gain_loss != 0})) {
+			frm.add_custom_button(__("View Exchange Gain/Loss Journals"), function() {
+				frappe.set_route("List", "Journal Entry", {"voucher_type": "Exchange Gain Or Loss", "reference_name": frm.doc.name});
+			}, __('Actions'));
+
+		}
 		erpnext.accounts.unreconcile_payments.add_unreconcile_btn(frm);
 	},
 
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index b16b03e..38a5209 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -1152,8 +1152,25 @@
 					)
 
 				make_reverse_gl_entries(gl_entries=gl_entries, partial_cancel=True)
-			else:
-				make_gl_entries(gl_entries)
+				return
+
+			# same reference added to payment entry
+			for gl_entry in gl_entries.copy():
+				if frappe.db.exists(
+					"GL Entry",
+					{
+						"account": gl_entry.account,
+						"voucher_type": gl_entry.voucher_type,
+						"voucher_no": gl_entry.voucher_no,
+						"voucher_detail_no": gl_entry.voucher_detail_no,
+						"debit": gl_entry.debit,
+						"credit": gl_entry.credit,
+						"is_cancelled": 0,
+					},
+				):
+					gl_entries.remove(gl_entry)
+
+			make_gl_entries(gl_entries)
 
 	def make_invoice_liability_entry(self, gl_entries, invoice):
 		args_dict = {
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.json b/erpnext/accounts/doctype/payment_request/payment_request.json
index 381f3fb..5ffd718 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.json
+++ b/erpnext/accounts/doctype/payment_request/payment_request.json
@@ -231,6 +231,28 @@
    "label": "SWIFT Number"
   },
   {
+   "collapsible": 1,
+   "fieldname": "accounting_dimensions_section",
+   "fieldtype": "Section Break",
+   "label": "Accounting Dimensions"
+  },
+  {
+   "fieldname": "cost_center",
+   "fieldtype": "Link",
+   "label": "Cost Center",
+   "options": "Cost Center"
+  },
+  {
+   "fieldname": "dimension_col_break",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "project",
+   "fieldtype": "Link",
+   "label": "Project",
+   "options": "Project"
+  },
+  {
    "depends_on": "eval: doc.payment_request_type == 'Inward'",
    "fieldname": "recipient_and_message",
    "fieldtype": "Section Break",
@@ -246,7 +268,8 @@
    "fieldname": "email_to",
    "fieldtype": "Data",
    "in_global_search": 1,
-   "label": "To"
+   "label": "To",
+   "options": "Email"
   },
   {
    "depends_on": "eval: doc.payment_channel != \"Phone\"",
@@ -317,9 +340,10 @@
   },
   {
    "fieldname": "payment_url",
-   "fieldtype": "Small Text",
    "hidden": 1,
-   "label": "payment_url",
+   "fieldtype": "Data",
+   "length": 500,
+   "options": "URL",
    "read_only": 1
   },
   {
@@ -344,6 +368,14 @@
    "read_only": 1
   },
   {
+   "fetch_from": "payment_gateway_account.payment_channel",
+   "fieldname": "payment_channel",
+   "fieldtype": "Select",
+   "label": "Payment Channel",
+   "options": "\nEmail\nPhone",
+   "read_only": 1
+  },
+  {
    "fieldname": "payment_order",
    "fieldtype": "Link",
    "label": "Payment Order",
@@ -358,43 +390,13 @@
    "options": "Payment Request",
    "print_hide": 1,
    "read_only": 1
-  },
-  {
-   "fetch_from": "payment_gateway_account.payment_channel",
-   "fieldname": "payment_channel",
-   "fieldtype": "Select",
-   "label": "Payment Channel",
-   "options": "\nEmail\nPhone",
-   "read_only": 1
-  },
-  {
-   "collapsible": 1,
-   "fieldname": "accounting_dimensions_section",
-   "fieldtype": "Section Break",
-   "label": "Accounting Dimensions"
-  },
-  {
-   "fieldname": "cost_center",
-   "fieldtype": "Link",
-   "label": "Cost Center",
-   "options": "Cost Center"
-  },
-  {
-   "fieldname": "dimension_col_break",
-   "fieldtype": "Column Break"
-  },
-  {
-   "fieldname": "project",
-   "fieldtype": "Link",
-   "label": "Project",
-   "options": "Project"
   }
  ],
  "in_create": 1,
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2022-12-21 16:56:40.115737",
+ "modified": "2023-09-16 14:15:02.510890",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Payment Request",
diff --git a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py
index af1c066..d984d86 100644
--- a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py
+++ b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py
@@ -33,7 +33,7 @@
 	def on_cancel(self):
 		self.validate_future_closing_vouchers()
 		self.db_set("gle_processing_status", "In Progress")
-		self.ignore_linked_doctypes = ("GL Entry", "Stock Ledger Entry")
+		self.ignore_linked_doctypes = ("GL Entry", "Stock Ledger Entry", "Payment Ledger Entry")
 		gle_count = frappe.db.count(
 			"GL Entry",
 			{"voucher_type": "Period Closing Voucher", "voucher_no": self.name, "is_cancelled": 0},
diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
index 842f159..e36e97b 100644
--- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
+++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
@@ -414,7 +414,7 @@
 				selling_price_list = (
 					customer_price_list or customer_group_price_list or profile.get("selling_price_list")
 				)
-				if customer_currency != profile.get("currency"):
+				if customer_currency and customer_currency != profile.get("currency"):
 					self.set("currency", customer_currency)
 
 			else:
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
index 7863103..9a5ad35 100644
--- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
@@ -65,6 +65,7 @@
 		filters = get_common_filters(doc)
 
 		if doc.report == "General Ledger":
+			filters.update(get_gl_filters(doc, entry, tax_id, presentation_currency))
 			col, res = get_soa(filters)
 			for x in [0, -2, -1]:
 				res[x]["account"] = res[x]["account"].replace("'", "")
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 9ffdaf6..84b0149 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -1801,6 +1801,10 @@
 		)
 
 	def test_outstanding_amount_after_advance_payment_entry_cancellation(self):
+		"""Test impact of advance PE submission/cancellation on SI and SO."""
+		from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
+
+		sales_order = make_sales_order(item_code="138-CMS Shoe", qty=1, price_list_rate=500)
 		pe = frappe.get_doc(
 			{
 				"doctype": "Payment Entry",
@@ -1820,10 +1824,25 @@
 				"paid_to": "_Test Cash - _TC",
 			}
 		)
+		pe.append(
+			"references",
+			{
+				"reference_doctype": "Sales Order",
+				"reference_name": sales_order.name,
+				"total_amount": sales_order.grand_total,
+				"outstanding_amount": sales_order.grand_total,
+				"allocated_amount": 300,
+			},
+		)
 		pe.insert()
 		pe.submit()
 
+		sales_order.reload()
+		self.assertEqual(sales_order.advance_paid, 300)
+
 		si = frappe.copy_doc(test_records[0])
+		si.items[0].sales_order = sales_order.name
+		si.items[0].so_detail = sales_order.get("items")[0].name
 		si.is_pos = 0
 		si.append(
 			"advances",
@@ -1831,6 +1850,7 @@
 				"doctype": "Sales Invoice Advance",
 				"reference_type": "Payment Entry",
 				"reference_name": pe.name,
+				"reference_row": pe.references[0].name,
 				"advance_amount": 300,
 				"allocated_amount": 300,
 				"remarks": pe.remarks,
@@ -1839,7 +1859,13 @@
 		si.insert()
 		si.submit()
 
-		si.load_from_db()
+		si.reload()
+		pe.reload()
+		sales_order.reload()
+
+		# Check if SO is unlinked/replaced by SI in PE & if SO advance paid is 0
+		self.assertEqual(pe.references[0].reference_name, si.name)
+		self.assertEqual(sales_order.advance_paid, 0.0)
 
 		# check outstanding after advance allocation
 		self.assertEqual(
@@ -1847,11 +1873,9 @@
 			flt(si.rounded_total - si.total_advance, si.precision("outstanding_amount")),
 		)
 
-		# added to avoid Document has been modified exception
-		pe = frappe.get_doc("Payment Entry", pe.name)
 		pe.cancel()
+		si.reload()
 
-		si.load_from_db()
 		# check outstanding after advance cancellation
 		self.assertEqual(
 			flt(si.outstanding_amount),
diff --git a/erpnext/accounts/report/trial_balance/trial_balance.js b/erpnext/accounts/report/trial_balance/trial_balance.js
index ee6b4fe..c12ab0f 100644
--- a/erpnext/accounts/report/trial_balance/trial_balance.js
+++ b/erpnext/accounts/report/trial_balance/trial_balance.js
@@ -99,6 +99,12 @@
 				"label": __("Include Default Book Entries"),
 				"fieldtype": "Check",
 				"default": 1
+			},
+			{
+				"fieldname": "show_net_values",
+				"label": __("Show net values in opening and closing columns"),
+				"fieldtype": "Check",
+				"default": 1
 			}
 		],
 		"formatter": erpnext.financial_statements.formatter,
diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py
index 376571f..2a8aa0c 100644
--- a/erpnext/accounts/report/trial_balance/trial_balance.py
+++ b/erpnext/accounts/report/trial_balance/trial_balance.py
@@ -120,7 +120,9 @@
 		ignore_opening_entries=True,
 	)
 
-	calculate_values(accounts, gl_entries_by_account, opening_balances)
+	calculate_values(
+		accounts, gl_entries_by_account, opening_balances, filters.get("show_net_values")
+	)
 	accumulate_values_into_parents(accounts, accounts_by_name)
 
 	data = prepare_data(accounts, filters, parent_children_map, company_currency)
@@ -310,7 +312,7 @@
 	return gle
 
 
-def calculate_values(accounts, gl_entries_by_account, opening_balances):
+def calculate_values(accounts, gl_entries_by_account, opening_balances, show_net_values):
 	init = {
 		"opening_debit": 0.0,
 		"opening_credit": 0.0,
@@ -335,7 +337,8 @@
 		d["closing_debit"] = d["opening_debit"] + d["debit"]
 		d["closing_credit"] = d["opening_credit"] + d["credit"]
 
-		prepare_opening_closing(d)
+		if show_net_values:
+			prepare_opening_closing(d)
 
 
 def calculate_total_row(accounts, company_currency):
@@ -375,7 +378,7 @@
 
 	for d in accounts:
 		# Prepare opening closing for group account
-		if parent_children_map.get(d.account):
+		if parent_children_map.get(d.account) and filters.get("show_net_values"):
 			prepare_opening_closing(d)
 
 		has_value = False
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 1360f73..555ed4f 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -581,6 +581,10 @@
 	"""
 	jv_detail = journal_entry.get("accounts", {"name": d["voucher_detail_no"]})[0]
 
+	# Update Advance Paid in SO/PO since they might be getting unlinked
+	if jv_detail.get("reference_type") in ("Sales Order", "Purchase Order"):
+		frappe.get_doc(jv_detail.reference_type, jv_detail.reference_name).set_total_advance_paid()
+
 	if flt(d["unadjusted_amount"]) - flt(d["allocated_amount"]) != 0:
 		# adjust the unreconciled balance
 		amount_in_account_currency = flt(d["unadjusted_amount"]) - flt(d["allocated_amount"])
@@ -647,6 +651,13 @@
 
 	if d.voucher_detail_no:
 		existing_row = payment_entry.get("references", {"name": d["voucher_detail_no"]})[0]
+
+		# Update Advance Paid in SO/PO since they are getting unlinked
+		if existing_row.get("reference_doctype") in ("Sales Order", "Purchase Order"):
+			frappe.get_doc(
+				existing_row.reference_doctype, existing_row.reference_name
+			).set_total_advance_paid()
+
 		original_row = existing_row.as_dict().copy()
 		existing_row.update(reference_details)
 
diff --git a/erpnext/buying/doctype/supplier/supplier.json b/erpnext/buying/doctype/supplier/supplier.json
index a07af71..19972ca 100644
--- a/erpnext/buying/doctype/supplier/supplier.json
+++ b/erpnext/buying/doctype/supplier/supplier.json
@@ -45,12 +45,13 @@
   "column_break1",
   "contact_html",
   "primary_address_and_contact_detail_section",
-  "supplier_primary_contact",
-  "mobile_no",
-  "email_id",
   "column_break_44",
   "supplier_primary_address",
   "primary_address",
+  "column_break_mglr",
+  "supplier_primary_contact",
+  "mobile_no",
+  "email_id",
   "accounting_tab",
   "payment_terms",
   "default_accounts_section",
@@ -469,6 +470,10 @@
   {
    "fieldname": "column_break_1mqv",
    "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "column_break_mglr",
+   "fieldtype": "Column Break"
   }
  ],
  "icon": "fa fa-user",
@@ -481,7 +486,7 @@
    "link_fieldname": "party"
   }
  ],
- "modified": "2023-06-26 14:20:00.961554",
+ "modified": "2023-09-21 12:24:20.398889",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Supplier",
diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py
index a66b549..e9aed1a 100644
--- a/erpnext/projects/doctype/project/project.py
+++ b/erpnext/projects/doctype/project/project.py
@@ -70,6 +70,7 @@
 				tmp_task_details.append(template_task_details)
 				task = self.create_task_from_template(template_task_details)
 				project_tasks.append(task)
+
 			self.dependency_mapping(tmp_task_details, project_tasks)
 
 	def create_task_from_template(self, task_details):
@@ -108,36 +109,28 @@
 
 	def dependency_mapping(self, template_tasks, project_tasks):
 		for project_task in project_tasks:
-			if project_task.get("template_task"):
-				template_task = frappe.get_doc("Task", project_task.template_task)
-			else:
-				template_task = list(filter(lambda x: x.subject == project_task.subject, template_tasks))[0]
-				template_task = frappe.get_doc("Task", template_task.name)
+			template_task = frappe.get_doc("Task", project_task.template_task)
 
 			self.check_depends_on_value(template_task, project_task, project_tasks)
 			self.check_for_parent_tasks(template_task, project_task, project_tasks)
 
 	def check_depends_on_value(self, template_task, project_task, project_tasks):
 		if template_task.get("depends_on") and not project_task.get("depends_on"):
+			project_template_map = {pt.template_task: pt for pt in project_tasks}
+
 			for child_task in template_task.get("depends_on"):
-				child_task_subject = frappe.db.get_value("Task", child_task.task, "subject")
-				corresponding_project_task = list(
-					filter(lambda x: x.subject == child_task_subject, project_tasks)
-				)
-				if len(corresponding_project_task):
+				if project_template_map and project_template_map.get(child_task.task):
 					project_task.reload()  # reload, as it might have been updated in the previous iteration
-					project_task.append("depends_on", {"task": corresponding_project_task[0].name})
+					project_task.append("depends_on", {"task": project_template_map.get(child_task.task).name})
 					project_task.save()
 
 	def check_for_parent_tasks(self, template_task, project_task, project_tasks):
 		if template_task.get("parent_task") and not project_task.get("parent_task"):
-			parent_task_subject = frappe.db.get_value("Task", template_task.get("parent_task"), "subject")
-			corresponding_project_task = list(
-				filter(lambda x: x.subject == parent_task_subject, project_tasks)
-			)
-			if len(corresponding_project_task):
-				project_task.parent_task = corresponding_project_task[0].name
-				project_task.save()
+			for pt in project_tasks:
+				if pt.template_task == template_task.parent_task:
+					project_task.parent_task = pt.name
+					project_task.save()
+					break
 
 	def is_row_updated(self, row, existing_task_data, fields):
 		if self.get("__islocal") or not existing_task_data:
diff --git a/erpnext/public/js/utils/unreconcile.js b/erpnext/public/js/utils/unreconcile.js
index bbdd51d..fa00ed2 100644
--- a/erpnext/public/js/utils/unreconcile.js
+++ b/erpnext/public/js/utils/unreconcile.js
@@ -17,7 +17,7 @@
 				},
 				callback: function(r) {
 					if (r.message) {
-						frm.add_custom_button(__("Un-Reconcile"), function() {
+						frm.add_custom_button(__("UnReconcile"), function() {
 							erpnext.accounts.unreconcile_payments.build_unreconcile_dialog(frm);
 						}, __('Actions'));
 					}
@@ -87,11 +87,11 @@
 						unreconcile_dialog_fields[0].get_data = function(){ return r.message};
 
 						let d = new frappe.ui.Dialog({
-							title: 'Un-Reconcile Allocations',
+							title: 'UnReconcile Allocations',
 							fields: unreconcile_dialog_fields,
 							size: 'large',
 							cannot_add_rows: true,
-							primary_action_label: 'Un-Reconcile',
+							primary_action_label: 'UnReconcile',
 							primary_action(values) {
 
 								let selected_allocations = values.allocations.filter(x=>x.__checked);
diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json
index be8f62f..0f42def 100644
--- a/erpnext/selling/doctype/customer/customer.json
+++ b/erpnext/selling/doctype/customer/customer.json
@@ -48,12 +48,13 @@
   "column_break1",
   "contact_html",
   "primary_address_and_contact_detail",
-  "customer_primary_contact",
-  "mobile_no",
-  "email_id",
   "column_break_26",
   "customer_primary_address",
   "primary_address",
+  "column_break_nwor",
+  "customer_primary_contact",
+  "mobile_no",
+  "email_id",
   "tax_tab",
   "taxation_section",
   "tax_id",
@@ -339,12 +340,12 @@
    "label": "Default Accounts"
   },
   {
-    "description": "Mention if non-standard Receivable account",
-    "fieldname": "accounts",
-    "fieldtype": "Table",
-    "label": "Accounts",
-    "options": "Party Account"
-   },
+   "description": "Mention if non-standard Receivable account",
+   "fieldname": "accounts",
+   "fieldtype": "Table",
+   "label": "Accounts",
+   "options": "Party Account"
+  },
   {
    "fieldname": "credit_limit_section",
    "fieldtype": "Section Break",
@@ -568,6 +569,10 @@
    "fieldtype": "Table",
    "label": "Customer Portal Users",
    "options": "Portal User"
+  },
+  {
+   "fieldname": "column_break_nwor",
+   "fieldtype": "Column Break"
   }
  ],
  "icon": "fa fa-user",
@@ -581,7 +586,7 @@
    "link_fieldname": "party"
   }
  ],
- "modified": "2023-06-22 13:21:10.678382",
+ "modified": "2023-09-21 12:23:20.706020",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Customer",
diff --git a/erpnext/setup/setup_wizard/data/country_wise_tax.json b/erpnext/setup/setup_wizard/data/country_wise_tax.json
index 3532d6b..a746ebe 100644
--- a/erpnext/setup/setup_wizard/data/country_wise_tax.json
+++ b/erpnext/setup/setup_wizard/data/country_wise_tax.json
@@ -157,9 +157,14 @@
 	},
 
 	"Botswana": {
-		"Botswana Tax": {
+		"Botswana Tax 14%": {
 			"account_name": "VAT",
-			"tax_rate": 12.00
+			"tax_rate": 14.00
+		},
+		"Botswana Tax 12%": {
+			"account_name": "VAT",
+			"tax_rate": 12.00,
+			"default": 1
 		}
 	},
 
diff --git a/erpnext/stock/dashboard/item_dashboard.py b/erpnext/stock/dashboard/item_dashboard.py
index 5a8d84a..e638268 100644
--- a/erpnext/stock/dashboard/item_dashboard.py
+++ b/erpnext/stock/dashboard/item_dashboard.py
@@ -3,7 +3,7 @@
 from frappe.utils import cint, flt
 
 from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import (
-	get_sre_reserved_qty_for_item_and_warehouse as get_reserved_stock,
+	get_sre_reserved_qty_for_items_and_warehouses as get_reserved_stock_details,
 )
 
 
@@ -61,7 +61,10 @@
 		limit_page_length=21,
 	)
 
-	sre_reserved_stock_details = get_reserved_stock(item_code, warehouse)
+	item_code_list = [item_code] if item_code else [i.item_code for i in items]
+	warehouse_list = [warehouse] if warehouse else [i.warehouse for i in items]
+
+	sre_reserved_stock_details = get_reserved_stock_details(item_code_list, warehouse_list)
 	precision = cint(frappe.db.get_single_value("System Settings", "float_precision"))
 
 	for item in items:
@@ -75,7 +78,8 @@
 				"reserved_qty_for_production": flt(item.reserved_qty_for_production, precision),
 				"reserved_qty_for_sub_contract": flt(item.reserved_qty_for_sub_contract, precision),
 				"actual_qty": flt(item.actual_qty, precision),
-				"reserved_stock": sre_reserved_stock_details,
+				"reserved_stock": flt(sre_reserved_stock_details.get((item.item_code, item.warehouse))),
 			}
 		)
+
 	return items
diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js
index 989bfd0..bf3301f 100644
--- a/erpnext/stock/doctype/material_request/material_request.js
+++ b/erpnext/stock/doctype/material_request/material_request.js
@@ -218,7 +218,8 @@
 					plc_conversion_rate: 1,
 					rate: item.rate,
 					uom: item.uom,
-					conversion_factor: item.conversion_factor
+					conversion_factor: item.conversion_factor,
+					project: item.project,
 				},
 				overwrite_warehouse: overwrite_warehouse
 			},
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
index 26ca012..e36d576 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
@@ -346,7 +346,7 @@
 		"""Raises an exception if there is any reserved stock for the items in the Stock Reconciliation."""
 
 		from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import (
-			get_sre_reserved_qty_for_item_and_warehouse as get_sre_reserved_qty_details,
+			get_sre_reserved_qty_for_items_and_warehouses as get_sre_reserved_qty_details,
 		)
 
 		item_code_list, warehouse_list = [], []
diff --git a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.js b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.js
index 4d96636..c5df319 100644
--- a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.js
+++ b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.js
@@ -1,42 +1,42 @@
 // Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
 // For license information, please see license.txt
 
-frappe.ui.form.on("Stock Reservation Entry", {
+frappe.ui.form.on('Stock Reservation Entry', {
 	refresh(frm) {
-		frm.trigger("set_queries");
-		frm.trigger("toggle_read_only_fields");
-		frm.trigger("hide_rate_related_fields");
-		frm.trigger("hide_primary_action_button");
-		frm.trigger("make_sb_entries_warehouse_read_only");
+		frm.trigger('set_queries');
+		frm.trigger('toggle_read_only_fields');
+		frm.trigger('hide_rate_related_fields');
+		frm.trigger('hide_primary_action_button');
+		frm.trigger('make_sb_entries_warehouse_read_only');
 	},
 
 	has_serial_no(frm) {
-		frm.trigger("toggle_read_only_fields");
+		frm.trigger('toggle_read_only_fields');
 	},
 
 	has_batch_no(frm) {
-		frm.trigger("toggle_read_only_fields");
+		frm.trigger('toggle_read_only_fields');
 	},
 
 	warehouse(frm) {
 		if (frm.doc.warehouse) {
 			frm.doc.sb_entries.forEach((row) => {
-				frappe.model.set_value(row.doctype, row.name, "warehouse", frm.doc.warehouse);
+				frappe.model.set_value(row.doctype, row.name, 'warehouse', frm.doc.warehouse);
 			});
 		}
 	},
 
 	set_queries(frm) {
-		frm.set_query("warehouse", () => {
+		frm.set_query('warehouse', () => {
 			return {
 				filters: {
-					"is_group": 0,
-					"company": frm.doc.company,
+					'is_group': 0,
+					'company': frm.doc.company,
 				}
 			};
 		});
 
-		frm.set_query("serial_no", "sb_entries", function(doc, cdt, cdn) {
+		frm.set_query('serial_no', 'sb_entries', function(doc, cdt, cdn) {
 			var selected_serial_nos = doc.sb_entries.map(row => {
 				return row.serial_no;
 			});
@@ -45,16 +45,16 @@
 				filters: {
 					item_code: doc.item_code,
 					warehouse: row.warehouse,
-					status: "Active",
-					name: ["not in", selected_serial_nos],
+					status: 'Active',
+					name: ['not in', selected_serial_nos],
 				}
 			}
 		});
 
-		frm.set_query("batch_no", "sb_entries", function(doc, cdt, cdn) {
+		frm.set_query('batch_no', 'sb_entries', function(doc, cdt, cdn) {
 			let filters = {
 				item: doc.item_code,
-				batch_qty: [">", 0],
+				batch_qty: ['>', 0],
 				disabled: 0,
 			}
 
@@ -63,7 +63,7 @@
 					return row.batch_no;
 				});
 
-				filters.name = ["not in", selected_batch_nos];
+				filters.name = ['not in', selected_batch_nos];
 			}
 
 			return { filters: filters }
@@ -74,37 +74,37 @@
 		if (frm.doc.has_serial_no) {
 			frm.doc.sb_entries.forEach(row => {
 				if (row.qty !== 1) {
-					frappe.model.set_value(row.doctype, row.name, "qty", 1);
+					frappe.model.set_value(row.doctype, row.name, 'qty', 1);
 				}
 			})
 		}
 
 		frm.fields_dict.sb_entries.grid.update_docfield_property(
-			"serial_no", "read_only", !frm.doc.has_serial_no
+			'serial_no', 'read_only', !frm.doc.has_serial_no
 		);
 
 		frm.fields_dict.sb_entries.grid.update_docfield_property(
-			"batch_no", "read_only", !frm.doc.has_batch_no
+			'batch_no', 'read_only', !frm.doc.has_batch_no
 		);
 
 		// Qty will always be 1 for Serial No.
 		frm.fields_dict.sb_entries.grid.update_docfield_property(
-			"qty", "read_only", frm.doc.has_serial_no
+			'qty', 'read_only', frm.doc.has_serial_no
 		);
 
-		frm.set_df_property("sb_entries", "allow_on_submit", frm.doc.against_pick_list ? 0 : 1);
+		frm.set_df_property('sb_entries', 'allow_on_submit', frm.doc.against_pick_list ? 0 : 1);
 	},
 
 	hide_rate_related_fields(frm) {
-		["incoming_rate", "outgoing_rate", "stock_value_difference", "is_outward", "stock_queue"].forEach(field => {
+		['incoming_rate', 'outgoing_rate', 'stock_value_difference', 'is_outward', 'stock_queue'].forEach(field => {
 			frm.fields_dict.sb_entries.grid.update_docfield_property(
-				field, "hidden", 1
+				field, 'hidden', 1
 			);
 		});
 	},
 
 	hide_primary_action_button(frm) {
-		// Hide "Amend" button on cancelled document
+		// Hide 'Amend' button on cancelled document
 		if (frm.doc.docstatus == 2) {
 			frm.page.btn_primary.hide()
 		}
@@ -112,15 +112,15 @@
 
 	make_sb_entries_warehouse_read_only(frm) {
 		frm.fields_dict.sb_entries.grid.update_docfield_property(
-			"warehouse", "read_only", 1
+			'warehouse', 'read_only', 1
 		);
 	},
 });
 
-frappe.ui.form.on("Serial and Batch Entry", {
+frappe.ui.form.on('Serial and Batch Entry', {
 	sb_entries_add(frm, cdt, cdn) {
 		if (frm.doc.warehouse) {
-			frappe.model.set_value(cdt, cdn, "warehouse", frm.doc.warehouse);
+			frappe.model.set_value(cdt, cdn, 'warehouse', frm.doc.warehouse);
 		}
 	},
 });
\ No newline at end of file
diff --git a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py
index bd7bb66..936be3f 100644
--- a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py
+++ b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py
@@ -14,7 +14,7 @@
 
 		self.validate_amended_doc()
 		self.validate_mandatory()
-		self.validate_for_group_warehouse()
+		self.validate_group_warehouse()
 		validate_disabled_warehouse(self.warehouse)
 		validate_warehouse_company(self.warehouse, self.company)
 		self.validate_uom_is_integer()
@@ -74,7 +74,7 @@
 				msg = _("{0} is required").format(self.meta.get_label(d))
 				frappe.throw(msg)
 
-	def validate_for_group_warehouse(self) -> None:
+	def validate_group_warehouse(self) -> None:
 		"""Raises an exception if `Warehouse` is a Group Warehouse."""
 
 		if frappe.get_cached_value("Warehouse", self.warehouse, "is_group"):
@@ -544,10 +544,36 @@
 	return available_serial_nos_list
 
 
-def get_sre_reserved_qty_for_item_and_warehouse(
-	item_code: str | list, warehouse: str | list = None
-) -> float | dict:
-	"""Returns `Reserved Qty` for Item and Warehouse combination OR a dict like {("item_code", "warehouse"): "reserved_qty", ... }."""
+def get_sre_reserved_qty_for_item_and_warehouse(item_code: str, warehouse: str = None) -> float:
+	"""Returns current `Reserved Qty` for Item and Warehouse combination."""
+
+	sre = frappe.qb.DocType("Stock Reservation Entry")
+	query = (
+		frappe.qb.from_(sre)
+		.select(Sum(sre.reserved_qty - sre.delivered_qty).as_("reserved_qty"))
+		.where(
+			(sre.docstatus == 1)
+			& (sre.item_code == item_code)
+			& (sre.status.notin(["Delivered", "Cancelled"]))
+		)
+		.groupby(sre.item_code, sre.warehouse)
+	)
+
+	if warehouse:
+		query = query.where(sre.warehouse == warehouse)
+
+	reserved_qty = query.run(as_list=True)
+
+	return flt(reserved_qty[0][0]) if reserved_qty else 0.0
+
+
+def get_sre_reserved_qty_for_items_and_warehouses(
+	item_code_list: list, warehouse_list: list = None
+) -> dict:
+	"""Returns a dict like {("item_code", "warehouse"): "reserved_qty", ... }."""
+
+	if not item_code_list:
+		return {}
 
 	sre = frappe.qb.DocType("Stock Reservation Entry")
 	query = (
@@ -557,29 +583,20 @@
 			sre.warehouse,
 			Sum(sre.reserved_qty - sre.delivered_qty).as_("reserved_qty"),
 		)
-		.where((sre.docstatus == 1) & (sre.status.notin(["Delivered", "Cancelled"])))
+		.where(
+			(sre.docstatus == 1)
+			& sre.item_code.isin(item_code_list)
+			& (sre.status.notin(["Delivered", "Cancelled"]))
+		)
 		.groupby(sre.item_code, sre.warehouse)
 	)
 
-	query = (
-		query.where(sre.item_code.isin(item_code))
-		if isinstance(item_code, list)
-		else query.where(sre.item_code == item_code)
-	)
-
-	if warehouse:
-		query = (
-			query.where(sre.warehouse.isin(warehouse))
-			if isinstance(warehouse, list)
-			else query.where(sre.warehouse == warehouse)
-		)
+	if warehouse_list:
+		query = query.where(sre.warehouse.isin(warehouse_list))
 
 	data = query.run(as_dict=True)
 
-	if isinstance(item_code, str) and isinstance(warehouse, str):
-		return data[0]["reserved_qty"] if data else 0.0
-	else:
-		return {(d["item_code"], d["warehouse"]): d["reserved_qty"] for d in data} if data else {}
+	return {(d["item_code"], d["warehouse"]): d["reserved_qty"] for d in data} if data else {}
 
 
 def get_sre_reserved_qty_details_for_voucher(voucher_type: str, voucher_no: str) -> dict:
@@ -711,7 +728,7 @@
 	).run(as_dict=True)
 
 
-def get_ssb_bundle_for_voucher(sre: dict) -> object | None:
+def get_ssb_bundle_for_voucher(sre: dict) -> object:
 	"""Returns a new `Serial and Batch Bundle` against the provided SRE."""
 
 	sb_entries = get_serial_batch_entries_for_voucher(sre["name"])
diff --git a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry_list.js b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry_list.js
index 442ac39..5b390f7 100644
--- a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry_list.js
+++ b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry_list.js
@@ -4,13 +4,14 @@
 frappe.listview_settings['Stock Reservation Entry'] = {
 	get_indicator: function (doc) {
 		const status_colors = {
-            'Draft': 'red',
-            'Partially Reserved': 'orange',
-            'Reserved': 'blue',
-            'Partially Delivered': 'purple',
-            'Delivered': 'green',
-            'Cancelled': 'red',
+                  'Draft': 'red',
+                  'Partially Reserved': 'orange',
+                  'Reserved': 'blue',
+                  'Partially Delivered': 'purple',
+                  'Delivered': 'green',
+                  'Cancelled': 'red',
 		};
-		return [__(doc.status), status_colors[doc.status], 'status,=,' + doc.status];
+
+            return [__(doc.status), status_colors[doc.status], 'status,=,' + doc.status];
 	},
 };
\ No newline at end of file
diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py
index 337b0ea..a59f9de 100644
--- a/erpnext/stock/report/stock_balance/stock_balance.py
+++ b/erpnext/stock/report/stock_balance/stock_balance.py
@@ -165,7 +165,7 @@
 
 	def get_sre_reserved_qty_details(self) -> dict:
 		from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import (
-			get_sre_reserved_qty_for_item_and_warehouse as get_reserved_qty_details,
+			get_sre_reserved_qty_for_items_and_warehouses as get_reserved_qty_details,
 		)
 
 		item_code_list, warehouse_list = [], []
diff --git a/erpnext/stock/report/stock_ledger_variance/__init__.py b/erpnext/stock/report/stock_ledger_variance/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/stock/report/stock_ledger_variance/__init__.py
diff --git a/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.js b/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.js
new file mode 100644
index 0000000..b1e4a74
--- /dev/null
+++ b/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.js
@@ -0,0 +1,101 @@
+// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+const DIFFERENCE_FIELD_NAMES = [
+	"difference_in_qty",
+	"fifo_qty_diff",
+	"fifo_value_diff",
+	"fifo_valuation_diff",
+	"valuation_diff",
+	"fifo_difference_diff",
+	"diff_value_diff"
+];
+
+frappe.query_reports["Stock Ledger Variance"] = {
+	"filters": [
+		{
+			"fieldname": "item_code",
+			"fieldtype": "Link",
+			"label": "Item",
+			"options": "Item",
+			get_query: function() {
+				return {
+					filters: {is_stock_item: 1, has_serial_no: 0}
+				}
+			}
+		},
+		{
+			"fieldname": "warehouse",
+			"fieldtype": "Link",
+			"label": "Warehouse",
+			"options": "Warehouse",
+			get_query: function() {
+				return {
+					filters: {is_group: 0, disabled: 0}
+				}
+			}
+		},
+		{
+			"fieldname": "difference_in",
+			"fieldtype": "Select",
+			"label": "Difference In",
+			"options": [
+				"",
+				"Qty",
+				"Value",
+				"Valuation",
+			],
+		},
+		{
+			"fieldname": "include_disabled",
+			"fieldtype": "Check",
+			"label": "Include Disabled",
+		}
+	],
+
+	formatter (value, row, column, data, default_formatter) {
+		value = default_formatter(value, row, column, data);
+
+		if (DIFFERENCE_FIELD_NAMES.includes(column.fieldname) && Math.abs(data[column.fieldname]) > 0.001) {
+			value = "<span style='color:red'>" + value + "</span>";
+		}
+
+		return value;
+	},
+
+	get_datatable_options(options) {
+		return Object.assign(options, {
+			checkboxColumn: true,
+		});
+	},
+
+	onload(report) {
+		report.page.add_inner_button(__('Create Reposting Entries'), () => {
+			let message = `
+				<div>
+					<p>
+						Reposting Entries will change the value of
+						accounts Stock In Hand, and Stock Expenses
+						in the Trial Balance report and will also change
+						the Balance Value in the Stock Balance report.
+					</p>
+					<p>Are you sure you want to create Reposting Entries?</p>
+				</div>`;
+			let indexes = frappe.query_report.datatable.rowmanager.getCheckedRows();
+			let selected_rows = indexes.map(i => frappe.query_report.data[i]);
+
+			if (!selected_rows.length) {
+				frappe.throw(__("Please select rows to create Reposting Entries"));
+			}
+
+			frappe.confirm(__(message), () => {
+				frappe.call({
+					method: 'erpnext.stock.report.stock_ledger_invariant_check.stock_ledger_invariant_check.create_reposting_entries',
+					args: {
+						rows: selected_rows,
+					}
+				});
+			});
+		});
+	},
+};
diff --git a/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.json b/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.json
new file mode 100644
index 0000000..f36ed1b
--- /dev/null
+++ b/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.json
@@ -0,0 +1,22 @@
+{
+ "add_total_row": 0,
+ "columns": [],
+ "creation": "2023-09-20 10:44:19.414449",
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "letterhead": null,
+ "modified": "2023-09-20 10:44:19.414449",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Stock Ledger Variance",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Stock Ledger Entry",
+ "report_name": "Stock Ledger Variance",
+ "report_type": "Script Report",
+ "roles": []
+}
\ No newline at end of file
diff --git a/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.py b/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.py
new file mode 100644
index 0000000..732f108
--- /dev/null
+++ b/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.py
@@ -0,0 +1,279 @@
+# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+import frappe
+from frappe import _
+from frappe.utils import cint, flt
+
+from erpnext.stock.report.stock_ledger_invariant_check.stock_ledger_invariant_check import (
+	get_data as stock_ledger_invariant_check,
+)
+
+
+def execute(filters=None):
+	columns, data = [], []
+
+	filters = frappe._dict(filters or {})
+	columns = get_columns()
+	data = get_data(filters)
+
+	return columns, data
+
+
+def get_columns():
+	return [
+		{
+			"fieldname": "name",
+			"fieldtype": "Link",
+			"label": _("Stock Ledger Entry"),
+			"options": "Stock Ledger Entry",
+		},
+		{
+			"fieldname": "posting_date",
+			"fieldtype": "Data",
+			"label": _("Posting Date"),
+		},
+		{
+			"fieldname": "posting_time",
+			"fieldtype": "Data",
+			"label": _("Posting Time"),
+		},
+		{
+			"fieldname": "creation",
+			"fieldtype": "Data",
+			"label": _("Creation"),
+		},
+		{
+			"fieldname": "item_code",
+			"fieldtype": "Link",
+			"label": _("Item"),
+			"options": "Item",
+		},
+		{
+			"fieldname": "warehouse",
+			"fieldtype": "Link",
+			"label": _("Warehouse"),
+			"options": "Warehouse",
+		},
+		{
+			"fieldname": "voucher_type",
+			"fieldtype": "Link",
+			"label": _("Voucher Type"),
+			"options": "DocType",
+		},
+		{
+			"fieldname": "voucher_no",
+			"fieldtype": "Dynamic Link",
+			"label": _("Voucher No"),
+			"options": "voucher_type",
+		},
+		{
+			"fieldname": "batch_no",
+			"fieldtype": "Link",
+			"label": _("Batch"),
+			"options": "Batch",
+		},
+		{
+			"fieldname": "use_batchwise_valuation",
+			"fieldtype": "Check",
+			"label": _("Batchwise Valuation"),
+		},
+		{
+			"fieldname": "actual_qty",
+			"fieldtype": "Float",
+			"label": _("Qty Change"),
+		},
+		{
+			"fieldname": "incoming_rate",
+			"fieldtype": "Float",
+			"label": _("Incoming Rate"),
+		},
+		{
+			"fieldname": "consumption_rate",
+			"fieldtype": "Float",
+			"label": _("Consumption Rate"),
+		},
+		{
+			"fieldname": "qty_after_transaction",
+			"fieldtype": "Float",
+			"label": _("(A) Qty After Transaction"),
+		},
+		{
+			"fieldname": "expected_qty_after_transaction",
+			"fieldtype": "Float",
+			"label": _("(B) Expected Qty After Transaction"),
+		},
+		{
+			"fieldname": "difference_in_qty",
+			"fieldtype": "Float",
+			"label": _("A - B"),
+		},
+		{
+			"fieldname": "stock_queue",
+			"fieldtype": "Data",
+			"label": _("FIFO/LIFO Queue"),
+		},
+		{
+			"fieldname": "fifo_queue_qty",
+			"fieldtype": "Float",
+			"label": _("(C) Total Qty in Queue"),
+		},
+		{
+			"fieldname": "fifo_qty_diff",
+			"fieldtype": "Float",
+			"label": _("A - C"),
+		},
+		{
+			"fieldname": "stock_value",
+			"fieldtype": "Float",
+			"label": _("(D) Balance Stock Value"),
+		},
+		{
+			"fieldname": "fifo_stock_value",
+			"fieldtype": "Float",
+			"label": _("(E) Balance Stock Value in Queue"),
+		},
+		{
+			"fieldname": "fifo_value_diff",
+			"fieldtype": "Float",
+			"label": _("D - E"),
+		},
+		{
+			"fieldname": "stock_value_difference",
+			"fieldtype": "Float",
+			"label": _("(F) Change in Stock Value"),
+		},
+		{
+			"fieldname": "stock_value_from_diff",
+			"fieldtype": "Float",
+			"label": _("(G) Sum of Change in Stock Value"),
+		},
+		{
+			"fieldname": "diff_value_diff",
+			"fieldtype": "Float",
+			"label": _("G - D"),
+		},
+		{
+			"fieldname": "fifo_stock_diff",
+			"fieldtype": "Float",
+			"label": _("(H) Change in Stock Value (FIFO Queue)"),
+		},
+		{
+			"fieldname": "fifo_difference_diff",
+			"fieldtype": "Float",
+			"label": _("H - F"),
+		},
+		{
+			"fieldname": "valuation_rate",
+			"fieldtype": "Float",
+			"label": _("(I) Valuation Rate"),
+		},
+		{
+			"fieldname": "fifo_valuation_rate",
+			"fieldtype": "Float",
+			"label": _("(J) Valuation Rate as per FIFO"),
+		},
+		{
+			"fieldname": "fifo_valuation_diff",
+			"fieldtype": "Float",
+			"label": _("I - J"),
+		},
+		{
+			"fieldname": "balance_value_by_qty",
+			"fieldtype": "Float",
+			"label": _("(K) Valuation = Value (D) ÷ Qty (A)"),
+		},
+		{
+			"fieldname": "valuation_diff",
+			"fieldtype": "Float",
+			"label": _("I - K"),
+		},
+	]
+
+
+def get_data(filters=None):
+	filters = frappe._dict(filters or {})
+	item_warehouse_map = get_item_warehouse_combinations(filters)
+
+	data = []
+	if item_warehouse_map:
+		precision = cint(frappe.db.get_single_value("System Settings", "float_precision"))
+
+		for item_warehouse in item_warehouse_map:
+			report_data = stock_ledger_invariant_check(item_warehouse)
+
+			if not report_data:
+				continue
+
+			for row in report_data:
+				if has_difference(row, precision, filters.difference_in):
+					data.append(add_item_warehouse_details(row, item_warehouse))
+					break
+
+	return data
+
+
+def get_item_warehouse_combinations(filters: dict = None) -> dict:
+	filters = frappe._dict(filters or {})
+
+	bin = frappe.qb.DocType("Bin")
+	item = frappe.qb.DocType("Item")
+	warehouse = frappe.qb.DocType("Warehouse")
+
+	query = (
+		frappe.qb.from_(bin)
+		.inner_join(item)
+		.on(bin.item_code == item.name)
+		.inner_join(warehouse)
+		.on(bin.warehouse == warehouse.name)
+		.select(
+			bin.item_code,
+			bin.warehouse,
+		)
+		.where((item.is_stock_item == 1) & (item.has_serial_no == 0) & (warehouse.is_group == 0))
+	)
+
+	if filters.item_code:
+		query = query.where(item.name == filters.item_code)
+	if filters.warehouse:
+		query = query.where(warehouse.name == filters.warehouse)
+	if not filters.include_disabled:
+		query = query.where((item.disabled == 0) & (warehouse.disabled == 0))
+
+	return query.run(as_dict=1)
+
+
+def has_difference(row, precision, difference_in):
+	has_qty_difference = flt(row.difference_in_qty, precision) or flt(row.fifo_qty_diff, precision)
+	has_value_difference = (
+		flt(row.diff_value_diff, precision)
+		or flt(row.fifo_value_diff, precision)
+		or flt(row.fifo_difference_diff, precision)
+	)
+	has_valuation_difference = flt(row.valuation_diff, precision) or flt(
+		row.fifo_valuation_diff, precision
+	)
+
+	if difference_in == "Qty" and has_qty_difference:
+		return True
+	elif difference_in == "Value" and has_value_difference:
+		return True
+	elif difference_in == "Valuation" and has_valuation_difference:
+		return True
+	elif difference_in not in ["Qty", "Value", "Valuation"] and (
+		has_qty_difference or has_value_difference or has_valuation_difference
+	):
+		return True
+
+	return False
+
+
+def add_item_warehouse_details(row, item_warehouse):
+	row.update(
+		{
+			"item_code": item_warehouse.item_code,
+			"warehouse": item_warehouse.warehouse,
+		}
+	)
+
+	return row
diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv
index 62d19f6..03e9de4 100644
--- a/erpnext/translations/de.csv
+++ b/erpnext/translations/de.csv
@@ -477,7 +477,7 @@
 Chapter information.,Gruppeninformation,
 Charge of type 'Actual' in row {0} cannot be included in Item Rate or Paid Amount,Kosten für den Typ „Tatsächlich“ in Zeile {0} können nicht in den Artikelpreis oder den bezahlen Betrag einfließen,
 Chargeble,Belastung,
-Charges are updated in Purchase Receipt against each item,Kosten werden im Kaufbeleg für jede Position aktualisiert,
+Charges are updated in Purchase Receipt against each item,Kosten werden im Eingangsbeleg für jede Position aktualisiert,
 "Charges will be distributed proportionately based on item qty or amount, as per your selection",Die Kosten werden gemäß Ihrer Wahl anteilig verteilt basierend auf Artikelmenge oder -preis,
 Chart of Cost Centers,Kostenstellenplan,
 Check all,Alle prüfen,
@@ -1264,7 +1264,7 @@
 Item Variants,Artikelvarianten,
 Item Variants updated,Artikelvarianten aktualisiert,
 Item has variants.,Artikel hat Varianten.,
-Item must be added using 'Get Items from Purchase Receipts' button,"Artikel müssen über die Schaltfläche ""Artikel von Kaufbeleg übernehmen"" hinzugefügt werden",
+Item must be added using 'Get Items from Purchase Receipts' button,"Artikel müssen über die Schaltfläche ""Artikel von Eingangsbeleg übernehmen"" hinzugefügt werden",
 Item valuation rate is recalculated considering landed cost voucher amount,Artikelpreis wird unter Einbezug von Belegen über den Einstandspreis neu berechnet,
 Item variant {0} exists with same attributes,Artikelvariante {0} mit denselben Attributen existiert,
 Item {0} does not exist,Artikel {0} existiert nicht,
@@ -1524,7 +1524,7 @@
 New Quality Procedure,Neues Qualitätsverfahren,
 New Sales Invoice,Neue Ausgangsrechnung,
 New Sales Person Name,Neuer Verkaufspersonenname,
-New Serial No cannot have Warehouse. Warehouse must be set by Stock Entry or Purchase Receipt,"""Neue Seriennummer"" kann keine Lagerangabe enthalten. Lagerangaben müssen durch eine Lagerbuchung oder einen Kaufbeleg erstellt werden",
+New Serial No cannot have Warehouse. Warehouse must be set by Stock Entry or Purchase Receipt,"""Neue Seriennummer"" kann keine Lagerangabe enthalten. Lagerangaben müssen durch eine Lagerbuchung oder einen Eingangsbeleg erstellt werden",
 New Warehouse Name,Neuer Lagername,
 New credit limit is less than current outstanding amount for the customer. Credit limit has to be atleast {0},Neues Kreditlimit ist weniger als der aktuell ausstehende Betrag für den Kunden. Kreditlimit muss mindestens {0} sein,
 New task,Neuer Vorgang,
@@ -1811,7 +1811,7 @@
 Please enter Planned Qty for Item {0} at row {1},Bitte die geplante Menge für Artikel {0} in Zeile {1} eingeben,
 Please enter Preferred Contact Email,Bitte geben Sie Bevorzugte Kontakt per E-Mail,
 Please enter Production Item first,Bitte zuerst Herstellungsartikel eingeben,
-Please enter Purchase Receipt first,Bitte zuerst Kaufbeleg eingeben,
+Please enter Purchase Receipt first,Bitte zuerst Eingangsbeleg eingeben,
 Please enter Receipt Document,Bitte geben Sie Eingangsbeleg,
 Please enter Reference date,Bitte den Stichtag eingeben,
 Please enter Reqd by Date,Bitte geben Sie Requd by Date ein,
@@ -2045,8 +2045,8 @@
 Purchase Orders are not allowed for {0} due to a scorecard standing of {1}.,Kaufaufträge sind für {0} wegen einer Scorecard von {1} nicht erlaubt.,
 Purchase Orders given to Suppliers.,An Lieferanten erteilte Bestellungen,
 Purchase Price List,Einkaufspreisliste,
-Purchase Receipt,Kaufbeleg,
-Purchase Receipt {0} is not submitted,Kaufbeleg {0} wurde nicht übertragen,
+Purchase Receipt,Eingangsbeleg,
+Purchase Receipt {0} is not submitted,Eingangsbeleg {0} wurde nicht übertragen,
 Purchase Tax Template,Umsatzsteuer-Vorlage,
 Purchase User,Nutzer Einkauf,
 Purchase orders help you plan and follow up on your purchases,Bestellungen helfen Ihnen bei der Planung und Follow-up auf Ihre Einkäufe,
@@ -2108,7 +2108,7 @@
 Reason For Putting On Hold,Grund für das auf Eis legen,
 Reason for Hold,Grund für das auf Eis legen,
 Reason for hold: ,Grund für das auf Eis legen:,
-Receipt,Kaufbeleg,
+Receipt,Eingangsbeleg,
 Receipt document must be submitted,Eingangsbeleg muss vorgelegt werden,
 Receivable,Forderung,
 Receivable Account,Forderungskonto,
@@ -2571,7 +2571,7 @@
 Stock In Hand,Stock In Hand,
 Stock Items,Lagerartikel,
 Stock Ledger,Lagerbuch,
-Stock Ledger Entries and GL Entries are reposted for the selected Purchase Receipts,Buchungen auf das Lagerbuch und Hauptbuch-Buchungen werden für die gewählten Kaufbelege umgebucht,
+Stock Ledger Entries and GL Entries are reposted for the selected Purchase Receipts,Buchungen auf das Lagerbuch und Hauptbuch-Buchungen werden für die gewählten Eingangsbelege umgebucht,
 Stock Levels,Lagerbestände,
 Stock Liabilities,Lager-Verbindlichkeiten,
 Stock Qty,Lagermenge,
@@ -2583,7 +2583,7 @@
 Stock Value,Lagerwert,
 Stock balance in Batch {0} will become negative {1} for Item {2} at Warehouse {3},Lagerbestand in Charge {0} wird für Artikel {2} im Lager {3} negativ {1},
 Stock cannot be updated against Delivery Note {0},Lager kann nicht mit Lieferschein {0} aktualisiert werden,
-Stock cannot be updated against Purchase Receipt {0},Auf nicht gegen Kaufbeleg aktualisiert werden {0},
+Stock cannot be updated against Purchase Receipt {0},Bestand kann nicht gegen Eingangsbeleg {0} aktualisiert werden,
 Stock cannot exist for Item {0} since has variants,"Für Artikel {0} kann es kein Lager geben, da es Varianten gibt",
 Stock transactions before {0} are frozen,Lagertransaktionen vor {0} werden gesperrt,
 Stop,Anhalten,
@@ -2648,7 +2648,7 @@
 Supplier Part No,Lieferant Teile-Nr,
 Supplier Quotation,Lieferantenangebot,
 Supplier Scorecard,Lieferanten-Scorecard,
-Supplier Warehouse mandatory for sub-contracted Purchase Receipt,Lieferantenlager notwendig für Kaufbeleg aus Unteraufträgen,
+Supplier Warehouse mandatory for sub-contracted Purchase Receipt,Lieferantenlager notwendig für Eingangsbeleg aus Unteraufträgen,
 Supplier database.,Lieferantendatenbank,
 Supplier {0} not found in {1},Lieferant {0} nicht in {1} gefunden,
 Supplier(s),Lieferant(en),
@@ -3356,7 +3356,7 @@
 Communication,Kommunikation,
 Compact Item Print,Artikel kompakt drucken,
 Company,Unternehmen,
-Company of asset {0} and purchase document {1} doesn't matches.,Das Unternehmen von Anlage {0} und Kaufbeleg {1} stimmt nicht überein.,
+Company of asset {0} and purchase document {1} doesn't matches.,Das Unternehmen von Anlage {0} und Eingangsbeleg {1} stimmt nicht überein.,
 Compare BOMs for changes in Raw Materials and Operations,Vergleichen Sie Stücklisten auf Änderungen in Rohstoffen und Vorgängen,
 Compare List function takes on list arguments,Die Funktion &quot;Liste vergleichen&quot; übernimmt Listenargumente,
 Complete,Komplett,
@@ -3616,7 +3616,7 @@
 Purchase Invoice cannot be made against an existing asset {0},Eingangsrechnung kann nicht für ein vorhandenes Asset erstellt werden {0},
 Purchase Invoices,Eingangsrechnungen,
 Purchase Orders,Kauforder,
-Purchase Receipt doesn't have any Item for which Retain Sample is enabled.,"Der Kaufbeleg enthält keinen Artikel, für den die Option &quot;Probe aufbewahren&quot; aktiviert ist.",
+Purchase Receipt doesn't have any Item for which Retain Sample is enabled.,"Der Eingangsbeleg enthält keinen Artikel, für den die Option &quot;Probe aufbewahren&quot; aktiviert ist.",
 Purchase Return,Warenrücksendung,
 Qty of Finished Goods Item,Menge des Fertigerzeugnisses,
 Quality Inspection required for Item {0} to submit,"Qualitätsprüfung erforderlich, damit Artikel {0} eingereicht werden kann",
@@ -3925,7 +3925,7 @@
 {0} {1} has accounting entries in currency {2} for company {3}. Please select a receivable or payable account with currency {2}.,{0} {1} hat Buchhaltungseinträge in Währung {2} für Firma {3}. Bitte wählen Sie ein Debitoren- oder Kreditorenkonto mit der Währung {2} aus.,
 Invalid Account,Ungültiger Account,
 Purchase Order Required,Bestellung erforderlich,
-Purchase Receipt Required,Kaufbeleg notwendig,
+Purchase Receipt Required,Eingangsbeleg notwendig,
 Account Missing,Konto fehlt,
 Requested,Angefordert,
 Partially Paid,Teilweise bezahlt,
@@ -4691,7 +4691,7 @@
 Item Tax Rate,Artikelsteuersatz,
 Tax detail table fetched from item master as a string and stored in this field.\nUsed for Taxes and Charges,Die Tabelle Steuerdetails wird aus dem Artikelstamm als Zeichenfolge entnommen und in diesem Feld gespeichert. Wird verwendet für Steuern und Abgaben,
 Purchase Order Item,Bestellartikel,
-Purchase Receipt Detail,Kaufbelegdetail,
+Purchase Receipt Detail,Eingangsbelegposition,
 Item Weight Details,Artikel Gewicht Details,
 Weight Per Unit,Gewicht pro Einheit,
 Total Weight,Gesamtgewicht,
@@ -4992,7 +4992,7 @@
 Maintenance Required,Wartung erforderlich,
 Check if Asset requires Preventive Maintenance or Calibration,"Überprüfen Sie, ob der Vermögenswert eine vorbeugende Wartung oder Kalibrierung erfordert",
 Booked Fixed Asset,Gebuchtes Anlagevermögen,
-Purchase Receipt Amount,Kaufbelegbetrag,
+Purchase Receipt Amount,Betrag Eingangsbeleg,
 Default Finance Book,Standardfinanzbuch,
 Quality Manager,Qualitätsmanager,
 Asset Category Name,Name Vermögenswertkategorie,
@@ -5112,7 +5112,7 @@
 Stock Uom,Lagermaßeinheit,
 Raw Material Item Code,Rohmaterial-Artikelnummer,
 Supplied Qty,Gelieferte Anzahl,
-Purchase Receipt Item Supplied,Kaufbeleg-Artikel geliefert,
+Purchase Receipt Item Supplied,Eingangsbeleg-Artikel geliefert,
 Current Stock,Aktueller Lagerbestand,
 PUR-RFQ-.YYYY.-,PUR-RFQ-.YYYY.-,
 For individual supplier,Für einzelne Anbieter,
@@ -5132,7 +5132,7 @@
 Represents Company,Repräsentiert das Unternehmen,
 Supplier Type,Lieferantentyp,
 Allow Purchase Invoice Creation Without Purchase Order,Erstellen von Eingangsrechnung ohne Bestellung zulassen,
-Allow Purchase Invoice Creation Without Purchase Receipt,Erstellen von Eingangsrechnung ohne Kaufbeleg ohne Kaufbeleg zulassen,
+Allow Purchase Invoice Creation Without Purchase Receipt,Erstellen von Eingangsrechnung ohne Eingangsbeleg zulassen,
 Warn RFQs,Warnung Ausschreibungen,
 Warn POs,Warnen Sie POs,
 Prevent RFQs,Vermeidung von Ausschreibungen,
@@ -7199,13 +7199,13 @@
 Receipt Document Type,Receipt Dokumenttyp,
 Receipt Document,Eingangsbeleg,
 Applicable Charges,Anfallende Gebühren,
-Purchase Receipt Item,Kaufbeleg-Artikel,
-Landed Cost Purchase Receipt,Einstandspreis-Kaufbeleg,
+Purchase Receipt Item,Eingangsbeleg-Artikel,
+Landed Cost Purchase Receipt,Einstandspreis-Eingangsbeleg,
 Landed Cost Taxes and Charges,Einstandspreis Steuern und Gebühren,
 Landed Cost Voucher,Beleg über Einstandskosten,
-Purchase Receipts,Kaufbelege,
-Purchase Receipt Items,Kaufbeleg-Artikel,
-Get Items From Purchase Receipts,Artikel vom Kaufbeleg übernehmen,
+Purchase Receipts,Eingangsbelege,
+Purchase Receipt Items,Eingangsbeleg-Artikel,
+Get Items From Purchase Receipts,Artikel vom Eingangsbeleg übernehmen,
 Distribute Charges Based On,Kosten auf folgender Grundlage verteilen,
 Landed Cost Help,Hilfe zum Einstandpreis,
 Manufacturers used in Items,Hersteller im Artikel verwendet,
@@ -7253,7 +7253,7 @@
 MAT-PRE-.YYYY.-,MAT-PRE-.JJJJ.-,
 Supplier Delivery Note,Lieferschein Nr.,
 Time at which materials were received,"Zeitpunkt, zu dem Materialien empfangen wurden",
-Return Against Purchase Receipt,Zurück zum Kaufbeleg,
+Return Against Purchase Receipt,Zurück zum Eingangsbeleg,
 Rate at which supplier's currency is converted to company's base currency,"Kurs, zu dem die Währung des Lieferanten in die Basiswährung des Unternehmens umgerechnet wird",
 Sets 'Accepted Warehouse' in each row of the items table.,Legt &#39;Akzeptiertes Lager&#39; in jeder Zeile der Artikeltabelle fest.,
 Sets 'Rejected Warehouse' in each row of the items table.,Legt &#39;Abgelehntes Lager&#39; in jeder Zeile der Artikeltabelle fest.,
@@ -7293,7 +7293,7 @@
 Quick Stock Balance,Schneller Lagerbestand,
 Available Quantity,verfügbare Anzahl,
 Distinct unit of an Item,Eindeutige Einheit eines Artikels,
-Warehouse can only be changed via Stock Entry / Delivery Note / Purchase Receipt,Lager kann nur über Lagerbuchung / Lieferschein / Kaufbeleg geändert werden,
+Warehouse can only be changed via Stock Entry / Delivery Note / Purchase Receipt,Lager kann nur über Lagerbuchung / Lieferschein / Eingangsbeleg geändert werden,
 Purchase / Manufacture Details,Einzelheiten zu Kauf / Herstellung,
 Creation Document Type,Belegerstellungs-Typ,
 Creation Document No,Belegerstellungs-Nr.,
@@ -7321,7 +7321,7 @@
 Send to Subcontractor,An Subunternehmer senden,
 Delivery Note No,Lieferschein-Nummer,
 Sales Invoice No,Ausgangsrechnungs-Nr.,
-Purchase Receipt No,Kaufbeleg Nr.,
+Purchase Receipt No,Eingangsbeleg Nr.,
 Inspection Required,Prüfung erforderlich,
 From BOM,Von Stückliste,
 For Quantity,Für Menge,
@@ -7350,7 +7350,7 @@
 Against Stock Entry,Gegen Lagerbuchung,
 Stock Entry Child,Stock Entry Child,
 PO Supplied Item,PO geliefertes Einzelteil,
-Reference Purchase Receipt,Referenz Kaufbeleg,
+Reference Purchase Receipt,Referenz Eingangsbeleg,
 Stock Ledger Entry,Buchung im Lagerbuch,
 Outgoing Rate,Verkaufspreis,
 Actual Qty After Transaction,Tatsächliche Anzahl nach Transaktionen,
@@ -7566,7 +7566,7 @@
 Received Qty Amount,Erhaltene Menge Menge,
 Billed Qty,Rechnungsmenge,
 Purchase Order Trends,Entwicklung Bestellungen,
-Purchase Receipt Trends,Trendanalyse Kaufbelege,
+Purchase Receipt Trends,Trendanalyse Eingangsbelege,
 Purchase Register,Übersicht über Einkäufe,
 Quotation Trends,Trendanalyse Angebote,
 Received Items To Be Billed,"Von Lieferanten gelieferte Artikel, die noch abgerechnet werden müssen",
@@ -7803,8 +7803,8 @@
 "By default, the Supplier Name is set as per the Supplier Name entered. If you want Suppliers to be named by a  ","Standardmäßig wird der Lieferantenname gemäß dem eingegebenen Lieferantennamen festgelegt. Wenn Sie möchten, dass Lieferanten von a benannt werden",
  choose the 'Naming Series' option.,Wählen Sie die Option &quot;Naming Series&quot;.,
 Configure the default Price List when creating a new Purchase transaction. Item prices will be fetched from this Price List.,Konfigurieren Sie die Standardpreisliste beim Erstellen einer neuen Kauftransaktion. Artikelpreise werden aus dieser Preisliste abgerufen.,
-"If this option is configured 'Yes', ERPNext will prevent you from creating a Purchase Invoice or Receipt without creating a Purchase Order first. This configuration can be overridden for a particular supplier by enabling the 'Allow Purchase Invoice Creation Without Purchase Order' checkbox in the Supplier master.","Wenn diese Option auf 'Ja' gesetzt ist, validiert ERPNext, dass Sie eine Bestellung angelegt haben, bevor Sie eine Eingangsrechnung oder einen Kaufbeleg erfassen können. Diese Konfiguration kann für einzelne Lieferanten überschrieben werden, indem Sie die Option 'Erstellung von Eingangsrechnungen ohne Bestellung zulassen' im Lieferantenstamm aktivieren.",
-"If this option is configured 'Yes', ERPNext will prevent you from creating a Purchase Invoice without creating a Purchase Receipt first. This configuration can be overridden for a particular supplier by enabling the 'Allow Purchase Invoice Creation Without Purchase Receipt' checkbox in the Supplier master.","Wenn diese Option auf 'Ja' gesetzt ist, validiert ERPNext, dass Sie einen Kaufbeleg angelegt haben, bevor Sie eine Eingangsrechnung erfasen können. Diese Konfiguration kann für einzelne Lieferanten überschrieben werden, indem Sie die Option 'Erstellung von Kaufrechnungen ohne Kaufbeleg zulassen' im Lieferantenstamm aktivieren.",
+"If this option is configured 'Yes', ERPNext will prevent you from creating a Purchase Invoice or Receipt without creating a Purchase Order first. This configuration can be overridden for a particular supplier by enabling the 'Allow Purchase Invoice Creation Without Purchase Order' checkbox in the Supplier master.","Wenn diese Option auf 'Ja' gesetzt ist, validiert ERPNext, dass Sie eine Bestellung angelegt haben, bevor Sie eine Eingangsrechnung oder einen Eingangsbeleg erfassen können. Diese Konfiguration kann für einzelne Lieferanten überschrieben werden, indem Sie die Option 'Erstellung von Eingangsrechnungen ohne Bestellung zulassen' im Lieferantenstamm aktivieren.",
+"If this option is configured 'Yes', ERPNext will prevent you from creating a Purchase Invoice without creating a Purchase Receipt first. This configuration can be overridden for a particular supplier by enabling the 'Allow Purchase Invoice Creation Without Purchase Receipt' checkbox in the Supplier master.","Wenn diese Option auf 'Ja' gesetzt ist, validiert ERPNext, dass Sie einen Eingangsbeleg angelegt haben, bevor Sie eine Eingangsrechnung erfassen können. Diese Konfiguration kann für einzelne Lieferanten überschrieben werden, indem Sie die Option 'Erstellung von Kaufrechnungen ohne Eingangsbeleg zulassen' im Lieferantenstamm aktivieren.",
 Quantity & Stock,Menge & Lager,
 Call Details,Anrufdetails,
 Authorised By,Authorisiert von,
@@ -8046,7 +8046,6 @@
 Image Description,Bildbeschreibung,
 Transfer Status,Übertragungsstatus,
 MAT-PR-RET-.YYYY.-,MAT-PR-RET-.YYYY.-,
-Track this Purchase Receipt against any Project,Verfolgen Sie diesen Kaufbeleg für jedes Projekt,
 Please Select a Supplier,Bitte wählen Sie einen Lieferanten,
 Add to Transit,Zum Transit hinzufügen,
 Set Basic Rate Manually,Grundpreis manuell einstellen,
@@ -8472,7 +8471,7 @@
 Only select this if you have set up the Cash Flow Mapper documents,"Wählen Sie diese Option nur, wenn Sie die Cash Flow Mapper-Dokumente eingerichtet haben",
 Payment Channel,Zahlungskanal,
 Is Purchase Order Required for Purchase Invoice & Receipt Creation?,Ist für die Erstellung von Eingangsrechnungen und Quittungen eine Bestellung erforderlich?,
-Is Purchase Receipt Required for Purchase Invoice Creation?,Ist für die Erstellung der Eingangsrechnungen ein Kaufbeleg erforderlich?,
+Is Purchase Receipt Required for Purchase Invoice Creation?,Ist für die Erstellung der Eingangsrechnungen ein Eingangsbeleg erforderlich?,
 Maintain Same Rate Throughout the Purchase Cycle,Behalten Sie den gleichen Preis während des gesamten Kaufzyklus bei,
 Allow Item To Be Added Multiple Times in a Transaction,"Zulassen, dass ein Element in einer Transaktion mehrmals hinzugefügt wird",
 Suppliers,Lieferanten,
@@ -8546,7 +8545,7 @@
 Raise Material Request When Stock Reaches Re-order Level,"Erhöhen Sie die Materialanforderung, wenn der Lagerbestand die Nachbestellmenge erreicht",
 Notify by Email on Creation of Automatic Material Request,Benachrichtigen Sie per E-Mail über die Erstellung einer automatischen Materialanforderung,
 Allow Material Transfer from Delivery Note to Sales Invoice,Materialübertragung vom Lieferschein zur Ausgangsrechnung zulassen,
-Allow Material Transfer from Purchase Receipt to Purchase Invoice,Materialübertragung vom Kaufbeleg zur Eingangsrechnung zulassen,
+Allow Material Transfer from Purchase Receipt to Purchase Invoice,Materialübertragung vom Eingangsbeleg zur Eingangsrechnung zulassen,
 Freeze Stocks Older Than (Days),Aktien einfrieren älter als (Tage),
 Role Allowed to Edit Frozen Stock,Rolle darf eingefrorenes Material bearbeiten,
 The unallocated amount of Payment Entry {0} is greater than the Bank Transaction's unallocated amount,Der nicht zugewiesene Betrag der Zahlungseingabe {0} ist größer als der nicht zugewiesene Betrag der Banküberweisung,
@@ -8671,20 +8670,17 @@
 Please set default Cash or Bank account in Mode of Payments {},Bitte setzen Sie das Standard-Bargeld- oder Bankkonto im Zahlungsmodus {},
 Please ensure {} account is a Balance Sheet account. You can change the parent account to a Balance Sheet account or select a different account.,"Bitte stellen Sie sicher, dass das Konto {} ein Bilanzkonto ist. Sie können das übergeordnete Konto in ein Bilanzkonto ändern oder ein anderes Konto auswählen.",
 Please ensure {} account is a Payable account. Change the account type to Payable or select a different account.,"Bitte stellen Sie sicher, dass das Konto {} ein zahlbares Konto ist. Ändern Sie den Kontotyp in &quot;Verbindlichkeiten&quot; oder wählen Sie ein anderes Konto aus.",
-Row {}: Expense Head changed to {} ,Zeile {}: Ausgabenkopf geändert in {},
-because account {} is not linked to warehouse {} ,weil das Konto {} nicht mit dem Lager {} verknüpft ist,
-or it is not the default inventory account,oder es ist nicht das Standard-Inventarkonto,
-Expense Head Changed,Ausgabenkopf geändert,
-because expense is booked against this account in Purchase Receipt {},weil die Kosten für dieses Konto im Kaufbeleg {} gebucht werden,
-as no Purchase Receipt is created against Item {}. ,da für Artikel {} kein Kaufbeleg erstellt wird.,
-This is done to handle accounting for cases when Purchase Receipt is created after Purchase Invoice,"Dies erfolgt zur Abrechnung von Fällen, in denen der Kaufbeleg nach der Eingangsrechnung erstellt wird",
+"Row {0}: Expense Head changed to {1} because account {2} is not linked to warehouse {3} or it is not the default inventory account","Zeile {0}: Aufwandskonto geändert zu {1}, weil das Konto {2} nicht mit dem Lager {3} verknüpft ist oder es nicht das Standard-Inventarkonto ist",
+Row {0}: Expense Head changed to {1} because expense is booked against this account in Purchase Receipt {2},"Zeile {0}: Aufwandskonto geändert zu {1}, da dieses bereits in Eingangsbeleg {2} verwendet wurde",
+Row {0}: Expense Head changed to {1} as no Purchase Receipt is created against Item {2}.,"Zeile {0}: Aufwandskonto geändert zu {1}, da kein Eingangsbeleg für Artikel {2} erstellt wird.",
+This is done to handle accounting for cases when Purchase Receipt is created after Purchase Invoice,"Dies erfolgt zur Abrechnung von Fällen, in denen der Eingangsbeleg nach der Eingangsrechnung erstellt wird",
 Purchase Order Required for item {},Bestellung erforderlich für Artikel {},
 To submit the invoice without purchase order please set {} ,"Um die Rechnung ohne Bestellung einzureichen, setzen Sie bitte {}",
 as {} in {},wie in {},
 Mandatory Purchase Order,Obligatorische Bestellung,
-Purchase Receipt Required for item {},Kaufbeleg für Artikel {} erforderlich,
-To submit the invoice without purchase receipt please set {} ,"Um die Rechnung ohne Kaufbeleg einzureichen, setzen Sie bitte {}",
-Mandatory Purchase Receipt,Obligatorischer Kaufbeleg,
+Purchase Receipt Required for item {},Eingangsbeleg für Artikel {} erforderlich,
+To submit the invoice without purchase receipt please set {} ,"Um die Rechnung ohne Eingangsbeleg einzureichen, setzen Sie bitte {}",
+Mandatory Purchase Receipt,Obligatorischer Eingangsbeleg,
 POS Profile {} does not belongs to company {},Das POS-Profil {} gehört nicht zur Firma {},
 User {} is disabled. Please select valid user/cashier,Benutzer {} ist deaktiviert. Bitte wählen Sie einen gültigen Benutzer / Kassierer aus,
 Row #{}: Original Invoice {} of return invoice {} is {}. ,Zeile # {}: Die Originalrechnung {} der Rücksenderechnung {} ist {}.,
diff --git a/erpnext/translations/fr.csv b/erpnext/translations/fr.csv
index 3180631..4f4a61f 100644
--- a/erpnext/translations/fr.csv
+++ b/erpnext/translations/fr.csv
@@ -7097,8 +7097,8 @@
 No of Months,Nombre de mois,
 Customer Items,Articles du clients,
 Inspection Criteria,Critères d'Inspection,
-Inspection Required before Purchase,Inspection Requise avant Achat,
-Inspection Required before Delivery,Inspection Requise avant Livraison,
+Inspection Required before Purchase,Inspection Requise à la réception,
+Inspection Required before Delivery,Inspection Requise à l'expedition,
 Default BOM,Nomenclature par Défaut,
 Supply Raw Materials for Purchase,Fournir les Matières Premières pour l'Achat,
 If subcontracted to a vendor,Si sous-traité à un fournisseur,
@@ -8840,3 +8840,21 @@
 Is Mandatory,Est obligatoire,
 WhatsApp,WhatsApp,
 Make a call,Passer un coup de téléphone,
+No of Employees,Nb de salarié(e)s
+No. of Employees,Nb de salarié(e)s
+Annual Revenue,CA annuel
+Qualified By,Qualifié par
+Qualified on,Qualifié le
+Open Tasks,Tâche à faire ouverte
+No open task,Pas de Tâche à faire ouverte
+Open Events,Evénements ouvert
+No open event,Pas Evénements ouvert
+New Task,Nv. Tâche à faire
+No Notes,Pas de note
+New Note,Nouvelle Note
+Prospect Owner,Resp. du Prospect
+Deal Owner,Resp. de l'opportunité
+Stage,Etape
+Probability,Probabilité
+Closing,Clôture
+Allow Sales,Autoriser à la vente