fix: fix twilio contact viewing, note creation & linking code
This commit is contained in:
parent
e6d72146b5
commit
cfae3101c5
@ -24,34 +24,51 @@ def set_default_calling_medium(medium):
|
|||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def create_and_add_note_to_call_log(call_sid, content):
|
def add_note_to_call_log(call_sid, note):
|
||||||
"""Add note to call log based on call sid."""
|
"""Add/Update note to call log based on call sid."""
|
||||||
note = frappe.get_doc(
|
_note = None
|
||||||
{
|
if not note.get("name"):
|
||||||
"doctype": "FCRM Note",
|
_note = frappe.get_doc(
|
||||||
"content": content,
|
{
|
||||||
}
|
"doctype": "FCRM Note",
|
||||||
).insert(ignore_permissions=True)
|
"content": note.get("content"),
|
||||||
|
}
|
||||||
|
).insert(ignore_permissions=True)
|
||||||
|
call_log = frappe.get_cached_doc("CRM Call Log", call_sid)
|
||||||
|
call_log.link_with_reference_doc("FCRM Note", _note.name)
|
||||||
|
call_log.save(ignore_permissions=True)
|
||||||
|
else:
|
||||||
|
_note = frappe.set_value("FCRM Note", note.get("name"), "content", note.get("content"))
|
||||||
|
|
||||||
call_log = frappe.get_doc("CRM Call Log", call_sid)
|
return _note
|
||||||
call_log.link_with_reference_doc("FCRM Note", note.name)
|
|
||||||
call_log.save(ignore_permissions=True)
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def create_and_add_task_to_call_log(call_sid, task):
|
def add_task_to_call_log(call_sid, task):
|
||||||
"""Add task to call log based on call sid."""
|
"""Add/Update task to call log based on call sid."""
|
||||||
_task = frappe.get_doc(
|
_task = None
|
||||||
{
|
if not task.get("name"):
|
||||||
"doctype": "CRM Task",
|
_task = frappe.get_doc(
|
||||||
"title": task.get("title"),
|
{
|
||||||
"description": task.get("description"),
|
"doctype": "CRM Task",
|
||||||
}
|
"title": task.get("title"),
|
||||||
).insert(ignore_permissions=True)
|
"description": task.get("description"),
|
||||||
|
}
|
||||||
|
).insert(ignore_permissions=True)
|
||||||
|
call_log = frappe.get_doc("CRM Call Log", call_sid)
|
||||||
|
call_log.link_with_reference_doc("CRM Task", _task.name)
|
||||||
|
call_log.save(ignore_permissions=True)
|
||||||
|
else:
|
||||||
|
_task = frappe.get_doc("CRM Task", task.get("name"))
|
||||||
|
_task.update(
|
||||||
|
{
|
||||||
|
"title": task.get("title"),
|
||||||
|
"description": task.get("description"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
_task.save(ignore_permissions=True)
|
||||||
|
|
||||||
call_log = frappe.get_doc("CRM Call Log", call_sid)
|
return _task
|
||||||
call_log.link_with_reference_doc("CRM Task", _task.name)
|
|
||||||
call_log.save(ignore_permissions=True)
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
|||||||
@ -4,8 +4,9 @@ import frappe
|
|||||||
from frappe import _
|
from frappe import _
|
||||||
from werkzeug.wrappers import Response
|
from werkzeug.wrappers import Response
|
||||||
|
|
||||||
|
from crm.integrations.api import get_contact_by_phone_number
|
||||||
|
|
||||||
from .twilio_handler import IncomingCall, Twilio, TwilioCallDetails
|
from .twilio_handler import IncomingCall, Twilio, TwilioCallDetails
|
||||||
from .utils import parse_mobile_no
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
@ -69,13 +70,31 @@ def twilio_incoming_call_handler(**kwargs):
|
|||||||
|
|
||||||
|
|
||||||
def create_call_log(call_details: TwilioCallDetails):
|
def create_call_log(call_details: TwilioCallDetails):
|
||||||
call_log = frappe.get_doc(
|
details = call_details.to_dict()
|
||||||
{**call_details.to_dict(), "doctype": "CRM Call Log", "telephony_medium": "Twilio"}
|
|
||||||
)
|
call_log = frappe.get_doc({**details, "doctype": "CRM Call Log", "telephony_medium": "Twilio"})
|
||||||
call_log.reference_docname, call_log.reference_doctype = get_lead_or_deal_from_number(call_log)
|
|
||||||
call_log.flags.ignore_permissions = True
|
# link call log with lead/deal
|
||||||
call_log.save()
|
contact_number = details.get("from") if details.get("type") == "Incoming" else details.get("to")
|
||||||
|
link(contact_number, call_log)
|
||||||
|
|
||||||
|
call_log.save(ignore_permissions=True)
|
||||||
frappe.db.commit()
|
frappe.db.commit()
|
||||||
|
return call_log
|
||||||
|
|
||||||
|
|
||||||
|
def link(contact_number, call_log):
|
||||||
|
contact = get_contact_by_phone_number(contact_number)
|
||||||
|
if contact.get("name"):
|
||||||
|
doctype = "Contact"
|
||||||
|
docname = contact.get("name")
|
||||||
|
if contact.get("lead"):
|
||||||
|
doctype = "CRM Lead"
|
||||||
|
docname = contact.get("lead")
|
||||||
|
elif contact.get("deal"):
|
||||||
|
doctype = "CRM Deal"
|
||||||
|
docname = contact.get("deal")
|
||||||
|
call_log.link_with_reference_doc(doctype, docname)
|
||||||
|
|
||||||
|
|
||||||
def update_call_log(call_sid, status=None):
|
def update_call_log(call_sid, status=None):
|
||||||
@ -84,18 +103,19 @@ def update_call_log(call_sid, status=None):
|
|||||||
if not (twilio and frappe.db.exists("CRM Call Log", call_sid)):
|
if not (twilio and frappe.db.exists("CRM Call Log", call_sid)):
|
||||||
return
|
return
|
||||||
|
|
||||||
call_details = twilio.get_call_info(call_sid)
|
try:
|
||||||
call_log = frappe.get_doc("CRM Call Log", call_sid)
|
call_details = twilio.get_call_info(call_sid)
|
||||||
call_log.status = TwilioCallDetails.get_call_status(status or call_details.status)
|
call_log = frappe.get_doc("CRM Call Log", call_sid)
|
||||||
call_log.duration = call_details.duration
|
call_log.status = TwilioCallDetails.get_call_status(status or call_details.status)
|
||||||
call_log.start_time = get_datetime_from_timestamp(call_details.start_time)
|
call_log.duration = call_details.duration
|
||||||
call_log.end_time = get_datetime_from_timestamp(call_details.end_time)
|
call_log.start_time = get_datetime_from_timestamp(call_details.start_time)
|
||||||
if call_log.note and call_log.reference_docname:
|
call_log.end_time = get_datetime_from_timestamp(call_details.end_time)
|
||||||
frappe.db.set_value("FCRM Note", call_log.note, "reference_doctype", call_log.reference_doctype)
|
call_log.save(ignore_permissions=True)
|
||||||
frappe.db.set_value("FCRM Note", call_log.note, "reference_docname", call_log.reference_docname)
|
frappe.db.commit()
|
||||||
call_log.flags.ignore_permissions = True
|
return call_log
|
||||||
call_log.save()
|
except Exception:
|
||||||
frappe.db.commit()
|
frappe.log_error(title="Error while updating call record")
|
||||||
|
frappe.db.commit()
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist(allow_guest=True)
|
@frappe.whitelist(allow_guest=True)
|
||||||
@ -106,7 +126,7 @@ def update_recording_info(**kwargs):
|
|||||||
call_sid = args.CallSid
|
call_sid = args.CallSid
|
||||||
update_call_log(call_sid)
|
update_call_log(call_sid)
|
||||||
frappe.db.set_value("CRM Call Log", call_sid, "recording_url", recording_url)
|
frappe.db.set_value("CRM Call Log", call_sid, "recording_url", recording_url)
|
||||||
except:
|
except Exception:
|
||||||
frappe.log_error(title=_("Failed to capture Twilio recording"))
|
frappe.log_error(title=_("Failed to capture Twilio recording"))
|
||||||
|
|
||||||
|
|
||||||
@ -128,7 +148,7 @@ def update_call_status_info(**kwargs):
|
|||||||
|
|
||||||
client = Twilio.get_twilio_client()
|
client = Twilio.get_twilio_client()
|
||||||
client.calls(args.ParentCallSid).user_defined_messages.create(content=json.dumps(call_info))
|
client.calls(args.ParentCallSid).user_defined_messages.create(content=json.dumps(call_info))
|
||||||
except:
|
except Exception:
|
||||||
frappe.log_error(title=_("Failed to update Twilio call status"))
|
frappe.log_error(title=_("Failed to update Twilio call status"))
|
||||||
|
|
||||||
|
|
||||||
@ -144,45 +164,3 @@ def get_datetime_from_timestamp(timestamp):
|
|||||||
system_timezone = frappe.utils.get_system_timezone()
|
system_timezone = frappe.utils.get_system_timezone()
|
||||||
converted_datetime = datetime_utc_tz.astimezone(ZoneInfo(system_timezone))
|
converted_datetime = datetime_utc_tz.astimezone(ZoneInfo(system_timezone))
|
||||||
return frappe.utils.format_datetime(converted_datetime, "yyyy-MM-dd HH:mm:ss")
|
return frappe.utils.format_datetime(converted_datetime, "yyyy-MM-dd HH:mm:ss")
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def add_note_to_call_log(call_sid, note):
|
|
||||||
"""Add note to call log. based on child call sid."""
|
|
||||||
twilio = Twilio.connect()
|
|
||||||
if not twilio:
|
|
||||||
return
|
|
||||||
|
|
||||||
call_details = twilio.get_call_info(call_sid)
|
|
||||||
sid = call_sid if call_details.direction == "inbound" else call_details.parent_call_sid
|
|
||||||
|
|
||||||
frappe.db.set_value("CRM Call Log", sid, "note", note)
|
|
||||||
frappe.db.commit()
|
|
||||||
|
|
||||||
|
|
||||||
def get_lead_or_deal_from_number(call):
|
|
||||||
"""Get lead/deal from the given number."""
|
|
||||||
|
|
||||||
def find_record(doctype, mobile_no, where=""):
|
|
||||||
mobile_no = parse_mobile_no(mobile_no)
|
|
||||||
|
|
||||||
query = f"""
|
|
||||||
SELECT name, mobile_no
|
|
||||||
FROM `tab{doctype}`
|
|
||||||
WHERE CONCAT('+', REGEXP_REPLACE(mobile_no, '[^0-9]', '')) = {mobile_no}
|
|
||||||
"""
|
|
||||||
|
|
||||||
data = frappe.db.sql(query + where, as_dict=True)
|
|
||||||
return data[0].name if data else None
|
|
||||||
|
|
||||||
doctype = "CRM Deal"
|
|
||||||
number = call.get("to") if call.type == "Outgoing" else call.get("from")
|
|
||||||
|
|
||||||
doc = find_record(doctype, number) or None
|
|
||||||
if not doc:
|
|
||||||
doctype = "CRM Lead"
|
|
||||||
doc = find_record(doctype, number, "AND converted is not True")
|
|
||||||
if not doc:
|
|
||||||
doc = find_record(doctype, number)
|
|
||||||
|
|
||||||
return doc, doctype
|
|
||||||
|
|||||||
@ -15,10 +15,3 @@ def merge_dicts(d1: dict, d2: dict):
|
|||||||
"""
|
"""
|
||||||
return {k: {**v, **d2.get(k, {})} for k, v in d1.items()}
|
return {k: {**v, **d2.get(k, {})} for k, v in d1.items()}
|
||||||
|
|
||||||
|
|
||||||
def parse_mobile_no(mobile_no: str):
|
|
||||||
"""Parse mobile number to remove spaces, brackets, etc.
|
|
||||||
>>> parse_mobile_no("+91 (766) 667 6666")
|
|
||||||
... "+917666676666"
|
|
||||||
"""
|
|
||||||
return "".join([c for c in mobile_no if c.isdigit() or c == "+"])
|
|
||||||
|
|||||||
@ -146,8 +146,8 @@
|
|||||||
ref="content"
|
ref="content"
|
||||||
editor-class="prose-sm h-[290px] text-ink-white overflow-auto mt-1"
|
editor-class="prose-sm h-[290px] text-ink-white overflow-auto mt-1"
|
||||||
:bubbleMenu="true"
|
:bubbleMenu="true"
|
||||||
:content="note"
|
:content="note.content"
|
||||||
@change="(val) => (note = val)"
|
@change="(val) => (note.content = val)"
|
||||||
:placeholder="__('Take a note...')"
|
:placeholder="__('Take a note...')"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -210,8 +210,21 @@
|
|||||||
</template>
|
</template>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
v-if="(note && note != '<p></p>') || task.title"
|
v-if="(note.name || task.name) && dirty"
|
||||||
|
@click="update"
|
||||||
|
class="bg-surface-white !text-ink-gray-9 hover:!bg-surface-gray-3"
|
||||||
|
variant="solid"
|
||||||
|
:label="__('Update')"
|
||||||
|
size="md"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
v-else-if="
|
||||||
|
((note?.content && note.content != '<p></p>') || task.title) &&
|
||||||
|
!note.name &&
|
||||||
|
!task.name
|
||||||
|
"
|
||||||
@click="save"
|
@click="save"
|
||||||
class="bg-surface-white !text-ink-gray-9 hover:!bg-surface-gray-3"
|
class="bg-surface-white !text-ink-gray-9 hover:!bg-surface-gray-3"
|
||||||
variant="solid"
|
variant="solid"
|
||||||
@ -234,8 +247,8 @@ import CountUpTimer from '@/components/CountUpTimer.vue'
|
|||||||
import { createToast } from '@/utils'
|
import { createToast } from '@/utils'
|
||||||
import { globalStore } from '@/stores/global'
|
import { globalStore } from '@/stores/global'
|
||||||
import { useDraggable, useWindowSize } from '@vueuse/core'
|
import { useDraggable, useWindowSize } from '@vueuse/core'
|
||||||
import { TextEditor, Avatar, Button, call, createResource } from 'frappe-ui'
|
import { TextEditor, Avatar, Button, createResource } from 'frappe-ui'
|
||||||
import { ref, onBeforeUnmount, watch } from 'vue'
|
import { ref, onBeforeUnmount, watch, nextTick } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
const { $socket } = globalStore()
|
const { $socket } = globalStore()
|
||||||
@ -289,7 +302,12 @@ const getContact = createResource({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const note = ref('')
|
const dirty = ref(false)
|
||||||
|
|
||||||
|
const note = ref({
|
||||||
|
name: '',
|
||||||
|
content: '',
|
||||||
|
})
|
||||||
|
|
||||||
const showNote = ref(false)
|
const showNote = ref(false)
|
||||||
|
|
||||||
@ -303,15 +321,25 @@ function showNoteWindow() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createNote() {
|
function createUpdateNote() {
|
||||||
call('crm.integrations.api.create_and_add_note_to_call_log', {
|
createResource({
|
||||||
call_sid: callData.value.CallSid,
|
url: 'crm.integrations.api.add_note_to_call_log',
|
||||||
content: note.value,
|
params: {
|
||||||
|
call_sid: callData.value.CallSid,
|
||||||
|
note: note.value,
|
||||||
|
},
|
||||||
|
auto: true,
|
||||||
|
onSuccess(_note) {
|
||||||
|
note.value['name'] = _note.name
|
||||||
|
nextTick(() => {
|
||||||
|
dirty.value = false
|
||||||
|
})
|
||||||
|
},
|
||||||
})
|
})
|
||||||
note.value = ''
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const task = ref({
|
const task = ref({
|
||||||
|
name: '',
|
||||||
title: '',
|
title: '',
|
||||||
description: '',
|
description: '',
|
||||||
assigned_to: '',
|
assigned_to: '',
|
||||||
@ -332,21 +360,25 @@ function showTaskWindow() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createTask() {
|
function createUpdateTask() {
|
||||||
call('crm.integrations.api.create_and_add_task_to_call_log', {
|
createResource({
|
||||||
call_sid: callData.value.CallSid,
|
url: 'crm.integrations.api.add_task_to_call_log',
|
||||||
task: task.value,
|
params: {
|
||||||
|
call_sid: callData.value.CallSid,
|
||||||
|
task: task.value,
|
||||||
|
},
|
||||||
|
auto: true,
|
||||||
|
onSuccess(_task) {
|
||||||
|
task.value['name'] = _task.name
|
||||||
|
nextTick(() => {
|
||||||
|
dirty.value = false
|
||||||
|
})
|
||||||
|
},
|
||||||
})
|
})
|
||||||
task.value = {
|
|
||||||
title: '',
|
|
||||||
description: '',
|
|
||||||
assigned_to: '',
|
|
||||||
due_date: '',
|
|
||||||
status: 'Backlog',
|
|
||||||
priority: 'Low',
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch([note, task], () => (dirty.value = true), { deep: true })
|
||||||
|
|
||||||
function updateWindowHeight(condition) {
|
function updateWindowHeight(condition) {
|
||||||
let callPopup = callPopupHeader.value.parentElement
|
let callPopup = callPopupHeader.value.parentElement
|
||||||
let top = parseInt(callPopup.style.top)
|
let top = parseInt(callPopup.style.top)
|
||||||
@ -420,8 +452,12 @@ function openDealOrLead() {
|
|||||||
function closeCallPopup() {
|
function closeCallPopup() {
|
||||||
showCallPopup.value = false
|
showCallPopup.value = false
|
||||||
showSmallCallPopup.value = false
|
showSmallCallPopup.value = false
|
||||||
note.value = ''
|
note.value = {
|
||||||
|
name: '',
|
||||||
|
content: '',
|
||||||
|
}
|
||||||
task.value = {
|
task.value = {
|
||||||
|
name: '',
|
||||||
title: '',
|
title: '',
|
||||||
description: '',
|
description: '',
|
||||||
assigned_to: '',
|
assigned_to: '',
|
||||||
@ -432,8 +468,13 @@ function closeCallPopup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
if (note.value) createNote()
|
if (note.value.content) createUpdateNote()
|
||||||
if (task.value.title) createTask()
|
if (task.value.title) createUpdateTask()
|
||||||
|
}
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
if (note.value.content) createUpdateNote()
|
||||||
|
if (task.value.title) createUpdateTask()
|
||||||
}
|
}
|
||||||
|
|
||||||
const callDuration = ref('00:00')
|
const callDuration = ref('00:00')
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col items-center justify-center gap-3">
|
<div class="flex flex-col items-center justify-center gap-3">
|
||||||
<Avatar
|
<Avatar
|
||||||
|
v-if="contact?.image"
|
||||||
:image="contact.image"
|
:image="contact.image"
|
||||||
:label="contact.full_name"
|
:label="contact.full_name"
|
||||||
class="relative flex !h-24 !w-24 items-center justify-center [&>div]:text-[30px]"
|
class="relative flex !h-24 !w-24 items-center justify-center [&>div]:text-[30px]"
|
||||||
@ -20,9 +21,9 @@
|
|||||||
/>
|
/>
|
||||||
<div class="flex flex-col items-center justify-center gap-1">
|
<div class="flex flex-col items-center justify-center gap-1">
|
||||||
<div class="text-xl font-medium">
|
<div class="text-xl font-medium">
|
||||||
{{ contact.full_name }}
|
{{ contact?.full_name ?? __('Unknown') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm text-ink-gray-5">{{ contact.mobile_no }}</div>
|
<div class="text-sm text-ink-gray-5">{{ contact?.mobile_no }}</div>
|
||||||
</div>
|
</div>
|
||||||
<CountUpTimer ref="counterUp">
|
<CountUpTimer ref="counterUp">
|
||||||
<div v-if="onCall" class="my-1 text-base">
|
<div v-if="onCall" class="my-1 text-base">
|
||||||
@ -120,12 +121,13 @@
|
|||||||
>
|
>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<Avatar
|
<Avatar
|
||||||
|
v-if="contact?.image"
|
||||||
:image="contact.image"
|
:image="contact.image"
|
||||||
:label="contact.full_name"
|
:label="contact.full_name"
|
||||||
class="relative flex !h-5 !w-5 items-center justify-center"
|
class="relative flex !h-5 !w-5 items-center justify-center"
|
||||||
/>
|
/>
|
||||||
<div class="max-w-[120px] truncate">
|
<div class="max-w-[120px] truncate">
|
||||||
{{ contact.full_name }}
|
{{ contact?.full_name ?? __('Unknown') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="onCall" class="flex items-center gap-2">
|
<div v-if="onCall" class="flex items-center gap-2">
|
||||||
@ -195,20 +197,13 @@ import CountUpTimer from '@/components/CountUpTimer.vue'
|
|||||||
import NoteModal from '@/components/Modals/NoteModal.vue'
|
import NoteModal from '@/components/Modals/NoteModal.vue'
|
||||||
import { Device } from '@twilio/voice-sdk'
|
import { Device } from '@twilio/voice-sdk'
|
||||||
import { useDraggable, useWindowSize } from '@vueuse/core'
|
import { useDraggable, useWindowSize } from '@vueuse/core'
|
||||||
import { contactsStore } from '@/stores/contacts'
|
|
||||||
import { capture } from '@/telemetry'
|
import { capture } from '@/telemetry'
|
||||||
import { Avatar, call } from 'frappe-ui'
|
import { Avatar, call, createResource } from 'frappe-ui'
|
||||||
import { ref, watch } from 'vue'
|
import { ref, watch } from 'vue'
|
||||||
|
|
||||||
const { getContact, getLeadContact } = contactsStore()
|
|
||||||
|
|
||||||
let device = ''
|
let device = ''
|
||||||
let log = ref('Connecting...')
|
let log = ref('Connecting...')
|
||||||
let _call = null
|
let _call = null
|
||||||
const contact = ref({
|
|
||||||
full_name: '',
|
|
||||||
mobile_no: '',
|
|
||||||
})
|
|
||||||
|
|
||||||
let showCallPopup = ref(false)
|
let showCallPopup = ref(false)
|
||||||
let showSmallCallWindow = ref(false)
|
let showSmallCallWindow = ref(false)
|
||||||
@ -218,8 +213,36 @@ let muted = ref(false)
|
|||||||
let callPopup = ref(null)
|
let callPopup = ref(null)
|
||||||
let counterUp = ref(null)
|
let counterUp = ref(null)
|
||||||
let callStatus = ref('')
|
let callStatus = ref('')
|
||||||
|
|
||||||
|
const phoneNumber = ref('')
|
||||||
|
|
||||||
|
const contact = ref({
|
||||||
|
full_name: '',
|
||||||
|
image: '',
|
||||||
|
mobile_no: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(phoneNumber, (value) => {
|
||||||
|
if (!value) return
|
||||||
|
getContact.fetch()
|
||||||
|
})
|
||||||
|
|
||||||
|
const getContact = createResource({
|
||||||
|
url: 'crm.integrations.api.get_contact_by_phone_number',
|
||||||
|
makeParams() {
|
||||||
|
return {
|
||||||
|
phone_number: phoneNumber.value,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cache: ['contact', phoneNumber.value],
|
||||||
|
onSuccess(data) {
|
||||||
|
contact.value = data
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
const showNoteModal = ref(false)
|
const showNoteModal = ref(false)
|
||||||
const note = ref({
|
const note = ref({
|
||||||
|
name: '',
|
||||||
title: '',
|
title: '',
|
||||||
content: '',
|
content: '',
|
||||||
})
|
})
|
||||||
@ -227,9 +250,9 @@ const note = ref({
|
|||||||
async function updateNote(_note, insert_mode = false) {
|
async function updateNote(_note, insert_mode = false) {
|
||||||
note.value = _note
|
note.value = _note
|
||||||
if (insert_mode && _note.name) {
|
if (insert_mode && _note.name) {
|
||||||
await call('crm.integrations.twilio.api.add_note_to_call_log', {
|
await call('crm.integrations.api.add_note_to_call_log', {
|
||||||
call_sid: _call.parameters.CallSid,
|
call_sid: _call.parameters.CallSid,
|
||||||
note: _note.name,
|
note: _note,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -298,19 +321,7 @@ function toggleMute() {
|
|||||||
|
|
||||||
function handleIncomingCall(call) {
|
function handleIncomingCall(call) {
|
||||||
log.value = `Incoming call from ${call.parameters.From}`
|
log.value = `Incoming call from ${call.parameters.From}`
|
||||||
|
phoneNumber.value = 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 = {
|
|
||||||
full_name: __('Unknown'),
|
|
||||||
mobile_no: call.parameters.From,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
showCallPopup.value = true
|
showCallPopup.value = true
|
||||||
_call = call
|
_call = call
|
||||||
@ -352,6 +363,7 @@ function hangUpCall() {
|
|||||||
callStatus.value = ''
|
callStatus.value = ''
|
||||||
muted.value = false
|
muted.value = false
|
||||||
note.value = {
|
note.value = {
|
||||||
|
name: '',
|
||||||
title: '',
|
title: '',
|
||||||
content: '',
|
content: '',
|
||||||
}
|
}
|
||||||
@ -373,19 +385,7 @@ function handleDisconnectedIncomingCall() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function makeOutgoingCall(number) {
|
async function makeOutgoingCall(number) {
|
||||||
// check if number has a country code
|
phoneNumber.value = number
|
||||||
// if (number?.replace(/[^0-9+]/g, '').length == 10) {
|
|
||||||
// $dialog({
|
|
||||||
// title: 'Invalid Mobile Number',
|
|
||||||
// message: `${number} is not a valid mobile number. Either add a country code or check the number again.`,
|
|
||||||
// })
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
contact.value = getContact(number)
|
|
||||||
if (!contact.value) {
|
|
||||||
contact.value = getLeadContact(number)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (device) {
|
if (device) {
|
||||||
log.value = `Attempting to call ${number} ...`
|
log.value = `Attempting to call ${number} ...`
|
||||||
@ -431,6 +431,7 @@ async function makeOutgoingCall(number) {
|
|||||||
muted.value = false
|
muted.value = false
|
||||||
counterUp.value.stop()
|
counterUp.value.stop()
|
||||||
note.value = {
|
note.value = {
|
||||||
|
name: '',
|
||||||
title: '',
|
title: '',
|
||||||
content: '',
|
content: '',
|
||||||
}
|
}
|
||||||
@ -445,6 +446,7 @@ async function makeOutgoingCall(number) {
|
|||||||
callStatus.value = ''
|
callStatus.value = ''
|
||||||
muted.value = false
|
muted.value = false
|
||||||
note.value = {
|
note.value = {
|
||||||
|
name: '',
|
||||||
title: '',
|
title: '',
|
||||||
content: '',
|
content: '',
|
||||||
}
|
}
|
||||||
@ -471,6 +473,7 @@ function cancelCall() {
|
|||||||
callStatus.value = ''
|
callStatus.value = ''
|
||||||
muted.value = false
|
muted.value = false
|
||||||
note.value = {
|
note.value = {
|
||||||
|
name: '',
|
||||||
title: '',
|
title: '',
|
||||||
content: '',
|
content: '',
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user