# API de numeración global de boletos

## Alcance

La configuración es:

- global
- única para todo el sistema
- aplicable solo a boletos futuros

No renumera boletos históricos.

## Endpoints

| Método | Ruta | Permiso |
| --- | --- | --- |
| `GET` | `/api/v1/admin/settings/ticket-numbering` | `settings.ticket_numbering.view` |
| `PUT` | `/api/v1/admin/settings/ticket-numbering` | `settings.ticket_numbering.update` |

## Respuesta de consulta

```json
{
  "mode": "custom",
  "prefix": "BOLT-",
  "suffix": null,
  "padding_length": 5,
  "initial_number": 1,
  "next_sequence": 1,
  "format_version": 2,
  "has_issued_tickets": false,
  "can_change_initial_number": true,
  "current_format": "BOLT-00001",
  "last_ticket_number": null,
  "updated_at": "2026-07-17T12:00:00.000000Z",
  "updated_by": null,
  "examples": [
    "BOLT-00001",
    "BOLT-00002",
    "BOLT-00003"
  ]
}
```

## Payload de actualización

```json
{
  "mode": "custom",
  "prefix": "BOLT-",
  "suffix": null,
  "padding_length": 5,
  "initial_number": 1,
  "expected_updated_at": "2026-07-17T12:00:00.000000Z"
}
```

## Reglas

- `mode`: `numeric_only` o `custom`
- `prefix`: opcional
- `suffix`: opcional
- `padding_length`: mínimo `1`
- `initial_number`: solo editable antes del primer boleto
- `expected_updated_at`: protege contra cambios concurrentes

## Estrategia de secuencia

- la secuencia visible no se deriva de `MAX + 1`
- el siguiente valor se reserva desde la configuración global
- el entero interno sigue siendo independiente del formato visible
- los boletos nuevos guardan versión de formato y número visible

## Compatibilidad histórica

- los boletos anteriores conservan su número histórico
- los nuevos boletos usan `ticket_number_display`
- el frontend siempre debe mostrar `ticket_number` como valor visible expuesto por la API

## Errores relevantes

- `403 FORBIDDEN`
- `409 TICKET_NUMBERING_CONFLICT`
- `422 TICKET_NUMBERING_INITIAL_NUMBER_LOCKED`
- `419` CSRF expirado
