commission overrides in org Settings page
This commit is contained in:
@@ -19,6 +19,7 @@ import InvoiceDetailModal from '../../components/owner/InvoiceDetailModal';
|
||||
import CreateItemModal from '../../components/owner/CreateItemModal';
|
||||
import CommissionSettingsModal from '../../components/owner/CommissionSettingsModal';
|
||||
import { usePermissions } from '../../hooks/usePermissions';
|
||||
import { resolveCommission, findAssignedUserRoleKey } from '../../utils/commissionResolver';
|
||||
|
||||
// --- NEOMORPHIC STYLING CONSTANTS ---
|
||||
const NEO_PANEL_CLASS = "dark:bg-zinc-900/60 dark:backdrop-blur-3xl border border-zinc-200 dark:border-white/5 dark:shadow-[8px_8px_16px_rgba(0,0,0,0.6),-8px_-8px_16px_rgba(255,255,255,0.02)] rounded-3xl relative overflow-hidden transition-all duration-300";
|
||||
@@ -138,6 +139,7 @@ const OwnerProjectDetail = () => {
|
||||
const {
|
||||
projects, vendors, personnel,
|
||||
orgCommissionDefaults, userCommissionOverrides,
|
||||
roleCommissionOverrides, orgMembers, orgRoles,
|
||||
updateOrgCommissionDefaults, setUserCommissionOverride,
|
||||
removeUserCommissionOverride, updateProject,
|
||||
} = useMockStore();
|
||||
@@ -243,7 +245,7 @@ const OwnerProjectDetail = () => {
|
||||
projects.find(p => p.id === projectId && p.ownerId === user?.id)
|
||||
, [projects, projectId, user]);
|
||||
|
||||
// ── Commission hierarchy resolution: Job → User → Org ──────────────────
|
||||
// ── Commission hierarchy: Job → Individual → Role → Org ──────────────
|
||||
const jobCommissionOverride = useMemo(() => {
|
||||
if (commissionConfig) return commissionConfig;
|
||||
if (!project) return null;
|
||||
@@ -251,17 +253,20 @@ const OwnerProjectDetail = () => {
|
||||
return null;
|
||||
}, [commissionConfig, project]);
|
||||
|
||||
const resolvedCommission = useMemo(() => {
|
||||
// Priority: Job Override → User Override → Org Default
|
||||
if (jobCommissionOverride) {
|
||||
return { source: 'job', type: jobCommissionOverride.type, rate: Number(jobCommissionOverride.rate) || 0 };
|
||||
}
|
||||
const userOverride = userCommissionOverrides.find(o => o.enabled && o.userId === (project?.salesRepId || project?.contractorId));
|
||||
if (userOverride) {
|
||||
return { source: 'user', type: userOverride.type, rate: Number(userOverride.rate) || 0 };
|
||||
}
|
||||
return { source: 'org', type: orgCommissionDefaults.type, rate: Number(orgCommissionDefaults.rate) || 0 };
|
||||
}, [jobCommissionOverride, userCommissionOverrides, orgCommissionDefaults, project]);
|
||||
const assignedUserId = project?.salesRepId || project?.contractorId;
|
||||
const assignedUserRoleKey = useMemo(
|
||||
() => findAssignedUserRoleKey(assignedUserId, orgMembers),
|
||||
[assignedUserId, orgMembers]
|
||||
);
|
||||
|
||||
const resolvedCommission = useMemo(() => resolveCommission({
|
||||
jobOverride: jobCommissionOverride,
|
||||
userId: assignedUserId,
|
||||
userCommissionOverrides,
|
||||
orgMembers,
|
||||
roleCommissionOverrides,
|
||||
orgCommissionDefaults,
|
||||
}), [jobCommissionOverride, assignedUserId, userCommissionOverrides, orgMembers, roleCommissionOverrides, orgCommissionDefaults]);
|
||||
|
||||
const activeCommissionConfig = resolvedCommission;
|
||||
|
||||
@@ -776,6 +781,7 @@ const OwnerProjectDetail = () => {
|
||||
const src = resolvedCommission.source;
|
||||
const badgeCfg = {
|
||||
org: { icon: Building2, label: 'Org Default', color: 'text-sky-500 dark:text-[#00f0ff]', bg: 'bg-sky-50 dark:bg-[#00f0ff]/10', border: 'border-sky-200 dark:border-[#00f0ff]/20' },
|
||||
role: { icon: Shield, label: 'Role Override', color: 'text-emerald-500 dark:text-emerald-400', bg: 'bg-emerald-50 dark:bg-emerald-500/10', border: 'border-emerald-200 dark:border-emerald-500/20' },
|
||||
user: { icon: UserIcon, label: 'User Override', color: 'text-purple-500 dark:text-purple-400', bg: 'bg-purple-50 dark:bg-purple-500/10', border: 'border-purple-200 dark:border-purple-500/20' },
|
||||
job: { icon: Briefcase, label: 'Job Override', color: 'text-amber-600 dark:text-[#fda913]', bg: 'bg-amber-50 dark:bg-[#fda913]/10', border: 'border-amber-200 dark:border-[#fda913]/20' },
|
||||
};
|
||||
@@ -1845,6 +1851,9 @@ const OwnerProjectDetail = () => {
|
||||
onClose={() => setCommissionSettingsOpen(false)}
|
||||
orgDefaults={orgCommissionDefaults}
|
||||
userOverrides={userCommissionOverrides}
|
||||
roleOverrides={roleCommissionOverrides}
|
||||
orgRoles={orgRoles}
|
||||
assignedUserRoleKey={assignedUserRoleKey}
|
||||
jobOverride={project?.commissionOverride || (commissionConfig ? { type: commissionConfig.type, rate: commissionConfig.rate } : null)}
|
||||
activeSource={resolvedCommission.source}
|
||||
personnel={personnel}
|
||||
|
||||
@@ -21,6 +21,7 @@ const OwnerSnapshot = () => {
|
||||
const {
|
||||
owners, projects, users, personnel,
|
||||
orgCommissionDefaults, userCommissionOverrides,
|
||||
roleCommissionOverrides, orgMembers,
|
||||
addJobTeamMember, removeJobTeamMember, updateJobTeamMember,
|
||||
} = useMockStore();
|
||||
|
||||
@@ -372,6 +373,8 @@ const OwnerSnapshot = () => {
|
||||
userRole={user?.role}
|
||||
orgCommissionDefaults={orgCommissionDefaults}
|
||||
userCommissionOverrides={userCommissionOverrides}
|
||||
roleCommissionOverrides={roleCommissionOverrides}
|
||||
orgMembers={orgMembers}
|
||||
totalReceived={teamFinancials.totalReceived}
|
||||
grossProfit={teamFinancials.grossProfit}
|
||||
onAddMember={addJobTeamMember}
|
||||
|
||||
Reference in New Issue
Block a user