feat(whatsapp): schema del bot de reservas + panel de trabajos por jefe (F1+F3)
FASE 1 — schema:
- Cliente.email opcional; nuevo telefonoNorm (E.164, único) para matchear por WhatsApp
- TipoServicio.jefeMecanicoId opcional (trabajos per-jefe; globales legacy quedan null)
- Turno.autoId/kilometros opcionales (reservas por WhatsApp sin auto/km)
- Nuevo modelo ConversacionWhatsapp (estado del bot por teléfono)
- admin/turnos/[id]: no permite COMPLETADO sin auto+km; Sheets tolera email nulo
FASE 3 — panel de trabajos del jefe:
- API jefe/servicios (GET/POST) y jefe/servicios/[id] (PATCH/DELETE), scoped al jefe
- DELETE desactiva si el trabajo ya tiene turnos asociados
- Página /jefe/servicios (alta/listado/activar/editar/eliminar) + nav Turnos|Trabajos
- Dashboard del jefe resiliente a turnos sin auto/km ("a completar")
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { verificarSesion } from "@/lib/auth-admin";
|
||||
|
||||
// Lista los trabajos cargados por el jefe logueado (los suyos, no los globales).
|
||||
export async function GET() {
|
||||
const sesion = await verificarSesion("jefe_session");
|
||||
if (!sesion || sesion.role !== "jefe")
|
||||
return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const servicios = await prisma.tipoServicio.findMany({
|
||||
where: { jefeMecanicoId: sesion.sub },
|
||||
orderBy: { nombre: "asc" },
|
||||
});
|
||||
|
||||
return NextResponse.json(servicios);
|
||||
}
|
||||
|
||||
// Crea un trabajo propio del jefe (nombre + duración en horas).
|
||||
export async function POST(req: NextRequest) {
|
||||
const sesion = await verificarSesion("jefe_session");
|
||||
if (!sesion || sesion.role !== "jefe")
|
||||
return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const { nombre, duracionHoras } = await req.json();
|
||||
const dur = Number(duracionHoras);
|
||||
if (!nombre || typeof nombre !== "string" || !nombre.trim())
|
||||
return NextResponse.json({ error: "El nombre del trabajo es obligatorio" }, { status: 400 });
|
||||
if (!Number.isFinite(dur) || dur <= 0 || dur > 24)
|
||||
return NextResponse.json(
|
||||
{ error: "La duración debe ser un número de horas entre 0 y 24" },
|
||||
{ status: 400 }
|
||||
);
|
||||
|
||||
const servicio = await prisma.tipoServicio.create({
|
||||
data: { nombre: nombre.trim(), duracionHoras: dur, jefeMecanicoId: sesion.sub },
|
||||
});
|
||||
|
||||
return NextResponse.json(servicio, { status: 201 });
|
||||
}
|
||||
Reference in New Issue
Block a user