feat: provision to create RIV from `Stock Ledger Invariant Check` report (#37115)

* feat: provision to create RIV from `Stock Ledger Invariant Check` report

* fix: `linter`
diff --git a/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.js b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.js
index 3447e0a..36e91e3 100644
--- a/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.js
+++ b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.js
@@ -3,23 +3,23 @@
 
 
 const DIFFERNCE_FIELD_NAMES = [
-	"difference_in_qty",
-	"fifo_qty_diff",
-	"fifo_value_diff",
-	"fifo_valuation_diff",
-	"valuation_diff",
-	"fifo_difference_diff",
-	"diff_value_diff"
+	'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 Invariant Check"] = {
-	"filters": [
+frappe.query_reports['Stock Ledger Invariant Check'] = {
+	'filters': [
 		{
-			"fieldname": "item_code",
-			"fieldtype": "Link",
-			"label": "Item",
-			"mandatory": 1,
-			"options": "Item",
+			'fieldname': 'item_code',
+			'fieldtype': 'Link',
+			'label': 'Item',
+			'mandatory': 1,
+			'options': 'Item',
 			get_query: function() {
 				return {
 					filters: {is_stock_item: 1, has_serial_no: 0}
@@ -27,18 +27,61 @@
 			}
 		},
 		{
-			"fieldname": "warehouse",
-			"fieldtype": "Link",
-			"label": "Warehouse",
-			"mandatory": 1,
-			"options": "Warehouse",
+			'fieldname': 'warehouse',
+			'fieldtype': 'Link',
+			'label': 'Warehouse',
+			'mandatory': 1,
+			'options': 'Warehouse',
 		}
 	],
+
 	formatter (value, row, column, data, default_formatter) {
 		value = default_formatter(value, row, column, data);
 		if (DIFFERNCE_FIELD_NAMES.includes(column.fieldname) && Math.abs(data[column.fieldname]) > 0.001) {
-			value = "<span style='color:red'>" + value + "</span>";
+			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 Entry'), () => {
+			let message = `
+				<div>
+					<p>
+						Reposting Entry 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 a Reposting Entry?</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 a row to create a Reposting Entry'));
+			}
+			else if (selected_rows.length > 1) {
+				frappe.throw(__('Please select only one row to create a Reposting Entry'));
+			}
+			else {
+				frappe.confirm(__(message), () => {
+					frappe.call({
+						method: 'erpnext.stock.report.stock_ledger_invariant_check.stock_ledger_invariant_check.create_reposting_entries',
+						args: {
+							rows: selected_rows,
+							item_code: frappe.query_report.get_filter_values().item_code,
+							warehouse: frappe.query_report.get_filter_values().warehouse,
+						}
+					});
+				});
+			}
+		});
+	},
 };
diff --git a/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.py b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.py
index ed0e2fc..e11c9bb 100644
--- a/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.py
+++ b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.py
@@ -5,6 +5,7 @@
 
 import frappe
 from frappe import _
+from frappe.utils import get_link_to_form, parse_json
 
 SLE_FIELDS = (
 	"name",
@@ -258,3 +259,35 @@
 			"label": _("H - J"),
 		},
 	]
+
+
+@frappe.whitelist()
+def create_reposting_entries(rows, item_code=None, warehouse=None):
+	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": "Item and Warehouse",
+					"status": "Queued",
+					"item_code": item_code or row.item_code,
+					"warehouse": warehouse or row.warehouse,
+					"posting_date": row.posting_date,
+					"posting_time": row.posting_time,
+					"allow_nagative_stock": 1,
+				}
+			).submit()
+
+			entries.append(get_link_to_form("Repost Item Valuation", doc.name))
+		except frappe.DuplicateEntryError:
+			continue
+
+	if entries:
+		entries = ", ".join(entries)
+		frappe.msgprint(_("Reposting entries created: {0}").format(entries))