From ae8dd2b2bc86cf36162e905ccce9b371b7c123d2 Mon Sep 17 00:00:00 2001 From: Daizy Modi Date: Thu, 15 Dec 2022 16:47:27 +0530 Subject: [PATCH 1/8] fix: remove guest role from doctype --- erpnext/crm/doctype/appointment/appointment.json | 13 ++----------- .../appointment_booking_settings.json | 12 ++++-------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/erpnext/crm/doctype/appointment/appointment.json b/erpnext/crm/doctype/appointment/appointment.json index fe7b4e17f0b9..c26b064c4c56 100644 --- a/erpnext/crm/doctype/appointment/appointment.json +++ b/erpnext/crm/doctype/appointment/appointment.json @@ -102,7 +102,7 @@ } ], "links": [], - "modified": "2021-06-30 13:09:14.228756", + "modified": "2022-12-15 11:11:02.131986", "modified_by": "Administrator", "module": "CRM", "name": "Appointment", @@ -121,16 +121,6 @@ "share": 1, "write": 1 }, - { - "create": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "Guest", - "share": 1 - }, { "create": 1, "delete": 1, @@ -170,5 +160,6 @@ "quick_entry": 1, "sort_field": "modified", "sort_order": "DESC", + "states": [], "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json b/erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json index 4b26e4901bd4..436eb10c888e 100644 --- a/erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json +++ b/erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json @@ -1,4 +1,5 @@ { + "actions": [], "creation": "2019-08-27 10:56:48.309824", "doctype": "DocType", "editable_grid": 1, @@ -101,7 +102,8 @@ } ], "issingle": 1, - "modified": "2019-11-26 12:14:17.669366", + "links": [], + "modified": "2022-12-15 11:10:13.517742", "modified_by": "Administrator", "module": "CRM", "name": "Appointment Booking Settings", @@ -117,13 +119,6 @@ "share": 1, "write": 1 }, - { - "email": 1, - "print": 1, - "read": 1, - "role": "Guest", - "share": 1 - }, { "create": 1, "email": 1, @@ -147,5 +142,6 @@ "quick_entry": 1, "sort_field": "modified", "sort_order": "DESC", + "states": [], "track_changes": 1 } \ No newline at end of file From 25f0b26a17e98aa8d01533f0a183e030e2be82f7 Mon Sep 17 00:00:00 2001 From: Daizy Modi Date: Thu, 15 Dec 2022 16:49:23 +0530 Subject: [PATCH 2/8] fix: remove unused page `book-appointment` --- erpnext/www/book-appointment/__init__.py | 0 erpnext/www/book-appointment/verify/__init__.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 erpnext/www/book-appointment/__init__.py delete mode 100644 erpnext/www/book-appointment/verify/__init__.py diff --git a/erpnext/www/book-appointment/__init__.py b/erpnext/www/book-appointment/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/erpnext/www/book-appointment/verify/__init__.py b/erpnext/www/book-appointment/verify/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 From 9a00b3bdbd15f4ab83c496e7ee4a35e447b4cfe6 Mon Sep 17 00:00:00 2001 From: Daizy Modi Date: Thu, 15 Dec 2022 16:51:00 +0530 Subject: [PATCH 3/8] fix: format html of verify email for book appointment --- erpnext/www/book_appointment/verify/index.html | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/erpnext/www/book_appointment/verify/index.html b/erpnext/www/book_appointment/verify/index.html index 58c07e85ccce..eaaf8ecfc737 100644 --- a/erpnext/www/book_appointment/verify/index.html +++ b/erpnext/www/book_appointment/verify/index.html @@ -5,14 +5,12 @@ {% endblock%} {% block page_content %} - - {% if success==True %} -
+ {%- set alert_class = 'alert-success' if success else 'alert-danger' -%} +
+ {% if success==True %} {{ _("Your email has been verified and your appointment has been scheduled") }} -
- {% else %} -
+ {% else %} {{ _("Verification failed please check the link") }} -
- {% endif %} + {% endif %} +
{% endblock%} From ac51c2750043d8fe5e2be329eded7a7f6eef2c57 Mon Sep 17 00:00:00 2001 From: Daizy Modi Date: Thu, 15 Dec 2022 16:53:51 +0530 Subject: [PATCH 4/8] fix: fetch required details from appointment booking settings --- erpnext/www/book_appointment/index.py | 38 ++++++++++++-------- erpnext/www/book_appointment/verify/index.py | 4 +-- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/erpnext/www/book_appointment/index.py b/erpnext/www/book_appointment/index.py index 06e99da3f946..8cb66275e051 100644 --- a/erpnext/www/book_appointment/index.py +++ b/erpnext/www/book_appointment/index.py @@ -26,8 +26,12 @@ def get_context(context): @frappe.whitelist(allow_guest=True) def get_appointment_settings(): - settings = frappe.get_doc("Appointment Booking Settings") - settings.holiday_list = frappe.get_doc("Holiday List", settings.holiday_list) + settings = frappe.get_cached_value( + "Appointment Booking Settings", + None, + ["holiday_list", "advance_booking_days", "appointment_duration", "success_redirect_url"], + as_dict=True, + ) return settings @@ -90,23 +94,27 @@ def get_available_slots_between(query_start_time, query_end_time, settings): @frappe.whitelist(allow_guest=True) def create_appointment(date, time, tz, contact): - format_string = "%Y-%m-%d %H:%M:%S" - scheduled_time = datetime.datetime.strptime(date + " " + time, format_string) + contact = json.loads(contact) + datetime_obj = datetime.datetime.strptime(date + " " + time, "%Y-%m-%d %H:%M:%S") # Strip tzinfo from datetime objects since it's handled by the doctype + scheduled_time_obj = datetime_obj.replace(tzinfo=None) + scheduled_time = convert_to_system_timezone(tz, scheduled_time_obj) scheduled_time = scheduled_time.replace(tzinfo=None) - scheduled_time = convert_to_system_timezone(tz, scheduled_time) - scheduled_time = scheduled_time.replace(tzinfo=None) + # Create a appointment document from form appointment = frappe.new_doc("Appointment") - appointment.scheduled_time = scheduled_time - contact = json.loads(contact) - appointment.customer_name = contact.get("name", None) - appointment.customer_phone_number = contact.get("number", None) - appointment.customer_skype = contact.get("skype", None) - appointment.customer_details = contact.get("notes", None) - appointment.customer_email = contact.get("email", None) - appointment.status = "Open" - appointment.insert() + appointment.update( + { + "scheduled_time": scheduled_time, + "customer_name": contact.get("name", None), + "customer_phone_number": contact.get("number", None), + "customer_skype": contact.get("skype", None), + "customer_details": contact.get("notes", None), + "customer_email": contact.get("email", None), + "status": "Open", + } + ) + appointment.insert(ignore_permissions=True) return appointment diff --git a/erpnext/www/book_appointment/verify/index.py b/erpnext/www/book_appointment/verify/index.py index 1a5ba9de7e50..4a1ed75ee905 100644 --- a/erpnext/www/book_appointment/verify/index.py +++ b/erpnext/www/book_appointment/verify/index.py @@ -2,7 +2,6 @@ from frappe.utils.verified_command import verify_request -@frappe.whitelist(allow_guest=True) def get_context(context): if not verify_request(): context.success = False @@ -15,7 +14,6 @@ def get_context(context): appointment = frappe.get_doc("Appointment", appointment_name) appointment.set_verified(email) context.success = True - return context else: context.success = False - return context + return context From 4bfe2ea572c32d1ad8c8d927bf4f43ad5be86df4 Mon Sep 17 00:00:00 2001 From: Daizy Modi Date: Thu, 15 Dec 2022 17:19:28 +0530 Subject: [PATCH 5/8] fix: agent assignment and permissions for appointment --- .../crm/doctype/appointment/appointment.py | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/erpnext/crm/doctype/appointment/appointment.py b/erpnext/crm/doctype/appointment/appointment.py index 6e7ba1fd5bcc..29d092245b44 100644 --- a/erpnext/crm/doctype/appointment/appointment.py +++ b/erpnext/crm/doctype/appointment/appointment.py @@ -6,7 +6,9 @@ import frappe from frappe import _ +from frappe.desk.form.assign_to import add as add_assignment from frappe.model.document import Document +from frappe.share import add_docshare from frappe.utils import get_url, getdate, now from frappe.utils.verified_command import get_signed_params @@ -130,13 +132,13 @@ def create_lead_and_link(self): self.party = lead.name def auto_assign(self): - from frappe.desk.form.assign_to import add as add_assignemnt - existing_assignee = self.get_assignee_from_latest_opportunity() if existing_assignee: # If the latest opportunity is assigned to someone # Assign the appointment to the same - add_assignemnt({"doctype": self.doctype, "name": self.name, "assign_to": [existing_assignee]}) + add_agent_assignment( + {"doctype": self.doctype, "name": self.name, "assign_to": [existing_assignee]} + ) return if self._assign: return @@ -144,7 +146,7 @@ def auto_assign(self): for agent in available_agents: if _check_agent_availability(agent, self.scheduled_time): agent = agent[0] - add_assignemnt({"doctype": self.doctype, "name": self.name, "assign_to": [agent]}) + add_agent_assignment({"doctype": self.doctype, "name": self.name, "assign_to": [agent]}) break def get_assignee_from_latest_opportunity(self): @@ -201,7 +203,7 @@ def _get_verify_url(self): def _get_agents_sorted_by_asc_workload(date): - appointments = frappe.db.get_list("Appointment", fields="*") + appointments = frappe.get_all("Appointment", fields="*") agent_list = _get_agent_list_as_strings() if not appointments: return agent_list @@ -226,7 +228,7 @@ def _get_agent_list_as_strings(): def _check_agent_availability(agent_email, scheduled_time): - appointemnts_at_scheduled_time = frappe.get_list( + appointemnts_at_scheduled_time = frappe.get_all( "Appointment", filters={"scheduled_time": scheduled_time} ) for appointment in appointemnts_at_scheduled_time: @@ -240,3 +242,12 @@ def _get_employee_from_user(user): if employee_docname: return frappe.get_doc("Employee", employee_docname) return None + + +def add_agent_assignment(args): + doc = frappe.get_cached_doc(args.get("doctype"), args.get("name")) + for assign_to in args.get("assign_to"): + if not frappe.has_permission(doc=doc, user=assign_to): + add_docshare(doc.doctype, doc.name, assign_to, flags={"ignore_share_permission": True}) + + add_assignment(args) From 56f3ac15d8e043080ab0050694d7d627e5a3cfad Mon Sep 17 00:00:00 2001 From: Daizy Modi Date: Thu, 15 Dec 2022 18:02:14 +0530 Subject: [PATCH 6/8] fix: removed unncessary changes --- erpnext/crm/doctype/appointment/appointment.py | 8 +++++--- erpnext/www/book_appointment/verify/index.html | 14 ++++++++------ erpnext/www/book_appointment/verify/index.py | 3 ++- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/erpnext/crm/doctype/appointment/appointment.py b/erpnext/crm/doctype/appointment/appointment.py index 29d092245b44..8480f2ca44a0 100644 --- a/erpnext/crm/doctype/appointment/appointment.py +++ b/erpnext/crm/doctype/appointment/appointment.py @@ -245,9 +245,11 @@ def _get_employee_from_user(user): def add_agent_assignment(args): - doc = frappe.get_cached_doc(args.get("doctype"), args.get("name")) + doctype = args.get("doctype") + docname = args.get("name") + for assign_to in args.get("assign_to"): - if not frappe.has_permission(doc=doc, user=assign_to): - add_docshare(doc.doctype, doc.name, assign_to, flags={"ignore_share_permission": True}) + if not frappe.has_permission(doctype=doctype, doc=docname, user=assign_to): + add_docshare(doctype, docname, assign_to, flags={"ignore_share_permission": True}) add_assignment(args) diff --git a/erpnext/www/book_appointment/verify/index.html b/erpnext/www/book_appointment/verify/index.html index eaaf8ecfc737..58c07e85ccce 100644 --- a/erpnext/www/book_appointment/verify/index.html +++ b/erpnext/www/book_appointment/verify/index.html @@ -5,12 +5,14 @@ {% endblock%} {% block page_content %} - {%- set alert_class = 'alert-success' if success else 'alert-danger' -%} -
- {% if success==True %} + + {% if success==True %} +
{{ _("Your email has been verified and your appointment has been scheduled") }} - {% else %} +
+ {% else %} +
{{ _("Verification failed please check the link") }} - {% endif %} -
+
+ {% endif %} {% endblock%} diff --git a/erpnext/www/book_appointment/verify/index.py b/erpnext/www/book_appointment/verify/index.py index 4a1ed75ee905..3beb8667ae7b 100644 --- a/erpnext/www/book_appointment/verify/index.py +++ b/erpnext/www/book_appointment/verify/index.py @@ -14,6 +14,7 @@ def get_context(context): appointment = frappe.get_doc("Appointment", appointment_name) appointment.set_verified(email) context.success = True + return context else: context.success = False - return context + return context From 5d0b5c8d2a0564fedef0683971391863a70915a4 Mon Sep 17 00:00:00 2001 From: Daizy Modi Date: Fri, 16 Dec 2022 10:10:29 +0530 Subject: [PATCH 7/8] fix: pass necessary params instead of args --- .../crm/doctype/appointment/appointment.py | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/erpnext/crm/doctype/appointment/appointment.py b/erpnext/crm/doctype/appointment/appointment.py index 8480f2ca44a0..a4e00d6c47b3 100644 --- a/erpnext/crm/doctype/appointment/appointment.py +++ b/erpnext/crm/doctype/appointment/appointment.py @@ -136,9 +136,7 @@ def auto_assign(self): if existing_assignee: # If the latest opportunity is assigned to someone # Assign the appointment to the same - add_agent_assignment( - {"doctype": self.doctype, "name": self.name, "assign_to": [existing_assignee]} - ) + assign_agents(self.doctype, self.name, [existing_assignee]) return if self._assign: return @@ -146,7 +144,7 @@ def auto_assign(self): for agent in available_agents: if _check_agent_availability(agent, self.scheduled_time): agent = agent[0] - add_agent_assignment({"doctype": self.doctype, "name": self.name, "assign_to": [agent]}) + assign_agents(self.doctype, self.name, [agent]) break def get_assignee_from_latest_opportunity(self): @@ -244,12 +242,9 @@ def _get_employee_from_user(user): return None -def add_agent_assignment(args): - doctype = args.get("doctype") - docname = args.get("name") - - for assign_to in args.get("assign_to"): - if not frappe.has_permission(doctype=doctype, doc=docname, user=assign_to): - add_docshare(doctype, docname, assign_to, flags={"ignore_share_permission": True}) +def assign_agents(doctype: str, name: str, agents: list[str]) -> None: + for agent in agents: + if not frappe.has_permission(doctype=doctype, doc=name, user=agent): + add_docshare(doctype, name, agent, flags={"ignore_share_permission": True}) - add_assignment(args) + add_assignment({"doctype": doctype, "name": name, "assign_to": agents}) From 4802d719edf62e558b623b5dceaa75991df3a607 Mon Sep 17 00:00:00 2001 From: Daizy Modi Date: Fri, 16 Dec 2022 15:55:58 +0530 Subject: [PATCH 8/8] fix: removed unused data and minor changes --- .../crm/doctype/appointment/appointment.py | 19 +++++------- erpnext/www/book_appointment/index.js | 3 -- erpnext/www/book_appointment/index.py | 30 ++++++++----------- 3 files changed, 21 insertions(+), 31 deletions(-) diff --git a/erpnext/crm/doctype/appointment/appointment.py b/erpnext/crm/doctype/appointment/appointment.py index a4e00d6c47b3..bd49bdc925c4 100644 --- a/erpnext/crm/doctype/appointment/appointment.py +++ b/erpnext/crm/doctype/appointment/appointment.py @@ -136,15 +136,14 @@ def auto_assign(self): if existing_assignee: # If the latest opportunity is assigned to someone # Assign the appointment to the same - assign_agents(self.doctype, self.name, [existing_assignee]) + self.assign_agent(existing_assignee) return if self._assign: return available_agents = _get_agents_sorted_by_asc_workload(getdate(self.scheduled_time)) for agent in available_agents: if _check_agent_availability(agent, self.scheduled_time): - agent = agent[0] - assign_agents(self.doctype, self.name, [agent]) + self.assign_agent(agent[0]) break def get_assignee_from_latest_opportunity(self): @@ -199,6 +198,12 @@ def _get_verify_url(self): params = {"email": self.customer_email, "appointment": self.name} return get_url(verify_route + "?" + get_signed_params(params)) + def assign_agent(self, agent): + if not frappe.has_permission(doc=self, user=agent): + add_docshare(self.doctype, self.name, agent, flags={"ignore_share_permission": True}) + + add_assignment({"doctype": self.doctype, "name": self.name, "assign_to": [agent]}) + def _get_agents_sorted_by_asc_workload(date): appointments = frappe.get_all("Appointment", fields="*") @@ -240,11 +245,3 @@ def _get_employee_from_user(user): if employee_docname: return frappe.get_doc("Employee", employee_docname) return None - - -def assign_agents(doctype: str, name: str, agents: list[str]) -> None: - for agent in agents: - if not frappe.has_permission(doctype=doctype, doc=name, user=agent): - add_docshare(doctype, name, agent, flags={"ignore_share_permission": True}) - - add_assignment({"doctype": doctype, "name": name, "assign_to": agents}) diff --git a/erpnext/www/book_appointment/index.js b/erpnext/www/book_appointment/index.js index 46ac15518c7e..d02cdad4cf48 100644 --- a/erpnext/www/book_appointment/index.js +++ b/erpnext/www/book_appointment/index.js @@ -2,8 +2,6 @@ frappe.ready(async () => { initialise_select_date(); }) -window.holiday_list = []; - async function initialise_select_date() { navigate_to_page(1); await get_global_variables(); @@ -20,7 +18,6 @@ async function get_global_variables() { window.timezones = (await frappe.call({ method:'erpnext.www.book_appointment.index.get_timezones' })).message; - window.holiday_list = window.appointment_settings.holiday_list; } function setup_timezone_selector() { diff --git a/erpnext/www/book_appointment/index.py b/erpnext/www/book_appointment/index.py index 8cb66275e051..dfca9465ed1c 100644 --- a/erpnext/www/book_appointment/index.py +++ b/erpnext/www/book_appointment/index.py @@ -29,7 +29,7 @@ def get_appointment_settings(): settings = frappe.get_cached_value( "Appointment Booking Settings", None, - ["holiday_list", "advance_booking_days", "appointment_duration", "success_redirect_url"], + ["advance_booking_days", "appointment_duration", "success_redirect_url"], as_dict=True, ) return settings @@ -94,26 +94,22 @@ def get_available_slots_between(query_start_time, query_end_time, settings): @frappe.whitelist(allow_guest=True) def create_appointment(date, time, tz, contact): - contact = json.loads(contact) - datetime_obj = datetime.datetime.strptime(date + " " + time, "%Y-%m-%d %H:%M:%S") + format_string = "%Y-%m-%d %H:%M:%S" + scheduled_time = datetime.datetime.strptime(date + " " + time, format_string) # Strip tzinfo from datetime objects since it's handled by the doctype - scheduled_time_obj = datetime_obj.replace(tzinfo=None) - scheduled_time = convert_to_system_timezone(tz, scheduled_time_obj) scheduled_time = scheduled_time.replace(tzinfo=None) - + scheduled_time = convert_to_system_timezone(tz, scheduled_time) + scheduled_time = scheduled_time.replace(tzinfo=None) # Create a appointment document from form appointment = frappe.new_doc("Appointment") - appointment.update( - { - "scheduled_time": scheduled_time, - "customer_name": contact.get("name", None), - "customer_phone_number": contact.get("number", None), - "customer_skype": contact.get("skype", None), - "customer_details": contact.get("notes", None), - "customer_email": contact.get("email", None), - "status": "Open", - } - ) + appointment.scheduled_time = scheduled_time + contact = json.loads(contact) + appointment.customer_name = contact.get("name", None) + appointment.customer_phone_number = contact.get("number", None) + appointment.customer_skype = contact.get("skype", None) + appointment.customer_details = contact.get("notes", None) + appointment.customer_email = contact.get("email", None) + appointment.status = "Open" appointment.insert(ignore_permissions=True) return appointment