fix: Make changes to fix call flow and popup trigger
diff --git a/erpnext/crm/doctype/utils.py b/erpnext/crm/doctype/utils.py
index 3bd9246..5c33817 100644
--- a/erpnext/crm/doctype/utils.py
+++ b/erpnext/crm/doctype/utils.py
@@ -1,20 +1,25 @@
import frappe
+@frappe.whitelist()
def get_document_with_phone_number(number):
# finds contacts and leads
+ if not number: return
number = number[-10:]
number_filter = {
'phone': ['like', '%{}'.format(number)],
'mobile_no': ['like', '%{}'.format(number)]
}
- contacts = frappe.get_all('Contact', or_filters=number_filter,
- fields=['name'], limit=1)
+ contacts = frappe.get_all('Contact', or_filters=number_filter, limit=1)
if contacts:
return frappe.get_doc('Contact', contacts[0].name)
- leads = frappe.get_all('Leads', or_filters=number_filter,
- fields=['name'], limit=1)
+ leads = frappe.get_all('Lead', or_filters=number_filter, limit=1)
if leads:
- return frappe.get_doc('Lead', leads[0].name)
\ No newline at end of file
+ return frappe.get_doc('Lead', leads[0].name)
+
+
+def get_customer_last_interaction(contact_doc):
+ #
+ pass
\ No newline at end of file
diff --git a/erpnext/erpnext_integrations/exotel_integration.py b/erpnext/erpnext_integrations/exotel_integration.py
index 3a922f7..c45945f 100644
--- a/erpnext/erpnext_integrations/exotel_integration.py
+++ b/erpnext/erpnext_integrations/exotel_integration.py
@@ -6,66 +6,77 @@
@frappe.whitelist(allow_guest=True)
def handle_incoming_call(*args, **kwargs):
- # incoming_phone_number = kwargs.get('CallFrom')
+ exotel_settings = get_exotel_settings()
+ if not exotel_settings.enabled: return
- # contact = get_document_with_phone_number(incoming_phone_number)
- # last_communication = get_last_communication(incoming_phone_number, contact)
- call_log = create_call_log(kwargs)
+ employee_email = kwargs.get('AgentEmail')
+ status = kwargs.get('Status')
+
+ if status == 'free' and get_call_status(kwargs.get('CallSid')) == ['ringing', 'in-progress']:
+ # redirected to other agent number
+ frappe.publish_realtime('terminate_call_popup', user=employee_email)
+ return
+
+ call_log = get_call_log(kwargs)
+
data = frappe._dict({
'call_from': kwargs.get('CallFrom'),
'agent_email': kwargs.get('AgentEmail'),
'call_type': kwargs.get('Direction'),
- 'call_log': call_log
+ 'call_log': call_log,
+ 'call_status_method': 'erpnext.erpnext_integrations.exotel_integration.get_call_status'
})
-
- frappe.publish_realtime('show_call_popup', data, user=data.agent_email)
-
+ if call_log.call_status in ['ringing', 'in-progress']:
+ frappe.publish_realtime('show_call_popup', data, user=data.agent_email)
def get_last_communication(phone_number, contact):
# frappe.get_all('Communication', filter={})
return {}
-def create_call_log(call_payload):
+def get_call_log(call_payload):
communication = frappe.get_all('Communication', {
'communication_medium': 'Phone',
'call_id': call_payload.get('CallSid'),
}, limit=1)
if communication:
- log = frappe.get_doc('Communication', communication[0].name)
- log.call_status = 'Connected'
- log.save(ignore_permissions=True)
- return log
+ communication = frappe.get_doc('Communication', communication[0].name)
+ else:
+ communication = frappe.new_doc('Communication')
+ communication.subject = frappe._('Call from {}').format(call_payload.get("CallFrom"))
+ communication.communication_medium = 'Phone'
+ communication.phone_no = call_payload.get("CallFrom")
+ communication.comment_type = 'Info'
+ communication.communication_type = 'Communication'
+ communication.sent_or_received = 'Received'
+ communication.communication_date = call_payload.get('StartTime')
+ communication.call_id = call_payload.get('CallSid')
- communication = frappe.new_doc('Communication')
- communication.subject = frappe._('Call from {}').format(call_payload.get("CallFrom"))
- communication.communication_medium = 'Phone'
- communication.send_email = 0
- communication.phone_no = call_payload.get("CallFrom")
- communication.comment_type = 'Info'
- communication.communication_type = 'Communication'
- communication.status = 'Open'
- communication.sent_or_received = 'Received'
+ status = get_call_status(communication.call_id)
+ communication.call_status = status or 'failed'
+ communication.status = 'Closed' if status in ['completed', 'failed', 'no-answer'] else 'Open'
+ communication.call_duration = call_payload.get('Duration') if status in ['completed', 'failed', 'no-answer'] else 0
communication.content = 'call_payload'
- communication.call_status = 'Incoming'
- communication.communication_date = call_payload.get('StartTime')
- communication.call_id = call_payload.get('CallSid')
communication.save(ignore_permissions=True)
+ frappe.db.commit()
return communication
+@frappe.whitelist()
def get_call_status(call_id):
+ print(call_id)
settings = get_exotel_settings()
- response = requests.get('https://{api_key}:{api_token}@api.exotel.com/v1/Accounts/erpnext/{sid}/{call_id}.json'.format(
+ response = requests.get('https://{api_key}:{api_token}@api.exotel.com/v1/Accounts/erpnext/Calls/{call_id}.json'.format(
api_key=settings.api_key,
api_token=settings.api_token,
call_id=call_id
))
- return response.json()
+ status = response.json().get('Call', {}).get('Status')
+ return status
-@frappe.whitelist(allow_guest=True)
+@frappe.whitelist()
def make_a_call(from_number, to_number, caller_id):
settings = get_exotel_settings()
- response = requests.post('https://{api_key}:{api_token}@api.exotel.com/v1/Accounts/{sid}/Calls/connect.json'.format(
+ response = requests.post('https://{api_key}:{api_token}@api.exotel.com/v1/Accounts/{sid}/Calls/connect.json?details=true'.format(
api_key=settings.api_key,
api_token=settings.api_token,
), data={
diff --git a/erpnext/public/js/call_popup/call_popup.js b/erpnext/public/js/call_popup/call_popup.js
index 2d95c5d..7236f9e 100644
--- a/erpnext/public/js/call_popup/call_popup.js
+++ b/erpnext/public/js/call_popup/call_popup.js
@@ -1,8 +1,11 @@
class CallPopup {
- constructor({ call_from, call_log }) {
+ constructor({ call_from, call_log, call_status_method }) {
this.number = call_from;
this.call_log = call_log;
+ this.call_status_method = call_status_method;
this.make();
+ this.make_customer_contact();
+ this.setup_call_status_updater();
}
make() {
@@ -34,47 +37,54 @@
}]
});
this.set_call_status(this.call_log.call_status);
- this.make_customer_contact();
this.dialog.show();
this.dialog.get_close_btn().show();
- this.dialog.header.find('.indicator').removeClass('hidden').addClass('blue');
}
make_customer_contact() {
const wrapper = this.dialog.fields_dict["customer_info"].$wrapper;
- const contact = this.contact;
- const customer = this.contact.links ? this.contact.links[0] : null;
- const customer_link = customer ? frappe.utils.get_form_link(customer.link_doctype, customer.link_name, true): '';
- if (!contact) {
- wrapper.append('<b>Unknown Contact</b>');
- } else {
- wrapper.append(`
- <div class="customer-info flex">
- <img src="${contact.image}">
- <div class='flex-column'>
- <span>${contact.first_name} ${contact.last_name}</span>
- <span>${contact.mobile_no}</span>
- ${customer_link}
- </div>
- </div>
- `);
- }
- }
-
- make_summary_section() {
- //
- }
-
- set_call_status() {
- let title = '';
- if (this.call_log.call_status === 'Incoming') {
- if (this.contact) {
- title = __('Incoming call from {0}', [this.contact.name]);
+ wrapper.append('<div class="text-muted"> Loading... </div>');
+ frappe.xcall('erpnext.crm.doctype.utils.get_document_with_phone_number', {
+ 'number': this.number
+ }).then(contact_doc => {
+ wrapper.empty();
+ const contact = contact_doc;
+ if (!contact) {
+ wrapper.append('<div>Unknown Contact</div>');
+ wrapper.append(`<a href="#Form/Contact/New Contact?phone=${this.number}">${__('Make New Contact')}</a>`);
} else {
- title = __('Incoming call from unknown number');
+ const link = contact.links ? contact.links[0] : null;
+ const contact_link = link ? frappe.utils.get_form_link(link.link_doctype, link.link_name, true): '';
+ wrapper.append(`
+ <div class="customer-info flex">
+ <img src="${contact.image}">
+ <div class='flex-column'>
+ <span>${contact.first_name} ${contact.last_name}</span>
+ <span>${contact.mobile_no}</span>
+ ${contact_link}
+ </div>
+ </div>
+ `);
}
- } else {
+ });
+ }
+
+ set_indicator(color) {
+ this.dialog.header.find('.indicator').removeClass('hidden').addClass('blink').addClass(color);
+ }
+
+ set_call_status(call_status) {
+ let title = '';
+ call_status = this.call_log.call_status;
+ if (call_status === 'busy') {
+ title = __('Incoming call');
+ this.set_indicator('blue');
+ } else if (call_status === 'in-progress') {
title = __('Call Connected');
+ this.set_indicator('yellow');
+ } else if (call_status === 'missed') {
+ this.set_indicator('red');
+ title = __('Call Missed');
}
this.dialog.set_title(title);
}
@@ -83,6 +93,27 @@
this.call_log = data.call_log;
this.set_call_status();
}
+
+ setup_call_status_updater() {
+ this.updater = setInterval(this.get_call_status.bind(this), 2000);
+ }
+
+ get_call_status() {
+ frappe.xcall(this.call_status_method, {
+ 'call_id': this.call_log.call_id
+ }).then((call_status) => {
+ if (call_status === 'completed') {
+ clearInterval(this.updater);
+ }
+ });
+ }
+
+ terminate_popup() {
+ clearInterval(this.updater);
+ this.dialog.hide();
+ delete erpnext.call_popup;
+ frappe.msgprint('Call Forwarded');
+ }
}
$(document).on('app_ready', function () {
@@ -90,8 +121,15 @@
if (!erpnext.call_popup) {
erpnext.call_popup = new CallPopup(data);
} else {
+ console.log(data);
erpnext.call_popup.update(data);
erpnext.call_popup.dialog.show();
}
});
+
+ frappe.realtime.on('terminate_call_popup', () => {
+ if (erpnext.call_popup) {
+ erpnext.call_popup.terminate_popup();
+ }
+ });
});