feat: bootstrap taller-turnos project
Estructura inicial con Next.js 14, PostgreSQL/Prisma 7, autenticación por magic link (clientes) y JWT (admins), lógica de scheduling con 4 slots paralelos y API routes completas para cliente y panel admin. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
}
|
||||
|
||||
model Cliente {
|
||||
id String @id @default(cuid())
|
||||
email String @unique
|
||||
nombre String
|
||||
apellido String
|
||||
telefono String
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
autos Auto[]
|
||||
turnos Turno[]
|
||||
magicTokens MagicToken[]
|
||||
}
|
||||
|
||||
model Auto {
|
||||
id String @id @default(cuid())
|
||||
clienteId String
|
||||
patente String @unique
|
||||
marca String
|
||||
modelo String
|
||||
anio Int
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
cliente Cliente @relation(fields: [clienteId], references: [id])
|
||||
turnos Turno[]
|
||||
historial HistorialServicio[]
|
||||
}
|
||||
|
||||
model TipoServicio {
|
||||
id String @id @default(cuid())
|
||||
nombre String
|
||||
duracionHoras Float
|
||||
activo Boolean @default(true)
|
||||
|
||||
turnos Turno[]
|
||||
historial HistorialServicio[]
|
||||
}
|
||||
|
||||
model Turno {
|
||||
id String @id @default(cuid())
|
||||
clienteId String
|
||||
autoId String
|
||||
tipoServicioId String
|
||||
fechaInicio DateTime
|
||||
fechaFin DateTime
|
||||
estado EstadoTurno @default(PENDIENTE)
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
cliente Cliente @relation(fields: [clienteId], references: [id])
|
||||
auto Auto @relation(fields: [autoId], references: [id])
|
||||
tipoServicio TipoServicio @relation(fields: [tipoServicioId], references: [id])
|
||||
}
|
||||
|
||||
model HistorialServicio {
|
||||
id String @id @default(cuid())
|
||||
autoId String
|
||||
adminId String
|
||||
tipoServicioId String?
|
||||
descripcion String
|
||||
observaciones String?
|
||||
fechaRealizado DateTime
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
auto Auto @relation(fields: [autoId], references: [id])
|
||||
admin Admin @relation(fields: [adminId], references: [id])
|
||||
tipoServicio TipoServicio? @relation(fields: [tipoServicioId], references: [id])
|
||||
}
|
||||
|
||||
model Admin {
|
||||
id String @id @default(cuid())
|
||||
email String @unique
|
||||
nombre String
|
||||
passwordHash String
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
historial HistorialServicio[]
|
||||
}
|
||||
|
||||
model MagicToken {
|
||||
id String @id @default(cuid())
|
||||
clienteId String
|
||||
token String @unique
|
||||
expiresAt DateTime
|
||||
usado Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
cliente Cliente @relation(fields: [clienteId], references: [id])
|
||||
}
|
||||
|
||||
enum EstadoTurno {
|
||||
PENDIENTE
|
||||
CONFIRMADO
|
||||
CANCELADO
|
||||
COMPLETADO
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import bcrypt from "bcryptjs";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function main() {
|
||||
const hash = (pwd: string) => bcrypt.hash(pwd, 10);
|
||||
|
||||
await prisma.admin.upsert({
|
||||
where: { email: "jefe1@taller.com" },
|
||||
update: {},
|
||||
create: {
|
||||
email: "jefe1@taller.com",
|
||||
nombre: "Jefe 1",
|
||||
passwordHash: await hash("jefe1password"),
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.admin.upsert({
|
||||
where: { email: "jefe2@taller.com" },
|
||||
update: {},
|
||||
create: {
|
||||
email: "jefe2@taller.com",
|
||||
nombre: "Jefe 2",
|
||||
passwordHash: await hash("jefe2password"),
|
||||
},
|
||||
});
|
||||
|
||||
// Tipos de servicio de ejemplo
|
||||
const servicios = [
|
||||
{ nombre: "Cambio de aceite y filtro", duracionHoras: 1 },
|
||||
{ nombre: "Cambio de bujías", duracionHoras: 1 },
|
||||
{ nombre: "Cambio de frenos", duracionHoras: 2 },
|
||||
{ nombre: "Alineación y balanceo", duracionHoras: 1.5 },
|
||||
{ nombre: "Cambio de correa de distribución", duracionHoras: 4 },
|
||||
{ nombre: "Cambio de distribución con bomba de agua", duracionHoras: 8 },
|
||||
{ nombre: "Revisión general", duracionHoras: 2 },
|
||||
];
|
||||
|
||||
for (const s of servicios) {
|
||||
await prisma.tipoServicio.upsert({
|
||||
where: { id: s.nombre },
|
||||
update: {},
|
||||
create: s,
|
||||
}).catch(() => prisma.tipoServicio.create({ data: s }));
|
||||
}
|
||||
|
||||
console.log("Seed completado");
|
||||
}
|
||||
|
||||
main().finally(() => prisma.$disconnect());
|
||||
Reference in New Issue
Block a user