# Cartec OT Creation API - Documentation

## Base URL

```
http://localhost:3000/api
```

---

## Endpoints

### 1. Health Check

**GET** `/api/health`

Check if API is running.

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

---

### 2. Create OT

**POST** `/api/ot/create`

Create a new Orden de Trabajo (OT) with automatic client management and vehicle registration.

#### Request Headers

```
Content-Type: application/json
```

#### Request Body

```json
{
  "cliente": {
    "rut": "12345678-5",
    "nombre": "Juan Pérez García",
    "direccion": "Av. Providencia 1234",
    "comuna": "Providencia",
    "telefono": "+56912345678",
    "email": "juan.perez@example.com"
  },
  "tecnico": {
    "rut": "11111111-1"
  },
  "servicio": {
    "presGPS": "gpsimple",
    "tiposerv": "instalacion_gps",
    "taller_install": "cartec"
  },
  "vehiculos": [
    {
      "patente": "ABCD12",
      "marca": "Toyota",
      "modelo": "Corolla",
      "color": "Blanco",
      "anio": 2021
    },
    {
      "patente": "EFGH34",
      "marca": "Honda",
      "modelo": "Civic",
      "color": "Negro",
      "anio": 2022
    }
  ]
}
```

#### Field Descriptions

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `cliente.rut` | string | Yes | Chilean RUT (7-8 digits + verification digit) |
| `cliente.nombre` | string | Yes | Full client name |
| `cliente.direccion` | string | Yes | Installation address |
| `cliente.comuna` | string | Yes | Comuna (city district) |
| `cliente.telefono` | string | Yes | Contact phone number |
| `cliente.email` | string | Yes | Valid email address |
| `tecnico.rut` | string | Yes | Technician's RUT (must exist in database) |
| `servicio.presGPS` | string | Yes | GPS provider: `gpsimple`, `entel`, `tattersall`, `cemin`, `carflex` |
| `servicio.tiposerv` | string | Yes | Service type: `instalacion_gps`, `visita_tecnica`, `desinstalacion_gps` |
| `servicio.taller_install` | string | Yes | Installation location: `cartec`, `servitattersall` |
| `vehiculos[]` | array | Yes | Array of vehicles (at least 1 required) |
| `vehiculos[].patente` | string | Yes | Vehicle license plate (uppercase) |
| `vehiculos[].marca` | string | Yes | Vehicle make/brand |
| `vehiculos[].modelo` | string | Yes | Vehicle model |
| `vehiculos[].color` | string | No | Vehicle color (default: "NO INFORMADO") |
| `vehiculos[].anio` | integer | Yes | Vehicle year (1900-current year) |

#### Success Response

**Status Code:** `201 Created`

```json
{
  "success": 1,
  "message": "OT creada correctamente ID: 1656 Vehiculos: 2",
  "data": {
    "id_ot": 1656,
    "rut_cliente": "12345678-5",
    "rut_tecnico": "11111111-1",
    "vehiculos_procesados": 2
  }
}
```

#### Error Responses

**400 Bad Request** - Validation Error

```json
{
  "success": 0,
  "message": "Error de validación",
  "errors": {
    "cliente.rut": ["RUT de cliente es requerido"],
    "vehiculos.0.patente": ["Patente es requerida"]
  }
}
```

**400 Bad Request** - Invalid RUT

```json
{
  "success": 0,
  "message": "Error procesando RUT de cliente",
  "errors": {
    "cliente.rut": ["Dígito verificador inválido"]
  }
}
```

**404 Not Found** - Technician Not Found

```json
{
  "success": 0,
  "message": "Técnico no encontrado",
  "errors": {
    "tecnico.rut": ["El RUT del técnico no existe en el sistema"]
  }
}
```

**500 Internal Server Error** - Database Error

```json
{
  "success": 0,
  "message": "Error al crear la OT",
  "errors": {
    "server": ["Error SQL en procedimiento"]
  }
}
```

---

## GPS Provider Mapping

| `presGPS` Value | `empresa` | Logo URL |
|-----------------|-----------|----------|
| `gpsimple` | gpsimple | https://media.recuperauto.cl/Media/Cartec/gpsimple-logo.png |
| `entel` | entel | https://media.recuperauto.cl/Media/Cartec/follow-logo.png |
| `tattersall` | tattersall | https://media.recuperauto.cl/Media/Cartec/tattersall.png |
| `cemin` | cemin | https://media.recuperauto.cl/Media/Cartec/cemin.png |
| `carflex` | carflex | https://media.recuperauto.cl/Media/Cartec/carflex.png |

---

## Service Type Mapping

| `tiposerv` Value | `presGPS` | `motivo` |
|------------------|-----------|----------|
| `instalacion_gps` | gpsimple | Instalación GPS |
| `instalacion_gps` | entel | Instalación GPS FollowMyCar |
| `instalacion_gps` | tattersall | Instalación GPS Tattersall |
| `instalacion_gps` | cemin | Instalación GPS Cemin |
| `instalacion_gps` | carflex | Instalación GPS CarFlex |
| `visita_tecnica` | any | Visita_tecnica GPS |
| `desinstalacion_gps` | any | Desinstalación GPS |

---

## Taller Mapping

| `taller_install` Value | `taller` | Logo URL |
|------------------------|----------|----------|
| `cartec` | domicilio | https://media.recuperauto.cl/Media/Cartec/cartec-logo.png |
| `servitattersall` | servitattersall | https://media.recuperauto.cl/Media/Cartec/servitattersall-logo.svg |

---

## Client UPSERT Behavior

The API automatically manages client records:

- **If client exists** (by RUT): Updates name, address, comuna, phone, and email
- **If client doesn't exist**: Creates new client record

This ensures OT creation always succeeds and keeps client contact information up-to-date.

---

## RUT Validation

The API validates Chilean RUTs:

1. **Format:** `12345678-5` or `12345678` (verification digit optional)
2. **Length:** 7-8 digits + verification digit
3. **Verification:** Modulo 11 algorithm
4. **Output:** Always formatted as `NNNNNNNN-V`

**Examples:**
- ✅ `12345678-5` → Valid
- ✅ `12345678` → Auto-calculates verification digit
- ❌ `1234567-8` → Invalid (too short)
- ❌ `12345678-9` → Invalid (wrong verification digit)

---

## Vehicle Registration

Vehicles are automatically:

1. **Created** if patente doesn't exist
2. **Updated** if patente exists (marca, modelo, color, anio)
3. **Linked** to OT via `OT_Vehiculos` table

**Patente normalization:** Always converted to UPPERCASE

---

## Rate Limiting

Currently no rate limiting is enforced. For production, consider:

- **Max requests per minute:** 60
- **Max payload size:** 50MB
- **Timeout:** 30 seconds

---

## Example cURL Commands

### Health Check

```bash
curl http://localhost:3000/api/health
```

### Create OT (Simple)

```bash
curl -X POST http://localhost:3000/api/ot/create \
  -H "Content-Type: application/json" \
  -d '{
    "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",
      "tiposerv": "instalacion_gps",
      "taller_install": "cartec"
    },
    "vehiculos": [
      {
        "patente": "TEST01",
        "marca": "Toyota",
        "modelo": "Corolla",
        "color": "Blanco",
        "anio": 2021
      }
    ]
  }'
```

### Create OT (from file)

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

---

## HTTP Status Codes

| Code | Meaning | When |
|------|---------|------|
| 200 | OK | Health check successful |
| 201 | Created | OT created successfully |
| 400 | Bad Request | Validation error, invalid RUT, missing fields |
| 404 | Not Found | Technician not found |
| 500 | Internal Server Error | Database error, procedure error |

---

## Best Practices

### 1. Always Validate RUT Before Sending

```javascript
// Example RUT validation
function validateRUT(rut) {
  const clean = rut.replace(/[^0-9Kk]/g, '');
  if (clean.length < 8) return false;
  
  const body = clean.slice(0, -1);
  const dv = clean.slice(-1).toUpperCase();
  
  let sum = 0;
  let multiplier = 2;
  
  for (let i = body.length - 1; i >= 0; i--) {
    sum += parseInt(body[i]) * multiplier;
    multiplier = multiplier < 7 ? multiplier + 1 : 2;
  }
  
  const expectedDV = 11 - (sum % 11);
  const dvChar = expectedDV === 11 ? '0' : expectedDV === 10 ? 'K' : expectedDV.toString();
  
  return dv === dvChar;
}
```

### 2. Handle Errors Gracefully

```javascript
try {
  const response = await fetch('http://localhost:3000/api/ot/create', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(otData)
  });
  
  const result = await response.json();
  
  if (result.success) {
    console.log('OT created:', result.data.id_ot);
  } else {
    console.error('Error:', result.message, result.errors);
  }
} catch (error) {
  console.error('Network error:', error);
}
```

### 3. Batch Operations

For creating multiple OTs, send them sequentially with delay:

```javascript
for (const otData of otList) {
  await createOT(otData);
  await delay(1000); // 1 second delay
}
```

---

## Integration Examples

### PHP

```php
<?php
$data = [
    'cliente' => [
        'rut' => '12345678-5',
        'nombre' => 'Cliente PHP',
        'direccion' => 'Av. PHP 123',
        'comuna' => 'Santiago',
        'telefono' => '+56912345678',
        'email' => 'php@cartec.cl'
    ],
    'tecnico' => ['rut' => '11111111-1'],
    'servicio' => [
        'presGPS' => 'gpsimple',
        'tiposerv' => 'instalacion_gps',
        'taller_install' => 'cartec'
    ],
    'vehiculos' => [
        [
            'patente' => 'PHP001',
            'marca' => 'Toyota',
            'modelo' => 'Corolla',
            'color' => 'Blanco',
            'anio' => 2021
        ]
    ]
];

$ch = curl_init('http://localhost:3000/api/ot/create');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
$result = json_decode($response, true);

if ($result['success']) {
    echo "OT created: " . $result['data']['id_ot'];
} else {
    echo "Error: " . $result['message'];
}
?>
```

### Python

```python
import requests

data = {
    "cliente": {
        "rut": "12345678-5",
        "nombre": "Cliente Python",
        "direccion": "Av. Python 123",
        "comuna": "Santiago",
        "telefono": "+56912345678",
        "email": "python@cartec.cl"
    },
    "tecnico": {"rut": "11111111-1"},
    "servicio": {
        "presGPS": "gpsimple",
        "tiposerv": "instalacion_gps",
        "taller_install": "cartec"
    },
    "vehiculos": [
        {
            "patente": "PY001",
            "marca": "Toyota",
            "modelo": "Corolla",
            "color": "Blanco",
            "anio": 2021
        }
    ]
}

response = requests.post(
    'http://localhost:3000/api/ot/create',
    json=data,
    headers={'Content-Type': 'application/json'}
)

result = response.json()

if result['success']:
    print(f"OT created: {result['data']['id_ot']}")
else:
    print(f"Error: {result['message']}")
```

---

## Changelog

### Version 1.0.0 (2025-12-29)
- Initial production release
- Single endpoint for OT creation
- Client UPSERT functionality
- Vehicle registration
- RUT validation
- GPS provider mapping
- Stored procedure integration

---

## Support

For API issues or feature requests, contact the development team or check server logs:

```bash
sudo journalctl -u cartec-api -n 100
```

