generator client { provider = "prisma-client" output = "../src/generated/prisma" } datasource db { provider = "postgresql" } model User { id String @id @default(cuid()) email String @unique password String name String role String @default("asesor") createdAt DateTime @default(now()) updatedAt DateTime @updatedAt cotizaciones Cotizacion[] @relation("AsesorCotizaciones") } model Cliente { id String @id @default(cuid()) nombre String empresa String? email String? telefono String? rfc String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt cotizaciones Cotizacion[] @@index([nombre, empresa]) } model Cotizacion { id String @id @default(cuid()) numero String @unique fecha DateTime @default(now()) vigencia DateTime moneda String @default("MXN") tipoCambio String @default("NA") proyecto String @default("MKT Digital") esquemaPago String @default("Pago Unico/Mensual") estado String @default("borrador") incluirBonos Boolean @default(false) incluirFinanciamiento Boolean @default(false) incluirIva Boolean @default(true) esDoble Boolean @default(false) opcionesMetadata Json? observaciones String? clienteId String asesorId String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt cliente Cliente @relation(fields: [clienteId], references: [id]) asesor User @relation("AsesorCotizaciones", fields: [asesorId], references: [id]) servicios ServicioCotizado[] planBucefalo PlanBucefaloCotizacion? registrosHoras RegistroHoras[] @@index([clienteId]) @@index([asesorId]) @@index([estado]) @@index([createdAt]) } model Categoria { id String @id @default(cuid()) nombre String @unique descripcion String? color String @default("#6b7280") activo Boolean @default(true) orden Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt servicios ServicioCatalogo[] } model Paquete { id String @id @default(cuid()) nombre String descripcion String? activo Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt fases FasePaquete[] } model FasePaquete { id String @id @default(cuid()) paqueteId String nombre String orden Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt paquete Paquete @relation(fields: [paqueteId], references: [id], onDelete: Cascade) servicios ServicioPaquete[] @@index([paqueteId]) } model ServicioCatalogo { id String @id @default(cuid()) nombre String descripcion String? fase Int @default(1) tipoPago String @default("unico") precioBase Float tiempoEntrega String @default("4 - 10 dias") entregablesDefault Json @default("[]") categoriaId String? variante String? nivel String? activo Boolean @default(true) orden Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt servicios ServicioCotizado[] categoriaRel Categoria? @relation(fields: [categoriaId], references: [id]) paquetes ServicioPaquete[] @@index([categoriaId]) @@index([activo, fase, orden]) } model ServicioPaquete { id String @id @default(cuid()) servicioCatalogoId String fasePaqueteId String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt servicio ServicioCatalogo @relation(fields: [servicioCatalogoId], references: [id], onDelete: Cascade) fasePaquete FasePaquete @relation(fields: [fasePaqueteId], references: [id], onDelete: Cascade) @@unique([servicioCatalogoId, fasePaqueteId]) @@index([fasePaqueteId]) } model ServicioCotizado { id String @id @default(cuid()) cotizacionId String servicioCatalogoId String? nombre String? esPersonalizado Boolean @default(false) horas Float? tarifaHora Float? modeloCobro String @default("fijo") montoMinimo Float? horasIncluidas Float? opcion String? fase Int tipoPago String precio Float tiempoEntrega String entregables Json @default("[]") beneficios Json @default("[]") notas String? seleccionado Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt cotizacion Cotizacion @relation(fields: [cotizacionId], references: [id], onDelete: Cascade) servicioCatalogo ServicioCatalogo? @relation(fields: [servicioCatalogoId], references: [id]) @@index([cotizacionId]) @@index([servicioCatalogoId]) } model PlanBucefaloCotizacion { id String @id @default(cuid()) cotizacionId String @unique nivel String @default("basico") precio Float seleccionado Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt cotizacion Cotizacion @relation(fields: [cotizacionId], references: [id], onDelete: Cascade) } // Registro de horas trabajadas contra una cotizacion aprobada con cobro por tiempo // (modeloCobro horas/retainer/demanda). Se usa para emitir notas de pago al cliente: // cada entrada es un dia con un rango horario, una descripcion breve y una tarifa // (snapshot). `horas` se calcula del rango (calcularHorasRango) y se persiste. model RegistroHoras { id String @id @default(cuid()) cotizacionId String fecha DateTime horaInicio String horaFin String horas Float tarifaHora Float @default(0) descripcion String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt cotizacion Cotizacion @relation(fields: [cotizacionId], references: [id], onDelete: Cascade) @@index([cotizacionId]) @@index([fecha]) } model Configuracion { id String @id @default(cuid()) clave String @unique valor String updatedAt DateTime @updatedAt } model Bono { id String @id @default(cuid()) numero Int titulo String descripcion String activo Boolean @default(true) } model FinanciamientoPlan { id String @id @default(cuid()) meses Int @unique tasa Float comision Float montoMinimo Float iva Float @default(0.16) }