# Cartec API - OT Creation Service

API service for creating Órdenes de Trabajo (OT) with vehicle images and client signature support, built with Node.js, Express, and MySQL stored procedures.

## Features

- ✅ Complete OT creation flow
- ✅ RUT validation (Chilean format)
- ✅ Client signature handling (base64)
- ✅ Vehicle image handling (VIN images as base64)
- ✅ Technician verification
- ✅ Client upsert logic
- ✅ Multiple vehicles per OT
- ✅ GPS provider mapping
- ✅ Service type configuration
- ✅ Transaction-safe database operations

## Requirements

- Node.js >= 16.0.0
- MySQL >= 5.7
- npm or yarn

## Installation

### 1. Clone/Copy Project

```bash
cd /opt
cp -r /path/to/cartec_api .
cd cartec_api
```

### 2. Install Dependencies

```bash
npm install
```

### 3. Configure Environment

```bash
cp .env.example .env
nano .env
```

Update with your database credentials:

```env
PORT=3000
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=yourpassword
DB_NAME=revisa
DB_CONNECTION_LIMIT=10
NODE_ENV=development
```

### 4. Import Stored Procedure

```bash
mysql -u root -p revisa < sql/prc_api_create_OT.sql
```

## Usage

### Development Mode

```bash
npm run dev
```

### Production Mode

```bash
npm start
```

## API Endpoints

### Health Check

```bash
GET /api/health
```

**Response:**
```json
{
  "status": "ok",
  "timestamp": "2024-01-01T12:00:00.000Z"
}
```

### Create OT

```bash
POST /api/ot/create
Content-Type: application/json
```

**Request Body:**
```json
{
  "cliente": {
    "rut": "12345678-9",
    "nombre": "Juan Pérez",
    "direccion": "Av. Principal 123",
    "comuna": "Santiago",
    "telefono": "+56912345678",
    "email": "juan@example.com"
  },
  "tecnico": {
    "rut": "98765432-1"
  },
  "servicio": {
    "presGPS": "gpsimple",
    "tiposerv": "instalacion_gps",
    "taller_install": "cartec"
  },
  "firma": {
    "imgfirma": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA..."
  },
  "vehiculos": [
    {
      "patente": "ABCD12",
      "marca": "Toyota",
      "modelo": "Corolla",
      "color": "Blanco",
      "anio": 2020,
      "vin": "1HGBH41JXMN109186",
      "img_vin": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA..."
    }
  ]
}
```

**Success Response (201):**
```json
{
  "success": 1,
  "message": "OT creada exitosamente. ID: 1234. Vehículos procesados: 1",
  "data": {
    "id_ot": 1234,
    "rut_cliente": "12345678-9",
    "rut_tecnico": "98765432-1",
    "vehiculos_procesados": 1,
    "vehiculos_con_imagen": 1,
    "firma_incluida": true
  }
}
```

**Error Response (400):**
```json
{
  "success": 0,
  "message": "Error de validación",
  "errors": {
    "cliente.email": ["Email inválido"],
    "vehiculos.0.anio": ["Año inválido"]
  }
}
```

## Client Signature Handling

### Supported Formats

The API accepts client signatures in base64 format (typically captured from a canvas element):

1. **With data URI prefix** (recommended):
```json
{
  "firma": {
    "imgfirma": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA..."
  }
}
```

2. **Raw base64** (also supported):
```json
{
  "firma": {
    "imgfirma": "iVBORw0KGgoAAAANSUhEUgAAAAUA..."
  }
}
```

### Signature Requirements

- **Format**: PNG, JPG, JPEG, GIF, or WEBP
- **Encoding**: Base64
- **Max size**: 50MB (configurable in `src/index.js`)
- **Field**: Optional - OT can be created without signature
- **Typical source**: HTML5 Canvas element (signature pad)

### How It Works

1. Client signs on canvas/tablet
2. Canvas converted to base64 (PNG recommended)
3. API receives signature as base64 string
4. Validates format
5. Cleans data URI prefix if present
6. Passes to stored procedure
7. Procedure decodes base64 to binary (LONGBLOB)
8. Stores in `OT.imgfirma` field

## Vehicle Image Handling

### Supported Formats

The API accepts VIN images in base64 format:

1. **With data URI prefix** (recommended):
```json
{
  "img_vin": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA..."
}
```

2. **Raw base64** (also supported):
```json
{
  "img_vin": "iVBORw0KGgoAAAANSUhEUgAAAAUA..."
}
```

### Image Requirements

- **Format**: PNG, JPG, JPEG, GIF, or WEBP
- **Encoding**: Base64
- **Max size**: 50MB (configurable in `src/index.js`)
- **Field**: Optional - vehicles without images are also accepted

### How It Works

1. API receives image as base64 string
2. Validates format
3. Cleans data URI prefix if present
4. Passes to stored procedure
5. Procedure decodes base64 to binary (LONGBLOB)
6. Stores in `Vehiculos.img_vin` field

## Configuration Options

### GPS Providers

- `gpsimple` (default)
- `entel`
- `tattersall`
- `cemin`
- `carflex`

### Service Types

- `instalacion_gps` - GPS Installation
- `visita_tecnica` - Technical Visit
- `desinstalacion_gps` - GPS Uninstallation

### Installation Workshops

- `cartec` (default - domicilio)
- `servitattersall`

## Testing

### cURL Example

```bash
curl -X POST http://localhost:3000/api/ot/create \
  -H "Content-Type: application/json" \
  -d '{
    "cliente": {
      "rut": "12345678-9",
      "nombre": "Test Client",
      "direccion": "Test Address 123",
      "comuna": "Santiago",
      "telefono": "+56912345678",
      "email": "test@example.com"
    },
    "tecnico": {
      "rut": "98765432-1"
    },
    "servicio": {
      "presGPS": "gpsimple",
      "tiposerv": "instalacion_gps",
      "taller_install": "cartec"
    },
    "vehiculos": [
      {
        "patente": "TEST01",
        "marca": "Toyota",
        "modelo": "Corolla",
        "color": "Blanco",
        "anio": 2020,
        "vin": "1HGBH41JXMN109186"
      }
    ]
  }'
```

### With Image

```bash
# Convert image to base64 first
BASE64_IMG=$(base64 -w 0 /path/to/vin_image.jpg)

curl -X POST http://localhost:3000/api/ot/create \
  -H "Content-Type: application/json" \
  -d "{
    \"cliente\": {...},
    \"tecnico\": {...},
    \"servicio\": {...},
    \"vehiculos\": [
      {
        \"patente\": \"TEST01\",
        \"marca\": \"Toyota\",
        \"modelo\": \"Corolla\",
        \"color\": \"Blanco\",
        \"anio\": 2020,
        \"vin\": \"1HGBH41JXMN109186\",
        \"img_vin\": \"data:image/jpeg;base64,$BASE64_IMG\"
      }
    ]
  }"
```

## Database Tables

### Tables Modified/Created

- `Clientes` - Client upsert
- `OT` - Order creation (with imgfirma signature)
- `Vehiculos` - Vehicle upsert (with img_vin)
- `OT_Vehiculos` - OT-Vehicle relationship

## Error Handling

The API uses consistent error responses:

| Status | Meaning | Example |
|--------|---------|---------|
| 200 | Success | Health check |
| 201 | Created | OT created successfully |
| 400 | Bad Request | Validation errors |
| 404 | Not Found | Technician not found |
| 500 | Server Error | Database error |

## Logging

The API logs to console. For production, consider using a logging library like `winston` or `pino`.

## Security Considerations

- ✅ SQL Injection protected (prepared statements + stored procedure)
- ✅ Input validation on all fields
- ✅ RUT validation with checksum
- ✅ Email format validation
- ✅ Base64 image validation
- ⚠️ Consider adding authentication/authorization
- ⚠️ Consider rate limiting
- ⚠️ Consider request signing

## Performance

- Connection pooling enabled (default: 10 connections)
- Image size limit: 50MB
- Stored procedure for efficient database operations
- Transaction-safe operations

## Monitoring

See [DEPLOYMENT.md](./DEPLOYMENT.md) for production deployment with:
- Systemd service
- PM2 process manager
- Nginx reverse proxy
- Health checks
- Log management

## Troubleshooting

### "Technician not found"

Ensure the technician exists in the `Tecnicos` table:

```sql
SELECT * FROM Tecnicos WHERE rut_tecnico = '98765432-1';
```

### "Error SQL: 22032"

Invalid base64 data. Check that the image is properly encoded.

### Connection Issues

Verify database credentials in `.env` and check MySQL is running:

```bash
systemctl status mysql
```

## License

ISC

## Support

For issues or questions, contact the development team.

