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:
2026-06-11 12:22:28 +02:00
parent 58d7df64e9
commit 50bbfc6b22
2 changed files with 26 additions and 13 deletions

View File

@@ -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

View File

@@ -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 }}>