diff --git a/crm/api/session.py b/crm/api/session.py index 0bc64db9..7650d3c1 100644 --- a/crm/api/session.py +++ b/crm/api/session.py @@ -60,6 +60,27 @@ def get_contacts(): return contacts +@frappe.whitelist() +def get_lead_contacts(): + if frappe.session.user == "Guest": + frappe.throw("Authentication failed", exc=frappe.AuthenticationError) + + lead_contacts = frappe.get_all( + "CRM Lead", + fields=[ + "name", + "lead_name", + "mobile_no", + "phone", + "image", + "modified" + ], + order_by="lead_name asc", + distinct=True, + ) + + return lead_contacts + @frappe.whitelist() def get_organizations(): if frappe.session.user == "Guest": diff --git a/frontend/src/components/Activities.vue b/frontend/src/components/Activities.vue index 37439235..2f9d0905 100644 --- a/frontend/src/components/Activities.vue +++ b/frontend/src/components/Activities.vue @@ -727,7 +727,7 @@ import { ref, computed, h, defineModel, markRaw, watch, nextTick } from 'vue' const { makeCall } = globalStore() const { getUser } = usersStore() -const { getContact } = contactsStore() +const { getContact, getLeadContact } = contactsStore() const props = defineProps({ title: { @@ -783,8 +783,11 @@ const calls = createListResource({ doc.duration = secondsToDuration(doc.duration) if (doc.type === 'Incoming') { doc.caller = { - label: getContact(doc.from)?.full_name || 'Unknown', - image: getContact(doc.from)?.image, + label: + getContact(doc.from)?.full_name || + getLeadContact(doc.from)?.full_name || + 'Unknown', + image: getContact(doc.from)?.image || getLeadContact(doc.from)?.image, } doc.receiver = { label: getUser(doc.receiver).full_name, @@ -796,8 +799,11 @@ const calls = createListResource({ image: getUser(doc.caller).user_image, } doc.receiver = { - label: getContact(doc.to)?.full_name || 'Unknown', - image: getContact(doc.to)?.image, + label: + getContact(doc.to)?.full_name || + getLeadContact(doc.to)?.full_name || + 'Unknown', + image: getContact(doc.to)?.image || getLeadContact(doc.to)?.image, } } }) diff --git a/frontend/src/components/CallUI.vue b/frontend/src/components/CallUI.vue index 6797fc05..3b999a20 100644 --- a/frontend/src/components/CallUI.vue +++ b/frontend/src/components/CallUI.vue @@ -188,7 +188,7 @@ import { contactsStore } from '@/stores/contacts' import { Avatar, call } from 'frappe-ui' import { onMounted, ref, watch } from 'vue' -const { getContact } = contactsStore() +const { getContact, getLeadContact } = contactsStore() const { setMakeCall, setTwilioEnabled } = globalStore() let device = '' @@ -309,8 +309,10 @@ function handleIncomingCall(call) { log.value = `Incoming call from ${call.parameters.From}` // get name of the caller from the phone number - contact.value = getContact(call.parameters.From) + if (!contact.value) { + contact.value = getLeadContact(call.parameters.From) + } if (!contact.value) { contact.value = { @@ -381,6 +383,9 @@ function handleDisconnectedIncomingCall() { async function makeOutgoingCall(number) { contact.value = getContact(number) + if (!contact.value) { + contact.value = getLeadContact(number) + } if (device) { log.value = `Attempting to call ${contact.value.mobile_no} ...` diff --git a/frontend/src/pages/CallLog.vue b/frontend/src/pages/CallLog.vue index fd5215c8..66d8a7e1 100644 --- a/frontend/src/pages/CallLog.vue +++ b/frontend/src/pages/CallLog.vue @@ -164,7 +164,7 @@ import { useRouter } from 'vue-router' const router = useRouter() const { getUser } = usersStore() -const { contacts, getContact } = contactsStore() +const { contacts, getContact, getLeadContact } = contactsStore() const props = defineProps({ callLogId: { @@ -186,8 +186,11 @@ const callLog = createResource({ doc.duration = secondsToDuration(doc.duration) if (doc.type === 'Incoming') { doc.caller = { - label: getContact(doc.from)?.full_name || 'Unknown', - image: getContact(doc.from)?.image, + label: + getContact(doc.from)?.full_name || + getLeadContact(doc.from)?.full_name || + 'Unknown', + image: getContact(doc.from)?.image || getLeadContact(doc.from)?.image, } doc.receiver = { label: getUser(doc.receiver).full_name, @@ -199,8 +202,11 @@ const callLog = createResource({ image: getUser(doc.caller).user_image, } doc.receiver = { - label: getContact(doc.to)?.full_name || 'Unknown', - image: getContact(doc.to)?.image, + label: + getContact(doc.to)?.full_name || + getLeadContact(doc.to)?.full_name || + 'Unknown', + image: getContact(doc.to)?.image || getLeadContact(doc.to)?.image, } } return doc diff --git a/frontend/src/pages/CallLogs.vue b/frontend/src/pages/CallLogs.vue index bc80dad6..35f8f7ba 100644 --- a/frontend/src/pages/CallLogs.vue +++ b/frontend/src/pages/CallLogs.vue @@ -4,7 +4,11 @@ - + { if (row === 'caller') { _rows[row] = { label: incoming - ? getContact(callLog.from)?.full_name || 'Unknown' + ? getContact(callLog.from)?.full_name || + getLeadContact(callLog.from)?.full_name || + 'Unknown' : getUser(callLog.caller).full_name, image: incoming - ? getContact(callLog.from)?.image + ? getContact(callLog.from)?.image || + getLeadContact(callLog.from)?.image : getUser(callLog.caller).user_image, } } else if (row === 'receiver') { _rows[row] = { label: incoming ? getUser(callLog.receiver).full_name - : getContact(callLog.to)?.full_name || 'Unknown', + : getContact(callLog.to)?.full_name || + getLeadContact(callLog.to)?.full_name || + 'Unknown', image: incoming ? getUser(callLog.receiver).user_image - : getContact(callLog.to)?.image, + : getContact(callLog.to)?.image || + getLeadContact(callLog.to)?.image, } } else if (row === 'duration') { _rows[row] = { diff --git a/frontend/src/stores/contacts.js b/frontend/src/stores/contacts.js index b8298d8a..9e35be3b 100644 --- a/frontend/src/stores/contacts.js +++ b/frontend/src/stores/contacts.js @@ -5,6 +5,7 @@ import { reactive } from 'vue' export const contactsStore = defineStore('crm-contacts', () => { let contactsByPhone = reactive({}) let contactsByName = reactive({}) + let leadContactsByPhone = reactive({}) const contacts = createResource({ url: 'crm.api.session.get_contacts', @@ -28,6 +29,28 @@ export const contactsStore = defineStore('crm-contacts', () => { }, }) + const leadContacts = createResource({ + url: 'crm.api.session.get_lead_contacts', + cache: 'lead_contacts', + initialData: [], + auto: true, + transform(lead_contacts) { + for (let lead_contact of lead_contacts) { + // remove special characters from phone number to make it easier to search + // also remove spaces but keep + sign at the start + lead_contact.mobile_no = lead_contact.mobile_no.replace(/[^0-9+]/g, '') + lead_contact.full_name = lead_contact.lead_name + leadContactsByPhone[lead_contact.mobile_no] = lead_contact + } + return lead_contacts + }, + onError(error) { + if (error && error.exc_type === 'AuthenticationError') { + router.push('/login') + } + }, + }) + function getContact(mobile_no) { mobile_no = mobile_no.replace(/[^0-9+]/g, '') return contactsByPhone[mobile_no] @@ -35,10 +58,15 @@ export const contactsStore = defineStore('crm-contacts', () => { function getContactByName(name) { return contactsByName[name] } + function getLeadContact(mobile_no) { + mobile_no = mobile_no.replace(/[^0-9+]/g, '') + return leadContactsByPhone[mobile_no] + } return { contacts, getContact, getContactByName, + getLeadContact, } })