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
+18 -6
View File
@@ -27,6 +27,7 @@ const COMMISSION_TYPES = {
const COMMISSION_SOURCE_CFG = {
org: { label: 'Org Default', color: 'text-cyan-400', bg: 'bg-cyan-500/10 border-cyan-500/30', dot: 'bg-cyan-400' },
role: { label: 'Role', color: 'text-emerald-400', bg: 'bg-emerald-500/10 border-emerald-500/30', dot: 'bg-emerald-400' },
user: { label: 'User', color: 'text-violet-400', bg: 'bg-violet-500/10 border-violet-500/30', dot: 'bg-violet-400' },
job: { label: 'Job', color: 'text-amber-400', bg: 'bg-amber-500/10 border-amber-500/30', dot: 'bg-amber-400' },
};
@@ -42,7 +43,7 @@ const ROLE_COLORS = {
'Supplier': 'text-yellow-400 bg-yellow-500/10 border-yellow-500/20',
};
function resolveCommissionForMember(member, userCommissionOverrides, orgCommissionDefaults) {
function resolveCommissionForMember(member, userCommissionOverrides, roleCommissionOverrides, orgMembers, orgCommissionDefaults) {
if (member.jobCommission) {
return { type: member.jobCommission.type, rate: Number(member.jobCommission.rate) || 0, source: 'job' };
}
@@ -50,6 +51,13 @@ function resolveCommissionForMember(member, userCommissionOverrides, orgCommissi
if (userOvr) {
return { type: userOvr.type, rate: Number(userOvr.rate) || 0, source: 'user' };
}
const orgMember = (orgMembers || []).find(m => m.userId === member.userId);
if (orgMember) {
const roleOvr = (roleCommissionOverrides || []).find(o => o.enabled && o.roleKey === orgMember.roleKey);
if (roleOvr) {
return { type: roleOvr.type, rate: Number(roleOvr.rate) || 0, source: 'role' };
}
}
return { type: orgCommissionDefaults.type, rate: Number(orgCommissionDefaults.rate) || 0, source: 'org' };
}
@@ -75,6 +83,8 @@ const TeamManagementPanel = ({
userRole,
orgCommissionDefaults,
userCommissionOverrides,
roleCommissionOverrides = [],
orgMembers = [],
totalReceived = 0,
grossProfit = 0,
onAddMember,
@@ -114,11 +124,11 @@ const TeamManagementPanel = ({
const memberCommissions = useMemo(() => {
return visibleMembers.map(m => {
const resolved = resolveCommissionForMember(m, userCommissionOverrides, orgCommissionDefaults);
const resolved = resolveCommissionForMember(m, userCommissionOverrides, roleCommissionOverrides, orgMembers, orgCommissionDefaults);
const value = calcCommissionValue(resolved, totalReceived, grossProfit);
return { ...m, resolved, value };
});
}, [visibleMembers, userCommissionOverrides, orgCommissionDefaults, totalReceived, grossProfit]);
}, [visibleMembers, userCommissionOverrides, roleCommissionOverrides, orgMembers, orgCommissionDefaults, totalReceived, grossProfit]);
const activeMembers = visibleMembers.filter(m => m.status === 'active');
const pendingMembers = visibleMembers.filter(m => m.status === 'pending');
@@ -404,6 +414,8 @@ const TeamManagementPanel = ({
member={editingCommission}
orgDefaults={orgCommissionDefaults}
userOverrides={userCommissionOverrides}
roleOverrides={roleCommissionOverrides}
orgMembers={orgMembers}
onSave={(memberId, jobCommission) => {
onUpdateMember(project.id, memberId, { jobCommission });
setEditingCommission(null);
@@ -638,8 +650,8 @@ const RemoveConfirmModal = ({ member, projectName, onConfirm, onClose }) => (
// ─── Edit Commission Modal ─────────────────────────────────────────────────────
const EditCommissionModal = ({ member, orgDefaults, userOverrides, onSave, onClear, onClose }) => {
const resolved = resolveCommissionForMember(member, userOverrides, orgDefaults);
const EditCommissionModal = ({ member, orgDefaults, userOverrides, roleOverrides, orgMembers, onSave, onClear, onClose }) => {
const resolved = resolveCommissionForMember(member, userOverrides, roleOverrides, orgMembers, orgDefaults);
const hasJobOverride = !!member.jobCommission;
const [type, setType] = useState(hasJobOverride ? member.jobCommission.type : resolved.type);
@@ -717,7 +729,7 @@ const EditCommissionModal = ({ member, orgDefaults, userOverrides, onSave, onCle
onClick={() => onClear(member.id)}
className="w-full py-2 text-xs font-semibold text-zinc-500 hover:text-red-500 transition-colors"
>
Clear job override (revert to {COMMISSION_SOURCE_CFG[resolveCommissionForMember({ ...member, jobCommission: null }, userOverrides, orgDefaults).source]?.label || 'default'})
Clear job override (revert to {COMMISSION_SOURCE_CFG[resolveCommissionForMember({ ...member, jobCommission: null }, userOverrides, roleOverrides, orgMembers, orgDefaults).source]?.label || 'default'})
</button>
)}
</div>