fix: only show sales user filter to manager
This commit is contained in:
parent
4b12918ba5
commit
f747e076ab
@ -1,8 +1,11 @@
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
|
|
||||||
|
from crm.utils import sales_user_only
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
@sales_user_only
|
||||||
def get_number_card_data(from_date="", to_date="", user="", lead_conds="", deal_conds=""):
|
def get_number_card_data(from_date="", to_date="", user="", lead_conds="", deal_conds=""):
|
||||||
"""
|
"""
|
||||||
Get number card data for the dashboard.
|
Get number card data for the dashboard.
|
||||||
@ -11,6 +14,10 @@ def get_number_card_data(from_date="", to_date="", user="", lead_conds="", deal_
|
|||||||
from_date = frappe.utils.get_first_day(from_date or frappe.utils.nowdate())
|
from_date = frappe.utils.get_first_day(from_date or frappe.utils.nowdate())
|
||||||
to_date = frappe.utils.get_last_day(to_date or frappe.utils.nowdate())
|
to_date = frappe.utils.get_last_day(to_date or frappe.utils.nowdate())
|
||||||
|
|
||||||
|
is_sales_user = "Sales User" in frappe.get_roles(frappe.session.user)
|
||||||
|
if is_sales_user and not user:
|
||||||
|
user = frappe.session.user
|
||||||
|
|
||||||
lead_chart_data = get_lead_count(from_date, to_date, user, lead_conds)
|
lead_chart_data = get_lead_count(from_date, to_date, user, lead_conds)
|
||||||
deal_chart_data = get_deal_count(from_date, to_date, user, deal_conds)
|
deal_chart_data = get_deal_count(from_date, to_date, user, deal_conds)
|
||||||
get_won_deal_count_data = get_won_deal_count(from_date, to_date, user, deal_conds)
|
get_won_deal_count_data = get_won_deal_count(from_date, to_date, user, deal_conds)
|
||||||
|
|||||||
@ -23,9 +23,6 @@ def get_users():
|
|||||||
if frappe.session.user == user.name:
|
if frappe.session.user == user.name:
|
||||||
user.session_user = True
|
user.session_user = True
|
||||||
|
|
||||||
user.is_manager = "Sales Manager" in frappe.get_roles(user.name)
|
|
||||||
user.is_admin = user.name == "Administrator"
|
|
||||||
|
|
||||||
user.roles = frappe.get_roles(user.name)
|
user.roles = frappe.get_roles(user.name)
|
||||||
|
|
||||||
user.role = ""
|
user.role = ""
|
||||||
@ -42,7 +39,7 @@ def get_users():
|
|||||||
if frappe.session.user == user.name:
|
if frappe.session.user == user.name:
|
||||||
user.session_user = True
|
user.session_user = True
|
||||||
|
|
||||||
user.is_agent = frappe.db.exists("CRM Telephony Agent", {"user": user.name})
|
user.is_telephony_agent = frappe.db.exists("CRM Telephony Agent", {"user": user.name})
|
||||||
|
|
||||||
crm_users = []
|
crm_users = []
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
from frappe import frappe
|
import functools
|
||||||
|
|
||||||
|
import frappe
|
||||||
import phonenumbers
|
import phonenumbers
|
||||||
|
from frappe import _
|
||||||
|
from frappe.model.docstatus import DocStatus
|
||||||
|
from frappe.model.dynamic_links import get_dynamic_link_map
|
||||||
from frappe.utils import floor
|
from frappe.utils import floor
|
||||||
from phonenumbers import NumberParseException
|
from phonenumbers import NumberParseException
|
||||||
from phonenumbers import PhoneNumberFormat as PNF
|
from phonenumbers import PhoneNumberFormat as PNF
|
||||||
from frappe.model.docstatus import DocStatus
|
|
||||||
from frappe.model.dynamic_links import get_dynamic_link_map
|
|
||||||
|
|
||||||
|
|
||||||
def parse_phone_number(phone_number, default_country="IN"):
|
def parse_phone_number(phone_number, default_country="IN"):
|
||||||
@ -97,6 +100,7 @@ def seconds_to_duration(seconds):
|
|||||||
else:
|
else:
|
||||||
return "0s"
|
return "0s"
|
||||||
|
|
||||||
|
|
||||||
# Extracted from frappe core frappe/model/delete_doc.py/check_if_doc_is_linked
|
# Extracted from frappe core frappe/model/delete_doc.py/check_if_doc_is_linked
|
||||||
def get_linked_docs(doc, method="Delete"):
|
def get_linked_docs(doc, method="Delete"):
|
||||||
from frappe.model.rename_doc import get_link_fields
|
from frappe.model.rename_doc import get_link_fields
|
||||||
@ -161,6 +165,7 @@ def get_linked_docs(doc, method="Delete"):
|
|||||||
)
|
)
|
||||||
return docs
|
return docs
|
||||||
|
|
||||||
|
|
||||||
# Extracted from frappe core frappe/model/delete_doc.py/check_if_doc_is_dynamically_linked
|
# Extracted from frappe core frappe/model/delete_doc.py/check_if_doc_is_dynamically_linked
|
||||||
def get_dynamic_linked_docs(doc, method="Delete"):
|
def get_dynamic_linked_docs(doc, method="Delete"):
|
||||||
docs = []
|
docs = []
|
||||||
@ -222,3 +227,42 @@ def get_dynamic_linked_docs(doc, method="Delete"):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
return docs
|
return docs
|
||||||
|
|
||||||
|
|
||||||
|
def is_admin(user: str | None = None) -> bool:
|
||||||
|
"""
|
||||||
|
Check whether `user` is an admin
|
||||||
|
|
||||||
|
:param user: User to check against, defaults to current user
|
||||||
|
:return: Whether `user` is an admin
|
||||||
|
"""
|
||||||
|
user = user or frappe.session.user
|
||||||
|
return user == "Administrator"
|
||||||
|
|
||||||
|
|
||||||
|
def is_sales_user(user: str | None = None) -> bool:
|
||||||
|
"""
|
||||||
|
Check whether `user` is an agent
|
||||||
|
|
||||||
|
:param user: User to check against, defaults to current user
|
||||||
|
:return: Whether `user` is an agent
|
||||||
|
"""
|
||||||
|
user = user or frappe.session.user
|
||||||
|
return is_admin() or "Sales Manager" in frappe.get_roles(user) or "Sales User" in frappe.get_roles(user)
|
||||||
|
|
||||||
|
|
||||||
|
def sales_user_only(fn):
|
||||||
|
"""Decorator to validate if user is an agent."""
|
||||||
|
|
||||||
|
@functools.wraps(fn)
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
if not is_sales_user():
|
||||||
|
frappe.throw(
|
||||||
|
msg=_("You are not permitted to access this resource."),
|
||||||
|
title=_("Not Allowed"),
|
||||||
|
exc=frappe.PermissionError,
|
||||||
|
)
|
||||||
|
|
||||||
|
return fn(*args, **kwargs)
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|||||||
1
frontend/components.d.ts
vendored
1
frontend/components.d.ts
vendored
@ -163,6 +163,7 @@ declare module 'vue' {
|
|||||||
ListRows: typeof import('./src/components/ListViews/ListRows.vue')['default']
|
ListRows: typeof import('./src/components/ListViews/ListRows.vue')['default']
|
||||||
LoadingIndicator: typeof import('./src/components/Icons/LoadingIndicator.vue')['default']
|
LoadingIndicator: typeof import('./src/components/Icons/LoadingIndicator.vue')['default']
|
||||||
LostReasonModal: typeof import('./src/components/Modals/LostReasonModal.vue')['default']
|
LostReasonModal: typeof import('./src/components/Modals/LostReasonModal.vue')['default']
|
||||||
|
LucideCalendar: typeof import('~icons/lucide/calendar')['default']
|
||||||
LucideInfo: typeof import('~icons/lucide/info')['default']
|
LucideInfo: typeof import('~icons/lucide/info')['default']
|
||||||
LucideMoreHorizontal: typeof import('~icons/lucide/more-horizontal')['default']
|
LucideMoreHorizontal: typeof import('~icons/lucide/more-horizontal')['default']
|
||||||
LucidePlus: typeof import('~icons/lucide/plus')['default']
|
LucidePlus: typeof import('~icons/lucide/plus')['default']
|
||||||
|
|||||||
@ -65,7 +65,7 @@ import {
|
|||||||
import { Dialog, Avatar } from 'frappe-ui'
|
import { Dialog, Avatar } from 'frappe-ui'
|
||||||
import { ref, markRaw, computed, watch, h } from 'vue'
|
import { ref, markRaw, computed, watch, h } from 'vue'
|
||||||
|
|
||||||
const { isManager, isAgent, getUser } = usersStore()
|
const { isManager, isTelephonyAgent, getUser } = usersStore()
|
||||||
|
|
||||||
const user = computed(() => getUser() || {})
|
const user = computed(() => getUser() || {})
|
||||||
|
|
||||||
@ -123,7 +123,7 @@ const tabs = computed(() => {
|
|||||||
label: __('Telephony'),
|
label: __('Telephony'),
|
||||||
icon: PhoneIcon,
|
icon: PhoneIcon,
|
||||||
component: markRaw(TelephonySettings),
|
component: markRaw(TelephonySettings),
|
||||||
condition: () => isManager() || isAgent(),
|
condition: () => isManager() || isTelephonyAgent(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: __('WhatsApp'),
|
label: __('WhatsApp'),
|
||||||
@ -138,7 +138,7 @@ const tabs = computed(() => {
|
|||||||
condition: () => isManager(),
|
condition: () => isManager(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
condition: () => isManager() || isAgent(),
|
condition: () => isManager() || isTelephonyAgent(),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -93,7 +93,7 @@ import { toast } from 'frappe-ui'
|
|||||||
import { getRandom } from '@/utils'
|
import { getRandom } from '@/utils'
|
||||||
import { ref, computed, watch } from 'vue'
|
import { ref, computed, watch } from 'vue'
|
||||||
|
|
||||||
const { isManager, isAgent } = usersStore()
|
const { isManager, isTelephonyAgent } = usersStore()
|
||||||
|
|
||||||
const twilioFields = createResource({
|
const twilioFields = createResource({
|
||||||
url: 'crm.api.doc.get_fields',
|
url: 'crm.api.doc.get_fields',
|
||||||
@ -283,7 +283,7 @@ async function updateMedium() {
|
|||||||
const error = ref('')
|
const error = ref('')
|
||||||
|
|
||||||
function validateIfDefaultMediumIsEnabled() {
|
function validateIfDefaultMediumIsEnabled() {
|
||||||
if (isAgent() && !isManager()) return true
|
if (isTelephonyAgent() && !isManager()) return true
|
||||||
|
|
||||||
if (defaultCallingMedium.value === 'Twilio' && !twilio.doc.enabled) {
|
if (defaultCallingMedium.value === 'Twilio' && !twilio.doc.enabled) {
|
||||||
error.value = __('Twilio is not enabled')
|
error.value = __('Twilio is not enabled')
|
||||||
|
|||||||
@ -52,6 +52,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</DateRangePicker>
|
</DateRangePicker>
|
||||||
<Link
|
<Link
|
||||||
|
v-if="isAdmin() || isManager()"
|
||||||
class="form-control w-48"
|
class="form-control w-48"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
:value="filters.user && getUser(filters.user).full_name"
|
:value="filters.user && getUser(filters.user).full_name"
|
||||||
@ -145,7 +146,7 @@ import {
|
|||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { ref, reactive, computed } from 'vue'
|
import { ref, reactive, computed } from 'vue'
|
||||||
|
|
||||||
const { users, getUser } = usersStore()
|
const { users, getUser, isManager, isAdmin } = usersStore()
|
||||||
|
|
||||||
const showDatePicker = ref(false)
|
const showDatePicker = ref(false)
|
||||||
const datePickerRef = ref(null)
|
const datePickerRef = ref(null)
|
||||||
|
|||||||
@ -50,15 +50,19 @@ export const usersStore = defineStore('crm-users', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isAdmin(email) {
|
function isAdmin(email) {
|
||||||
return getUser(email).role === 'System Manager' || getUser(email).is_admin
|
return getUser(email).role === 'System Manager'
|
||||||
}
|
}
|
||||||
|
|
||||||
function isManager(email) {
|
function isManager(email) {
|
||||||
return getUser(email).is_manager
|
return getUser(email).role === 'Sales Manager'
|
||||||
}
|
}
|
||||||
|
|
||||||
function isAgent(email) {
|
function isSalesUser(email) {
|
||||||
return getUser(email).is_agent
|
return getUser(email).role === 'Sales User'
|
||||||
|
}
|
||||||
|
|
||||||
|
function isTelephonyAgent(email) {
|
||||||
|
return getUser(email).is_telphony_agent
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUserRole(email) {
|
function getUserRole(email) {
|
||||||
@ -74,7 +78,8 @@ export const usersStore = defineStore('crm-users', () => {
|
|||||||
getUser,
|
getUser,
|
||||||
isAdmin,
|
isAdmin,
|
||||||
isManager,
|
isManager,
|
||||||
isAgent,
|
isSalesUser,
|
||||||
|
isTelephonyAgent,
|
||||||
getUserRole,
|
getUserRole,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user