Fix: Offboarding-Checkliste nach Abteilung filtern, Rollen-Filterung pro Team
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -38,9 +38,14 @@ class OffboardingProtocol {
|
||||
e.first_name as employee_first_name,
|
||||
e.last_name as employee_last_name,
|
||||
e.email as employee_email,
|
||||
e.department as employee_department,
|
||||
r.name as employee_role_name,
|
||||
cu.username as created_by_username,
|
||||
uu.username as updated_by_username
|
||||
uu.username as updated_by_username,
|
||||
(SELECT d.id FROM onboarding_departments d
|
||||
WHERE LOWER(d.name) LIKE LOWER('%' || COALESCE(e.department,'') || '%')
|
||||
AND COALESCE(e.department,'') != ''
|
||||
ORDER BY d.id LIMIT 1) as employee_department_id
|
||||
FROM offboarding_protocols op
|
||||
INNER JOIN users e ON op.employee_user_id = e.id
|
||||
INNER JOIN roles r ON e.role_id = r.id
|
||||
|
||||
@@ -12,6 +12,8 @@ const TEAM_ICONS = { it: '💻', hr: '🧑💼', buchhaltung: '💶' };
|
||||
const TEAM_LABELS = { it: 'IT', hr: 'HR / Personal', buchhaltung: 'Buchhaltung' };
|
||||
const TAG_COLORS = { critical: '#ef4444', important: '#f59e0b', normal: '#64748b' };
|
||||
|
||||
const ROLE_TO_TEAM = { hr_personal: 'hr', buchhaltung: 'buchhaltung', produktion: 'it' };
|
||||
|
||||
const STATUS_LABEL = { pending: 'Ausstehend', in_progress: 'In Bearbeitung', completed: 'Abgeschlossen' };
|
||||
const STATUS_COLOR = { pending: '#f59e0b', in_progress: '#3b82f6', completed: '#34d399' };
|
||||
|
||||
@@ -29,18 +31,22 @@ function StatusBadge({ status }) {
|
||||
);
|
||||
}
|
||||
|
||||
function ProcessChecklist({ processes, checkedItems, onChange, disabled }) {
|
||||
function ProcessChecklist({ processes, checkedItems, onChange, disabled, userTeam = null }) {
|
||||
if (!processes?.length) return (
|
||||
<p style={{ color: 'var(--text-muted)', fontSize: 13 }}>Keine Prozesse konfiguriert.</p>
|
||||
);
|
||||
|
||||
const teams = ['it', 'hr', 'buchhaltung'];
|
||||
// Wenn userTeam gesetzt: nur dieses Team anzeigen
|
||||
const visibleTeams = userTeam ? [userTeam] : ['it', 'hr', 'buchhaltung'];
|
||||
const visibleProcesses = userTeam ? processes.filter(p => p.responsible_team === userTeam) : processes;
|
||||
|
||||
const teams = visibleTeams;
|
||||
const teamMap = {};
|
||||
teams.forEach(t => { teamMap[t] = []; });
|
||||
processes.forEach(p => { if (teamMap[p.responsible_team]) teamMap[p.responsible_team].push(p); });
|
||||
visibleProcesses.forEach(p => { if (teamMap[p.responsible_team]) teamMap[p.responsible_team].push(p); });
|
||||
|
||||
const total = processes.length;
|
||||
const checked = processes.filter(p => !!checkedItems[`proc_${p.id}`]).length;
|
||||
const total = visibleProcesses.length;
|
||||
const checked = visibleProcesses.filter(p => !!checkedItems[`proc_${p.id}`]).length;
|
||||
const pct = total > 0 ? Math.round(checked / total * 100) : 0;
|
||||
|
||||
return (
|
||||
@@ -134,17 +140,17 @@ export default function OffboardingDetailPage() {
|
||||
const [assetReturns, setAssetReturns] = useState([]);
|
||||
|
||||
const canManage = isAdmin() || isSuperAdmin();
|
||||
const canAct = canViewLifecycle(); // hr + support + admin dürfen handeln
|
||||
const canAct = canViewLifecycle();
|
||||
const userTeam = (canManage) ? null : (ROLE_TO_TEAM[user?.role_name] || null);
|
||||
|
||||
useEffect(() => { load(); }, [id]);
|
||||
|
||||
const load = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const [p, procs] = await Promise.all([
|
||||
offboardingService.getById(id),
|
||||
onboardingProcessService.getChecklistProcesses('offboarding').catch(() => []),
|
||||
]);
|
||||
const p = await offboardingService.getById(id);
|
||||
const deptId = p.employee_department_id || undefined;
|
||||
const procs = await onboardingProcessService.getChecklistProcesses('offboarding', deptId).catch(() => []);
|
||||
setProtocol(p);
|
||||
setChecklist(p.checklist_data ? JSON.parse(p.checklist_data) : {});
|
||||
setNotes(p.notes || '');
|
||||
@@ -228,8 +234,9 @@ export default function OffboardingDetailPage() {
|
||||
if (loading) return <div className="main-content"><LoadingSpinner /></div>;
|
||||
if (!protocol) return null;
|
||||
|
||||
const total = processes.length;
|
||||
const checked = processes.filter(p => !!checklist[`proc_${p.id}`]).length;
|
||||
const visibleProcs = userTeam ? processes.filter(p => p.responsible_team === userTeam) : processes;
|
||||
const total = visibleProcs.length;
|
||||
const checked = visibleProcs.filter(p => !!checklist[`proc_${p.id}`]).length;
|
||||
const pct = total > 0 ? Math.round(checked / total * 100) : 0;
|
||||
const statusColor = STATUS_COLOR[protocol.status] || '#6b7280';
|
||||
const initials = (protocol.employee_name || protocol.employee_email || '??').slice(0, 2).toUpperCase();
|
||||
@@ -411,6 +418,7 @@ export default function OffboardingDetailPage() {
|
||||
checkedItems={checklist}
|
||||
onChange={setChecklist}
|
||||
disabled={protocol.status === 'completed'}
|
||||
userTeam={userTeam}
|
||||
/>
|
||||
{protocol.status !== 'completed' && canAct && (
|
||||
<div style={{ marginTop: 16, display: 'flex', justifyContent: 'flex-end', gap: 10 }}>
|
||||
|
||||
Reference in New Issue
Block a user