fix: show linked calls and notes/tasks from linked call log in activity

This commit is contained in:
Shariq Ansari 2025-01-18 16:43:53 +05:30
parent f0180cc2d9
commit dbadd1bf0b
2 changed files with 149 additions and 46 deletions

View File

@ -1,10 +1,11 @@
import json
from bs4 import BeautifulSoup
import frappe
from bs4 import BeautifulSoup
from frappe import _
from frappe.utils.caching import redis_cache
from frappe.desk.form.load import get_docinfo
from frappe.query_builder import JoinType
@frappe.whitelist()
def get_activities(name):
@ -15,11 +16,14 @@ def get_activities(name):
else:
frappe.throw(_("Document not found"), frappe.DoesNotExistError)
def get_deal_activities(name):
get_docinfo('', "CRM Deal", name)
get_docinfo("", "CRM Deal", name)
docinfo = frappe.response["docinfo"]
deal_meta = frappe.get_meta("CRM Deal")
deal_fields = {field.fieldname: {"label": field.label, "options": field.options} for field in deal_meta.fields}
deal_fields = {
field.fieldname: {"label": field.label, "options": field.options} for field in deal_meta.fields
}
avoid_fields = [
"lead",
"response_by",
@ -43,13 +47,15 @@ def get_deal_activities(name):
activities, calls, notes, tasks, attachments = get_lead_activities(lead)
creation_text = "converted the lead to this deal"
activities.append({
"activity_type": "creation",
"creation": doc[0],
"owner": doc[1],
"data": creation_text,
"is_lead": False,
})
activities.append(
{
"activity_type": "creation",
"creation": doc[0],
"owner": doc[1],
"data": creation_text,
"is_lead": False,
}
)
docinfo.versions.reverse()
@ -107,7 +113,7 @@ def get_deal_activities(name):
"creation": comment.creation,
"owner": comment.owner,
"content": comment.content,
"attachments": get_attachments('Comment', comment.name),
"attachments": get_attachments("Comment", comment.name),
"is_lead": False,
}
activities.append(activity)
@ -125,7 +131,7 @@ def get_deal_activities(name):
"recipients": communication.recipients,
"cc": communication.cc,
"bcc": communication.bcc,
"attachments": get_attachments('Communication', communication.name),
"attachments": get_attachments("Communication", communication.name),
"read_by_recipient": communication.read_by_recipient,
"delivery_status": communication.delivery_status,
},
@ -144,21 +150,24 @@ def get_deal_activities(name):
}
activities.append(activity)
calls = calls + get_linked_calls(name)
notes = notes + get_linked_notes(name)
tasks = tasks + get_linked_tasks(name)
attachments = attachments + get_attachments('CRM Deal', name)
calls = calls + get_linked_calls(name).get("calls", [])
notes = notes + get_linked_notes(name) + get_linked_calls(name).get("notes", [])
tasks = tasks + get_linked_tasks(name) + get_linked_calls(name).get("tasks", [])
attachments = attachments + get_attachments("CRM Deal", name)
activities.sort(key=lambda x: x["creation"], reverse=True)
activities = handle_multiple_versions(activities)
return activities, calls, notes, tasks, attachments
def get_lead_activities(name):
get_docinfo('', "CRM Lead", name)
get_docinfo("", "CRM Lead", name)
docinfo = frappe.response["docinfo"]
lead_meta = frappe.get_meta("CRM Lead")
lead_fields = {field.fieldname: {"label": field.label, "options": field.options} for field in lead_meta.fields}
lead_fields = {
field.fieldname: {"label": field.label, "options": field.options} for field in lead_meta.fields
}
avoid_fields = [
"converted",
"response_by",
@ -169,13 +178,15 @@ def get_lead_activities(name):
]
doc = frappe.db.get_values("CRM Lead", name, ["creation", "owner"])[0]
activities = [{
"activity_type": "creation",
"creation": doc[0],
"owner": doc[1],
"data": "created this lead",
"is_lead": True,
}]
activities = [
{
"activity_type": "creation",
"creation": doc[0],
"owner": doc[1],
"data": "created this lead",
"is_lead": True,
}
]
docinfo.versions.reverse()
@ -233,7 +244,7 @@ def get_lead_activities(name):
"creation": comment.creation,
"owner": comment.owner,
"content": comment.content,
"attachments": get_attachments('Comment', comment.name),
"attachments": get_attachments("Comment", comment.name),
"is_lead": True,
}
activities.append(activity)
@ -251,7 +262,7 @@ def get_lead_activities(name):
"recipients": communication.recipients,
"cc": communication.cc,
"bcc": communication.bcc,
"attachments": get_attachments('Communication', communication.name),
"attachments": get_attachments("Communication", communication.name),
"read_by_recipient": communication.read_by_recipient,
"delivery_status": communication.delivery_status,
},
@ -270,10 +281,10 @@ def get_lead_activities(name):
}
activities.append(activity)
calls = get_linked_calls(name)
notes = get_linked_notes(name)
tasks = get_linked_tasks(name)
attachments = get_attachments('CRM Lead', name)
calls = get_linked_calls(name).get("calls", [])
notes = get_linked_notes(name) + get_linked_calls(name).get("notes", [])
tasks = get_linked_tasks(name) + get_linked_calls(name).get("tasks", [])
attachments = get_attachments("CRM Lead", name)
activities.sort(key=lambda x: x["creation"], reverse=True)
activities = handle_multiple_versions(activities)
@ -282,11 +293,25 @@ def get_lead_activities(name):
def get_attachments(doctype, name):
return frappe.db.get_all(
"File",
filters={"attached_to_doctype": doctype, "attached_to_name": name},
fields=["name", "file_name", "file_type", "file_url", "file_size", "is_private", "creation", "owner"],
) or []
return (
frappe.db.get_all(
"File",
filters={"attached_to_doctype": doctype, "attached_to_name": name},
fields=[
"name",
"file_name",
"file_type",
"file_url",
"file_size",
"is_private",
"modified",
"creation",
"owner",
],
)
or []
)
def handle_multiple_versions(versions):
activities = []
@ -298,7 +323,8 @@ def handle_multiple_versions(versions):
activities.append(version)
if not old_version:
old_version = version
if is_version: grouped_versions.append(version)
if is_version:
grouped_versions.append(version)
continue
if is_version and old_version.get("owner") and version["owner"] == old_version["owner"]:
grouped_versions.append(version)
@ -306,13 +332,15 @@ def handle_multiple_versions(versions):
if grouped_versions:
activities.append(parse_grouped_versions(grouped_versions))
grouped_versions = []
if is_version: grouped_versions.append(version)
if is_version:
grouped_versions.append(version)
old_version = version
if version == versions[-1] and grouped_versions:
activities.append(parse_grouped_versions(grouped_versions))
return activities
def parse_grouped_versions(versions):
version = versions[0]
if len(versions) == 1:
@ -321,6 +349,7 @@ def parse_grouped_versions(versions):
version["other_versions"] = other_versions
return version
def get_linked_calls(name):
calls = frappe.db.get_all(
"CRM Call Log",
@ -341,16 +370,87 @@ def get_linked_calls(name):
"note",
],
)
return calls or []
linked_calls = frappe.db.get_all(
"Dynamic Link", filters={"link_name": name, "parenttype": "CRM Call Log"}, pluck="parent"
)
notes = []
tasks = []
if linked_calls:
CallLog = frappe.qb.DocType("CRM Call Log")
Link = frappe.qb.DocType("Dynamic Link")
query = (
frappe.qb.from_(CallLog)
.select(
CallLog.name,
CallLog.caller,
CallLog.receiver,
CallLog["from"],
CallLog.to,
CallLog.duration,
CallLog.start_time,
CallLog.end_time,
CallLog.status,
CallLog.type,
CallLog.recording_url,
CallLog.creation,
CallLog.note,
Link.link_doctype,
Link.link_name,
)
.join(Link, JoinType.inner)
.on(Link.parent == CallLog.name)
.where(CallLog.name.isin(linked_calls))
)
_calls = query.run(as_dict=True)
for call in _calls:
if call.get("link_doctype") == "FCRM Note":
notes.append(call.link_name)
elif call.get("link_doctype") == "CRM Task":
tasks.append(call.link_name)
_calls = [call for call in _calls if call.get("link_doctype") not in ["FCRM Note", "CRM Task"]]
if _calls:
calls = calls + _calls
if notes:
notes = frappe.db.get_all(
"FCRM Note",
filters={"name": ("in", notes)},
fields=["name", "title", "content", "owner", "modified"],
)
if tasks:
tasks = frappe.db.get_all(
"CRM Task",
filters={"name": ("in", tasks)},
fields=[
"name",
"title",
"description",
"assigned_to",
"due_date",
"priority",
"status",
"modified",
],
)
return {"calls": calls, "notes": notes, "tasks": tasks}
def get_linked_notes(name):
notes = frappe.db.get_all(
"FCRM Note",
filters={"reference_docname": name},
fields=['name', 'title', 'content', 'owner', 'modified'],
fields=["name", "title", "content", "owner", "modified"],
)
return notes or []
def get_linked_tasks(name):
tasks = frappe.db.get_all(
"CRM Task",
@ -360,7 +460,6 @@ def get_linked_tasks(name):
"title",
"description",
"assigned_to",
"assigned_to",
"due_date",
"priority",
"status",
@ -369,6 +468,7 @@ def get_linked_tasks(name):
)
return tasks or []
def parse_attachment_log(html, type):
soup = BeautifulSoup(html, "html.parser")
a_tag = soup.find("a")
@ -390,4 +490,4 @@ def parse_attachment_log(html, type):
"file_name": a_tag.text,
"file_url": a_tag["href"],
"is_private": is_private,
}
}

View File

@ -662,13 +662,13 @@ const activities = computed(() => {
return sortByCreation(all_activities.data.calls)
} else if (title.value == 'Tasks') {
if (!all_activities.data?.tasks) return []
return sortByCreation(all_activities.data.tasks)
return sortByModified(all_activities.data.tasks)
} else if (title.value == 'Notes') {
if (!all_activities.data?.notes) return []
return sortByCreation(all_activities.data.notes)
return sortByModified(all_activities.data.notes)
} else if (title.value == 'Attachments') {
if (!all_activities.data?.attachments) return []
return sortByCreation(all_activities.data.attachments)
return sortByModified(all_activities.data.attachments)
}
_activities.forEach((activity) => {
@ -696,6 +696,9 @@ const activities = computed(() => {
function sortByCreation(list) {
return list.sort((a, b) => new Date(a.creation) - new Date(b.creation))
}
function sortByModified(list) {
return list.sort((b, a) => new Date(a.modified) - new Date(b.modified))
}
function update_activities_details(activity) {
activity.owner_name = getUser(activity.owner).full_name