Add jefe mecánico to client booking flow
Deploy / deploy (push) Successful in 6m52s

Cliente now picks a jefe mecánico after choosing the service so the
calendar shows that specific jefe's availability. Each jefe has its own
configurable parallel slot capacity (replacing the global SLOTS_PARALELOS
= 5). Admins manage jefes from /admin/jefes; jefes log in to /jefe to
see their daily agenda.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Beldor
2026-06-29 22:28:44 -03:00
parent f79e5ce75c
commit 0792ac3767
18 changed files with 719 additions and 22 deletions
+15
View File
@@ -0,0 +1,15 @@
import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { verificarSesion } from "@/lib/auth-admin";
export async function GET() {
const sesion = await verificarSesion("cliente_session");
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const jefes = await prisma.jefeMecanico.findMany({
where: { activo: true },
orderBy: { nombre: "asc" },
select: { id: true, nombre: true },
});
return NextResponse.json(jefes);
}
+4 -1
View File
@@ -9,13 +9,16 @@ export async function GET(req: NextRequest) {
const { searchParams } = new URL(req.url);
const tipoServicioId = searchParams.get("tipoServicioId");
const jefeMecanicoId = searchParams.get("jefeMecanicoId");
if (!tipoServicioId)
return NextResponse.json({ error: "tipoServicioId requerido" }, { status: 400 });
if (!jefeMecanicoId)
return NextResponse.json({ error: "jefeMecanicoId requerido" }, { status: 400 });
const servicio = await prisma.tipoServicio.findUnique({ where: { id: tipoServicioId } });
if (!servicio || !servicio.activo)
return NextResponse.json({ error: "Servicio no encontrado" }, { status: 404 });
const slots = await obtenerSlotsDisponibles(servicio.duracionHoras, 60, 500);
const slots = await obtenerSlotsDisponibles(jefeMecanicoId, servicio.duracionHoras, 60, 500);
return NextResponse.json(slots);
}
+18 -6
View File
@@ -9,7 +9,7 @@ export async function GET() {
const turnos = await prisma.turno.findMany({
where: { clienteId: sesion.sub },
include: { auto: true, tipoServicio: true },
include: { auto: true, tipoServicio: true, jefeMecanico: { select: { id: true, nombre: true } } },
orderBy: { fechaInicio: "desc" },
});
@@ -20,8 +20,8 @@ export async function POST(req: NextRequest) {
const sesion = await verificarSesion("cliente_session");
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const { autoId, tipoServicioId, fechaInicio, kilometros } = await req.json();
if (!autoId || !tipoServicioId || !fechaInicio || !kilometros)
const { autoId, tipoServicioId, jefeMecanicoId, fechaInicio, kilometros } = await req.json();
if (!autoId || !tipoServicioId || !jefeMecanicoId || !fechaInicio || !kilometros)
return NextResponse.json({ error: "Datos incompletos" }, { status: 400 });
const km = Number(kilometros);
@@ -38,16 +38,28 @@ export async function POST(req: NextRequest) {
if (!servicio || !servicio.activo)
return NextResponse.json({ error: "Servicio no disponible" }, { status: 404 });
const jefe = await prisma.jefeMecanico.findUnique({ where: { id: jefeMecanicoId } });
if (!jefe || !jefe.activo)
return NextResponse.json({ error: "Jefe mecánico no disponible" }, { status: 404 });
const inicio = new Date(fechaInicio);
const fin = new Date(inicio.getTime() + servicio.duracionHoras * 60 * 60 * 1000);
const disponible = await slotEstaDisponible(inicio, fin);
const disponible = await slotEstaDisponible(inicio, fin, jefeMecanicoId);
if (!disponible)
return NextResponse.json({ error: "El horario ya no está disponible" }, { status: 409 });
const turno = await prisma.turno.create({
data: { clienteId: sesion.sub, autoId, tipoServicioId, fechaInicio: inicio, fechaFin: fin, kilometros: km },
include: { auto: true, tipoServicio: true },
data: {
clienteId: sesion.sub,
autoId,
tipoServicioId,
jefeMecanicoId,
fechaInicio: inicio,
fechaFin: fin,
kilometros: km,
},
include: { auto: true, tipoServicio: true, jefeMecanico: { select: { id: true, nombre: true } } },
});
return NextResponse.json(turno, { status: 201 });