Skip to content

Commit

Permalink
Merge pull request #370 from frappe/develop
Browse files Browse the repository at this point in the history
chore: Merge develop to main
  • Loading branch information
shariquerik authored Sep 24, 2024
2 parents 205b360 + 446c367 commit afcb471
Show file tree
Hide file tree
Showing 9 changed files with 211 additions and 52 deletions.
28 changes: 12 additions & 16 deletions crm/api/comment.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import frappe
from frappe import _
from bs4 import BeautifulSoup
from crm.fcrm.doctype.crm_notification.crm_notification import notify_user

def on_update(self, method):
notify_mentions(self)
Expand All @@ -29,22 +30,17 @@ def notify_mentions(doc):
<span class="font-medium text-gray-900">{ doc.reference_name }</span>
</div>
"""
values = frappe._dict(
doctype="CRM Notification",
from_user=doc.owner,
to_user=mention.email,
type="Mention",
message=doc.content,
notification_text=notification_text,
notification_type_doctype="Comment",
notification_type_doc=doc.name,
reference_doctype=doc.reference_doctype,
reference_name=doc.reference_name,
)

if frappe.db.exists("CRM Notification", values):
return
frappe.get_doc(values).insert()
notify_user({
"owner": doc.owner,
"assigned_to": mention.email,
"notification_type": "Mention",
"message": doc.content,
"notification_text": notification_text,
"reference_doctype": "Comment",
"reference_docname": doc.name,
"redirect_to_doctype": doc.reference_doctype,
"redirect_to_docname": doc.reference_name,
})


def extract_mentions(html):
Expand Down
16 changes: 16 additions & 0 deletions crm/api/contact.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ def validate(doc, method):
set_primary_mobile_no(doc)
doc.set_primary_email()
doc.set_primary("mobile_no")
update_deals_email_mobile_no(doc)


def set_primary_email(doc):
Expand All @@ -25,6 +26,21 @@ def set_primary_mobile_no(doc):
doc.phone_nos[0].is_primary_mobile_no = 1


def update_deals_email_mobile_no(doc):
linked_deals = frappe.get_all(
"CRM Contacts",
filters={"contact": doc.name, "is_primary": 1},
fields=["parent"],
)

for linked_deal in linked_deals:
deal = frappe.get_cached_doc("CRM Deal", linked_deal.parent)
if deal.email != doc.email_id or deal.mobile_no != doc.mobile_no:
deal.email = doc.email_id
deal.mobile_no = doc.mobile_no
deal.save(ignore_permissions=True)


@frappe.whitelist()
def get_contact(name):
Contact = frappe.qb.DocType("Contact")
Expand Down
97 changes: 96 additions & 1 deletion crm/api/todo.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,103 @@
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)
frappe.db.set_value(doc.reference_type, doc.reference_name, fieldname, doc.allocated_to)

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)

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)

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)

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

if doctype.startswith("CRM "):
doctype = doctype[4:].lower()

if doctype in ["CRM Lead", "CRM Deal"]:
name = reference_doc.lead_name or name if doctype == "CRM Lead" else reference_doc.organization or reference_doc.lead_name or name

if is_cancelled:
return f"""
<div class="mb-2 leading-5 text-gray-600">
<span>{ _('Your assignment on {0} {1} has been removed by {2}').format(
doctype,
f'<span class="font-medium text-gray-900">{ name }</span>',
f'<span class="font-medium text-gray-900">{ owner }</span>'
) }</span>
</div>
"""

return f"""
<div class="mb-2 leading-5 text-gray-600">
<span class="font-medium text-gray-900">{ owner }</span>
<span>{ _('assigned a {0} {1} to you').format(
doctype,
f'<span class="font-medium text-gray-900">{ name }</span>'
) }</span>
</div>
"""

if doc.reference_type == "CRM Task":
if is_cancelled:
return f"""
<div class="mb-2 leading-5 text-gray-600">
<span>{ _('Your assignment on task {0} has been removed by {1}').format(
f'<span class="font-medium text-gray-900">{ reference_doc.title }</span>',
f'<span class="font-medium text-gray-900">{ owner }</span>'
) }</span>
</div>
"""
return f"""
<div class="mb-2 leading-5 text-gray-600">
<span class="font-medium text-gray-900">{ owner }</span>
<span>{ _('assigned a new task {0} to you').format(
f'<span class="font-medium text-gray-900">{ reference_doc.title }</span>'
) }</span>
</div>
"""

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

return doc.reference_type, doc.reference_name
48 changes: 22 additions & 26 deletions crm/api/whatsapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import json
from frappe import _
from crm.api.doc import get_assigned_users
from crm.fcrm.doctype.crm_notification.crm_notification import notify_user


def validate(doc, method):
Expand Down Expand Up @@ -29,30 +30,25 @@ def notify_agent(doc):
if doctype.startswith("CRM "):
doctype = doctype[4:].lower()
notification_text = f"""
<div class="mb-2 leading-5 text-gray-600">
<span class="font-medium text-gray-900">{ _('You') }</span>
<span>{ _('received a whatsapp message in {0}').format(doctype) }</span>
<span class="font-medium text-gray-900">{ doc.reference_name }</span>
</div>
"""
<div class="mb-2 leading-5 text-gray-600">
<span class="font-medium text-gray-900">{ _('You') }</span>
<span>{ _('received a whatsapp message in {0}').format(doctype) }</span>
<span class="font-medium text-gray-900">{ doc.reference_name }</span>
</div>
"""
assigned_users = get_assigned_users(doc.reference_doctype, doc.reference_name)
for user in assigned_users:
values = frappe._dict(
doctype="CRM Notification",
from_user=doc.owner,
to_user=user,
type="WhatsApp",
message=doc.message,
notification_text=notification_text,
notification_type_doctype="WhatsApp Message",
notification_type_doc=doc.name,
reference_doctype=doc.reference_doctype,
reference_name=doc.reference_name,
)

if frappe.db.exists("CRM Notification", values):
return
frappe.get_doc(values).insert(ignore_permissions=True)
notify_user({
"owner": doc.owner,
"assigned_to": user,
"notification_type": "WhatsApp",
"message": doc.message,
"notification_text": notification_text,
"reference_doctype": "WhatsApp Message",
"reference_docname": doc.name,
"redirect_to_doctype": doc.reference_doctype,
"redirect_to_docname": doc.reference_name,
})


def get_lead_or_deal_from_number(number):
Expand All @@ -62,10 +58,10 @@ def find_record(doctype, mobile_no, where=""):
mobile_no = parse_mobile_no(mobile_no)

query = f"""
SELECT name, mobile_no
FROM `tab{doctype}`
WHERE CONCAT('+', REGEXP_REPLACE(mobile_no, '[^0-9]', '')) = {mobile_no}
"""
SELECT name, mobile_no
FROM `tab{doctype}`
WHERE CONCAT('+', REGEXP_REPLACE(mobile_no, '[^0-9]', '')) = {mobile_no}
"""

data = frappe.db.sql(query + where, as_dict=True)
return data[0].name if data else None
Expand Down
4 changes: 2 additions & 2 deletions crm/fcrm/doctype/crm_notification/crm_notification.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"fieldtype": "Select",
"in_list_view": 1,
"label": "Type",
"options": "Mention\nWhatsApp",
"options": "Mention\nTask\nAssignment\nWhatsApp",
"reqd": 1
},
{
Expand Down Expand Up @@ -116,7 +116,7 @@
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2024-04-25 16:26:07.484857",
"modified": "2024-09-23 19:34:08.635305",
"modified_by": "Administrator",
"module": "FCRM",
"name": "CRM Notification",
Expand Down
30 changes: 28 additions & 2 deletions crm/fcrm/doctype/crm_notification/crm_notification.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,35 @@
# For license information, please see license.txt

import frappe
from frappe import _
from frappe.model.document import Document


class CRMNotification(Document):
def on_update(self):
frappe.publish_realtime("crm_notification")
def on_update(self):
frappe.publish_realtime("crm_notification")

def notify_user(args):
"""
Notify the assigned user
"""
args = frappe._dict(args)
if args.owner == args.assigned_to:
return

values = frappe._dict(
doctype="CRM Notification",
from_user=args.owner,
to_user=args.assigned_to,
type=args.notification_type,
message=args.message,
notification_text=args.notification_text,
notification_type_doctype=args.reference_doctype,
notification_type_doc=args.reference_docname,
reference_doctype=args.redirect_to_doctype,
reference_name=args.redirect_to_docname,
)

if frappe.db.exists("CRM Notification", values):
return
frappe.get_doc(values).insert(ignore_permissions=True)
29 changes: 28 additions & 1 deletion crm/fcrm/doctype/crm_task/crm_task.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,38 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt

# import frappe
import frappe
from frappe import _
from frappe.model.document import Document
from frappe.desk.form.assign_to import add as assign, remove as unassign
from crm.fcrm.doctype.crm_notification.crm_notification import notify_user


class CRMTask(Document):
def after_insert(self):
self.assign_to()

def validate(self):
if self.is_new() or not self.assigned_to:
return

if self.get_doc_before_save().assigned_to != self.assigned_to:
self.unassign_from_previous_user(self.get_doc_before_save().assigned_to)
self.assign_to()

def unassign_from_previous_user(self, user):
unassign(self.doctype, self.name, user)

def assign_to(self):
if self.assigned_to:
assign({
"assign_to": [self.assigned_to],
"doctype": self.doctype,
"name": self.name,
"description": self.title or self.description,
})


@staticmethod
def default_list_data():
columns = [
Expand Down
5 changes: 3 additions & 2 deletions crm/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@
},
"ToDo": {
"after_insert": ["crm.api.todo.after_insert"],
"on_update": ["crm.api.todo.on_update"],
},
"Comment": {
"on_update": ["crm.api.comment.on_update"],
Expand All @@ -152,8 +153,8 @@
"validate": ["crm.api.whatsapp.validate"],
"on_update": ["crm.api.whatsapp.on_update"],
},
"CRM Deal": {
"on_update": ["crm.fcrm.doctype.erpnext_crm_settings.erpnext_crm_settings.create_customer_in_erpnext"],
"CRM Deal": {
"on_update": ["crm.fcrm.doctype.erpnext_crm_settings.erpnext_crm_settings.create_customer_in_erpnext"],
},
}

Expand Down
6 changes: 4 additions & 2 deletions frontend/src/components/ListViews/TasksListView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@
:row="row"
>
<div v-if="column.key === 'due_date'">
<Tooltip :text="dateFormat(item, 'ddd, MMM D, YYYY | hh:mm a')">
<Tooltip
:text="item && dateFormat(item, 'ddd, MMM D, YYYY | hh:mm a')"
>
<div class="flex items-center gap-2 truncate text-base">
<CalendarIcon />
<div><CalendarIcon /></div>
<div v-if="item" class="truncate">
{{ dateFormat(item, 'D MMM, hh:mm a') }}
</div>
Expand Down

0 comments on commit afcb471

Please sign in to comment.