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>
487 lines
15 KiB
Markdown
487 lines
15 KiB
Markdown
# Documentación de Base de Datos - Mexus App
|
|
|
|
Este documento describe el esquema de base de datos utilizado en Mexus App.
|
|
|
|
## Diagrama de Relaciones
|
|
|
|
```
|
|
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
│ Empresa │───────│ User │───────│ Gasto │
|
|
└─────────────┘ └─────────────┘ └─────────────┘
|
|
│ │
|
|
│ │
|
|
▼ ▼
|
|
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
│ Obra │───────│ FaseObra │───────│ TareaObra │
|
|
└─────────────┘ └─────────────┘ └─────────────┘
|
|
│
|
|
├──────────────┬──────────────┬──────────────┐
|
|
▼ ▼ ▼ ▼
|
|
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
│ Presupuesto │ │ Empleado │ │Subcontratist│ │ Material │
|
|
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
|
|
│ │
|
|
▼ ▼
|
|
┌─────────────┐ ┌─────────────┐
|
|
│ Partida │ │ Movimiento │
|
|
│ Presupuesto │ │ Inventario │
|
|
└─────────────┘ └─────────────┘
|
|
```
|
|
|
|
## Modelos de Datos
|
|
|
|
### Empresa
|
|
|
|
Representa una empresa en el sistema (multi-tenant).
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| id | String | ID único (CUID) |
|
|
| nombre | String | Nombre de la empresa |
|
|
| rfc | String? | RFC (único) |
|
|
| direccion | String? | Dirección |
|
|
| telefono | String? | Teléfono |
|
|
| email | String? | Email de contacto |
|
|
| logo | String? | URL del logo |
|
|
| activo | Boolean | Estado activo (default: true) |
|
|
| createdAt | DateTime | Fecha de creación |
|
|
| updatedAt | DateTime | Fecha de actualización |
|
|
|
|
**Relaciones:**
|
|
- `usuarios` → User[] (1:N)
|
|
- `obras` → Obra[] (1:N)
|
|
- `materiales` → Material[] (1:N)
|
|
- `empleados` → Empleado[] (1:N)
|
|
- `subcontratistas` → Subcontratista[] (1:N)
|
|
|
|
---
|
|
|
|
### User
|
|
|
|
Usuarios del sistema con roles y permisos.
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| id | String | ID único (CUID) |
|
|
| email | String | Email (único) |
|
|
| password | String | Contraseña hasheada |
|
|
| nombre | String | Nombre |
|
|
| apellido | String | Apellido |
|
|
| telefono | String? | Teléfono |
|
|
| role | Role | Rol del usuario |
|
|
| activo | Boolean | Estado activo (default: true) |
|
|
| empresaId | String | ID de la empresa |
|
|
| createdAt | DateTime | Fecha de creación |
|
|
| updatedAt | DateTime | Fecha de actualización |
|
|
|
|
**Enum Role:**
|
|
- `ADMIN` - Administrador con acceso total
|
|
- `GERENTE` - Gerente de proyectos
|
|
- `SUPERVISOR` - Supervisor de obra
|
|
- `CONTADOR` - Contador/finanzas
|
|
- `EMPLEADO` - Empleado general
|
|
|
|
**Relaciones:**
|
|
- `empresa` → Empresa (N:1)
|
|
- `gastos` → Gasto[] (1:N)
|
|
- `obrasCreadas` → Obra[] (1:N)
|
|
|
|
---
|
|
|
|
### Obra
|
|
|
|
Proyectos de construcción.
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| id | String | ID único (CUID) |
|
|
| codigo | String | Código único de obra |
|
|
| nombre | String | Nombre del proyecto |
|
|
| descripcion | String? | Descripción |
|
|
| cliente | String | Nombre del cliente |
|
|
| ubicacion | String? | Dirección/ubicación |
|
|
| estado | EstadoObra | Estado actual |
|
|
| presupuestoTotal | Float | Presupuesto total MXN |
|
|
| fechaInicio | DateTime | Fecha de inicio |
|
|
| fechaFinEstimada | DateTime? | Fecha fin estimada |
|
|
| fechaFinReal | DateTime? | Fecha fin real |
|
|
| avanceGeneral | Float | Porcentaje de avance (0-100) |
|
|
| empresaId | String | ID de la empresa |
|
|
| creadoPorId | String | ID del usuario creador |
|
|
| createdAt | DateTime | Fecha de creación |
|
|
| updatedAt | DateTime | Fecha de actualización |
|
|
|
|
**Enum EstadoObra:**
|
|
- `PLANEACION` - En planeación
|
|
- `EN_PROGRESO` - En ejecución
|
|
- `PAUSADA` - Pausada temporalmente
|
|
- `COMPLETADA` - Finalizada
|
|
- `CANCELADA` - Cancelada
|
|
|
|
**Relaciones:**
|
|
- `empresa` → Empresa (N:1)
|
|
- `creadoPor` → User (N:1)
|
|
- `fases` → FaseObra[] (1:N)
|
|
- `gastos` → Gasto[] (1:N)
|
|
- `presupuestos` → Presupuesto[] (1:N)
|
|
- `empleadosAsignados` → EmpleadoObra[] (1:N)
|
|
- `subcontratistasAsignados` → SubcontratistaObra[] (1:N)
|
|
- `movimientosInventario` → MovimientoInventario[] (1:N)
|
|
|
|
---
|
|
|
|
### FaseObra
|
|
|
|
Fases o etapas de una obra.
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| id | String | ID único (CUID) |
|
|
| nombre | String | Nombre de la fase |
|
|
| descripcion | String? | Descripción |
|
|
| orden | Int | Orden de ejecución |
|
|
| fechaInicio | DateTime? | Fecha de inicio |
|
|
| fechaFin | DateTime? | Fecha de fin |
|
|
| avance | Float | Porcentaje de avance (default: 0) |
|
|
| estado | EstadoFase | Estado de la fase |
|
|
| obraId | String | ID de la obra |
|
|
| createdAt | DateTime | Fecha de creación |
|
|
| updatedAt | DateTime | Fecha de actualización |
|
|
|
|
**Enum EstadoFase:**
|
|
- `PENDIENTE` - No iniciada
|
|
- `EN_PROGRESO` - En ejecución
|
|
- `COMPLETADA` - Finalizada
|
|
- `CANCELADA` - Cancelada
|
|
|
|
**Relaciones:**
|
|
- `obra` → Obra (N:1)
|
|
- `tareas` → TareaObra[] (1:N)
|
|
|
|
---
|
|
|
|
### TareaObra
|
|
|
|
Tareas específicas dentro de una fase.
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| id | String | ID único (CUID) |
|
|
| nombre | String | Nombre de la tarea |
|
|
| descripcion | String? | Descripción |
|
|
| fechaInicio | DateTime? | Fecha de inicio |
|
|
| fechaFin | DateTime? | Fecha de fin |
|
|
| estado | EstadoTarea | Estado de la tarea |
|
|
| faseId | String | ID de la fase |
|
|
| createdAt | DateTime | Fecha de creación |
|
|
| updatedAt | DateTime | Fecha de actualización |
|
|
|
|
**Enum EstadoTarea:**
|
|
- `PENDIENTE` - No iniciada
|
|
- `EN_PROGRESO` - En ejecución
|
|
- `COMPLETADA` - Finalizada
|
|
- `BLOQUEADA` - Bloqueada por dependencia
|
|
|
|
**Relaciones:**
|
|
- `fase` → FaseObra (N:1)
|
|
|
|
---
|
|
|
|
### Presupuesto
|
|
|
|
Presupuestos asociados a obras.
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| id | String | ID único (CUID) |
|
|
| nombre | String | Nombre del presupuesto |
|
|
| version | Int | Número de versión (default: 1) |
|
|
| montoTotal | Float | Monto total calculado |
|
|
| aprobado | Boolean | Estado de aprobación |
|
|
| fechaAprobacion | DateTime? | Fecha de aprobación |
|
|
| obraId | String | ID de la obra |
|
|
| createdAt | DateTime | Fecha de creación |
|
|
| updatedAt | DateTime | Fecha de actualización |
|
|
|
|
**Relaciones:**
|
|
- `obra` → Obra (N:1)
|
|
- `partidas` → PartidaPresupuesto[] (1:N)
|
|
|
|
---
|
|
|
|
### PartidaPresupuesto
|
|
|
|
Líneas de detalle de un presupuesto.
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| id | String | ID único (CUID) |
|
|
| concepto | String | Concepto/descripción |
|
|
| unidad | String | Unidad de medida |
|
|
| cantidad | Float | Cantidad |
|
|
| precioUnitario | Float | Precio por unidad |
|
|
| subtotal | Float | Subtotal calculado |
|
|
| presupuestoId | String | ID del presupuesto |
|
|
| createdAt | DateTime | Fecha de creación |
|
|
| updatedAt | DateTime | Fecha de actualización |
|
|
|
|
**Relaciones:**
|
|
- `presupuesto` → Presupuesto (N:1)
|
|
|
|
---
|
|
|
|
### Gasto
|
|
|
|
Registro de gastos de obra.
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| id | String | ID único (CUID) |
|
|
| concepto | String | Concepto del gasto |
|
|
| descripcion | String? | Descripción detallada |
|
|
| monto | Float | Monto en MXN |
|
|
| categoria | CategoriaGasto | Categoría |
|
|
| fecha | DateTime | Fecha del gasto |
|
|
| comprobante | String? | Número de comprobante |
|
|
| estado | EstadoGasto | Estado de aprobación |
|
|
| obraId | String | ID de la obra |
|
|
| usuarioId | String | ID del usuario que registra |
|
|
| createdAt | DateTime | Fecha de creación |
|
|
| updatedAt | DateTime | Fecha de actualización |
|
|
|
|
**Enum CategoriaGasto:**
|
|
- `MATERIALES` - Compra de materiales
|
|
- `MANO_OBRA` - Pago de mano de obra
|
|
- `SUBCONTRATO` - Pagos a subcontratistas
|
|
- `EQUIPO` - Renta/compra de equipo
|
|
- `TRANSPORTE` - Fletes y transporte
|
|
- `ADMINISTRATIVO` - Gastos administrativos
|
|
- `OTROS` - Otros gastos
|
|
|
|
**Enum EstadoGasto:**
|
|
- `PENDIENTE` - Pendiente de aprobación
|
|
- `APROBADO` - Aprobado
|
|
- `RECHAZADO` - Rechazado
|
|
|
|
**Relaciones:**
|
|
- `obra` → Obra (N:1)
|
|
- `usuario` → User (N:1)
|
|
|
|
---
|
|
|
|
### Factura
|
|
|
|
Facturas emitidas y recibidas.
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| id | String | ID único (CUID) |
|
|
| numero | String | Número de factura |
|
|
| tipo | TipoFactura | Tipo (emitida/recibida) |
|
|
| cliente | String? | Nombre del cliente |
|
|
| proveedor | String? | Nombre del proveedor |
|
|
| subtotal | Float | Subtotal |
|
|
| iva | Float | IVA |
|
|
| total | Float | Total |
|
|
| fechaEmision | DateTime | Fecha de emisión |
|
|
| fechaVencimiento | DateTime? | Fecha de vencimiento |
|
|
| estado | EstadoFactura | Estado de pago |
|
|
| obraId | String | ID de la obra |
|
|
| createdAt | DateTime | Fecha de creación |
|
|
| updatedAt | DateTime | Fecha de actualización |
|
|
|
|
**Enum TipoFactura:**
|
|
- `EMITIDA` - Factura a cliente
|
|
- `RECIBIDA` - Factura de proveedor
|
|
|
|
**Enum EstadoFactura:**
|
|
- `PENDIENTE` - Pendiente de pago
|
|
- `PAGADA` - Pagada
|
|
- `VENCIDA` - Vencida
|
|
- `CANCELADA` - Cancelada
|
|
|
|
**Relaciones:**
|
|
- `obra` → Obra (N:1)
|
|
|
|
---
|
|
|
|
### Material
|
|
|
|
Catálogo de materiales de construcción.
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| id | String | ID único (CUID) |
|
|
| codigo | String | Código único |
|
|
| nombre | String | Nombre del material |
|
|
| descripcion | String? | Descripción |
|
|
| unidad | UnidadMedida | Unidad de medida |
|
|
| precioUnitario | Float | Precio por unidad |
|
|
| stockMinimo | Float | Stock mínimo para alertas |
|
|
| stockActual | Float | Stock actual (default: 0) |
|
|
| ubicacion | String? | Ubicación en bodega |
|
|
| activo | Boolean | Estado activo (default: true) |
|
|
| empresaId | String | ID de la empresa |
|
|
| createdAt | DateTime | Fecha de creación |
|
|
| updatedAt | DateTime | Fecha de actualización |
|
|
|
|
**Enum UnidadMedida:**
|
|
- `PIEZA` - Pieza
|
|
- `METRO` - Metro lineal
|
|
- `METRO_CUADRADO` - Metro cuadrado
|
|
- `METRO_CUBICO` - Metro cúbico
|
|
- `KILOGRAMO` - Kilogramo
|
|
- `LITRO` - Litro
|
|
- `BOLSA` - Bolsa
|
|
- `BULTO` - Bulto
|
|
- `ROLLO` - Rollo
|
|
- `CAJA` - Caja
|
|
- `UNIDAD` - Unidad
|
|
|
|
**Relaciones:**
|
|
- `empresa` → Empresa (N:1)
|
|
- `movimientos` → MovimientoInventario[] (1:N)
|
|
|
|
**Índice único:** `@@unique([codigo, empresaId])`
|
|
|
|
---
|
|
|
|
### MovimientoInventario
|
|
|
|
Registro de movimientos de inventario.
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| id | String | ID único (CUID) |
|
|
| tipo | TipoMovimiento | Tipo de movimiento |
|
|
| cantidad | Float | Cantidad |
|
|
| motivo | String? | Motivo/descripción |
|
|
| materialId | String | ID del material |
|
|
| obraId | String? | ID de la obra (opcional) |
|
|
| createdAt | DateTime | Fecha de creación |
|
|
|
|
**Enum TipoMovimiento:**
|
|
- `ENTRADA` - Entrada de material
|
|
- `SALIDA` - Salida de material
|
|
- `AJUSTE` - Ajuste de inventario
|
|
|
|
**Relaciones:**
|
|
- `material` → Material (N:1)
|
|
- `obra` → Obra (N:1, opcional)
|
|
|
|
---
|
|
|
|
### Empleado
|
|
|
|
Personal de la empresa.
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| id | String | ID único (CUID) |
|
|
| codigo | String | Código de empleado |
|
|
| nombre | String | Nombre |
|
|
| apellido | String | Apellido |
|
|
| curp | String? | CURP |
|
|
| rfc | String? | RFC |
|
|
| telefono | String? | Teléfono |
|
|
| email | String? | Email |
|
|
| puesto | String | Puesto/cargo |
|
|
| salarioDiario | Float | Salario diario |
|
|
| fechaIngreso | DateTime | Fecha de ingreso |
|
|
| activo | Boolean | Estado activo (default: true) |
|
|
| empresaId | String | ID de la empresa |
|
|
| createdAt | DateTime | Fecha de creación |
|
|
| updatedAt | DateTime | Fecha de actualización |
|
|
|
|
**Relaciones:**
|
|
- `empresa` → Empresa (N:1)
|
|
- `obrasAsignadas` → EmpleadoObra[] (1:N)
|
|
- `jornadas` → JornadaLaboral[] (1:N)
|
|
|
|
---
|
|
|
|
### Subcontratista
|
|
|
|
Empresas subcontratadas.
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| id | String | ID único (CUID) |
|
|
| nombre | String | Nombre/razón social |
|
|
| rfc | String? | RFC |
|
|
| contacto | String? | Persona de contacto |
|
|
| telefono | String? | Teléfono |
|
|
| email | String? | Email |
|
|
| especialidad | String | Especialidad/giro |
|
|
| activo | Boolean | Estado activo (default: true) |
|
|
| empresaId | String | ID de la empresa |
|
|
| createdAt | DateTime | Fecha de creación |
|
|
| updatedAt | DateTime | Fecha de actualización |
|
|
|
|
**Relaciones:**
|
|
- `empresa` → Empresa (N:1)
|
|
- `obrasAsignadas` → SubcontratistaObra[] (1:N)
|
|
|
|
---
|
|
|
|
## Tablas de Relación (N:M)
|
|
|
|
### EmpleadoObra
|
|
|
|
Asignación de empleados a obras.
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| id | String | ID único (CUID) |
|
|
| empleadoId | String | ID del empleado |
|
|
| obraId | String | ID de la obra |
|
|
| fechaAsignacion | DateTime | Fecha de asignación |
|
|
| fechaFin | DateTime? | Fecha de fin |
|
|
| activo | Boolean | Asignación activa |
|
|
|
|
### SubcontratistaObra
|
|
|
|
Asignación de subcontratistas a obras.
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| id | String | ID único (CUID) |
|
|
| subcontratistaId | String | ID del subcontratista |
|
|
| obraId | String | ID de la obra |
|
|
| descripcionTrabajo | String | Descripción del trabajo |
|
|
| montoContrato | Float | Monto del contrato |
|
|
| fechaInicio | DateTime | Fecha de inicio |
|
|
| fechaFin | DateTime? | Fecha de fin |
|
|
| estado | EstadoContrato | Estado del contrato |
|
|
|
|
---
|
|
|
|
## Comandos de Prisma
|
|
|
|
```bash
|
|
# Generar cliente Prisma
|
|
npx prisma generate
|
|
|
|
# Crear migración
|
|
npx prisma migrate dev --name descripcion_cambio
|
|
|
|
# Aplicar migraciones en producción
|
|
npx prisma migrate deploy
|
|
|
|
# Ver base de datos en navegador
|
|
npx prisma studio
|
|
|
|
# Ejecutar seed
|
|
npx prisma db seed
|
|
|
|
# Resetear base de datos (desarrollo)
|
|
npx prisma migrate reset
|
|
```
|
|
|
|
## Consideraciones de Seguridad
|
|
|
|
1. **Multi-tenant**: Todas las queries filtran por `empresaId` del usuario autenticado
|
|
2. **Índices**: Se han creado índices en campos frecuentemente consultados
|
|
3. **Cascade**: Las eliminaciones en cascada están configuradas para mantener integridad
|
|
4. **Soft delete**: Los registros importantes usan campo `activo` en lugar de eliminación física
|