From 50bbfc6b225d484438ffef557cf711c145659816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Gr=C3=BCssing?= Date: Thu, 11 Jun 2026 12:22:28 +0200 Subject: [PATCH] Fix: Offboarding-Checkliste nach Abteilung filtern, Rollen-Filterung pro Team Co-Authored-By: Claude Sonnet 4.6 --- backend/src/models/OffboardingProtocol.js | 7 ++++- frontend/src/pages/OffboardingDetailPage.jsx | 32 ++++++++++++-------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/backend/src/models/OffboardingProtocol.js b/backend/src/models/OffboardingProtocol.js index 9078eeb..3886727 100644 --- a/backend/src/models/OffboardingProtocol.js +++ b/backend/src/models/OffboardingProtocol.js @@ -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 diff --git a/frontend/src/pages/OffboardingDetailPage.jsx b/frontend/src/pages/OffboardingDetailPage.jsx index 6080a30..a6d1e2f 100644 --- a/frontend/src/pages/OffboardingDetailPage.jsx +++ b/frontend/src/pages/OffboardingDetailPage.jsx @@ -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 (

Keine Prozesse konfiguriert.

); - 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
; 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 && (