From 0c7b05d69618de17f341bc5150280f58e36eca6b Mon Sep 17 00:00:00 2001 From: David Malinowski Date: Wed, 26 Aug 2026 10:18:44 +0200 Subject: [PATCH] fix(tools): Service Report laesst sich ohne OTRSConnect nicht mehr speichern Der before_save-Hook am Service Report ruft save_backlinks auf, das auf den DocType "OTRSConnect Article" zugreift. Seit dem Entfernen der App otrsconnect (26.08.2026) existiert dieser DocType nicht mehr - jeder Speichervorgang warf dadurch einen DoesNotExistError. Frappe 16.31 wandelt den fuer Benutzer ohne Leserecht auf den DocType "DocType" zusaetzlich in einen PermissionError um ("Keine Berechtigung fuer DocType"), was die Ursache vollstaendig verschleierte. save_backlinks und clear_backlinks pruefen jetzt zuerst, ob der DocType ueberhaupt vorhanden ist, und tun sonst nichts. Auf Sites mit OTRSConnect bleibt das Verhalten unveraendert. Co-Authored-By: Claude Opus 5 (1M context) --- msp/tools.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/msp/tools.py b/msp/tools.py index 4be0d90..52b3948 100644 --- a/msp/tools.py +++ b/msp/tools.py @@ -544,7 +544,18 @@ def link_ERPNext_OTRS_Ticket(OTRSConnect_Ticket): frappe.msgprint("Kundennummerzuweisung nicht eindeutig möglich für: " + str(OTRSConnect_Ticket.customer_id) + "
" + str(OTRSConnect_Ticket.title) + "
" + str(OTRSConnect_Ticket.id)) @frappe.whitelist() +def _otrs_articles_vorhanden(): + """OTRSConnect wurde am 26.08.2026 aus der Bench entfernt; auf Sites ohne diese + App existiert der DocType nicht mehr. Ohne diese Pruefung wirft jeder Zugriff einen + DoesNotExistError, den Frappe 16.31 fuer Benutzer ohne DocType-Leserecht in einen + irrefuehrenden PermissionError umwandelt - und der before_save-Hook am Service Report + laesst dann kein Speichern mehr zu.""" + return bool(frappe.db.exists("DocType", "OTRSConnect Article")) + + def save_backlinks(doc, method): + if not _otrs_articles_vorhanden(): + return service_report = doc if hasattr(service_report, 'work'): @@ -577,6 +588,9 @@ def handle_backlinks(doc, method): clear_backlinks(doc) def clear_backlinks(doc): + if not _otrs_articles_vorhanden(): + return + if hasattr(doc, 'work'): for item in doc.work: if hasattr(item, 'otrs_article'):