refactor: Reposting utility of Stock ledger (#19155)

diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index bc2ddff..bc9c178 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -364,7 +364,7 @@
 			update_outstanding = "No" if (cint(self.is_paid) or self.write_off_account) else "Yes"
 
 			make_gl_entries(gl_entries,  cancel=(self.docstatus == 2),
-				update_outstanding=update_outstanding, merge_entries=False)
+				update_outstanding=update_outstanding, merge_entries=False, from_repost=from_repost)
 
 			if update_outstanding == "No":
 				update_outstanding_amt(self.credit_to, "Supplier", self.supplier,
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index abbac77..e1256a7 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -698,7 +698,7 @@
 				cint(self.redeem_loyalty_points)) else "Yes"
 
 			make_gl_entries(gl_entries, cancel=(self.docstatus == 2),
-				update_outstanding=update_outstanding, merge_entries=False)
+				update_outstanding=update_outstanding, merge_entries=False, from_repost=from_repost)
 
 			if update_outstanding == "No":
 				from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
diff --git a/erpnext/stock/stock_balance.py b/erpnext/stock/stock_balance.py
index d68f979..e5dc6b1 100644
--- a/erpnext/stock/stock_balance.py
+++ b/erpnext/stock/stock_balance.py
@@ -3,10 +3,10 @@
 
 from __future__ import print_function, unicode_literals
 import frappe
-
 from frappe.utils import flt, cstr, nowdate, nowtime
 from erpnext.stock.utils import update_bin
 from erpnext.stock.stock_ledger import update_entries_after
+from erpnext.controllers.stock_controller import update_gl_entries_after
 
 def repost(only_actual=False, allow_negative_stock=False, allow_zero_rate=False, only_bin=False):
 	"""
@@ -18,23 +18,29 @@
 		existing_allow_negative_stock = frappe.db.get_value("Stock Settings", None, "allow_negative_stock")
 		frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
 
-	for d in frappe.db.sql("""select distinct item_code, warehouse from
-		(select item_code, warehouse from tabBin
-		union
-		select item_code, warehouse from `tabStock Ledger Entry`) a"""):
-			try:
-				repost_stock(d[0], d[1], allow_zero_rate, only_actual, only_bin)
-				frappe.db.commit()
-			except:
-				frappe.db.rollback()
+	item_warehouses = frappe.db.sql("""
+		select distinct item_code, warehouse
+		from
+			(select item_code, warehouse from tabBin
+			union
+			select item_code, warehouse from `tabStock Ledger Entry`) a
+	""")
+	for d in item_warehouses:
+		try:
+			repost_stock(d[0], d[1], allow_zero_rate, only_actual, only_bin, allow_negative_stock)
+			frappe.db.commit()
+		except:
+			frappe.db.rollback()
 
 	if allow_negative_stock:
 		frappe.db.set_value("Stock Settings", None, "allow_negative_stock", existing_allow_negative_stock)
 	frappe.db.auto_commit_on_many_writes = 0
 
-def repost_stock(item_code, warehouse, allow_zero_rate=False, only_actual=False, only_bin=False):
+def repost_stock(item_code, warehouse, allow_zero_rate=False,
+	only_actual=False, only_bin=False, allow_negative_stock=False):
+
 	if not only_bin:
-		repost_actual_qty(item_code, warehouse, allow_zero_rate)
+		repost_actual_qty(item_code, warehouse, allow_zero_rate, allow_negative_stock)
 
 	if item_code and warehouse and not only_actual:
 		qty_dict = {
@@ -50,11 +56,8 @@
 
 		update_bin_qty(item_code, warehouse, qty_dict)
 
-def repost_actual_qty(item_code, warehouse, allow_zero_rate=False):
-	try:
-		update_entries_after({ "item_code": item_code, "warehouse": warehouse }, allow_zero_rate)
-	except:
-		pass
+def repost_actual_qty(item_code, warehouse, allow_zero_rate=False, allow_negative_stock=False):		update_entries_after({ "item_code": item_code, "warehouse": warehouse },
+		allow_zero_rate=allow_zero_rate, allow_negative_stock=allow_negative_stock)
 
 def get_balance_qty_from_sle(item_code, warehouse):
 	balance_qty = frappe.db.sql("""select qty_after_transaction from `tabStock Ledger Entry`
@@ -227,39 +230,14 @@
 			except:
 				pass
 
-def repost_all_stock_vouchers():
-	warehouses_with_account = frappe.db.sql_list("""select warehouse from tabAccount
-		where ifnull(account_type, '') = 'Stock' and (warehouse is not null and warehouse != '')
-		and is_group=0""")
+def repost_gle_for_stock_transactions(posting_date=None, posting_time=None, for_warehouses=None):
+	frappe.db.auto_commit_on_many_writes = 1
 
-	vouchers = frappe.db.sql("""select distinct voucher_type, voucher_no
-		from `tabStock Ledger Entry` sle
-		where voucher_type != "Serial No" and sle.warehouse in (%s)
-		order by posting_date, posting_time, creation""" %
-		', '.join(['%s']*len(warehouses_with_account)), tuple(warehouses_with_account))
+	if not posting_date:
+		posting_date = "1900-01-01"
+	if not posting_time:
+		posting_time = "00:00"
 
-	rejected = []
-	i = 0
-	for voucher_type, voucher_no in vouchers:
-		i+=1
-		print(i, "/", len(vouchers), voucher_type, voucher_no)
-		try:
-			for dt in ["Stock Ledger Entry", "GL Entry"]:
-				frappe.db.sql("""delete from `tab%s` where voucher_type=%s and voucher_no=%s"""%
-					(dt, '%s', '%s'), (voucher_type, voucher_no))
+	update_gl_entries_after(posting_date, posting_time, for_warehouses=for_warehouses)
 
-			doc = frappe.get_doc(voucher_type, voucher_no)
-			if voucher_type=="Stock Entry" and doc.purpose in ["Manufacture", "Repack"]:
-				doc.calculate_rate_and_amount(force=1)
-			elif voucher_type=="Purchase Receipt" and doc.is_subcontracted == "Yes":
-				doc.validate()
-
-			doc.update_stock_ledger()
-			doc.make_gl_entries(repost_future_gle=False)
-			frappe.db.commit()
-		except Exception:
-			print(frappe.get_traceback())
-			rejected.append([voucher_type, voucher_no])
-			frappe.db.rollback()
-
-	print(rejected)
+	frappe.db.auto_commit_on_many_writes = 0