"use server"; import { revalidatePath } from "next/cache"; import { sanitizeIlikeTerm } from "@/lib/supabase/query"; import { createClient } from "@/lib/supabase/server"; import type { CollectiveAgreement, Database, NoteCategory, RelationshipType, Weekday, WorkerType } from "@/lib/supabase/types"; type ActionResult = { success: boolean; error?: string }; type MutationFn = keyof Database["public"]["Functions"]; async function callRpc(fn: MutationFn, payload: Record, revalidate: string[]): Promise { const supabase = await createClient(); const { error } = await supabase.rpc(fn, { payload }); if (error) return { success: false, error: error.message }; for (const path of revalidate) revalidatePath(path); return { success: true }; } export async function hireEmployee(payload: { first_name: string; last_name: string; title_prefix?: string[]; title_suffix?: string[]; gender: "m" | "w"; birth_date: string; sv_nummer?: string; phone?: string; position_id?: string; team_id?: string; job_title?: string; location_id: string; entry_date: string; contract_type?: "unbefristet" | "befristet"; contract_end_date?: string; employment_type?: "Vollzeit" | "Teilzeit"; weekly_hours?: number; paygrade?: "A" | "B" | "C" | "D" | "E" | "F"; source: "Intern" | "Extern"; worker_type?: WorkerType; collective_agreement?: CollectiveAgreement; work_days?: Weekday[]; is_betriebsrat?: boolean; has_dienstwagen?: boolean; is_laterale_fuehrung?: boolean; is_c_level?: boolean; }): Promise { const supabase = await createClient(); const { data, error } = await supabase.rpc("hire_employee", { payload }); if (error) return { success: false, error: error.message }; revalidatePath("/employees"); revalidatePath("/"); revalidatePath("/positions"); return { success: true, employeeId: data as string }; } export async function terminateEmployee(payload: { employee_id: string; exit_date: string; exit_reason: string; note?: string; }): Promise { return callRpc("terminate_employee", payload, [`/employees/${payload.employee_id}`, "/employees", "/"]); } export async function transferEmployee(payload: { employee_id: string; effective_date: string; new_team_id: string; new_title?: string; }): Promise { return callRpc("transfer_employee", payload, [`/employees/${payload.employee_id}`, "/employees"]); } export async function promoteEmployee(payload: { employee_id: string; effective_date: string; new_title: string; new_paygrade?: "A" | "B" | "C" | "D" | "E" | "F"; }): Promise { return callRpc("promote_employee", payload, [`/employees/${payload.employee_id}`, "/employees"]); } export async function startKarenz(payload: { employee_id: string; karenz_start_date: string; planned_return_date: string; absence_type: string; note?: string; }): Promise { return callRpc("start_karenz", payload, [`/employees/${payload.employee_id}`, "/employees", "/"]); } export async function adjustKarenzReturn(payload: { employee_id: string; new_return_date: string; note?: string; }): Promise { return callRpc("adjust_karenz_return", payload, [`/employees/${payload.employee_id}`]); } export async function recordKarenzReturn(payload: { employee_id: string; return_date: string; employment_mode: "unverändert" | "Vollzeit" | "Teilzeit"; weekly_hours?: number; }): Promise { return callRpc("record_karenz_return", payload, [`/employees/${payload.employee_id}`, "/employees", "/"]); } export async function changeEmployeeData(payload: { employee_id: string; effective_date: string; person: Record; contract: Record; role: Record; }): Promise { return callRpc("change_employee_data", payload, [`/employees/${payload.employee_id}`, "/employees"]); } export async function rehireEmployee(payload: { employee_id: string; rehire_date: string }): Promise { return callRpc("rehire_employee", payload, [`/employees/${payload.employee_id}`, "/employees", "/"]); } export async function addEmployeeDependent(payload: { employee_id: string; first_name: string; last_name: string; relationship: RelationshipType; sv_nummer?: string; birth_date: string; effective_date: string; }): Promise { return callRpc("add_employee_dependent", payload, [`/employees/${payload.employee_id}`]); } export async function deleteEmployeeDependent(payload: { dependent_id: string; employee_id: string; effective_date: string; }): Promise { return callRpc("delete_employee_dependent", payload, [`/employees/${payload.employee_id}`]); } export async function addEmployeeNote(payload: { employee_id: string; category: NoteCategory; note_text: string; due_date?: string; }): Promise { return callRpc("add_employee_note", payload, [`/employees/${payload.employee_id}`, "/"]); } export async function completeEmployeeNote(payload: { note_id: string; employee_id: string }): Promise { return callRpc("complete_employee_note", payload, [`/employees/${payload.employee_id}`, "/"]); } export type EmployeeSearchResult = { id: string; first_name: string; last_name: string; job_title: string; team_id: string | null }; // Shared by "Position besetzen" (staff an open position) and the reorg // workbench's "Mitarbeiter:in(nen)" multi-select — both search active/ // on-leave employees by name or title. export async function searchActiveEmployees(query: string): Promise { const supabase = await createClient(); let q = supabase .from("employees") .select("id, first_name, last_name, job_title, team_id") .in("status", ["Aktiv", "Karenz"]) .limit(20); if (query.trim()) { const term = sanitizeIlikeTerm(query.trim()); q = q.or(`first_name.ilike.%${term}%,last_name.ilike.%${term}%,job_title.ilike.%${term}%`); } const { data } = await q; return data ?? []; }