Files
mexus-app/prisma/schema.prisma
Mexus 86bfbd2039 feat: Initial commit - Mexus App
Sistema de Gestión de Obras de Construcción completo con:
- Dashboard con KPIs y gráficos
- Módulo de obras con fases y tareas
- Control financiero (gastos, presupuestos)
- Gestión de recursos (personal, subcontratistas)
- Inventario de materiales con alertas de stock
- Reportes con exportación CSV
- Autenticación con roles (NextAuth.js v5)
- API REST completa
- Documentación de API y base de datos
- Configuración Docker para despliegue

Stack: Next.js 14+, TypeScript, Tailwind CSS, Prisma, PostgreSQL

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 01:10:55 +00:00

467 lines
12 KiB
Plaintext

// 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])
}