espace-paie-odentas/app/api/staff/salaries/search/route.ts

173 lines
No EOL
6.1 KiB
TypeScript

// app/api/staff/salaries/search/route.ts
export const dynamic = "force-dynamic";
import { NextResponse, NextRequest } from "next/server";
import { createSbServer } from "@/lib/supabaseServer";
export async function GET(req: NextRequest) {
try {
const sb = createSbServer();
const {
data: { user },
error: authError,
} = await sb.auth.getUser();
if (authError || !user) {
return NextResponse.json({ error: "Non authentifié" }, { status: 401 });
}
// Check if user is staff
const { data: staffData } = await sb
.from("staff_users")
.select("is_staff")
.eq("user_id", user.id)
.maybeSingle();
if (!staffData?.is_staff) {
return NextResponse.json({ error: "Accès refusé" }, { status: 403 });
}
const { searchParams } = new URL(req.url);
const q = searchParams.get("q") || "";
const civilite = searchParams.get("civilite");
const transat = searchParams.get("transat");
const organization = searchParams.get("organization");
const sortField = searchParams.get("sort") || "nom";
const sortOrder = searchParams.get("order") === "desc" ? false : true;
const limit = Math.min(100, Math.max(1, parseInt(searchParams.get("limit") || "50")));
const offset = Math.max(0, parseInt(searchParams.get("offset") || "0"));
console.log("🔍 Staff salaries search:", { q, civilite, transat, organization, sortField, sortOrder, limit, offset });
// Build query
let query = sb
.from("salaries")
.select(
`id, code_salarie, num_salarie, salarie, nom, nom_de_naissance, prenom, civilite, pseudonyme,
compte_transat, topaze, justificatifs_personnels, rf_au_sens_fiscal, intermittent_mineur_16,
adresse_mail, nir, conges_spectacles, tel, adresse, date_naissance, lieu_de_naissance,
iban, bic, abattement_2024, infos_caisses_organismes, notif_nouveau_salarie, notif_employeur,
derniere_profession, employer_id, notes, last_notif_justifs, created_at, updated_at,
organizations(name)`,
{ count: "exact" }
);
// Apply filters
if (q) {
const like = `%${q}%`;
query = query.or(
[
`nom.ilike.${like}`,
`prenom.ilike.${like}`,
`salarie.ilike.${like}`,
`adresse_mail.ilike.${like}`,
`code_salarie.ilike.${like}`,
`num_salarie.like.${like}`,
`tel.ilike.${like}`,
].join(",")
);
}
if (civilite) {
query = query.eq("civilite", civilite);
}
if (transat === "connected") {
query = query.ilike("compte_transat", "%connect%").not("compte_transat", "ilike", "%non%");
} else if (transat === "not_connected") {
query = query.or("compte_transat.is.null,compte_transat.ilike.%non%,not.compte_transat.ilike.%connect%");
}
if (organization) {
query = query.ilike("infos_caisses_organismes", `%${organization}%`);
}
// Apply sorting
const validSortFields = ["nom", "prenom", "civilite", "adresse_mail", "created_at", "code_salarie"];
const actualSortField = validSortFields.includes(sortField) ? sortField : "nom";
query = query.order(actualSortField, { ascending: sortOrder });
// Add secondary sort for consistency
if (actualSortField !== "nom") {
query = query.order("nom", { ascending: true });
}
// Apply pagination
query = query.range(offset, offset + limit - 1);
const { data, error, count } = await query;
console.log("🔍 Staff salaries search result:", {
data: data?.length,
error: error?.message,
count
});
if (error) {
console.error("💥 [API /staff/salaries/search] Supabase error:", error.message);
return NextResponse.json({ error: "supabase_error", detail: error.message }, { status: 500 });
}
// Transform data to match expected format
const rows = (data || []).map((r: any) => {
const fullName = r.salarie || [r.nom, r.prenom].filter(Boolean).join(" ").trim() || r.nom || "";
const matricule = r.code_salarie || (r.num_salarie ? String(r.num_salarie) : r.id);
const comp = (r.compte_transat || "").toString().toLowerCase();
const transatConnecte = comp.includes("connect") && !comp.includes("non");
return {
id: r.id,
matricule,
nom_complet: fullName,
email: r.adresse_mail,
transat_connecte: transatConnecte,
dernier_emploi: r.derniere_profession,
civilite: r.civilite,
tel: r.tel,
org_name: r.infos_caisses_organismes,
organization_name: r.organizations?.name || null,
created_at: r.created_at,
// Include ALL original fields for editing and display
code_salarie: r.code_salarie,
num_salarie: r.num_salarie,
nom: r.nom,
nom_de_naissance: r.nom_de_naissance,
prenom: r.prenom,
salarie: r.salarie,
pseudonyme: r.pseudonyme,
compte_transat: r.compte_transat,
topaze: r.topaze,
justificatifs_personnels: r.justificatifs_personnels,
rf_au_sens_fiscal: r.rf_au_sens_fiscal,
intermittent_mineur_16: r.intermittent_mineur_16,
adresse_mail: r.adresse_mail,
nir: r.nir,
conges_spectacles: r.conges_spectacles,
adresse: r.adresse,
date_naissance: r.date_naissance,
lieu_de_naissance: r.lieu_de_naissance,
iban: r.iban,
bic: r.bic,
abattement_2024: r.abattement_2024,
infos_caisses_organismes: r.infos_caisses_organismes,
notif_nouveau_salarie: r.notif_nouveau_salarie,
notif_employeur: r.notif_employeur,
derniere_profession: r.derniere_profession,
employer_id: r.employer_id,
notes: r.notes,
last_notif_justifs: r.last_notif_justifs,
updated_at: r.updated_at,
};
});
return NextResponse.json({
rows,
count: count ?? rows.length,
offset,
limit,
});
} catch (e: any) {
console.error("💥 [API /staff/salaries/search] Unexpected error:", e?.message);
return NextResponse.json({ error: "server_error", message: e?.message || "unknown" }, { status: 500 });
}
}