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>
This commit is contained in:
466
prisma/schema.prisma
Normal file
466
prisma/schema.prisma
Normal file
@@ -0,0 +1,466 @@
|
||||
// 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])
|
||||
}
|
||||
315
prisma/seed.ts
Normal file
315
prisma/seed.ts
Normal file
@@ -0,0 +1,315 @@
|
||||
import { PrismaClient, Role, EstadoObra, CategoriaGasto } from "@prisma/client";
|
||||
import bcrypt from "bcryptjs";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function main() {
|
||||
console.log("Seeding database...");
|
||||
|
||||
// Create empresa
|
||||
const empresa = await prisma.empresa.create({
|
||||
data: {
|
||||
nombre: "Constructora Demo S.A. de C.V.",
|
||||
rfc: "CDM123456ABC",
|
||||
direccion: "Av. Principal #123, Ciudad de Mexico",
|
||||
telefono: "55 1234 5678",
|
||||
email: "contacto@constructorademo.com",
|
||||
},
|
||||
});
|
||||
|
||||
console.log("Created empresa:", empresa.nombre);
|
||||
|
||||
// Create admin user
|
||||
const hashedPassword = await bcrypt.hash("admin123", 12);
|
||||
const adminUser = await prisma.user.create({
|
||||
data: {
|
||||
email: "admin@demo.com",
|
||||
password: hashedPassword,
|
||||
nombre: "Admin",
|
||||
apellido: "Demo",
|
||||
role: Role.ADMIN,
|
||||
empresaId: empresa.id,
|
||||
},
|
||||
});
|
||||
|
||||
console.log("Created admin user:", adminUser.email);
|
||||
|
||||
// Create supervisor user
|
||||
const supervisorUser = await prisma.user.create({
|
||||
data: {
|
||||
email: "supervisor@demo.com",
|
||||
password: hashedPassword,
|
||||
nombre: "Juan",
|
||||
apellido: "Supervisor",
|
||||
role: Role.SUPERVISOR,
|
||||
empresaId: empresa.id,
|
||||
},
|
||||
});
|
||||
|
||||
// Create cliente
|
||||
const cliente = await prisma.cliente.create({
|
||||
data: {
|
||||
nombre: "Cliente Residencial SA",
|
||||
rfc: "CRS987654XYZ",
|
||||
direccion: "Calle Ejemplo #456",
|
||||
telefono: "55 9876 5432",
|
||||
email: "cliente@ejemplo.com",
|
||||
empresaId: empresa.id,
|
||||
},
|
||||
});
|
||||
|
||||
console.log("Created cliente:", cliente.nombre);
|
||||
|
||||
// Create obra
|
||||
const obra = await prisma.obra.create({
|
||||
data: {
|
||||
nombre: "Torre Residencial Norte",
|
||||
descripcion: "Proyecto de torre residencial de 20 pisos con amenidades",
|
||||
direccion: "Av. Reforma #500, CDMX",
|
||||
estado: EstadoObra.EN_PROGRESO,
|
||||
fechaInicio: new Date("2024-01-15"),
|
||||
fechaFinPrevista: new Date("2025-06-30"),
|
||||
porcentajeAvance: 35,
|
||||
presupuestoTotal: 15000000,
|
||||
gastoTotal: 5250000,
|
||||
empresaId: empresa.id,
|
||||
clienteId: cliente.id,
|
||||
supervisorId: supervisorUser.id,
|
||||
},
|
||||
});
|
||||
|
||||
console.log("Created obra:", obra.nombre);
|
||||
|
||||
// Create fases
|
||||
const fases = await Promise.all([
|
||||
prisma.faseObra.create({
|
||||
data: {
|
||||
nombre: "Cimentacion",
|
||||
descripcion: "Excavacion y cimentacion profunda",
|
||||
orden: 1,
|
||||
porcentajeAvance: 100,
|
||||
obraId: obra.id,
|
||||
},
|
||||
}),
|
||||
prisma.faseObra.create({
|
||||
data: {
|
||||
nombre: "Estructura",
|
||||
descripcion: "Construccion de estructura de concreto",
|
||||
orden: 2,
|
||||
porcentajeAvance: 60,
|
||||
obraId: obra.id,
|
||||
},
|
||||
}),
|
||||
prisma.faseObra.create({
|
||||
data: {
|
||||
nombre: "Instalaciones",
|
||||
descripcion: "Instalaciones electricas, hidraulicas y sanitarias",
|
||||
orden: 3,
|
||||
porcentajeAvance: 10,
|
||||
obraId: obra.id,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
console.log("Created", fases.length, "fases");
|
||||
|
||||
// Create presupuesto
|
||||
const presupuesto = await prisma.presupuesto.create({
|
||||
data: {
|
||||
nombre: "Presupuesto Principal 2024",
|
||||
descripcion: "Presupuesto inicial aprobado",
|
||||
total: 15000000,
|
||||
aprobado: true,
|
||||
obraId: obra.id,
|
||||
},
|
||||
});
|
||||
|
||||
// Create partidas
|
||||
await Promise.all([
|
||||
prisma.partidaPresupuesto.create({
|
||||
data: {
|
||||
codigo: "CIM-001",
|
||||
descripcion: "Excavacion y cimentacion",
|
||||
unidad: "METRO_CUBICO",
|
||||
cantidad: 500,
|
||||
precioUnitario: 2500,
|
||||
total: 1250000,
|
||||
categoria: CategoriaGasto.MANO_DE_OBRA,
|
||||
presupuestoId: presupuesto.id,
|
||||
},
|
||||
}),
|
||||
prisma.partidaPresupuesto.create({
|
||||
data: {
|
||||
codigo: "EST-001",
|
||||
descripcion: "Concreto estructural",
|
||||
unidad: "METRO_CUBICO",
|
||||
cantidad: 2000,
|
||||
precioUnitario: 3500,
|
||||
total: 7000000,
|
||||
categoria: CategoriaGasto.MATERIALES,
|
||||
presupuestoId: presupuesto.id,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// Create gastos
|
||||
const gastos = await Promise.all([
|
||||
prisma.gasto.create({
|
||||
data: {
|
||||
concepto: "Compra de cemento",
|
||||
descripcion: "500 toneladas de cemento Portland",
|
||||
monto: 1500000,
|
||||
fecha: new Date("2024-02-01"),
|
||||
categoria: CategoriaGasto.MATERIALES,
|
||||
estado: "APROBADO",
|
||||
obraId: obra.id,
|
||||
creadoPorId: adminUser.id,
|
||||
aprobadoPorId: adminUser.id,
|
||||
fechaAprobacion: new Date("2024-02-02"),
|
||||
},
|
||||
}),
|
||||
prisma.gasto.create({
|
||||
data: {
|
||||
concepto: "Renta de maquinaria",
|
||||
descripcion: "Excavadora y retroexcavadora",
|
||||
monto: 750000,
|
||||
fecha: new Date("2024-02-15"),
|
||||
categoria: CategoriaGasto.EQUIPOS,
|
||||
estado: "APROBADO",
|
||||
obraId: obra.id,
|
||||
creadoPorId: supervisorUser.id,
|
||||
aprobadoPorId: adminUser.id,
|
||||
fechaAprobacion: new Date("2024-02-16"),
|
||||
},
|
||||
}),
|
||||
prisma.gasto.create({
|
||||
data: {
|
||||
concepto: "Nomina trabajadores",
|
||||
descripcion: "Pago quincenal",
|
||||
monto: 500000,
|
||||
fecha: new Date("2024-03-01"),
|
||||
categoria: CategoriaGasto.MANO_DE_OBRA,
|
||||
estado: "PAGADO",
|
||||
obraId: obra.id,
|
||||
creadoPorId: adminUser.id,
|
||||
aprobadoPorId: adminUser.id,
|
||||
fechaAprobacion: new Date("2024-03-01"),
|
||||
},
|
||||
}),
|
||||
prisma.gasto.create({
|
||||
data: {
|
||||
concepto: "Compra de acero",
|
||||
descripcion: "Varilla corrugada",
|
||||
monto: 2000000,
|
||||
fecha: new Date("2024-03-15"),
|
||||
categoria: CategoriaGasto.MATERIALES,
|
||||
estado: "PENDIENTE",
|
||||
obraId: obra.id,
|
||||
creadoPorId: supervisorUser.id,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
console.log("Created", gastos.length, "gastos");
|
||||
|
||||
// Create materiales
|
||||
const materiales = await Promise.all([
|
||||
prisma.material.create({
|
||||
data: {
|
||||
codigo: "CEM-001",
|
||||
nombre: "Cemento Portland",
|
||||
descripcion: "Cemento gris tipo I",
|
||||
unidad: "BOLSA",
|
||||
precioUnitario: 180,
|
||||
stockMinimo: 100,
|
||||
stockActual: 250,
|
||||
ubicacion: "Bodega A",
|
||||
empresaId: empresa.id,
|
||||
},
|
||||
}),
|
||||
prisma.material.create({
|
||||
data: {
|
||||
codigo: "VAR-001",
|
||||
nombre: "Varilla corrugada 3/8",
|
||||
descripcion: "Varilla de acero corrugado",
|
||||
unidad: "PIEZA",
|
||||
precioUnitario: 120,
|
||||
stockMinimo: 500,
|
||||
stockActual: 1200,
|
||||
ubicacion: "Bodega B",
|
||||
empresaId: empresa.id,
|
||||
},
|
||||
}),
|
||||
prisma.material.create({
|
||||
data: {
|
||||
codigo: "GRA-001",
|
||||
nombre: "Grava 3/4",
|
||||
descripcion: "Grava triturada",
|
||||
unidad: "METRO_CUBICO",
|
||||
precioUnitario: 450,
|
||||
stockMinimo: 50,
|
||||
stockActual: 30,
|
||||
ubicacion: "Patio",
|
||||
empresaId: empresa.id,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
console.log("Created", materiales.length, "materiales");
|
||||
|
||||
// Create empleados
|
||||
const empleados = await Promise.all([
|
||||
prisma.empleado.create({
|
||||
data: {
|
||||
nombre: "Pedro",
|
||||
apellido: "Martinez",
|
||||
documento: "PEMA850101ABC",
|
||||
telefono: "55 1111 2222",
|
||||
puesto: "Maestro de Obra",
|
||||
salarioBase: 25000,
|
||||
fechaIngreso: new Date("2023-01-15"),
|
||||
empresaId: empresa.id,
|
||||
},
|
||||
}),
|
||||
prisma.empleado.create({
|
||||
data: {
|
||||
nombre: "Maria",
|
||||
apellido: "Garcia",
|
||||
documento: "MAGA900520XYZ",
|
||||
telefono: "55 3333 4444",
|
||||
puesto: "Ingeniero Residente",
|
||||
salarioBase: 35000,
|
||||
fechaIngreso: new Date("2023-03-01"),
|
||||
empresaId: empresa.id,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
console.log("Created", empleados.length, "empleados");
|
||||
|
||||
// Create subcontratistas
|
||||
await prisma.subcontratista.create({
|
||||
data: {
|
||||
nombre: "Instalaciones Electromecanicas SA",
|
||||
rfc: "IEL123456ABC",
|
||||
especialidad: "Instalaciones Electricas",
|
||||
telefono: "55 5555 6666",
|
||||
email: "contacto@ielsa.com",
|
||||
empresaId: empresa.id,
|
||||
},
|
||||
});
|
||||
|
||||
console.log("Seed completed successfully!");
|
||||
console.log("\nCredenciales de acceso:");
|
||||
console.log("Email: admin@demo.com");
|
||||
console.log("Password: admin123");
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
Reference in New Issue
Block a user