diff --git a/crm/api/doc.py b/crm/api/doc.py index 1369a952..4c326b2f 100644 --- a/crm/api/doc.py +++ b/crm/api/doc.py @@ -662,7 +662,7 @@ def get_fields_meta(doctype, restricted_fieldtypes=None, as_array=False, only_re @frappe.whitelist() def remove_assignments(doctype, name, assignees, ignore_permissions=False): - assignees = json.loads(assignees) + assignees = frappe.parse_json(assignees) if not assignees: return diff --git a/crm/api/todo.py b/crm/api/todo.py index dc9dcf28..685e756b 100644 --- a/crm/api/todo.py +++ b/crm/api/todo.py @@ -1,90 +1,79 @@ import frappe from frappe import _ + from crm.fcrm.doctype.crm_notification.crm_notification import notify_user def after_insert(doc, method): - if ( - doc.reference_type in ["CRM Lead", "CRM Deal"] - and doc.reference_name - and doc.allocated_to - ): - fieldname = "lead_owner" if doc.reference_type == "CRM Lead" else "deal_owner" - lead_owner = frappe.db.get_value( - doc.reference_type, doc.reference_name, fieldname - ) - if not lead_owner: - frappe.db.set_value( - doc.reference_type, doc.reference_name, fieldname, doc.allocated_to - ) + if doc.reference_type in ["CRM Lead", "CRM Deal"] and doc.reference_name and doc.allocated_to: + fieldname = "lead_owner" if doc.reference_type == "CRM Lead" else "deal_owner" + owner = frappe.db.get_value(doc.reference_type, doc.reference_name, fieldname) + if not owner: + frappe.db.set_value( + doc.reference_type, doc.reference_name, fieldname, doc.allocated_to, update_modified=False + ) - if ( - doc.reference_type in ["CRM Lead", "CRM Deal", "CRM Task"] - and doc.reference_name - and doc.allocated_to - ): - notify_assigned_user(doc) + if doc.reference_type in ["CRM Lead", "CRM Deal", "CRM Task"] and doc.reference_name and doc.allocated_to: + notify_assigned_user(doc) def on_update(doc, method): - if ( - doc.has_value_changed("status") - and doc.status == "Cancelled" - and doc.reference_type in ["CRM Lead", "CRM Deal", "CRM Task"] - and doc.reference_name - and doc.allocated_to - ): - notify_assigned_user(doc, is_cancelled=True) + if ( + doc.has_value_changed("status") + and doc.status == "Cancelled" + and doc.reference_type in ["CRM Lead", "CRM Deal", "CRM Task"] + and doc.reference_name + and doc.allocated_to + ): + notify_assigned_user(doc, is_cancelled=True) def notify_assigned_user(doc, is_cancelled=False): - _doc = frappe.get_doc(doc.reference_type, doc.reference_name) - owner = frappe.get_cached_value("User", frappe.session.user, "full_name") - notification_text = get_notification_text(owner, doc, _doc, is_cancelled) + _doc = frappe.get_doc(doc.reference_type, doc.reference_name) + owner = frappe.get_cached_value("User", frappe.session.user, "full_name") + notification_text = get_notification_text(owner, doc, _doc, is_cancelled) - message = ( - _("Your assignment on {0} {1} has been removed by {2}").format( - doc.reference_type, doc.reference_name, owner - ) - if is_cancelled - else _("{0} assigned a {1} {2} to you").format( - owner, doc.reference_type, doc.reference_name - ) - ) + message = ( + _("Your assignment on {0} {1} has been removed by {2}").format( + doc.reference_type, doc.reference_name, owner + ) + if is_cancelled + else _("{0} assigned a {1} {2} to you").format(owner, doc.reference_type, doc.reference_name) + ) - redirect_to_doctype, redirect_to_name = get_redirect_to_doc(doc) + redirect_to_doctype, redirect_to_name = get_redirect_to_doc(doc) - notify_user( - { - "owner": frappe.session.user, - "assigned_to": doc.allocated_to, - "notification_type": "Assignment", - "message": message, - "notification_text": notification_text, - "reference_doctype": doc.reference_type, - "reference_docname": doc.reference_name, - "redirect_to_doctype": redirect_to_doctype, - "redirect_to_docname": redirect_to_name, - } - ) + notify_user( + { + "owner": frappe.session.user, + "assigned_to": doc.allocated_to, + "notification_type": "Assignment", + "message": message, + "notification_text": notification_text, + "reference_doctype": doc.reference_type, + "reference_docname": doc.reference_name, + "redirect_to_doctype": redirect_to_doctype, + "redirect_to_docname": redirect_to_name, + } + ) def get_notification_text(owner, doc, reference_doc, is_cancelled=False): - name = doc.reference_name - doctype = doc.reference_type + name = doc.reference_name + doctype = doc.reference_type - if doctype.startswith("CRM "): - doctype = doctype[4:].lower() + if doctype.startswith("CRM "): + doctype = doctype[4:].lower() - if doctype in ["lead", "deal"]: - name = ( - reference_doc.lead_name or name - if doctype == "lead" - else reference_doc.organization or reference_doc.lead_name or name - ) + if doctype in ["lead", "deal"]: + name = ( + reference_doc.lead_name or name + if doctype == "lead" + else reference_doc.organization or reference_doc.lead_name or name + ) - if is_cancelled: - return f""" + if is_cancelled: + return f"""
{ _('Your assignment on {0} {1} has been removed by {2}').format( doctype, @@ -94,7 +83,7 @@ def get_notification_text(owner, doc, reference_doc, is_cancelled=False):
""" - return f""" + return f"""
{ owner } { _('assigned a {0} {1} to you').format( @@ -104,9 +93,9 @@ def get_notification_text(owner, doc, reference_doc, is_cancelled=False):
""" - if doctype == "task": - if is_cancelled: - return f""" + if doctype == "task": + if is_cancelled: + return f"""
{ _('Your assignment on task {0} has been removed by {1}').format( f'{ reference_doc.title }', @@ -114,7 +103,7 @@ def get_notification_text(owner, doc, reference_doc, is_cancelled=False): ) }
""" - return f""" + return f"""
{ owner } { _('assigned a new task {0} to you').format( @@ -125,8 +114,8 @@ def get_notification_text(owner, doc, reference_doc, is_cancelled=False): def get_redirect_to_doc(doc): - if doc.reference_type == "CRM Task": - reference_doc = frappe.get_doc(doc.reference_type, doc.reference_name) - return reference_doc.reference_doctype, reference_doc.reference_docname + if doc.reference_type == "CRM Task": + reference_doc = frappe.get_doc(doc.reference_type, doc.reference_name) + return reference_doc.reference_doctype, reference_doc.reference_docname - return doc.reference_type, doc.reference_name + return doc.reference_type, doc.reference_name diff --git a/frontend/auto-imports.d.ts b/frontend/auto-imports.d.ts new file mode 100644 index 00000000..9d240079 --- /dev/null +++ b/frontend/auto-imports.d.ts @@ -0,0 +1,10 @@ +/* eslint-disable */ +/* prettier-ignore */ +// @ts-nocheck +// noinspection JSUnusedGlobalSymbols +// Generated by unplugin-auto-import +// biome-ignore lint: disable +export {} +declare global { + +} diff --git a/frontend/components.d.ts b/frontend/components.d.ts index afedd3ed..8b1b706a 100644 --- a/frontend/components.d.ts +++ b/frontend/components.d.ts @@ -25,6 +25,7 @@ declare module 'vue' { AscendingIcon: typeof import('./src/components/Icons/AscendingIcon.vue')['default'] AssignmentModal: typeof import('./src/components/Modals/AssignmentModal.vue')['default'] AssignTo: typeof import('./src/components/AssignTo.vue')['default'] + AssignToBody: typeof import('./src/components/AssignToBody.vue')['default'] AttachmentArea: typeof import('./src/components/Activities/AttachmentArea.vue')['default'] AttachmentIcon: typeof import('./src/components/Icons/AttachmentIcon.vue')['default'] AttachmentItem: typeof import('./src/components/AttachmentItem.vue')['default'] @@ -172,6 +173,7 @@ declare module 'vue' { LucideChevronRight: typeof import('~icons/lucide/chevron-right')['default'] LucidePenLine: typeof import('~icons/lucide/pen-line')['default'] LucideRefreshCcw: typeof import('~icons/lucide/refresh-ccw')['default'] + LucideX: typeof import('~icons/lucide/x')['default'] MarkAsDoneIcon: typeof import('./src/components/Icons/MarkAsDoneIcon.vue')['default'] MaximizeIcon: typeof import('./src/components/Icons/MaximizeIcon.vue')['default'] MenuIcon: typeof import('./src/components/Icons/MenuIcon.vue')['default'] diff --git a/frontend/src/components/Activities/Activities.vue b/frontend/src/components/Activities/Activities.vue index 32528416..2c8d0341 100644 --- a/frontend/src/components/Activities/Activities.vue +++ b/frontend/src/components/Activities/Activities.vue @@ -50,11 +50,13 @@ class="activity grid grid-cols-[30px_minmax(auto,_1fr)] gap-2 px-3 sm:gap-4 sm:px-10" >
@@ -72,11 +74,13 @@ class="activity grid grid-cols-[30px_minmax(auto,_1fr)] gap-4 px-3 sm:px-10" >
+
diff --git a/frontend/src/components/AssignTo.vue b/frontend/src/components/AssignTo.vue index 1f42df3a..96d29cb6 100644 --- a/frontend/src/components/AssignTo.vue +++ b/frontend/src/components/AssignTo.vue @@ -1,31 +1,100 @@ diff --git a/frontend/src/components/AssignToBody.vue b/frontend/src/components/AssignToBody.vue new file mode 100644 index 00000000..e4e226b0 --- /dev/null +++ b/frontend/src/components/AssignToBody.vue @@ -0,0 +1,212 @@ + + + diff --git a/frontend/src/components/Modals/AssignmentModal.vue b/frontend/src/components/Modals/AssignmentModal.vue index c6fc6dfd..0a0533dd 100644 --- a/frontend/src/components/Modals/AssignmentModal.vue +++ b/frontend/src/components/Modals/AssignmentModal.vue @@ -1,30 +1,8 @@ + @@ -132,7 +142,7 @@ const addValue = (value) => { } } -function updateAssignees() { +async function updateAssignees() { const removedAssignees = oldAssignees.value .filter( (assignee) => !assignees.value.find((a) => a.name === assignee.name), @@ -146,7 +156,7 @@ function updateAssignees() { .map((assignee) => assignee.name) if (removedAssignees.length) { - call('crm.api.doc.remove_assignments', { + await call('crm.api.doc.remove_assignments', { doctype: props.doctype, name: props.doc.name, assignees: JSON.stringify(removedAssignees), diff --git a/frontend/src/pages/Deal.vue b/frontend/src/pages/Deal.vue index e4be2857..14977a2a 100644 --- a/frontend/src/pages/Deal.vue +++ b/frontend/src/pages/Deal.vue @@ -16,7 +16,7 @@ v-if="document.actions?.length" :actions="document.actions" /> - + - + - +
- +