Merge branch 'develop' into onboarding
This commit is contained in:
commit
6ebcd0e887
@ -30,59 +30,6 @@ def get_users():
|
|||||||
return users
|
return users
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def get_contacts():
|
|
||||||
contacts = frappe.get_all(
|
|
||||||
"Contact",
|
|
||||||
fields=[
|
|
||||||
"name",
|
|
||||||
"salutation",
|
|
||||||
"first_name",
|
|
||||||
"last_name",
|
|
||||||
"full_name",
|
|
||||||
"gender",
|
|
||||||
"address",
|
|
||||||
"designation",
|
|
||||||
"image",
|
|
||||||
"email_id",
|
|
||||||
"mobile_no",
|
|
||||||
"phone",
|
|
||||||
"company_name",
|
|
||||||
"modified",
|
|
||||||
],
|
|
||||||
order_by="first_name asc",
|
|
||||||
distinct=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
for contact in contacts:
|
|
||||||
contact["email_ids"] = frappe.get_all(
|
|
||||||
"Contact Email",
|
|
||||||
filters={"parenttype": "Contact", "parent": contact.name},
|
|
||||||
fields=["name", "email_id", "is_primary"],
|
|
||||||
)
|
|
||||||
|
|
||||||
contact["phone_nos"] = frappe.get_all(
|
|
||||||
"Contact Phone",
|
|
||||||
filters={"parenttype": "Contact", "parent": contact.name},
|
|
||||||
fields=["name", "phone", "is_primary_phone", "is_primary_mobile_no"],
|
|
||||||
)
|
|
||||||
|
|
||||||
return contacts
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def get_lead_contacts():
|
|
||||||
lead_contacts = frappe.get_all(
|
|
||||||
"CRM Lead",
|
|
||||||
fields=["name", "lead_name", "mobile_no", "phone", "image", "modified"],
|
|
||||||
filters={"converted": 0},
|
|
||||||
order_by="lead_name asc",
|
|
||||||
distinct=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
return lead_contacts
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_organizations():
|
def get_organizations():
|
||||||
organizations = frappe.qb.get_query(
|
organizations = frappe.qb.get_query(
|
||||||
|
|||||||
@ -20,9 +20,13 @@ def get_deal_contacts(name):
|
|||||||
"CRM Contacts",
|
"CRM Contacts",
|
||||||
filters={"parenttype": "CRM Deal", "parent": name},
|
filters={"parenttype": "CRM Deal", "parent": name},
|
||||||
fields=["contact", "is_primary"],
|
fields=["contact", "is_primary"],
|
||||||
|
distinct=True,
|
||||||
)
|
)
|
||||||
deal_contacts = []
|
deal_contacts = []
|
||||||
for contact in contacts:
|
for contact in contacts:
|
||||||
|
if not contact.contact:
|
||||||
|
continue
|
||||||
|
|
||||||
is_primary = contact.is_primary
|
is_primary = contact.is_primary
|
||||||
contact = frappe.get_doc("Contact", contact.contact).as_dict()
|
contact = frappe.get_doc("Contact", contact.contact).as_dict()
|
||||||
|
|
||||||
|
|||||||
@ -115,13 +115,14 @@ class CRMLead(Document):
|
|||||||
elif user != agent:
|
elif user != agent:
|
||||||
frappe.share.remove(self.doctype, self.name, user)
|
frappe.share.remove(self.doctype, self.name, user)
|
||||||
|
|
||||||
def create_contact(self, throw=True):
|
def create_contact(self, existing_contact=None, throw=True):
|
||||||
if not self.lead_name:
|
if not self.lead_name:
|
||||||
self.set_full_name()
|
self.set_full_name()
|
||||||
self.set_lead_name()
|
self.set_lead_name()
|
||||||
|
|
||||||
existing_contact = self.contact_exists(throw)
|
existing_contact = existing_contact or self.contact_exists(throw)
|
||||||
if existing_contact:
|
if existing_contact:
|
||||||
|
self.update_lead_contact(existing_contact)
|
||||||
return existing_contact
|
return existing_contact
|
||||||
|
|
||||||
contact = frappe.new_doc("Contact")
|
contact = frappe.new_doc("Contact")
|
||||||
@ -151,12 +152,15 @@ class CRMLead(Document):
|
|||||||
|
|
||||||
return contact.name
|
return contact.name
|
||||||
|
|
||||||
def create_organization(self):
|
def create_organization(self, existing_organization=None):
|
||||||
if not self.organization:
|
if not self.organization and not existing_organization:
|
||||||
return
|
return
|
||||||
|
|
||||||
existing_organization = frappe.db.exists("CRM Organization", {"organization_name": self.organization})
|
existing_organization = existing_organization or frappe.db.exists(
|
||||||
|
"CRM Organization", {"organization_name": self.organization}
|
||||||
|
)
|
||||||
if existing_organization:
|
if existing_organization:
|
||||||
|
self.db_set("organization", existing_organization)
|
||||||
return existing_organization
|
return existing_organization
|
||||||
|
|
||||||
organization = frappe.new_doc("CRM Organization")
|
organization = frappe.new_doc("CRM Organization")
|
||||||
@ -172,6 +176,20 @@ class CRMLead(Document):
|
|||||||
organization.insert(ignore_permissions=True)
|
organization.insert(ignore_permissions=True)
|
||||||
return organization.name
|
return organization.name
|
||||||
|
|
||||||
|
def update_lead_contact(self, contact):
|
||||||
|
contact = frappe.get_cached_doc("Contact", contact)
|
||||||
|
frappe.db.set_value(
|
||||||
|
"CRM Lead",
|
||||||
|
self.name,
|
||||||
|
{
|
||||||
|
"salutation": contact.salutation,
|
||||||
|
"first_name": contact.first_name,
|
||||||
|
"last_name": contact.last_name,
|
||||||
|
"email": contact.email_id,
|
||||||
|
"mobile_no": contact.mobile_no,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
def contact_exists(self, throw=True):
|
def contact_exists(self, throw=True):
|
||||||
email_exist = frappe.db.exists("Contact Email", {"email_id": self.email})
|
email_exist = frappe.db.exists("Contact Email", {"email_id": self.email})
|
||||||
phone_exist = frappe.db.exists("Contact Phone", {"phone": self.phone})
|
phone_exist = frappe.db.exists("Contact Phone", {"phone": self.phone})
|
||||||
@ -383,7 +401,7 @@ class CRMLead(Document):
|
|||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def convert_to_deal(lead, doc=None, deal=None):
|
def convert_to_deal(lead, doc=None, deal=None, existing_contact=None, existing_organization=None):
|
||||||
if not (doc and doc.flags.get("ignore_permissions")) and not frappe.has_permission(
|
if not (doc and doc.flags.get("ignore_permissions")) and not frappe.has_permission(
|
||||||
"CRM Lead", "write", lead
|
"CRM Lead", "write", lead
|
||||||
):
|
):
|
||||||
@ -395,7 +413,7 @@ def convert_to_deal(lead, doc=None, deal=None):
|
|||||||
lead.db_set("converted", 1)
|
lead.db_set("converted", 1)
|
||||||
if lead.sla and frappe.db.exists("CRM Communication Status", "Replied"):
|
if lead.sla and frappe.db.exists("CRM Communication Status", "Replied"):
|
||||||
lead.db_set("communication_status", "Replied")
|
lead.db_set("communication_status", "Replied")
|
||||||
contact = lead.create_contact(False)
|
contact = lead.create_contact(existing_contact, False)
|
||||||
organization = lead.create_organization()
|
organization = lead.create_organization(existing_organization)
|
||||||
_deal = lead.create_deal(contact, organization, deal)
|
_deal = lead.create_deal(contact, organization, deal)
|
||||||
return _deal
|
return _deal
|
||||||
|
|||||||
@ -487,7 +487,6 @@ import FilesUploader from '@/components/FilesUploader/FilesUploader.vue'
|
|||||||
import { timeAgo, formatDate, startCase } from '@/utils'
|
import { timeAgo, formatDate, startCase } from '@/utils'
|
||||||
import { globalStore } from '@/stores/global'
|
import { globalStore } from '@/stores/global'
|
||||||
import { usersStore } from '@/stores/users'
|
import { usersStore } from '@/stores/users'
|
||||||
import { contactsStore } from '@/stores/contacts'
|
|
||||||
import { whatsappEnabled } from '@/composables/settings'
|
import { whatsappEnabled } from '@/composables/settings'
|
||||||
import { capture } from '@/telemetry'
|
import { capture } from '@/telemetry'
|
||||||
import { Button, Tooltip, createResource } from 'frappe-ui'
|
import { Button, Tooltip, createResource } from 'frappe-ui'
|
||||||
@ -506,7 +505,6 @@ import { useRoute } from 'vue-router'
|
|||||||
|
|
||||||
const { makeCall, $socket } = globalStore()
|
const { makeCall, $socket } = globalStore()
|
||||||
const { getUser } = usersStore()
|
const { getUser } = usersStore()
|
||||||
const { getContact, getLeadContact } = contactsStore()
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
doctype: {
|
doctype: {
|
||||||
|
|||||||
@ -203,7 +203,9 @@
|
|||||||
label: __('Export'),
|
label: __('Export'),
|
||||||
icon: () => h(ExportIcon, { class: 'h-4 w-4' }),
|
icon: () => h(ExportIcon, { class: 'h-4 w-4' }),
|
||||||
onClick: () => (showExportDialog = true),
|
onClick: () => (showExportDialog = true),
|
||||||
condition: () => !options.hideColumnsButton && route.params.viewType !== 'kanban',
|
condition: () =>
|
||||||
|
!options.hideColumnsButton &&
|
||||||
|
route.params.viewType !== 'kanban',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: __('Customize quick filters'),
|
label: __('Customize quick filters'),
|
||||||
@ -535,6 +537,7 @@ onMounted(() => useDebounceFn(reload, 100)())
|
|||||||
const isLoading = computed(() => list.value?.loading)
|
const isLoading = computed(() => list.value?.loading)
|
||||||
|
|
||||||
function reload() {
|
function reload() {
|
||||||
|
if (isLoading.value) return
|
||||||
list.value.params = getParams()
|
list.value.params = getParams()
|
||||||
list.value.reload()
|
list.value.reload()
|
||||||
}
|
}
|
||||||
@ -803,12 +806,13 @@ const quickFilters = createResource({
|
|||||||
url: 'crm.api.doc.get_quick_filters',
|
url: 'crm.api.doc.get_quick_filters',
|
||||||
params: { doctype: props.doctype },
|
params: { doctype: props.doctype },
|
||||||
cache: ['Quick Filters', props.doctype],
|
cache: ['Quick Filters', props.doctype],
|
||||||
auto: true,
|
|
||||||
onSuccess(filters) {
|
onSuccess(filters) {
|
||||||
setupNewQuickFilters(filters)
|
setupNewQuickFilters(filters)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (!quickFilters.data) quickFilters.fetch()
|
||||||
|
|
||||||
function setupNewQuickFilters(filters) {
|
function setupNewQuickFilters(filters) {
|
||||||
newQuickFilters.value = filters.map((f) => ({
|
newQuickFilters.value = filters.map((f) => ({
|
||||||
label: f.label,
|
label: f.label,
|
||||||
|
|||||||
@ -571,10 +571,11 @@ const sections = createResource({
|
|||||||
url: 'crm.fcrm.doctype.crm_fields_layout.crm_fields_layout.get_sidepanel_sections',
|
url: 'crm.fcrm.doctype.crm_fields_layout.crm_fields_layout.get_sidepanel_sections',
|
||||||
cache: ['sidePanelSections', 'CRM Deal'],
|
cache: ['sidePanelSections', 'CRM Deal'],
|
||||||
params: { doctype: 'CRM Deal' },
|
params: { doctype: 'CRM Deal' },
|
||||||
auto: true,
|
|
||||||
transform: (data) => getParsedSections(data),
|
transform: (data) => getParsedSections(data),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (!sections.data) sections.fetch()
|
||||||
|
|
||||||
function getParsedSections(_sections) {
|
function getParsedSections(_sections) {
|
||||||
_sections.forEach((section) => {
|
_sections.forEach((section) => {
|
||||||
if (section.name == 'contacts_section') return
|
if (section.name == 'contacts_section') return
|
||||||
@ -677,7 +678,6 @@ const dealContacts = createResource({
|
|||||||
url: 'crm.fcrm.doctype.crm_deal.api.get_deal_contacts',
|
url: 'crm.fcrm.doctype.crm_deal.api.get_deal_contacts',
|
||||||
params: { name: props.dealId },
|
params: { name: props.dealId },
|
||||||
cache: ['deal_contacts', props.dealId],
|
cache: ['deal_contacts', props.dealId],
|
||||||
auto: true,
|
|
||||||
transform: (data) => {
|
transform: (data) => {
|
||||||
data.forEach((contact) => {
|
data.forEach((contact) => {
|
||||||
contact.opened = false
|
contact.opened = false
|
||||||
@ -686,6 +686,8 @@ const dealContacts = createResource({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (!dealContacts.data) dealContacts.fetch()
|
||||||
|
|
||||||
function triggerCall() {
|
function triggerCall() {
|
||||||
let primaryContact = dealContacts.data?.find((c) => c.is_primary)
|
let primaryContact = dealContacts.data?.find((c) => c.is_primary)
|
||||||
let mobile_no = primaryContact.mobile_no || null
|
let mobile_no = primaryContact.mobile_no || null
|
||||||
|
|||||||
@ -341,7 +341,6 @@ import { getView } from '@/utils/view'
|
|||||||
import { getSettings } from '@/stores/settings'
|
import { getSettings } from '@/stores/settings'
|
||||||
import { usersStore } from '@/stores/users'
|
import { usersStore } from '@/stores/users'
|
||||||
import { globalStore } from '@/stores/global'
|
import { globalStore } from '@/stores/global'
|
||||||
import { contactsStore } from '@/stores/contacts'
|
|
||||||
import { statusesStore } from '@/stores/statuses'
|
import { statusesStore } from '@/stores/statuses'
|
||||||
import { getMeta } from '@/stores/meta'
|
import { getMeta } from '@/stores/meta'
|
||||||
import {
|
import {
|
||||||
@ -370,7 +369,6 @@ import { useActiveTabManager } from '@/composables/useActiveTabManager'
|
|||||||
const { brand } = getSettings()
|
const { brand } = getSettings()
|
||||||
const { isManager } = usersStore()
|
const { isManager } = usersStore()
|
||||||
const { $dialog, $socket, makeCall } = globalStore()
|
const { $dialog, $socket, makeCall } = globalStore()
|
||||||
const { getContactByName, contacts } = contactsStore()
|
|
||||||
const { statusOptions, getLeadStatus, getDealStatus } = statusesStore()
|
const { statusOptions, getLeadStatus, getDealStatus } = statusesStore()
|
||||||
const { doctypeMeta } = getMeta('CRM Lead')
|
const { doctypeMeta } = getMeta('CRM Lead')
|
||||||
|
|
||||||
@ -603,9 +601,7 @@ const existingOrganizationChecked = ref(false)
|
|||||||
const existingContact = ref('')
|
const existingContact = ref('')
|
||||||
const existingOrganization = ref('')
|
const existingOrganization = ref('')
|
||||||
|
|
||||||
async function convertToDeal(updated) {
|
async function convertToDeal() {
|
||||||
let valueUpdated = false
|
|
||||||
|
|
||||||
if (existingContactChecked.value && !existingContact.value) {
|
if (existingContactChecked.value && !existingContact.value) {
|
||||||
createToast({
|
createToast({
|
||||||
title: __('Error'),
|
title: __('Error'),
|
||||||
@ -626,56 +622,36 @@ async function convertToDeal(updated) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existingContactChecked.value && existingContact.value) {
|
if (!existingContactChecked.value && existingContact.value) {
|
||||||
lead.data.salutation = getContactByName(existingContact.value).salutation
|
existingContact.value = ''
|
||||||
lead.data.first_name = getContactByName(existingContact.value).first_name
|
|
||||||
lead.data.last_name = getContactByName(existingContact.value).last_name
|
|
||||||
lead.data.email_id = getContactByName(existingContact.value).email_id
|
|
||||||
lead.data.mobile_no = getContactByName(existingContact.value).mobile_no
|
|
||||||
existingContactChecked.value = false
|
|
||||||
valueUpdated = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existingOrganizationChecked.value && existingOrganization.value) {
|
if (!existingOrganizationChecked.value && existingOrganization.value) {
|
||||||
lead.data.organization = existingOrganization.value
|
existingOrganization.value = ''
|
||||||
existingOrganizationChecked.value = false
|
|
||||||
valueUpdated = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valueUpdated) {
|
let _deal = await call('crm.fcrm.doctype.crm_lead.crm_lead.convert_to_deal', {
|
||||||
updateLead(
|
lead: lead.data.name,
|
||||||
{
|
deal,
|
||||||
salutation: lead.data.salutation,
|
existing_contact: existingContact.value,
|
||||||
first_name: lead.data.first_name,
|
existing_organization: existingOrganization.value,
|
||||||
last_name: lead.data.last_name,
|
}).catch((err) => {
|
||||||
email_id: lead.data.email_id,
|
createToast({
|
||||||
mobile_no: lead.data.mobile_no,
|
title: __('Error converting to deal'),
|
||||||
organization: lead.data.organization,
|
text: __(err.messages?.[0]),
|
||||||
},
|
icon: 'x',
|
||||||
'',
|
iconClasses: 'text-ink-red-4',
|
||||||
() => convertToDeal(true),
|
|
||||||
)
|
|
||||||
showConvertToDealModal.value = false
|
|
||||||
} else {
|
|
||||||
let _deal = await call(
|
|
||||||
'crm.fcrm.doctype.crm_lead.crm_lead.convert_to_deal',
|
|
||||||
{ lead: lead.data.name, deal },
|
|
||||||
).catch((err) => {
|
|
||||||
createToast({
|
|
||||||
title: __('Error converting to deal'),
|
|
||||||
text: __(err.messages?.[0]),
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'text-ink-red-4',
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
if (_deal) {
|
})
|
||||||
updateOnboardingStep('convert_lead_to_deal')
|
if (_deal) {
|
||||||
capture('convert_lead_to_deal')
|
showConvertToDealModal.value = false
|
||||||
if (updated) {
|
existingContactChecked.value = false
|
||||||
await contacts.reload()
|
existingOrganizationChecked.value = false
|
||||||
}
|
existingContact.value = ''
|
||||||
router.push({ name: 'Deal', params: { dealId: _deal } })
|
existingOrganization.value = ''
|
||||||
}
|
updateOnboardingStep('convert_lead_to_deal')
|
||||||
|
capture('convert_lead_to_deal')
|
||||||
|
router.push({ name: 'Deal', params: { dealId: _deal } })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -178,7 +178,6 @@ import { createToast, setupAssignees, setupCustomizations } from '@/utils'
|
|||||||
import { getView } from '@/utils/view'
|
import { getView } from '@/utils/view'
|
||||||
import { getSettings } from '@/stores/settings'
|
import { getSettings } from '@/stores/settings'
|
||||||
import { globalStore } from '@/stores/global'
|
import { globalStore } from '@/stores/global'
|
||||||
import { contactsStore } from '@/stores/contacts'
|
|
||||||
import { statusesStore } from '@/stores/statuses'
|
import { statusesStore } from '@/stores/statuses'
|
||||||
import { getMeta } from '@/stores/meta'
|
import { getMeta } from '@/stores/meta'
|
||||||
import {
|
import {
|
||||||
@ -186,6 +185,7 @@ import {
|
|||||||
callEnabled,
|
callEnabled,
|
||||||
isMobileView,
|
isMobileView,
|
||||||
} from '@/composables/settings'
|
} from '@/composables/settings'
|
||||||
|
import { capture } from '@/telemetry'
|
||||||
import { useActiveTabManager } from '@/composables/useActiveTabManager'
|
import { useActiveTabManager } from '@/composables/useActiveTabManager'
|
||||||
import {
|
import {
|
||||||
createResource,
|
createResource,
|
||||||
@ -203,7 +203,6 @@ import { useRouter, useRoute } from 'vue-router'
|
|||||||
|
|
||||||
const { brand } = getSettings()
|
const { brand } = getSettings()
|
||||||
const { $dialog, $socket } = globalStore()
|
const { $dialog, $socket } = globalStore()
|
||||||
const { getContactByName, contacts } = contactsStore()
|
|
||||||
const { statusOptions, getLeadStatus } = statusesStore()
|
const { statusOptions, getLeadStatus } = statusesStore()
|
||||||
const { doctypeMeta } = getMeta('CRM Lead')
|
const { doctypeMeta } = getMeta('CRM Lead')
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
@ -433,9 +432,7 @@ const existingOrganizationChecked = ref(false)
|
|||||||
const existingContact = ref('')
|
const existingContact = ref('')
|
||||||
const existingOrganization = ref('')
|
const existingOrganization = ref('')
|
||||||
|
|
||||||
async function convertToDeal(updated) {
|
async function convertToDeal() {
|
||||||
let valueUpdated = false
|
|
||||||
|
|
||||||
if (existingContactChecked.value && !existingContact.value) {
|
if (existingContactChecked.value && !existingContact.value) {
|
||||||
createToast({
|
createToast({
|
||||||
title: __('Error'),
|
title: __('Error'),
|
||||||
@ -456,49 +453,28 @@ async function convertToDeal(updated) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existingContactChecked.value && existingContact.value) {
|
if (!existingContactChecked.value && existingContact.value) {
|
||||||
lead.data.salutation = getContactByName(existingContact.value).salutation
|
existingContact.value = ''
|
||||||
lead.data.first_name = getContactByName(existingContact.value).first_name
|
|
||||||
lead.data.last_name = getContactByName(existingContact.value).last_name
|
|
||||||
lead.data.email_id = getContactByName(existingContact.value).email_id
|
|
||||||
lead.data.mobile_no = getContactByName(existingContact.value).mobile_no
|
|
||||||
existingContactChecked.value = false
|
|
||||||
valueUpdated = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existingOrganizationChecked.value && existingOrganization.value) {
|
if (!existingOrganizationChecked.value && existingOrganization.value) {
|
||||||
lead.data.organization = existingOrganization.value
|
existingOrganization.value = ''
|
||||||
existingOrganizationChecked.value = false
|
|
||||||
valueUpdated = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valueUpdated) {
|
let deal = await call('crm.fcrm.doctype.crm_lead.crm_lead.convert_to_deal', {
|
||||||
updateLead(
|
lead: lead.data.name,
|
||||||
{
|
deal: {},
|
||||||
salutation: lead.data.salutation,
|
existing_contact: existingContact.value,
|
||||||
first_name: lead.data.first_name,
|
existing_organization: existingOrganization.value,
|
||||||
last_name: lead.data.last_name,
|
})
|
||||||
email_id: lead.data.email_id,
|
if (deal) {
|
||||||
mobile_no: lead.data.mobile_no,
|
|
||||||
organization: lead.data.organization,
|
|
||||||
},
|
|
||||||
'',
|
|
||||||
() => convertToDeal(true),
|
|
||||||
)
|
|
||||||
showConvertToDealModal.value = false
|
showConvertToDealModal.value = false
|
||||||
} else {
|
existingContactChecked.value = false
|
||||||
let deal = await call(
|
existingOrganizationChecked.value = false
|
||||||
'crm.fcrm.doctype.crm_lead.crm_lead.convert_to_deal',
|
existingContact.value = ''
|
||||||
{
|
existingOrganization.value = ''
|
||||||
lead: lead.data.name,
|
capture('convert_lead_to_deal')
|
||||||
},
|
router.push({ name: 'Deal', params: { dealId: deal } })
|
||||||
)
|
|
||||||
if (deal) {
|
|
||||||
if (updated) {
|
|
||||||
await contacts.reload()
|
|
||||||
}
|
|
||||||
router.push({ name: 'Deal', params: { dealId: deal } })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,80 +0,0 @@
|
|||||||
import { defineStore } from 'pinia'
|
|
||||||
import { createResource } from 'frappe-ui'
|
|
||||||
import { reactive } from 'vue'
|
|
||||||
|
|
||||||
export const contactsStore = defineStore('crm-contacts', () => {
|
|
||||||
let contactsByPhone = reactive({})
|
|
||||||
let contactsByName = reactive({})
|
|
||||||
let leadContactsByPhone = reactive({})
|
|
||||||
let allContacts = reactive([])
|
|
||||||
|
|
||||||
const contacts = createResource({
|
|
||||||
url: 'crm.api.session.get_contacts',
|
|
||||||
cache: 'contacts',
|
|
||||||
initialData: [],
|
|
||||||
auto: true,
|
|
||||||
transform(contacts) {
|
|
||||||
for (let contact of contacts) {
|
|
||||||
// remove special characters from phone number to make it easier to search
|
|
||||||
// also remove spaces but keep + sign at the start
|
|
||||||
contact.actual_mobile_no = contact.mobile_no
|
|
||||||
contact.mobile_no = contact.mobile_no?.replace(/[^0-9+]/g, '')
|
|
||||||
contactsByPhone[contact.mobile_no] = contact
|
|
||||||
contactsByName[contact.name] = contact
|
|
||||||
}
|
|
||||||
allContacts = [...contacts]
|
|
||||||
return contacts
|
|
||||||
},
|
|
||||||
onError(error) {
|
|
||||||
if (error && error.exc_type === 'AuthenticationError') {
|
|
||||||
router.push('/login')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
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]
|
|
||||||
}
|
|
||||||
function getContactByName(name) {
|
|
||||||
return contactsByName[name]
|
|
||||||
}
|
|
||||||
function getLeadContact(mobile_no) {
|
|
||||||
mobile_no = mobile_no?.replace(/[^0-9+]/g, '')
|
|
||||||
return leadContactsByPhone[mobile_no]
|
|
||||||
}
|
|
||||||
|
|
||||||
function getContacts() {
|
|
||||||
return allContacts || contacts?.data || []
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
contacts,
|
|
||||||
getContacts,
|
|
||||||
getContact,
|
|
||||||
getContactByName,
|
|
||||||
getLeadContact,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
@ -24,7 +24,7 @@ export function getMeta(doctype) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!doctypeMeta[doctype]) {
|
if (!doctypeMeta[doctype] && !meta.loading) {
|
||||||
meta.fetch()
|
meta.fetch()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,17 +4,17 @@ import { reactive, ref } from 'vue'
|
|||||||
const settings = ref({})
|
const settings = ref({})
|
||||||
const brand = reactive({})
|
const brand = reactive({})
|
||||||
|
|
||||||
export function getSettings() {
|
const _settings = createDocumentResource({
|
||||||
const _settings = createDocumentResource({
|
doctype: 'FCRM Settings',
|
||||||
doctype: 'FCRM Settings',
|
name: 'FCRM Settings',
|
||||||
name: 'FCRM Settings',
|
onSuccess: (data) => {
|
||||||
onSuccess: (data) => {
|
settings.value = data
|
||||||
settings.value = data
|
getSettings().setupBrand()
|
||||||
setupBrand()
|
return data
|
||||||
return data
|
},
|
||||||
},
|
})
|
||||||
})
|
|
||||||
|
|
||||||
|
export function getSettings() {
|
||||||
function setupBrand() {
|
function setupBrand() {
|
||||||
brand.name = settings.value?.brand_name
|
brand.name = settings.value?.brand_name
|
||||||
brand.logo = settings.value?.brand_logo
|
brand.logo = settings.value?.brand_logo
|
||||||
|
|||||||
@ -75,11 +75,9 @@ export function timeAgo(date) {
|
|||||||
return useTimeAgo(date).value
|
return useTimeAgo(date).value
|
||||||
}
|
}
|
||||||
|
|
||||||
const taskMeta = getMeta('CRM Task')
|
|
||||||
|
|
||||||
export function taskStatusOptions(action, data) {
|
export function taskStatusOptions(action, data) {
|
||||||
let options = ['Backlog', 'Todo', 'In Progress', 'Done', 'Canceled']
|
let options = ['Backlog', 'Todo', 'In Progress', 'Done', 'Canceled']
|
||||||
let statusMeta = taskMeta
|
let statusMeta = getMeta('CRM Task')
|
||||||
.getFields()
|
.getFields()
|
||||||
?.find((field) => field.fieldname == 'status')
|
?.find((field) => field.fieldname == 'status')
|
||||||
if (statusMeta) {
|
if (statusMeta) {
|
||||||
@ -98,7 +96,7 @@ export function taskStatusOptions(action, data) {
|
|||||||
|
|
||||||
export function taskPriorityOptions(action, data) {
|
export function taskPriorityOptions(action, data) {
|
||||||
let options = ['Low', 'Medium', 'High']
|
let options = ['Low', 'Medium', 'High']
|
||||||
let priorityMeta = taskMeta
|
let priorityMeta = getMeta('CRM Task')
|
||||||
.getFields()
|
.getFields()
|
||||||
?.find((field) => field.fieldname == 'priority')
|
?.find((field) => field.fieldname == 'priority')
|
||||||
if (priorityMeta) {
|
if (priorityMeta) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user