From 2efc3c9cb40b215f721c57e2493dfe504f6cd424 Mon Sep 17 00:00:00 2001 From: Shrihari Mahabal Date: Tue, 24 Mar 2026 15:02:12 +0530 Subject: [PATCH 1/5] fix: update user allowed reports cache after insert and trash to reflect updated reports in dropdown --- frappe/core/doctype/report/report.py | 16 ++++++++++++++ frappe/core/doctype/report/test_report.py | 27 +++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/frappe/core/doctype/report/report.py b/frappe/core/doctype/report/report.py index 828a28a075..4af12f2db4 100644 --- a/frappe/core/doctype/report/report.py +++ b/frappe/core/doctype/report/report.py @@ -85,6 +85,9 @@ class Report(Document): def before_insert(self): self.set_doctype_roles() + def after_insert(self): + self.update_report_cache() + def on_update(self): self.export_doc() @@ -106,6 +109,19 @@ class Report(Document): delete_custom_role("report", self.name) + def after_delete(self): + self.update_report_cache() + + def update_report_cache(self): + from frappe.boot import get_allowed_reports + + fresh_reports = get_allowed_reports() + + bootinfo = frappe.cache.hget("bootinfo", frappe.session.user) + if bootinfo and bootinfo.get("user"): + bootinfo["user"]["all_reports"] = fresh_reports + frappe.cache.hset("bootinfo", frappe.session.user, bootinfo) + def delete_report_folder(self): from frappe.modules.export_file import delete_folder diff --git a/frappe/core/doctype/report/test_report.py b/frappe/core/doctype/report/test_report.py index ba9382ef8e..1a5d7dd269 100644 --- a/frappe/core/doctype/report/test_report.py +++ b/frappe/core/doctype/report/test_report.py @@ -406,3 +406,30 @@ result = [ self.assertEqual(result[-1][0], "Total") self.assertEqual(result[-1][1], 200) self.assertEqual(result[-1][2], 150.50) + + def test_report_cache_invalidation(self): + from frappe.boot import get_bootinfo + + frappe.set_user("test@example.com") + + try: + bootinfo = get_bootinfo() + frappe.cache.hset("bootinfo", frappe.session.user, bootinfo) + + report_name = _save_report( + "Test Cache Invalidation Report", + "User", + json.dumps([{"fieldname": "email", "fieldtype": "Data", "label": "Email"}]), + ) + + cached_bootinfo = frappe.cache.hget("bootinfo", frappe.session.user) + self.assertIn(report_name, cached_bootinfo["user"]["all_reports"]) + + doc = frappe.get_doc("Report", report_name) + delete_report(doc.name) + + cached_bootinfo = frappe.cache.hget("bootinfo", frappe.session.user) + self.assertNotIn(report_name, cached_bootinfo["user"]["all_reports"]) + + finally: + frappe.set_user("Administrator") From fd4245fc569a200737149416bb45661818286986 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 25 Mar 2026 16:45:22 +0530 Subject: [PATCH 2/5] refactor: trigger cache clearing with clear_cache hook --- frappe/core/doctype/report/report.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/frappe/core/doctype/report/report.py b/frappe/core/doctype/report/report.py index 4af12f2db4..88d63b9490 100644 --- a/frappe/core/doctype/report/report.py +++ b/frappe/core/doctype/report/report.py @@ -85,9 +85,6 @@ class Report(Document): def before_insert(self): self.set_doctype_roles() - def after_insert(self): - self.update_report_cache() - def on_update(self): self.export_doc() @@ -109,8 +106,9 @@ class Report(Document): delete_custom_role("report", self.name) - def after_delete(self): + def clear_cache(self): self.update_report_cache() + return super().clear_cache() def update_report_cache(self): from frappe.boot import get_allowed_reports From 6572760990fd3a45fc0ca1e7a845e1673f2e6ee8 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 25 Mar 2026 16:46:53 +0530 Subject: [PATCH 3/5] fix: Clear report cache for all users Co-Authored-By: Shrihari Mahabal --- frappe/core/doctype/report/report.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/frappe/core/doctype/report/report.py b/frappe/core/doctype/report/report.py index 88d63b9490..1c08b3d533 100644 --- a/frappe/core/doctype/report/report.py +++ b/frappe/core/doctype/report/report.py @@ -111,14 +111,7 @@ class Report(Document): return super().clear_cache() def update_report_cache(self): - from frappe.boot import get_allowed_reports - - fresh_reports = get_allowed_reports() - - bootinfo = frappe.cache.hget("bootinfo", frappe.session.user) - if bootinfo and bootinfo.get("user"): - bootinfo["user"]["all_reports"] = fresh_reports - frappe.cache.hset("bootinfo", frappe.session.user, bootinfo) + frappe.cache.delete_key("bootinfo") def delete_report_folder(self): from frappe.modules.export_file import delete_folder From 6d80ff3e4ebff885e0158b686cd10249390bc197 Mon Sep 17 00:00:00 2001 From: Shrihari Mahabal Date: Thu, 26 Mar 2026 18:35:13 +0530 Subject: [PATCH 4/5] test: fix tests --- frappe/core/doctype/report/test_report.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/frappe/core/doctype/report/test_report.py b/frappe/core/doctype/report/test_report.py index 1a5d7dd269..17cb668a54 100644 --- a/frappe/core/doctype/report/test_report.py +++ b/frappe/core/doctype/report/test_report.py @@ -413,23 +413,20 @@ result = [ frappe.set_user("test@example.com") try: - bootinfo = get_bootinfo() - frappe.cache.hset("bootinfo", frappe.session.user, bootinfo) - report_name = _save_report( "Test Cache Invalidation Report", "User", json.dumps([{"fieldname": "email", "fieldtype": "Data", "label": "Email"}]), ) - cached_bootinfo = frappe.cache.hget("bootinfo", frappe.session.user) - self.assertIn(report_name, cached_bootinfo["user"]["all_reports"]) + bootinfo = get_bootinfo() + self.assertIn(report_name, bootinfo["user"]["all_reports"]) doc = frappe.get_doc("Report", report_name) delete_report(doc.name) - cached_bootinfo = frappe.cache.hget("bootinfo", frappe.session.user) - self.assertNotIn(report_name, cached_bootinfo["user"]["all_reports"]) + bootinfo = get_bootinfo() + self.assertNotIn(report_name, bootinfo["user"]["all_reports"]) finally: frappe.set_user("Administrator") From 79d9788a533b8f778083d2728bab2aa2958a259a Mon Sep 17 00:00:00 2001 From: Shrihari Mahabal Date: Thu, 26 Mar 2026 19:52:24 +0530 Subject: [PATCH 5/5] test: use sessions.get instead of internal get_bootinfo --- frappe/core/doctype/report/test_report.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/frappe/core/doctype/report/test_report.py b/frappe/core/doctype/report/test_report.py index 17cb668a54..1ed50d0c04 100644 --- a/frappe/core/doctype/report/test_report.py +++ b/frappe/core/doctype/report/test_report.py @@ -408,25 +408,30 @@ result = [ self.assertEqual(result[-1][2], 150.50) def test_report_cache_invalidation(self): - from frappe.boot import get_bootinfo + import frappe.sessions + from frappe.utils import set_request frappe.set_user("test@example.com") + set_request(method="GET", path="/app") try: + frappe.sessions.get() + report_name = _save_report( "Test Cache Invalidation Report", "User", json.dumps([{"fieldname": "email", "fieldtype": "Data", "label": "Email"}]), ) - bootinfo = get_bootinfo() - self.assertIn(report_name, bootinfo["user"]["all_reports"]) + cached_bootinfo = frappe.sessions.get() + self.assertIn(report_name, cached_bootinfo["user"]["all_reports"]) doc = frappe.get_doc("Report", report_name) delete_report(doc.name) - bootinfo = get_bootinfo() - self.assertNotIn(report_name, bootinfo["user"]["all_reports"]) + cached_bootinfo = frappe.sessions.get() + self.assertNotIn(report_name, cached_bootinfo["user"]["all_reports"]) finally: + frappe.local.request = None frappe.set_user("Administrator")