173 lines
No EOL
6.1 KiB
TypeScript
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 });
|
|
}
|
|
} |