Merge pull request #18353 from surajshetty3416/refactor-call-popup
fix(call popup): Multiple changes
This commit is contained in:
commit
9002a6c195
@ -8,12 +8,18 @@
|
|||||||
"from",
|
"from",
|
||||||
"to",
|
"to",
|
||||||
"column_break_3",
|
"column_break_3",
|
||||||
|
"received_by",
|
||||||
"medium",
|
"medium",
|
||||||
|
"caller_information",
|
||||||
|
"contact",
|
||||||
|
"contact_name",
|
||||||
|
"column_break_10",
|
||||||
|
"lead",
|
||||||
|
"lead_name",
|
||||||
"section_break_5",
|
"section_break_5",
|
||||||
"status",
|
"status",
|
||||||
"duration",
|
"duration",
|
||||||
"recording_url",
|
"recording_url"
|
||||||
"summary"
|
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@ -60,12 +66,6 @@
|
|||||||
"label": "Duration",
|
"label": "Duration",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "summary",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"label": "Summary",
|
|
||||||
"read_only": 1
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "recording_url",
|
"fieldname": "recording_url",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
@ -77,10 +77,58 @@
|
|||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Medium",
|
"label": "Medium",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "received_by",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Received By",
|
||||||
|
"options": "Employee",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "caller_information",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Caller Information"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "contact",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Contact",
|
||||||
|
"options": "Contact",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "lead",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Lead ",
|
||||||
|
"options": "Lead",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "contact.name",
|
||||||
|
"fieldname": "contact_name",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 1,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Contact Name",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_10",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "lead.lead_name",
|
||||||
|
"fieldname": "lead_name",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 1,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Lead Name",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"in_create": 1,
|
"in_create": 1,
|
||||||
"modified": "2019-07-01 09:09:48.516722",
|
"modified": "2019-08-06 05:46:53.144683",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Communication",
|
"module": "Communication",
|
||||||
"name": "Call Log",
|
"name": "Call Log",
|
||||||
@ -97,10 +145,15 @@
|
|||||||
"role": "System Manager",
|
"role": "System Manager",
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"write": 1
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"read": 1,
|
||||||
|
"role": "Employee"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "ASC",
|
"sort_order": "ASC",
|
||||||
"title_field": "from",
|
"title_field": "from",
|
||||||
"track_changes": 1
|
"track_changes": 1,
|
||||||
|
"track_views": 1
|
||||||
}
|
}
|
@ -4,16 +4,83 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
|
from frappe import _
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from erpnext.crm.doctype.utils import get_employee_emails_for_popup
|
from erpnext.crm.doctype.utils import get_scheduled_employees_for_popup
|
||||||
|
from frappe.contacts.doctype.contact.contact import get_contact_with_phone_number
|
||||||
|
from erpnext.crm.doctype.lead.lead import get_lead_with_phone_number
|
||||||
|
|
||||||
class CallLog(Document):
|
class CallLog(Document):
|
||||||
|
def before_insert(self):
|
||||||
|
# strip 0 from the start of the number for proper number comparisions
|
||||||
|
# eg. 07888383332 should match with 7888383332
|
||||||
|
number = self.get('from').lstrip('0')
|
||||||
|
self.contact = get_contact_with_phone_number(number)
|
||||||
|
self.lead = get_lead_with_phone_number(number)
|
||||||
|
|
||||||
def after_insert(self):
|
def after_insert(self):
|
||||||
employee_emails = get_employee_emails_for_popup(self.medium)
|
self.trigger_call_popup()
|
||||||
for email in employee_emails:
|
|
||||||
frappe.publish_realtime('show_call_popup', self, user=email)
|
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
doc_before_save = self.get_doc_before_save()
|
doc_before_save = self.get_doc_before_save()
|
||||||
if doc_before_save and doc_before_save.status in ['Ringing'] and self.status in ['Missed', 'Completed']:
|
if not doc_before_save: return
|
||||||
|
if doc_before_save.status in ['Ringing'] and self.status in ['Missed', 'Completed']:
|
||||||
frappe.publish_realtime('call_{id}_disconnected'.format(id=self.id), self)
|
frappe.publish_realtime('call_{id}_disconnected'.format(id=self.id), self)
|
||||||
|
elif doc_before_save.to != self.to:
|
||||||
|
self.trigger_call_popup()
|
||||||
|
|
||||||
|
def trigger_call_popup(self):
|
||||||
|
scheduled_employees = get_scheduled_employees_for_popup(self.to)
|
||||||
|
employee_emails = get_employees_with_number(self.to)
|
||||||
|
|
||||||
|
# check if employees with matched number are scheduled to receive popup
|
||||||
|
emails = set(scheduled_employees).intersection(employee_emails)
|
||||||
|
|
||||||
|
# # if no employee found with matching phone number then show popup to scheduled employees
|
||||||
|
# emails = emails or scheduled_employees if employee_emails
|
||||||
|
|
||||||
|
for email in emails:
|
||||||
|
frappe.publish_realtime('show_call_popup', self, user=email)
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def add_call_summary(call_log, summary):
|
||||||
|
doc = frappe.get_doc('Call Log', call_log)
|
||||||
|
doc.add_comment('Comment', frappe.bold(_('Call Summary')) + '<br><br>' + summary)
|
||||||
|
|
||||||
|
def get_employees_with_number(number):
|
||||||
|
if not number: return []
|
||||||
|
|
||||||
|
employee_emails = frappe.cache().hget('employees_with_number', number)
|
||||||
|
if employee_emails: return employee_emails
|
||||||
|
|
||||||
|
employees = frappe.get_all('Employee', filters={
|
||||||
|
'cell_number': ['like', '%{}'.format(number.lstrip('0'))],
|
||||||
|
'user_id': ['!=', '']
|
||||||
|
}, fields=['user_id'])
|
||||||
|
|
||||||
|
employee_emails = [employee.user_id for employee in employees]
|
||||||
|
frappe.cache().hset('employees_with_number', number, employee_emails)
|
||||||
|
|
||||||
|
return employee
|
||||||
|
|
||||||
|
def set_caller_information(doc, state):
|
||||||
|
'''Called from hoooks on creation of Lead or Contact'''
|
||||||
|
if doc.doctype not in ['Lead', 'Contact']: return
|
||||||
|
|
||||||
|
numbers = [doc.get('phone'), doc.get('mobile_no')]
|
||||||
|
for_doc = doc.doctype.lower()
|
||||||
|
|
||||||
|
for number in numbers:
|
||||||
|
if not number: continue
|
||||||
|
print(number)
|
||||||
|
filters = frappe._dict({
|
||||||
|
'from': ['like', '%{}'.format(number.lstrip('0'))],
|
||||||
|
for_doc: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
logs = frappe.get_all('Call Log', filters=filters)
|
||||||
|
|
||||||
|
for log in logs:
|
||||||
|
call_log = frappe.get_doc('Call Log', log.name)
|
||||||
|
call_log.set(for_doc, doc.name)
|
||||||
|
call_log.save(ignore_permissions=True)
|
||||||
|
@ -241,3 +241,15 @@ def make_lead_from_communication(communication, ignore_communication_links=False
|
|||||||
|
|
||||||
link_communication_to_document(doc, "Lead", lead_name, ignore_communication_links)
|
link_communication_to_document(doc, "Lead", lead_name, ignore_communication_links)
|
||||||
return lead_name
|
return lead_name
|
||||||
|
|
||||||
|
def get_lead_with_phone_number(number):
|
||||||
|
if not number: return
|
||||||
|
|
||||||
|
leads = frappe.get_all('Lead', or_filters={
|
||||||
|
'phone': ['like', '%{}'.format(number)],
|
||||||
|
'mobile_no': ['like', '%{}'.format(number)]
|
||||||
|
}, limit=1)
|
||||||
|
|
||||||
|
lead = leads[0].name if leads else None
|
||||||
|
|
||||||
|
return lead
|
@ -3,82 +3,57 @@ from frappe import _
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_document_with_phone_number(number):
|
def get_last_interaction(contact=None, lead=None):
|
||||||
# finds contacts and leads
|
|
||||||
if not number: return
|
|
||||||
number = number.lstrip('0')
|
|
||||||
number_filter = {
|
|
||||||
'phone': ['like', '%{}'.format(number)],
|
|
||||||
'mobile_no': ['like', '%{}'.format(number)]
|
|
||||||
}
|
|
||||||
contacts = frappe.get_all('Contact', or_filters=number_filter, limit=1)
|
|
||||||
|
|
||||||
if contacts:
|
if not contact and not lead: return
|
||||||
return frappe.get_doc('Contact', contacts[0].name)
|
|
||||||
|
|
||||||
leads = frappe.get_all('Lead', or_filters=number_filter, limit=1)
|
last_communication = None
|
||||||
|
last_issue = None
|
||||||
if leads:
|
if contact:
|
||||||
return frappe.get_doc('Lead', leads[0].name)
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def get_last_interaction(number, reference_doc):
|
|
||||||
reference_doc = json.loads(reference_doc) if reference_doc else get_document_with_phone_number(number)
|
|
||||||
|
|
||||||
if not reference_doc: return
|
|
||||||
|
|
||||||
reference_doc = frappe._dict(reference_doc)
|
|
||||||
|
|
||||||
last_communication = {}
|
|
||||||
last_issue = {}
|
|
||||||
if reference_doc.doctype == 'Contact':
|
|
||||||
customer_name = ''
|
|
||||||
query_condition = ''
|
query_condition = ''
|
||||||
for link in reference_doc.links:
|
values = []
|
||||||
link = frappe._dict(link)
|
contact = frappe.get_doc('Contact', contact)
|
||||||
|
for link in contact.links:
|
||||||
if link.link_doctype == 'Customer':
|
if link.link_doctype == 'Customer':
|
||||||
customer_name = link.link_name
|
last_issue = get_last_issue_from_customer(link.link_name)
|
||||||
query_condition += "(`reference_doctype`='{}' AND `reference_name`='{}') OR".format(link.link_doctype, link.link_name)
|
query_condition += "(`reference_doctype`=%s AND `reference_name`=%s) OR"
|
||||||
|
values += [link_link_doctype, link_link_name]
|
||||||
|
|
||||||
if query_condition:
|
if query_condition:
|
||||||
|
# remove extra appended 'OR'
|
||||||
query_condition = query_condition[:-2]
|
query_condition = query_condition[:-2]
|
||||||
last_communication = frappe.db.sql("""
|
last_communication = frappe.db.sql("""
|
||||||
SELECT `name`, `content`
|
SELECT `name`, `content`
|
||||||
FROM `tabCommunication`
|
FROM `tabCommunication`
|
||||||
WHERE {}
|
WHERE `sent_or_received`='Received'
|
||||||
|
AND ({})
|
||||||
ORDER BY `modified`
|
ORDER BY `modified`
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
""".format(query_condition)) # nosec
|
""".format(query_condition), values, as_dict=1) # nosec
|
||||||
|
|
||||||
if customer_name:
|
if lead:
|
||||||
last_issue = frappe.get_all('Issue', {
|
|
||||||
'customer': customer_name
|
|
||||||
}, ['name', 'subject', 'customer'], limit=1)
|
|
||||||
|
|
||||||
elif reference_doc.doctype == 'Lead':
|
|
||||||
last_communication = frappe.get_all('Communication', filters={
|
last_communication = frappe.get_all('Communication', filters={
|
||||||
'reference_doctype': reference_doc.doctype,
|
'reference_doctype': 'Lead',
|
||||||
'reference_name': reference_doc.name,
|
'reference_name': lead,
|
||||||
'sent_or_received': 'Received'
|
'sent_or_received': 'Received'
|
||||||
}, fields=['name', 'content'], limit=1)
|
}, fields=['name', 'content'], order_by='`creation` DESC', limit=1)
|
||||||
|
|
||||||
|
last_communication = last_communication[0] if last_communication else None
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'last_communication': last_communication[0] if last_communication else None,
|
'last_communication': last_communication,
|
||||||
'last_issue': last_issue[0] if last_issue else None
|
'last_issue': last_issue
|
||||||
}
|
}
|
||||||
|
|
||||||
@frappe.whitelist()
|
def get_last_issue_from_customer(customer_name):
|
||||||
def add_call_summary(docname, summary):
|
issues = frappe.get_all('Issue', {
|
||||||
call_log = frappe.get_doc('Call Log', docname)
|
'customer': customer_name
|
||||||
summary = _('Call Summary by {0}: {1}').format(
|
}, ['name', 'subject', 'customer'], order_by='`creation` DESC', limit=1)
|
||||||
frappe.utils.get_fullname(frappe.session.user), summary)
|
|
||||||
if not call_log.summary:
|
|
||||||
call_log.summary = summary
|
|
||||||
else:
|
|
||||||
call_log.summary += '<br>' + summary
|
|
||||||
call_log.save(ignore_permissions=True)
|
|
||||||
|
|
||||||
def get_employee_emails_for_popup(communication_medium):
|
return issues[0] if issues else None
|
||||||
|
|
||||||
|
|
||||||
|
def get_scheduled_employees_for_popup(communication_medium):
|
||||||
now_time = frappe.utils.nowtime()
|
now_time = frappe.utils.nowtime()
|
||||||
weekday = frappe.utils.get_weekday()
|
weekday = frappe.utils.get_weekday()
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@ def handle_incoming_call(**kwargs):
|
|||||||
call_log = get_call_log(call_payload)
|
call_log = get_call_log(call_payload)
|
||||||
if not call_log:
|
if not call_log:
|
||||||
create_call_log(call_payload)
|
create_call_log(call_payload)
|
||||||
|
else:
|
||||||
|
update_call_log(call_payload, call_log=call_log)
|
||||||
|
|
||||||
@frappe.whitelist(allow_guest=True)
|
@frappe.whitelist(allow_guest=True)
|
||||||
def handle_end_call(**kwargs):
|
def handle_end_call(**kwargs):
|
||||||
@ -27,10 +29,11 @@ def handle_end_call(**kwargs):
|
|||||||
def handle_missed_call(**kwargs):
|
def handle_missed_call(**kwargs):
|
||||||
update_call_log(kwargs, 'Missed')
|
update_call_log(kwargs, 'Missed')
|
||||||
|
|
||||||
def update_call_log(call_payload, status):
|
def update_call_log(call_payload, status='Ringing', call_log=None):
|
||||||
call_log = get_call_log(call_payload)
|
call_log = call_log or get_call_log(call_payload)
|
||||||
if call_log:
|
if call_log:
|
||||||
call_log.status = status
|
call_log.status = status
|
||||||
|
call_log.to = call_payload.get('DialWhomNumber')
|
||||||
call_log.duration = call_payload.get('DialCallDuration') or 0
|
call_log.duration = call_payload.get('DialCallDuration') or 0
|
||||||
call_log.recording_url = call_payload.get('RecordingUrl')
|
call_log.recording_url = call_payload.get('RecordingUrl')
|
||||||
call_log.save(ignore_permissions=True)
|
call_log.save(ignore_permissions=True)
|
||||||
@ -48,7 +51,7 @@ def get_call_log(call_payload):
|
|||||||
def create_call_log(call_payload):
|
def create_call_log(call_payload):
|
||||||
call_log = frappe.new_doc('Call Log')
|
call_log = frappe.new_doc('Call Log')
|
||||||
call_log.id = call_payload.get('CallSid')
|
call_log.id = call_payload.get('CallSid')
|
||||||
call_log.to = call_payload.get('CallTo')
|
call_log.to = call_payload.get('DialWhomNumber')
|
||||||
call_log.medium = call_payload.get('To')
|
call_log.medium = call_payload.get('To')
|
||||||
call_log.status = 'Ringing'
|
call_log.status = 'Ringing'
|
||||||
setattr(call_log, 'from', call_payload.get('CallFrom'))
|
setattr(call_log, 'from', call_payload.get('CallFrom'))
|
||||||
|
@ -231,8 +231,12 @@ doc_events = {
|
|||||||
('Sales Invoice', 'Purchase Invoice', 'Delivery Note'): {
|
('Sales Invoice', 'Purchase Invoice', 'Delivery Note'): {
|
||||||
'validate': 'erpnext.regional.india.utils.set_place_of_supply'
|
'validate': 'erpnext.regional.india.utils.set_place_of_supply'
|
||||||
},
|
},
|
||||||
"Contact":{
|
"Contact": {
|
||||||
"on_trash": "erpnext.support.doctype.issue.issue.update_issue"
|
"on_trash": "erpnext.support.doctype.issue.issue.update_issue",
|
||||||
|
"after_insert": "erpnext.communication.doctype.call_log.call_log.set_caller_information"
|
||||||
|
},
|
||||||
|
"Lead": {
|
||||||
|
"after_insert": "erpnext.communication.doctype.call_log.call_log.set_caller_information"
|
||||||
},
|
},
|
||||||
"Email Unsubscribe": {
|
"Email Unsubscribe": {
|
||||||
"after_insert": "erpnext.crm.doctype.email_campaign.email_campaign.unsubscribe_recipient"
|
"after_insert": "erpnext.crm.doctype.email_campaign.email_campaign.unsubscribe_recipient"
|
||||||
|
@ -76,6 +76,7 @@ class Employee(NestedSet):
|
|||||||
if self.user_id:
|
if self.user_id:
|
||||||
self.update_user()
|
self.update_user()
|
||||||
self.update_user_permissions()
|
self.update_user_permissions()
|
||||||
|
self.reset_employee_emails_cache()
|
||||||
|
|
||||||
def update_user_permissions(self):
|
def update_user_permissions(self):
|
||||||
if not self.create_user_permission: return
|
if not self.create_user_permission: return
|
||||||
@ -214,6 +215,15 @@ class Employee(NestedSet):
|
|||||||
doc.validate_employee_creation()
|
doc.validate_employee_creation()
|
||||||
doc.db_set("employee", self.name)
|
doc.db_set("employee", self.name)
|
||||||
|
|
||||||
|
def reset_employee_emails_cache(self):
|
||||||
|
prev_doc = self.get_doc_before_save() or {}
|
||||||
|
cell_number = self.get('cell_number')
|
||||||
|
prev_number = prev_doc.get('cell_number')
|
||||||
|
if (cell_number != prev_number or
|
||||||
|
self.get('user_id') != prev_doc.get('user_id')):
|
||||||
|
frappe.cache().hdel('employees_with_number', cell_number)
|
||||||
|
frappe.cache().hdel('employees_with_number', prev_number)
|
||||||
|
|
||||||
def get_timeline_data(doctype, name):
|
def get_timeline_data(doctype, name):
|
||||||
'''Return timeline for attendance'''
|
'''Return timeline for attendance'''
|
||||||
return dict(frappe.db.sql('''select unix_timestamp(attendance_date), count(*)
|
return dict(frappe.db.sql('''select unix_timestamp(attendance_date), count(*)
|
||||||
|
@ -11,12 +11,51 @@ class CallPopup {
|
|||||||
'static': true,
|
'static': true,
|
||||||
'minimizable': true,
|
'minimizable': true,
|
||||||
'fields': [{
|
'fields': [{
|
||||||
'fieldname': 'caller_info',
|
'fieldname': 'name',
|
||||||
'fieldtype': 'HTML'
|
'label': 'Name',
|
||||||
|
'default': this.get_caller_name() || __('Unknown Caller'),
|
||||||
|
'fieldtype': 'Data',
|
||||||
|
'read_only': 1
|
||||||
|
}, {
|
||||||
|
'fieldtype': 'Button',
|
||||||
|
'label': __('Open Contact'),
|
||||||
|
'click': () => frappe.set_route('Form', 'Contact', this.call_log.contact),
|
||||||
|
'depends_on': () => this.call_log.contact
|
||||||
|
}, {
|
||||||
|
'fieldtype': 'Button',
|
||||||
|
'label': __('Open Lead'),
|
||||||
|
'click': () => frappe.set_route('Form', 'Lead', this.call_log.lead),
|
||||||
|
'depends_on': () => this.call_log.lead
|
||||||
|
}, {
|
||||||
|
'fieldtype': 'Button',
|
||||||
|
'label': __('Make New Contact'),
|
||||||
|
'click': () => frappe.new_doc('Contact', { 'mobile_no': this.caller_number }),
|
||||||
|
'depends_on': () => !this.get_caller_name()
|
||||||
|
}, {
|
||||||
|
'fieldtype': 'Button',
|
||||||
|
'label': __('Make New Lead'),
|
||||||
|
'click': () => frappe.new_doc('Lead', { 'mobile_no': this.caller_number }),
|
||||||
|
'depends_on': () => !this.get_caller_name()
|
||||||
|
}, {
|
||||||
|
'fieldtype': 'Column Break',
|
||||||
|
}, {
|
||||||
|
'fieldname': 'number',
|
||||||
|
'label': 'Phone Number',
|
||||||
|
'fieldtype': 'Data',
|
||||||
|
'default': this.caller_number,
|
||||||
|
'read_only': 1
|
||||||
}, {
|
}, {
|
||||||
'fielname': 'last_interaction',
|
'fielname': 'last_interaction',
|
||||||
'fieldtype': 'Section Break',
|
'fieldtype': 'Section Break',
|
||||||
'label': __('Activity'),
|
'label': __('Activity'),
|
||||||
|
'depends_on': () => this.get_caller_name()
|
||||||
|
}, {
|
||||||
|
'fieldtype': 'Small Text',
|
||||||
|
'label': __('Last Issue'),
|
||||||
|
'fieldname': 'last_issue',
|
||||||
|
'read_only': true,
|
||||||
|
'depends_on': () => this.call_log.contact,
|
||||||
|
'default': `<i class="text-muted">${__('No issue has been raised by the caller.')}<i>`
|
||||||
}, {
|
}, {
|
||||||
'fieldtype': 'Small Text',
|
'fieldtype': 'Small Text',
|
||||||
'label': __('Last Communication'),
|
'label': __('Last Communication'),
|
||||||
@ -24,13 +63,7 @@ class CallPopup {
|
|||||||
'read_only': true,
|
'read_only': true,
|
||||||
'default': `<i class="text-muted">${__('No communication found.')}<i>`
|
'default': `<i class="text-muted">${__('No communication found.')}<i>`
|
||||||
}, {
|
}, {
|
||||||
'fieldtype': 'Small Text',
|
'fieldtype': 'Section Break',
|
||||||
'label': __('Last Issue'),
|
|
||||||
'fieldname': 'last_issue',
|
|
||||||
'read_only': true,
|
|
||||||
'default': `<i class="text-muted">${__('No issue raised by the customer.')}<i>`
|
|
||||||
}, {
|
|
||||||
'fieldtype': 'Column Break',
|
|
||||||
}, {
|
}, {
|
||||||
'fieldtype': 'Small Text',
|
'fieldtype': 'Small Text',
|
||||||
'label': __('Call Summary'),
|
'label': __('Call Summary'),
|
||||||
@ -41,13 +74,21 @@ class CallPopup {
|
|||||||
'click': () => {
|
'click': () => {
|
||||||
const call_summary = this.dialog.get_value('call_summary');
|
const call_summary = this.dialog.get_value('call_summary');
|
||||||
if (!call_summary) return;
|
if (!call_summary) return;
|
||||||
frappe.xcall('erpnext.crm.doctype.utils.add_call_summary', {
|
frappe.xcall('erpnext.communication.doctype.call_log.call_log.add_call_summary', {
|
||||||
'docname': this.call_log.id,
|
'call_log': this.call_log.name,
|
||||||
'summary': call_summary,
|
'summary': call_summary,
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.close_modal();
|
this.close_modal();
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: `${__('Call Summary Saved')}<br><a class="text-small text-muted" href="#Form/Call Log/${this.call_log.name}">${__('View call log')}</a>`,
|
message: `
|
||||||
|
${__('Call Summary Saved')}
|
||||||
|
<br>
|
||||||
|
<a
|
||||||
|
class="text-small text-muted"
|
||||||
|
href="#Form/Call Log/${this.call_log.name}">
|
||||||
|
${__('View call log')}
|
||||||
|
</a>
|
||||||
|
`,
|
||||||
indicator: 'green'
|
indicator: 'green'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -55,71 +96,14 @@ class CallPopup {
|
|||||||
}],
|
}],
|
||||||
});
|
});
|
||||||
this.set_call_status();
|
this.set_call_status();
|
||||||
this.make_caller_info_section();
|
|
||||||
this.dialog.get_close_btn().show();
|
this.dialog.get_close_btn().show();
|
||||||
|
this.make_last_interaction_section();
|
||||||
this.dialog.$body.addClass('call-popup');
|
this.dialog.$body.addClass('call-popup');
|
||||||
this.dialog.set_secondary_action(this.close_modal.bind(this));
|
this.dialog.set_secondary_action(this.close_modal.bind(this));
|
||||||
frappe.utils.play_sound('incoming-call');
|
frappe.utils.play_sound('incoming-call');
|
||||||
this.dialog.show();
|
this.dialog.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
make_caller_info_section() {
|
|
||||||
const wrapper = this.dialog.get_field('caller_info').$wrapper;
|
|
||||||
wrapper.append(`<div class="text-muted"> ${__("Loading...")} </div>`);
|
|
||||||
frappe.xcall('erpnext.crm.doctype.utils.get_document_with_phone_number', {
|
|
||||||
'number': this.caller_number
|
|
||||||
}).then(contact_doc => {
|
|
||||||
wrapper.empty();
|
|
||||||
const contact = this.contact = contact_doc;
|
|
||||||
if (!contact) {
|
|
||||||
this.setup_unknown_caller(wrapper);
|
|
||||||
} else {
|
|
||||||
this.setup_known_caller(wrapper);
|
|
||||||
this.set_call_status();
|
|
||||||
this.make_last_interaction_section();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_unknown_caller(wrapper) {
|
|
||||||
wrapper.append(`
|
|
||||||
<div class="caller-info">
|
|
||||||
<b>${__('Unknown Number')}:</b> ${this.caller_number}
|
|
||||||
<button
|
|
||||||
class="margin-left btn btn-new btn-default btn-xs"
|
|
||||||
data-doctype="Contact"
|
|
||||||
title=${__("Make New Contact")}>
|
|
||||||
<i class="octicon octicon-plus text-medium"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
`).find('button').click(
|
|
||||||
() => frappe.set_route(`Form/Contact/New Contact?phone=${this.caller_number}`)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_known_caller(wrapper) {
|
|
||||||
const contact = this.contact;
|
|
||||||
const contact_name = frappe.utils.get_form_link(contact.doctype, contact.name, true, this.get_caller_name());
|
|
||||||
const links = contact.links ? contact.links : [];
|
|
||||||
|
|
||||||
let contact_links = '';
|
|
||||||
|
|
||||||
links.forEach(link => {
|
|
||||||
contact_links += `<div>${link.link_doctype}: ${frappe.utils.get_form_link(link.link_doctype, link.link_name, true)}</div>`;
|
|
||||||
});
|
|
||||||
wrapper.append(`
|
|
||||||
<div class="caller-info flex">
|
|
||||||
${frappe.avatar(null, 'avatar-xl', contact.name, contact.image || '')}
|
|
||||||
<div>
|
|
||||||
<h5>${contact_name}</h5>
|
|
||||||
<div>${contact.mobile_no || ''}</div>
|
|
||||||
<div>${contact.phone_no || ''}</div>
|
|
||||||
${contact_links}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
|
|
||||||
set_indicator(color, blink=false) {
|
set_indicator(color, blink=false) {
|
||||||
let classes = `indicator ${color} ${blink ? 'blink': ''}`;
|
let classes = `indicator ${color} ${blink ? 'blink': ''}`;
|
||||||
this.dialog.header.find('.indicator').attr('class', classes);
|
this.dialog.header.find('.indicator').attr('class', classes);
|
||||||
@ -129,7 +113,7 @@ class CallPopup {
|
|||||||
let title = '';
|
let title = '';
|
||||||
call_status = call_status || this.call_log.status;
|
call_status = call_status || this.call_log.status;
|
||||||
if (['Ringing'].includes(call_status) || !call_status) {
|
if (['Ringing'].includes(call_status) || !call_status) {
|
||||||
title = __('Incoming call from {0}', [this.get_caller_name()]);
|
title = __('Incoming call from {0}', [this.get_caller_name() || this.caller_number]);
|
||||||
this.set_indicator('blue', true);
|
this.set_indicator('blue', true);
|
||||||
} else if (call_status === 'In Progress') {
|
} else if (call_status === 'In Progress') {
|
||||||
title = __('Call Connected');
|
title = __('Call Connected');
|
||||||
@ -164,13 +148,13 @@ class CallPopup {
|
|||||||
if (!this.dialog.get_value('call_summary')) {
|
if (!this.dialog.get_value('call_summary')) {
|
||||||
this.close_modal();
|
this.close_modal();
|
||||||
}
|
}
|
||||||
}, 10000);
|
}, 30000);
|
||||||
}
|
}
|
||||||
|
|
||||||
make_last_interaction_section() {
|
make_last_interaction_section() {
|
||||||
frappe.xcall('erpnext.crm.doctype.utils.get_last_interaction', {
|
frappe.xcall('erpnext.crm.doctype.utils.get_last_interaction', {
|
||||||
'number': this.caller_number,
|
'contact': this.call_log.contact,
|
||||||
'reference_doc': this.contact
|
'lead': this.call_log.lead
|
||||||
}).then(data => {
|
}).then(data => {
|
||||||
const comm_field = this.dialog.get_field('last_communication');
|
const comm_field = this.dialog.get_field('last_communication');
|
||||||
if (data.last_communication) {
|
if (data.last_communication) {
|
||||||
@ -182,15 +166,20 @@ class CallPopup {
|
|||||||
const issue = data.last_issue;
|
const issue = data.last_issue;
|
||||||
const issue_field = this.dialog.get_field("last_issue");
|
const issue_field = this.dialog.get_field("last_issue");
|
||||||
issue_field.set_value(issue.subject);
|
issue_field.set_value(issue.subject);
|
||||||
issue_field.$wrapper.append(`<a class="text-medium" href="#List/Issue?customer=${issue.customer}">
|
issue_field.$wrapper.append(`
|
||||||
${__('View all issues from {0}', [issue.customer])}
|
<a class="text-medium" href="#List/Issue?customer=${issue.customer}">
|
||||||
</a>`);
|
${__('View all issues from {0}', [issue.customer])}
|
||||||
|
</a>
|
||||||
|
`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get_caller_name() {
|
get_caller_name() {
|
||||||
return this.contact ? this.contact.lead_name || this.contact.name || '' : this.caller_number;
|
let log = this.call_log;
|
||||||
|
return log.contact_name || log.lead_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_listener() {
|
setup_listener() {
|
||||||
frappe.realtime.on(`call_${this.call_log.id}_disconnected`, call_log => {
|
frappe.realtime.on(`call_${this.call_log.id}_disconnected`, call_log => {
|
||||||
this.call_disconnected(call_log);
|
this.call_disconnected(call_log);
|
||||||
|
Loading…
Reference in New Issue
Block a user