Merge branch 'develop' into PACKING-SLIP-FOR-DN-PACKED-ITEMS
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index e158df6..7e68ec1 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -326,7 +326,7 @@
 erpnext.patches.v15_0.update_asset_value_for_manual_depr_entries
 erpnext.patches.v15_0.update_gpa_and_ndb_for_assdeprsch
 erpnext.patches.v14_0.create_accounting_dimensions_for_closing_balance
-erpnext.patches.v14_0.update_closing_balances #10-05-2023
+erpnext.patches.v14_0.update_closing_balances #17-05-2023
 execute:frappe.db.set_single_value("Accounts Settings", "merge_similar_account_heads", 0)
 # below migration patches should always run last
 erpnext.patches.v14_0.migrate_gl_to_payment_ledger
diff --git a/erpnext/patches/v14_0/update_closing_balances.py b/erpnext/patches/v14_0/update_closing_balances.py
index bb108ab..d664677 100644
--- a/erpnext/patches/v14_0/update_closing_balances.py
+++ b/erpnext/patches/v14_0/update_closing_balances.py
@@ -13,8 +13,8 @@
 def execute():
 	frappe.db.truncate("Account Closing Balance")
 
+	i = 0
 	company_wise_order = {}
-	get_opening_entries = True
 	for pcv in frappe.db.get_all(
 		"Period Closing Voucher",
 		fields=["company", "posting_date", "name"],
@@ -29,6 +29,7 @@
 				pcv.posting_date, pcv.fiscal_year, company=pcv.company
 			)[1]
 
+			# get gl entries against pcv
 			gl_entries = frappe.db.get_all(
 				"GL Entry", filters={"voucher_no": pcv.name, "is_cancelled": 0}, fields=["*"]
 			)
@@ -37,20 +38,31 @@
 				entry["closing_date"] = pcv_doc.posting_date
 				entry["period_closing_voucher"] = pcv_doc.name
 
+			# get all gl entries for the year
 			closing_entries = frappe.db.get_all(
 				"GL Entry",
 				filters={
 					"is_cancelled": 0,
 					"voucher_no": ["!=", pcv.name],
-					"posting_date": ["<=", pcv.posting_date],
+					"posting_date": ["between", [pcv_doc.year_start_date, pcv.posting_date]],
+					"is_opening": "No",
 				},
 				fields=["*"],
 			)
 
+			if i == 0:
+				# add opening entries only for the first pcv
+				closing_entries += frappe.db.get_all(
+					"GL Entry",
+					filters={"is_cancelled": 0, "is_opening": "Yes"},
+					fields=["*"],
+				)
+
 			for entry in closing_entries:
 				entry["closing_date"] = pcv_doc.posting_date
 				entry["period_closing_voucher"] = pcv_doc.name
 
 			make_closing_entries(gl_entries + closing_entries, voucher_name=pcv.name)
 			company_wise_order[pcv.company].append(pcv.posting_date)
-			get_opening_entries = False
+
+			i += 1
diff --git a/erpnext/setup/module_onboarding/home/home.json b/erpnext/setup/module_onboarding/home/home.json
index 516f122..1fd9679 100644
--- a/erpnext/setup/module_onboarding/home/home.json
+++ b/erpnext/setup/module_onboarding/home/home.json
@@ -25,16 +25,13 @@
  "documentation_url": "https://docs.erpnext.com/docs/v14/user/manual/en/setting-up/company-setup",
  "idx": 0,
  "is_complete": 0,
- "modified": "2023-05-16 13:13:24.043792",
+ "modified": "2023-05-20 19:45:03.936741",
  "modified_by": "Administrator",
  "module": "Setup",
  "name": "Home",
  "owner": "Administrator",
  "steps": [
   {
-   "step": "Navigation Help"
-  },
-  {
    "step": "Create an Item"
   },
   {
@@ -47,7 +44,7 @@
    "step": "Create a Quotation"
   }
  ],
- "subtitle": "Item, Customer, Supplier, Navigation Help and Quotation",
+ "subtitle": "Item, Customer, Supplier and Quotation",
  "success_message": "You're ready to start your journey with ERPNext",
  "title": "Let's begin your journey with ERPNext"
 }
\ No newline at end of file
diff --git a/erpnext/setup/onboarding_step/create_a_customer/create_a_customer.json b/erpnext/setup/onboarding_step/create_a_customer/create_a_customer.json
index e1a8f90..5b0fd41 100644
--- a/erpnext/setup/onboarding_step/create_a_customer/create_a_customer.json
+++ b/erpnext/setup/onboarding_step/create_a_customer/create_a_customer.json
@@ -9,7 +9,7 @@
  "is_complete": 0,
  "is_single": 0,
  "is_skipped": 0,
- "modified": "2023-05-16 12:54:54.112364",
+ "modified": "2023-05-16 20:01:34.202622",
  "modified_by": "Administrator",
  "name": "Create a Customer",
  "owner": "Administrator",
diff --git a/erpnext/setup/onboarding_step/create_a_supplier/create_a_supplier.json b/erpnext/setup/onboarding_step/create_a_supplier/create_a_supplier.json
index ef493fe..4ac26e2 100644
--- a/erpnext/setup/onboarding_step/create_a_supplier/create_a_supplier.json
+++ b/erpnext/setup/onboarding_step/create_a_supplier/create_a_supplier.json
@@ -9,7 +9,7 @@
  "is_complete": 0,
  "is_single": 0,
  "is_skipped": 0,
- "modified": "2023-05-16 12:55:08.610113",
+ "modified": "2023-05-19 15:32:55.069257",
  "modified_by": "Administrator",
  "name": "Create a Supplier",
  "owner": "Administrator",
diff --git a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.js b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.js
index 7a170be..50a78a8 100644
--- a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.js
+++ b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.js
@@ -33,5 +33,40 @@
 			"fieldtype": "Date",
 			"default": frappe.datetime.get_today(),
 		},
-	]
+	],
+
+	get_datatable_options(options) {
+		return Object.assign(options, {
+			checkboxColumn: true,
+		});
+	},
+
+	onload(report) {
+		report.page.add_inner_button(__("Create Reposting Entries"), function() {
+			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>
+			`;
+
+			frappe.confirm(__(message), () => {
+				let indexes = frappe.query_report.datatable.rowmanager.getCheckedRows();
+				let selected_rows = indexes.map(i => frappe.query_report.data[i]);
+
+				frappe.call({
+					method: "erpnext.stock.report.stock_and_account_value_comparison.stock_and_account_value_comparison.create_reposting_entries",
+					args: {
+						rows: selected_rows,
+						company: frappe.query_report.get_filter_values().company
+					}
+				});
+
+			});
+		});
+	}
 };
diff --git a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py
index 106e877..b1da3ec 100644
--- a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py
+++ b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py
@@ -4,6 +4,7 @@
 
 import frappe
 from frappe import _
+from frappe.utils import get_link_to_form, parse_json
 
 import erpnext
 from erpnext.accounts.utils import get_currency_precision, get_stock_accounts
@@ -134,3 +135,35 @@
 			"width": "120",
 		},
 	]
+
+
+@frappe.whitelist()
+def create_reposting_entries(rows, company):
+	if isinstance(rows, str):
+		rows = parse_json(rows)
+
+	entries = []
+	for row in rows:
+		row = frappe._dict(row)
+
+		try:
+			doc = frappe.get_doc(
+				{
+					"doctype": "Repost Item Valuation",
+					"based_on": "Transaction",
+					"status": "Queued",
+					"voucher_type": row.voucher_type,
+					"voucher_no": row.voucher_no,
+					"posting_date": row.posting_date,
+					"company": company,
+					"allow_nagative_stock": 1,
+				}
+			).submit()
+
+			entries.append(get_link_to_form("Repost Item Valuation", doc.name))
+		except frappe.DuplicateEntryError:
+			pass
+
+	if entries:
+		entries = ", ".join(entries)
+		frappe.msgprint(_(f"Reposting entries created: {entries}"))
diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py
index fb52697..10654dd 100644
--- a/erpnext/stock/utils.py
+++ b/erpnext/stock/utils.py
@@ -256,8 +256,6 @@
 	if isinstance(args, str):
 		args = json.loads(args)
 
-	voucher_no = args.get("voucher_no") or args.get("name")
-
 	in_rate = None
 	if (args.get("serial_no") or "").strip():
 		in_rate = get_avg_purchase_rate(args.get("serial_no"))
@@ -280,12 +278,13 @@
 				in_rate = (
 					_get_fifo_lifo_rate(previous_stock_queue, args.get("qty") or 0, valuation_method)
 					if previous_stock_queue
-					else 0
+					else None
 				)
 		elif valuation_method == "Moving Average":
-			in_rate = previous_sle.get("valuation_rate") or 0
+			in_rate = previous_sle.get("valuation_rate")
 
 	if in_rate is None:
+		voucher_no = args.get("voucher_no") or args.get("name")
 		in_rate = get_valuation_rate(
 			args.get("item_code"),
 			args.get("warehouse"),