Files
mexus-app/docs/DATABASE.md
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

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