Merge pull request #33227 from barredterra/add-translation-variable-order

fix: add translation variable index
diff --git a/.github/helper/install.sh b/.github/helper/install.sh
index 2bb950f..2b3d8cb 100644
--- a/.github/helper/install.sh
+++ b/.github/helper/install.sh
@@ -24,15 +24,14 @@
 
 
 if [ "$DB" == "mariadb" ];then
-    mysql --host 127.0.0.1 --port 3306 -u root -e "SET GLOBAL character_set_server = 'utf8mb4'"
-    mysql --host 127.0.0.1 --port 3306 -u root -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'"
+    mysql --host 127.0.0.1 --port 3306 -u root -proot -e "SET GLOBAL character_set_server = 'utf8mb4'"
+    mysql --host 127.0.0.1 --port 3306 -u root -proot -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'"
 
-    mysql --host 127.0.0.1 --port 3306 -u root -e "CREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe'"
-    mysql --host 127.0.0.1 --port 3306 -u root -e "CREATE DATABASE test_frappe"
-    mysql --host 127.0.0.1 --port 3306 -u root -e "GRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost'"
+    mysql --host 127.0.0.1 --port 3306 -u root -proot -e "CREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe'"
+    mysql --host 127.0.0.1 --port 3306 -u root -proot -e "CREATE DATABASE test_frappe"
+    mysql --host 127.0.0.1 --port 3306 -u root -proot -e "GRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost'"
 
-    mysql --host 127.0.0.1 --port 3306 -u root -e "UPDATE mysql.user SET Password=PASSWORD('travis') WHERE User='root'"
-    mysql --host 127.0.0.1 --port 3306 -u root -e "FLUSH PRIVILEGES"
+    mysql --host 127.0.0.1 --port 3306 -u root -proot -e "FLUSH PRIVILEGES"
 fi
 
 if [ "$DB" == "postgres" ];then
diff --git a/.github/helper/site_config_mariadb.json b/.github/helper/site_config_mariadb.json
index 948ad08..49e7fcf 100644
--- a/.github/helper/site_config_mariadb.json
+++ b/.github/helper/site_config_mariadb.json
@@ -9,7 +9,7 @@
  "mail_password": "test",
  "admin_password": "admin",
  "root_login": "root",
- "root_password": "travis",
+ "root_password": "root",
  "host_name": "http://test_site:8000",
  "install_apps": ["erpnext"],
  "throttle_user_limit": 100
diff --git a/.github/workflows/patch.yml b/.github/workflows/patch.yml
index 9e06254..d5f0052 100644
--- a/.github/workflows/patch.yml
+++ b/.github/workflows/patch.yml
@@ -25,7 +25,7 @@
       mysql:
         image: mariadb:10.3
         env:
-          MYSQL_ALLOW_EMPTY_PASSWORD: YES
+          MARIADB_ROOT_PASSWORD: 'root'
         ports:
           - 3306:3306
         options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
diff --git a/.github/workflows/server-tests-mariadb.yml b/.github/workflows/server-tests-mariadb.yml
index b40faa7..bbb8a7e 100644
--- a/.github/workflows/server-tests-mariadb.yml
+++ b/.github/workflows/server-tests-mariadb.yml
@@ -45,9 +45,9 @@
 
     services:
       mysql:
-        image: mariadb:10.3
+        image: mariadb:10.6
         env:
-          MYSQL_ALLOW_EMPTY_PASSWORD: YES
+          MARIADB_ROOT_PASSWORD: 'root'
         ports:
           - 3306:3306
         options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
diff --git a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py
index 4592421..3207e41 100644
--- a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py
+++ b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py
@@ -9,10 +9,6 @@
 from frappe.utils import add_days, add_years, cstr, getdate
 
 
-class FiscalYearIncorrectDate(frappe.ValidationError):
-	pass
-
-
 class FiscalYear(Document):
 	@frappe.whitelist()
 	def set_as_default(self):
@@ -53,23 +49,18 @@
 					)
 
 	def validate_dates(self):
+		self.validate_from_to_dates("year_start_date", "year_end_date")
 		if self.is_short_year:
 			# Fiscal Year can be shorter than one year, in some jurisdictions
 			# under certain circumstances. For example, in the USA and Germany.
 			return
 
-		if getdate(self.year_start_date) > getdate(self.year_end_date):
-			frappe.throw(
-				_("Fiscal Year Start Date should be one year earlier than Fiscal Year End Date"),
-				FiscalYearIncorrectDate,
-			)
-
 		date = getdate(self.year_start_date) + relativedelta(years=1) - relativedelta(days=1)
 
 		if getdate(self.year_end_date) != date:
 			frappe.throw(
 				_("Fiscal Year End Date should be one year after Fiscal Year Start Date"),
-				FiscalYearIncorrectDate,
+				frappe.exceptions.InvalidDates,
 			)
 
 	def on_update(self):
@@ -169,5 +160,6 @@
 
 
 def get_from_and_to_date(fiscal_year):
-	fields = ["year_start_date as from_date", "year_end_date as to_date"]
-	return frappe.get_cached_value("Fiscal Year", fiscal_year, fields, as_dict=1)
+	fields = ["year_start_date", "year_end_date"]
+	cached_results = frappe.get_cached_value("Fiscal Year", fiscal_year, fields, as_dict=1)
+	return dict(from_date=cached_results.year_start_date, to_date=cached_results.year_end_date)
diff --git a/erpnext/accounts/doctype/fiscal_year/test_fiscal_year.py b/erpnext/accounts/doctype/fiscal_year/test_fiscal_year.py
index 6e946f7..181406b 100644
--- a/erpnext/accounts/doctype/fiscal_year/test_fiscal_year.py
+++ b/erpnext/accounts/doctype/fiscal_year/test_fiscal_year.py
@@ -7,8 +7,6 @@
 import frappe
 from frappe.utils import now_datetime
 
-from erpnext.accounts.doctype.fiscal_year.fiscal_year import FiscalYearIncorrectDate
-
 test_ignore = ["Company"]
 
 
@@ -26,7 +24,7 @@
 			}
 		)
 
-		self.assertRaises(FiscalYearIncorrectDate, fy.insert)
+		self.assertRaises(frappe.exceptions.InvalidDates, fy.insert)
 
 
 def test_record_generator():
@@ -35,8 +33,8 @@
 			"doctype": "Fiscal Year",
 			"year": "_Test Short Fiscal Year 2011",
 			"is_short_year": 1,
-			"year_end_date": "2011-04-01",
-			"year_start_date": "2011-12-31",
+			"year_start_date": "2011-04-01",
+			"year_end_date": "2011-12-31",
 		}
 	]
 
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
index ed46d85..b666e0d 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
@@ -10,7 +10,7 @@
 import frappe
 from frappe import _, throw
 from frappe.model.document import Document
-from frappe.utils import cint, flt, getdate
+from frappe.utils import cint, flt
 
 apply_on_dict = {"Item Code": "items", "Item Group": "item_groups", "Brand": "brands"}
 
@@ -184,8 +184,7 @@
 		if self.is_cumulative and not (self.valid_from and self.valid_upto):
 			frappe.throw(_("Valid from and valid upto fields are mandatory for the cumulative"))
 
-		if self.valid_from and self.valid_upto and getdate(self.valid_from) > getdate(self.valid_upto):
-			frappe.throw(_("Valid from date must be less than valid upto date"))
+		self.validate_from_to_dates("valid_from", "valid_upto")
 
 	def validate_condition(self):
 		if (
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 0a92820..0e9f976 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -231,7 +231,9 @@
 		)
 
 		if (
-			cint(frappe.db.get_single_value("Buying Settings", "maintain_same_rate")) and not self.is_return
+			cint(frappe.db.get_single_value("Buying Settings", "maintain_same_rate"))
+			and not self.is_return
+			and not self.is_internal_supplier
 		):
 			self.validate_rate_with_reference_doc(
 				[
diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.py b/erpnext/accounts/doctype/tax_rule/tax_rule.py
index 4d20129..87c5e6d 100644
--- a/erpnext/accounts/doctype/tax_rule/tax_rule.py
+++ b/erpnext/accounts/doctype/tax_rule/tax_rule.py
@@ -32,7 +32,7 @@
 
 	def validate(self):
 		self.validate_tax_template()
-		self.validate_date()
+		self.validate_from_to_dates("from_date", "to_date")
 		self.validate_filters()
 		self.validate_use_for_shopping_cart()
 
@@ -51,10 +51,6 @@
 		if not (self.sales_tax_template or self.purchase_tax_template):
 			frappe.throw(_("Tax Template is mandatory."))
 
-	def validate_date(self):
-		if self.from_date and self.to_date and self.from_date > self.to_date:
-			frappe.throw(_("From Date cannot be greater than To Date"))
-
 	def validate_filters(self):
 		filters = {
 			"tax_type": self.tax_type,
diff --git a/erpnext/accounts/report/utils.py b/erpnext/accounts/report/utils.py
index eed5836..d3cd290 100644
--- a/erpnext/accounts/report/utils.py
+++ b/erpnext/accounts/report/utils.py
@@ -28,7 +28,7 @@
 		filters["presentation_currency"] if filters.get("presentation_currency") else company_currency
 	)
 
-	report_date = filters.get("to_date")
+	report_date = filters.get("to_date") or filters.get("period_end_date")
 
 	if not report_date:
 		fiscal_year_to_date = get_from_and_to_date(filters.get("to_fiscal_year"))["to_date"]
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 0514604..2efa545 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -322,17 +322,18 @@
 					)
 
 				if self.is_internal_transfer():
-					if rate != d.rate:
-						d.rate = rate
-						frappe.msgprint(
-							_(
-								"Row {0}: Item rate has been updated as per valuation rate since its an internal stock transfer"
-							).format(d.idx),
-							alert=1,
-						)
-					d.discount_percentage = 0.0
-					d.discount_amount = 0.0
-					d.margin_rate_or_amount = 0.0
+					if self.doctype == "Purchase Receipt" or self.get("update_stock"):
+						if rate != d.rate:
+							d.rate = rate
+							frappe.msgprint(
+								_(
+									"Row {0}: Item rate has been updated as per valuation rate since its an internal stock transfer"
+								).format(d.idx),
+								alert=1,
+							)
+						d.discount_percentage = 0.0
+						d.discount_amount = 0.0
+						d.margin_rate_or_amount = 0.0
 
 	def validate_for_subcontracting(self):
 		if self.is_subcontracted and self.get("is_old_subcontracting_flow"):
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index 965335b..0ebc8d4 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -442,30 +442,31 @@
 
 				# For internal transfers use incoming rate as the valuation rate
 				if self.is_internal_transfer():
-					if d.doctype == "Packed Item":
-						incoming_rate = flt(
-							flt(d.incoming_rate, d.precision("incoming_rate")) * d.conversion_factor,
-							d.precision("incoming_rate"),
-						)
-						if d.incoming_rate != incoming_rate:
-							d.incoming_rate = incoming_rate
-					else:
-						rate = flt(
-							flt(d.incoming_rate, d.precision("incoming_rate")) * d.conversion_factor,
-							d.precision("rate"),
-						)
-						if d.rate != rate:
-							d.rate = rate
-							frappe.msgprint(
-								_(
-									"Row {0}: Item rate has been updated as per valuation rate since its an internal stock transfer"
-								).format(d.idx),
-								alert=1,
+					if self.doctype == "Delivery Note" or self.get("update_stock"):
+						if d.doctype == "Packed Item":
+							incoming_rate = flt(
+								flt(d.incoming_rate, d.precision("incoming_rate")) * d.conversion_factor,
+								d.precision("incoming_rate"),
 							)
+							if d.incoming_rate != incoming_rate:
+								d.incoming_rate = incoming_rate
+						else:
+							rate = flt(
+								flt(d.incoming_rate, d.precision("incoming_rate")) * d.conversion_factor,
+								d.precision("rate"),
+							)
+							if d.rate != rate:
+								d.rate = rate
+								frappe.msgprint(
+									_(
+										"Row {0}: Item rate has been updated as per valuation rate since its an internal stock transfer"
+									).format(d.idx),
+									alert=1,
+								)
 
-						d.discount_percentage = 0.0
-						d.discount_amount = 0.0
-						d.margin_rate_or_amount = 0.0
+							d.discount_percentage = 0.0
+							d.discount_amount = 0.0
+							d.margin_rate_or_amount = 0.0
 
 			elif self.get("return_against"):
 				# Get incoming rate of return entry from reference document
diff --git a/erpnext/manufacturing/report/production_planning_report/production_planning_report.py b/erpnext/manufacturing/report/production_planning_report/production_planning_report.py
index 16c25ce..109d9ab 100644
--- a/erpnext/manufacturing/report/production_planning_report/production_planning_report.py
+++ b/erpnext/manufacturing/report/production_planning_report/production_planning_report.py
@@ -49,7 +49,7 @@
 					parent.bom_no,
 					parent.fg_warehouse.as_("warehouse"),
 				)
-				.where(parent.status.notin(["Completed", "Stopped"]))
+				.where(parent.status.notin(["Completed", "Stopped", "Closed"]))
 			)
 
 			if order_by == "Planned Start Date":
@@ -79,10 +79,11 @@
 				query = query.where(child.parent.isin(self.filters.docnames))
 
 			if doctype == "Sales Order":
-				query = query.select(
-					child.delivery_date,
-					parent.base_grand_total,
-				).where((child.stock_qty > child.produced_qty) & (parent.per_delivered < 100.0))
+				query = query.select(child.delivery_date, parent.base_grand_total,).where(
+					(child.stock_qty > child.produced_qty)
+					& (parent.per_delivered < 100.0)
+					& (parent.status.notin(["Completed", "Closed"]))
+				)
 
 				if order_by == "Delivery Date":
 					query = query.orderby(child.delivery_date, order=Order.asc)
@@ -91,7 +92,9 @@
 
 			elif doctype == "Material Request":
 				query = query.select(child.schedule_date,).where(
-					(parent.per_ordered < 100) & (parent.material_request_type == "Manufacture")
+					(parent.per_ordered < 100)
+					& (parent.material_request_type == "Manufacture")
+					& (parent.status != "Stopped")
 				)
 
 				if order_by == "Required Date":
diff --git a/erpnext/patches/v13_0/update_exchange_rate_settings.py b/erpnext/patches/v13_0/update_exchange_rate_settings.py
index 746195f..130a7bf 100644
--- a/erpnext/patches/v13_0/update_exchange_rate_settings.py
+++ b/erpnext/patches/v13_0/update_exchange_rate_settings.py
@@ -1,5 +1,8 @@
+import frappe
+
 from erpnext.setup.install import setup_currency_exchange
 
 
 def execute():
+	frappe.reload_doc("accounts", "doctype", "currency_exchange_settings")
 	setup_currency_exchange()
diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py
index d80133c..cbf2493 100644
--- a/erpnext/projects/doctype/project/project.py
+++ b/erpnext/projects/doctype/project/project.py
@@ -42,6 +42,8 @@
 		self.send_welcome_email()
 		self.update_costing()
 		self.update_percent_complete()
+		self.validate_from_to_dates("expected_start_date", "expected_end_date")
+		self.validate_from_to_dates("actual_start_date", "actual_end_date")
 
 	def copy_from_template(self):
 		"""
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index fa50785..79f1b3a 100755
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -9,6 +9,7 @@
 from frappe.desk.form.assign_to import clear, close_all_assignments
 from frappe.model.mapper import get_mapped_doc
 from frappe.utils import add_days, cstr, date_diff, flt, get_link_to_form, getdate, today
+from frappe.utils.data import format_date
 from frappe.utils.nestedset import NestedSet
 
 
@@ -16,10 +17,6 @@
 	pass
 
 
-class EndDateCannotBeGreaterThanProjectEndDateError(frappe.ValidationError):
-	pass
-
-
 class Task(NestedSet):
 	nsm_parent_field = "parent_task"
 
@@ -34,8 +31,6 @@
 
 	def validate(self):
 		self.validate_dates()
-		self.validate_parent_expected_end_date()
-		self.validate_parent_project_dates()
 		self.validate_progress()
 		self.validate_status()
 		self.update_depends_on()
@@ -43,51 +38,42 @@
 		self.validate_completed_on()
 
 	def validate_dates(self):
-		if (
-			self.exp_start_date
-			and self.exp_end_date
-			and getdate(self.exp_start_date) > getdate(self.exp_end_date)
-		):
-			frappe.throw(
-				_("{0} can not be greater than {1}").format(
-					frappe.bold("Expected Start Date"), frappe.bold("Expected End Date")
-				)
-			)
-
-		if (
-			self.act_start_date
-			and self.act_end_date
-			and getdate(self.act_start_date) > getdate(self.act_end_date)
-		):
-			frappe.throw(
-				_("{0} can not be greater than {1}").format(
-					frappe.bold("Actual Start Date"), frappe.bold("Actual End Date")
-				)
-			)
+		self.validate_from_to_dates("exp_start_date", "exp_end_date")
+		self.validate_from_to_dates("act_start_date", "act_end_date")
+		self.validate_parent_expected_end_date()
+		self.validate_parent_project_dates()
 
 	def validate_parent_expected_end_date(self):
-		if self.parent_task:
-			parent_exp_end_date = frappe.db.get_value("Task", self.parent_task, "exp_end_date")
-			if parent_exp_end_date and getdate(self.get("exp_end_date")) > getdate(parent_exp_end_date):
-				frappe.throw(
-					_(
-						"Expected End Date should be less than or equal to parent task's Expected End Date {0}."
-					).format(getdate(parent_exp_end_date))
-				)
+		if not self.parent_task or not self.exp_end_date:
+			return
+
+		parent_exp_end_date = frappe.db.get_value("Task", self.parent_task, "exp_end_date")
+		if not parent_exp_end_date:
+			return
+
+		if getdate(self.exp_end_date) > getdate(parent_exp_end_date):
+			frappe.throw(
+				_(
+					"Expected End Date should be less than or equal to parent task's Expected End Date {0}."
+				).format(format_date(parent_exp_end_date)),
+				frappe.exceptions.InvalidDates,
+			)
 
 	def validate_parent_project_dates(self):
 		if not self.project or frappe.flags.in_test:
 			return
 
-		expected_end_date = frappe.db.get_value("Project", self.project, "expected_end_date")
-
-		if expected_end_date:
-			validate_project_dates(
-				getdate(expected_end_date), self, "exp_start_date", "exp_end_date", "Expected"
-			)
-			validate_project_dates(
-				getdate(expected_end_date), self, "act_start_date", "act_end_date", "Actual"
-			)
+		if project_end_date := frappe.db.get_value("Project", self.project, "expected_end_date"):
+			project_end_date = getdate(project_end_date)
+			for fieldname in ("exp_start_date", "exp_end_date", "act_start_date", "act_end_date"):
+				task_date = self.get(fieldname)
+				if task_date and date_diff(project_end_date, getdate(task_date)) < 0:
+					frappe.throw(
+						_("Task's {0} cannot be after Project's Expected End Date.").format(
+							_(self.meta.get_label(fieldname))
+						),
+						frappe.exceptions.InvalidDates,
+					)
 
 	def validate_status(self):
 		if self.is_template and self.status != "Template":
@@ -398,15 +384,3 @@
 
 def on_doctype_update():
 	frappe.db.add_index("Task", ["lft", "rgt"])
-
-
-def validate_project_dates(project_end_date, task, task_start, task_end, actual_or_expected_date):
-	if task.get(task_start) and date_diff(project_end_date, getdate(task.get(task_start))) < 0:
-		frappe.throw(
-			_("Task's {0} Start Date cannot be after Project's End Date.").format(actual_or_expected_date)
-		)
-
-	if task.get(task_end) and date_diff(project_end_date, getdate(task.get(task_end))) < 0:
-		frappe.throw(
-			_("Task's {0} End Date cannot be after Project's End Date.").format(actual_or_expected_date)
-		)
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index d0eb377..60c3356 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -6,7 +6,7 @@
 
 import frappe
 import frappe.defaults
-from frappe import _, msgprint
+from frappe import _, msgprint, qb
 from frappe.contacts.address_and_contact import (
 	delete_contact_and_address,
 	load_address_and_contact,
@@ -732,12 +732,15 @@
 @frappe.validate_and_sanitize_search_inputs
 def get_customer_primary_contact(doctype, txt, searchfield, start, page_len, filters):
 	customer = filters.get("customer")
-	return frappe.db.sql(
-		"""
-		select `tabContact`.name from `tabContact`, `tabDynamic Link`
-			where `tabContact`.name = `tabDynamic Link`.parent and `tabDynamic Link`.link_name = %(customer)s
-			and `tabDynamic Link`.link_doctype = 'Customer'
-			and `tabContact`.name like %(txt)s
-		""",
-		{"customer": customer, "txt": "%%%s%%" % txt},
+
+	con = qb.DocType("Contact")
+	dlink = qb.DocType("Dynamic Link")
+
+	return (
+		qb.from_(con)
+		.join(dlink)
+		.on(con.name == dlink.parent)
+		.select(con.name, con.full_name, con.email_id)
+		.where((dlink.link_name == customer) & (con.name.like(f"%{txt}%")))
+		.run()
 	)
diff --git a/erpnext/setup/doctype/employee/employee.py b/erpnext/setup/doctype/employee/employee.py
index 13a6f20..facefa3 100755
--- a/erpnext/setup/doctype/employee/employee.py
+++ b/erpnext/setup/doctype/employee/employee.py
@@ -145,33 +145,10 @@
 		if self.date_of_birth and getdate(self.date_of_birth) > getdate(today()):
 			throw(_("Date of Birth cannot be greater than today."))
 
-		if (
-			self.date_of_birth
-			and self.date_of_joining
-			and getdate(self.date_of_birth) >= getdate(self.date_of_joining)
-		):
-			throw(_("Date of Joining must be greater than Date of Birth"))
-
-		elif (
-			self.date_of_retirement
-			and self.date_of_joining
-			and (getdate(self.date_of_retirement) <= getdate(self.date_of_joining))
-		):
-			throw(_("Date Of Retirement must be greater than Date of Joining"))
-
-		elif (
-			self.relieving_date
-			and self.date_of_joining
-			and (getdate(self.relieving_date) < getdate(self.date_of_joining))
-		):
-			throw(_("Relieving Date must be greater than or equal to Date of Joining"))
-
-		elif (
-			self.contract_end_date
-			and self.date_of_joining
-			and (getdate(self.contract_end_date) <= getdate(self.date_of_joining))
-		):
-			throw(_("Contract End Date must be greater than Date of Joining"))
+		self.validate_from_to_dates("date_of_birth", "date_of_joining")
+		self.validate_from_to_dates("date_of_joining", "date_of_retirement")
+		self.validate_from_to_dates("date_of_joining", "relieving_date")
+		self.validate_from_to_dates("date_of_joining", "contract_end_date")
 
 	def validate_email(self):
 		if self.company_email:
diff --git a/erpnext/stock/doctype/packed_item/packed_item.py b/erpnext/stock/doctype/packed_item/packed_item.py
index 4d05d7a..d606751 100644
--- a/erpnext/stock/doctype/packed_item/packed_item.py
+++ b/erpnext/stock/doctype/packed_item/packed_item.py
@@ -48,7 +48,7 @@
 				update_packed_item_from_cancelled_doc(item_row, bundle_item, pi_row, doc)
 
 				if set_price_from_children:  # create/update bundle item wise price dict
-					update_product_bundle_rate(parent_items_price, pi_row)
+					update_product_bundle_rate(parent_items_price, pi_row, item_row)
 
 	if parent_items_price:
 		set_product_bundle_rate_amount(doc, parent_items_price)  # set price in bundle item
@@ -247,7 +247,7 @@
 	return prev_doc_packed_items_map
 
 
-def update_product_bundle_rate(parent_items_price, pi_row):
+def update_product_bundle_rate(parent_items_price, pi_row, item_row):
 	"""
 	Update the price dict of Product Bundles based on the rates of the Items in the bundle.
 
@@ -259,7 +259,7 @@
 	if not rate:
 		parent_items_price[key] = 0.0
 
-	parent_items_price[key] += flt(pi_row.rate)
+	parent_items_price[key] += flt((pi_row.rate * pi_row.qty) / item_row.stock_qty)
 
 
 def set_product_bundle_rate_amount(doc, parent_items_price):
diff --git a/erpnext/stock/doctype/packed_item/test_packed_item.py b/erpnext/stock/doctype/packed_item/test_packed_item.py
index ad7fd9a..ad06732 100644
--- a/erpnext/stock/doctype/packed_item/test_packed_item.py
+++ b/erpnext/stock/doctype/packed_item/test_packed_item.py
@@ -126,8 +126,8 @@
 		so.packed_items[1].rate = 200
 		so.save()
 
-		self.assertEqual(so.items[0].rate, 350)
-		self.assertEqual(so.items[0].amount, 700)
+		self.assertEqual(so.items[0].rate, 700)
+		self.assertEqual(so.items[0].amount, 1400)
 
 	def test_newly_mapped_doc_packed_items(self):
 		"Test impact on packed items in newly mapped DN from SO."
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 673fcb5..3739cb8 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -173,7 +173,9 @@
 		)
 
 		if (
-			cint(frappe.db.get_single_value("Buying Settings", "maintain_same_rate")) and not self.is_return
+			cint(frappe.db.get_single_value("Buying Settings", "maintain_same_rate"))
+			and not self.is_return
+			and not self.is_internal_supplier
 		):
 			self.validate_rate_with_reference_doc(
 				[["Purchase Order", "purchase_order", "purchase_order_item"]]
diff --git a/erpnext/stock/report/warehouse_wise_stock_balance/__init__.py b/erpnext/stock/report/warehouse_wise_stock_balance/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/stock/report/warehouse_wise_stock_balance/__init__.py
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
new file mode 100644
index 0000000..58a043e
--- /dev/null
+++ b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js
@@ -0,0 +1,20 @@
+// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Warehouse Wise Stock Balance"] = {
+	"filters": [
+		{
+			"fieldname":"company",
+			"label": __("Company"),
+			"fieldtype": "Link",
+			"options": "Company",
+			"reqd": 1,
+			"default": frappe.defaults.get_user_default("Company")
+		}
+	],
+	"initial_depth": 3,
+	"tree": true,
+	"parent_field": "parent_warehouse",
+	"name_field": "warehouse"
+};
diff --git a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.json b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.json
new file mode 100644
index 0000000..4f7ec65
--- /dev/null
+++ b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.json
@@ -0,0 +1,30 @@
+{
+ "add_total_row": 0,
+ "columns": [],
+ "creation": "2022-12-06 14:15:31.924345",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "json": "{}",
+ "modified": "2022-12-06 14:16:55.969214",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Warehouse Wise Stock Balance",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Stock Ledger Entry",
+ "report_name": "Warehouse Wise Stock Balance",
+ "report_type": "Script Report",
+ "roles": [
+  {
+   "role": "Stock User"
+  },
+  {
+   "role": "Accounts Manager"
+  }
+ ]
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..d364b57
--- /dev/null
+++ b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.py
@@ -0,0 +1,103 @@
+# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from typing import Any, Dict, List, Optional, TypedDict
+
+import frappe
+from frappe import _
+from frappe.query_builder.functions import Sum
+
+
+class StockBalanceFilter(TypedDict):
+	company: Optional[str]
+	warehouse: Optional[str]
+
+
+SLEntry = Dict[str, Any]
+
+
+def execute(filters=None):
+	columns, data = [], []
+	columns = get_columns()
+	data = get_data(filters)
+
+	return columns, data
+
+
+def get_warehouse_wise_balance(filters: StockBalanceFilter) -> List[SLEntry]:
+	sle = frappe.qb.DocType("Stock Ledger Entry")
+
+	query = (
+		frappe.qb.from_(sle)
+		.select(sle.warehouse, Sum(sle.stock_value_difference).as_("stock_balance"))
+		.where((sle.docstatus < 2) & (sle.is_cancelled == 0))
+		.groupby(sle.warehouse)
+	)
+
+	if filters.get("company"):
+		query = query.where(sle.company == filters.get("company"))
+
+	data = query.run(as_list=True)
+	return frappe._dict(data) if data else frappe._dict()
+
+
+def get_warehouses(report_filters: StockBalanceFilter):
+	return frappe.get_all(
+		"Warehouse",
+		fields=["name", "parent_warehouse", "is_group"],
+		filters={"company": report_filters.company},
+		order_by="lft",
+	)
+
+
+def get_data(filters: StockBalanceFilter):
+	warehouse_balance = get_warehouse_wise_balance(filters)
+	warehouses = get_warehouses(filters)
+
+	for warehouse in warehouses:
+		warehouse.stock_balance = warehouse_balance.get(warehouse.name, 0) or 0.0
+
+	update_indent(warehouses)
+	set_balance_in_parent(warehouses)
+
+	return warehouses
+
+
+def update_indent(warehouses):
+	for warehouse in warehouses:
+
+		def add_indent(warehouse, indent):
+			warehouse.indent = indent
+			for child in warehouses:
+				if child.parent_warehouse == warehouse.name:
+					add_indent(child, indent + 1)
+
+		if warehouse.is_group:
+			add_indent(warehouse, warehouse.indent or 0)
+
+
+def set_balance_in_parent(warehouses):
+	# sort warehouses by indent in descending order
+	warehouses = sorted(warehouses, key=lambda x: x.get("indent", 0), reverse=1)
+
+	for warehouse in warehouses:
+
+		def update_balance(warehouse, balance):
+			for parent in warehouses:
+				if warehouse.parent_warehouse == parent.name:
+					parent.stock_balance += balance
+
+		update_balance(warehouse, warehouse.stock_balance)
+
+
+def get_columns():
+	return [
+		{
+			"label": _("Warehouse"),
+			"fieldname": "name",
+			"fieldtype": "Link",
+			"options": "Warehouse",
+			"width": 200,
+		},
+		{"label": _("Stock Balance"), "fieldname": "stock_balance", "fieldtype": "Float", "width": 150},
+	]
diff --git a/erpnext/stock/workspace/stock/stock.json b/erpnext/stock/workspace/stock/stock.json
index ed33067..de5e6de 100644
--- a/erpnext/stock/workspace/stock/stock.json
+++ b/erpnext/stock/workspace/stock/stock.json
@@ -5,7 +5,7 @@
    "label": "Warehouse wise Stock Value"
   }
  ],
- "content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Stock\",\"col\":12}},{\"type\":\"chart\",\"data\":{\"chart_name\":\"Warehouse wise Stock Value\",\"col\":12}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Quick Access</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Material Request\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Entry\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Receipt\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Delivery Note\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Ledger\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Balance\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Masters & Reports</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Items and Pricing\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Stock Transactions\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Stock Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Serial No and Batch\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Tools\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Key Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Other Reports\",\"col\":4}}]",
+ "content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Stock\",\"col\":12}},{\"type\":\"chart\",\"data\":{\"chart_name\":\"Warehouse wise Stock Value\",\"col\":12}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Quick Access</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Material Request\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Entry\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Receipt\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Delivery Note\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Ledger\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Balance\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Masters &amp; Reports</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Items and Pricing\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Stock Transactions\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Stock Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Serial No and Batch\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Tools\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Key Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Other Reports\",\"col\":4}}]",
  "creation": "2020-03-02 15:43:10.096528",
  "docstatus": 0,
  "doctype": "Workspace",
@@ -210,80 +210,6 @@
   {
    "hidden": 0,
    "is_query_report": 0,
-   "label": "Stock Reports",
-   "link_count": 0,
-   "onboard": 0,
-   "type": "Card Break"
-  },
-  {
-   "dependencies": "Item",
-   "hidden": 0,
-   "is_query_report": 1,
-   "label": "Stock Ledger",
-   "link_count": 0,
-   "link_to": "Stock Ledger",
-   "link_type": "Report",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "dependencies": "Item",
-   "hidden": 0,
-   "is_query_report": 1,
-   "label": "Stock Balance",
-   "link_count": 0,
-   "link_to": "Stock Balance",
-   "link_type": "Report",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "dependencies": "Item",
-   "hidden": 0,
-   "is_query_report": 1,
-   "label": "Stock Projected Qty",
-   "link_count": 0,
-   "link_to": "Stock Projected Qty",
-   "link_type": "Report",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "dependencies": "Item",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Stock Summary",
-   "link_count": 0,
-   "link_to": "stock-balance",
-   "link_type": "Page",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "Item",
-   "hidden": 0,
-   "is_query_report": 1,
-   "label": "Stock Ageing",
-   "link_count": 0,
-   "link_to": "Stock Ageing",
-   "link_type": "Report",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "Item",
-   "hidden": 0,
-   "is_query_report": 1,
-   "label": "Item Price Stock",
-   "link_count": 0,
-   "link_to": "Item Price Stock",
-   "link_type": "Report",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
    "label": "Settings",
    "link_count": 0,
    "onboard": 0,
@@ -705,15 +631,100 @@
    "link_type": "Report",
    "onboard": 0,
    "type": "Link"
+  },
+  {
+   "hidden": 0,
+   "is_query_report": 0,
+   "label": "Stock Reports",
+   "link_count": 7,
+   "onboard": 0,
+   "type": "Card Break"
+  },
+  {
+   "dependencies": "Item",
+   "hidden": 0,
+   "is_query_report": 1,
+   "label": "Stock Ledger",
+   "link_count": 0,
+   "link_to": "Stock Ledger",
+   "link_type": "Report",
+   "onboard": 1,
+   "type": "Link"
+  },
+  {
+   "dependencies": "Item",
+   "hidden": 0,
+   "is_query_report": 1,
+   "label": "Stock Balance",
+   "link_count": 0,
+   "link_to": "Stock Balance",
+   "link_type": "Report",
+   "onboard": 1,
+   "type": "Link"
+  },
+  {
+   "dependencies": "Item",
+   "hidden": 0,
+   "is_query_report": 1,
+   "label": "Stock Projected Qty",
+   "link_count": 0,
+   "link_to": "Stock Projected Qty",
+   "link_type": "Report",
+   "onboard": 1,
+   "type": "Link"
+  },
+  {
+   "dependencies": "Item",
+   "hidden": 0,
+   "is_query_report": 0,
+   "label": "Stock Summary",
+   "link_count": 0,
+   "link_to": "stock-balance",
+   "link_type": "Page",
+   "onboard": 0,
+   "type": "Link"
+  },
+  {
+   "dependencies": "Item",
+   "hidden": 0,
+   "is_query_report": 1,
+   "label": "Stock Ageing",
+   "link_count": 0,
+   "link_to": "Stock Ageing",
+   "link_type": "Report",
+   "onboard": 0,
+   "type": "Link"
+  },
+  {
+   "dependencies": "Item",
+   "hidden": 0,
+   "is_query_report": 1,
+   "label": "Item Price Stock",
+   "link_count": 0,
+   "link_to": "Item Price Stock",
+   "link_type": "Report",
+   "onboard": 0,
+   "type": "Link"
+  },
+  {
+   "hidden": 0,
+   "is_query_report": 0,
+   "label": "Warehouse Wise Stock Balance",
+   "link_count": 0,
+   "link_to": "Warehouse Wise Stock Balance",
+   "link_type": "Report",
+   "onboard": 0,
+   "type": "Link"
   }
  ],
- "modified": "2022-01-13 17:47:38.339931",
+ "modified": "2022-12-06 17:03:56.397272",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock",
  "owner": "Administrator",
  "parent_page": "",
  "public": 1,
+ "quick_lists": [],
  "restrict_to_domain": "",
  "roles": [],
  "sequence_id": 24.0,
diff --git a/erpnext/translations/zh.csv b/erpnext/translations/zh.csv
index 716f1f2..d1f1b07 100644
--- a/erpnext/translations/zh.csv
+++ b/erpnext/translations/zh.csv
@@ -453,11 +453,11 @@
 Cancel the journal entry {0} first,首先取消日记条目{0},
 Canceled,取消,
 "Cannot Submit, Employees left to mark attendance",无法提交,不能为已离职员工登记考勤,
-Cannot be a fixed asset item as Stock Ledger is created.,不能成为股票分类账创建的固定资产项目。,
+Cannot be a fixed asset item as Stock Ledger is created.,不能成为库存分类账创建的固定资产项目。,
 Cannot cancel because submitted Stock Entry {0} exists,不能取消,因为提交的仓储记录{0}已经存在,
 Cannot cancel transaction for Completed Work Order.,无法取消已完成工单的交易。,
 Cannot cancel {0} {1} because Serial No {2} does not belong to the warehouse {3},无法取消{0} {1},因为序列号{2}不属于仓库{3},
-Cannot change Attributes after stock transaction. Make a new Item and transfer stock to the new Item,股票交易后不能更改属性。创建一个新项目并将库存转移到新项目,
+Cannot change Attributes after stock transaction. Make a new Item and transfer stock to the new Item,库存交易后不能更改属性。创建一个新项目并将库存转移到新项目,
 Cannot change Fiscal Year Start Date and Fiscal Year End Date once the Fiscal Year is saved.,财年保存后便不能更改财年开始日期和结束日期,
 Cannot change Service Stop Date for item in row {0},无法更改行{0}中项目的服务停止日期,
 Cannot change Variant properties after stock transaction. You will have to make a new Item to do this.,存货业务发生后不能更改变体物料的属性。需要新建新物料。,
@@ -2309,7 +2309,7 @@
 Received,收到,
 Received On,收到的,
 Received Quantity,收到的数量,
-Received Stock Entries,收到的股票条目,
+Received Stock Entries,收到的库存条目,
 Receiver List is empty. Please create Receiver List,接收人列表为空。请创建接收人列表,
 Recipients,收件人,
 Reconcile,核消(对帐),
@@ -2783,7 +2783,7 @@
 State/UT Tax,州/ UT税,
 Statement of Account,对账单,
 Status must be one of {0},状态必须是{0}中的一个,
-Stock,股票,
+Stock,库存,
 Stock Adjustment,库存调整,
 Stock Analytics,库存分析,
 Stock Assets,库存资产,
@@ -2963,7 +2963,7 @@
 The holiday on {0} is not between From Date and To Date,在{0}这个节日之间没有从日期和结束日期,
 The name of the institute for which you are setting up this system.,对于要为其建立这个系统的该机构的名称。,
 The name of your company for which you are setting up this system.,贵公司的名称,
-The number of shares and the share numbers are inconsistent,股份数量和股票数量不一致,
+The number of shares and the share numbers are inconsistent,股份数量和库存数量不一致,
 The payment gateway account in plan {0} is different from the payment gateway account in this payment request,计划{0}中的支付网关帐户与此付款请求中的支付网关帐户不同,
 The selected BOMs are not for the same item,所选物料清单不能用于同一个物料,
 The selected item cannot have Batch,所选物料不能有批次,
@@ -3514,7 +3514,7 @@
 Ageing Range 4,老化范围4,
 Allocated amount cannot be greater than unadjusted amount,分配的金额不能大于未调整的金额,
 Allocated amount cannot be negative,分配数量不能为负数,
-"Difference Account must be a Asset/Liability type account, since this Stock Entry is an Opening Entry",差异账户必须是资产/负债类型账户,因为此股票分录是开仓分录,
+"Difference Account must be a Asset/Liability type account, since this Stock Entry is an Opening Entry",差异账户必须是资产/负债类型账户,因为此库存分录是开仓分录,
 Error in some rows,某些行出错,
 Import Successful,导入成功,
 Please save first,请先保存,
@@ -3531,7 +3531,7 @@
 Invalid GSTIN! The input you've entered doesn't match the GSTIN format for UIN Holders or Non-Resident OIDAR Service Providers,GSTIN无效!您输入的输入与UIN持有人或非居民OIDAR服务提供商的GSTIN格式不符,
 Invoice Grand Total,发票总计,
 Last carbon check date cannot be a future date,最后的碳检查日期不能是未来的日期,
-Make Stock Entry,进入股票,
+Make Stock Entry,进入库存,
 Quality Feedback,质量反馈,
 Quality Feedback Template,质量反馈模板,
 Rules for applying different promotional schemes.,适用不同促销计划的规则。,
@@ -3626,7 +3626,7 @@
 BOM Comparison Tool,BOM比较工具,
 BOM recursion: {0} cannot be child of {1},BOM递归:{0}不能是{1}的子代,
 BOM recursion: {0} cannot be parent or child of {1},BOM递归:{0}不能是{1}的父级或子级,
-Back to Home,回到家,
+Back to Home,回到主页,
 Back to Messages,回到消息,
 Bank Data mapper doesn't exist,银行数据映射器不存在,
 Bank Details,银行明细,
@@ -3786,7 +3786,7 @@
 Help Article,帮助文章,
 "Helps you keep tracks of Contracts based on Supplier, Customer and Employee",帮助您根据供应商,客户和员工记录合同,
 Helps you manage appointments with your leads,帮助您管理潜在客户的约会,
-Home,家,
+Home,主页,
 IBAN is not valid,IBAN无效,
 Import Data from CSV / Excel files.,从CSV / Excel文件导入数据。,
 In Progress,进行中,
@@ -4064,8 +4064,8 @@
 Status,状态,
 Status must be Cancelled or Completed,状态必须已取消或已完成,
 Stock Balance Report,库存余额报告,
-Stock Entry has been already created against this Pick List,已经根据此选择列表创建了股票输入,
-Stock Ledger ID,股票分类帐编号,
+Stock Entry has been already created against this Pick List,已经根据此选择列表创建了库存输入,
+Stock Ledger ID,库存分类帐编号,
 Stock Value ({0}) and Account Balance ({1}) are out of sync for account {2} and it's linked warehouses.,库存值({0})和帐户余额({1})与帐户{2}及其链接的仓库不同步。,
 Stores - {0},商店-{0},
 Student with email {0} does not exist,电子邮件{0}的学生不存在,
@@ -6127,7 +6127,7 @@
 Procedure Prescription,程序处方,
 Service Unit,服务单位,
 Consumables,耗材,
-Consume Stock,消费股票,
+Consume Stock,消费库存,
 Invoice Consumables Separately,发票耗材分开,
 Consumption Invoiced,消费发票,
 Consumable Total Amount,耗材总量,
@@ -8285,8 +8285,8 @@
 Warranty Period (Days),保修期限(天数),
 Serial No Details,序列号信息,
 MAT-STE-.YYYY.-,MAT-STE-.YYYY.-,
-Stock Entry Type,股票进入类型,
-Stock Entry (Outward GIT),股票进入(外向GIT),
+Stock Entry Type,库存进入类型,
+Stock Entry (Outward GIT),库存进入(外向GIT),
 Material Consumption for Manufacture,生产所需的材料消耗,
 Repack,包装,
 Send to Subcontractor,发送给分包商,
@@ -8318,8 +8318,8 @@
 BOM No. for a Finished Good Item,成品物料的物料清单编号,
 Material Request used to make this Stock Entry,创建此手工库存移动的材料申请,
 Subcontracted Item,外包物料,
-Against Stock Entry,反对股票进入,
-Stock Entry Child,股票入境儿童,
+Against Stock Entry,反对库存进入,
+Stock Entry Child,库存入境儿童,
 PO Supplied Item,PO提供的物品,
 Reference Purchase Receipt,参考购买收据,
 Stock Ledger Entry,库存分类帐分录,
@@ -8571,7 +8571,7 @@
 Serial No Status,序列号状态,
 Serial No Warranty Expiry,序列号/保修到期,
 Stock Ageing,库存账龄,
-Stock and Account Value Comparison,股票和账户价值比较,
+Stock and Account Value Comparison,库存和账户价值比较,
 Stock Projected Qty,预期可用库存,
 Student and Guardian Contact Details,学生和监护人联系方式,
 Student Batch-Wise Attendance,学生按批考勤,
@@ -9655,7 +9655,7 @@
 Notify by Email on Creation of Automatic Material Request,通过电子邮件通知创建自动物料请求,
 Allow Material Transfer from Delivery Note to Sales Invoice,允许物料从交货单转移到销售发票,
 Allow Material Transfer from Purchase Receipt to Purchase Invoice,允许从收货到采购发票的物料转移,
-Freeze Stocks Older Than (Days),冻结大于(天)的股票,
+Freeze Stocks Older Than (Days),冻结大于(天)的库存,
 Role Allowed to Edit Frozen Stock,允许角色编辑冻结库存,
 The unallocated amount of Payment Entry {0} is greater than the Bank Transaction's unallocated amount,付款条目{0}的未分配金额大于银行交易的未分配金额,
 Payment Received,已收到付款,
@@ -9698,7 +9698,7 @@
 Item {0} {1},项目{0} {1},
 Last Stock Transaction for item {0} under warehouse {1} was on {2}.,仓库{1}下项目{0}的上次库存交易在{2}上。,
 Stock Transactions for Item {0} under warehouse {1} cannot be posted before this time.,在此之前,不能过帐仓库{1}下物料{0}的库存交易。,
-Posting future stock transactions are not allowed due to Immutable Ledger,由于总帐不可变,不允许过帐未来的股票交易,
+Posting future stock transactions are not allowed due to Immutable Ledger,由于总帐不可变,不允许过帐未来的库存交易,
 A BOM with name {0} already exists for item {1}.,项目{1}的名称为{0}的BOM已存在。,
 {0}{1} Did you rename the item? Please contact Administrator / Tech support,{0} {1}您是否重命名了该项目?请联系管理员/技术支持,
 At row #{0}: the sequence id {1} cannot be less than previous row sequence id {2},在第{0}行:序列ID {1}不能小于上一行的序列ID {2},