- Ajout sous-header total net à payer sur page virements-salaires - Migration transfer_done_at pour tracking précis des virements - Nouvelle page saisie tableau pour création factures en masse - APIs bulk pour mise à jour dates signature et jours technicien - API demande mandat SEPA avec email template - Webhook DocuSeal pour signature contrats (mode TEST) - Composants modaux détails et vérification PDF fiches de paie - Upload/suppression/remplacement PDFs dans PayslipsGrid - Amélioration affichage colonnes et filtres grilles contrats/paies - Template email mandat SEPA avec sous-texte CTA - APIs bulk facturation (création, update statut/date paiement) - API clients sans facture pour période donnée - Corrections calculs dates et montants avec auto-remplissage
75 lines
2.9 KiB
TypeScript
75 lines
2.9 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { createSbServer } from "@/lib/supabaseServer";
|
|
|
|
export async function GET(req: Request, { params }: { params: { id: string } }) {
|
|
try {
|
|
const sb = createSbServer();
|
|
const { data: { user } } = await sb.auth.getUser();
|
|
if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
|
|
const { data: me } = await sb.from('staff_users').select('is_staff').eq('user_id', user.id).maybeSingle();
|
|
if (!me?.is_staff) return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
|
|
|
|
const payslipId = params.id;
|
|
|
|
// Fetch payslip with relations
|
|
const { data, error } = await sb
|
|
.from('payslips')
|
|
.select(`
|
|
*,
|
|
cddu_contracts!contract_id(
|
|
id,
|
|
contract_number,
|
|
employee_name,
|
|
employee_id,
|
|
structure,
|
|
type_de_contrat,
|
|
org_id,
|
|
salaries!employee_id(salarie, nom, prenom),
|
|
organizations!org_id(organization_details(code_employeur))
|
|
)
|
|
`)
|
|
.eq('id', payslipId)
|
|
.single();
|
|
|
|
if (error) return NextResponse.json({ error: error.message }, { status: 500 });
|
|
if (!data) return NextResponse.json({ error: 'Not found' }, { status: 404 });
|
|
|
|
return NextResponse.json(data);
|
|
} catch (err: any) {
|
|
console.error(err);
|
|
return NextResponse.json({ error: 'Internal' }, { status: 500 });
|
|
}
|
|
}
|
|
|
|
export async function PATCH(req: Request, { params }: { params: { id: string } }) {
|
|
try {
|
|
const sb = createSbServer();
|
|
const { data: { user } } = await sb.auth.getUser();
|
|
if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
|
|
const { data: me } = await sb.from('staff_users').select('is_staff').eq('user_id', user.id).maybeSingle();
|
|
if (!me?.is_staff) return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
|
|
|
|
const payslipId = params.id;
|
|
const body = await req.json().catch(() => ({}));
|
|
|
|
// Allow patching a limited set of fields to avoid accidental overwrites
|
|
const allowed: Record<string, any> = {};
|
|
const fields = ['period_start','period_end','period_month','gross_amount','net_amount','processed','paye','traite', 'employer_cost', 'pay_number', 'aem_status', 'transfer_done', 'net_after_withholding', 'pay_date', 'payslip_path', 'contract_id', 'organization_id', 'storage_path', 'storage_url'];
|
|
for (const f of fields) {
|
|
if (Object.prototype.hasOwnProperty.call(body, f)) allowed[f] = body[f];
|
|
}
|
|
|
|
if (Object.keys(allowed).length === 0) {
|
|
return NextResponse.json({ error: 'missing_fields' }, { status: 400 });
|
|
}
|
|
|
|
const { data, error } = await sb.from('payslips').update(allowed).eq('id', payslipId).select().maybeSingle();
|
|
if (error) return NextResponse.json({ error: error.message }, { status: 500 });
|
|
return NextResponse.json(data);
|
|
} catch (err: any) {
|
|
console.error(err);
|
|
return NextResponse.json({ error: 'Internal' }, { status: 500 });
|
|
}
|
|
}
|