commission overrides in org Settings page

This commit is contained in:
Satyam Rastogi
2026-05-13 12:51:36 +05:30
parent 455462ded4
commit 8f4a0e81fb
6 changed files with 177 additions and 24 deletions
+21 -12
View File
@@ -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}
+3
View File
@@ -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}