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>
528 lines
10 KiB
Markdown
528 lines
10 KiB
Markdown
# Documentación de API - Mexus App
|
|
|
|
Esta documentación describe todos los endpoints disponibles en la API REST de Mexus App.
|
|
|
|
## Base URL
|
|
|
|
```
|
|
Desarrollo: http://localhost:3000/api
|
|
Producción: https://tu-dominio.com/api
|
|
```
|
|
|
|
## Autenticación
|
|
|
|
La API utiliza NextAuth.js para la autenticación. Las peticiones autenticadas requieren una cookie de sesión válida.
|
|
|
|
### Headers requeridos
|
|
|
|
```
|
|
Content-Type: application/json
|
|
Cookie: authjs.session-token=<token>
|
|
```
|
|
|
|
---
|
|
|
|
## Endpoints de Autenticación
|
|
|
|
### Obtener token CSRF
|
|
|
|
```http
|
|
GET /api/auth/csrf
|
|
```
|
|
|
|
**Respuesta exitosa (200):**
|
|
```json
|
|
{
|
|
"csrfToken": "0ee47c595b90ef7b0356521f5354695cfe22a5797fa30cecba0a279ce28a9719"
|
|
}
|
|
```
|
|
|
|
### Iniciar sesión
|
|
|
|
```http
|
|
POST /api/auth/callback/credentials
|
|
Content-Type: application/x-www-form-urlencoded
|
|
```
|
|
|
|
**Parámetros:**
|
|
| Campo | Tipo | Requerido | Descripción |
|
|
|-------|------|-----------|-------------|
|
|
| csrfToken | string | Sí | Token CSRF obtenido previamente |
|
|
| email | string | Sí | Correo electrónico del usuario |
|
|
| password | string | Sí | Contraseña del usuario |
|
|
|
|
**Respuesta exitosa (302):** Redirección a dashboard con cookie de sesión
|
|
|
|
### Obtener sesión actual
|
|
|
|
```http
|
|
GET /api/auth/session
|
|
```
|
|
|
|
**Respuesta exitosa (200):**
|
|
```json
|
|
{
|
|
"user": {
|
|
"id": "cmkk6tf3y00025x5stdh7x2f9",
|
|
"email": "admin@demo.com",
|
|
"nombre": "Admin",
|
|
"apellido": "Demo",
|
|
"role": "ADMIN",
|
|
"empresaId": "cmkk6ter000005x5smacuuh5x"
|
|
},
|
|
"expires": "2026-01-20T00:25:19.994Z"
|
|
}
|
|
```
|
|
|
|
### Cerrar sesión
|
|
|
|
```http
|
|
POST /api/auth/signout
|
|
```
|
|
|
|
---
|
|
|
|
## Endpoints de Obras
|
|
|
|
### Listar obras
|
|
|
|
```http
|
|
GET /api/obras
|
|
```
|
|
|
|
**Respuesta exitosa (200):**
|
|
```json
|
|
[
|
|
{
|
|
"id": "cmkk6tf4900085x5semza5bzu",
|
|
"codigo": "OBR-2024-001",
|
|
"nombre": "Edificio Residencial Aurora",
|
|
"descripcion": "Construcción de edificio de 8 niveles",
|
|
"cliente": "Inmobiliaria del Norte S.A.",
|
|
"ubicacion": "Col. Centro, Ciudad",
|
|
"estado": "EN_PROGRESO",
|
|
"presupuestoTotal": 15000000,
|
|
"fechaInicio": "2024-01-15T00:00:00.000Z",
|
|
"fechaFinEstimada": "2025-06-30T00:00:00.000Z",
|
|
"avanceGeneral": 35,
|
|
"_count": {
|
|
"fases": 4,
|
|
"gastos": 12
|
|
}
|
|
}
|
|
]
|
|
```
|
|
|
|
### Crear obra
|
|
|
|
```http
|
|
POST /api/obras
|
|
Content-Type: application/json
|
|
```
|
|
|
|
**Body:**
|
|
```json
|
|
{
|
|
"codigo": "OBR-2024-002",
|
|
"nombre": "Casa Habitación López",
|
|
"descripcion": "Construcción de casa de 2 niveles",
|
|
"cliente": "Juan López García",
|
|
"ubicacion": "Fracc. Las Palmas #123",
|
|
"presupuestoTotal": 2500000,
|
|
"fechaInicio": "2024-03-01",
|
|
"fechaFinEstimada": "2024-09-30"
|
|
}
|
|
```
|
|
|
|
**Campos:**
|
|
| Campo | Tipo | Requerido | Descripción |
|
|
|-------|------|-----------|-------------|
|
|
| codigo | string | Sí | Código único de la obra |
|
|
| nombre | string | Sí | Nombre del proyecto |
|
|
| descripcion | string | No | Descripción detallada |
|
|
| cliente | string | Sí | Nombre del cliente |
|
|
| ubicacion | string | No | Dirección o ubicación |
|
|
| presupuestoTotal | number | Sí | Presupuesto en MXN |
|
|
| fechaInicio | date | Sí | Fecha de inicio |
|
|
| fechaFinEstimada | date | No | Fecha estimada de finalización |
|
|
|
|
**Respuesta exitosa (201):**
|
|
```json
|
|
{
|
|
"id": "cmkk7tf4900085x5semza5bzu",
|
|
"codigo": "OBR-2024-002",
|
|
"nombre": "Casa Habitación López",
|
|
"estado": "PLANEACION",
|
|
"avanceGeneral": 0,
|
|
"createdAt": "2024-01-20T10:30:00.000Z"
|
|
}
|
|
```
|
|
|
|
### Obtener obra por ID
|
|
|
|
```http
|
|
GET /api/obras/{id}
|
|
```
|
|
|
|
**Parámetros de URL:**
|
|
| Parámetro | Tipo | Descripción |
|
|
|-----------|------|-------------|
|
|
| id | string | ID de la obra |
|
|
|
|
**Respuesta exitosa (200):**
|
|
```json
|
|
{
|
|
"id": "cmkk6tf4900085x5semza5bzu",
|
|
"codigo": "OBR-2024-001",
|
|
"nombre": "Edificio Residencial Aurora",
|
|
"descripcion": "Construcción de edificio de 8 niveles",
|
|
"estado": "EN_PROGRESO",
|
|
"presupuestoTotal": 15000000,
|
|
"avanceGeneral": 35,
|
|
"fases": [
|
|
{
|
|
"id": "fase1",
|
|
"nombre": "Cimentación",
|
|
"orden": 1,
|
|
"avance": 100,
|
|
"estado": "COMPLETADA"
|
|
}
|
|
],
|
|
"gastos": [
|
|
{
|
|
"id": "gasto1",
|
|
"concepto": "Compra de cemento",
|
|
"monto": 45000,
|
|
"estado": "APROBADO"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Actualizar obra
|
|
|
|
```http
|
|
PUT /api/obras/{id}
|
|
Content-Type: application/json
|
|
```
|
|
|
|
**Body:** (campos opcionales)
|
|
```json
|
|
{
|
|
"nombre": "Edificio Residencial Aurora - Fase 2",
|
|
"estado": "EN_PROGRESO",
|
|
"avanceGeneral": 45
|
|
}
|
|
```
|
|
|
|
**Respuesta exitosa (200):** Objeto obra actualizado
|
|
|
|
### Eliminar obra
|
|
|
|
```http
|
|
DELETE /api/obras/{id}
|
|
```
|
|
|
|
**Respuesta exitosa (200):**
|
|
```json
|
|
{
|
|
"message": "Obra eliminada exitosamente"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Endpoints de Gastos
|
|
|
|
### Listar gastos
|
|
|
|
```http
|
|
GET /api/gastos
|
|
```
|
|
|
|
**Query Parameters:**
|
|
| Parámetro | Tipo | Descripción |
|
|
|-----------|------|-------------|
|
|
| obraId | string | Filtrar por obra específica |
|
|
| estado | string | Filtrar por estado (PENDIENTE, APROBADO, RECHAZADO) |
|
|
|
|
**Respuesta exitosa (200):**
|
|
```json
|
|
[
|
|
{
|
|
"id": "cmkk6tf5r000k5x5sxwf04qji",
|
|
"concepto": "Compra de materiales",
|
|
"descripcion": "Cemento y varilla para cimentación",
|
|
"monto": 85000,
|
|
"categoria": "MATERIALES",
|
|
"estado": "APROBADO",
|
|
"fecha": "2024-01-20T00:00:00.000Z",
|
|
"comprobante": "FAC-12345",
|
|
"obra": {
|
|
"id": "obra1",
|
|
"nombre": "Edificio Aurora"
|
|
},
|
|
"usuario": {
|
|
"nombre": "Juan",
|
|
"apellido": "Pérez"
|
|
}
|
|
}
|
|
]
|
|
```
|
|
|
|
### Crear gasto
|
|
|
|
```http
|
|
POST /api/gastos
|
|
Content-Type: application/json
|
|
```
|
|
|
|
**Body:**
|
|
```json
|
|
{
|
|
"concepto": "Pago de mano de obra",
|
|
"descripcion": "Pago semanal de albañiles",
|
|
"monto": 25000,
|
|
"categoria": "MANO_OBRA",
|
|
"fecha": "2024-01-20",
|
|
"obraId": "cmkk6tf4900085x5semza5bzu",
|
|
"comprobante": "REC-001"
|
|
}
|
|
```
|
|
|
|
**Campos:**
|
|
| Campo | Tipo | Requerido | Descripción |
|
|
|-------|------|-----------|-------------|
|
|
| concepto | string | Sí | Concepto del gasto |
|
|
| descripcion | string | No | Descripción detallada |
|
|
| monto | number | Sí | Monto en MXN |
|
|
| categoria | enum | Sí | MATERIALES, MANO_OBRA, SUBCONTRATO, EQUIPO, TRANSPORTE, ADMINISTRATIVO, OTROS |
|
|
| fecha | date | Sí | Fecha del gasto |
|
|
| obraId | string | Sí | ID de la obra asociada |
|
|
| comprobante | string | No | Número de factura/recibo |
|
|
|
|
**Respuesta exitosa (201):** Objeto gasto creado
|
|
|
|
### Aprobar gasto
|
|
|
|
```http
|
|
PATCH /api/gastos/{id}/aprobar
|
|
Content-Type: application/json
|
|
```
|
|
|
|
**Body:**
|
|
```json
|
|
{
|
|
"estado": "APROBADO"
|
|
}
|
|
```
|
|
|
|
**Valores permitidos para estado:** `APROBADO`, `RECHAZADO`
|
|
|
|
**Respuesta exitosa (200):** Objeto gasto actualizado
|
|
|
|
### Eliminar gasto
|
|
|
|
```http
|
|
DELETE /api/gastos/{id}
|
|
```
|
|
|
|
**Respuesta exitosa (200):**
|
|
```json
|
|
{
|
|
"message": "Gasto eliminado exitosamente"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Endpoints de Materiales
|
|
|
|
### Listar materiales
|
|
|
|
```http
|
|
GET /api/materiales
|
|
```
|
|
|
|
**Respuesta exitosa (200):**
|
|
```json
|
|
[
|
|
{
|
|
"id": "cmkk6tf6f000x5x5s413dejgf",
|
|
"codigo": "CEM-001",
|
|
"nombre": "Cemento Portland",
|
|
"descripcion": "Cemento gris tipo I",
|
|
"unidad": "BOLSA",
|
|
"precioUnitario": 180,
|
|
"stockMinimo": 100,
|
|
"stockActual": 250,
|
|
"ubicacion": "Bodega A",
|
|
"activo": true
|
|
}
|
|
]
|
|
```
|
|
|
|
### Crear material
|
|
|
|
```http
|
|
POST /api/materiales
|
|
Content-Type: application/json
|
|
```
|
|
|
|
**Body:**
|
|
```json
|
|
{
|
|
"codigo": "VAR-002",
|
|
"nombre": "Varilla corrugada 1/2",
|
|
"descripcion": "Varilla de acero corrugado",
|
|
"unidad": "PIEZA",
|
|
"precioUnitario": 180,
|
|
"stockMinimo": 200,
|
|
"ubicacion": "Bodega B"
|
|
}
|
|
```
|
|
|
|
**Campos:**
|
|
| Campo | Tipo | Requerido | Descripción |
|
|
|-------|------|-----------|-------------|
|
|
| codigo | string | Sí | Código único del material |
|
|
| nombre | string | Sí | Nombre del material |
|
|
| descripcion | string | No | Descripción |
|
|
| unidad | enum | Sí | PIEZA, METRO, METRO_CUADRADO, METRO_CUBICO, KILOGRAMO, LITRO, BOLSA, BULTO, ROLLO, CAJA, UNIDAD |
|
|
| precioUnitario | number | Sí | Precio por unidad |
|
|
| stockMinimo | number | No | Stock mínimo para alertas |
|
|
| ubicacion | string | No | Ubicación en bodega |
|
|
|
|
**Respuesta exitosa (201):** Objeto material creado
|
|
|
|
### Actualizar material
|
|
|
|
```http
|
|
PUT /api/materiales/{id}
|
|
Content-Type: application/json
|
|
```
|
|
|
|
**Body:** (campos opcionales)
|
|
```json
|
|
{
|
|
"precioUnitario": 195,
|
|
"stockMinimo": 150
|
|
}
|
|
```
|
|
|
|
### Eliminar material
|
|
|
|
```http
|
|
DELETE /api/materiales/{id}
|
|
```
|
|
|
|
### Registrar movimiento de inventario
|
|
|
|
```http
|
|
POST /api/materiales/movimiento
|
|
Content-Type: application/json
|
|
```
|
|
|
|
**Body:**
|
|
```json
|
|
{
|
|
"materialId": "cmkk6tf6f000x5x5s413dejgf",
|
|
"tipo": "SALIDA",
|
|
"cantidad": 50,
|
|
"motivo": "Envío a obra Edificio Aurora",
|
|
"obraId": "cmkk6tf4900085x5semza5bzu"
|
|
}
|
|
```
|
|
|
|
**Campos:**
|
|
| Campo | Tipo | Requerido | Descripción |
|
|
|-------|------|-----------|-------------|
|
|
| materialId | string | Sí | ID del material |
|
|
| tipo | enum | Sí | ENTRADA, SALIDA, AJUSTE |
|
|
| cantidad | number | Sí | Cantidad del movimiento |
|
|
| motivo | string | No | Razón del movimiento |
|
|
| obraId | string | No | Obra destino (para salidas) |
|
|
|
|
**Respuesta exitosa (201):**
|
|
```json
|
|
{
|
|
"id": "mov123",
|
|
"tipo": "SALIDA",
|
|
"cantidad": 50,
|
|
"motivo": "Envío a obra Edificio Aurora",
|
|
"materialId": "cmkk6tf6f000x5x5s413dejgf",
|
|
"obraId": "cmkk6tf4900085x5semza5bzu",
|
|
"createdAt": "2024-01-20T15:30:00.000Z"
|
|
}
|
|
```
|
|
|
|
**Nota:** El stock del material se actualiza automáticamente según el tipo de movimiento.
|
|
|
|
---
|
|
|
|
## Códigos de Error
|
|
|
|
| Código | Descripción |
|
|
|--------|-------------|
|
|
| 400 | Bad Request - Datos inválidos |
|
|
| 401 | Unauthorized - No autenticado |
|
|
| 403 | Forbidden - Sin permisos |
|
|
| 404 | Not Found - Recurso no encontrado |
|
|
| 500 | Internal Server Error |
|
|
|
|
**Formato de error:**
|
|
```json
|
|
{
|
|
"error": "Descripción del error"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Ejemplos con cURL
|
|
|
|
### Login y obtener materiales
|
|
|
|
```bash
|
|
# 1. Obtener CSRF token
|
|
CSRF=$(curl -s -c cookies.txt http://localhost:3000/api/auth/csrf | grep -oP '"csrfToken":"[^"]*"' | cut -d'"' -f4)
|
|
|
|
# 2. Login
|
|
curl -s -b cookies.txt -c cookies.txt \
|
|
-X POST "http://localhost:3000/api/auth/callback/credentials" \
|
|
-H "Content-Type: application/x-www-form-urlencoded" \
|
|
-d "csrfToken=$CSRF&email=admin@demo.com&password=admin123"
|
|
|
|
# 3. Obtener materiales
|
|
curl -s -b cookies.txt http://localhost:3000/api/materiales
|
|
```
|
|
|
|
### Crear un gasto
|
|
|
|
```bash
|
|
curl -X POST http://localhost:3000/api/gastos \
|
|
-b cookies.txt \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"concepto": "Compra de cemento",
|
|
"monto": 15000,
|
|
"categoria": "MATERIALES",
|
|
"fecha": "2024-01-20",
|
|
"obraId": "cmkk6tf4900085x5semza5bzu"
|
|
}'
|
|
```
|
|
|
|
### Registrar entrada de material
|
|
|
|
```bash
|
|
curl -X POST http://localhost:3000/api/materiales/movimiento \
|
|
-b cookies.txt \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"materialId": "cmkk6tf6f000x5x5s413dejgf",
|
|
"tipo": "ENTRADA",
|
|
"cantidad": 100,
|
|
"motivo": "Compra a proveedor"
|
|
}'
|
|
```
|