mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-25 16:04:46 +00:00
refactor: use flags to decide on current stage
This commit is contained in:
@@ -16,9 +16,15 @@ frappe.ui.form.on("Transaction Deletion Record", {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
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.get_field('doctypes_to_be_ignored').grid.cannot_add_rows = true;
|
||||||
frm.refresh_field("doctypes_to_be_ignored");
|
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) {
|
refresh: function (frm) {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
"reset_company_default_values",
|
"reset_company_default_values",
|
||||||
"clear_notifications",
|
"clear_notifications",
|
||||||
"delete_transactions",
|
"delete_transactions",
|
||||||
|
"initialize_doctypes_table",
|
||||||
"section_break_tbej",
|
"section_break_tbej",
|
||||||
"doctypes",
|
"doctypes",
|
||||||
"doctypes_to_be_ignored",
|
"doctypes_to_be_ignored",
|
||||||
@@ -110,12 +111,19 @@
|
|||||||
"label": "Delete Transactions",
|
"label": "Delete Transactions",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"read_only": 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,
|
"index_web_pages_for_search": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-02-03 14:40:40.207482",
|
"modified": "2024-02-03 20:48:34.107577",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Setup",
|
"module": "Setup",
|
||||||
"name": "Transaction Deletion Record",
|
"name": "Transaction Deletion Record",
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ class TransactionDeletionRecord(Document):
|
|||||||
delete_transactions: DF.Check
|
delete_transactions: DF.Check
|
||||||
doctypes: DF.Table[TransactionDeletionRecordItem]
|
doctypes: DF.Table[TransactionDeletionRecordItem]
|
||||||
doctypes_to_be_ignored: DF.Table[TransactionDeletionRecordItem]
|
doctypes_to_be_ignored: DF.Table[TransactionDeletionRecordItem]
|
||||||
|
initialize_doctypes_table: DF.Check
|
||||||
reset_company_default_values: DF.Check
|
reset_company_default_values: DF.Check
|
||||||
status: DF.Literal["Queued", "Running", "Failed", "Completed", "Cancelled"]
|
status: DF.Literal["Queued", "Running", "Failed", "Completed", "Cancelled"]
|
||||||
# end: auto-generated types
|
# end: auto-generated types
|
||||||
@@ -79,8 +80,10 @@ class TransactionDeletionRecord(Document):
|
|||||||
self.delete_bins()
|
self.delete_bins()
|
||||||
self.delete_lead_addresses()
|
self.delete_lead_addresses()
|
||||||
self.reset_company_values()
|
self.reset_company_values()
|
||||||
clear_notifications()
|
if not self.clear_notifications:
|
||||||
self.db_set("clear_notifications", 1)
|
clear_notifications()
|
||||||
|
self.db_set("clear_notifications", 1)
|
||||||
|
self.initialize_doctypes_to_be_deleted_table()
|
||||||
self.delete_company_transactions()
|
self.delete_company_transactions()
|
||||||
|
|
||||||
def populate_doctypes_to_be_ignored_table(self):
|
def populate_doctypes_to_be_ignored_table(self):
|
||||||
@@ -89,92 +92,108 @@ class TransactionDeletionRecord(Document):
|
|||||||
self.append("doctypes_to_be_ignored", {"doctype_name": doctype})
|
self.append("doctypes_to_be_ignored", {"doctype_name": doctype})
|
||||||
|
|
||||||
def delete_bins(self):
|
def delete_bins(self):
|
||||||
frappe.db.sql(
|
if not self.delete_bin_data:
|
||||||
"""delete from `tabBin` where warehouse in
|
frappe.db.sql(
|
||||||
(select name from tabWarehouse where company=%s)""",
|
"""delete from `tabBin` where warehouse in
|
||||||
self.company,
|
(select name from tabWarehouse where company=%s)""",
|
||||||
)
|
self.company,
|
||||||
self.db_set("delete_bin_data", 1)
|
)
|
||||||
|
self.db_set("delete_bin_data", 1)
|
||||||
|
|
||||||
def delete_lead_addresses(self):
|
def delete_lead_addresses(self):
|
||||||
"""Delete addresses to which leads are linked"""
|
"""Delete addresses to which leads are linked"""
|
||||||
leads = frappe.get_all("Lead", filters={"company": self.company})
|
if not self.delete_leads_and_addresses:
|
||||||
leads = ["'%s'" % row.get("name") for row in leads]
|
leads = frappe.get_all("Lead", filters={"company": self.company})
|
||||||
addresses = []
|
leads = ["'%s'" % row.get("name") for row in leads]
|
||||||
if leads:
|
addresses = []
|
||||||
addresses = frappe.db.sql_list(
|
if leads:
|
||||||
"""select parent from `tabDynamic Link` where link_name
|
addresses = frappe.db.sql_list(
|
||||||
in ({leads})""".format(
|
"""select parent from `tabDynamic Link` where link_name
|
||||||
leads=",".join(leads)
|
in ({leads})""".format(
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
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)
|
leads=",".join(leads)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
frappe.db.sql(
|
if addresses:
|
||||||
"""update `tabCustomer` set lead_name=NULL where lead_name in ({leads})""".format(
|
addresses = ["%s" % frappe.db.escape(addr) for addr in addresses]
|
||||||
leads=",".join(leads)
|
|
||||||
|
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):
|
def reset_company_values(self):
|
||||||
company_obj = frappe.get_doc("Company", self.company)
|
if not self.reset_company_default_values:
|
||||||
company_obj.total_monthly_sales = 0
|
company_obj = frappe.get_doc("Company", self.company)
|
||||||
company_obj.sales_monthly_history = None
|
company_obj.total_monthly_sales = 0
|
||||||
company_obj.save()
|
company_obj.sales_monthly_history = None
|
||||||
self.db_set("reset_company_default_values", 1)
|
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):
|
def delete_company_transactions(self):
|
||||||
doctypes_to_be_ignored_list = self.get_doctypes_to_be_ignored_list()
|
if not self.delete_transactions:
|
||||||
docfields = self.get_doctypes_with_company_field(doctypes_to_be_ignored_list)
|
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()
|
tables = self.get_all_child_doctypes()
|
||||||
for docfield in docfields:
|
for docfield in self.doctypes:
|
||||||
if docfield["parent"] != self.doctype:
|
if docfield.doctype_name != self.doctype:
|
||||||
no_of_docs = self.get_number_of_docs_linked_with_specified_company(
|
no_of_docs = self.get_number_of_docs_linked_with_specified_company(
|
||||||
docfield["parent"], docfield["fieldname"]
|
docfield.doctype_name, docfield.docfield_name
|
||||||
)
|
|
||||||
|
|
||||||
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}
|
|
||||||
)
|
)
|
||||||
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_version_log(docfield.doctype_name, reference_doc_names)
|
||||||
self.delete_comments(docfield["parent"], reference_doc_names)
|
self.delete_communications(docfield.doctype_name, reference_doc_names)
|
||||||
self.unlink_attachments(docfield["parent"], 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"])
|
naming_series = frappe.db.get_value("DocType", docfield.doctype_name, "autoname")
|
||||||
self.delete_docs_linked_with_specified_company(docfield["parent"], docfield["fieldname"])
|
# TODO: do this at the end of each doctype
|
||||||
|
if naming_series:
|
||||||
naming_series = frappe.db.get_value("DocType", docfield["parent"], "autoname")
|
if "#" in naming_series:
|
||||||
if naming_series:
|
self.update_naming_series(naming_series, docfield.doctype_name)
|
||||||
if "#" in naming_series:
|
self.db_set("delete_transactions", 1)
|
||||||
self.update_naming_series(naming_series, docfield["parent"])
|
|
||||||
self.db_set("delete_transactions", 1)
|
|
||||||
|
|
||||||
def get_doctypes_to_be_ignored_list(self):
|
def get_doctypes_to_be_ignored_list(self):
|
||||||
singles = frappe.get_all("DocType", filters={"issingle": 1}, pluck="name")
|
singles = frappe.get_all("DocType", filters={"issingle": 1}, pluck="name")
|
||||||
@@ -203,22 +222,21 @@ class TransactionDeletionRecord(Document):
|
|||||||
def get_number_of_docs_linked_with_specified_company(self, doctype, company_fieldname):
|
def get_number_of_docs_linked_with_specified_company(self, doctype, company_fieldname):
|
||||||
return frappe.db.count(doctype, {company_fieldname: self.company})
|
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:
|
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}
|
||||||
def delete_child_tables(self, doctype, company_fieldname):
|
)
|
||||||
parent_docs_to_be_deleted = frappe.get_all(
|
self.save(ignore_permissions=True)
|
||||||
doctype, {company_fieldname: self.company}, pluck="name"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
def delete_child_tables(self, doctype, reference_doc_names):
|
||||||
child_tables = frappe.get_all(
|
child_tables = frappe.get_all(
|
||||||
"DocField", filters={"fieldtype": "Table", "parent": doctype}, pluck="options"
|
"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:
|
||||||
for table in child_tables:
|
frappe.db.delete(table, {"parent": ["in", reference_doc_names]})
|
||||||
frappe.db.delete(table, {"parent": ["in", batch]})
|
|
||||||
|
|
||||||
def delete_docs_linked_with_specified_company(self, doctype, company_fieldname):
|
def delete_docs_linked_with_specified_company(self, doctype, company_fieldname):
|
||||||
frappe.db.delete(doctype, {company_fieldname: self.company})
|
frappe.db.delete(doctype, {company_fieldname: self.company})
|
||||||
@@ -242,17 +260,11 @@ class TransactionDeletionRecord(Document):
|
|||||||
|
|
||||||
frappe.db.sql("""update `tabSeries` set current = %s where name=%s""", (last, prefix))
|
frappe.db.sql("""update `tabSeries` set current = %s where name=%s""", (last, prefix))
|
||||||
|
|
||||||
def delete_version_log(self, doctype, company_fieldname):
|
def delete_version_log(self, doctype, docnames):
|
||||||
dt = qb.DocType(doctype)
|
versions = qb.DocType("Version")
|
||||||
names = qb.from_(dt).select(dt.name).where(dt[company_fieldname] == self.company).run(as_list=1)
|
qb.from_(versions).delete().where(
|
||||||
names = [x[0] for x in names]
|
(versions.ref_doctype == doctype) & (versions.docname.isin(docnames))
|
||||||
|
).run()
|
||||||
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_communications(self, doctype, reference_doc_names):
|
def delete_communications(self, doctype, reference_doc_names):
|
||||||
communications = frappe.get_all(
|
communications = frappe.get_all(
|
||||||
|
|||||||
@@ -6,7 +6,9 @@
|
|||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"doctype_name",
|
"doctype_name",
|
||||||
"no_of_docs"
|
"docfield_name",
|
||||||
|
"no_of_docs",
|
||||||
|
"done"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@@ -22,12 +24,24 @@
|
|||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Number of Docs"
|
"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,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-05-08 23:10:46.166744",
|
"modified": "2024-02-03 21:06:32.274445",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Setup",
|
"module": "Setup",
|
||||||
"name": "Transaction Deletion Record Item",
|
"name": "Transaction Deletion Record Item",
|
||||||
@@ -35,5 +49,6 @@
|
|||||||
"permissions": [],
|
"permissions": [],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,9 @@ class TransactionDeletionRecordItem(Document):
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from frappe.types import DF
|
from frappe.types import DF
|
||||||
|
|
||||||
|
docfield_name: DF.Data | None
|
||||||
doctype_name: DF.Link
|
doctype_name: DF.Link
|
||||||
|
done: DF.Check
|
||||||
no_of_docs: DF.Data | None
|
no_of_docs: DF.Data | None
|
||||||
parent: DF.Data
|
parent: DF.Data
|
||||||
parentfield: DF.Data
|
parentfield: DF.Data
|
||||||
|
|||||||
Reference in New Issue
Block a user