fix: only show sales user filter to manager

(cherry picked from commit f747e076ab6b1bc58eb4aa14fe01628317c0b2eb)
This commit is contained in:
Shariq Ansari 2025-07-08 12:58:46 +05:30 committed by Mergify
parent 6caff5cd59
commit 39a419889f
8 changed files with 73 additions and 18 deletions

View File

@ -1,8 +1,11 @@
import frappe
from frappe import _
from crm.utils import sales_user_only
@frappe.whitelist()
@sales_user_only
def get_number_card_data(from_date="", to_date="", user="", lead_conds="", deal_conds=""):
"""
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())
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)
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)

View File

@ -23,9 +23,6 @@ def get_users():
if frappe.session.user == user.name:
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.role = ""
@ -42,7 +39,7 @@ def get_users():
if frappe.session.user == user.name:
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 = []

View File

@ -1,10 +1,13 @@
from frappe import frappe
import functools
import frappe
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 phonenumbers import NumberParseException
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"):
@ -97,6 +100,7 @@ def seconds_to_duration(seconds):
else:
return "0s"
# Extracted from frappe core frappe/model/delete_doc.py/check_if_doc_is_linked
def get_linked_docs(doc, method="Delete"):
from frappe.model.rename_doc import get_link_fields
@ -161,6 +165,7 @@ def get_linked_docs(doc, method="Delete"):
)
return docs
# Extracted from frappe core frappe/model/delete_doc.py/check_if_doc_is_dynamically_linked
def get_dynamic_linked_docs(doc, method="Delete"):
docs = []
@ -222,3 +227,42 @@ def get_dynamic_linked_docs(doc, method="Delete"):
}
)
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

View File

@ -163,6 +163,7 @@ declare module 'vue' {
ListRows: typeof import('./src/components/ListViews/ListRows.vue')['default']
LoadingIndicator: typeof import('./src/components/Icons/LoadingIndicator.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']
LucideMoreHorizontal: typeof import('~icons/lucide/more-horizontal')['default']
LucidePlus: typeof import('~icons/lucide/plus')['default']

View File

@ -65,7 +65,7 @@ import {
import { Dialog, Avatar } from 'frappe-ui'
import { ref, markRaw, computed, watch, h } from 'vue'
const { isManager, isAgent, getUser } = usersStore()
const { isManager, isTelephonyAgent, getUser } = usersStore()
const user = computed(() => getUser() || {})
@ -123,7 +123,7 @@ const tabs = computed(() => {
label: __('Telephony'),
icon: PhoneIcon,
component: markRaw(TelephonySettings),
condition: () => isManager() || isAgent(),
condition: () => isManager() || isTelephonyAgent(),
},
{
label: __('WhatsApp'),
@ -138,7 +138,7 @@ const tabs = computed(() => {
condition: () => isManager(),
},
],
condition: () => isManager() || isAgent(),
condition: () => isManager() || isTelephonyAgent(),
},
]

View File

@ -93,7 +93,7 @@ import { toast } from 'frappe-ui'
import { getRandom } from '@/utils'
import { ref, computed, watch } from 'vue'
const { isManager, isAgent } = usersStore()
const { isManager, isTelephonyAgent } = usersStore()
const twilioFields = createResource({
url: 'crm.api.doc.get_fields',
@ -283,7 +283,7 @@ async function updateMedium() {
const error = ref('')
function validateIfDefaultMediumIsEnabled() {
if (isAgent() && !isManager()) return true
if (isTelephonyAgent() && !isManager()) return true
if (defaultCallingMedium.value === 'Twilio' && !twilio.doc.enabled) {
error.value = __('Twilio is not enabled')

View File

@ -52,6 +52,7 @@
</template>
</DateRangePicker>
<Link
v-if="isAdmin() || isManager()"
class="form-control w-48"
variant="outline"
:value="filters.user && getUser(filters.user).full_name"
@ -145,7 +146,7 @@ import {
} from 'frappe-ui'
import { ref, reactive, computed } from 'vue'
const { users, getUser } = usersStore()
const { users, getUser, isManager, isAdmin } = usersStore()
const showDatePicker = ref(false)
const datePickerRef = ref(null)

View File

@ -50,15 +50,19 @@ export const usersStore = defineStore('crm-users', () => {
}
function isAdmin(email) {
return getUser(email).role === 'System Manager' || getUser(email).is_admin
return getUser(email).role === 'System Manager'
}
function isManager(email) {
return getUser(email).is_manager
return getUser(email).role === 'Sales Manager'
}
function isAgent(email) {
return getUser(email).is_agent
function isSalesUser(email) {
return getUser(email).role === 'Sales User'
}
function isTelephonyAgent(email) {
return getUser(email).is_telphony_agent
}
function getUserRole(email) {
@ -74,7 +78,8 @@ export const usersStore = defineStore('crm-users', () => {
getUser,
isAdmin,
isManager,
isAgent,
isSalesUser,
isTelephonyAgent,
getUserRole,
}
})