Merge pull request #739 from frappe/main-hotfix
This commit is contained in:
commit
de50772a22
@ -63,6 +63,11 @@ def check_app_permission():
|
||||
if frappe.session.user == "Administrator":
|
||||
return True
|
||||
|
||||
allowed_modules = frappe.utils.modules.get_modules_from_all_apps_for_user()
|
||||
allowed_modules = [x["module_name"] for x in allowed_modules]
|
||||
if "FCRM" not in allowed_modules:
|
||||
return False
|
||||
|
||||
roles = frappe.get_roles()
|
||||
if any(
|
||||
role in ["System Manager", "Sales User", "Sales Manager", "Sales Master Manager"] for role in roles
|
||||
|
||||
@ -23,11 +23,11 @@ def update_deals_email_mobile_no(doc):
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_contact(name):
|
||||
Contact = frappe.qb.DocType("Contact")
|
||||
contact = frappe.get_doc("Contact", name)
|
||||
contact.check_permission("read")
|
||||
|
||||
query = frappe.qb.from_(Contact).select("*").where(Contact.name == name).limit(1)
|
||||
contact = contact.as_dict()
|
||||
|
||||
contact = query.run(as_dict=True)
|
||||
if not len(contact):
|
||||
frappe.throw(_("Contact not found"), frappe.DoesNotExistError)
|
||||
contact = contact.pop()
|
||||
|
||||
@ -6,7 +6,10 @@ from crm.fcrm.doctype.crm_form_script.crm_form_script import get_form_script
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_deal(name):
|
||||
deal = frappe.get_doc("CRM Deal", name).as_dict()
|
||||
deal = frappe.get_doc("CRM Deal", name)
|
||||
deal.check_permission("read")
|
||||
|
||||
deal = deal.as_dict()
|
||||
|
||||
deal["fields_meta"] = get_fields_meta("CRM Deal")
|
||||
deal["_form_script"] = get_form_script("CRM Deal")
|
||||
|
||||
@ -6,7 +6,10 @@ from crm.fcrm.doctype.crm_form_script.crm_form_script import get_form_script
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_lead(name):
|
||||
lead = frappe.get_doc("CRM Lead", name).as_dict()
|
||||
lead = frappe.get_doc("CRM Lead", name)
|
||||
lead.check_permission("read")
|
||||
|
||||
lead = lead.as_dict()
|
||||
|
||||
lead["fields_meta"] = get_fields_meta("CRM Lead")
|
||||
lead["_form_script"] = get_form_script("CRM Lead")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1
frontend/components.d.ts
vendored
1
frontend/components.d.ts
vendored
@ -88,6 +88,7 @@ declare module 'vue' {
|
||||
EmailTemplatesListView: typeof import('./src/components/ListViews/EmailTemplatesListView.vue')['default']
|
||||
ERPNextIcon: typeof import('./src/components/Icons/ERPNextIcon.vue')['default']
|
||||
ERPNextSettings: typeof import('./src/components/Settings/ERPNextSettings.vue')['default']
|
||||
ErrorPage: typeof import('./src/components/ErrorPage.vue')['default']
|
||||
ExotelCallUI: typeof import('./src/components/Telephony/ExotelCallUI.vue')['default']
|
||||
ExportIcon: typeof import('./src/components/Icons/ExportIcon.vue')['default']
|
||||
ExternalLinkIcon: typeof import('./src/components/Icons/ExternalLinkIcon.vue')['default']
|
||||
|
||||
24
frontend/src/components/ErrorPage.vue
Normal file
24
frontend/src/components/ErrorPage.vue
Normal file
@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<div
|
||||
class="grid h-full place-items-center px-4 py-20 text-center text-lg text-ink-gray-5"
|
||||
>
|
||||
<div class="flex flex-col justify-between items-center gap-3">
|
||||
<FeatherIcon name="x-octagon" class="h-12 w-12 text-ink-red-3" />
|
||||
<div class="text-2xl font-semibold">{{ errorTitle }}</div>
|
||||
<div v-html="errorMessage" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
errorTitle: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
errorMessage: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
</script>
|
||||
@ -8,7 +8,7 @@
|
||||
</Breadcrumbs>
|
||||
</template>
|
||||
</LayoutHeader>
|
||||
<div ref="parentRef" class="flex h-full">
|
||||
<div v-if="contact.data" ref="parentRef" class="flex h-full">
|
||||
<Resizer
|
||||
v-if="contact.data"
|
||||
:parent="$refs.parentRef"
|
||||
@ -168,10 +168,12 @@
|
||||
</template>
|
||||
</Tabs>
|
||||
</div>
|
||||
<ErrorPage v-else :errorTitle="errorTitle" :errorMessage="errorMessage" />
|
||||
<AddressModal v-model="showAddressModal" v-model:address="_address" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import ErrorPage from '@/components/ErrorPage.vue'
|
||||
import Resizer from '@/components/Resizer.vue'
|
||||
import Icon from '@/components/Icon.vue'
|
||||
import SidePanelLayout from '@/components/SidePanelLayout.vue'
|
||||
@ -202,6 +204,7 @@ import {
|
||||
} from 'frappe-ui'
|
||||
import { ref, computed, h } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { errorMessage as _errorMessage } from '../utils'
|
||||
|
||||
const { brand } = getSettings()
|
||||
const { $dialog, makeCall } = globalStore()
|
||||
@ -225,6 +228,9 @@ const showAddressModal = ref(false)
|
||||
const _contact = ref({})
|
||||
const _address = ref({})
|
||||
|
||||
const errorTitle = ref('')
|
||||
const errorMessage = ref('')
|
||||
|
||||
const contact = createResource({
|
||||
url: 'crm.api.contact.get_contact',
|
||||
cache: ['contact', props.contactId],
|
||||
@ -237,6 +243,18 @@ const contact = createResource({
|
||||
mobile_no: data.mobile_no,
|
||||
}
|
||||
},
|
||||
onSuccess: () => {
|
||||
errorTitle.value = ''
|
||||
errorMessage.value = ''
|
||||
},
|
||||
onError: (err) => {
|
||||
if (err.messages?.[0]) {
|
||||
errorTitle.value = __('Not permitted')
|
||||
errorMessage.value = __(err.messages?.[0])
|
||||
} else {
|
||||
router.push({ name: 'Contacts' })
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const breadcrumbs = computed(() => {
|
||||
|
||||
@ -89,7 +89,7 @@
|
||||
@click="
|
||||
deal.data.email
|
||||
? openEmailBox()
|
||||
: errorMessage(__('No email set'))
|
||||
: _errorMessage(__('No email set'))
|
||||
"
|
||||
/>
|
||||
</Button>
|
||||
@ -103,7 +103,7 @@
|
||||
@click="
|
||||
deal.data.website
|
||||
? openWebsite(deal.data.website)
|
||||
: errorMessage(__('No website set'))
|
||||
: _errorMessage(__('No website set'))
|
||||
"
|
||||
/>
|
||||
</Button>
|
||||
@ -267,6 +267,7 @@
|
||||
</div>
|
||||
</Resizer>
|
||||
</div>
|
||||
<ErrorPage v-else :errorTitle="errorTitle" :errorMessage="errorMessage" />
|
||||
<OrganizationModal
|
||||
v-model="showOrganizationModal"
|
||||
v-model:organization="_organization"
|
||||
@ -297,6 +298,7 @@
|
||||
/>
|
||||
</template>
|
||||
<script setup>
|
||||
import ErrorPage from '@/components/ErrorPage.vue'
|
||||
import Icon from '@/components/Icon.vue'
|
||||
import Resizer from '@/components/Resizer.vue'
|
||||
import LoadingIndicator from '@/components/Icons/LoadingIndicator.vue'
|
||||
@ -330,7 +332,7 @@ import {
|
||||
createToast,
|
||||
setupAssignees,
|
||||
setupCustomizations,
|
||||
errorMessage,
|
||||
errorMessage as _errorMessage,
|
||||
copyToClipboard,
|
||||
} from '@/utils'
|
||||
import { getView } from '@/utils/view'
|
||||
@ -372,11 +374,17 @@ const props = defineProps({
|
||||
},
|
||||
})
|
||||
|
||||
const errorTitle = ref('')
|
||||
const errorMessage = ref('')
|
||||
|
||||
const deal = createResource({
|
||||
url: 'crm.fcrm.doctype.crm_deal.api.get_deal',
|
||||
params: { name: props.dealId },
|
||||
cache: ['deal', props.dealId],
|
||||
onSuccess: (data) => {
|
||||
errorTitle.value = ''
|
||||
errorMessage.value = ''
|
||||
|
||||
if (data.organization) {
|
||||
organization.update({
|
||||
params: { doctype: 'CRM Organization', name: data.organization },
|
||||
@ -401,6 +409,14 @@ const deal = createResource({
|
||||
call,
|
||||
})
|
||||
},
|
||||
onError: (err) => {
|
||||
if (err.messages?.[0]) {
|
||||
errorTitle.value = __('Not permitted')
|
||||
errorMessage.value = __(err.messages?.[0])
|
||||
} else {
|
||||
router.push({ name: 'Deals' })
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const organization = createResource({
|
||||
@ -698,12 +714,12 @@ function triggerCall() {
|
||||
let mobile_no = primaryContact.mobile_no || null
|
||||
|
||||
if (!primaryContact) {
|
||||
errorMessage(__('No primary contact set'))
|
||||
_errorMessage(__('No primary contact set'))
|
||||
return
|
||||
}
|
||||
|
||||
if (!mobile_no) {
|
||||
errorMessage(__('No mobile number set'))
|
||||
_errorMessage(__('No mobile number set'))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -124,7 +124,7 @@
|
||||
() =>
|
||||
lead.data.mobile_no
|
||||
? makeCall(lead.data.mobile_no)
|
||||
: errorMessage(__('No phone number set'))
|
||||
: _errorMessage(__('No phone number set'))
|
||||
"
|
||||
>
|
||||
<PhoneIcon class="h-4 w-4" />
|
||||
@ -139,7 +139,7 @@
|
||||
@click="
|
||||
lead.data.email
|
||||
? openEmailBox()
|
||||
: errorMessage(__('No email set'))
|
||||
: _errorMessage(__('No email set'))
|
||||
"
|
||||
/>
|
||||
</Button>
|
||||
@ -153,7 +153,7 @@
|
||||
@click="
|
||||
lead.data.website
|
||||
? openWebsite(lead.data.website)
|
||||
: errorMessage(__('No website set'))
|
||||
: _errorMessage(__('No website set'))
|
||||
"
|
||||
/>
|
||||
</Button>
|
||||
@ -191,6 +191,7 @@
|
||||
</div>
|
||||
</Resizer>
|
||||
</div>
|
||||
<ErrorPage v-else :errorTitle="errorTitle" :errorMessage="errorMessage" />
|
||||
<Dialog
|
||||
v-model="showConvertToDealModal"
|
||||
:options="{
|
||||
@ -309,6 +310,7 @@
|
||||
/>
|
||||
</template>
|
||||
<script setup>
|
||||
import ErrorPage from '@/components/ErrorPage.vue'
|
||||
import Icon from '@/components/Icon.vue'
|
||||
import Resizer from '@/components/Resizer.vue'
|
||||
import ActivityIcon from '@/components/Icons/ActivityIcon.vue'
|
||||
@ -342,7 +344,7 @@ import {
|
||||
createToast,
|
||||
setupAssignees,
|
||||
setupCustomizations,
|
||||
errorMessage,
|
||||
errorMessage as _errorMessage,
|
||||
copyToClipboard,
|
||||
} from '@/utils'
|
||||
import { getView } from '@/utils/view'
|
||||
@ -392,11 +394,16 @@ const props = defineProps({
|
||||
},
|
||||
})
|
||||
|
||||
const errorTitle = ref('')
|
||||
const errorMessage = ref('')
|
||||
|
||||
const lead = createResource({
|
||||
url: 'crm.fcrm.doctype.crm_lead.api.get_lead',
|
||||
params: { name: props.leadId },
|
||||
cache: ['lead', props.leadId],
|
||||
onSuccess: (data) => {
|
||||
errorTitle.value = ''
|
||||
errorMessage.value = ''
|
||||
setupAssignees(lead)
|
||||
setupCustomizations(lead, {
|
||||
doc: data,
|
||||
@ -410,6 +417,14 @@ const lead = createResource({
|
||||
call,
|
||||
})
|
||||
},
|
||||
onError: (err) => {
|
||||
if (err.messages?.[0]) {
|
||||
errorTitle.value = __('Not permitted')
|
||||
errorMessage.value = __(err.messages?.[0])
|
||||
} else {
|
||||
router.push({ name: 'Leads' })
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
</Breadcrumbs>
|
||||
</template>
|
||||
</LayoutHeader>
|
||||
<div ref="parentRef" class="flex h-full">
|
||||
<div v-if="organization.doc" ref="parentRef" class="flex h-full">
|
||||
<Resizer
|
||||
v-if="organization.doc"
|
||||
:parent="$refs.parentRef"
|
||||
@ -160,6 +160,7 @@
|
||||
</template>
|
||||
</Tabs>
|
||||
</div>
|
||||
<ErrorPage v-else :errorTitle="errorTitle" :errorMessage="errorMessage" />
|
||||
<QuickEntryModal
|
||||
v-if="showQuickEntryModal"
|
||||
v-model="showQuickEntryModal"
|
||||
@ -169,6 +170,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import ErrorPage from '@/components/ErrorPage.vue'
|
||||
import Resizer from '@/components/Resizer.vue'
|
||||
import SidePanelLayout from '@/components/SidePanelLayout.vue'
|
||||
import Icon from '@/components/Icon.vue'
|
||||
@ -221,12 +223,27 @@ const showQuickEntryModal = ref(false)
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const errorTitle = ref('')
|
||||
const errorMessage = ref('')
|
||||
|
||||
const organization = createDocumentResource({
|
||||
doctype: 'CRM Organization',
|
||||
name: props.organizationId,
|
||||
cache: ['organization', props.organizationId],
|
||||
fields: ['*'],
|
||||
auto: true,
|
||||
onSuccess: () => {
|
||||
errorTitle.value = ''
|
||||
errorMessage.value = ''
|
||||
},
|
||||
onError: (err) => {
|
||||
if (err.messages?.[0]) {
|
||||
errorTitle.value = __('Not permitted')
|
||||
errorMessage.value = __(err.messages?.[0])
|
||||
} else {
|
||||
router.push({ name: 'Organizations' })
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
async function updateField(fieldname, value) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user