fix: dont fail repost for recoverable errors (#30979)

recoverable erros:
1. timeout
2. lock/deadlocks
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 06229bb..4d9a7e0 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -367,7 +367,8 @@
 erpnext.patches.v13_0.create_gst_custom_fields_in_quotation
 erpnext.patches.v13_0.copy_custom_field_filters_to_website_item
 erpnext.patches.v13_0.change_default_item_manufacturer_fieldtype
+erpnext.patches.v13_0.requeue_recoverable_reposts
 erpnext.patches.v14_0.discount_accounting_separation
 erpnext.patches.v14_0.delete_employee_transfer_property_doctype
 erpnext.patches.v13_0.create_accounting_dimensions_in_orders
-erpnext.patches.v13_0.set_per_billed_in_return_delivery_note
\ No newline at end of file
+erpnext.patches.v13_0.set_per_billed_in_return_delivery_note
diff --git a/erpnext/patches/v13_0/requeue_recoverable_reposts.py b/erpnext/patches/v13_0/requeue_recoverable_reposts.py
new file mode 100644
index 0000000..f37c21c
--- /dev/null
+++ b/erpnext/patches/v13_0/requeue_recoverable_reposts.py
@@ -0,0 +1,21 @@
+import frappe
+
+
+def execute():
+	recoverable = ("QueryDeadlockError", "QueryTimeoutError", "JobTimeoutException")
+
+	failed_reposts = frappe.get_all(
+		"Repost Item Valuation",
+		fields=["name", "error_log"],
+		filters={
+			"status": "Failed",
+			"docstatus": 1,
+			"modified": (">", "2022-04-20"),
+			"error_log": ("is", "set"),
+		},
+	)
+	for riv in failed_reposts:
+		for exc in recoverable:
+			if exc in riv.error_log:
+				frappe.db.set_value("Repost Item Valuation", riv.name, "status", "Queued")
+				break
diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
index 236b944..328afc8 100644
--- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
+++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
@@ -3,9 +3,11 @@
 
 import frappe
 from frappe import _
+from frappe.exceptions import QueryDeadlockError, QueryTimeoutError
 from frappe.model.document import Document
 from frappe.utils import cint, get_link_to_form, get_weekday, now, nowtime
 from frappe.utils.user import get_users_with_role
+from rq.timeouts import JobTimeoutException
 
 import erpnext
 from erpnext.accounts.utils import get_future_stock_vouchers, repost_gle_for_stock_vouchers
@@ -15,6 +17,8 @@
 	repost_future_sle,
 )
 
+RecoverableErrors = (JobTimeoutException, QueryDeadlockError, QueryTimeoutError)
+
 
 class RepostItemValuation(Document):
 	def validate(self):
@@ -132,7 +136,7 @@
 
 		doc.set_status("Completed")
 
-	except Exception:
+	except Exception as e:
 		frappe.db.rollback()
 		traceback = frappe.get_traceback()
 		doc.log_error("Unable to repost item valuation")
@@ -142,9 +146,9 @@
 			message += "<br>" + "Traceback: <br>" + traceback
 		frappe.db.set_value(doc.doctype, doc.name, "error_log", message)
 
-		notify_error_to_stock_managers(doc, message)
-		doc.set_status("Failed")
-		raise
+		if not isinstance(e, RecoverableErrors):
+			notify_error_to_stock_managers(doc, message)
+			doc.set_status("Failed")
 	finally:
 		if not frappe.flags.in_test:
 			frappe.db.commit()