> For the complete documentation index, see [llms.txt](https://navixy.com/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://navixy.com/docs/analytics/es/example-queries/leasing.md).

# Arrendamiento

Plantillas de consultas SQL para análisis bancarios y de arrendamiento, que abarcan ciclo de vida del activo, cumplimiento de contratos, programación del mantenimiento y seguimiento de límites de uso

{% hint style="warning" %}
Activar **IoT Query** Antes de utilizar los datos para crear analíticas integrales. Si todavía no lo tiene, contáctenos para obtener detalles de activación - <iotquery@navixy.com>
{% endhint %}

Las empresas de arrendamiento (en particular, los bancos y los proveedores de arrendamiento de flotas) conservan la propiedad del vehículo o equipo mientras el cliente solo renta su uso, por lo que asumen el riesgo relacionado con el activo durante todo el contrato. 

Para proteger el valor residual, hacer cumplir los límites contractuales (kilometraje, geografía, mantenimiento) y agilizar las obligaciones de servicio integral, dependen de Navixy. Los datos GPS en tiempo real, los diagnósticos basados en sensores y la analítica del comportamiento les permiten verificar las condiciones de uso, automatizar la programación del servicio, detectar problemas mecánicos de forma temprana, calcular penalizaciones o cargos por kilometraje excedente y, cuando sea necesario, inmovilizar o recuperar el activo; todo esto asegura su inversión, reduce el costo operativo y mejora la transparencia para el cliente durante todo el ciclo de vida del arrendamiento.

Navixy **IoT Query** ayudará a organizar cualquier tipo de analítica en cada etapa del contrato de arrendamiento. Un contrato de arrendamiento pasa por varias fases predecibles: Incorporación y configuración del activo → Fase operativa → Supervisión de riesgos y cumplimiento

En conjunto, las siguientes recetas SQL de su libro monitorean cada hito crítico a lo largo de ese ciclo de vida:

| Fase del ciclo de vida                                   | Objetivos e hitos                                                                                                                                   | Casos de uso / recetas cubiertos                                                                                                                                                                                                     |
| -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Incorporación y configuración del activo                 | • Registrar el vehículo, activar el seguro y las credenciales del conductor. • Importar activos al portal del cliente con la visibilidad correcta.  | Alertas de vencimiento de registro/seguro – fechas base capturadas. Vencimiento de la licencia del conductor – valida a los conductores antes de la entrega.                                                                         |
| Planificación de mantenimiento preventivo                | • Establezca programaciones de servicio recurrentes, basadas en kilometraje y basadas en tiempo. • Garantice los cambios estacionales de llantas.   | Inspecciones periódicas por intervalo – tareas guiadas por calendario. Servicio por umbral de kilometraje – reglas de servicio menor/mayor guiadas por km. Monitoreo de horas del motor – servicio guiado por horas para maquinaria. |
| Límites de uso sujetos al contrato                       | • Haga cumplir las asignaciones de kilometraje y los topes financieros. • Detecte el sobreuso a tiempo para evitar sorpresas al final del contrato. | Tope de kilometraje y penalizaciones – control anual / del kilometraje total del contrato.                                                                                                                                           |
| Comportamiento en tiempo real del conductor y del activo | • Proteja el valor del activo; oriente a los conductores. • Detecte el uso indebido que invalida la cobertura de «servicio completo».               | Frenado brusco. Aceleración brusca. Giros bruscos/toma de curvas.                                                                                                                                                                    |
| Supervisión de riesgos y cumplimiento                    | • Mantenga los activos dentro de los límites geográficos y contractuales. • Conserve el derecho de desactivar o recuperar.                          | Salida de geocerca (frontera del país) – alerta instantánea ante una infracción del territorio. Ignición & detección de inactividad – seguimiento del desperdicio / uso indebido de Combustible.                                     |

### Plantilla de tablero

Aunque las recetas SQL a continuación ofrecen control completo sobre la analítica de arrendamiento, puede empezar más rápido con un tablero prediseñado que visualiza métricas críticas a lo largo del ciclo de vida del arrendamiento. La plantilla elimina la creación de consultas y visualizaciones desde cero. Impórtela, ajuste los parámetros y comience a monitorear de inmediato el cumplimiento, el riesgo y la protección del Activo.

La plantilla aborda flujos de trabajo clave de arrendamiento: seguimiento del vencimiento del registro y del Seguro, monitoreo de la licencia del Conductor, detección de Frenado brusco y aceleración con clasificaciones de severidad, análisis del tiempo de inactividad y monitoreo de actividad del Dispositivo.

<figure><img src="https://3863334083-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoFNFEIINiGFbhi3Px3dE%2Fuploads%2Fgit-blob-64ef38d2255e595e6b5ee405e94ff208302d8131%2Fimage%20(16).png?alt=media" alt=""><figcaption></figcaption></figure>

Importe la configuración en [Dashboard Studio](https://marketplace.navixy.com/shop/dashboard-studio/)ajuste los umbrales para sus contratos (límites de Kilometraje, niveles de severidad del comportamiento, parámetros de detección de inactividad) y despliegue un espacio de trabajo de monitoreo completo. Esto funciona bien cuando los equipos necesitan tableros operativos para la supervisión diaria del cumplimiento y del riesgo sin escribir SQL.

**Requisitos previos:**

* IoT Query disponible en su entorno
* Dashboard Studio instalado y accesible
* Al menos 72 horas de datos de seguimiento
* Tablas estándar del esquema pobladas: `Seguimiento_datos_núcleo`, `estados`, `objetos`, `Gestión de vehículos`, `Empleados`

**Configuración después de la importación:**

Después de importar la plantilla, adáptela a sus contratos de arrendamiento específicos y umbrales operativos:

1. Revise el rango de tiempo predeterminado de 72 horas y ajústelo si la disponibilidad de sus datos es diferente.
2. Configure umbrales de severidad para eventos de manejo en los parámetros de la consulta (predeterminado: 60+ km/h/s para advertencias, 80+ km/h/s para alertas críticas).
3. Configure los parámetros de detección de ralentí (predeterminado: velocidad por debajo de 5 km/h, duración mínima de 5 minutos).
4. Actualice las etiquetas de la zona de geocerca en la consulta de cruce de frontera si monitorea restricciones territoriales.
5. Use el selector global de tiempo para analizar periodos históricos o centrarse en la actividad reciente.

**JSON de la plantilla:**

{% file src="/files/7c52da888666fa7790bf65c2a28d60e8f1bb810b" %}

{% code lineNumbers="true" expandable="true" %}

```json
{
  "id": null,
  "uid": "hola-mundo",
  "Etiquetas": [
    "ejemplo",
    "primeros-pasos"
  ],
  "time": {
    "to": "ahora",
    "from": "ahora-72h"
  },
  "links": [],
  "style": "oscuro", 
  "title": "Panel de arrendamiento",
  "panels": [
    {
      "id": 10,
      "type": "text",
      "title": "Detección de Ignición y ralentí",
      "gridPos": {
        "h": 4,
        "w": 24,
        "x": 0,
        "y": 158
      },
      "opciones": {
        "modo": "markdown",
        "contenido": " "
      },
      "x-navixy": {
        "sql": {
          "sentencia": ""
        },
        "conjunto de datos": {
          "forma": "tabla",
          "columnas": {}
        }
      }
    },
    {
      "id": 11,
      "type": "piechart",
      "title": "Conductores con las fechas de vencimiento más próximas",
      "gridPos": {
        "h": 12,
        "w": 12,
        "x": 12,
        "y": 0
      },
      "opciones": {
        "pieType": "donut"
      },
      "x-navixy": {
        "sql": {
          "params": {},
          "statement": "SELECT \r\n    CASE \r\n        WHEN (DATE(e.driver_license_valid_till) - CURRENT_DATE)::INTEGER < 0 THEN 'Vencida'\r\n        ELSE 'Otros'\r\n    END AS category,\r\n    COUNT(*) AS value\r\nFROM raw_business_data.employees e\r\nWHERE e.driver_license_valid_till IS NOT NULL\r\nGROUP BY category\r\nORDER BY category"
        },
        "verificar": {
          "max_rows": 1000
        },
        "conjunto de datos": {
          "shape": "pie",
          "columns": {
            "value": {
              "type": "integer"
            },
            "category": {
              "type": "string"
            }
          }
        }
      }
    },
    {
      "id": 12,
      "type": "piechart",
      "title": "Gestión de vehículos con las fechas de vencimiento más próximas",
      "gridPos": {
        "h": 12,
        "w": 12,
        "x": 0,
        "y": 0
      },
      "opciones": {
        "pieType": "donut"
      },
      "x-navixy": {
        "sql": {
          "params": {},
          "statement": "WITH expiry_data AS (\r\n    SELECT \r\n        CASE \r\n            WHEN v.free_insurance_valid_till_date IS NOT NULL\r\n                AND (v.liability_insurance_valid_till IS NULL \r\n                      OR v.free_insurance_valid_till_date <= v.liability_insurance_valid_till)\r\n                THEN v.free_insurance_valid_till_date\r\n            WHEN v.liability_insurance_valid_till IS NOT NULL\r\n                THEN v.liability_insurance_valid_till\r\n            ELSE NULL\r\n        END AS nearest_expiry_date\r\n    FROM raw_business_data.vehicles v\r\n),\r\ncategorized_data AS (\r\n    SELECT \r\n        CASE \r\n            WHEN (DATE(nearest_expiry_date) - CURRENT_DATE)::INTEGER < 0 THEN 'Expirado'\r\n            WHEN (DATE(nearest_expiry_date) - CURRENT_DATE)::INTEGER >= 0 \r\n                  AND (DATE(nearest_expiry_date) - CURRENT_DATE)::INTEGER < 30 THEN 'Expira dentro de 30 días'\r\n            ELSE 'Otros'\r\n        END AS category\r\n    FROM expiry_data\r\n    WHERE nearest_expiry_date IS NOT NULL\r\n)\r\nSELECT \r\n    category,\r\n    COUNT(*) AS value\r\nFROM categorized_data\r\nGROUP BY category\r\nORDER BY \r\n    CASE category\r\n        WHEN 'Expirado' THEN 1\r\n        WHEN 'Expira dentro de 30 días' THEN 2\r\n        WHEN 'Otros' THEN 3\r\n    END"
        },
        "verificar": {
          "max_rows": 1000
        },
        "conjunto de datos": {
          "shape": "pie",
          "columns": {
            "value": {
              "type": "integer"
            },
            "category": {
              "type": "string"
            }
          }
        }
      }
    },
    {
      "id": 13,
      "type": "barchart",
      "title": "Eventos de Frenado brusco",
      "gridPos": {
        "h": 11,
        "w": 24,
        "x": 0,
        "y": 12
      },
      "opciones": {
        "textMode": "auto"
      },
      "x-navixy": {
        "sql": {
          "params": {},
          "statement": "WITH spd AS (\r\n          SELECT\r\n            device_id,\r\n            device_time,\r\n            speed/100.0 AS kmh,\r\n            LAG(speed/100.0) OVER (PARTITION BY device_id ORDER BY device_time) AS prev_kmh,\r\n            EXTRACT(EPOCH FROM (device_time - LAG(device_time) OVER (PARTITION BY device_id ORDER BY device_time))) AS dt_sec\r\n          FROM\r\n            raw_telematics_data.tracking_data_core\r\n          WHERE 1=1\r\n        ),\r\n        decels AS (\r\n          SELECT\r\n            device_id,\r\n            device_time,\r\n            (prev_kmh - kmh) / NULLIF(dt_sec, 0) AS decel_kmh_per_sec\r\n          FROM\r\n            spd\r\n          WHERE\r\n            prev_kmh IS NOT NULL\r\n        ),\r\n        events_with_severity AS (\r\n          SELECT \r\n            DATE(d.device_time) AS category,\r\n            CASE \r\n              WHEN d.decel_kmh_per_sec >= 80 THEN 'Crítico'\r\n              WHEN d.decel_kmh_per_sec >= 60 THEN 'Advertencia'\r\n              ELSE 'Normal'\r\n            END AS series\r\n          FROM decels d\r\n          WHERE d.decel_kmh_per_sec >= 60\r\n        )\r\n        SELECT \r\n          category,\r\n          COUNT(*) AS value,\r\n          series\r\n        FROM events_with_severity\r\n        GROUP BY category, series\r\n        ORDER BY series"
        },
        "verificar": {
          "max_rows": 1000
        },
        "conjunto de datos": {
          "shape": "category_value",
          "columns": {
            "value": {
              "type": "integer"
            },
            "series": {
              "type": "string"
            },
            "category": {
              "type": "date"
            }
          }
        },
        "visualización": {
          "sortOrder": "none",
          "colorPalette": "vibrante"
        }
      }
    },
    {
      "id": 14,
      "type": "barchart",
      "title": "Eventos de Aceleración brusca",
      "gridPos": {
        "h": 17,
        "w": 24,
        "x": 0,
        "y": 41
      },
      "opciones": {
        "orientation": "vertical"
      },
      "x-navixy": {
        "sql": {
          "params": {},
          "statement": "WITH spd AS (\r\n          SELECT\r\n            device_id,\r\n            device_time,\r\n            speed/100.0 AS kmh,\r\n            LAG(speed/100.0) OVER (PARTITION BY device_id ORDER BY device_time) AS prev_kmh,\r\n            EXTRACT(EPOCH FROM (device_time - LAG(device_time) OVER (PARTITION BY device_id ORDER BY device_time))) AS dt_sec\r\n          FROM\r\n            raw_telematics_data.tracking_data_core\r\n        ),\r\n        accels AS (\r\n          SELECT\r\n            device_id,\r\n            device_time,\r\n            (kmh - prev_kmh) / NULLIF(dt_sec, 0) AS accel_kmh_per_sec\r\n          FROM\r\n            spd\r\n          WHERE\r\n            prev_kmh IS NOT NULL\r\n        ),\r\n        events_with_severity AS (\r\n          SELECT \r\n            DATE(a.device_time) AS category,\r\n            CASE \r\n              WHEN a.accel_kmh_per_sec >= 80 THEN 'Crítico'\r\n              WHEN a.accel_kmh_per_sec >= 60 THEN 'Advertencia'\r\n              ELSE 'Normal'\r\n            END AS series\r\n          FROM accels a\r\n          WHERE a.accel_kmh_per_sec >= 60\r\n        )\r\n        SELECT \r\n          category,\r\n          COUNT(*) AS value,\r\n          series\r\n        FROM events_with_severity\r\n        GROUP BY category, series\r\n        ORDER BY series"
        },
        "verificar": {
          "max_rows": 1000
        },
        "conjunto de datos": {
          "shape": "category_value",
          "columns": {
            "value": {
              "type": "integer"
            },
            "series": {
              "type": "string"
            },
            "category": {
              "type": "date"
            }
          }
        },
        "visualización": {
          "colorPalette": "vibrante"
        }
      }
    },
    {
      "id": 15,
      "type": "barchart",
      "title": "Giros bruscos / toma de curvas",
      "gridPos": {
        "h": 13,
        "w": 24,
        "x": 0,
        "y": 23
      },
      "opciones": {
        "orientation": "vertical"
      },
      "x-navixy": {
        "sql": {
          "params": {},
          "declaración": "WITH pts AS (\r\n          SELECT\r\n            device_id,\r\n            device_time,\r\n            latitude/1e7::numeric AS lat,\r\n            longitude/1e7::numeric AS lon,\r\n            LAG(latitude/1e7::numeric) OVER (PARTITION BY device_id ORDER BY device_time) AS prev_lat,\r\n            LAG(longitude/1e7::numeric) OVER (PARTITION BY device_id ORDER BY device_time) AS prev_lon,\r\n            speed/100.0 AS kmh,\r\n            LAG(speed/100.0) OVER (PARTITION BY device_id ORDER BY device_time) AS prev_kmh\r\n          FROM\r\n            raw_telematics_data.tracking_data_core\r\n        ),\r\n        bearing AS (\r\n          SELECT *,\r\n                 atan2(\r\n                   sin(radians(lon-prev_lon))*cos(radians(lat)),\r\n                   cos(radians(prev_lat))*sin(radians(lat)) -\r\n                   sin(radians(prev_lat))*cos(radians(lat))*cos(radians(lon-prev_lon))\r\n                 ) * 180/pi() AS heading_change\r\n          FROM pts\r\n          WHERE prev_lat IS NOT NULL AND prev_lon IS NOT NULL\r\n        ),\r\n        events_with_severity AS (\r\n          SELECT \r\n            DATE(b.device_time) AS category,\r\n            CASE \r\n              WHEN ABS(b.heading_change) >= 50 AND b.kmh >= 30 THEN 'Crítico'\r\n              WHEN ABS(b.heading_change) >= 30 AND b.kmh >= 30 THEN 'Advertencia'\r\n              ELSE 'Normal'\r\n            END AS series\r\n          FROM bearing b\r\n        )\r\n        SELECT \r\n          category,\r\n          COUNT(*) AS value,\r\n          series\r\n        FROM events_with_severity\r\n        GROUP BY category, series\r\n        ORDER BY category, series"
        },
        "verificar": {
          "max_rows": 1000
        },
        "conjunto de datos": {
          "shape": "category_value",
          "columns": {
            "value": {
              "type": "integer"
            },
            "series": {
              "type": "string"
            },
            "category": {
              "type": "date"
            }
          }
        },
        "visualización": {
          "stacking": "percent",
          "colorPalette": "classic"
        }
      }
    },
    {
      "id": 16,
      "type": "stat",
      "title": "Eventos totales de ralentí",
      "gridPos": {
        "h": 5,
        "w": 8,
        "x": 0,
        "y": 36
      },
      "opciones": {
        "textMode": "auto"
      },
      "x-navixy": {
        "sql": {
          "params": {},
          "declaración": "WITH ign AS (\r\n          SELECT device_id,\r\n                 device_time,\r\n                 value::int AS ign_on\r\n          FROM raw_telematics_data.states\r\n          WHERE state_name = 'ignition'\r\n        ),\r\n        spd AS (\r\n          SELECT device_id, device_time, speed/100.0 AS kmh\r\n          FROM raw_telematics_data.tracking_data_core\r\n        ),\r\n        merged AS (\r\n          SELECT i.device_id,\r\n                 i.device_time,\r\n                 i.ign_on,\r\n                 s.kmh,\r\n                 LEAD(i.device_time) OVER (PARTITION BY i.device_id ORDER BY i.device_time) AS next_time\r\n          FROM ign i\r\n          LEFT JOIN spd s ON s.device_id = i.device_id AND s.device_time = i.device_time\r\n        )\r\n        SELECT COUNT(*) AS value\r\n        FROM merged m\r\n        WHERE m.ign_on = 1 \r\n          AND (m.kmh IS NULL OR m.kmh < 5) \r\n          AND m.next_time IS NOT NULL\r\n          AND EXTRACT(EPOCH FROM (m.next_time - m.device_time))/60 >= 5"
        },
        "verificar": {
          "max_rows": 1000
        },
        "conjunto de datos": {
          "shape": "kpi",
          "columnas": {}
        }
      }
    },
    {
      "id": 9,
      "type": "timeseries",
      "title": "Mensajes a lo largo del tiempo",
      "gridPos": {
        "h": 13,
        "w": 24,
        "x": 0,
        "y": 83
      },
      "opciones": {
        "legend": {
          "calcs": [],
          "placement": "bottom",
          "showLegend": true,
          "displayMode": "list"
        },
        "tooltip": {
          "mode": "single",
          "sort": "none"
        }
      },
      "targets": [],
      "x-navixy": {
        "sql": {
          "params": {},
          "statement": "WITH bounds AS (\nSELECT date_trunc('hour', NOW() - INTERVAL '24 hours') AS start_ts, date_trunc('hour', NOW()) AS end_ts ), hours AS (\nSELECT generate_series( (\nSELECT start_ts\nFROM bounds), (\nSELECT end_ts\nFROM bounds), INTERVAL '1 hour' ) AS bucket ), counts AS (\nSELECT date_trunc('hour', t.device_time) AS bucket, COUNT(*) AS messages, COUNT(DISTINCT t.device_id) AS unique_devices\nFROM raw_telematics_data.tracking_data_core t --\n    JOIN raw_business_data.objects o\n  ON o.device_id = t.device_id --\n  AND o.client_id = 398286 -- uncomment & set if you want a specific client\nWHERE t.device_time >= (\nSELECT start_ts\nFROM bounds)\n  AND t.device_time < (\nSELECT end_ts\nFROM bounds) + INTERVAL '1 hour'\nGROUP BY 1 )\nSELECT h.bucket AS time, COALESCE(c.messages, 0) AS messages, COALESCE(c.unique_devices, 0) AS unique_devices\nFROM hours h LEFT\n    JOIN counts c USING (bucket)\nORDER BY time;"
        },
        "verificar": {
          "max_rows": 1000
        },
        "conjunto de datos": {
          "shape": "time_value",
          "columnas": {}
        },
        "visualización": {
          "lineStyle": "solid",
          "colorPalette": "modern",
          "interpolation": "smooth",
          "legendPosition": "top"
        }
      },
      "datasource": null,
      "fieldConfig": {
        "defaults": {
          "unit": "short",
          "color": {
            "mode": "palette-classic"
          },
          "custom": {
            "apilamiento": {
              "mode": "none",
              "grupo": "A"
            },
            "drawStyle": "line",
            "lineWidth": 1,
            "spanNulls": false,
            "showPoints": "auto",
            "fillOpacity": 10,
            "gradientMode": "none",
            "axisPlacement": "auto",
            "lineInterpolation": "linear"
          },
          "mappings": [],
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              }
            ]
          }
        },
        "overrides": []
      }
    },
    {
      "id": 1,
      "type": "kpi",
      "title": "Conteo de muestras",
      "gridPos": {
        "h": 5,
        "w": 6,
        "x": 18,
        "y": 128
      },
      "opciones": {
        "textMode": "auto",
        "colorMode": "value",
        "graphMode": "none",
        "justifyMode": "auto",
        "orientation": "auto"
      },
      "targets": [],
      "x-navixy": {
        "sql": {
          "params": {
            "tenant_id": {
              "type": "uuid"
            }
          },
          "statement": "SELECT *\nFROM raw_telematics_data.tracking_data_core LIMIT 10;"
        },
        "verificar": {
          "max_rows": 1
        },
        "conjunto de datos": {
          "shape": "kpi",
          "columns": {
            "value": {
              "type": "number"
            }
          }
        }
      },
      "datasource": null,
      "description": "",
      "fieldConfig": {
        "defaults": {
          "unit": "short",
          "color": {
            "mode": "thresholds"
          },
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              }
            ]
          }
        },
        "overrides": []
      }
    },
    {
      "id": 2,
      "type": "barchart",
      "title": "Datos de ejemplo por categoría",
      "gridPos": {
        "h": 15,
        "w": 18,
        "x": 0,
        "y": 130
      },
      "opciones": {
        "valueMode": "color",
        "displayMode": "gradient",
        "orientation": "horizontal",
        "showUnfilled": true
      },
      "targets": [],
      "x-navixy": {
        "sql": {
          "params": {},
          "statement": "SELECT o.object_label, COUNT(*) AS msgs_24h\nFROM raw_telematics_data.tracking_data_core AS t\n    JOIN raw_business_data.objects AS o\n  ON o.device_id = t.device_id\nWHERE t.device_time >= NOW() - INTERVAL '24 hours'\nGROUP BY o.client_id, o.object_label, t.device_id\nORDER BY msgs_24h DESC LIMIT 20;"
        },
        "verificar": {
          "max_rows": 10
        },
        "conjunto de datos": {
          "shape": "category_value",
          "columnas": {}
        },
        "visualización": {
          "orientation": "vertical"
        }
      },
      "datasource": null,
      "fieldConfig": {
        "defaults": {
          "unit": "short",
          "color": {
            "mode": "palette-classic"
          },
          "custom": {
            "hideFrom": {
              "viz": false,
              "legend": false,
              "tooltip": false
            }
          },
          "mappings": [],
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              }
            ]
          }
        },
        "overrides": []
      }
    },
    {
      "id": 3,
      "type": "table",
      "title": "Mensajes por día,",
      "gridPos": {
        "h": 9,
        "w": 12,
        "x": 4,
        "y": 148
      },
      "opciones": {
        "sortBy": [],
        "showHeader": true
      },
      "targets": [],
      "x-navixy": {
        "sql": {
          "params": {
            "__to": null,
            "__from": null
          },
          "statement": "SELECT TO_CHAR(date_trunc('day', t.device_time), 'Mon DD, YYYY') AS \"Fecha\", \n       COUNT(*) AS \"Mensajes\"\nFROM raw_telematics_data.tracking_data_core AS t\nWHERE t.device_time >= ${__from}\n  AND t.device_time < ${__to}\nGROUP BY 1\nORDER BY 1;"
        },
        "verificar": {
          "max_rows": 10
        },
        "conjunto de datos": {
          "forma": "tabla",
          "columnas": {}
        },
        "visualización": {
          "pageSize": 5
        }
      },
      "datasource": null,
      "fieldConfig": {
        "defaults": {
          "custom": {
            "align": "auto",
            "displayMode": "auto"
          },
          "mappings": [],
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              }
            ]
          }
        },
        "overrides": []
      }
    },
    {
      "id": 6,
      "type": "kpi",
      "title": "Tiempo total en ralentí",
      "gridPos": {
        "h": 5,
        "w": 8,
        "x": 8,
        "y": 36
      },
      "opciones": {
        "textMode": "auto"
      },
      "x-navixy": {
        "sql": {
          "params": {},
          "statement": "WITH ign AS (\n    SELECT device_id,\n            device_time,\n            value::int AS ign_on\n    FROM raw_telematics_data.states\n    WHERE state_name = 'ignition'\n  ),\n  spd AS (\n    SELECT device_id, device_time, speed/100 AS kmh\n    FROM raw_telematics_data.tracking_data_core\n  ),\n  merged AS (\n    SELECT i.device_id,\n            i.device_time,\n            i.ign_on,\n            s.kmh,\n            LEAD(i.device_time) OVER (PARTITION BY i.device_id ORDER BY i.device_time) AS next_time\n    FROM ign i\n    LEFT JOIN spd s ON s.device_id = i.device_id AND s.device_time = i.device_time\n  )\n  SELECT round(COALESCE(SUM(EXTRACT(EPOCH FROM (m.next_time - m.device_time))/60), 0), 0) AS value\n  FROM merged m\n  WHERE m.ign_on = 1 \n    AND (m.kmh IS NULL OR m.kmh < 5) \n    AND m.next_time IS NOT NULL\n    AND EXTRACT(EPOCH FROM (m.next_time - m.device_time))/60 >= 5"
        },
        "verificar": {
          "max_rows": 1000
        },
        "conjunto de datos": {
          "shape": "kpi",
          "columns": {
            "value": {
              "type": "number"
            }
          }
        }
      }
    },
    {
      "id": 7,
      "type": "piechart",
      "title": "Dispositivos más activos en las últimas 24 h",
      "gridPos": {
        "h": 9,
        "w": 12,
        "x": 0,
        "y": 121
      },
      "opciones": {
        "pieType": "donut"
      },
      "x-navixy": {
        "sql": {
          "params": {},
          "statement": "SELECT o.object_label, COUNT(*) AS msgs_24h\nFROM raw_telematics_data.tracking_data_core AS t\n    JOIN raw_business_data.objects AS o\n  ON o.device_id = t.device_id\nWHERE t.device_time >= NOW() - INTERVAL '24 hours'\nGROUP BY o.client_id, o.object_label, t.device_id\nORDER BY msgs_24h DESC LIMIT 20;"
        },
        "verificar": {
          "max_rows": 1000
        },
        "conjunto de datos": {
          "shape": "pie",
          "columnas": {}
        }
      }
    },
    {
      "id": 8,
      "type": "table",
      "title": "Movimientos recientes del vehículo",
      "gridPos": {
        "h": 25,
        "w": 24,
        "x": 0,
        "y": 96
      },
      "opciones": {
        "showHeader": true
      },
      "x-navixy": {
        "sql": {
          "params": {},
          "statement": "SELECT\n  to_char(t.device_time, 'YYYY-MM-DD HH24:MI:SS TZ') AS \"Marca de tiempo\",\n  t.device_id                                       AS \"ID del dispositivo\",\n  t.speed                                           AS \"Velocidad\",\n  round(t.latitude::numeric  / 10000000, 6)         AS \"Latitud (°)\",\n  round(t.longitude::numeric / 10000000, 6)         AS \"Longitud (°)\"\nFROM raw_telematics_data.tracking_data_core t\nWHERE t.device_time >= NOW() - INTERVAL '3 days'\n  AND t.speed > 0\nORDER BY t.device_time DESC;"
        },
        "verificar": {
          "max_rows": 3
        },
        "conjunto de datos": {
          "forma": "tabla",
          "columns": {
            "Velocidad": {
              "type": "integer"
            },
            "ID del dispositivo": {
              "type": "integer"
            },
            "Marca de tiempo": {
              "type": "string"
            },
            "Latitud (°)": {
              "type": "number"
            },
            "Longitud (°)": {
              "type": "number"
            }
          }
        },
        "visualización": {
          "pageSize": 25,
          "sortable": true,
          "showHeader": true,
          "showTotals": false,
          "rowHighlighting": "hover"
        }
      }
    },
    {
      "id": 19,
      "type": "stat",
      "title": "Duración promedio de inactividad",
      "gridPos": {
        "h": 5,
        "w": 8,
        "x": 16,
        "y": 36
      },
      "opciones": {
        "textMode": "auto"
      },
      "x-navixy": {
        "sql": {
          "params": {},
          "sentencia": "WITH ign AS (\r\n          SELECT device_id,\r\n                 device_time,\r\n                 value::int AS ign_on\r\n          FROM raw_telematics_data.states\r\n          WHERE state_name = 'ignition'\r\n        ),\r\n        spd AS (\r\n          SELECT device_id, device_time, speed/100.0 AS kmh\r\n          FROM raw_telematics_data.tracking_data_core\r\n        ),\r\n        merged AS (\r\n          SELECT i.device_id,\r\n                 i.device_time,\r\n                 i.ign_on,\r\n                 s.kmh,\r\n                 LEAD(i.device_time) OVER (PARTITION BY i.device_id ORDER BY i.device_time) AS next_time\r\n          FROM ign i\r\n          LEFT JOIN spd s ON s.device_id = i.device_id AND s.device_time = i.device_time\r\n        )\r\n        SELECT round(COALESCE(AVG(EXTRACT(EPOCH FROM (m.next_time - m.device_time))/60), 0),0) AS value\r\n        FROM merged m\r\n        WHERE m.ign_on = 1 \r\n          AND (m.kmh IS NULL OR m.kmh < 5) \r\n          AND m.next_time IS NOT NULL\r\n          AND EXTRACT(EPOCH FROM (m.next_time - m.device_time))/60 >= 5"
        },
        "verificar": {
          "max_rows": 1000
        },
        "conjunto de datos": {
          "shape": "kpi",
          "columnas": {}
        }
      }
    }
  ],
  "refresh": "30s",
  "version": 1,
  "editable": true,
  "timezone": "browser",
  "x-navixy": {
    "ejecución": {
      "dialect": "postgresql",
      "endpoint": "/api/v1/sql/run",
      "max_rows": 1000,
      "read_only": true,
      "timeout_ms": 5000,
      "allowed_schemas": [
        "demo_data"
      ]
    },
    "parameters": {
      "bindings": {
        "to": "${__to}",
        "from": "${__from}",
        "tenant_id": "${var_tenant}"
      }
    },
    "schemaVersion": "1.0.0"
  },
  "templating": {
    "list": [
      {
        "name": "var_tenant",
        "type": "constant",
        "label": "Inquilino",
        "query": "demo-tenant-id",
        "current": {
          "text": "Inquilino de demostración",
          "value": "demo-tenant-id"
        },
        "options": [
          {
            "text": "Inquilino de demostración",
            "value": "demo-tenant-id",
            "selected": true
          }
        ]
      }
    ],
    "enable": true
  },
  "timepicker": {
    "now": true,
    "enable": true,
    "hidden": false,
    "collapse": false,
    "time_options": [
      "5m",
      "15m",
      "1h",
      "6h",
      "12h",
      "24h"
    ],
    "refresh_intervals": [
      "5s",
      "10s",
      "30s",
      "1m",
      "5m",
      "15m",
      "30 m",
      "1h"
    ]
  },
  "annotations": {
    "list": [
      {
        "hide": true,
        "name": "Anotaciones y Alertas",
        "type": "dashboard",
        "enable": true,
        "target": {
          "Etiquetas": [],
          "type": "dashboard",
          "limit": 100,
          "matchAny": false
        },
        "builtIn": 1,
        "iconColor": "rgba(0, 211, 255, 1)",
        "datasource": {
          "uid": "-- Dashboard --",
          "type": "dashboard"
        }
      }
    ]
  },
  "description": "Panel de ejemplo sencillo para comenzar",
  "graphTooltip": 1,
  "schemaVersion": 38
}
```

{% endcode %}

Para obtener más información sobre la aplicación de panel de IoT Querie, consulte [Dashboard Studio](/docs/analytics/es/dashboard-studio.md).

Para recibir asistencia con la configuración, comuníquese con <iotquery@navixy.com>.

## **Alertas de vencimiento de registro / seguro**

Los bancos deben rastrear los próximos vencimientos de registro y Seguro porque son responsables de las inspecciones técnicas, el registro y el Seguro. Las Alertas oportunas evitan multas y tiempo fuera de servicio del vehículo.

{% code expandable="true" %}

```sql
SELECT 
    v.vehicle_id,
    v.vehicle_label,
    v.registration_number,
    v.free_seguro_valid_till_date,
    v.seguro_de_responsabilidad_válido_hasta
DESDE raw_business_data.vehicles v
WHERE v.free_insurance_valid_till_date BETWEEN CURRENT_DATE AND CURRENT_DATE + INTERVAL '30 days'
    OR v.Seguro_valid_till ENTRE CURRENT_DATE Y CURRENT_DATE + INTERVALO '30 días';
```

{% endcode %}

## **Vencimiento de la licencia de conductor**

Aunque no siempre es obligatorio, ofrecer alertas proactivas de vencimiento de licencias es un servicio de valor agregado. Las advertencias tempranas permiten a los clientes renovar las licencias antes de que caduquen. Tenga en cuenta que usted

{% code expandable="true" %}

```sql
SELECT e.employee_id,
       e.first_name || ' ' || e.last_name AS nombre_del_conductor,
       número de licencia del Conductor,
       e.driver_license_valid_till
FROM raw_business_data.employees e
WHERE e.driver_license_valid_till BETWEEN CURRENT_DATE AND CURRENT_DATE + (30 * INTERVAL '1 day');
```

{% endcode %}

## Salida de geocerca (frontera nacional) <a href="#geofence-exit-country-border" id="geofence-exit-country-border"></a>

Los contratos pueden restringir el Movimiento del vehículo a un territorio específico (p. ej., Serbia). Salir de esa zona debe alertar de inmediato al banco para que pueda actuar (p. ej., contactar al cliente, inmovilizar el Activo).

Esta consulta SQL está diseñada para monitorear e identificar cuándo un dispositivo sale de una zona geográfica predefinida etiquetada «Tallaght Garaje Geofences». El proceso comienza recopilando y ordenando los puntos geográficos que definen el límite de la zona. Para asegurar que el límite forme un polígono válido, el primer punto se agrega al final de la lista, cerrando efectivamente la forma. Este conjunto cerrado de puntos se usa después para crear un polígono que representa la zona geográfica, el cual se convierte en un objeto geográfico para el análisis espacial.

La consulta luego recupera datos de Seguimiento del dispositivo dentro de un intervalo de tiempo especificado, convirtiendo los valores brutos de latitud y longitud en puntos geográficos. Calcula si cada punto del dispositivo está dentro o fuera de la zona predefinida mediante la función ST\_Contains, que comprueba la contención espacial. El parámetro calculado pos indica 'dentro' si el punto está dentro de la zona y 'fuera' en caso contrario. Por último, la consulta filtra estos resultados para detectar transiciones en las que un dispositivo pasa de estar dentro de la zona a estar fuera, usando una función de ventana para comparar la posición actual con la anterior. Esta lógica ayuda a supervisar los movimientos del dispositivo y a detectar eventos de salida de áreas geográficas específicas. Asegúrese de agregar el valor correcto para el parámetro: `z.zone_label = 'your_zone_label'.`

{% code expandable="true" %}

```sql
WITH zone AS (
  SELECT z.zone_id,
         ST_MakePolygon(ST_MakeLine(ARRAY_AGG(ST_MakePoint(g.longitude, g.latitude) ORDER BY g.number)))::geography AS geog
  FROM raw_business_data.zones z
  JOIN raw_business_data.geofence_points g ON g.zone_id = z.zone_id
  WHERE z.zone_label = 'your_zone_label'
  Grupo BY z.zone_id
),
pts AS (
  SELECT device_id,
         hora del dispositivo,
         ST_SetSRID(ST_MakePoint(longitude/1e7::numeric, latitude/1e7::numeric), 4326)::geography AS geog
  FROM raw_telematics_data.Seguimiento_data_core
  WHERE device_time BETWEEN '2025-07-27 00:00:00' AND '2025-07-28 23:59:59'
),
states AS (
  SELECT p.*,
         CASE WHEN ST_Contains(z.geog::geometry, p.geog::geometry) THEN 'inside' ELSE 'outside' END AS pos
  FROM pts p CROSS JOIN zone z
),
filtered_states AS (
  SELECT
    device_id,
    hora del dispositivo,
    pos,
    LAG(pos) OVER (PARTITION BY device_id ORDER BY device_time) AS prev_pos
  FROM states
)
SELECT device_id, device_time, pos
FROM filtered_states
WHERE prev_pos = 'inside' AND pos = 'outside';

```

{% endcode %}

## **Inspecciones rutinarias por intervalo de tiempo**

Algunas Tareas de Mantenimiento se repiten en intervalos de tiempo fijos. El sistema debe marcar los vehículos de Gestión de vehículos cuyo próximo control de inspección/revisión venza dentro de un intervalo definido.

{% code expandable="true" %}

```sql
WITH t AS (
    SELECT
        vehicle_id,
        description,
        start_date,
        date_repeat_interval,
        make_interval(days => date_repeat_interval) AS repeat_interval
    DESDE raw_business_data.vehicle_service_tasks
    WHERE date_repeat_interval IS NOT NULL
)
SELECT
    vehicle_id,
    description,
    start_date,
    date_repeat_interval,
    start_date
        + intervalo de repetición
            * floor(
                extract(epoch from (current_date::timestamp - start_date))
                / extract(epoch from repeat_interval)
              ) AS last_due,
    start_date
        + intervalo de repetición
            * (
                floor(
                    extract(epoch from (current_date::timestamp - start_date))
                    / extract(epoch from repeat_interval)
                ) + 1
              ) AS next_due
DE t
WHERE (
        start_date
            + intervalo de repetición
                * (
                    floor(
                        extract(epoch from (current_date::timestamp - start_date))
                        / extract(epoch from repeat_interval)
                    ) + 1
                  )
      ) BETWEEN current_date
          AND (current_date + interval '30 days');
```

{% endcode %}

## **Servicio por umbral de Kilometraje (menor/mayor)**

Los servicios menores y mayores se activan por el Kilometraje desde el último evento de servicio. Cuando los kilómetros acumulados superan el umbral, se debe programar el servicio correspondiente.

Tenga en cuenta el `El campo vst.description debe tener comentarios / descripción relevantes para poder usarlo en los filtros del código SQL a continuación.`

{% code expandable="true" %}

```sql
SELECT
  v.vehicle_id,
  v.vehicle_label,
  km.km_since_service,
  vst.Kilometraje_limit
DE
  raw_business_data.Gestión de vehículos v
  JOIN LATERAL (
    SELECT MAX(vst.completion_date) AS last_service_date
    FROM raw_business_data.vehicle_service_tareas vst
    WHERE vst.vehicle_id = v.vehicle_id
      AND (vst.description ILIKE '%minor%' OR vst.description ILIKE '%major%')
      AND vst.completion_date IS NOT NULL
  ) es verdadero
  JOIN raw_business_data.Objeto o ON o.object_id = v.vehicle_id
  JOIN LATERAL (
    SELECT SUM(t.trip_distance_meters) / 1000.0 AS km_since_service
    FROM processed_common_data.Viajes t
    WHERE t.device_id = o.device_id
      Y t.trip_start_time > ls.last_service_date
  ) km EN VERDADERO
  JOIN raw_business_data.vehicle_service_tasks vst
    ON vst.vehicle_id = v.vehicle_id
    AND vst.completion_date = ls.last_service_date
    AND (vst.description ILIKE '%minor%' OR vst.description ILIKE '%major%')

```

{% endcode %}

## **Límite de kilometraje y penalizaciones**

Los contratos de arrendamiento suelen limitar el Kilometraje (p. ej., 25,000 km/año). Si se supera el límite, se aplican cláusulas de penalización. El sistema debe comparar el Kilometraje real durante el período del contrato con el límite acordado y calcular las tarifas.

{% code expandable="true" %}

```sql
WITH driven AS (
  SELECT
    o.objeto_id,
    DATE_TRUNC('year', t.trip_start_time) AS year,
    SUM(t.trip_distance_meters) / 1000.0 AS km_year
  DE
    processed_common_data.Viajes t
    JOIN raw_business_data.objects o ON o.device_id = t.device_id
  WHERE
    t.trip_start_time >= '2023-01-01'::date
    Y t.trip_start_time < '2024-01-01'::date
  AGRUPAR POR
    o.object_id, DATE_TRUNC('year', t.trip_start_time)
),
limits AS (
  SELECT
    objeto_id,
    10000 AS km_limit,
    0.5 AS penalty_rate
  DE
    raw_business_data.objects
)
SELECT
  d.Objeto_id,
  d.year,
  d.km_year,
  l.km_limit,
  GREATEST(d.km_year - l.km_limit, 0) AS km_over,
  GREATEST(d.km_year - l.km_limit, 0) * l.penalty_rate AS penalty_amount
DE
  impulsado d
  JOIN limits l ON d.object_id = l.object_id;
```

{% endcode %}

## **Monitoreo de horas de motor**

Para maquinaria y equipo agrícola, las horas de operación —no el Kilometraje— son las que determinan el Mantenimiento y la facturación. Los datos de horas del motor (por ejemplo, de CAN-Bus) deben monitorearse y resumirse.

{% code expandable="true" %}

```sql
WITH last_service AS (
  SELECT
    vst.vehicle_id,
    MAX(vst.completion_date) AS last_service_date,
    MAX(vst.completion_engine_hours) AS last_service_engine_hours
  DE
    raw_business_data.vehicle_service_tareas vst
  AGRUPAR POR
    vst.vehicle_id
),
engine_hours_since_service AS (
  SELECT
    v.vehicle_id,
    SUM(t.trip_duration_seconds) / 3600.0 AS horas_del_motor_desde_el_servicio
  DE
    raw_business_data.Gestión de vehículos v
    UNIR raw_business_data.objects o ON o.object_id = v.object_id
    JOIN processed_common_data.Viajes t ON t.device_id = o.device_id
    JOIN last_service ls ON ls.vehicle_id = v.vehicle_id
  WHERE
    t.trip_start_time > ls.last_service_date
  AGRUPAR POR
    v.vehicle_id
)
SELECT
  v.vehicle_id,
  v.vehicle_label,
  ls.last_service_engine_hours,
  ehs.engine_hours_since_service,
  (COALESCE(ehs.engine_hours_since_service,0) + COALESCE(ls.last_service_engine_hours,0)) AS current_engine_hours,
  vst.engine_hours_limit
DE
  raw_business_data.Gestión de vehículos v
  JOIN last_service ls ON ls.vehicle_id = v.vehicle_id
  LEFT JOIN engine_hours_since_service ehs ON ehs.vehicle_id = v.vehicle_id
  JOIN raw_business_data.vehicle_service_tasks vst
    ON vst.vehicle_id = v.vehicle_id
    AND vst.completion_date = ls.last_service_date
```

{% endcode %}

## **Eventos de frenado brusco**

El comportamiento de manejo afecta el desgaste y el cumplimiento del contrato. Detectar Frenado brusco ayuda al banco a atribuir el desgaste prematuro de frenos y llantas al mal uso por parte del conductor y, si es necesario, trasladar los costos.

La consulta SQL a continuación primero calcula la velocidad en kilómetros por hora y la diferencia de tiempo entre puntos de datos consecutivos para cada dispositivo. Con esta información, luego calcula la tasa de desaceleración en kilómetros por hora por segundo. Finalmente, filtra y devuelve los registros donde la tasa de desaceleración es de 20 km/h por segundo o superior, lo que indica eventos de desaceleración significativos.

{% code expandable="true" %}

```sql
WITH spd AS (
  SELECT
    device_id,
    hora del dispositivo,
    speed/100.0 AS kmh,
    LAG(speed/100.0) OVER (PARTITION BY device_id ORDER BY device_time) AS prev_kmh,
    EXTRACT(EPOCH FROM (device_time - LAG(device_time) OVER (PARTITION BY device_id ORDER BY device_time))) AS dt_sec
  DE
    raw_telematics_data.seguimiento_data_core
  WHERE
    device_time BETWEEN '2025-07-24 00:00:00' AND '2025-07-24 23:59:59'
),
decels AS (
  SELECT
    device_id,
    hora del dispositivo,
    (prev_kmh - kmh) / NULLIF(dt_sec, 0) AS decel_kmh_per_sec
  DE
    spd
  WHERE
    prev_kmh IS NOT NULL
)
SELECT *
FROM decels
WHERE decel_kmh_per_sec >= 20;
```

{% endcode %}

## **Eventos de aceleración brusca**

La aceleración agresiva aumenta el desgaste de las llantas, las transmisiones, los trenes motrices y los soportes del motor. Identificar estos eventos apoya la capacitación y la posible recuperación de costos.

La consulta SQL a continuación está diseñada para identificar eventos de aceleración significativos a partir de un conjunto de datos de seguimiento. Primero calcula la velocidad en kilómetros por hora y la diferencia de tiempo entre puntos de datos consecutivos para cada dispositivo. Con esta información, luego calcula la tasa de aceleración en kilómetros por hora por segundo. Por último, filtra y devuelve los registros donde la tasa de aceleración alcanza o supera un umbral especificado, lo que indica eventos de aceleración significativos.

{% code expandable="true" %}

```sql
WITH spd AS (
  SELECT
    device_id,
    hora del dispositivo,
    speed/100.0 AS kmh,
    LAG(speed/100.0) OVER (PARTITION BY device_id ORDER BY device_time) AS prev_kmh,
    EXTRACT(EPOCH FROM (device_time - LAG(device_time) OVER (PARTITION BY device_id ORDER BY device_time))) AS dt_sec
  DE
    raw_telematics_data.seguimiento_data_core
  WHERE
    device_time BETWEEN '2025-07-28 00:00:00' AND '2025-07-28 23:59:59'
)
SELECT
  device_id,
  hora del dispositivo,
  (kmh - prev_kmh) / NULLIF(dt_sec, 0) AS accel_kmh_per_sec
DE
  spd
WHERE
  prev_kmh IS NOT NULL
  AND (kmh - prev_kmh) / NULLIF(dt_sec, 0) >= 20;
```

{% endcode %}

## **Giros bruscos / toma de curvas**

Los giros bruscos combinados con cambios repentinos de velocidad indican manejo riesgoso. El seguimiento de ese comportamiento ayuda a detectar el uso indebido del vehículo.

Esta consulta SQL está diseñada para identificar cambios significativos en la dirección y la velocidad a partir de los datos de seguimiento durante un período de tiempo especificado. Primero convierte los valores brutos de latitud y longitud en grados decimales y calcula la velocidad en kilómetros por hora. Usando la función LAG, recupera los datos anteriores de ubicación y velocidad para cada dispositivo, lo que permite calcular los cambios a lo largo del tiempo. Luego, la consulta calcula el cambio de rumbo en grados usando funciones trigonométricas para determinar el rumbo entre puntos consecutivos. También calcula el cambio de velocidad entre estos puntos. Finalmente, la consulta filtra los resultados para incluir solo aquellos registros en los que el cambio absoluto de rumbo es de 10 grados o más y el cambio absoluto de velocidad es de 5 km/h o más, identificando maniobras o eventos significativos en los datos de seguimiento.

{% code expandable="true" %}

```sql
WITH pts AS (
  SELECT
    device_id,
    hora del dispositivo,
    latitude/1e7::numeric AS lat,
    longitude/1e7::numeric AS lon,
    LAG(latitude/1e7::numeric) OVER (PARTITION BY device_id ORDER BY device_time) AS prev_lat,
    LAG(longitude/1e7::numeric) OVER (PARTITION BY device_id ORDER BY device_time) AS prev_lon,
    speed/100.0 AS kmh,
    LAG(speed/100.0) OVER (PARTITION BY device_id ORDER BY device_time) AS prev_kmh
  DE
    raw_telematics_data.seguimiento_data_core
  WHERE
    device_time BETWEEN '2025-07-28 00:00:00' AND '2025-07-28 23:59:59'
),
bearing AS (
  SELECT *,
         atan2(
           sin(radians(lon-prev_lon))*cos(radians(lat)), 
           cos(radians(prev_lat))*sin(radians(lat)) -
           sin(radians(prev_lat))*cos(radians(lat))*cos(radians(lon-prev_lon))
         ) * 180/pi() AS heading_change,
         (kmh - prev_kmh) AS delta_speed
  FROM pts
)
SELECT *
FROM bearing
WHERE abs(heading_change) >= 10
  AND abs(delta_speed) >= 5;

```

{% endcode %}

## **Detección de ignición y ralentí**

Medir el tiempo en ralentí (ignición encendida, baja o nula velocidad) ayuda a reducir el desperdicio de combustible e identificar el uso indebido. Los periodos prolongados de ralentí deben reportarse y gestionarse.

{% hint style="info" %}
[Dashboard Studio](/docs/analytics/es/dashboard-studio.md) y herramientas similares no admiten la sustitución de variables (`:variable` sintaxis). Reemplace todos los parámetros con valores literales antes de ejecutar esta consulta. Consulte el siguiente ejemplo para ver el formato correcto.
{% endhint %}

{% code expandable="true" %}

```sql
WITH ign AS (
    SELECT
        device_id,
        hora del dispositivo,
        value::int AS ign_on
    FROM raw_telematics_data.states
    WHERE state_name = 'Ignición'
      AND device_time BETWEEN :from_ts::timestamptz AND :to_ts::timestamptz
      -- Para Dashboard Studio, reemplace :from_ts y :to_ts con marcas de tiempo literales:
      -- TIMESTAMPTZ '2024-01-01 00:00:00+00' AND TIMESTAMPTZ '2024-01-07 00:00:00+00'
),
spd AS (
    SELECT
        device_id,
        hora del dispositivo,
        speed / 100.0 AS kmh
    FROM raw_telematics_data.Seguimiento_data_core
    WHERE device_time BETWEEN :from_ts AND :to_ts
    -- Para Dashboard Studio, reemplace :from_ts y :to_ts con marcas de tiempo literales:
    -- TIMESTAMPTZ '2024-01-01 00:00:00+00' AND TIMESTAMPTZ '2024-01-07 00:00:00+00'
),
merged AS (
    SELECT
        i.device_id,
        i.device_time,
        i.ign_on,
        s.kmh,
        LEAD(i.device_time) OVER (
            PARTITION BY i.device_id
            ORDER BY i.device_time
        ) AS next_time
    FROM ign i
    LEFT JOIN spd s USING (device_id, device_time)
)
SELECT
    device_id,
    device_time AS idle_start,
    next_time   AS idle_end,
    EXTRACT(EPOCH FROM (next_time - device_time)) / 60.0 AS idle_minutes
FROM merged
WHERE ign_on = 1
  AND kmh < :idle_speed
  -- Para Dashboard Studio, reemplace :idle_speed por un valor numérico, por ejemplo, 5
  AND next_time IS NOT NULL
  AND (next_time - device_time) >= (:idle_min::int * INTERVAL '1 minute');
  -- Para Dashboard Studio, reemplace :idle_min por un valor numérico, por ejemplo, (5 * INTERVAL '1 minute')
```

{% endcode %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://navixy.com/docs/analytics/es/example-queries/leasing.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
