979 lines
16 KiB
Markdown
979 lines
16 KiB
Markdown
# API Reference - ERP Construccion
|
|
|
|
Referencia completa de endpoints REST.
|
|
|
|
**Base URL:** `http://localhost:3000/api/v1`
|
|
|
|
---
|
|
|
|
## Autenticacion
|
|
|
|
Todas las rutas (excepto login/register) requieren header:
|
|
|
|
```http
|
|
Authorization: Bearer <access_token>
|
|
```
|
|
|
|
---
|
|
|
|
## Auth Endpoints
|
|
|
|
### POST /auth/login
|
|
|
|
Autenticar usuario.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"email": "user@example.com",
|
|
"password": "securePassword123"
|
|
}
|
|
```
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"user": {
|
|
"id": "uuid",
|
|
"email": "user@example.com",
|
|
"firstName": "Juan",
|
|
"lastName": "Perez",
|
|
"role": "admin"
|
|
},
|
|
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
|
|
"refreshToken": "eyJhbGciOiJIUzI1NiIs...",
|
|
"expiresIn": 900
|
|
}
|
|
```
|
|
|
|
**Response 401:**
|
|
```json
|
|
{
|
|
"error": "Unauthorized",
|
|
"message": "Invalid credentials"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /auth/register
|
|
|
|
Registrar nuevo usuario.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"email": "nuevo@example.com",
|
|
"password": "securePassword123",
|
|
"firstName": "Maria",
|
|
"lastName": "Lopez",
|
|
"tenantId": "tenant-uuid"
|
|
}
|
|
```
|
|
|
|
**Response 201:**
|
|
```json
|
|
{
|
|
"user": {
|
|
"id": "new-uuid",
|
|
"email": "nuevo@example.com",
|
|
"firstName": "Maria",
|
|
"lastName": "Lopez",
|
|
"role": "viewer"
|
|
},
|
|
"accessToken": "...",
|
|
"refreshToken": "...",
|
|
"expiresIn": 900
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /auth/refresh
|
|
|
|
Renovar access token.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"refreshToken": "eyJhbGciOiJIUzI1NiIs..."
|
|
}
|
|
```
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"accessToken": "new-access-token",
|
|
"refreshToken": "new-refresh-token",
|
|
"expiresIn": 900
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /auth/logout
|
|
|
|
Revocar refresh token.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"refreshToken": "eyJhbGciOiJIUzI1NiIs..."
|
|
}
|
|
```
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /auth/change-password
|
|
|
|
Cambiar password del usuario autenticado.
|
|
|
|
**Headers:**
|
|
```
|
|
Authorization: Bearer <access_token>
|
|
```
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"currentPassword": "oldPassword123",
|
|
"newPassword": "newSecurePassword456"
|
|
}
|
|
```
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Conceptos Endpoints
|
|
|
|
### GET /conceptos
|
|
|
|
Listar conceptos con paginacion.
|
|
|
|
**Query Parameters:**
|
|
| Param | Tipo | Default | Descripcion |
|
|
|-------|------|---------|-------------|
|
|
| `page` | number | 1 | Pagina actual |
|
|
| `limit` | number | 20 | Items por pagina |
|
|
| `search` | string | - | Buscar por codigo/nombre |
|
|
| `parentId` | uuid | - | Filtrar por padre |
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"data": [
|
|
{
|
|
"id": "uuid-1",
|
|
"code": "01",
|
|
"name": "Preliminares",
|
|
"unit": "PZA",
|
|
"unitPrice": 0,
|
|
"level": 0,
|
|
"path": "01",
|
|
"isActive": true
|
|
},
|
|
{
|
|
"id": "uuid-2",
|
|
"code": "01.01",
|
|
"name": "Trazo y nivelacion",
|
|
"unit": "M2",
|
|
"unitPrice": 25.50,
|
|
"level": 1,
|
|
"path": "01/01",
|
|
"parentId": "uuid-1",
|
|
"isActive": true
|
|
}
|
|
],
|
|
"total": 150,
|
|
"page": 1,
|
|
"limit": 20,
|
|
"totalPages": 8
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /conceptos/:id
|
|
|
|
Obtener concepto por ID.
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"id": "uuid-1",
|
|
"code": "01",
|
|
"name": "Preliminares",
|
|
"description": "Trabajos preliminares de obra",
|
|
"unit": "PZA",
|
|
"unitPrice": 0,
|
|
"level": 0,
|
|
"path": "01",
|
|
"isActive": true,
|
|
"createdAt": "2025-01-01T00:00:00Z",
|
|
"updatedAt": "2025-01-01T00:00:00Z"
|
|
}
|
|
```
|
|
|
|
**Response 404:**
|
|
```json
|
|
{
|
|
"error": "Not Found",
|
|
"message": "Concepto not found"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /conceptos
|
|
|
|
Crear nuevo concepto.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"code": "01.02",
|
|
"name": "Demoliciones",
|
|
"description": "Trabajos de demolicion",
|
|
"unit": "M3",
|
|
"unitPrice": 150.00,
|
|
"parentId": "uuid-1"
|
|
}
|
|
```
|
|
|
|
**Response 201:**
|
|
```json
|
|
{
|
|
"id": "new-uuid",
|
|
"code": "01.02",
|
|
"name": "Demoliciones",
|
|
"description": "Trabajos de demolicion",
|
|
"unit": "M3",
|
|
"unitPrice": 150.00,
|
|
"level": 1,
|
|
"path": "01/02",
|
|
"parentId": "uuid-1",
|
|
"isActive": true,
|
|
"createdAt": "2025-01-15T10:30:00Z"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /conceptos/tree
|
|
|
|
Obtener arbol de conceptos.
|
|
|
|
**Query Parameters:**
|
|
| Param | Tipo | Descripcion |
|
|
|-------|------|-------------|
|
|
| `rootId` | uuid | ID del nodo raiz (opcional) |
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"data": [
|
|
{
|
|
"id": "uuid-1",
|
|
"code": "01",
|
|
"name": "Preliminares",
|
|
"level": 0,
|
|
"children": [
|
|
{
|
|
"id": "uuid-2",
|
|
"code": "01.01",
|
|
"name": "Trazo y nivelacion",
|
|
"level": 1,
|
|
"children": []
|
|
},
|
|
{
|
|
"id": "uuid-3",
|
|
"code": "01.02",
|
|
"name": "Demoliciones",
|
|
"level": 1,
|
|
"children": []
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Presupuestos Endpoints
|
|
|
|
### GET /presupuestos
|
|
|
|
Listar presupuestos.
|
|
|
|
**Query Parameters:**
|
|
| Param | Tipo | Descripcion |
|
|
|-------|------|-------------|
|
|
| `fraccionamientoId` | uuid | Filtrar por proyecto |
|
|
| `status` | string | draft/submitted/approved |
|
|
| `page` | number | Pagina |
|
|
| `limit` | number | Items por pagina |
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"data": [
|
|
{
|
|
"id": "uuid-1",
|
|
"code": "PPTO-2025-001",
|
|
"name": "Presupuesto Casa Tipo A",
|
|
"version": 1,
|
|
"status": "approved",
|
|
"totalAmount": 1500000.00,
|
|
"fraccionamiento": {
|
|
"id": "frac-uuid",
|
|
"name": "Residencial Los Pinos"
|
|
},
|
|
"approvedAt": "2025-01-10T15:00:00Z"
|
|
}
|
|
],
|
|
"total": 25,
|
|
"page": 1,
|
|
"limit": 20,
|
|
"totalPages": 2
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /presupuestos/:id
|
|
|
|
Obtener presupuesto con partidas.
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"id": "uuid-1",
|
|
"code": "PPTO-2025-001",
|
|
"name": "Presupuesto Casa Tipo A",
|
|
"version": 1,
|
|
"status": "approved",
|
|
"totalAmount": 1500000.00,
|
|
"partidas": [
|
|
{
|
|
"id": "partida-1",
|
|
"concepto": {
|
|
"id": "concepto-uuid",
|
|
"code": "01.01",
|
|
"name": "Trazo y nivelacion",
|
|
"unit": "M2"
|
|
},
|
|
"quantity": 120.00,
|
|
"unitPrice": 25.50,
|
|
"totalAmount": 3060.00
|
|
}
|
|
],
|
|
"fraccionamiento": {
|
|
"id": "frac-uuid",
|
|
"name": "Residencial Los Pinos"
|
|
},
|
|
"createdAt": "2025-01-01T00:00:00Z",
|
|
"approvedAt": "2025-01-10T15:00:00Z",
|
|
"approvedBy": {
|
|
"id": "user-uuid",
|
|
"firstName": "Juan",
|
|
"lastName": "Director"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /presupuestos
|
|
|
|
Crear presupuesto.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"code": "PPTO-2025-002",
|
|
"name": "Presupuesto Casa Tipo B",
|
|
"fraccionamientoId": "frac-uuid"
|
|
}
|
|
```
|
|
|
|
**Response 201:**
|
|
```json
|
|
{
|
|
"id": "new-uuid",
|
|
"code": "PPTO-2025-002",
|
|
"name": "Presupuesto Casa Tipo B",
|
|
"version": 1,
|
|
"status": "draft",
|
|
"totalAmount": 0,
|
|
"fraccionamientoId": "frac-uuid",
|
|
"createdAt": "2025-01-15T10:30:00Z"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /presupuestos/:id/partidas
|
|
|
|
Agregar partida a presupuesto.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"conceptoId": "concepto-uuid",
|
|
"quantity": 100.00,
|
|
"unitPrice": 25.50
|
|
}
|
|
```
|
|
|
|
**Response 201:**
|
|
```json
|
|
{
|
|
"id": "partida-uuid",
|
|
"presupuestoId": "presupuesto-uuid",
|
|
"conceptoId": "concepto-uuid",
|
|
"quantity": 100.00,
|
|
"unitPrice": 25.50,
|
|
"totalAmount": 2550.00
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /presupuestos/:id/approve
|
|
|
|
Aprobar presupuesto.
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"id": "presupuesto-uuid",
|
|
"status": "approved",
|
|
"approvedAt": "2025-01-15T12:00:00Z",
|
|
"approvedById": "user-uuid"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /presupuestos/:id/version
|
|
|
|
Crear nueva version del presupuesto.
|
|
|
|
**Response 201:**
|
|
```json
|
|
{
|
|
"id": "new-version-uuid",
|
|
"code": "PPTO-2025-001",
|
|
"name": "Presupuesto Casa Tipo A",
|
|
"version": 2,
|
|
"status": "draft",
|
|
"totalAmount": 1500000.00,
|
|
"partidas": [...]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Avances Endpoints
|
|
|
|
### GET /avances
|
|
|
|
Listar avances de obra.
|
|
|
|
**Query Parameters:**
|
|
| Param | Tipo | Descripcion |
|
|
|-------|------|-------------|
|
|
| `loteId` | uuid | Filtrar por lote |
|
|
| `departamentoId` | uuid | Filtrar por departamento |
|
|
| `status` | string | captured/reviewed/approved/rejected |
|
|
| `dateFrom` | date | Fecha desde |
|
|
| `dateTo` | date | Fecha hasta |
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"data": [
|
|
{
|
|
"id": "avance-uuid",
|
|
"lote": {
|
|
"id": "lote-uuid",
|
|
"number": "L-001"
|
|
},
|
|
"concepto": {
|
|
"id": "concepto-uuid",
|
|
"code": "02.01",
|
|
"name": "Cimentacion",
|
|
"unit": "M3"
|
|
},
|
|
"quantity": 15.50,
|
|
"progressDate": "2025-01-15",
|
|
"status": "approved",
|
|
"capturedBy": {
|
|
"firstName": "Pedro",
|
|
"lastName": "Residente"
|
|
}
|
|
}
|
|
],
|
|
"total": 150,
|
|
"page": 1,
|
|
"limit": 20,
|
|
"totalPages": 8
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /avances
|
|
|
|
Registrar avance de obra.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"loteId": "lote-uuid",
|
|
"conceptoId": "concepto-uuid",
|
|
"quantity": 15.50,
|
|
"progressDate": "2025-01-15",
|
|
"notes": "Cimentacion completada"
|
|
}
|
|
```
|
|
|
|
**Response 201:**
|
|
```json
|
|
{
|
|
"id": "new-avance-uuid",
|
|
"loteId": "lote-uuid",
|
|
"conceptoId": "concepto-uuid",
|
|
"quantity": 15.50,
|
|
"progressDate": "2025-01-15",
|
|
"status": "captured",
|
|
"capturedById": "user-uuid",
|
|
"notes": "Cimentacion completada",
|
|
"createdAt": "2025-01-15T14:30:00Z"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /avances/:id/fotos
|
|
|
|
Agregar foto a avance.
|
|
|
|
**Request (multipart/form-data):**
|
|
```
|
|
file: <archivo imagen>
|
|
description: "Vista frontal de cimentacion"
|
|
latitude: 20.123456
|
|
longitude: -99.654321
|
|
```
|
|
|
|
**Response 201:**
|
|
```json
|
|
{
|
|
"id": "foto-uuid",
|
|
"avanceObraId": "avance-uuid",
|
|
"fileName": "IMG_20250115_143000.jpg",
|
|
"filePath": "/uploads/avances/2025/01/IMG_20250115_143000.jpg",
|
|
"fileSize": 2048576,
|
|
"mimeType": "image/jpeg",
|
|
"latitude": 20.123456,
|
|
"longitude": -99.654321,
|
|
"description": "Vista frontal de cimentacion",
|
|
"takenAt": "2025-01-15T14:30:00Z"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /avances/:id/review
|
|
|
|
Revisar avance (workflow).
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"id": "avance-uuid",
|
|
"status": "reviewed",
|
|
"reviewedAt": "2025-01-15T16:00:00Z",
|
|
"reviewedById": "supervisor-uuid"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /avances/:id/approve
|
|
|
|
Aprobar avance (workflow).
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"id": "avance-uuid",
|
|
"status": "approved",
|
|
"approvedAt": "2025-01-15T17:00:00Z",
|
|
"approvedById": "manager-uuid"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /avances/:id/reject
|
|
|
|
Rechazar avance (workflow).
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"reason": "Cantidad incorrecta, verificar medicion"
|
|
}
|
|
```
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"id": "avance-uuid",
|
|
"status": "rejected",
|
|
"rejectedAt": "2025-01-15T16:30:00Z",
|
|
"rejectedById": "supervisor-uuid",
|
|
"rejectionReason": "Cantidad incorrecta, verificar medicion"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Bitacora Endpoints
|
|
|
|
### GET /bitacora/:fraccionamientoId
|
|
|
|
Obtener entradas de bitacora.
|
|
|
|
**Query Parameters:**
|
|
| Param | Tipo | Descripcion |
|
|
|-------|------|-------------|
|
|
| `dateFrom` | date | Fecha desde |
|
|
| `dateTo` | date | Fecha hasta |
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"data": [
|
|
{
|
|
"id": "bitacora-uuid",
|
|
"entryNumber": 125,
|
|
"entryDate": "2025-01-15",
|
|
"weather": "Soleado",
|
|
"temperature": 28.5,
|
|
"workersCount": 45,
|
|
"activities": "Colado de cimentacion lotes 15-20",
|
|
"incidents": "Ninguno",
|
|
"observations": "Se requiere mas cemento para manana",
|
|
"createdBy": {
|
|
"firstName": "Pedro",
|
|
"lastName": "Residente"
|
|
}
|
|
}
|
|
],
|
|
"total": 125,
|
|
"page": 1,
|
|
"limit": 20,
|
|
"totalPages": 7
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /bitacora
|
|
|
|
Crear entrada de bitacora.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"fraccionamientoId": "frac-uuid",
|
|
"entryDate": "2025-01-15",
|
|
"weather": "Soleado",
|
|
"temperature": 28.5,
|
|
"workersCount": 45,
|
|
"activities": "Colado de cimentacion lotes 15-20",
|
|
"incidents": "Ninguno",
|
|
"observations": "Se requiere mas cemento para manana"
|
|
}
|
|
```
|
|
|
|
**Response 201:**
|
|
```json
|
|
{
|
|
"id": "new-bitacora-uuid",
|
|
"entryNumber": 126,
|
|
"entryDate": "2025-01-15",
|
|
"weather": "Soleado",
|
|
"temperature": 28.5,
|
|
"workersCount": 45,
|
|
"activities": "Colado de cimentacion lotes 15-20",
|
|
"createdById": "user-uuid",
|
|
"createdAt": "2025-01-15T18:00:00Z"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Estimaciones Endpoints
|
|
|
|
### GET /estimaciones
|
|
|
|
Listar estimaciones.
|
|
|
|
**Query Parameters:**
|
|
| Param | Tipo | Descripcion |
|
|
|-------|------|-------------|
|
|
| `contratoId` | uuid | Filtrar por contrato |
|
|
| `status` | string | draft/submitted/reviewed/approved/rejected |
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"data": [
|
|
{
|
|
"id": "est-uuid",
|
|
"number": 5,
|
|
"periodStart": "2025-01-01",
|
|
"periodEnd": "2025-01-15",
|
|
"status": "approved",
|
|
"subtotal": 500000.00,
|
|
"iva": 80000.00,
|
|
"retentions": 25000.00,
|
|
"amortization": 10000.00,
|
|
"totalAmount": 545000.00,
|
|
"contrato": {
|
|
"id": "contrato-uuid",
|
|
"number": "CTR-2025-001"
|
|
}
|
|
}
|
|
],
|
|
"total": 5,
|
|
"page": 1,
|
|
"limit": 20,
|
|
"totalPages": 1
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /estimaciones/:id
|
|
|
|
Obtener estimacion con detalles.
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"id": "est-uuid",
|
|
"number": 5,
|
|
"periodStart": "2025-01-01",
|
|
"periodEnd": "2025-01-15",
|
|
"status": "approved",
|
|
"subtotal": 500000.00,
|
|
"iva": 80000.00,
|
|
"retentions": 25000.00,
|
|
"amortization": 10000.00,
|
|
"totalAmount": 545000.00,
|
|
"conceptos": [
|
|
{
|
|
"id": "est-concepto-uuid",
|
|
"concepto": {
|
|
"code": "02.01",
|
|
"name": "Cimentacion",
|
|
"unit": "M3"
|
|
},
|
|
"contractQuantity": 1000.00,
|
|
"previousQuantity": 400.00,
|
|
"currentQuantity": 150.00,
|
|
"accumulatedQuantity": 550.00,
|
|
"pendingQuantity": 450.00,
|
|
"unitPrice": 1200.00,
|
|
"currentAmount": 180000.00,
|
|
"accumulatedAmount": 660000.00,
|
|
"generadores": [
|
|
{
|
|
"description": "Lotes 15-20",
|
|
"length": 10.00,
|
|
"width": 5.00,
|
|
"height": 0.30,
|
|
"quantity": 6,
|
|
"partial": 90.00
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"workflow": [
|
|
{
|
|
"fromStatus": "draft",
|
|
"toStatus": "submitted",
|
|
"changedAt": "2025-01-16T10:00:00Z",
|
|
"changedBy": {
|
|
"firstName": "Pedro",
|
|
"lastName": "Residente"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /estimaciones
|
|
|
|
Crear estimacion.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"contratoId": "contrato-uuid",
|
|
"periodStart": "2025-01-16",
|
|
"periodEnd": "2025-01-31"
|
|
}
|
|
```
|
|
|
|
**Response 201:**
|
|
```json
|
|
{
|
|
"id": "new-est-uuid",
|
|
"number": 6,
|
|
"contratoId": "contrato-uuid",
|
|
"periodStart": "2025-01-16",
|
|
"periodEnd": "2025-01-31",
|
|
"status": "draft",
|
|
"subtotal": 0,
|
|
"totalAmount": 0,
|
|
"createdAt": "2025-01-16T09:00:00Z"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /estimaciones/:id/conceptos
|
|
|
|
Agregar concepto a estimacion.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"conceptoId": "concepto-uuid",
|
|
"contractQuantity": 1000.00,
|
|
"currentQuantity": 150.00,
|
|
"unitPrice": 1200.00
|
|
}
|
|
```
|
|
|
|
**Response 201:**
|
|
```json
|
|
{
|
|
"id": "new-est-concepto-uuid",
|
|
"estimacionId": "est-uuid",
|
|
"conceptoId": "concepto-uuid",
|
|
"contractQuantity": 1000.00,
|
|
"previousQuantity": 550.00,
|
|
"currentQuantity": 150.00,
|
|
"accumulatedQuantity": 700.00,
|
|
"pendingQuantity": 300.00,
|
|
"unitPrice": 1200.00,
|
|
"currentAmount": 180000.00,
|
|
"accumulatedAmount": 840000.00
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /estimaciones/:id/submit
|
|
|
|
Enviar estimacion para revision.
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"id": "est-uuid",
|
|
"status": "submitted",
|
|
"submittedAt": "2025-01-20T10:00:00Z",
|
|
"submittedById": "user-uuid"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /estimaciones/:id/approve
|
|
|
|
Aprobar estimacion.
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"id": "est-uuid",
|
|
"status": "approved",
|
|
"approvedAt": "2025-01-21T15:00:00Z",
|
|
"approvedById": "director-uuid"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Codigos de Error
|
|
|
|
| Codigo | Descripcion |
|
|
|--------|-------------|
|
|
| 400 | Bad Request - Datos invalidos |
|
|
| 401 | Unauthorized - Token invalido o expirado |
|
|
| 403 | Forbidden - Sin permisos |
|
|
| 404 | Not Found - Recurso no encontrado |
|
|
| 409 | Conflict - Conflicto (ej: duplicado) |
|
|
| 422 | Unprocessable Entity - Validacion fallida |
|
|
| 500 | Internal Server Error |
|
|
|
|
### Formato de Error
|
|
|
|
```json
|
|
{
|
|
"error": "Bad Request",
|
|
"message": "Validation failed",
|
|
"details": [
|
|
{
|
|
"field": "email",
|
|
"message": "Invalid email format"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Rate Limiting
|
|
|
|
| Tipo | Limite |
|
|
|------|--------|
|
|
| Login | 5 requests/min por IP |
|
|
| API General | 100 requests/min por usuario |
|
|
| Uploads | 10 requests/min por usuario |
|
|
|
|
**Headers de respuesta:**
|
|
```
|
|
X-RateLimit-Limit: 100
|
|
X-RateLimit-Remaining: 95
|
|
X-RateLimit-Reset: 1610000000
|
|
```
|
|
|
|
---
|
|
|
|
**Ultima actualizacion:** 2025-12-12
|