From 51823d1b8806709786d6fb9f9f85639968c65a94 Mon Sep 17 00:00:00 2001 From: naaa760 Date: Fri, 8 Aug 2025 14:12:36 +0530 Subject: [PATCH] Added input validation Added document existence checks Added reference field validation Changed None to empty strings for reference fields --- crm/api/doc.py | 134 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 98 insertions(+), 36 deletions(-) diff --git a/crm/api/doc.py b/crm/api/doc.py index afa2f2a6..50fabefe 100644 --- a/crm/api/doc.py +++ b/crm/api/doc.py @@ -751,7 +751,12 @@ def getCounts(d, doctype): @frappe.whitelist() def get_linked_docs_of_document(doctype, docname): - doc = frappe.get_doc(doctype, docname) + try: + doc = frappe.get_doc(doctype, docname) + except frappe.DoesNotExistError: + + return [] + linked_docs = get_linked_docs(doc) dynamic_linked_docs = get_dynamic_linked_docs(doc) @@ -760,7 +765,16 @@ def get_linked_docs_of_document(doctype, docname): docs_data = [] for doc in linked_docs: - data = frappe.get_doc(doc["reference_doctype"], doc["reference_docname"]) + + if not doc.get("reference_doctype") or not doc.get("reference_docname"): + continue + + try: + data = frappe.get_doc(doc["reference_doctype"], doc["reference_docname"]) + except (frappe.DoesNotExistError, frappe.ValidationError): + + continue + title = data.get("title") if data.doctype == "CRM Call Log": title = f"Call from {data.get('from')} to {data.get('to')}" @@ -780,25 +794,42 @@ def get_linked_docs_of_document(doctype, docname): def remove_doc_link(doctype, docname): - linked_doc_data = frappe.get_doc(doctype, docname) - linked_doc_data.update( - { - "reference_doctype": None, - "reference_docname": None, - } - ) - linked_doc_data.save(ignore_permissions=True) + + if not doctype or not docname: + return + + try: + linked_doc_data = frappe.get_doc(doctype, docname) + + linked_doc_data.update( + { + "reference_doctype": "", + "reference_docname": "", + } + ) + linked_doc_data.save(ignore_permissions=True) + except (frappe.DoesNotExistError, frappe.ValidationError): + + pass def remove_contact_link(doctype, docname): - linked_doc_data = frappe.get_doc(doctype, docname) - linked_doc_data.update( - { - "contact": None, - "contacts": [], - } - ) - linked_doc_data.save(ignore_permissions=True) + + if not doctype or not docname: + return + + try: + linked_doc_data = frappe.get_doc(doctype, docname) + linked_doc_data.update( + { + "contact": None, + "contacts": [], + } + ) + linked_doc_data.save(ignore_permissions=True) + except (frappe.DoesNotExistError, frappe.ValidationError): + + pass @frappe.whitelist() @@ -807,13 +838,21 @@ def remove_linked_doc_reference(items, remove_contact=None, delete=False): items = frappe.parse_json(items) for item in items: - if remove_contact: - remove_contact_link(item["doctype"], item["docname"]) - else: - remove_doc_link(item["doctype"], item["docname"]) + + if not item.get("doctype") or not item.get("docname"): + continue + + try: + if remove_contact: + remove_contact_link(item["doctype"], item["docname"]) + else: + remove_doc_link(item["doctype"], item["docname"]) - if delete: - frappe.delete_doc(item["doctype"], item["docname"]) + if delete: + frappe.delete_doc(item["doctype"], item["docname"]) + except (frappe.DoesNotExistError, frappe.ValidationError): + # Skip if document doesn't exist or has validation errors + continue return "success" @@ -822,20 +861,43 @@ def remove_linked_doc_reference(items, remove_contact=None, delete=False): def delete_bulk_docs(doctype, items, delete_linked=False): from frappe.desk.reportview import delete_bulk + + if not doctype: + frappe.throw("Doctype is required") + + if not items: + frappe.throw("Items are required") + items = frappe.parse_json(items) + if not isinstance(items, list): + frappe.throw("Items must be a list") + for doc in items: - linked_docs = get_linked_docs_of_document(doctype, doc) - for linked_doc in linked_docs: - remove_linked_doc_reference( - [ - { - "doctype": linked_doc["reference_doctype"], - "docname": linked_doc["reference_docname"], - } - ], - remove_contact=doctype == "Contact", - delete=delete_linked, - ) + try: + + if not frappe.db.exists(doctype, doc): + frappe.log_error(f"Document {doctype} {doc} does not exist", "Bulk Delete Error") + continue + + linked_docs = get_linked_docs_of_document(doctype, doc) + for linked_doc in linked_docs: + + if not linked_doc.get("reference_doctype") or not linked_doc.get("reference_docname"): + continue + + remove_linked_doc_reference( + [ + { + "doctype": linked_doc["reference_doctype"], + "docname": linked_doc["reference_docname"], + } + ], + remove_contact=doctype == "Contact", + delete=delete_linked, + ) + except Exception as e: + + frappe.log_error(f"Error processing linked docs for {doctype} {doc}: {str(e)}", "Bulk Delete Error") if len(items) > 10: frappe.enqueue("frappe.desk.reportview.delete_bulk", doctype=doctype, items=items)