# API Creación OT - Documentación Técnica

**Versión:** 1.0.0 | **Stack:** Node.js + Express + MySQL

---

## Arquitectura

```
Cliente HTTP → Node.js API (puerto 3000) → MySQL Stored Procedure → Tablas (OT, Clientes, Vehiculos, OT_Vehiculos)
```

**Flujo:**
1. Validación de entrada (RUT, email, campos requeridos)
2. Verificación de existencia de técnico
3. Llamada a procedimiento almacenado `prc_api_create_OT`
4. El procedimiento realiza:
   - UPSERT de cliente (INSERT si no existe, UPDATE si existe)
   - INSERT de OT con mapeo de GPS provider y tipo de servicio
   - UPSERT de vehículos
   - INSERT de relaciones en OT_Vehiculos
5. Respuesta con ID de OT creada

---

## Endpoints

### Health Check
```http
GET /api/health
```

**Response:**
```json
{ "status": "ok", "timestamp": "2025-12-29T20:00:00.000Z" }
```

---

### Crear OT
```http
POST /api/ot/create
Content-Type: application/json
```

**Request Body:**
```json
{
  "cliente": {
    "rut": "12345678-5",
    "nombre": "Cliente Test",
    "direccion": "Av. Test 123",
    "comuna": "Santiago",
    "telefono": "+56912345678",
    "email": "test@cartec.cl"
  },
  "tecnico": {
    "rut": "11111111-1"
  },
  "servicio": {
    "presGPS": "gpsimple|entel|tattersall|cemin|carflex",
    "tiposerv": "instalacion_gps|visita_tecnica|desinstalacion_gps",
    "taller_install": "cartec|servitattersall"
  },
  "vehiculos": [
    {
      "patente": "ABCD12",
      "marca": "Toyota",
      "modelo": "Corolla",
      "color": "Blanco",
      "anio": 2021
    }
  ]
}
```

**Success Response (201):**
```json
{
  "success": 1,
  "message": "OT creada correctamente ID: 1656 Vehiculos: 1",
  "data": {
    "id_ot": 1656,
    "rut_cliente": "12345678-5",
    "rut_tecnico": "11111111-1",
    "vehiculos_procesados": 1
  }
}
```

**Error Responses:**
- `400` - Validación fallida, RUT inválido
- `404` - Técnico no existe
- `500` - Error de procedimiento almacenado

---

## Parámetros de Entrada

### Campo `cliente`
| Campo | Tipo | Validación |
|-------|------|------------|
| `rut` | string | RUT chileno con dígito verificador (módulo 11) |
| `nombre` | string | Requerido, no vacío |
| `direccion` | string | Requerido |
| `comuna` | string | Requerido |
| `telefono` | string | Requerido |
| `email` | string | Formato email válido |

### Campo `tecnico`
| Campo | Tipo | Validación |
|-------|------|------------|
| `rut` | string | Debe existir en tabla `Tecnicos` |

### Campo `servicio`
| Campo | Tipo | Valores Permitidos |
|-------|------|-------------------|
| `presGPS` | string | `gpsimple`, `entel`, `tattersall`, `cemin`, `carflex` |
| `tiposerv` | string | `instalacion_gps`, `visita_tecnica`, `desinstalacion_gps` |
| `taller_install` | string | `cartec`, `servitattersall` |

### Campo `vehiculos[]`
| Campo | Tipo | Validación |
|-------|------|------------|
| `patente` | string | Requerido, convertido a UPPERCASE |
| `marca` | string | Requerido |
| `modelo` | string | Requerido |
| `color` | string | Opcional, default: "NO INFORMADO" |
| `anio` | integer | Rango: 1900 - año_actual+1 |

---

## Mapeo de Datos

### GPS Provider → Empresa + Logo
```javascript
{
  'gpsimple': { empresa: 'gpsimple', logo: 'https://media.recuperauto.cl/Media/Cartec/gpsimple-logo.png' },
  'entel': { empresa: 'entel', logo: 'https://media.recuperauto.cl/Media/Cartec/follow-logo.png' },
  'tattersall': { empresa: 'tattersall', logo: 'https://media.recuperauto.cl/Media/Cartec/tattersall.png' },
  'cemin': { empresa: 'cemin', logo: 'https://media.recuperauto.cl/Media/Cartec/cemin.png' },
  'carflex': { empresa: 'carflex', logo: 'https://media.recuperauto.cl/Media/Cartec/carflex.png' }
}
```

### Tipo Servicio → Motivo
```javascript
{
  'instalacion_gps': {
    'gpsimple': 'Instalación GPS',
    'entel': 'Instalación GPS FollowMyCar',
    'tattersall': 'Instalación GPS Tattersall',
    'cemin': 'Instalación GPS Cemin',
    'carflex': 'Instalación GPS CarFlex'
  },
  'visita_tecnica': 'Visita_tecnica GPS',
  'desinstalacion_gps': 'Desinstalación GPS'
}
```

### Taller → Logo
```javascript
{
  'cartec': { taller: 'domicilio', logo: 'https://media.recuperauto.cl/Media/Cartec/cartec-logo.png' },
  'servitattersall': { taller: 'servitattersall', logo: 'https://media.recuperauto.cl/Media/Cartec/servitattersall-logo.svg' }
}
```

---

## Procedimiento Almacenado

**Nombre:** `prc_api_create_OT`

**Signature:**
```sql
CALL prc_api_create_OT(
  IN  p_rut_cliente      VARCHAR(15),
  IN  p_nombre_cliente   VARCHAR(255),
  IN  p_direccion        VARCHAR(255),
  IN  p_comuna           VARCHAR(100),
  IN  p_telefono         VARCHAR(50),
  IN  p_email            VARCHAR(255),
  IN  p_rut_tecnico      VARCHAR(15),
  IN  p_presGPS          VARCHAR(50),
  IN  p_tiposerv         VARCHAR(50),
  IN  p_taller_install   VARCHAR(100),
  IN  p_vehiculos_json   JSON,
  OUT p_resultado        CHAR(1),      -- 'T' = éxito, 'F' = fallo
  OUT p_mensaje          VARCHAR(255),
  OUT p_id_ot            INT
)
```

**Tablas Modificadas:**
- `Clientes` - UPSERT por `rut_cliente`
- `OT` - INSERT
- `Vehiculos` - UPSERT por `patente`
- `OT_Vehiculos` - INSERT

---

## Instalación

### 1. Desplegar API
```bash
sudo mkdir -p /opt/cartec_api
cd /var/www/html/W_CartecInstalador/api_deployment
sudo cp -r * /opt/cartec_api/
cd /opt/cartec_api
```

### 2. Configurar
```bash
cp env.example .env
nano .env
```

```env
PORT=3000
NODE_ENV=production
DB_HOST=localhost
DB_PORT=3306
DB_USER=root
DB_PASSWORD=tu_password
DB_NAME=revisa
DB_CONNECTION_LIMIT=10
```

### 3. Instalar
```bash
npm install
mysql -u root -p revisa < sql/api_procedure.sql
```

### 4. Servicio
```bash
sudo cp config/cartec-api.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable cartec-api
sudo systemctl start cartec-api
```

---

## Comandos

### Gestión del Servicio
```bash
sudo systemctl start cartec-api      # Iniciar
sudo systemctl stop cartec-api       # Detener
sudo systemctl restart cartec-api    # Reiniciar
sudo systemctl status cartec-api     # Estado
```

### Logs
```bash
sudo journalctl -u cartec-api -f     # Seguir en tiempo real
sudo journalctl -u cartec-api -n 100 # Últimas 100 líneas
```

### Testing
```bash
# Health check
curl http://localhost:3000/api/health

# Crear OT
curl -X POST http://localhost:3000/api/ot/create \
  -H "Content-Type: application/json" \
  -d '{
    "cliente": {"rut": "12345678-5", "nombre": "Test", "direccion": "Av Test 123", "comuna": "Santiago", "telefono": "+56912345678", "email": "test@test.cl"},
    "tecnico": {"rut": "11111111-1"},
    "servicio": {"presGPS": "gpsimple", "tiposerv": "instalacion_gps", "taller_install": "cartec"},
    "vehiculos": [{"patente": "TEST01", "marca": "Toyota", "modelo": "Corolla", "color": "Blanco", "anio": 2021}]
  }'
```

### Verificación DB
```bash
# Ver última OT creada
mysql -u root -p revisa -e "SELECT * FROM OT ORDER BY id_ot DESC LIMIT 1\G"

# Ver vehículos de última OT
mysql -u root -p revisa -e "
SELECT ov.id_ot, ov.patente, v.marca, v.modelo 
FROM OT_Vehiculos ov 
JOIN Vehiculos v ON ov.patente = v.patente 
WHERE ov.id_ot = (SELECT MAX(id_ot) FROM OT);"

# Verificación completa
mysql -u root -p revisa < /opt/cartec_api/sql/verify_ot_data.sql
```

---

## Troubleshooting

### API no inicia
```bash
# Verificar logs
sudo journalctl -u cartec-api -n 50

# Verificar puerto
sudo netstat -tlnp | grep 3000

# Verificar proceso
ps aux | grep node
```

### Error en creación de OT
```bash
# Verificar procedimiento
mysql -u root -p revisa -e "SHOW PROCEDURE STATUS WHERE Name = 'prc_api_create_OT';"

# Verificar técnico existe
mysql -u root -p revisa -e "SELECT * FROM Tecnicos WHERE rut_tecnico = '11111111-1';"

# Reinstalar procedimiento
mysql -u root -p revisa < /opt/cartec_api/sql/api_procedure.sql
```

---

## Validación de RUT

**Algoritmo Módulo 11:**
```javascript
function validarRUT(rut) {
  const clean = rut.replace(/[^0-9Kk]/g, '');
  const body = clean.slice(0, -1);
  const dv = clean.slice(-1).toUpperCase();
  
  let sum = 0, mult = 2;
  for (let i = body.length - 1; i >= 0; i--) {
    sum += parseInt(body[i]) * mult;
    mult = mult < 7 ? mult + 1 : 2;
  }
  
  const expected = 11 - (sum % 11);
  const expectedDV = expected === 11 ? '0' : expected === 10 ? 'K' : expected.toString();
  
  return dv === expectedDV;
}
```

---

## Estructura de Archivos

```
/opt/cartec_api/
├── src/index.js                  # Código de la API
├── sql/api_procedure.sql         # Procedimiento (requerido)
├── .env                          # Configuración (crear desde env.example)
├── package.json
└── node_modules/
```

---

## Dependencias

```json
{
  "express": "^4.18.2",
  "mysql2": "^3.6.5"
}
```

**Requisitos:**
- Node.js >=12.0.0
- MySQL 8.0+
- Ubuntu 22.04 LTS (recomendado)

---

## Performance

- **Timeout:** 30s
- **Payload máximo:** 50MB
- **Connection pool:** 10 conexiones (configurable en `.env`)
- **Puerto:** 3000 (configurable)

---

## Integración



### cURL
```bash
curl -X POST http://localhost:3000/api/ot/create \
  -H "Content-Type: application/json" \
  -d @payload.json
```

---

## Notas Técnicas

1. **Cliente UPSERT:** Si el cliente existe (por RUT), se actualiza su información de contacto. Si no existe, se crea.

2. **Vehículo UPSERT:** Similar al cliente, se actualiza o crea según existencia de patente.

3. **Transacciones:** El procedimiento almacenado maneja transacciones. Si falla algún paso, hace ROLLBACK completo.

4. **Foreign Keys:** El procedimiento maneja automáticamente las restricciones de clave foránea al crear clientes/vehículos antes de la OT.

5. **Estado OT:** Siempre se crea con `estado_ot = 'pendiente'`.

6. **Fechas:** `fecha` y `fecha_serv` se establecen automáticamente a NOW() y CURDATE().

---

## Archivos Clave

| Archivo | Ubicación | Propósito |
|---------|-----------|-----------|
| API | `/opt/cartec_api/src/index.js` | Código fuente |
| Procedimiento | `/opt/cartec_api/sql/api_procedure.sql` | Lógica de BD |
| Servicio | `/etc/systemd/system/cartec-api.service` | Daemon |
| Config | `/opt/cartec_api/.env` | Credenciales |
| Logs | `journalctl -u cartec-api` | Debugging |

---

**Última actualización:** Diciembre 2025  
**Contacto:** Equipo de Desarrollo Cartec


---

## Acceso desde Red Local

### Configuración para 192.168.100.87

#### 1. Verificar que la API escucha en todas las interfaces

El API ya está configurado para escuchar en `0.0.0.0` (todas las interfaces), no requiere cambios.

#### 2. Abrir puerto en firewall

```bash
# Verificar estado del firewall
sudo ufw status

# Si está activo, abrir puerto 3000
sudo ufw allow 3000/tcp

# Verificar
sudo ufw status
```

#### 3. Verificar que el puerto está escuchando

```bash
# Ver que esté escuchando en 0.0.0.0:3000 (no en 127.0.0.1)
sudo netstat -tlnp | grep 3000
# Debe mostrar: 0.0.0.0:3000

# O con ss
sudo ss -tlnp | grep 3000
```

#### 4. Llamadas desde otros equipos en la red

**Desde cualquier máquina en 192.168.100.x:**

```bash
# Health check
curl http://192.168.100.87:3000/api/health

# Crear OT
curl -X POST http://192.168.100.87:3000/api/ot/create \
  -H "Content-Type: application/json" \
  -d '{
    "cliente": {
      "rut": "12345678-5",
      "nombre": "Cliente Red",
      "direccion": "Av. Test 123",
      "comuna": "Santiago",
      "telefono": "+56912345678",
      "email": "test@cartec.cl"
    },
    "tecnico": {"rut": "11111111-1"},
    "servicio": {
      "presGPS": "gpsimple",
      "tiposerv": "instalacion_gps",
      "taller_install": "cartec"
    },
    "vehiculos": [
      {
        "patente": "RED01",
        "marca": "Toyota",
        "modelo": "Corolla",
        "color": "Blanco",
        "anio": 2021
      }
    ]
  }'
```

#### 5. Integración desde otros servidores

**PHP:**
```php
$url = 'http://192.168.100.87:3000/api/ot/create';
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_POST => 1,
    CURLOPT_POSTFIELDS => json_encode($datos),
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_RETURNTRANSFER => true
]);
$response = json_decode(curl_exec($ch), true);
```

**JavaScript/Node.js:**
```javascript
const axios = require('axios');

const response = await axios.post('http://192.168.100.87:3000/api/ot/create', {
  cliente: { ... },
  tecnico: { ... },
  servicio: { ... },
  vehiculos: [ ... ]
});
```

**Python:**
```python
import requests
response = requests.post(
    'http://192.168.100.87:3000/api/ot/create',
    json=datos
)
```

#### 6. Troubleshooting Red

```bash
# Desde la máquina remota, verificar conectividad
ping 192.168.100.87

# Verificar si el puerto está abierto
telnet 192.168.100.87 3000
# o
nc -zv 192.168.100.87 3000

# Desde el servidor, verificar conexiones
sudo netstat -an | grep 3000
```

#### 7. Si la API solo escucha en localhost

Si `netstat` muestra `127.0.0.1:3000` en lugar de `0.0.0.0:3000`, editar `.env`:

```bash
nano /opt/cartec_api/.env
```

Cambiar o agregar:
```env
HOST=0.0.0.0  # Escuchar en todas las interfaces
PORT=3000
```

Reiniciar:
```bash
sudo systemctl restart cartec-api
```

#### 8. Configuración de proxy reverso (opcional)

Si deseas usar un nombre de dominio o HTTPS:

**Nginx:**
```nginx
server {
    listen 80;
    server_name api-cartec.local;

    location /api/ {
        proxy_pass http://localhost:3000/api/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
```

Luego acceder: `http://192.168.100.87/api/health`

---

## URLs de Acceso

| Origen | URL Base |
|--------|----------|
| Mismo servidor | `http://localhost:3000/api` |
| Red local (192.168.100.x) | `http://192.168.100.87:3000/api` |
| Con Nginx | `http://192.168.100.87/api` |

---


18736998-3
12345678-5 