fix: ignore stale custom fields while checking back-links (#22940)

* fix: ignore non-existing back-links

* refactor: less indentation, guard clauses
This commit is contained in:
Ankush Menat 2023-10-27 14:07:58 +05:30 committed by GitHub
parent f4cd1bb8af
commit 1560fa8610
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -250,37 +250,45 @@ def check_if_doc_is_linked(doc, method="Delete"):
for lf in link_fields:
link_dt, link_field, issingle = lf["parent"], lf["fieldname"], lf["issingle"]
if not issingle:
fields = ["name", "docstatus"]
if frappe.get_meta(link_dt).istable:
fields.extend(["parent", "parenttype"])
try:
meta = frappe.get_meta(link_dt)
except frappe.DoesNotExistError:
# This mostly happens when app do not remove their customizations, we shouldn't
# prevent link checks from failing in those cases
continue
for item in frappe.db.get_values(link_dt, {link_field: doc.name}, fields, as_dict=True):
# available only in child table cases
item_parent = getattr(item, "parent", None)
linked_doctype = item.parenttype if item_parent else link_dt
if linked_doctype in frappe.get_hooks("ignore_links_on_delete") or (
linked_doctype in ignore_linked_doctypes and method == "Cancel"
):
# don't check for communication and todo!
continue
if method != "Delete" and (method != "Cancel" or not DocStatus(item.docstatus).is_submitted()):
# don't raise exception if not
# linked to a non-cancelled doc when deleting or to a submitted doc when cancelling
continue
elif link_dt == doc.doctype and (item_parent or item.name) == doc.name:
# don't raise exception if not
# linked to same item or doc having same name as the item
continue
else:
reference_docname = item_parent or item.name
raise_link_exists_exception(doc, linked_doctype, reference_docname)
else:
if issingle:
if frappe.db.get_value(link_dt, None, link_field) == doc.name:
raise_link_exists_exception(doc, link_dt, link_dt)
continue
fields = ["name", "docstatus"]
if meta.istable:
fields.extend(["parent", "parenttype"])
for item in frappe.db.get_values(link_dt, {link_field: doc.name}, fields, as_dict=True):
# available only in child table cases
item_parent = getattr(item, "parent", None)
linked_doctype = item.parenttype if item_parent else link_dt
if linked_doctype in frappe.get_hooks("ignore_links_on_delete") or (
linked_doctype in ignore_linked_doctypes and method == "Cancel"
):
# don't check for communication and todo!
continue
if method != "Delete" and (method != "Cancel" or not DocStatus(item.docstatus).is_submitted()):
# don't raise exception if not
# linked to a non-cancelled doc when deleting or to a submitted doc when cancelling
continue
elif link_dt == doc.doctype and (item_parent or item.name) == doc.name:
# don't raise exception if not
# linked to same item or doc having same name as the item
continue
else:
reference_docname = item_parent or item.name
raise_link_exists_exception(doc, linked_doctype, reference_docname)
def check_if_doc_is_dynamically_linked(doc, method="Delete"):