From 610ead22e8f2b73321fa0f67cd030d35ca7f462a Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Thu, 20 Jul 2023 13:08:26 +0530 Subject: [PATCH 1/6] fix: show only projects with access in customer portal --- erpnext/projects/doctype/project/project.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index 7d80ac1cb7df..f5fd67bfcf4b 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -13,6 +13,7 @@ from erpnext import get_default_company from erpnext.controllers.queries import get_filters_cond +from erpnext.controllers.website_list_for_contact import get_customers_suppliers from erpnext.setup.doctype.holiday_list.holiday_list import is_holiday @@ -318,6 +319,7 @@ def get_timeline_data(doctype: str, name: str) -> dict[int, int]: def get_project_list( doctype, txt, filters, limit_start, limit_page_length=20, order_by="modified" ): + customers, suppliers = get_customers_suppliers("Project", frappe.session.user) meta = frappe.get_meta(doctype) if not filters: filters = [] @@ -325,6 +327,7 @@ def get_project_list( fields = "distinct *" or_filters = [] + filters.append([doctype, "customer", "in", customers]) if txt: if meta.search_fields: From 5d7dd9b0ec5759bda695e2fb3dcd6527a769505a Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Thu, 20 Jul 2023 18:20:53 +0530 Subject: [PATCH 2/6] fix: project route permissions for user --- erpnext/hooks.py | 3 +- erpnext/projects/doctype/project/project.py | 40 +++++++++++++++------ 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 316d9437fb8b..dab166e49f2f 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -185,7 +185,7 @@ ] standard_portal_menu_items = [ - {"title": "Projects", "route": "/project", "reference_doctype": "Project"}, + {"title": "Projects", "route": "/project", "reference_doctype": "Project", "role": "Customer"}, { "title": "Request for Quotations", "route": "/rfq", @@ -277,6 +277,7 @@ "Delivery Note": "erpnext.controllers.website_list_for_contact.has_website_permission", "Issue": "erpnext.support.doctype.issue.issue.has_website_permission", "Timesheet": "erpnext.controllers.website_list_for_contact.has_website_permission", + "Project": "erpnext.controllers.website_list_for_contact.has_website_permission", } before_tests = "erpnext.setup.utils.before_tests" diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index f5fd67bfcf4b..c2ed579e73f9 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -10,6 +10,7 @@ from frappe.query_builder import Interval from frappe.query_builder.functions import Count, CurDate, Date, UnixTimestamp from frappe.utils import add_days, flt, get_datetime, get_time, get_url, nowtime, today +from frappe.utils.user import is_website_user from erpnext import get_default_company from erpnext.controllers.queries import get_filters_cond @@ -319,15 +320,24 @@ def get_timeline_data(doctype: str, name: str) -> dict[int, int]: def get_project_list( doctype, txt, filters, limit_start, limit_page_length=20, order_by="modified" ): + user = frappe.session.user customers, suppliers = get_customers_suppliers("Project", frappe.session.user) + + ignore_permissions = False + if is_website_user(): + if not filters: + filters = [] + + if customers: + filters.append([doctype, "customer", "in", customers]) + + ignore_permissions = True + meta = frappe.get_meta(doctype) - if not filters: - filters = [] fields = "distinct *" or_filters = [] - filters.append([doctype, "customer", "in", customers]) if txt: if meta.search_fields: @@ -354,18 +364,26 @@ def get_project_list( limit_start=limit_start, limit_page_length=limit_page_length, order_by=order_by, + ignore_permissions=ignore_permissions, ) def get_list_context(context=None): - return { - "show_sidebar": True, - "show_search": True, - "no_breadcrumbs": True, - "title": _("Projects"), - "get_list": get_project_list, - "row_template": "templates/includes/projects/project_row.html", - } + from erpnext.controllers.website_list_for_contact import get_list_context + + list_context = get_list_context(context) + list_context.update( + { + "show_sidebar": True, + "show_search": True, + "no_breadcrumbs": True, + "title": _("Projects"), + "get_list": get_project_list, + "row_template": "templates/includes/projects/project_row.html", + } + ) + + return list_context @frappe.whitelist() From c071523e3518c2511bcadce5b109de668ae58835 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 16 Aug 2023 12:23:10 +0530 Subject: [PATCH 3/6] fix: delete portal settings for education doctypes --- erpnext/patches/v14_0/delete_education_doctypes.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/patches/v14_0/delete_education_doctypes.py b/erpnext/patches/v14_0/delete_education_doctypes.py index 76b2300fd2a1..24b9fa1d71c5 100644 --- a/erpnext/patches/v14_0/delete_education_doctypes.py +++ b/erpnext/patches/v14_0/delete_education_doctypes.py @@ -44,6 +44,9 @@ def execute(): doctypes = frappe.get_all("DocType", {"module": "education", "custom": 0}, pluck="name") for doctype in doctypes: + frappe.delete_doc( + "Portal Menu Item", {"reference_doctype": doctype}, ignore_missing=True, force=True + ) frappe.delete_doc("DocType", doctype, ignore_missing=True) frappe.delete_doc("Module Def", "Education", ignore_missing=True, force=True) From d119d2ec320e7f7c733253e1850c81c3f209bfd6 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 16 Aug 2023 17:35:07 +0530 Subject: [PATCH 4/6] fix: delete doc without filters --- erpnext/patches/v14_0/delete_education_doctypes.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/erpnext/patches/v14_0/delete_education_doctypes.py b/erpnext/patches/v14_0/delete_education_doctypes.py index 24b9fa1d71c5..468c2fda32be 100644 --- a/erpnext/patches/v14_0/delete_education_doctypes.py +++ b/erpnext/patches/v14_0/delete_education_doctypes.py @@ -44,11 +44,14 @@ def execute(): doctypes = frappe.get_all("DocType", {"module": "education", "custom": 0}, pluck="name") for doctype in doctypes: - frappe.delete_doc( - "Portal Menu Item", {"reference_doctype": doctype}, ignore_missing=True, force=True - ) frappe.delete_doc("DocType", doctype, ignore_missing=True) + portal_menu_items = frappe.get_all( + "Portal Menu Item", {"reference_doctype": ("in", doctypes)}, pluck="name" + ) + for menu_item in portal_menu_items: + frappe.delete_doc("Portal Menu Item", menu_item, ignore_missing=True, force=True) + frappe.delete_doc("Module Def", "Education", ignore_missing=True, force=True) click.secho( From e8f6c286d1c3eeff2851da84d8b250bc922d3254 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Fri, 18 Aug 2023 13:21:37 +0530 Subject: [PATCH 5/6] fix: remove portal menu items in pre-model sync patch --- erpnext/patches.txt | 1 + .../delete_education_module_portal_menu_items.py | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 erpnext/patches/v14_0/delete_education_module_portal_menu_items.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 73e0a95da93b..76e4dee9b69d 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -262,6 +262,7 @@ erpnext.patches.v14_0.update_reference_due_date_in_journal_entry erpnext.patches.v15_0.saudi_depreciation_warning erpnext.patches.v15_0.delete_saudi_doctypes erpnext.patches.v14_0.show_loan_management_deprecation_warning +erpnext.patches.v14_0.delete_education_module_portal_menu_items [post_model_sync] execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings') diff --git a/erpnext/patches/v14_0/delete_education_module_portal_menu_items.py b/erpnext/patches/v14_0/delete_education_module_portal_menu_items.py new file mode 100644 index 000000000000..d964f1494415 --- /dev/null +++ b/erpnext/patches/v14_0/delete_education_module_portal_menu_items.py @@ -0,0 +1,13 @@ +# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors +# License: MIT. See LICENSE + +import frappe + + +def execute(): + doctypes = frappe.get_all("DocType", {"module": "education", "custom": 0}, pluck="name") + items = frappe.get_all( + "Portal Menu Item", filters={"reference_doctype": ("in", doctypes)}, pluck="name" + ) + for item in items: + frappe.delete_doc("Portal Menu Item", item, ignore_missing=True, force=True) From a7137514b69caac2a1371d080e902ea982269aa0 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 25 Aug 2023 21:05:49 +0530 Subject: [PATCH 6/6] chore: Update patch --- erpnext/patches/v14_0/delete_education_doctypes.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/erpnext/patches/v14_0/delete_education_doctypes.py b/erpnext/patches/v14_0/delete_education_doctypes.py index 468c2fda32be..56a596a02e7a 100644 --- a/erpnext/patches/v14_0/delete_education_doctypes.py +++ b/erpnext/patches/v14_0/delete_education_doctypes.py @@ -43,14 +43,17 @@ def execute(): frappe.delete_doc("Number Card", card, ignore_missing=True, force=True) doctypes = frappe.get_all("DocType", {"module": "education", "custom": 0}, pluck="name") + for doctype in doctypes: frappe.delete_doc("DocType", doctype, ignore_missing=True) - portal_menu_items = frappe.get_all( - "Portal Menu Item", {"reference_doctype": ("in", doctypes)}, pluck="name" - ) - for menu_item in portal_menu_items: - frappe.delete_doc("Portal Menu Item", menu_item, ignore_missing=True, force=True) + portal_settings = frappe.get_doc("Portal Settings") + + for row in portal_settings.get("menu"): + if row.reference_doctype in doctypes: + row.delete() + + portal_settings.save() frappe.delete_doc("Module Def", "Education", ignore_missing=True, force=True)