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:
+38
-19
@@ -7,16 +7,18 @@ datasource db {
|
||||
}
|
||||
|
||||
model Cliente {
|
||||
id String @id @default(cuid())
|
||||
email String @unique
|
||||
nombre String
|
||||
apellido String
|
||||
telefono String
|
||||
createdAt DateTime @default(now())
|
||||
id String @id @default(cuid())
|
||||
email String? @unique
|
||||
nombre String
|
||||
apellido String
|
||||
telefono String
|
||||
telefonoNorm String? @unique // teléfono en formato E.164, usado para matchear al que escribe por WhatsApp
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
autos Auto[]
|
||||
turnos Turno[]
|
||||
magicTokens MagicToken[]
|
||||
autos Auto[]
|
||||
turnos Turno[]
|
||||
magicTokens MagicToken[]
|
||||
conversaciones ConversacionWhatsapp[]
|
||||
}
|
||||
|
||||
model Auto {
|
||||
@@ -35,30 +37,32 @@ model Auto {
|
||||
}
|
||||
|
||||
model TipoServicio {
|
||||
id String @id @default(cuid())
|
||||
nombre String
|
||||
duracionHoras Float
|
||||
activo Boolean @default(true)
|
||||
id String @id @default(cuid())
|
||||
nombre String
|
||||
duracionHoras Float
|
||||
activo Boolean @default(true)
|
||||
jefeMecanicoId String? // trabajo cargado por un jefe mecánico puntual; null = servicio global (legacy)
|
||||
|
||||
turnos Turno[]
|
||||
historial HistorialServicio[]
|
||||
jefeMecanico JefeMecanico? @relation(fields: [jefeMecanicoId], references: [id])
|
||||
turnos Turno[]
|
||||
historial HistorialServicio[]
|
||||
}
|
||||
|
||||
model Turno {
|
||||
id String @id @default(cuid())
|
||||
clienteId String
|
||||
autoId String
|
||||
autoId String?
|
||||
tipoServicioId String
|
||||
jefeMecanicoId String
|
||||
fechaInicio DateTime
|
||||
fechaFin DateTime
|
||||
kilometros Int
|
||||
kilometros Int?
|
||||
estado EstadoTurno @default(PENDIENTE)
|
||||
comentario String?
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
cliente Cliente @relation(fields: [clienteId], references: [id])
|
||||
auto Auto @relation(fields: [autoId], references: [id])
|
||||
auto Auto? @relation(fields: [autoId], references: [id])
|
||||
tipoServicio TipoServicio @relation(fields: [tipoServicioId], references: [id])
|
||||
jefeMecanico JefeMecanico @relation(fields: [jefeMecanicoId], references: [id])
|
||||
}
|
||||
@@ -72,7 +76,8 @@ model JefeMecanico {
|
||||
activo Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
turnos Turno[]
|
||||
turnos Turno[]
|
||||
servicios TipoServicio[]
|
||||
}
|
||||
|
||||
model HistorialServicio {
|
||||
@@ -117,3 +122,17 @@ enum EstadoTurno {
|
||||
CANCELADO
|
||||
COMPLETADO
|
||||
}
|
||||
|
||||
// Estado de la conversación del bot de WhatsApp, por número de teléfono.
|
||||
// El webhook es stateless: acá se guarda en qué paso está y las selecciones parciales.
|
||||
model ConversacionWhatsapp {
|
||||
id String @id @default(cuid())
|
||||
telefono String @unique // wa_id del cliente (E.164, sin '+')
|
||||
paso String @default("INICIO") // paso de la máquina de estados
|
||||
datos Json @default("{}") // selecciones parciales (mecánico, trabajo, slot, alta en curso, etc.)
|
||||
clienteId String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
cliente Cliente? @relation(fields: [clienteId], references: [id])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user