// Prisma schema for Construction Management System generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } // ============== ENUMS ============== enum Role { ADMIN GERENTE SUPERVISOR CONTADOR EMPLEADO } enum EstadoObra { PLANIFICACION EN_PROGRESO PAUSADA COMPLETADA CANCELADA } enum EstadoTarea { PENDIENTE EN_PROGRESO COMPLETADA BLOQUEADA } enum EstadoGasto { PENDIENTE APROBADO RECHAZADO PAGADO } enum CategoriaGasto { MATERIALES MANO_DE_OBRA EQUIPOS SUBCONTRATISTAS PERMISOS TRANSPORTE SERVICIOS OTROS } enum TipoFactura { EMITIDA RECIBIDA } enum EstadoFactura { PENDIENTE PAGADA VENCIDA CANCELADA } enum TipoMovimiento { ENTRADA SALIDA AJUSTE } enum UnidadMedida { UNIDAD METRO METRO_CUADRADO METRO_CUBICO KILOGRAMO TONELADA LITRO BOLSA PIEZA ROLLO CAJA } // ============== MODELS ============== model User { id String @id @default(cuid()) email String @unique password String nombre String apellido String role Role @default(EMPLEADO) telefono String? activo Boolean @default(true) empresaId String empresa Empresa @relation(fields: [empresaId], references: [id]) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations gastosCreados Gasto[] @relation("GastoCreador") gastosAprobados Gasto[] @relation("GastoAprobador") tareasAsignadas TareaObra[] obrasSupervision Obra[] @relation("ObraSupervisor") registrosAvance RegistroAvance[] @@index([empresaId]) @@index([email]) } model Empresa { id String @id @default(cuid()) nombre String rfc String? @unique direccion String? telefono String? email String? logo String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations usuarios User[] obras Obra[] materiales Material[] empleados Empleado[] subcontratistas Subcontratista[] clientes Cliente[] } model Cliente { id String @id @default(cuid()) nombre String rfc String? direccion String? telefono String? email String? empresaId String empresa Empresa @relation(fields: [empresaId], references: [id]) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations obras Obra[] @@index([empresaId]) } model Obra { id String @id @default(cuid()) nombre String descripcion String? direccion String estado EstadoObra @default(PLANIFICACION) fechaInicio DateTime? fechaFinPrevista DateTime? fechaFinReal DateTime? porcentajeAvance Float @default(0) presupuestoTotal Float @default(0) gastoTotal Float @default(0) imagenPortada String? empresaId String empresa Empresa @relation(fields: [empresaId], references: [id]) clienteId String? cliente Cliente? @relation(fields: [clienteId], references: [id]) supervisorId String? supervisor User? @relation("ObraSupervisor", fields: [supervisorId], references: [id]) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations fases FaseObra[] presupuestos Presupuesto[] gastos Gasto[] facturas Factura[] movimientosInv MovimientoInventario[] asignaciones AsignacionEmpleado[] contratos ContratoSubcontratista[] registrosAvance RegistroAvance[] @@index([empresaId]) @@index([estado]) @@index([clienteId]) } model FaseObra { id String @id @default(cuid()) nombre String descripcion String? orden Int fechaInicio DateTime? fechaFin DateTime? porcentajeAvance Float @default(0) obraId String obra Obra @relation(fields: [obraId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations tareas TareaObra[] @@index([obraId]) } model TareaObra { id String @id @default(cuid()) nombre String descripcion String? estado EstadoTarea @default(PENDIENTE) prioridad Int @default(1) fechaInicio DateTime? fechaFin DateTime? porcentajeAvance Float @default(0) faseId String fase FaseObra @relation(fields: [faseId], references: [id], onDelete: Cascade) asignadoId String? asignado User? @relation(fields: [asignadoId], references: [id]) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([faseId]) @@index([estado]) } model RegistroAvance { id String @id @default(cuid()) descripcion String porcentaje Float fotos String[] obraId String obra Obra @relation(fields: [obraId], references: [id], onDelete: Cascade) registradoPorId String registradoPor User @relation(fields: [registradoPorId], references: [id]) createdAt DateTime @default(now()) @@index([obraId]) } model Presupuesto { id String @id @default(cuid()) nombre String descripcion String? version Int @default(1) total Float @default(0) aprobado Boolean @default(false) obraId String obra Obra @relation(fields: [obraId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations partidas PartidaPresupuesto[] @@index([obraId]) } model PartidaPresupuesto { id String @id @default(cuid()) codigo String descripcion String unidad UnidadMedida cantidad Float precioUnitario Float total Float categoria CategoriaGasto presupuestoId String presupuesto Presupuesto @relation(fields: [presupuestoId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations gastos Gasto[] @@index([presupuestoId]) } model Gasto { id String @id @default(cuid()) concepto String descripcion String? monto Float fecha DateTime categoria CategoriaGasto estado EstadoGasto @default(PENDIENTE) comprobante String? notas String? obraId String obra Obra @relation(fields: [obraId], references: [id], onDelete: Cascade) partidaId String? partida PartidaPresupuesto? @relation(fields: [partidaId], references: [id]) creadoPorId String creadoPor User @relation("GastoCreador", fields: [creadoPorId], references: [id]) aprobadoPorId String? aprobadoPor User? @relation("GastoAprobador", fields: [aprobadoPorId], references: [id]) fechaAprobacion DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([obraId]) @@index([estado]) @@index([categoria]) @@index([fecha]) } model Factura { id String @id @default(cuid()) numero String tipo TipoFactura concepto String monto Float iva Float @default(0) total Float fechaEmision DateTime fechaVencimiento DateTime? fechaPago DateTime? estado EstadoFactura @default(PENDIENTE) archivo String? obraId String obra Obra @relation(fields: [obraId], references: [id], onDelete: Cascade) proveedorNombre String? proveedorRfc String? clienteNombre String? clienteRfc String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([obraId]) @@index([tipo]) @@index([estado]) } model Material { id String @id @default(cuid()) codigo String nombre String descripcion String? unidad UnidadMedida precioUnitario Float stockMinimo Float @default(0) stockActual Float @default(0) ubicacion String? activo Boolean @default(true) empresaId String empresa Empresa @relation(fields: [empresaId], references: [id]) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations movimientos MovimientoInventario[] @@unique([codigo, empresaId]) @@index([empresaId]) @@index([nombre]) } model MovimientoInventario { id String @id @default(cuid()) tipo TipoMovimiento cantidad Float motivo String? materialId String material Material @relation(fields: [materialId], references: [id]) obraId String? obra Obra? @relation(fields: [obraId], references: [id]) createdAt DateTime @default(now()) @@index([materialId]) @@index([obraId]) @@index([tipo]) } model Empleado { id String @id @default(cuid()) nombre String apellido String documento String? telefono String? email String? puesto String salarioBase Float? fechaIngreso DateTime fechaBaja DateTime? activo Boolean @default(true) empresaId String empresa Empresa @relation(fields: [empresaId], references: [id]) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations asignaciones AsignacionEmpleado[] jornadas JornadaTrabajo[] @@index([empresaId]) } model AsignacionEmpleado { id String @id @default(cuid()) fechaInicio DateTime fechaFin DateTime? activo Boolean @default(true) empleadoId String empleado Empleado @relation(fields: [empleadoId], references: [id]) obraId String obra Obra @relation(fields: [obraId], references: [id]) createdAt DateTime @default(now()) @@index([empleadoId]) @@index([obraId]) } model JornadaTrabajo { id String @id @default(cuid()) fecha DateTime horasRegular Float @default(0) horasExtra Float @default(0) notas String? empleadoId String empleado Empleado @relation(fields: [empleadoId], references: [id]) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([empleadoId]) @@index([fecha]) } model Subcontratista { id String @id @default(cuid()) nombre String rfc String? especialidad String telefono String? email String? direccion String? activo Boolean @default(true) empresaId String empresa Empresa @relation(fields: [empresaId], references: [id]) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations contratos ContratoSubcontratista[] @@index([empresaId]) } model ContratoSubcontratista { id String @id @default(cuid()) descripcion String montoContratado Float montoPagado Float @default(0) fechaInicio DateTime fechaFin DateTime? estado String @default("ACTIVO") subcontratistaId String subcontratista Subcontratista @relation(fields: [subcontratistaId], references: [id]) obraId String obra Obra @relation(fields: [obraId], references: [id]) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([subcontratistaId]) @@index([obraId]) }