0046b6c3cf
- lib/turnos.ts: crearTurno() compartido (valida servicio/jefe/slot); cliente/turnos POST lo reutiliza - lib/telefono.ts: normalización de teléfono (E.164 sin '+') para matchear el wa_id - lib/whatsapp-bot.ts: procesarMensaje(telefono, texto), state machine completa: identidad por teléfono + verificación por email registrado / alta nueva, elegir mecánico (botones) -> trabajo (letras) -> horario (letras, con "más") -> confirmar, crea turno sin auto/km; expiración 30min, "cancelar" global, manejo de inválidos y 409. Devuelve objetos-respuesta (texto/botones) -> independiente de Meta (lo traduce F0). - scripts/test-whatsapp-bot.ts + npm run test:bot: corre la máquina de estados con un Prisma en memoria (sin DB ni Meta), ejercitando scheduling y crearTurno reales. 27/27 OK. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
51 lines
1.9 KiB
TypeScript
51 lines
1.9 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { prisma } from "@/lib/prisma";
|
|
import { verificarSesion } from "@/lib/auth-admin";
|
|
import { crearTurno } from "@/lib/turnos";
|
|
|
|
export async function GET() {
|
|
const sesion = await verificarSesion("cliente_session");
|
|
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
|
|
|
const turnos = await prisma.turno.findMany({
|
|
where: { clienteId: sesion.sub },
|
|
include: { auto: true, tipoServicio: true, jefeMecanico: { select: { id: true, nombre: true } } },
|
|
orderBy: { fechaInicio: "desc" },
|
|
});
|
|
|
|
return NextResponse.json(turnos);
|
|
}
|
|
|
|
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, jefeMecanicoId, fechaInicio, kilometros } = await req.json();
|
|
if (!autoId || !tipoServicioId || !jefeMecanicoId || !fechaInicio || !kilometros)
|
|
return NextResponse.json({ error: "Datos incompletos" }, { status: 400 });
|
|
|
|
const km = Number(kilometros);
|
|
if (!Number.isInteger(km) || km <= 0 || km > 1000000)
|
|
return NextResponse.json({ error: "Kilometraje inválido (debe ser entre 1 y 1.000.000)" }, { status: 400 });
|
|
|
|
// Verificar que el auto pertenece al cliente
|
|
const auto = await prisma.auto.findFirst({
|
|
where: { id: autoId, clienteId: sesion.sub },
|
|
});
|
|
if (!auto) return NextResponse.json({ error: "Auto no encontrado" }, { status: 404 });
|
|
|
|
const resultado = await crearTurno({
|
|
clienteId: sesion.sub,
|
|
jefeMecanicoId,
|
|
tipoServicioId,
|
|
fechaInicio: new Date(fechaInicio),
|
|
autoId,
|
|
kilometros: km,
|
|
});
|
|
|
|
if (!resultado.ok)
|
|
return NextResponse.json({ error: resultado.error }, { status: resultado.status });
|
|
|
|
return NextResponse.json(resultado.turno, { status: 201 });
|
|
}
|