feat: utility to repost accounting ledgers without cancellation (#36469)

* feat: introduce doctypes for repost

* refactor: basic filters and validations

* chore: basic validations

* chore: added barebones function to generate ledger entries

* chore: repost on submit

* chore: repost in background

* chore: include payment entry and journal entry

* chore: ignore repost doc on cancel

* chore: preview method

* chore: rudimentary form of preview

* refactor: preview template

* refactor: basic background colors to differentiate old and new

* chore: remove commented code

* test: basic functionality

* chore: fix conflict

* chore: prevent repost on invoices with deferred accounting

* refactor(test): rename and test basic validations and methods

* refactor(test): test all validations

* fix(test): use proper name account name

* refactor(test): fix failing test case

* refactor(test): clear old entries

* refactor(test): simpler logic to clear old records

* refactor(test): make use of deletion flag

* refactor(test): split into multiple test cases
diff --git a/erpnext/accounts/test/accounts_mixin.py b/erpnext/accounts/test/accounts_mixin.py
index c82164e..70bbf7e 100644
--- a/erpnext/accounts/test/accounts_mixin.py
+++ b/erpnext/accounts/test/accounts_mixin.py
@@ -4,7 +4,7 @@
 
 
 class AccountsTestMixin:
-	def create_customer(self, customer_name, currency=None):
+	def create_customer(self, customer_name="_Test Customer", currency=None):
 		if not frappe.db.exists("Customer", customer_name):
 			customer = frappe.new_doc("Customer")
 			customer.customer_name = customer_name
@@ -17,7 +17,7 @@
 		else:
 			self.customer = customer_name
 
-	def create_supplier(self, supplier_name, currency=None):
+	def create_supplier(self, supplier_name="_Test Supplier", currency=None):
 		if not frappe.db.exists("Supplier", supplier_name):
 			supplier = frappe.new_doc("Supplier")
 			supplier.supplier_name = supplier_name
@@ -31,7 +31,7 @@
 		else:
 			self.supplier = supplier_name
 
-	def create_item(self, item_name, is_stock=0, warehouse=None, company=None):
+	def create_item(self, item_name="_Test Item", is_stock=0, warehouse=None, company=None):
 		item = create_item(item_name, is_stock_item=is_stock, warehouse=warehouse, company=company)
 		self.item = item.name
 
@@ -62,19 +62,44 @@
 		self.debit_usd = "Debtors USD - " + abbr
 		self.cash = "Cash - " + abbr
 		self.creditors = "Creditors - " + abbr
+		self.retained_earnings = "Retained Earnings - " + abbr
 
-		# create bank account
-		bank_account = "HDFC - " + abbr
-		if frappe.db.exists("Account", bank_account):
-			self.bank = bank_account
-		else:
-			bank_acc = frappe.get_doc(
+		# Deferred revenue, expense and bank accounts
+		other_accounts = [
+			frappe._dict(
 				{
-					"doctype": "Account",
+					"attribute_name": "deferred_revenue",
+					"account_name": "Deferred Revenue",
+					"parent_account": "Current Liabilities - " + abbr,
+				}
+			),
+			frappe._dict(
+				{
+					"attribute_name": "deferred_expense",
+					"account_name": "Deferred Expense",
+					"parent_account": "Current Assets - " + abbr,
+				}
+			),
+			frappe._dict(
+				{
+					"attribute_name": "bank",
 					"account_name": "HDFC",
 					"parent_account": "Bank Accounts - " + abbr,
-					"company": self.company,
 				}
-			)
-			bank_acc.save()
-			self.bank = bank_acc.name
+			),
+		]
+		for acc in other_accounts:
+			acc_name = acc.account_name + " - " + abbr
+			if frappe.db.exists("Account", acc_name):
+				setattr(self, acc.attribute_name, acc_name)
+			else:
+				new_acc = frappe.get_doc(
+					{
+						"doctype": "Account",
+						"account_name": acc.account_name,
+						"parent_account": acc.parent_account,
+						"company": self.company,
+					}
+				)
+				new_acc.save()
+				setattr(self, acc.attribute_name, new_acc.name)