feat: Sondervertretungs-Faktoren (special_assignments)

- Neues Model SpecialAssignment mit AssignmentMode (fza|payroll|both)
- CRUD-Endpunkte unter /users/{id}/special-assignments
- Payroll-Report: GET /reports/special-assignments/payroll?year=&month=
- Migration 0029: special_assignments Tabelle + btree_gist Overlap-Constraint
- _recalculate_overtime_balance berücksichtigt FZA-Faktoren
- Frontend: Sondervertretungs-Zeiträume im UsersPage Edit-Modal
- Frontend: ReportsPage neuer Tab 'Sondervertretungen' mit Payroll-Tabelle + CSV-Export

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 00:55:47 +02:00
parent 1170e59e49
commit d60349df67
12 changed files with 837 additions and 39 deletions
+51
View File
@@ -0,0 +1,51 @@
export type AssignmentMode = 'fza' | 'payroll' | 'both';
export interface SpecialAssignmentOut {
id: string;
user_id: string;
company_id: string;
date_from: string;
date_to: string;
factor: number;
mode: AssignmentMode;
description: string | null;
label: string | null;
}
export interface SpecialAssignmentCreate {
date_from: string;
date_to: string;
factor: number;
mode: AssignmentMode;
description?: string;
label?: string;
}
// ── Payroll Report ────────────────────────────────────────────────────────────
export interface PayrollAssignmentEntry {
assignment_id: string;
label: string | null;
date_from: string;
date_to: string;
factor: number;
normal_hours: number;
factor_hours: number;
extra_hours: number;
}
export interface PayrollAssignmentRow {
user_id: string;
user_name: string;
personnel_number: string | null;
assignments: PayrollAssignmentEntry[];
total_normal_hours: number;
total_factor_hours: number;
total_extra_hours: number;
}
export interface PayrollAssignmentReport {
year: number;
month: number;
rows: PayrollAssignmentRow[];
}