refactor: use flags to decide on current stage
diff --git a/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js b/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js
index 671f927..1a8b52f 100644
--- a/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js
+++ b/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js
@@ -16,9 +16,15 @@
});
}
- frm.get_field("doctypes_to_be_ignored").grid.cannot_add_rows = true;
- frm.fields_dict["doctypes_to_be_ignored"].grid.set_column_disp("no_of_docs", false);
- frm.refresh_field("doctypes_to_be_ignored");
+
+ frm.get_field('doctypes_to_be_ignored').grid.cannot_add_rows = true;
+ frm.fields_dict['doctypes_to_be_ignored'].grid.set_column_disp('no_of_docs', false);
+ frm.fields_dict['doctypes_to_be_ignored'].grid.set_column_disp('done', false);
+ frm.refresh_field('doctypes_to_be_ignored');
+
+ frm.get_field('doctypes').grid.cannot_add_rows = true;
+ frm.fields_dict['doctypes'].grid.set_column_disp('no_of_docs', true);
+ frm.refresh_field('doctypes');
},
refresh: function (frm) {
diff --git a/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.json b/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.json
index a9e04d3..6a84841 100644
--- a/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.json
+++ b/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.json
@@ -15,6 +15,7 @@
"reset_company_default_values",
"clear_notifications",
"delete_transactions",
+ "initialize_doctypes_table",
"section_break_tbej",
"doctypes",
"doctypes_to_be_ignored",
@@ -110,12 +111,19 @@
"label": "Delete Transactions",
"no_copy": 1,
"read_only": 1
+ },
+ {
+ "default": "0",
+ "fieldname": "initialize_doctypes_table",
+ "fieldtype": "Check",
+ "label": "Initialize Summary Table",
+ "read_only": 1
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2024-02-03 14:40:40.207482",
+ "modified": "2024-02-03 20:48:34.107577",
"modified_by": "Administrator",
"module": "Setup",
"name": "Transaction Deletion Record",
diff --git a/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py b/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py
index f1f6a5b..5a5a827 100644
--- a/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py
+++ b/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py
@@ -30,6 +30,7 @@
delete_transactions: DF.Check
doctypes: DF.Table[TransactionDeletionRecordItem]
doctypes_to_be_ignored: DF.Table[TransactionDeletionRecordItem]
+ initialize_doctypes_table: DF.Check
reset_company_default_values: DF.Check
status: DF.Literal["Queued", "Running", "Failed", "Completed", "Cancelled"]
# end: auto-generated types
@@ -79,8 +80,10 @@
self.delete_bins()
self.delete_lead_addresses()
self.reset_company_values()
- clear_notifications()
- self.db_set("clear_notifications", 1)
+ if not self.clear_notifications:
+ clear_notifications()
+ self.db_set("clear_notifications", 1)
+ self.initialize_doctypes_to_be_deleted_table()
self.delete_company_transactions()
def populate_doctypes_to_be_ignored_table(self):
@@ -89,92 +92,108 @@
self.append("doctypes_to_be_ignored", {"doctype_name": doctype})
def delete_bins(self):
- frappe.db.sql(
- """delete from `tabBin` where warehouse in
- (select name from tabWarehouse where company=%s)""",
- self.company,
- )
- self.db_set("delete_bin_data", 1)
+ if not self.delete_bin_data:
+ frappe.db.sql(
+ """delete from `tabBin` where warehouse in
+ (select name from tabWarehouse where company=%s)""",
+ self.company,
+ )
+ self.db_set("delete_bin_data", 1)
def delete_lead_addresses(self):
"""Delete addresses to which leads are linked"""
- leads = frappe.get_all("Lead", filters={"company": self.company})
- leads = ["'%s'" % row.get("name") for row in leads]
- addresses = []
- if leads:
- addresses = frappe.db.sql_list(
- """select parent from `tabDynamic Link` where link_name
- in ({leads})""".format(
- leads=",".join(leads)
- )
- )
-
- if addresses:
- addresses = ["%s" % frappe.db.escape(addr) for addr in addresses]
-
- frappe.db.sql(
- """delete from `tabAddress` where name in ({addresses}) and
- name not in (select distinct dl1.parent from `tabDynamic Link` dl1
- inner join `tabDynamic Link` dl2 on dl1.parent=dl2.parent
- and dl1.link_doctype<>dl2.link_doctype)""".format(
- addresses=",".join(addresses)
- )
- )
-
- frappe.db.sql(
- """delete from `tabDynamic Link` where link_doctype='Lead'
- and parenttype='Address' and link_name in ({leads})""".format(
+ if not self.delete_leads_and_addresses:
+ leads = frappe.get_all("Lead", filters={"company": self.company})
+ leads = ["'%s'" % row.get("name") for row in leads]
+ addresses = []
+ if leads:
+ addresses = frappe.db.sql_list(
+ """select parent from `tabDynamic Link` where link_name
+ in ({leads})""".format(
leads=",".join(leads)
)
)
- frappe.db.sql(
- """update `tabCustomer` set lead_name=NULL where lead_name in ({leads})""".format(
- leads=",".join(leads)
+ if addresses:
+ addresses = ["%s" % frappe.db.escape(addr) for addr in addresses]
+
+ frappe.db.sql(
+ """delete from `tabAddress` where name in ({addresses}) and
+ name not in (select distinct dl1.parent from `tabDynamic Link` dl1
+ inner join `tabDynamic Link` dl2 on dl1.parent=dl2.parent
+ and dl1.link_doctype<>dl2.link_doctype)""".format(
+ addresses=",".join(addresses)
+ )
+ )
+
+ frappe.db.sql(
+ """delete from `tabDynamic Link` where link_doctype='Lead'
+ and parenttype='Address' and link_name in ({leads})""".format(
+ leads=",".join(leads)
+ )
+ )
+
+ frappe.db.sql(
+ """update `tabCustomer` set lead_name=NULL where lead_name in ({leads})""".format(
+ leads=",".join(leads)
+ )
)
- )
- self.db_set("delete_leads_and_addresses", 1)
+ self.db_set("delete_leads_and_addresses", 1)
def reset_company_values(self):
- company_obj = frappe.get_doc("Company", self.company)
- company_obj.total_monthly_sales = 0
- company_obj.sales_monthly_history = None
- company_obj.save()
- self.db_set("reset_company_default_values", 1)
+ if not self.reset_company_default_values:
+ company_obj = frappe.get_doc("Company", self.company)
+ company_obj.total_monthly_sales = 0
+ company_obj.sales_monthly_history = None
+ company_obj.save()
+ self.db_set("reset_company_default_values", 1)
+
+ def initialize_doctypes_to_be_deleted_table(self):
+ if not self.initialize_doctypes_table:
+ doctypes_to_be_ignored_list = self.get_doctypes_to_be_ignored_list()
+ docfields = self.get_doctypes_with_company_field(doctypes_to_be_ignored_list)
+ tables = self.get_all_child_doctypes()
+ for docfield in docfields:
+ if docfield["parent"] != self.doctype:
+ no_of_docs = self.get_number_of_docs_linked_with_specified_company(
+ docfield["parent"], docfield["fieldname"]
+ )
+ if no_of_docs > 0:
+ # Initialize
+ self.populate_doctypes_table(tables, docfield["parent"], docfield["fieldname"], 0)
+ self.db_set("initialize_doctypes_table", 1)
def delete_company_transactions(self):
- doctypes_to_be_ignored_list = self.get_doctypes_to_be_ignored_list()
- docfields = self.get_doctypes_with_company_field(doctypes_to_be_ignored_list)
+ if not self.delete_transactions:
+ doctypes_to_be_ignored_list = self.get_doctypes_to_be_ignored_list()
+ docfields = self.get_doctypes_with_company_field(doctypes_to_be_ignored_list)
- tables = self.get_all_child_doctypes()
- for docfield in docfields:
- if docfield["parent"] != self.doctype:
- no_of_docs = self.get_number_of_docs_linked_with_specified_company(
- docfield["parent"], docfield["fieldname"]
- )
-
- if no_of_docs > 0:
- self.delete_version_log(docfield["parent"], docfield["fieldname"])
-
- reference_docs = frappe.get_all(
- docfield["parent"], filters={docfield["fieldname"]: self.company}
+ tables = self.get_all_child_doctypes()
+ for docfield in self.doctypes:
+ if docfield.doctype_name != self.doctype:
+ no_of_docs = self.get_number_of_docs_linked_with_specified_company(
+ docfield.doctype_name, docfield.docfield_name
)
- reference_doc_names = [r.name for r in reference_docs]
+ if no_of_docs > 0:
+ reference_docs = frappe.get_all(
+ docfield.doctype_name, filters={docfield.docfield_name: self.company}, limit=self.batch_size
+ )
+ reference_doc_names = [r.name for r in reference_docs]
- self.delete_communications(docfield["parent"], reference_doc_names)
- self.delete_comments(docfield["parent"], reference_doc_names)
- self.unlink_attachments(docfield["parent"], reference_doc_names)
+ self.delete_version_log(docfield.doctype_name, reference_doc_names)
+ self.delete_communications(docfield.doctype_name, reference_doc_names)
+ self.delete_comments(docfield.doctype_name, reference_doc_names)
+ self.unlink_attachments(docfield.doctype_name, reference_doc_names)
- self.populate_doctypes_table(tables, docfield["parent"], no_of_docs)
+ self.delete_child_tables(docfield.doctype_name, reference_doc_names)
+ self.delete_docs_linked_with_specified_company(docfield.doctype_name, docfield.docfield_name)
- self.delete_child_tables(docfield["parent"], docfield["fieldname"])
- self.delete_docs_linked_with_specified_company(docfield["parent"], docfield["fieldname"])
-
- naming_series = frappe.db.get_value("DocType", docfield["parent"], "autoname")
- if naming_series:
- if "#" in naming_series:
- self.update_naming_series(naming_series, docfield["parent"])
- self.db_set("delete_transactions", 1)
+ naming_series = frappe.db.get_value("DocType", docfield.doctype_name, "autoname")
+ # TODO: do this at the end of each doctype
+ if naming_series:
+ if "#" in naming_series:
+ self.update_naming_series(naming_series, docfield.doctype_name)
+ self.db_set("delete_transactions", 1)
def get_doctypes_to_be_ignored_list(self):
singles = frappe.get_all("DocType", filters={"issingle": 1}, pluck="name")
@@ -203,22 +222,21 @@
def get_number_of_docs_linked_with_specified_company(self, doctype, company_fieldname):
return frappe.db.count(doctype, {company_fieldname: self.company})
- def populate_doctypes_table(self, tables, doctype, no_of_docs):
+ def populate_doctypes_table(self, tables, doctype, fieldname, no_of_docs):
+ self.flags.ignore_validate_update_after_submit = True
if doctype not in tables:
- self.append("doctypes", {"doctype_name": doctype, "no_of_docs": no_of_docs})
+ self.append(
+ "doctypes", {"doctype_name": doctype, "docfield_name": fieldname, "no_of_docs": no_of_docs}
+ )
+ self.save(ignore_permissions=True)
- def delete_child_tables(self, doctype, company_fieldname):
- parent_docs_to_be_deleted = frappe.get_all(
- doctype, {company_fieldname: self.company}, pluck="name"
- )
-
+ def delete_child_tables(self, doctype, reference_doc_names):
child_tables = frappe.get_all(
"DocField", filters={"fieldtype": "Table", "parent": doctype}, pluck="options"
)
- for batch in create_batch(parent_docs_to_be_deleted, self.batch_size):
- for table in child_tables:
- frappe.db.delete(table, {"parent": ["in", batch]})
+ for table in child_tables:
+ frappe.db.delete(table, {"parent": ["in", reference_doc_names]})
def delete_docs_linked_with_specified_company(self, doctype, company_fieldname):
frappe.db.delete(doctype, {company_fieldname: self.company})
@@ -242,17 +260,11 @@
frappe.db.sql("""update `tabSeries` set current = %s where name=%s""", (last, prefix))
- def delete_version_log(self, doctype, company_fieldname):
- dt = qb.DocType(doctype)
- names = qb.from_(dt).select(dt.name).where(dt[company_fieldname] == self.company).run(as_list=1)
- names = [x[0] for x in names]
-
- if names:
- versions = qb.DocType("Version")
- for batch in create_batch(names, self.batch_size):
- qb.from_(versions).delete().where(
- (versions.ref_doctype == doctype) & (versions.docname.isin(batch))
- ).run()
+ def delete_version_log(self, doctype, docnames):
+ versions = qb.DocType("Version")
+ qb.from_(versions).delete().where(
+ (versions.ref_doctype == doctype) & (versions.docname.isin(docnames))
+ ).run()
def delete_communications(self, doctype, reference_doc_names):
communications = frappe.get_all(
diff --git a/erpnext/setup/doctype/transaction_deletion_record_item/transaction_deletion_record_item.json b/erpnext/setup/doctype/transaction_deletion_record_item/transaction_deletion_record_item.json
index be0be94..4e5e184 100644
--- a/erpnext/setup/doctype/transaction_deletion_record_item/transaction_deletion_record_item.json
+++ b/erpnext/setup/doctype/transaction_deletion_record_item/transaction_deletion_record_item.json
@@ -6,7 +6,9 @@
"engine": "InnoDB",
"field_order": [
"doctype_name",
- "no_of_docs"
+ "docfield_name",
+ "no_of_docs",
+ "done"
],
"fields": [
{
@@ -22,12 +24,24 @@
"fieldtype": "Data",
"in_list_view": 1,
"label": "Number of Docs"
+ },
+ {
+ "default": "0",
+ "fieldname": "done",
+ "fieldtype": "Check",
+ "in_list_view": 1,
+ "label": "Done"
+ },
+ {
+ "fieldname": "docfield_name",
+ "fieldtype": "Data",
+ "label": "DocField Name"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
- "modified": "2021-05-08 23:10:46.166744",
+ "modified": "2024-02-03 21:06:32.274445",
"modified_by": "Administrator",
"module": "Setup",
"name": "Transaction Deletion Record Item",
@@ -35,5 +49,6 @@
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [],
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/setup/doctype/transaction_deletion_record_item/transaction_deletion_record_item.py b/erpnext/setup/doctype/transaction_deletion_record_item/transaction_deletion_record_item.py
index f154cdb..ce716ac 100644
--- a/erpnext/setup/doctype/transaction_deletion_record_item/transaction_deletion_record_item.py
+++ b/erpnext/setup/doctype/transaction_deletion_record_item/transaction_deletion_record_item.py
@@ -15,7 +15,9 @@
if TYPE_CHECKING:
from frappe.types import DF
+ docfield_name: DF.Data | None
doctype_name: DF.Link
+ done: DF.Check
no_of_docs: DF.Data | None
parent: DF.Data
parentfield: DF.Data