fix: Update call_popup
- Setup missed & call ended listeners
- Show contacts based on links
diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py
index 938cbfd..d1d0968 100644
--- a/erpnext/crm/doctype/lead/lead.py
+++ b/erpnext/crm/doctype/lead/lead.py
@@ -352,7 +352,7 @@
leads = frappe.get_all('Lead', or_filters={
'phone': ['like', '%{}'.format(number)],
'mobile_no': ['like', '%{}'.format(number)]
- }, limit=1)
+ }, limit=1, order_by="creation DESC")
lead = leads[0].name if leads else None
@@ -361,4 +361,4 @@
def daily_open_lead():
leads = frappe.get_all("Lead", filters = [["contact_date", "Between", [nowdate(), nowdate()]]])
for lead in leads:
- frappe.db.set_value("Lead", lead.name, "status", "Open")
\ No newline at end of file
+ frappe.db.set_value("Lead", lead.name, "status", "Open")
diff --git a/erpnext/public/js/call_popup/call_popup.js b/erpnext/public/js/call_popup/call_popup.js
index f3d09ee..2429788 100644
--- a/erpnext/public/js/call_popup/call_popup.js
+++ b/erpnext/public/js/call_popup/call_popup.js
@@ -7,10 +7,103 @@
}
make() {
+ frappe.utils.play_sound('incoming-call');
this.dialog = new frappe.ui.Dialog({
'static': true,
- 'minimizable': true,
- 'fields': [{
+ 'minimizable': true
+ });
+ this.dialog.get_close_btn().show();
+ this.setup_dialog();
+ this.set_call_status();
+ frappe.utils.bind_actions_with_object(this.dialog.$body, this);
+ this.dialog.$wrapper.addClass('call-popup');
+ this.dialog.get_close_btn().unbind('click').click(this.close_modal.bind(this));
+ this.dialog.show();
+ }
+
+ setup_dialog() {
+ this.setup_call_details();
+ this.dialog.$body.empty().append(this.caller_info);
+ }
+
+ set_indicator(color, blink=false) {
+ let classes = `indicator ${color} ${blink ? 'blink': ''}`;
+ this.dialog.header.find('.indicator').attr('class', classes);
+ }
+
+ set_call_status(call_status) {
+ let title = '';
+ call_status = call_status || this.call_log.status;
+ if (['Ringing'].includes(call_status) || !call_status) {
+ title = __('Incoming call from {0}', [this.get_caller_name() || this.caller_number]);
+ this.set_indicator('blue', true);
+ } else if (call_status === 'In Progress') {
+ title = __('Call Connected');
+ this.set_indicator('green');
+ } else if (['No Answer', 'Missed'].includes(call_status)) {
+ this.set_indicator('yellow');
+ title = __('Call Missed');
+ } else if (['Completed', 'Busy', 'Failed'].includes(call_status)) {
+ this.set_indicator('red');
+ title = __('Call Ended');
+ } else {
+ this.set_indicator('blue');
+ title = call_status;
+ }
+ this.dialog.set_title(title);
+ }
+
+ update_call_log(call_log, missed) {
+ this.call_log = call_log;
+ this.set_call_status(missed ? 'Missed': null);
+ }
+
+ close_modal() {
+ this.dialog.hide();
+ delete erpnext.call_popup;
+ }
+
+ call_ended(call_log, missed) {
+ frappe.utils.play_sound('call-disconnect');
+ this.update_call_log(call_log, missed);
+ setTimeout(() => {
+ if (!this.dialog.get_value('call_summary')) {
+ this.close_modal();
+ }
+ }, 60000);
+ this.clear_listeners();
+ }
+
+ get_caller_name() {
+ const contact_link = this.get_contact_link();
+ return contact_link.link_title || contact_link.link_name;
+ }
+
+ get_contact_link() {
+ let log = this.call_log;
+ let contact_link = log.links.find(d => d.link_doctype === 'Contact');
+ return contact_link || {};
+ }
+
+ setup_listener() {
+ frappe.realtime.on(`call_${this.call_log.id}_ended`, call_log => {
+ this.call_ended(call_log);
+ });
+
+ frappe.realtime.on(`call_${this.call_log.id}_missed`, call_log => {
+ this.call_ended(call_log, true);
+ });
+ }
+
+ clear_listeners() {
+ frappe.realtime.off(`call_${this.call_log.id}_ended`);
+ frappe.realtime.off(`call_${this.call_log.id}_missed`);
+ }
+
+ setup_call_details() {
+ this.caller_info = $(`<div></div>`);
+ this.call_details = new frappe.ui.FieldGroup({
+ fields: [{
'fieldname': 'name',
'label': 'Name',
'default': this.get_caller_name() || __('Unknown Caller'),
@@ -19,17 +112,17 @@
}, {
'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
+ 'click': () => frappe.set_route('Form', 'Contact', this.get_contact_link().link_name),
+ 'depends_on': () => this.get_caller_name()
}, {
'fieldtype': 'Button',
'label': __('Create New Contact'),
- 'click': () => frappe.new_doc('Contact', { 'mobile_no': this.caller_number }),
+ 'click': this.create_new_contact.bind(this),
+ 'depends_on': () => !this.get_caller_name()
+ }, {
+ 'fieldtype': 'Button',
+ 'label': __('Create New Customer'),
+ 'click': this.create_new_customer.bind(this),
'depends_on': () => !this.get_caller_name()
}, {
'fieldtype': 'Button',
@@ -45,25 +138,8 @@
'default': this.caller_number,
'read_only': 1
}, {
- 'fielname': 'last_interaction',
'fieldtype': 'Section Break',
- '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',
- 'label': __('Last Communication'),
- 'fieldname': 'last_communication',
- 'read_only': true,
- 'default': `<i class="text-muted">${__('No communication found.')}<i>`
- }, {
- 'fieldtype': 'Section Break',
+ 'hide_border': 1,
}, {
'fieldtype': 'Small Text',
'label': __('Call Summary'),
@@ -72,7 +148,7 @@
'fieldtype': 'Button',
'label': __('Save'),
'click': () => {
- const call_summary = this.dialog.get_value('call_summary');
+ const call_summary = this.call_details.get_value('call_summary');
if (!call_summary) return;
frappe.xcall('erpnext.telephony.doctype.call_log.call_log.add_call_summary', {
'call_log': this.call_log.name,
@@ -94,98 +170,29 @@
});
}
}],
+ body: this.caller_info
});
- this.set_call_status();
- this.dialog.get_close_btn().show();
- this.make_last_interaction_section();
- this.dialog.$body.addClass('call-popup');
- this.dialog.set_secondary_action(this.close_modal.bind(this));
- frappe.utils.play_sound('incoming-call');
- this.dialog.show();
+ this.call_details.make();
}
- set_indicator(color, blink=false) {
- let classes = `indicator ${color} ${blink ? 'blink': ''}`;
- this.dialog.header.find('.indicator').attr('class', classes);
+ is_known_caller() {
+ return Boolean(this.get_caller_name());
}
- set_call_status(call_status) {
- let title = '';
- call_status = call_status || this.call_log.status;
- if (['Ringing'].includes(call_status) || !call_status) {
- title = __('Incoming call from {0}', [this.get_caller_name() || this.caller_number]);
- this.set_indicator('blue', true);
- } 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');
- } else if (['Completed', 'Disconnected'].includes(call_status)) {
- this.set_indicator('red');
- title = __('Call Disconnected');
- } else {
- this.set_indicator('blue');
- title = call_status;
- }
- this.dialog.set_title(title);
+ create_new_customer() {
+ // to avoid quick entry form
+ const new_customer = frappe.model.get_new_doc('Customer');
+ new_customer.mobile_no = this.caller_number;
+ frappe.set_route('Form', new_customer.doctype, new_customer.name);
}
- update_call_log(call_log) {
- this.call_log = call_log;
- this.set_call_status();
- }
-
- close_modal() {
- this.dialog.hide();
- delete erpnext.call_popup;
- }
-
- call_disconnected(call_log) {
- frappe.utils.play_sound('call-disconnect');
- this.update_call_log(call_log);
- setTimeout(() => {
- if (!this.dialog.get_value('call_summary')) {
- this.close_modal();
- }
- }, 30000);
- }
-
- make_last_interaction_section() {
- frappe.xcall('erpnext.crm.doctype.utils.get_last_interaction', {
- 'contact': this.call_log.contact,
- 'lead': this.call_log.lead
- }).then(data => {
- const comm_field = this.dialog.get_field('last_communication');
- if (data.last_communication) {
- const comm = data.last_communication;
- comm_field.set_value(comm.content);
- }
-
- if (data.last_issue) {
- const issue = data.last_issue;
- const issue_field = this.dialog.get_field("last_issue");
- issue_field.set_value(issue.subject);
- issue_field.$wrapper.append(`
- <a class="text-medium" href="/app/issue?customer=${issue.customer}">
- ${__('View all issues from {0}', [issue.customer])}
- </a>
- `);
- }
- });
- }
-
- get_caller_name() {
- let log = this.call_log;
- return log.contact_name || log.lead_name;
- }
-
- setup_listener() {
- frappe.realtime.on(`call_${this.call_log.id}_disconnected`, call_log => {
- this.call_disconnected(call_log);
- // Remove call disconnect listener after the call is disconnected
- frappe.realtime.off(`call_${this.call_log.id}_disconnected`);
- });
+ create_new_contact() {
+ // TODO: fix new_doc, it should accept child table values
+ const new_contact = frappe.model.get_new_doc('Contact');
+ const phone_no = frappe.model.add_child(new_contact, 'Contact Phone', 'phone_nos');
+ phone_no.phone = this.caller_number;
+ phone_no.is_primary_mobile_no = 1;
+ frappe.set_route('Form', new_contact.doctype, new_contact.name);
}
}
@@ -200,3 +207,5 @@
}
});
});
+
+window.CallPopup = CallPopup;