openapi: 3.1.0
info:
  title: Drivers
  description: '# Transcend Drivers Module API - Documentación Completa


    Este API es parte de **TransCend** y corresponde al módulo de gestión de conductores.
    Proporciona operaciones CRUD para conductores, seguimiento de posición en tiempo
    real, gestión de horas de conducción y registro completo de historial de conducción
    con datos de tacógrafo.


    ## 🎯 Propósito Principal

    Centralizar toda la información relacionada con los conductores de la plataforma,
    incluyendo:

    - Datos personales y licencias

    - Ubicación actual y seguimiento GPS

    - Horas de servicio y cumplimiento normativo

    - Historial completo de conducción con datos de tacógrafo

    - Análisis de cumplimiento y detección de infracciones


    ## 🔐 Autenticación

    Todas las rutas requieren autenticación mediante:

    1. **JWT Token** (preferido): Token obtenido del módulo IAM

    2. **API Key**: Para integraciones de servicios externos


    ## 📋 Convenciones de Respuesta

    - Éxito: `200` o `201` con datos en formato JSON

    - Error: `4xx` o `5xx` con objeto `{ error: \"mensaje descriptivo\" }`

    - Validación: `400` para datos inválidos, `404` para recursos no encontrados


    ## ⚠️ Limitaciones y Cuotas

    - Máximo 1000 conductores por usuario

    - Actualización de posición: 1 por minuto por conductor

    - Consultas de posición: 10 por segundo por usuario

    - Historial de posiciones: Retenido por 30 días

    '
  version: 2.7.071315
  contact:
    email: support@cargoffer.com
  license: Private API - Access by agreement only
servers:
- url: https://api.pro.cargoffer.com
  description: Producción
components:
  schemas:
    Error:
      type: object
      properties:
        error:
          type: string
          description: Mensaje descriptivo del error en español
          example: Parámetros inválidos o faltantes
      required:
      - error
    Driver:
      type: object
      properties:
        _id:
          type: string
          description: 'Identificador único del conductor en formato MongoDB ObjectId.

            **Formato**: 24 caracteres hexadecimales (ej: 5f8d3b7b3f6b8a1b9c3b7b3f)

            **Generado automáticamente** por el sistema al crear el conductor.

            **Requerido** para todas las operaciones que referencien un conductor
            específico.

            '
          example: 5f8d3b7b3f6b8a1b9c3b7b3f
        owner:
          type: string
          description: 'ID del usuario propietario del conductor.

            **Asignado automáticamente** basado en el token JWT del usuario autenticado.

            **No modificable** manualmente.

            Usado para aislamiento de datos entre usuarios.

            '
          example: 63d7907cbe76403b35da63df
        name:
          type: string
          description: 'Nombre completo del conductor según documento de identidad.

            **Requerido** para crear/actualizar un conductor.

            **Validación**: Mínimo 3 caracteres, máximo 100.

            **Formato**: Texto plano, sin caracteres especiales.

            '
          example: Juan Pérez García
        licenseNumber:
          type: string
          description: 'Número de licencia de conducir válida.

            **Requerido** para crear un conductor.

            **Único** en el sistema, no se puede modificar después de creación.

            **Formato específico por país**:

            - España: 8 dígitos + 1 letra (ej: 12345678X)

            - Francia: 12 caracteres alfanuméricos

            - Alemania: 11 dígitos

            '
          example: 12345678X
        enabled:
          type: boolean
          description: 'Estado de habilitación del conductor.

            **Por defecto**: `true`

            **Uso**: Para deshabilitar temporalmente un conductor sin eliminarlo.

            **Efecto**: Conductores deshabilitados no aparecen en búsquedas ni pueden
            recibir rutas.

            '
          example: true
        currentPosition:
          type: object
          properties:
            coordinates:
              type: array
              items:
                type: number
                format: float
              minItems: 2
              maxItems: 2
              description: 'Coordenadas GPS en formato [longitud, latitud].

                **Precisión mínima**: 6 decimales (~11cm).

                **Valores válidos**:

                - Latitud: -90 a 90

                - Longitud: -180 a 180

                '
              example:
              - -3.7038
              - 40.4168
            timestamp:
              type: string
              format: date-time
              description: 'Fecha y hora exacta de la posición en formato ISO 8601
                (UTC).

                **Actualizado automáticamente** cada vez que se reporta nueva posición.

                **Usado para**: Calcular velocidad, estimar tiempos de llegada, verificar
                actualidad.

                '
              example: '2025-04-30T10:30:00.000Z'
          description: 'Última posición conocida del conductor.

            **Actualizado automáticamente** cada 5 minutos cuando el conductor está
            en ruta.

            **Formato**: Objeto con coordenadas y timestamp.

            **Uso principal**: Mostrar ubicación en tiempo real en mapas.

            '
        positionHistory:
          type: array
          items:
            type: object
            properties:
              coordinates:
                type: array
                items:
                  type: number
                  format: float
                minItems: 2
                maxItems: 2
              timestamp:
                type: string
                format: date-time
          description: 'Historial de posiciones del conductor (últimos 30 días).

            **Máximo**: 1000 posiciones almacenadas.

            **Purga automática**: Posiciones mayores a 30 días se eliminan.

            **Uso**: Análisis de rutas, auditoría, reconstrucción de trayectos.

            '
        hoursStatus:
          type: object
          properties:
            remainingWeeklyHours:
              type: number
              description: 'Horas restantes disponibles esta semana (lunes a domingo).

                **Calculado automáticamente** basado en registros de conducción.

                **No puede ser negativo**.

                **Alerta**: Cuando < 4 horas restantes.

                '
              example: 12.5
            remainingBiweeklyHours:
              type: number
              description: 'Horas restantes disponibles en el periodo bimensual actual.

                **Regulación UE**: Máximo 90 horas en 2 semanas consecutivas.

                **Calculado automáticamente**.

                '
              example: 45.0
            remainingDayHours:
              type: number
              description: 'Horas restantes disponibles hoy.

                **Regulación UE**: Máximo 9 horas diarias (puede extenderse a 10 horas
                2 veces por semana).

                **Actualizado en tiempo real**.

                '
              example: 3.5
            lastRestStart:
              type: string
              format: date-time
              description: 'Fecha y hora de inicio del último periodo de descanso.

                **Usado para**: Calcular cumplimiento de descansos obligatorios.

                **Regulación**: Mínimo 11 horas de descanso diario.

                '
              example: '2025-04-30T21:00:00.000Z'
            lastDrivingStart:
              type: string
              format: date-time
              description: 'Fecha y hora de inicio de la última sesión de conducción.

                **Usado para**: Calcular tiempo máximo de conducción ininterrumpida.

                **Regulación**: Máximo 4.5 horas sin descanso de 45 minutos.

                '
              example: '2025-04-30T08:00:00.000Z'
          description: 'Estado actual de las horas de conducción del conductor.

            **Actualizado automáticamente** con cada registro de actividad.

            **Usado para**: Cumplimiento normativo, prevención de infracciones.

            '
        drivingHistory:
          type: array
          items:
            type: object
            properties:
              type:
                type: string
                enum:
                - driving
                - rest
                description: 'Tipo de actividad registrada.

                  - `driving`: Periodo de conducción activa

                  - `rest`: Periodo de descanso obligatorio

                  '
              startTime:
                type: string
                format: date-time
                description: Hora de inicio de la actividad
              endTime:
                type: string
                format: date-time
                description: Hora de fin de la actividad (null si está en curso)
              durationMinutes:
                type: number
                description: Duración total en minutos
              coordinates:
                type: array
                items:
                  type: array
                  items:
                    type: number
                    format: float
                  minItems: 2
                  maxItems: 2
                description: 'Puntos significativos de la ruta durante esta actividad.

                  **Máximo**: 100 puntos por registro.

                  **Formato**: [[lng, lat], [lng, lat], ...]

                  '
          description: 'Historial detallado de actividades del conductor.

            **Usado para**: Auditoría, análisis de productividad, cumplimiento normativo.

            **Retención**: 6 meses para fines legales.

            '
      required:
      - _id
      - name
      - licenseNumber
      - enabled
    PositionUpdate:
      type: object
      properties:
        coordinates:
          type: array
          items:
            type: number
            format: float
          minItems: 2
          maxItems: 2
          description: 'Coordenadas GPS actuales en formato [longitud, latitud].

            **Requerido**: Sí

            **Precisión**: Mínimo 6 decimales

            **Ejemplo válido**: [-3.7038, 40.4168] (Madrid, España)

            '
          example:
          - -3.7038
          - 40.4168
        timestamp:
          type: string
          format: date-time
          description: 'Fecha y hora exacta de la posición.

            **Requerido**: Sí

            **Formato**: ISO 8601 (UTC)

            **Restricción**: No puede ser fecha futura

            **Diferencia máxima**: 5 minutos con tiempo del servidor

            '
          example: '2025-04-30T10:30:00.000Z'
      required:
      - coordinates
      - timestamp
    DriverActivity:
      type: object
      properties:
        type:
          type: string
          enum:
          - driving
          - rest
          description: 'Tipo de actividad a registrar.

            - `driving`: Inicio/fin de periodo de conducción

            - `rest`: Inicio/fin de periodo de descanso

            **Requerido**: Sí

            '
          example: driving
        startTime:
          type: string
          format: date-time
          description: 'Fecha y hora de inicio de la actividad.

            **Requerido**: Sí

            **Formato**: ISO 8601 (UTC)

            **Validación**: No puede superponerse con actividades existentes

            '
          example: '2025-04-30T08:00:00.000Z'
        endTime:
          type: string
          format: date-time
          description: 'Fecha y hora de fin de la actividad.

            **Opcional**: Si no se proporciona, se asume actividad en curso

            **Validación**: Debe ser posterior a startTime

            '
          example: '2025-04-30T12:30:00.000Z'
        coordinates:
          type: array
          items:
            type: array
            items:
              type: number
              format: float
            minItems: 2
            maxItems: 2
          description: 'Puntos de ruta significativos durante la actividad.

            **Opcional**: Solo para actividades de tipo `driving`

            **Máximo**: 50 puntos

            **Uso**: Reconstrucción de ruta, cálculo de distancia

            '
          example:
          - - -3.7038
            - 40.4168
          - - -3.71
            - 40.42
          - - -3.715
            - 40.425
      required:
      - type
      - startTime
    HistoricalDrivingRecord:
      type: object
      properties:
        _id:
          type: string
          description: ID único del registro de tacógrafo
          example: 5f8d3b7b3f6b8a1b9c3b7b3f
        archivoDescarga:
          type: object
          properties:
            nombre:
              type: string
              description: Nombre del archivo descargado del tacógrafo
              example: TACO_20250430_083000
            extension:
              type: string
              enum:
              - TGD
              - DDD
              - C1B
              - V1B
              description: Formato del archivo de tacógrafo
              example: TGD
            fechaDescarga:
              type: string
              format: date-time
              description: Fecha y hora de la descarga
              example: '2025-04-30T10:30:00.000Z'
        conductor:
          type: object
          properties:
            nombre:
              type: string
              description: Nombre del conductor
              example: Juan
            apellidos:
              type: string
              description: Apellidos del conductor
              example: Pérez García
            numeroTarjeta:
              type: string
              description: Número de tarjeta de conductor (16 dígitos)
              example: ES123456789012345
            fechaCaducidad:
              type: string
              format: date-time
              description: Fecha de caducidad de la tarjeta
              example: '2026-12-31T23:59:59.000Z'
        sesion:
          type: object
          properties:
            fechaInsercion:
              type: string
              format: date-time
              description: Fecha de inserción de la tarjeta en el tacógrafo
              example: '2025-04-30T08:00:00.000Z'
            fechaExtraccion:
              type: string
              format: date-time
              description: Fecha de extracción de la tarjeta
              example: '2025-04-30T17:30:00.000Z'
            vehiculo:
              type: object
              properties:
                matricula:
                  type: string
                  description: Matrícula del vehículo
                  example: 1234ABC
        actividades:
          type: array
          items:
            type: object
            properties:
              tipo:
                type: string
                enum:
                - CONDUCCION
                - TRABAJO
                - DISPONIBILIDAD
                - DESCANSO
                - DESCONOCIDO
                description: Tipo de actividad registrada
              fechaInicio:
                type: string
                format: date-time
              fechaFin:
                type: string
                format: date-time
              duracionMinutos:
                type: number
                description: Duración en minutos
        conduccion:
          type: object
          properties:
            distanciaTotal:
              type: number
              description: Distancia total recorrida en km
              example: 450.75
            tiempoConduccionTotal:
              type: number
              description: Tiempo total de conducción en minutos
              example: 480
            velocidadMaxima:
              type: number
              description: Velocidad máxima registrada en km/h
              example: 95.5
            velocidadPromedio:
              type: number
              description: Velocidad promedio en km/h
              example: 72.3
        eventos:
          type: array
          items:
            type: object
            properties:
              tipo:
                type: string
                enum:
                - FALLO_SENSOR
                - FALLO_TACOGRAFO
                - MANIPULACION
                - TARJETA_NO_INSERTADA
                - EXCESO_VELOCIDAD
                - EVENTO_PERSONALIZADO
                - ERROR_DATOS
                description: Tipo de evento registrado
              fechaHora:
                type: string
                format: date-time
              codigo:
                type: string
                description: Código del evento
              descripcion:
                type: string
                description: Descripción del evento
              gravedad:
                type: string
                enum:
                - LEVE
                - GRAVE
                - MUY_GRAVE
                description: Gravedad del evento
        resumenTiempos:
          type: object
          properties:
            tiempoConduccion:
              type: number
              description: Tiempo total de conducción en minutos
            tiempoDescanso:
              type: number
              description: Tiempo total de descanso en minutos
            cumpleNormativa:
              type: boolean
              description: Indica si cumple la normativa
            infracciones:
              type: array
              items:
                type: string
              description: Lista de infracciones detectadas
    HistoricalDrivingAnalysis:
      type: object
      properties:
        basicInfo:
          type: object
          properties:
            driver:
              type: string
              description: Nombre completo del conductor
            vehicle:
              type: string
              description: Matrícula del vehículo
            period:
              type: string
              description: Periodo de la sesión
        drivingAnalysis:
          type: object
          properties:
            totalTime:
              type: number
              description: Tiempo total de conducción en minutos
            totalDistance:
              type: number
              description: Distancia total en km
            averageSpeed:
              type: number
              description: Velocidad promedio en km/h
            maxSpeed:
              type: number
              description: Velocidad máxima en km/h
            speedExcesses:
              type: number
              description: Número de excesos de velocidad
        activityBreakdown:
          type: object
          additionalProperties:
            type: number
          description: Desglose de actividades por tipo (minutos)
        eventsSummary:
          type: object
          properties:
            total:
              type: number
              description: Total de eventos registrados
            byType:
              type: object
              additionalProperties:
                type: number
              description: Eventos agrupados por tipo
            bySeverity:
              type: object
              additionalProperties:
                type: number
              description: Eventos agrupados por gravedad
    ComplianceCheck:
      type: object
      properties:
        isValid:
          type: boolean
          description: Indica si el registro es válido para circular
        infractions:
          type: array
          items:
            type: string
          description: Lista de infracciones detectadas
        complianceDetails:
          type: object
          properties:
            drivingTime:
              type: object
              properties:
                value:
                  type: number
                  description: Tiempo de conducción real en minutos
                limit:
                  type: number
                  description: Límite permitido en minutos (540 = 9 horas)
                compliant:
                  type: boolean
                  description: Indica si cumple el límite
            restTime:
              type: object
              properties:
                value:
                  type: number
                  description: Tiempo de descanso real en minutos
                limit:
                  type: number
                  description: Límite mínimo en minutos (660 = 11 horas)
                compliant:
                  type: boolean
                  description: Indica si cumple el mínimo
            cardValid:
              type: object
              properties:
                value:
                  type: string
                  format: date-time
                  description: Fecha de caducidad de la tarjeta
                compliant:
                  type: boolean
                  description: Indica si la tarjeta está vigente
            calibrationValid:
              type: object
              properties:
                value:
                  type: string
                  format: date-time
                  description: Fecha de última calibración
                compliant:
                  type: boolean
                  description: Indica si la calibración es reciente (<1 año)
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: '**JWT Token** para autenticación de usuarios.


        **Obtención**: A través del módulo IAM de Transcend.


        **Formato**: `Bearer <token>`


        **Incluir en**: Header `Authorization`


        **Ejemplo**:

        ```

        Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

        ```

        '
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: '**API Key** para autenticación de servicios externos.


        **Obtención**: Generada en el panel de administración de Transcend.


        **Uso**: Para integraciones automatizadas, webhooks, servicios de backend.


        **Incluir en**: Header `X-API-Key`


        **Ejemplo**:

        ```

        X-API-Key: sk_live_1234567890abcdef

        ```

        '
  parameters:
    DriverId:
      name: id
      in: path
      description: '**Identificador único del conductor** (MongoDB ObjectId).


        **Formato**: 24 caracteres hexadecimales.


        **Ejemplo válido**: `5f8d3b7b3f6b8a1b9c3b7b3f`


        **Obtención**: Al crear un conductor o listar conductores.


        **Uso**: En todas las rutas que operan sobre un conductor específico.

        '
      required: true
      schema:
        type: string
        pattern: ^[0-9a-fA-F]{24}$
        example: 5f8d3b7b3f6b8a1b9c3b7b3f
    RecordId:
      name: id
      in: path
      description: '**Identificador único del registro de tacógrafo**.


        **Formato**: MongoDB ObjectId (24 caracteres hexadecimales).


        **Obtención**: Al crear o listar registros históricos.

        '
      required: true
      schema:
        type: string
        pattern: ^[0-9a-fA-F]{24}$
        example: 5f8d3b7b3f6b8a1b9c3b7b3f
    EventId:
      name: eventId
      in: path
      description: '**Identificador único de un evento** dentro de un registro.


        **Formato**: MongoDB ObjectId (24 caracteres hexadecimales).


        **Obtención**: Al listar eventos de un registro.

        '
      required: true
      schema:
        type: string
        pattern: ^[0-9a-fA-F]{24}$
        example: 5f8d3b7b3f6b8a1b9c3b7b3f
    DriverCardNumber:
      name: driverCardNumber
      in: path
      description: '**Número de tarjeta de conductor** (16 dígitos).


        **Formato**: País (2 letras) + 14 dígitos (ej: ES12345678901234).


        **Obtención**: De la tarjeta física del conductor.

        '
      required: true
      schema:
        type: string
        pattern: ^[A-Z]{2}[0-9]{14}$
        example: ES12345678901234
    LicensePlate:
      name: licensePlate
      in: path
      description: '**Matrícula del vehículo**.


        **Formato**: Depende del país (ej: 1234ABC para España).


        **Longitud máxima**: 10 caracteres.

        '
      required: true
      schema:
        type: string
        maxLength: 10
        example: 1234ABC
    Language:
      name: lang
      in: query
      description: '**Idioma para las respuestas**.


        **Código ISO 639-1** (2 letras).


        **Por defecto**: `es` (español).


        **Soportados**: `es`, `en`, `fr`, `de`, `it`, `pt`

        '
      required: false
      schema:
        type: string
        minLength: 2
        maxLength: 2
        default: es
        example: es
    StartDate:
      name: startDate
      in: query
      description: '**Fecha de inicio** para filtros por rango.


        **Formato**: ISO 8601 (`YYYY-MM-DD` o `YYYY-MM-DDTHH:mm:ssZ`).


        **Ejemplo**: `2025-04-30` o `2025-04-30T08:00:00Z`

        '
      required: false
      schema:
        type: string
        format: date-time
        example: '2025-04-30T00:00:00Z'
    EndDate:
      name: endDate
      in: query
      description: '**Fecha de fin** para filtros por rango.


        **Formato**: ISO 8601 (`YYYY-MM-DD` o `YYYY-MM-DDTHH:mm:ssZ`).


        **Ejemplo**: `2025-04-30` o `2025-04-30T23:59:59Z`

        '
      required: false
      schema:
        type: string
        format: date-time
        example: '2025-04-30T23:59:59Z'
    Page:
      name: page
      in: query
      description: '**Número de página** para resultados paginados.


        **Por defecto**: `1`


        **Mínimo**: `1`

        '
      required: false
      schema:
        type: integer
        minimum: 1
        default: 1
        example: 1
    PageSize:
      name: pageSize
      in: query
      description: '**Tamaño de página** (número de resultados por página).


        **Por defecto**: `10`


        **Mínimo**: `1`


        **Máximo**: `100`

        '
      required: false
      schema:
        type: integer
        minimum: 1
        maximum: 100
        default: 10
        example: 10
    Sort:
      name: sort
      in: query
      description: '**Orden de los resultados**.


        **Valores**: `asc` (ascendente) o `desc` (descendente).


        **Por defecto**: `desc` (más recientes primero).


        **Campos aplicables**: `createdAt`, `updatedAt`, `name`

        '
      required: false
      schema:
        type: string
        enum:
        - asc
        - desc
paths:
  /drivers:
    get:
      summary: Listar conductores
      description: '**Obtiene una lista paginada de todos los conductores** asociados
        al usuario autenticado.


        ## 📋 Funcionalidades

        - **Paginación**: Soporta parámetros `page` y `pageSize`

        - **Ordenamiento**: Por `name`, `createdAt`, `updatedAt` (por defecto: más
        recientes primero)

        - **Filtros**: Por nombre, estado habilitado, etc.

        - **Aislamiento**: Solo muestra conductores del usuario propietario


        ## 🔍 Parámetros de consulta

        - `page`: Número de página (por defecto: 1)

        - `pageSize`: Resultados por página (máximo: 100)

        - `sort`: Orden (`asc`/`desc`)

        - `lang`: Idioma de respuesta (`es` por defecto)


        ## 📊 Respuesta

        Lista de objetos `Driver` con información completa incluyendo posición actual,
        estado de horas y historial reciente.

        '
      operationId: getDrivers
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      parameters:
      - $ref: '#/components/parameters/Page'
      - $ref: '#/components/parameters/PageSize'
      - $ref: '#/components/parameters/Sort'
      - $ref: '#/components/parameters/Language'
      responses:
        '200':
          description: Lista de conductores obtenida exitosamente
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Driver'
                  pagination:
                    type: object
                    properties:
                      page:
                        type: integer
                        example: 1
                      pageSize:
                        type: integer
                        example: 10
                      total:
                        type: integer
                        example: 150
                      totalPages:
                        type: integer
                        example: 15
                example:
                  data:
                  - _id: 5f8d3b7b3f6b8a1b9c3b7b3f
                    owner: 63d7907cbe76403b35da63df
                    name: Juan Pérez García
                    licenseNumber: 12345678X
                    enabled: true
                    currentPosition:
                      coordinates:
                      - -3.7038
                      - 40.4168
                      timestamp: '2025-04-30T10:30:00.000Z'
                    hoursStatus:
                      remainingWeeklyHours: 12.5
                      remainingDayHours: 3.5
                  - _id: 5f8d3b7b3f6b8a1b9c3b7b4f
                    owner: 63d7907cbe76403b35da63df
                    name: María López Ruiz
                    licenseNumber: 87654321Y
                    enabled: true
                    currentPosition:
                      coordinates:
                      - -3.71
                      - 40.42
                      timestamp: '2025-04-30T09:15:00.000Z'
                    hoursStatus:
                      remainingWeeklyHours: 8.0
                      remainingDayHours: 2.0
                  pagination:
                    page: 1
                    pageSize: 10
                    total: 2
                    totalPages: 1
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
    post:
      summary: Crear conductor
      description: '**Crea un nuevo conductor** en el sistema.


        ## 📝 Requisitos

        - Nombre completo (3-100 caracteres)

        - Número de licencia válido (único en el sistema)

        - El conductor se asocia automáticamente al usuario autenticado


        ## ✅ Validaciones

        - Número de licencia debe ser único

        - Formato de licencia válido según país

        - Máximo 1000 conductores por usuario


        ## 📊 Respuesta

        Objeto `Driver` completo con ID generado y campos por defecto.

        '
      operationId: createDriver
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      parameters:
      - $ref: '#/components/parameters/Language'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  minLength: 3
                  maxLength: 100
                  example: Juan Pérez García
                licenseNumber:
                  type: string
                  minLength: 8
                  maxLength: 20
                  example: 12345678X
              required:
              - name
              - licenseNumber
            example:
              name: Juan Pérez García
              licenseNumber: 12345678X
      responses:
        '201':
          description: Conductor creado exitosamente
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Driver'
              example:
                _id: 5f8d3b7b3f6b8a1b9c3b7b3f
                owner: 63d7907cbe76403b35da63df
                name: Juan Pérez García
                licenseNumber: 12345678X
                enabled: true
                currentPosition: null
                hoursStatus:
                  remainingWeeklyHours: 48.0
                  remainingBiweeklyHours: 90.0
                  remainingDayHours: 9.0
                  lastRestStart: null
                  lastDrivingStart: null
                positionHistory: []
                drivingHistory: []
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '409':
          description: Conflicto - Número de licencia ya existe
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: El número de licencia ya está registrado
        '429':
          description: Límite de consultas excedido
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Límite de consultas de posición excedido (10 por segundo)
        '500':
          $ref: '#/components/responses/InternalServerError'
  /drivers/{id}/daily-limits:
    parameters:
    - $ref: '#/components/parameters/DriverId'
    - $ref: '#/components/parameters/Language'
    get:
      summary: Obtener límites diarios de horas del conductor
      description: '**Obtiene el estado actual de las horas de conducción del conductor**.


        ## ⏱️ Información proporcionada

        - Horas restantes disponibles hoy

        - Horas restantes esta semana (lunes-domingo)

        - Horas restantes en el periodo bimensual

        - Fecha del último descanso obligatorio

        - Fecha del último inicio de conducción


        ## 📊 Cálculos automáticos

        - Basados en registros de actividad de conducción

        - Cumplimiento normativo UE (Reglamento 561/2006)

        - Actualización en tiempo real con cada registro de actividad


        ## ⚠️ Alertas y límites

        - **Alerta**: Cuando quedan < 4 horas semanales

        - **Máximo diario**: 9 horas (10 horas máximo 2 veces por semana)

        - **Máximo semanal**: 48 horas (56 horas máximo 2 veces cada 4 semanas)

        - **Máximo bimensual**: 90 horas


        ## 🔄 Actualización

        - Se recalcula automáticamente con cada registro de actividad

        - Incluye pausas obligatorias de 45 minutos cada 4.5 horas

        - Descansos diarios mínimos de 11 horas

        '
      operationId: getDriverDailyLimits
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      responses:
        '200':
          description: Límites diarios obtenidos exitosamente
          content:
            application/json:
              schema:
                type: object
                properties:
                  remainingWeeklyHours:
                    type: number
                    description: Horas restantes esta semana
                    example: 12.5
                  remainingBiweeklyHours:
                    type: number
                    description: Horas restantes en periodo bimensual
                    example: 45.0
                  remainingDayHours:
                    type: number
                    description: Horas restantes hoy
                    example: 3.5
                  lastRestStart:
                    type: string
                    format: date-time
                    description: Último inicio de descanso
                    example: '2025-04-30T21:00:00.000Z'
                  lastDrivingStart:
                    type: string
                    format: date-time
                    description: Último inicio de conducción
                    example: '2025-04-30T08:00:00.000Z'
                  compliance:
                    type: object
                    properties:
                      isCompliant:
                        type: boolean
                        description: Cumple normativa actual
                        example: true
                      warnings:
                        type: array
                        items:
                          type: string
                        description: Alertas de cumplimiento
                        example:
                        - Próximo descanso obligatorio en 2 horas
                example:
                  remainingWeeklyHours: 12.5
                  remainingBiweeklyHours: 45.0
                  remainingDayHours: 3.5
                  lastRestStart: '2025-04-30T21:00:00.000Z'
                  lastDrivingStart: '2025-04-30T08:00:00.000Z'
                  compliance:
                    isCompliant: true
                    warnings: []
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: Conductor no encontrado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Conductor no encontrado o sin permisos de acceso
        '500':
          $ref: '#/components/responses/InternalServerError'
  /drivers/{id}/hours-history:
    parameters:
    - $ref: '#/components/parameters/DriverId'
    - $ref: '#/components/parameters/Language'
    post:
      summary: Registrar actividad de horas del conductor
      description: '**Registra una nueva actividad de conducción o descanso para el
        conductor**.


        ## 📝 Tipos de actividad

        - **`driving`**: Periodo de conducción activa

        - **`rest`**: Periodo de descanso obligatorio


        ## ⏱️ Requisitos de registro

        - **Timestamp de inicio**: Fecha y hora de inicio de la actividad

        - **Timestamp de fin**: Opcional, si la actividad continúa

        - **Coordenadas**: Opcional para actividades de conducción (máximo 50 puntos)

        - **Tipo de actividad**: `driving` o `rest`


        ## ✅ Validaciones

        - No superposición con actividades existentes

        - Duración máxima de conducción continua: 4.5 horas

        - Descanso mínimo diario: 11 horas

        - Coordenadas válidas si proporcionadas


        ## 🔄 Efectos automáticos

        - Recalcula límites de horas disponibles

        - Actualiza estado de cumplimiento normativo

        - Genera alertas si se aproximan límites

        - Registra en historial permanente

        '
      operationId: addDriverHoursHistory
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DriverActivity'
            example:
              type: driving
              startTime: '2025-04-30T08:00:00.000Z'
              endTime: '2025-04-30T12:30:00.000Z'
              coordinates:
              - - -3.7038
                - 40.4168
              - - -3.71
                - 40.42
              - - -3.715
                - 40.425
      responses:
        '201':
          description: Actividad registrada exitosamente
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  activity:
                    $ref: '#/components/schemas/DriverActivity'
                  updatedLimits:
                    type: object
                    properties:
                      remainingWeeklyHours:
                        type: number
                        example: 8.0
                      remainingDayHours:
                        type: number
                        example: 2.5
                      compliance:
                        type: object
                        properties:
                          isCompliant:
                            type: boolean
                            example: true
                          warnings:
                            type: array
                            items:
                              type: string
                            example: []
                  message:
                    type: string
                    example: Actividad de conducción registrada correctamente
                example:
                  success: true
                  activity:
                    type: driving
                    startTime: '2025-04-30T08:00:00.000Z'
                    endTime: '2025-04-30T12:30:00.000Z'
                    coordinates:
                    - - -3.7038
                      - 40.4168
                    - - -3.71
                      - 40.42
                  updatedLimits:
                    remainingWeeklyHours: 8.0
                    remainingDayHours: 2.5
                    compliance:
                      isCompliant: true
                      warnings: []
                  message: Actividad de conducción registrada correctamente
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: Conductor no encontrado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Conductor no encontrado o sin permisos de acceso
        '409':
          description: Conflicto de horarios
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: La actividad se superpone con registros existentes
        '500':
          $ref: '#/components/responses/InternalServerError'
  /historical-driving:
    get:
      summary: Listar registros históricos de tacógrafo
      description: '**Obtiene una lista paginada de todos los registros históricos
        de tacógrafo**.


        ## 📋 Funcionalidades

        - **Paginación**: Soporta parámetros `page` y `pageSize`

        - **Filtros**: Por conductor, vehículo, rango de fechas

        - **Ordenamiento**: Por fecha de creación, conductor, vehículo

        - **Aislamiento**: Solo registros del usuario propietario


        ## 🔍 Parámetros de consulta

        - `page`: Número de página (por defecto: 1)

        - `pageSize`: Resultados por página (máximo: 100)

        - `startDate`/`endDate`: Rango de fechas

        - `driverCardNumber`: Filtrar por conductor

        - `licensePlate`: Filtrar por vehículo

        - `sort`: Orden (`asc`/`desc`)

        - `lang`: Idioma de respuesta (`es` por defecto)


        ## 📊 Respuesta

        Lista de objetos `HistoricalDrivingRecord` con metadatos de paginación.

        '
      operationId: getHistoricalDrivingRecords
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      parameters:
      - $ref: '#/components/parameters/Language'
      - $ref: '#/components/parameters/StartDate'
      - $ref: '#/components/parameters/EndDate'
      - $ref: '#/components/parameters/Page'
      - $ref: '#/components/parameters/PageSize'
      - $ref: '#/components/parameters/Sort'
      - name: driverCardNumber
        in: query
        description: '**Filtrar por número de tarjeta del conductor**.

          **Formato**: ES12345678901234 (país + 14 dígitos)

          '
        required: false
        schema:
          type: string
          pattern: ^[A-Z]{2}[0-9]{14}$
          example: ES12345678901234
      - name: licensePlate
        in: query
        description: '**Filtrar por matrícula del vehículo**.

          **Longitud máxima**: 10 caracteres

          '
        required: false
        schema:
          type: string
          maxLength: 10
          example: 1234ABC
      responses:
        '200':
          description: Registros obtenidos exitosamente
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/HistoricalDrivingRecord'
                  pagination:
                    type: object
                    properties:
                      page:
                        type: integer
                        example: 1
                      pageSize:
                        type: integer
                        example: 10
                      total:
                        type: integer
                        example: 150
                      totalPages:
                        type: integer
                        example: 15
                example:
                  data:
                  - _id: 5f8d3b7b3f6b8a1b9c3b7b3f
                    archivoDescarga:
                      nombre: TACO_20250430_083000
                      extension: TGD
                      fechaDescarga: '2025-04-30T10:30:00.000Z'
                    conductor:
                      nombre: Juan
                      apellidos: Pérez García
                      numeroTarjeta: ES123456789012345
                      fechaCaducidad: '2026-12-31T23:59:59.000Z'
                    sesion:
                      fechaInsercion: '2025-04-30T08:00:00.000Z'
                      fechaExtraccion: '2025-04-30T17:30:00.000Z'
                      vehiculo:
                        matricula: 1234ABC
                    conduccion:
                      distanciaTotal: 450.75
                      tiempoConduccionTotal: 480
                      velocidadMaxima: 95.5
                      velocidadPromedio: 72.3
                  pagination:
                    page: 1
                    pageSize: 10
                    total: 1
                    totalPages: 1
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
    post:
      summary: Crear registro histórico de tacógrafo
      description: '**Crea un nuevo registro histórico a partir de datos de tacógrafo**.


        ## 📝 Requisitos

        - Archivo de tacógrafo descargado (TGD, DDD, C1B, V1B)

        - Información del conductor (tarjeta válida)

        - Información del vehículo

        - Datos de actividad parseados


        ## ✅ Validaciones

        - Archivo válido y no corrupto

        - Tarjeta de conductor vigente

        - Calibración del tacógrafo reciente (<1 año)

        - No duplicados (mismo archivo, conductor, fecha)


        ## 🔄 Procesamiento automático

        - Parseo de datos del tacógrafo

        - Cálculo de tiempos de conducción

        - Detección de infracciones

        - Generación de resumen y análisis

        - Almacenamiento de eventos registrados

        '
      operationId: createHistoricalDrivingRecord
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      parameters:
      - $ref: '#/components/parameters/Language'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                archivoDescarga:
                  type: object
                  properties:
                    nombre:
                      type: string
                      example: TACO_20250430_083000
                    extension:
                      type: string
                      enum:
                      - TGD
                      - DDD
                      - C1B
                      - V1B
                      example: TGD
                    fechaDescarga:
                      type: string
                      format: date-time
                      example: '2025-04-30T10:30:00.000Z'
                    contenido:
                      type: string
                      description: Contenido del archivo en base64
                      example: U0dEX0ZJTEVfREFUQQ==
                  required:
                  - nombre
                  - extension
                  - fechaDescarga
                  - contenido
                conductor:
                  type: object
                  properties:
                    nombre:
                      type: string
                      example: Juan
                    apellidos:
                      type: string
                      example: Pérez García
                    numeroTarjeta:
                      type: string
                      pattern: ^[A-Z]{2}[0-9]{14}$
                      example: ES123456789012345
                    fechaCaducidad:
                      type: string
                      format: date-time
                      example: '2026-12-31T23:59:59.000Z'
                  required:
                  - nombre
                  - apellidos
                  - numeroTarjeta
                  - fechaCaducidad
                vehiculo:
                  type: object
                  properties:
                    matricula:
                      type: string
                      maxLength: 10
                      example: 1234ABC
                  required:
                  - matricula
              required:
              - archivoDescarga
              - conductor
              - vehiculo
            example:
              archivoDescarga:
                nombre: TACO_20250430_083000
                extension: TGD
                fechaDescarga: '2025-04-30T10:30:00.000Z'
                contenido: U0dEX0ZJTEVfREFUQQ==
              conductor:
                nombre: Juan
                apellidos: Pérez García
                numeroTarjeta: ES123456789012345
                fechaCaducidad: '2026-12-31T23:59:59.000Z'
              vehiculo:
                matricula: 1234ABC
      responses:
        '201':
          description: Registro creado exitosamente
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HistoricalDrivingRecord'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '409':
          description: Registro duplicado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Ya existe un registro para este conductor y fecha
        '500':
          $ref: '#/components/responses/InternalServerError'
  /historical-driving/{id}:
    parameters:
    - $ref: '#/components/parameters/RecordId'
    - $ref: '#/components/parameters/Language'
    get:
      summary: Obtener registro histórico específico
      description: '**Obtiene la información completa de un registro histórico de
        tacógrafo**.


        ## 📋 Información incluida

        - Metadatos del archivo descargado

        - Información del conductor y vehículo

        - Sesión completa (inicio/fin)

        - Todas las actividades registradas

        - Resumen de conducción (distancia, tiempo, velocidades)

        - Lista completa de eventos registrados


        ## 🔒 Permisos

        - Solo el propietario del registro puede acceder

        - Validación por campo `owner` (asociado al usuario)


        ## 💾 Datos históricos

        - Registros se retienen indefinidamente para cumplimiento legal

        - Incluye datos parseados del tacógrafo original

        - Eventos categorizados por tipo y gravedad

        '
      operationId: getHistoricalDrivingRecord
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      responses:
        '200':
          description: Registro obtenido exitosamente
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HistoricalDrivingRecord'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: Registro no encontrado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Registro histórico no encontrado o sin permisos de acceso
        '500':
          $ref: '#/components/responses/InternalServerError'
    put:
      summary: Actualizar registro histórico
      description: '**Actualiza información de un registro histórico existente**.


        ## 📝 Campos actualizables

        - Información del conductor (si cambió la tarjeta)

        - Información del vehículo

        - Notas o comentarios adicionales

        - **No se pueden modificar datos del tacógrafo original**


        ## ✅ Validaciones

        - El registro debe existir y pertenecer al usuario

        - Solo campos permitidos pueden actualizarse

        - Mantiene integridad de datos originales


        ## ⚠️ Restricciones

        - Datos del tacógrafo son inmutables

        - Solo metadatos administrativos pueden cambiarse

        - Cambios se auditan automáticamente

        '
      operationId: updateHistoricalDrivingRecord
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                conductor:
                  type: object
                  properties:
                    nombre:
                      type: string
                      example: Juan
                    apellidos:
                      type: string
                      example: Pérez García
                    numeroTarjeta:
                      type: string
                      pattern: ^[A-Z]{2}[0-9]{14}$
                      example: ES123456789012345
                    fechaCaducidad:
                      type: string
                      format: date-time
                      example: '2026-12-31T23:59:59.000Z'
                vehiculo:
                  type: object
                  properties:
                    matricula:
                      type: string
                      maxLength: 10
                      example: 1234ABC
                notas:
                  type: string
                  description: Notas administrativas opcionales
                  maxLength: 500
                  example: Registro verificado manualmente - datos correctos
            example:
              conductor:
                nombre: Juan
                apellidos: Pérez García
                numeroTarjeta: ES123456789012345
                fechaCaducidad: '2026-12-31T23:59:59.000Z'
              vehiculo:
                matricula: 1234ABC
              notas: Registro verificado manualmente - datos correctos
      responses:
        '200':
          description: Registro actualizado exitosamente
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HistoricalDrivingRecord'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: Registro no encontrado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Registro histórico no encontrado o sin permisos de acceso
        '500':
          $ref: '#/components/responses/InternalServerError'
    delete:
      summary: Eliminar registro histórico
      description: '**Elimina permanentemente un registro histórico del sistema**.


        ## ⚠️ Operación destructiva

        - **Requiere justificación legal para eliminación**

        - Elimina todos los datos asociados (actividades, eventos, análisis)

        - **No se puede deshacer**


        ## 🔒 Restricciones

        - Solo administradores pueden eliminar registros

        - Registros con más de 2 años requieren aprobación especial

        - Operación auditada y registrada


        ## 📋 Consecuencias

        - Se pierden datos de cumplimiento histórico

        - Afecta reportes y análisis retrospectivos

        - Requiere documentación legal de eliminación

        '
      operationId: deleteHistoricalDrivingRecord
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      responses:
        '204':
          description: Registro eliminado exitosamente (sin contenido)
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Permisos insuficientes
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Solo administradores pueden eliminar registros históricos
        '404':
          description: Registro no encontrado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Registro histórico no encontrado
        '409':
          description: No se puede eliminar
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Registro no puede eliminarse por restricciones legales
        '500':
          $ref: '#/components/responses/InternalServerError'
  /historical-driving/{id}/analysis:
    parameters:
    - $ref: '#/components/parameters/RecordId'
    - $ref: '#/components/parameters/Language'
    get:
      summary: Obtener análisis detallado del registro
      description: '**Obtiene un análisis completo del registro de tacógrafo**.

        Incluye métricas de conducción, eventos y cumplimiento normativo.

        '
      operationId: getHistoricalDrivingAnalysis
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      responses:
        '200':
          description: Análisis obtenido exitosamente
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HistoricalDrivingAnalysis'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /historical-driving/{id}/events:
    parameters:
    - $ref: '#/components/parameters/RecordId'
    - $ref: '#/components/parameters/Language'
    get:
      summary: Listar eventos del registro histórico
      description: '**Obtiene la lista de eventos registrados en el tacógrafo**.

        Incluye eventos del tacógrafo y eventos manuales agregados.

        '
      operationId: getHistoricalDrivingEvents
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      responses:
        '200':
          description: Eventos obtenidos exitosamente
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        tipo:
                          type: string
                        fechaHora:
                          type: string
                          format: date-time
                        descripcion:
                          type: string
                        gravedad:
                          type: string
                  pagination:
                    type: object
                    properties:
                      total:
                        type: integer
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /drivers/{id}:
    parameters:
    - $ref: '#/components/parameters/DriverId'
    - $ref: '#/components/parameters/Language'
    get:
      summary: Obtener conductor por ID
      description: '**Obtiene la información completa de un conductor específico**.


        ## 🔍 Detalles incluidos

        - Información personal y de licencia

        - Posición actual y estado de horas

        - Historial de posiciones (últimos 30 días)

        - Historial de conducción (últimos 6 meses)


        ## 🔒 Permisos

        - Solo el propietario del conductor puede acceder

        - Validación automática por campo `owner`

        '
      operationId: getDriverById
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      responses:
        '200':
          description: Información del conductor obtenida exitosamente
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Driver'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: Conductor no encontrado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Conductor no encontrado o sin permisos de acceso
        '500':
          $ref: '#/components/responses/InternalServerError'
    put:
      summary: Actualizar conductor
      description: '**Actualiza la información de un conductor existente**.


        ## 📝 Campos actualizables

        - `name`: Nombre completo

        - `enabled`: Estado de habilitación

        - `licenseNumber`: **No se puede cambiar** (requiere eliminación y recreación)


        ## ✅ Validaciones

        - El conductor debe existir y pertenecer al usuario

        - Nombre debe tener 3-100 caracteres

        - Solo campos permitidos pueden actualizarse


        ## ⚠️ Consideraciones

        - Cambiar `enabled` a `false` deshabilita el conductor para nuevas rutas

        - No afecta datos históricos existentes

        '
      operationId: updateDriver
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  minLength: 3
                  maxLength: 100
                  example: Juan Pérez García
                enabled:
                  type: boolean
                  example: true
              required:
              - name
              - enabled
            example:
              name: Juan Pérez García
              enabled: true
      responses:
        '200':
          description: Conductor actualizado exitosamente
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Driver'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: Conductor no encontrado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Conductor no encontrado o sin permisos de acceso
        '500':
          $ref: '#/components/responses/InternalServerError'
    delete:
      summary: Eliminar conductor
      description: '**Elimina permanentemente un conductor del sistema**.


        ## ⚠️ Operación destructiva

        - **No se puede deshacer**

        - Elimina todos los datos asociados (posiciones, horas, historial)


        ## 🔒 Restricciones

        - Solo el propietario puede eliminar

        - Conductor debe existir

        - No elimina datos de registros históricos de tacógrafo


        ## 📋 Consecuencias

        - Se pierden todas las posiciones históricas

        - Se pierden todos los registros de horas

        - El conductor desaparece de todas las búsquedas

        '
      operationId: deleteDriver
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      responses:
        '204':
          description: Conductor eliminado exitosamente (sin contenido)
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: Conductor no encontrado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Conductor no encontrado o sin permisos de acceso
        '500':
          $ref: '#/components/responses/InternalServerError'
  /drivers/{id}/position:
    parameters:
    - $ref: '#/components/parameters/DriverId'
    - $ref: '#/components/parameters/Language'
    get:
      summary: Obtener posición actual del conductor
      description: '**Obtiene la posición GPS más reciente del conductor**.


        ## 📍 Información proporcionada

        - Coordenadas actuales (longitud, latitud)

        - Timestamp exacto de la última actualización

        - Precisión GPS (cuando disponible)


        ## ⏰ Actualización

        - Las posiciones se actualizan automáticamente cada 5 minutos

        - Si no hay posición reciente (>30 min), se devuelve `null`


        ## 📊 Uso típico

        - Mostrar ubicación en mapas en tiempo real

        - Calcular tiempos estimados de llegada

        - Verificar si el conductor está en ruta activa

        '
      operationId: getDriverPosition
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      responses:
        '200':
          description: Posición obtenida exitosamente
          content:
            application/json:
              schema:
                type: object
                properties:
                  coordinates:
                    type: array
                    items:
                      type: number
                      format: float
                    minItems: 2
                    maxItems: 2
                    description: '[longitud, latitud]'
                    example:
                    - -3.7038
                    - 40.4168
                  timestamp:
                    type: string
                    format: date-time
                    description: Fecha y hora de la posición
                    example: '2025-04-30T10:30:00.000Z'
                  accuracy:
                    type: number
                    description: Precisión GPS en metros (opcional)
                    example: 10
                nullable: true
              example:
                coordinates:
                - -3.7038
                - 40.4168
                timestamp: '2025-04-30T10:30:00.000Z'
                accuracy: 10
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: Conductor no encontrado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Conductor no encontrado o sin permisos de acceso
        '429':
          description: Límite de consultas excedido
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Límite de consultas de posición excedido (10 por segundo)
        '500':
          $ref: '#/components/responses/InternalServerError'
    put:
      summary: Actualizar posición del conductor
      description: '**Actualiza la posición GPS actual del conductor**.


        ## 📍 Requisitos

        - Coordenadas válidas (latitud -90/+90, longitud -180/+180)

        - Timestamp no futuro (máximo 5 minutos de diferencia)

        - Precisión mínima: 6 decimales (~11cm)


        ## ⏱️ Limitaciones

        - **Máximo 1 actualización por minuto** por conductor

        - Las actualizaciones se almacenan automáticamente en el historial

        - Posiciones antiguas (>30 días) se purgan automáticamente


        ## 🔄 Efectos

        - Actualiza `currentPosition` del conductor

        - Agrega entrada al `positionHistory`

        - Recalcula estado de horas si está en actividad de conducción

        '
      operationId: updateDriverPosition
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PositionUpdate'
            example:
              coordinates:
              - -3.7038
              - 40.4168
              timestamp: '2025-04-30T10:30:00.000Z'
      responses:
        '200':
          description: Posición actualizada exitosamente
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  position:
                    $ref: '#/components/schemas/PositionUpdate'
                  message:
                    type: string
                    example: Posición actualizada correctamente
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: Conductor no encontrado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Conductor no encontrado o sin permisos de acceso
        '429':
          description: Límite de actualizaciones excedido
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Límite de actualizaciones de posición excedido (1 por minuto)
        '500':
          $ref: '#/components/responses/InternalServerError'
  /drivers/{id}/positions:
    parameters:
    - $ref: '#/components/parameters/DriverId'
    - $ref: '#/components/parameters/Language'
    - $ref: '#/components/parameters/StartDate'
    - $ref: '#/components/parameters/EndDate'
    - $ref: '#/components/parameters/Page'
    - $ref: '#/components/parameters/PageSize'
    get:
      summary: Obtener historial de posiciones del conductor
      description: '**Obtiene el historial completo de posiciones GPS del conductor**.


        ## 📊 Información incluida

        - Todas las posiciones registradas en el rango de fechas

        - Coordenadas y timestamps exactos

        - Información de precisión GPS (cuando disponible)


        ## 📅 Rangos de fecha

        - **Por defecto**: Últimas 24 horas

        - **Máximo**: 30 días por consulta

        - **Formato**: ISO 8601 (`YYYY-MM-DD` o `YYYY-MM-DDTHH:mm:ssZ`)


        ## 📈 Paginación

        - Máximo 1000 posiciones por página

        - Ordenadas por timestamp descendente (más recientes primero)

        - Total disponible en metadatos de paginación


        ## 💾 Retención

        - Las posiciones se retienen por **30 días**

        - Posiciones más antiguas se eliminan automáticamente

        - Datos históricos se usan para auditoría y reconstrucción de rutas

        '
      operationId: getDriverPositions
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      responses:
        '200':
          description: Historial de posiciones obtenido exitosamente
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        coordinates:
                          type: array
                          items:
                            type: number
                            format: float
                          minItems: 2
                          maxItems: 2
                          example:
                          - -3.7038
                          - 40.4168
                        timestamp:
                          type: string
                          format: date-time
                          example: '2025-04-30T10:30:00.000Z'
                        accuracy:
                          type: number
                          description: Precisión GPS en metros
                          example: 10
                  pagination:
                    type: object
                    properties:
                      page:
                        type: integer
                        example: 1
                      pageSize:
                        type: integer
                        example: 100
                      total:
                        type: integer
                        example: 1250
                      totalPages:
                        type: integer
                        example: 13
                example:
                  data:
                  - coordinates:
                    - -3.7038
                    - 40.4168
                    timestamp: '2025-04-30T10:30:00.000Z'
                    accuracy: 10
                  - coordinates:
                    - -3.71
                    - 40.42
                    timestamp: '2025-04-30T10:25:00.000Z'
                    accuracy: 8
                  - coordinates:
                    - -3.715
                    - 40.425
                    timestamp: '2025-04-30T10:20:00.000Z'
                    accuracy: 12
                  pagination:
                    page: 1
                    pageSize: 100
                    total: 1250
                    totalPages: 13
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: Conductor no encontrado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Conductor no encontrado o sin permisos de acceso
        '429':
          description: Límite de consultas excedido
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Límite de consultas de posición excedido (10 por segundo)
        '500':
          $ref: '#/components/responses/InternalServerError'
