Repository: prefeitura-rio/pipelines_rj_smtr
Pull request #297: GPS Viagens 2.0
Author: login: akaBotelho
Created: 2024-10-29T23:29:21Z | Merged: 2025-05-26T23:15:34Z



<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **Novos Recursos**
  - Adicionados modelos e tabelas para monitoramento de GPS, incluindo status de operação, velocidade, paradas, trajeto correto e realocação de veículos.
  - Novos seletores para materialização de tabelas de GPS.
  - Novos parâmetros de configuração para modo e fonte de GPS, além de opções de buffer e segmentação.
  - Inclusão de fontes de dados para registros, realocações e garagens de diferentes provedores.

- **Documentação**
  - Documentação ampliada para campos de captura de GPS, realocação de linhas e informações de garagens.
  - Esquemas detalhados para novos modelos de staging e monitoramento.

- **Chores**
  - Adicionados changelogs detalhando as novas funcionalidades e modelos.
  - Macro para facilitar filtros por data e hora em partições.

- **Refatoração/Estilo**
  - Ajustes em parâmetros e nomes de variáveis para maior clareza e padronização.
  - Reformatação de blocos de configuração para melhor legibilidade.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/pipelines/migration/br_rj_riodejaneiro_onibus_gps/flows.py b/pipelines/migration/br_rj_riodejaneiro_onibus_gps/flows.py
index 79c0fd078..21088fafc 100644
--- a/pipelines/migration/br_rj_riodejaneiro_onibus_gps/flows.py
+++ b/pipelines/migration/br_rj_riodejaneiro_onibus_gps/flows.py
@@ -166,7 +166,7 @@
     rematerialization = Parameter("rematerialization", default=False)
     date_range_start_param = Parameter("date_range_start", default=None)
     date_range_end_param = Parameter("date_range_end", default=None)
-    fifteen_minutes = Parameter("fifteen_minutes", default="")
+    _15_minutos = Parameter("15_minutos", default=False)
     materialize_delay_hours = Parameter(
         "materialize_delay_hours",
         default=constants.GPS_SPPO_MATERIALIZE_DELAY_HOURS.value,
@@ -229,7 +229,7 @@
                 table_id=table_id,
                 upstream=True,
                 exclude="+data_versao_efetiva",
-                _vars=[date_range, dataset_sha, {"fifteen_minutes": fifteen_minutes}],
+                _vars=[date_range, dataset_sha, {"15_minutos": _15_minutos}],
                 flags="--full-refresh",
             )
 
@@ -239,7 +239,7 @@
                 dataset_id=dataset_id,
                 table_id=table_id,
                 exclude="+data_versao_efetiva",
-                _vars=[date_range, dataset_sha, {"fifteen_minutes": fifteen_minutes}],
+                _vars=[date_range, dataset_sha, {"15_minutos": _15_minutos}],
                 upstream=True,
             )
 
@@ -594,7 +594,7 @@
         "table_id": constants.GPS_SPPO_15_MIN_TREATED_TABLE_ID.value,
         "materialize_delay_hours": 0,
         "truncate_minutes": False,
-        "fifteen_minutes": "_15_minutos",
+        "15_minutos": True,
     },
 )
 materialize_gps_15_min.name = "SMTR: GPS SPPO 15 Minutos - Materialização (subflow)"
@@ -621,7 +621,7 @@
             "rebuild": rebuild,
             "materialize_delay_hours": 0,
             "truncate_minutes": False,
-            "fifteen_minutes": "_15_minutos",
+            "15_minutos": True,
         },
     )
 
diff --git a/queries/CHANGELOG.md b/queries/CHANGELOG.md
index 86d1eece0..d7edf60e0 100644
--- a/queries/CHANGELOG.md
+++ b/queries/CHANGELOG.md
@@ -1,5 +1,11 @@
 # Changelog - queries
 
+## [1.0.4] - 2025-05-20
+
+### Adicionado
+
+- Adiciona selector `gps` e `gps_15_minutos` (https://github.com/prefeitura-rio/pipelines_rj_smtr/pull/297)
+
 ## [1.0.3] - 2025-05-13
 
 ### Alterado
diff --git a/queries/dbt_project.yml b/queries/dbt_project.yml
index 1fcfae736..71a7b3c7e 100644
--- a/queries/dbt_project.yml
+++ b/queries/dbt_project.yml
@@ -38,7 +38,9 @@ vars:
   sppo_registros_staging: "rj-smtr-staging.br_rj_riodejaneiro_onibus_gps_staging.registros"
   sppo_realocacao_staging: "rj-smtr-staging.br_rj_riodejaneiro_onibus_gps_staging.realocacao"
   data_inicio_realocacao: "2022-11-15"
-  fifteen_minutes: ""
+  15_minutos: false
+  modo_gps: "onibus"
+  fonte_gps: "conecta"
 
   # Parametros de intersecção do ônibus com rota
   ## Tamanho do buffer da rota
@@ -54,6 +56,8 @@ vars:
   velocidade_limiar_parado: 3
   ## Distância mínima para que o veículo seja identificado parado em um terminal ou garagem em aux_registros_parada
   distancia_limiar_parada: 250
+  ## Tamanho do buffer do segmento
+  buffer_segmento_metros: 20 # flag_trajeto_correto
 
   ### [ANTIGO] SIGMOB ###
 
diff --git a/queries/macros/generate_date_hour_partition_filter.sql b/queries/macros/generate_date_hour_partition_filter.sql
new file mode 100644
index 000000000..186ae9f7a
--- /dev/null
+++ b/queries/macros/generate_date_hour_partition_filter.sql
@@ -0,0 +1,19 @@
+{% macro generate_date_hour_partition_filter(start_timestamp, end_timestamp) %}
+    {% set start = modules.datetime.datetime.fromisoformat(start_timestamp) %}
+    {% set end = modules.datetime.datetime.fromisoformat(end_timestamp) %}
+    {% set days = (end.date() - start.date()).days %}
+
+    {% if days == 0 %}
+        data = date("{{ start_timestamp }}")
+        and hora between {{ start.hour }} and {{ end.hour }}
+
+    {% elif days == 1 %}
+        (data = date("{{ start_timestamp }}") and hora >= {{ start.hour }})
+        or (data = date("{{ end_timestamp }}") and hora <= {{ end.hour }})
+    {% else %}
+        (data = date("{{ start_timestamp }}") and hora >= {{ start.hour }})
+        or (data > date("{{ start_timestamp }}") and data < date("{{ end_timestamp }}"))
+        or (data = date("{{ end_timestamp }}") and hora <= {{ end.hour }})
+    {% endif %}
+
+{% endmacro %}
diff --git a/queries/models/br_rj_riodejaneiro_brt_gps/schema.yml b/queries/models/br_rj_riodejaneiro_brt_gps/schema.yml
index 36ac06259..c32dc6419 100644
--- a/queries/models/br_rj_riodejaneiro_brt_gps/schema.yml
+++ b/queries/models/br_rj_riodejaneiro_brt_gps/schema.yml
@@ -64,32 +64,33 @@ models:
         description: "{{ doc('sentido') }}"
       - name: velocidade
         description: "{{ doc('velocidade_instantanea') }}"
-  - name: registros_historico
-    description: "View para os dados históricos capturados em staging com tratamento básico e conversão de valores"
-    columns:
-      - name: codigo
-        description: "{{ doc('codigo') }}"
-      - name: placa
-        description: "{{ doc('placa') }}"
-      - name: linha
-        description: "{{ doc('linha') }}"
-      - name: latitude
-        description: "{{ doc('latitude_gps') }}"
-      - name: longitude
-        description: "{{ doc('longitude_gps') }}"
-      - name: timestamp_gps
-        description: "{{ doc('timestamp_gps') }}"
-      - name: velocidade
-        description: "{{ doc('velocidade_instantanea') }}"
-      - name: id_migracao_trajeto
-        description: ""
-      - name: sentido
-        description: "{{ doc('sentido') }}"
-      - name: trajeto
-        description: "{{ doc('trajeto') }}"
-      - name: timestamp_captura
-        description: "{{ doc('timestamp_captura') }}"
-      - name: data
-        description: "{{ doc('data_captura') }}"
-      - name: hora
-        description: "Hora do 'timestamp_captura'"
\ No newline at end of file
+
+  # - name: registros_historico
+  #   description: "View para os dados históricos capturados em staging com tratamento básico e conversão de valores"
+  #   columns:
+  #     - name: codigo
+  #       description: "{{ doc('codigo') }}"
+  #     - name: placa
+  #       description: "{{ doc('placa') }}"
+  #     - name: linha
+  #       description: "{{ doc('linha') }}"
+  #     - name: latitude
+  #       description: "{{ doc('latitude_gps') }}"
+  #     - name: longitude
+  #       description: "{{ doc('longitude_gps') }}"
+  #     - name: timestamp_gps
+  #       description: "{{ doc('timestamp_gps') }}"
+  #     - name: velocidade
+  #       description: "{{ doc('velocidade_instantanea') }}"
+  #     - name: id_migracao_trajeto
+  #       description: ""
+  #     - name: sentido
+  #       description: "{{ doc('sentido') }}"
+  #     - name: trajeto
+  #       description: "{{ doc('trajeto') }}"
+  #     - name: timestamp_captura
+  #       description: "{{ doc('timestamp_captura') }}"
+  #     - name: data
+  #       description: "{{ doc('data_captura') }}"
+  #     - name: hora
+  #       description: "Hora do 'timestamp_captura'"
\ No newline at end of file
diff --git a/queries/models/br_rj_riodejaneiro_onibus_gps/sppo_aux_registros_filtrada.sql b/queries/models/br_rj_riodejaneiro_onibus_gps/sppo_aux_registros_filtrada.sql
index 266193ee1..b5bce0516 100644
--- a/queries/models/br_rj_riodejaneiro_onibus_gps/sppo_aux_registros_filtrada.sql
+++ b/queries/models/br_rj_riodejaneiro_onibus_gps/sppo_aux_registros_filtrada.sql
@@ -1,18 +1,12 @@
-{% if var("fifteen_minutes") == "_15_minutos" %}
-    {{
-        config(
-            materialized="ephemeral",
-        )
-    }}
-{% else %}
-    {{
-        config(
-            materialized="incremental",
-            partition_by={"field": "data", "data_type": "date", "granularity": "day"},
-            require_partition_filter=true,
-        )
-    }}
-{% endif %}
+-- fmt: off
+{{
+    config(
+        materialized = 'ephemeral' if var('15_minutos', false) else 'incremental',
+        partition_by = {"field": "data", "data_type": "date", "granularity": "day"} if not var('15_minutos', false) else none,
+        require_partition_filter = true if not var('15_minutos', false) else false
+    )
+}}
+-- fmt: on
 
 /*
 Descrição:
diff --git a/queries/models/br_rj_riodejaneiro_onibus_gps/sppo_aux_registros_realocacao.sql b/queries/models/br_rj_riodejaneiro_onibus_gps/sppo_aux_registros_realocacao.sql
index 2ab44127b..0da96875c 100644
--- a/queries/models/br_rj_riodejaneiro_onibus_gps/sppo_aux_registros_realocacao.sql
+++ b/queries/models/br_rj_riodejaneiro_onibus_gps/sppo_aux_registros_realocacao.sql
@@ -1,75 +1,68 @@
-{% if var("fifteen_minutes") == "_15_minutos" %}
+-- fmt: off
 {{
-  config(
-      materialized='ephemeral',
-  )
+    config(
+        materialized = 'ephemeral' if var('15_minutos', false) else 'incremental',
+        partition_by = {"field": "data", "data_type": "date", "granularity": "day"} if not var('15_minutos', false) else none,
+    )
 }}
-{% else %}
-{{
-  config(
-      materialized='incremental',
-      partition_by={
-            "field":"data",
-            "data_type": "date",
-            "granularity":"day"
-      }
-  )
-}}
-{% endif %}
+-- fmt: on
 
 -- 1. Filtra realocações válidas dentro do intervalo de GPS avaliado
-with realocacao as (
-  select
-    * except(datetime_saida),
-    case
-      when datetime_saida is null then datetime_operacao
-      else datetime_saida
-    end as datetime_saida,
-  from
-    {{ ref('sppo_realocacao') }}
-  where
-    -- Realocação deve acontecer após o registro de GPS e até 1 hora depois
-    datetime_diff(datetime_operacao, datetime_entrada, minute) between 0 and 60
-    and data between DATE("{{var('date_range_start')}}")
-    and DATE(datetime_add("{{var('date_range_end')}}", interval 1 hour))
-    and (datetime_saida >= datetime("{{var('date_range_start')}}") or datetime_operacao >= datetime("{{var('date_range_start')}}"))
-),
--- 2. Altera registros de GPS com servicos realocados
-gps as (
-  select
-    ordem,
-    timestamp_gps,
-    linha,
-    data,
-    hora
-  from {{ ref('sppo_registros') }}
-  where
-    data between DATE("{{var('date_range_start')}}") and DATE("{{var('date_range_end')}}")
-    and timestamp_gps > "{{var('date_range_start')}}" and timestamp_gps <= "{{var('date_range_end')}}"
-),
-combinacao as (
-  select
-    r.id_veiculo,
-    g.timestamp_gps,
-    g.linha as servico_gps,
-    r.servico as servico_realocado,
-    r.datetime_operacao as datetime_realocacao,
-    g.data,
-    g.hora
-  from gps g
-  inner join realocacao r
-  on
-    g.ordem = r.id_veiculo
-    and g.linha != r.servico
-    and g.timestamp_gps between r.datetime_entrada and r.datetime_saida
-)
+with
+    realocacao as (
+        select
+            * except (datetime_saida),
+            case
+                when datetime_saida is null then datetime_operacao else datetime_saida
+            end as datetime_saida,
+        from {{ ref("sppo_realocacao") }}
+        where
+            -- Realocação deve acontecer após o registro de GPS e até 1 hora depois
+            datetime_diff(datetime_operacao, datetime_entrada, minute) between 0 and 60
+            and data between date("{{var('date_range_start')}}") and date(
+                datetime_add("{{var('date_range_end')}}", interval 1 hour)
+            )
+            and (
+                datetime_saida >= datetime("{{var('date_range_start')}}")
+                or datetime_operacao >= datetime("{{var('date_range_start')}}")
+            )
+    ),
+    -- 2. Altera registros de GPS com servicos realocados
+    gps as (
+        select ordem, timestamp_gps, linha, data, hora
+        from {{ ref("sppo_registros") }}
+        where
+            data between date("{{var('date_range_start')}}") and date(
+                "{{var('date_range_end')}}"
+            )
+            and timestamp_gps > "{{var('date_range_start')}}"
+            and timestamp_gps <= "{{var('date_range_end')}}"
+    ),
+    combinacao as (
+        select
+            r.id_veiculo,
+            g.timestamp_gps,
+            g.linha as servico_gps,
+            r.servico as servico_realocado,
+            r.datetime_operacao as datetime_realocacao,
+            g.data,
+            g.hora
+        from gps g
+        inner join
+            realocacao r
+            on g.ordem = r.id_veiculo
+            and g.linha != r.servico
+            and g.timestamp_gps between r.datetime_entrada and r.datetime_saida
+    )
 -- Filtra realocacao mais recente para cada timestamp
-select
-  * except(rn)
-from (
-  select
-    *,
-    row_number() over (partition by id_veiculo, timestamp_gps order by datetime_realocacao desc) as rn
-  from combinacao
-)
-where rn = 1
\ No newline at end of file
+select * except (rn)
+from
+    (
+        select
+            *,
+            row_number() over (
+                partition by id_veiculo, timestamp_gps order by datetime_realocacao desc
+            ) as rn
+        from combinacao
+    )
+where rn = 1
diff --git a/queries/models/docs.md b/queries/models/docs.md
index d77c20c31..6c5e29b49 100644
--- a/queries/models/docs.md
+++ b/queries/models/docs.md
@@ -767,3 +767,35 @@ Quantidade de viagens apuradas por dia
 {% docs viagens_faixa %}
 Quantidade de viagens apuradas por faixa horária
 {% enddocs %}
+
+{% docs hora_captura %}
+Hora da captura
+{% enddocs %}
+
+{% docs direcao_gps %}
+Direção do movimento em graus
+{% enddocs %}
+
+{% docs datetime_envio_gps %}
+Data e hora em que o GPS enviou os dados de localização
+{% enddocs %}
+
+{% docs datetime_servidor_gps %}
+Data e hora em que o servidor recebeu os dados de localização do GPS
+{% enddocs %}
+
+{% docs datetime_saida %}
+Datetime de saída do veículo na linha realocada
+{% enddocs %}
+
+{% docs datetime_processamento %}
+Datetime de processamento da realocação pela empresa operadora
+{% enddocs %}
+
+{% docs datetime_operacao %}
+Datetime que o registro da realocação foi informado pela empresa operadora
+{% enddocs %}
+
+{% docs servico_realocacao %}
+Linha de ônibus [serviço] realocada informada pela empresa operadora
+{% enddocs %}
\ No newline at end of file
diff --git a/queries/models/monitoramento/CHANGELOG.md b/queries/models/monitoramento/CHANGELOG.md
index 78c6cec96..79b529464 100644
--- a/queries/models/monitoramento/CHANGELOG.md
+++ b/queries/models/monitoramento/CHANGELOG.md
@@ -1,5 +1,11 @@
 # Changelog - monitoramento
 
+## [1.3.7] - 2025-05-20
+
+### Adicionado
+
+ - Cria modelos `gps`, `gps_15_minutos`, `aux_gps`, `aux_gps_filtrada`, `aux_gps_parada`, `aux_gps_realocacao`, `aux_gps_trajeto_correto`, `aux_gps_velocidade` ,`aux_realocacao` e `staging_garagens`(https://github.com/prefeitura-rio/pipelines_rj_smtr/pull/297)
+
 ## [1.3.6] - 2025-05-13
 
 ### Corrigido
diff --git a/queries/models/monitoramento/gps.sql b/queries/models/monitoramento/gps.sql
new file mode 100644
index 000000000..8a4308930
--- /dev/null
+++ b/queries/models/monitoramento/gps.sql
@@ -0,0 +1,112 @@
+{{
+    config(
+        materialized="incremental",
+        incremental_strategy="insert_overwrite",
+        partition_by={"field": "data", "data_type": "date", "granularity": "day"},
+        tags=["geolocalizacao"],
+        alias=this.name ~ "_" ~ var("modo_gps") ~ "_" ~ var("fonte_gps"),
+    )
+}}
+
+{% set staging_gps = ref("staging_gps") %}
+{% if execute and is_incremental() %}
+    {% set gps_partitions_query %}
+    SELECT DISTINCT
+      CONCAT("'", DATE(data), "'") AS data
+    FROM
+      {{ staging_gps }}
+    WHERE
+      {{ generate_date_hour_partition_filter(var('date_range_start'), var('date_range_end')) }}
+    {% endset %}
+
+    {% set gps_partitions = run_query(gps_partitions_query).columns[0].values() %}
+{% endif %}
+
+with
+    registros as (
+        select
+            data,
+            hora,
+            id_veiculo,
+            datetime_gps,
+            datetime_captura,
+            velocidade,
+            servico,
+            latitude,
+            longitude,
+        from {{ ref("aux_gps_filtrada") }}
+    ),
+    velocidades as (
+        select
+            id_veiculo,
+            datetime_gps,
+            servico,
+            velocidade,
+            distancia,
+            indicador_em_movimento
+        from {{ ref("aux_gps_velocidade") }}
+    ),
+    paradas as (
+        select id_veiculo, datetime_gps, servico, tipo_parada
+        from {{ ref("aux_gps_parada") }}
+    ),
+    indicadores as (
+        select id_veiculo, datetime_gps, servico, route_id, indicador_trajeto_correto
+        from {{ ref("aux_gps_trajeto_correto") }}
+    ),
+    novos_dados as (
+        select
+            date(r.datetime_gps) as data,
+            extract(hour from r.datetime_gps) as hora,
+            r.datetime_gps,
+            r.id_veiculo,
+            r.servico,
+            r.latitude,
+            r.longitude,
+            case
+                when
+                    indicador_em_movimento is true and indicador_trajeto_correto is true
+                then 'Em operação'
+                when
+                    indicador_em_movimento is true
+                    and indicador_trajeto_correto is false
+                then 'Operando fora trajeto'
+                when indicador_em_movimento is false
+                then
+                    case
+                        when tipo_parada is not null
+                        then concat("Parado ", tipo_parada)
+                        when indicador_trajeto_correto is true
+                        then 'Parado trajeto correto'
+                        else 'Parado fora trajeto'
+                    end
+            end as status,
+            r.velocidade as velocidade_instantanea,
+            v.velocidade as velocidade_estimada_10_min,
+            v.distancia,
+            0 as priority
+        from registros r
+        join indicadores i using (id_veiculo, datetime_gps, servico)
+        join velocidades v using (id_veiculo, datetime_gps, servico)
+        join paradas p using (id_veiculo, datetime_gps, servico)
+    ),
+    particoes_completas as (
+        select *
+        from novos_dados
+
+        {% if is_incremental() and gps_partitions | length > 0 %}
+            union all
+
+            select * except (versao, datetime_ultima_atualizacao), 1 as priority
+            from {{ this }}
+            where data in ({{ gps_partitions | join(", ") }})
+        {% endif %}
+    )
+select
+    * except (priority),
+    '{{ var("version") }}' as versao,
+    current_datetime("America/Sao_Paulo") as datetime_ultima_atualizacao
+from particoes_completas
+qualify
+    row_number() over (partition by id_veiculo, datetime_gps, servico order by priority)
+    = 1
diff --git a/queries/models/monitoramento/gps_15_minutos.sql b/queries/models/monitoramento/gps_15_minutos.sql
new file mode 100644
index 000000000..92bba3c71
--- /dev/null
+++ b/queries/models/monitoramento/gps_15_minutos.sql
@@ -0,0 +1,81 @@
+{{
+    config(
+        materialized="table",
+        partition_by={"field": "data", "data_type": "date", "granularity": "day"},
+        tags=["geolocalizacao"],
+        alias=this.name ~ "_" ~ var("modo_gps") ~ "_" ~ var("fonte_gps"),
+    )
+}}
+
+with
+    registros as (
+        -- 1. registros_filtrada
+        select
+            data,
+            hora,
+            id_veiculo,
+            datetime_gps,
+            datetime_captura,
+            velocidade,
+            servico,
+            latitude,
+            longitude,
+        from {{ ref("aux_gps_filtrada") }}
+    ),
+    velocidades as (
+        -- 2. velocidades
+        select
+            id_veiculo,
+            datetime_gps,
+            servico,
+            velocidade,
+            distancia,
+            indicador_em_movimento
+        from {{ ref("aux_gps_velocidade") }}
+    ),
+    paradas as (
+        -- 3. paradas
+        select id_veiculo, datetime_gps, servico, tipo_parada
+        from {{ ref("aux_gps_parada") }}
+    ),
+    indicadores as (
+        -- 4. indicador_trajeto_correto
+        select id_veiculo, datetime_gps, servico, route_id, indicador_trajeto_correto
+        from {{ ref("aux_gps_trajeto_correto") }}
+    )
+-- 5. Junção final
+select
+    date(r.datetime_gps) data,
+    extract(hour from r.datetime_gps) hora,
+    r.datetime_gps,
+    r.id_veiculo,
+    r.servico,
+    r.latitude,
+    r.longitude,
+    case
+        when indicador_em_movimento is true and indicador_trajeto_correto is true
+        then 'Em operação'
+        when indicador_em_movimento is true and indicador_trajeto_correto is false
+        then 'Operando fora trajeto'
+        when indicador_em_movimento is false
+        then
+            case
+                when tipo_parada is not null
+                then concat("Parado ", tipo_parada)
+                else
+                    case
+                        when indicador_trajeto_correto is true
+                        then 'Parado trajeto correto'
+                        else 'Parado fora trajeto'
+                    end
+            end
+    end status,
+    r.velocidade as velocidade_instantanea,
+    v.velocidade as velocidade_estimada_10_min,
+    v.distancia,
+    '{{ var("version") }}' as versao,
+    current_datetime("America/Sao_Paulo") as datetime_ultima_atualizacao
+from registros r
+join indicadores i using (id_veiculo, datetime_gps, servico)
+join velocidades v using (id_veiculo, datetime_gps, servico)
+join paradas p using (id_veiculo, datetime_gps, servico)
diff --git a/queries/models/monitoramento/schema.yml b/queries/models/monitoramento/schema.yml
index 0b9bcf7b3..ae98f643a 100644
--- a/queries/models/monitoramento/schema.yml
+++ b/queries/models/monitoramento/schema.yml
@@ -285,3 +285,63 @@ models:
         description: "{{ doc('datetime_ultima_atualizacao') }}"
         data_type: datetime
         quote: true
+
+  - name: gps
+    description: "Tabela com os dados tratados de registros de GPS da API {{ var('fonte_gps') }}, incluindo velocidade estimada, estado de movimento, parada em terminal ou garagem e interseção com o traçado da linha informada"
+    columns:
+      - name: data
+        description: "{{ doc('data_gps') }}"
+      - name: hora
+        description: "{{ doc('hora_gps') }}"
+      - name: datetime_gps
+        description: "{{ doc('timestamp_gps') }}"
+      - name: id_veiculo
+        description: "{{ doc('id_veiculo') }}"
+      - name: servico
+        description: "{{ doc('servico') }}"
+      - name: latitude
+        description: "{{ doc('latitude_gps') }}"
+      - name: longitude
+        description: "{{ doc('longitude_gps') }}"
+      - name: status
+        description: "{{ doc('status_veiculo_gps') }}"
+      - name: velocidade_instantanea
+        description: "{{ doc('velocidade_instantanea') }}"
+      - name: velocidade_estimada_10_min
+        description: "{{ doc('velocidade_estimada_10_min') }}"
+      - name: distancia
+        description: "{{ doc('distancia_gps') }}"
+      - name: versao
+        description: "{{ doc('versao') }}"
+      - name: datetime_ultima_atualizacao
+        description: "{{ doc('datetime_ultima_atualizacao') }}"
+
+  - name: gps_15_minutos
+    description: "Tabela com os dados tratados de registros de GPS da API {{ var('fonte_gps') }}, incluindo velocidade estimada, estado de movimento, parada em terminal ou garagem e interseção com o traçado da linha informada"
+    columns:
+      - name: data
+        description: "{{ doc('data_gps') }}"
+      - name: hora
+        description: "{{ doc('hora_gps') }}"
+      - name: datetime_gps
+        description: "{{ doc('timestamp_gps') }}"
+      - name: id_veiculo
+        description: "{{ doc('id_veiculo') }}"
+      - name: servico
+        description: "{{ doc('servico') }}"
+      - name: latitude
+        description: "{{ doc('latitude_gps') }}"
+      - name: longitude
+        description: "{{ doc('longitude_gps') }}"
+      - name: status
+        description: "{{ doc('status_veiculo_gps') }}"
+      - name: velocidade_instantanea
+        description: "{{ doc('velocidade_instantanea') }}"
+      - name: velocidade_estimada_10_min
+        description: "{{ doc('velocidade_estimada_10_min') }}"
+      - name: distancia
+        description: "{{ doc('distancia_gps') }}"
+      - name: versao
+        description: "{{ doc('versao') }}"
+      - name: datetime_ultima_atualizacao
+        description: "{{ doc('datetime_ultima_atualizacao') }}"
\ No newline at end of file
diff --git a/queries/models/monitoramento/staging/aux_gps_filtrada.sql b/queries/models/monitoramento/staging/aux_gps_filtrada.sql
new file mode 100644
index 000000000..90554cf70
--- /dev/null
+++ b/queries/models/monitoramento/staging/aux_gps_filtrada.sql
@@ -0,0 +1,37 @@
+{{ config(materialized="ephemeral") }}
+
+with
+    box as (
+        /* Geometria de caixa que contém a área do município de Rio de Janeiro.*/
+        select min_longitude, min_latitude, max_longitude, max_latitude
+        from {{ var("limites_caixa") }}
+    ),
+    gps as (
+        select *, st_geogpoint(longitude, latitude) posicao_veiculo_geo
+        from {{ ref("aux_gps_realocacao") }}
+    ),
+    filtrada as (
+        select
+            data,
+            hora,
+            datetime_gps,
+            id_veiculo,
+            servico,
+            latitude,
+            longitude,
+            posicao_veiculo_geo,
+            datetime_captura,
+            velocidade,
+        from gps
+        cross join box
+        where
+            st_intersectsbox(
+                posicao_veiculo_geo,
+                min_longitude,
+                min_latitude,
+                max_longitude,
+                max_latitude
+            )
+    )
+select *
+from filtrada
diff --git a/queries/models/monitoramento/staging/aux_gps_parada.sql b/queries/models/monitoramento/staging/aux_gps_parada.sql
new file mode 100644
index 000000000..02687b371
--- /dev/null
+++ b/queries/models/monitoramento/staging/aux_gps_parada.sql
@@ -0,0 +1,118 @@
+{{ config(materialized="ephemeral") }}
+
+{% set incremental_filter %}
+    data between
+        date('{{ var("date_range_start") }}')
+        and date('{{ var("date_range_end") }}')
+{% endset %}
+
+{% set calendario = ref("calendario") %}
+{# {% set calendario = "rj-smtr.planejamento.calendario" %} #}
+{% if execute %}
+    {% set gtfs_feeds_query %}
+        select distinct concat("'", feed_start_date, "'") as feed_start_date
+        from {{ calendario }}
+        where {{ incremental_filter }}
+    {% endset %}
+    {% set gtfs_feeds = run_query(gtfs_feeds_query).columns[0].values() %}
+{% endif %}
+
+with
+    terminais as (
+        select
+            st_geogpoint(stop_lon, stop_lat) as ponto_parada,
+            stop_name as nome_parada,
+            'terminal' as tipo_parada
+        from {{ ref("stops_gtfs") }}
+        {# from `rj-smtr`.`gtfs`.`stops` #}
+        where location_type = "1" and feed_start_date in ({{ gtfs_feeds | join(", ") }})
+    ),
+    garagens as (
+        select
+            * except (geometry_wkt, operador),
+            st_geogfromtext(geometry_wkt, make_valid => true) as geometry,
+            operador as nome_parada,
+            'garagem' as tipo_parada
+        from {{ ref("staging_garagens") }}
+        where
+            ativa
+            and inicio_vigencia <= date('{{ var("date_range_end") }}')
+            and (
+                fim_vigencia is null
+                or fim_vigencia >= date('{{ var("date_range_start") }}')
+            )
+    ),
+    posicoes_veiculos as (
+        select id_veiculo, datetime_gps, data, servico, posicao_veiculo_geo
+        from {{ ref("aux_gps_filtrada") }}
+    ),
+    veiculos_em_garagens as (
+        select
+            v.id_veiculo,
+            v.datetime_gps,
+            v.data,
+            v.servico,
+            v.posicao_veiculo_geo,
+            g.nome_parada,
+            g.tipo_parada
+        from posicoes_veiculos v
+        join
+            garagens g
+            on st_intersects(v.posicao_veiculo_geo, g.geometry)
+            and v.data >= g.inicio_vigencia
+            and (g.fim_vigencia is null or v.data <= g.fim_vigencia)
+    ),
+    terminais_proximos as (
+        select
+            v.id_veiculo,
+            v.datetime_gps,
+            v.data,
+            v.servico,
+            v.posicao_veiculo_geo,
+            t.nome_parada,
+            t.tipo_parada,
+            round(
+                st_distance(v.posicao_veiculo_geo, t.ponto_parada), 1
+            ) as distancia_parada,
+            case
+                when
+                    round(st_distance(v.posicao_veiculo_geo, t.ponto_parada), 1)
+                    < {{ var("distancia_limiar_parada") }}
+                then t.tipo_parada
+                else null
+            end as status_terminal
+        from posicoes_veiculos v
+        join
+            terminais t
+            on st_dwithin(
+                v.posicao_veiculo_geo,
+                t.ponto_parada,
+                {{ var("distancia_limiar_parada") }}
+            )
+        qualify
+            row_number() over (
+                partition by v.datetime_gps, v.id_veiculo, v.servico
+                order by st_distance(v.posicao_veiculo_geo, t.ponto_parada)
+            )
+            = 1
+    ),
+    resultados_combinados as (
+        select
+            v.id_veiculo,
+            v.datetime_gps,
+            v.data,
+            v.servico,
+            coalesce(g.tipo_parada, t.status_terminal) as tipo_parada,
+            coalesce(g.nome_parada, t.nome_parada) as nome_parada
+        from posicoes_veiculos v
+        left join
+            veiculos_em_garagens g
+            on v.id_veiculo = g.id_veiculo
+            and v.datetime_gps = g.datetime_gps
+        left join
+            terminais_proximos t
+            on v.id_veiculo = t.id_veiculo
+            and v.datetime_gps = t.datetime_gps
+    )
+select data, datetime_gps, id_veiculo, servico, tipo_parada, nome_parada
+from resultados_combinados
diff --git a/queries/models/monitoramento/staging/aux_gps_realocacao.sql b/queries/models/monitoramento/staging/aux_gps_realocacao.sql
new file mode 100644
index 000000000..01d3f3c55
--- /dev/null
+++ b/queries/models/monitoramento/staging/aux_gps_realocacao.sql
@@ -0,0 +1,68 @@
+{{ config(materialized="ephemeral") }}
+
+{% set partition_filter %}
+    ({{ generate_date_hour_partition_filter(var('date_range_start'), var('date_range_end')) }})
+{% endset %}
+
+-- 1. Filtra realocações válidas dentro do intervalo de GPS avaliado
+with
+    realocacao as (
+        select
+            * except (datetime_saida),
+            case
+                when datetime_saida is null then datetime_operacao else datetime_saida
+            end as datetime_saida
+        from {{ ref("staging_realocacao") }}
+        where
+            {{ partition_filter }}
+            -- Realocação deve acontecer após o registro de GPS e até 1 hora depois
+            and datetime_diff(datetime_operacao, datetime_entrada, minute)
+            between 0 and 60
+            and (
+                datetime_saida >= datetime("{{var('date_range_start')}}")
+                or datetime_operacao >= datetime("{{var('date_range_start')}}")
+            )
+    ),
+    -- 2. Altera registros de GPS com servicos realocados
+    gps as (
+        select *
+        from {{ ref("staging_gps") }}
+        where
+            {{ partition_filter }}
+            and datetime_gps > "{{var('date_range_start')}}"
+            and datetime_gps <= "{{var('date_range_end')}}"
+    ),
+    servicos_realocados as (
+        select
+            g.* except (servico),
+            g.servico as servico_gps,
+            r.servico as servico_realocado,
+            r.datetime_operacao as datetime_realocado
+        from gps g
+        inner join
+            realocacao r
+            on g.id_veiculo = r.id_veiculo
+            and g.servico != r.servico
+            and g.datetime_gps between r.datetime_entrada and r.datetime_saida
+    ),
+    gps_com_realocacao as (
+        select
+            g.* except (servico),
+            coalesce(s.servico_realocado, g.servico) as servico,
+            s.datetime_realocado
+        from gps g
+        left join servicos_realocados s using (id_veiculo, datetime_gps)
+    )
+-- Filtra realocacao mais recente para cada timestamp
+select * except (rn)
+from
+    (
+        select
+            *,
+            row_number() over (
+                partition by id_veiculo, datetime_gps
+                order by datetime_captura desc, datetime_realocado desc
+            ) as rn
+        from gps_com_realocacao
+    )
+where rn = 1
diff --git a/queries/models/monitoramento/staging/aux_gps_trajeto_correto.sql b/queries/models/monitoramento/staging/aux_gps_trajeto_correto.sql
new file mode 100644
index 000000000..596516c8c
--- /dev/null
+++ b/queries/models/monitoramento/staging/aux_gps_trajeto_correto.sql
@@ -0,0 +1,56 @@
+{{ config(materialized="ephemeral") }}
+
+with
+    registros as (
+        select id_veiculo, servico, data, posicao_veiculo_geo, datetime_gps
+        from {{ ref("aux_gps_filtrada") }}
+    ),
+    shapes as (
+        select distinct data, servico, feed_version, feed_start_date, route_id, shape_id
+        from {{ ref("viagem_planejada_planejamento") }}
+        {# from `rj-smtr`.`planejamento`.`viagem_planejada` #}
+        where
+            data between date('{{ var("date_range_start") }}') and date(
+                '{{ var("date_range_end") }}'
+            )
+    ),
+    intersec as (
+        select
+            r.*,
+            s.feed_version,
+            s.route_id,
+            s.shape_id,
+            st_dwithin(
+                sg.shape, r.posicao_veiculo_geo, {{ var("buffer_segmento_metros") }}
+            ) as indicador_intersecao
+        from registros r
+        left join shapes s using (servico, data)
+        left join
+            {{ ref("shapes_geom_gtfs") }} sg using (
+                {# `rj-smtr`.`gtfs`.`shapes_geom` sg using ( #}
+                feed_version, feed_start_date, shape_id
+            )
+    ),
+    indicador as (
+        select
+            *,
+            count(case when indicador_intersecao then 1 end) over (
+                partition by id_veiculo
+                order by
+                    unix_seconds(timestamp(datetime_gps))
+                    range
+                    between {{ var("intervalo_max_desvio_segundos") }} preceding
+                    and current row
+            )
+            >= 1 as indicador_trajeto_correto
+        from intersec
+    )
+select
+    data,
+    datetime_gps,
+    id_veiculo,
+    servico,
+    route_id,
+    logical_or(indicador_trajeto_correto) as indicador_trajeto_correto
+from indicador
+group by id_veiculo, servico, route_id, data, datetime_gps
diff --git a/queries/models/monitoramento/staging/aux_gps_velocidade.sql b/queries/models/monitoramento/staging/aux_gps_velocidade.sql
new file mode 100644
index 000000000..4062501e3
--- /dev/null
+++ b/queries/models/monitoramento/staging/aux_gps_velocidade.sql
@@ -0,0 +1,73 @@
+{{ config(materialized="ephemeral") }}
+
+with
+    anterior as (
+        select
+            data,
+            hora,
+            id_veiculo,
+            datetime_gps,
+            servico,
+            latitude,
+            longitude,
+            posicao_veiculo_geo,
+            datetime_captura,
+            velocidade as velocidade_original,
+            lag(posicao_veiculo_geo) over w as posicao_anterior,
+            lag(datetime_gps) over w as datetime_anterior
+        from {{ ref("aux_gps_filtrada") }}
+        window w as (partition by id_veiculo, servico order by datetime_gps)
+    ),
+    calculo_velocidade as (
+        select
+            *,
+            st_distance(posicao_veiculo_geo, posicao_anterior) as distancia,
+            ifnull(
+                safe_divide(
+                    st_distance(posicao_veiculo_geo, posicao_anterior),
+                    datetime_diff(datetime_gps, datetime_anterior, second)
+                ),
+                0
+            )
+            * 3.6 as velocidade
+        from anterior
+    ),
+    media as (
+        select
+            data,
+            datetime_gps,
+            id_veiculo,
+            servico,
+            distancia,
+            velocidade,
+            -- Calcula média móvel
+            avg(velocidade) over (
+                partition by id_veiculo, servico
+                order by
+                    unix_seconds(timestamp(datetime_gps))
+                    range
+                    between {{ var("janela_movel_velocidade") }} preceding
+                    and current row
+            ) as velocidade_media
+        from calculo_velocidade
+    )
+select
+    data,
+    datetime_gps,
+    id_veiculo,
+    servico,
+    distancia,
+    round(
+        case
+            when velocidade_media > {{ var("velocidade_maxima") }}
+            then {{ var("velocidade_maxima") }}
+            else velocidade_media
+        end,
+        1
+    ) as velocidade,
+    case
+        when velocidade_media < {{ var("velocidade_limiar_parado") }}
+        then false
+        else true
+    end as indicador_em_movimento
+from media
diff --git a/queries/models/monitoramento/staging/schema.yml b/queries/models/monitoramento/staging/schema.yml
new file mode 100644
index 000000000..a12d51229
--- /dev/null
+++ b/queries/models/monitoramento/staging/schema.yml
@@ -0,0 +1,82 @@
+version: 2
+
+models:
+  - name: staging_gps
+    description: "Tabela com todos os registros de GPS da API {{ var('fonte_gps') }}"
+    columns:
+      - name: data
+        description: "{{ doc('data_captura') }}"
+      - name: hora
+        description: "{{ doc('hora_captura') }}"
+      - name: datetime_gps
+        description: "{{ doc('timestamp_gps') }}"
+      - name: id_veiculo
+        description: "{{ doc('id_veiculo') }}"
+      - name: servico
+        description: "{{ doc('servico') }}"
+      - name: sentido
+        description: "{{ doc('sentido') }}"
+      - name: latitude
+        description: "{{ doc('latitude_gps') }}"
+      - name: longitude
+        description: "{{ doc('longitude_gps') }}"
+      - name: velocidade
+        description: "{{ doc('velocidade_instantanea') }}"
+      - name: direcao
+        description: "{{ doc('direcao_gps') }}"
+      - name: route_id
+        description: "{{ doc('route_id') }}"
+      - name: trip_id
+        description: "{{ doc('trip_id') }}"
+      - name: shape_id
+        description: "{{ doc('shape_id') }}"
+      - name: datetime_envio
+        description: "{{ doc('datetime_envio_gps') }}"
+      - name: datetime_servidor
+        description: "{{ doc('datetime_servidor_gps') }}"
+      - name: datetime_captura
+        description: "{{ doc('datetime_captura') }}"
+  - name: staging_realocacao
+    description: "Tabela com todas as realocações de linha informadas pela API {{ var('fonte_gps') }}"
+    columns:
+      - name: data
+        description: "{{ doc('data_captura') }}"
+      - name: hora
+        description: "{{ doc('hora_captura') }}"
+      - name: datetime_operacao
+        description: "{{ doc('datetime_operacao') }}"
+      - name: id_veiculo
+        description: "{{ doc('id_veiculo') }}"
+      - name: servico
+        description: "{{ doc('servico_realocacao') }}"
+      - name: datetime_entrada
+        description: "{{ doc('datetime_entrada') }}"
+      - name: datetime_saida
+        description: "{{ doc('datetime_saida') }}"
+      - name: datetime_processamento
+        description: "{{ doc('datetime_processamento') }}"
+      - name: datetime_captura
+        description: "{{ doc('datetime_captura') }}"
+  - name: staging_garagens
+    description: "Tabela com informações das garagens dos operadores"
+    columns:
+      - name: data
+        description: "{{ doc('data_captura') }}"
+      - name: operador
+        description: "Nome da empresa operadora de transporte público"
+      - name: endereco
+        description: "Endereço completo da garagem do operador"
+      - name: bairro
+        description: "Nome do bairro onde está localizada a garagem"
+      - name: oficial
+        description: "Indicador se a garagem é oficial"
+      - name: ativa
+        description: "Status operacional da garagem"
+      - name: uso
+        description: "Tipo de uso da garagem"
+      - name: obs
+        description: "Observações adicionais sobre a garagem"
+      - name: area_m2
+        description: "Área total da garagem (m²)"
+      - name: geometry_wkt
+        description: "Geometria da garagem em formato WKT"
\ No newline at end of file
diff --git a/queries/models/monitoramento/staging/staging_garagens.sql b/queries/models/monitoramento/staging/staging_garagens.sql
new file mode 100644
index 000000000..a5af2a04e
--- /dev/null
+++ b/queries/models/monitoramento/staging/staging_garagens.sql
@@ -0,0 +1,51 @@
+{{
+    config(
+        alias="garagens",
+    )
+}}
+
+with
+    garagens as (
+        select
+            data as inicio_vigencia,
+            nullif(trim(safe_cast(operador as string)), "") as operador,
+            nullif(trim(safe_cast(endereco as string)), "") as endereco,
+            nullif(trim(safe_cast(bairro as string)), "") as bairro,
+            case
+                when upper(trim(safe_cast(oficial as string))) = "SIM"
+                then true
+                when upper(trim(safe_cast(oficial as string))) = "NÃO"
+                then false
+                else null
+            end as oficial,
+            case
+                when upper(trim(safe_cast(ativa_ou_inativa as string))) = "ATIVA"
+                then true
+                when upper(trim(safe_cast(ativa_ou_inativa as string))) = "INATIVA"
+                then false
+                else null
+            end as ativa,
+            lower(nullif(trim(safe_cast(uso as string)), "")) as uso,
+            nullif(trim(safe_cast(obs as string)), "") as observacao,
+            safe_cast(area_m2 as string) as area_m2,
+            safe_cast(geometry_wkt as string) as geometry_wkt
+        from {{ source("monitoramento_staging", "garagens") }}
+    )
+select
+    inicio_vigencia,
+    date_sub(
+        lead(inicio_vigencia) over (
+            partition by operador, endereco order by inicio_vigencia
+        ),
+        interval 1 day
+    ) as fim_vigencia,
+    operador,
+    endereco,
+    bairro,
+    oficial,
+    ativa,
+    uso,
+    observacao,
+    area_m2,
+    geometry_wkt
+from garagens
diff --git a/queries/models/monitoramento/staging/staging_gps.sql b/queries/models/monitoramento/staging/staging_gps.sql
new file mode 100644
index 000000000..3ad70ea0a
--- /dev/null
+++ b/queries/models/monitoramento/staging/staging_gps.sql
@@ -0,0 +1,93 @@
+{{ config(alias=this.name ~ "_" ~ var("fonte_gps")) }}
+
+with
+    source_data as (
+        select
+            data,
+            safe_cast(hora as int64) hora,
+            datetime(
+                parse_timestamp(
+                    '%Y-%m-%dT%H:%M:%SZ',
+                    safe_cast(json_value(content, '$.datetime') as string)
+                ),
+                "America/Sao_Paulo"
+            ) datetime_gps,
+            safe_cast(id_veiculo as string) id_veiculo,
+            concat(
+                ifnull(
+                    regexp_extract(
+                        safe_cast(json_value(content, '$.servico') as string), r'[A-Z]+'
+                    ),
+                    ""
+                ),
+                ifnull(
+                    regexp_extract(
+                        safe_cast(json_value(content, '$.servico') as string), r'[0-9]+'
+                    ),
+                    ""
+                )
+            ) as servico,
+            safe_cast(json_value(content, '$.sentido') as string) sentido,
+            safe_cast(
+                replace(json_value(content, '$.latitude'), ',', '.') as float64
+            ) latitude,
+            safe_cast(
+                replace(json_value(content, '$.longitude'), ',', '.') as float64
+            ) longitude,
+            safe_cast(json_value(content, '$.velocidade') as int64) velocidade,
+            safe_cast(json_value(content, '$.direcao') as numeric) direcao,
+            safe_cast(json_value(content, '$.route_id') as string) route_id,
+            safe_cast(json_value(content, '$.trip_id') as string) trip_id,
+            safe_cast(json_value(content, '$.shape_id') as string) shape_id,
+            datetime(
+                parse_timestamp(
+                    '%Y-%m-%dT%H:%M:%SZ',
+                    safe_cast(json_value(content, '$.datetime_envio') as string)
+                ),
+                "America/Sao_Paulo"
+            ) datetime_envio,
+            datetime(
+                parse_timestamp('%Y-%m-%dT%H:%M:%SZ', datetime_servidor),
+                "America/Sao_Paulo"
+            ) datetime_servidor,
+            datetime(
+                parse_timestamp(
+                    '%Y-%m-%d %H:%M:%S%Ez',
+                    safe_cast(
+                        json_value(content, '$._datetime_execucao_flow') as string
+                    )
+                ),
+                "America/Sao_Paulo"
+            ) datetime_execucao_flow,
+            datetime(
+                parse_timestamp('%Y-%m-%d %H:%M:%S%Ez', timestamp_captura),
+                "America/Sao_Paulo"
+            ) datetime_captura
+        from {{ source("source_" ~ var("fonte_gps"), "registros") }}
+    ),
+    filtered_data as (
+        select *
+        from source_data
+        where
+            datetime_diff(datetime_envio, datetime_gps, second) >= -20
+            and datetime_diff(datetime_envio, datetime_gps, minute) <= 60
+    )
+select
+    data,
+    hora,
+    id_veiculo,
+    servico,
+    sentido,
+    latitude,
+    longitude,
+    datetime_gps,
+    velocidade,
+    direcao,
+    route_id,
+    trip_id,
+    shape_id,
+    datetime_envio,
+    datetime_servidor,
+    datetime_execucao_flow,
+    datetime_captura
+from filtered_data
diff --git a/queries/models/monitoramento/staging/staging_realocacao.sql b/queries/models/monitoramento/staging/staging_realocacao.sql
new file mode 100644
index 000000000..94e21a75a
--- /dev/null
+++ b/queries/models/monitoramento/staging/staging_realocacao.sql
@@ -0,0 +1,81 @@
+{{ config(alias=this.name ~ "_" ~ var("fonte_gps")) }}
+
+with
+    source_data as (
+        select
+            data,
+            safe_cast(hora as int64) hora,
+            datetime(
+                parse_timestamp(
+                    '%Y-%m-%dT%H:%M:%SZ',
+                    safe_cast(json_value(content, '$.datetime_operacao') as string)
+                ),
+                "America/Sao_Paulo"
+            ) datetime_operacao,
+            safe_cast(id_veiculo as string) id_veiculo,
+            concat(
+                ifnull(
+                    regexp_extract(
+                        safe_cast(json_value(content, '$.servico') as string), r'[A-Z]+'
+                    ),
+                    ""
+                ),
+                ifnull(
+                    regexp_extract(
+                        safe_cast(json_value(content, '$.servico') as string), r'[0-9]+'
+                    ),
+                    ""
+                )
+            ) as servico,
+            datetime(
+                parse_timestamp(
+                    '%Y-%m-%dT%H:%M:%SZ',
+                    safe_cast(json_value(content, '$.datetime_entrada') as string)
+                ),
+                "America/Sao_Paulo"
+            ) datetime_entrada,
+            case
+                when
+                    safe_cast(json_value(content, '$.datetime_saida') as string)
+                    = '1971-01-01 00:00:00-0300'
+                then null
+                else
+                    datetime(
+                        parse_timestamp(
+                            '%Y-%m-%dT%H:%M:%SZ',
+                            safe_cast(json_value(content, '$.datetime_saida') as string)
+                        ),
+                        "America/Sao_Paulo"
+                    )
+            end as datetime_saida,
+            datetime(
+                parse_timestamp('%Y-%m-%dT%H:%M:%SZ', datetime_processamento),
+                "America/Sao_Paulo"
+            ) datetime_processamento,
+            datetime(
+                parse_timestamp(
+                    '%Y-%m-%d %H:%M:%S%Ez',
+                    safe_cast(
+                        json_value(content, '$._datetime_execucao_flow') as string
+                    )
+                ),
+                "America/Sao_Paulo"
+            ) datetime_execucao_flow,
+            datetime(
+                parse_timestamp('%Y-%m-%d %H:%M:%S%Ez', timestamp_captura),
+                "America/Sao_Paulo"
+            ) datetime_captura
+        from {{ source("source_" ~ var("fonte_gps"), "realocacao") }}
+    )
+select distinct
+    data,
+    hora,
+    datetime_operacao,
+    id_veiculo,
+    servico,
+    datetime_entrada,
+    datetime_saida,
+    datetime_processamento,
+    datetime_execucao_flow,
+    datetime_captura
+from source_data
diff --git a/queries/models/sources.yml b/queries/models/sources.yml
index 723bbc506..c3f46f134 100644
--- a/queries/models/sources.yml
+++ b/queries/models/sources.yml
@@ -318,3 +318,30 @@ sources:
 
     tables:
       - name: ordem_servico
+
+  - name: monitoramento_staging
+    database: rj-smtr-staging
+
+    tables:
+      - name: garagens
+
+  - name: source_cittati
+    database: rj-smtr-staging
+
+    tables:
+      - name: registros
+      - name: realocacao
+
+  - name: source_conecta
+    database: rj-smtr-staging
+
+    tables:
+      - name: registros
+      - name: realocacao
+
+  - name: source_zirix
+    database: rj-smtr-staging
+
+    tables:
+      - name: registros
+      - name: realocacao
\ No newline at end of file
diff --git a/queries/selectors.yml b/queries/selectors.yml
index 24ba6e0e7..f9effeade 100644
--- a/queries/selectors.yml
+++ b/queries/selectors.yml
@@ -255,6 +255,32 @@ selectors:
       method: fqn
       value: snapshot_transito_autuacao
 
+  - name: gps
+    description: Materialização das tabelas de gps
+    definition:
+      union:
+        - method: fqn
+          value: staging_gps
+        - method: fqn
+          value: staging_realocacao
+        - method: fqn
+          value: staging_garagens
+        - method: fqn
+          value: gps
+
+  - name: gps_15_minutos
+    description: Materialização das tabelas de gps 15 minutos
+    definition:
+      union:
+        - method: fqn
+          value: staging_gps
+        - method: fqn
+          value: staging_realocacao
+        - method: fqn
+          value: staging_garagens
+        - method: fqn
+          value: gps_15_minutos
+
   - name: snapshot_viagem
     definition:
       union:
@@ -286,5 +312,3 @@ selectors:
       union:
         - method: fqn
           value: snapshot_sppo_veiculo_dia
-
-


Reviews:
user: login: eng-rodrigocunha
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2024-11-05T17:33:27Z
user: login: akaBotelho
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-11-05T17:55:17Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 7**

<details>
<summary>🔭 Outside diff range comments (1)</summary><blockquote>

<details>
<summary>queries/models/monitoramento/staging/aux_realocacao.sql (1)</summary><blockquote>

`25-26`: _🛠️ Refactor suggestion_

**Fonte dinâmica possivelmente inválida**  
O trecho  
```sql
from {{ source('br_rj_riodejaneiro_onibus_gps_' ~ var("fonte_gps") ~ '_staging', "realocacao") }}
```  
gera duplo underscore (`gps__staging`) se `fonte_gps` for vazio, levando a erro de compilação (`source ... not found`). Considere:

```diff
- from {{ source('br_rj_riodejaneiro_onibus_gps_' ~ var("fonte_gps") ~ '_staging', "realocacao") }}
+ from {{ source(
+      'br_rj_riodejaneiro_onibus_gps_' ~ coalesce(var("fonte_gps"), "defaultFonte") ~ '_staging',
+      "realocacao"
+    ) }}
```

Isso evita referências inválidas.

</blockquote></details>

</blockquote></details>

<details>
<summary>♻️ Duplicate comments (1)</summary><blockquote>

<details>
<summary>queries/models/monitoramento/staging/aux_gps_parada.sql (1)</summary><blockquote>

`21-26`: **Referências hardcoded em vez de `ref`**  
O uso de  
```sql
from `rj-smtr`.`gtfs`.`stops`
left join `rj-smtr`.`gtfs`.`stop_times`
```  
reduz portabilidade. Recomendo voltar a usar:

```sql
from {{ ref("stops_gtfs") }}
left join {{ ref("stop_times_gtfs") }}
```

Isso mantém o projeto desacoplado de esquemas específicos.

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (14)</summary><blockquote>

<details>
<summary>queries/models/monitoramento/staging/aux_gps.sql (2)</summary><blockquote>

`1-2`: **Delimitador ausente ao concatenar alias e variável**  
Recomendo usar um separador (por exemplo `"_"`) entre `this.name` e `var("fonte_gps")` para gerar aliases legíveis (ex.: `aux_gps_defaultSource`) e evitar colisões com nomes existentes.

---

`15-18`: **Simplificar aninhamento de casts de timestamp**  
A expressão `datetime(timestamp(timestamp_captura), "America/Sao_Paulo")` aplica `timestamp` duas vezes. Considere remover o cast redundante, por exemplo:  
```sql
safe_cast(datetime(timestamp_captura), "America/Sao_Paulo") as datetime_captura
```

</blockquote></details>
<details>
<summary>queries/dbt_project.yml (2)</summary><blockquote>

`41-44`: **Definir valores e descrições para as novas variáveis**  
As variáveis `fifteen_minutes`, `modo_gps` e `fonte_gps` estão vazias e sem comentário de uso. Recomendo:

- Adicionar comentários explicativos de cada variável.
- Definir valores padrão úteis ou validar presença em runtime.

Isso ajuda a evitar configurações incorretas e falhas silenciosas.

---

`59-61`: **Variável duplicada `buffer_segmento_metros`**  
A variável `buffer_segmento_metros` foi adicionada em duas seções (GPS e Viagens 2.0), o que pode causar comportamento inesperado se os contextos diferirem. Sugiro renomear uma delas ou consolidar o uso em um único lugar.

</blockquote></details>
<details>
<summary>queries/models/monitoramento/staging/aux_realocacao.sql (1)</summary><blockquote>

`1-2`: **Delimitador ausente ao concatenar alias e variável**  
Assim como em `aux_gps.sql`, usar `this.name ~ "_" ~ var("fonte_gps")` melhora a legibilidade do alias e evita nomes colidirem.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 GitHub Actions: CD-docs</summary>

[error] 1-1: Compilation Error: Model depends on a source named 'br_rj_riodejaneiro_onibus_gps__staging.realocacao' which was not found.

</details>

</details>

</blockquote></details>
<details>
<summary>queries/models/monitoramento/staging/aux_gps_parada.sql (3)</summary><blockquote>

`3-15`: **Uso de `run_query` para obter `feed_start_date` pode impactar compilação**  
Chamar `run_query` durante a etapa de compilação impede paralelismo e pode afetar a performance do dbt. Sugiro mover essa lógica para uma macro ou parametrizar `feed_start_date` via variável.

---

`31-34`: **Conversão de geometrias inconsistente**  
Em `garagens` você converte geometrias para texto com `st_astext` e depois reconverte com `st_geogfromtext` no `union all`. Considere usar `st_geogpoint(stop_lon, stop_lat)` em ambos os CTEs para evitar o overhead de texto/WKT.

---

`43-44`: **Filtro de `stop_name` sensível a case**  
A expressão `stop_name like "%Garagem%"` é case-sensitive. Avalie usar `ILIKE` ou `LOWER(stop_name) LIKE "%garagem%"` para garantir capturar todas as variações.

</blockquote></details>
<details>
<summary>queries/models/monitoramento/staging/aux_gps_trajeto_correto.sql (2)</summary><blockquote>

`30-49`: **Substituir `count(...) >= 1` por agregação booleana**  
Em vez de contar ocorrências, use `BOOL_OR` para expressar diretamente a existência de intersecções:

```sql
BOOL_OR(
  st_dwithin(
    shape,
    posicao_veiculo_geo,
    {{ var("buffer_segmento_metros") }}
  )
) OVER (
  PARTITION BY id_veiculo
  ORDER BY unix_seconds(timestamp(datetime_gps))
  RANGE BETWEEN {{ var("intervalo_max_desvio_segundos") }} PRECEDING AND CURRENT ROW
) AS indicador_trajeto_correto
```

---

`56-64`: **Fontes explícitas em vez de `ref` nos CTEs de shapes e viagem planejada**  
O uso de tabelas literais (`rj-smtr-dev`.`rafael__planejamento`.`viagem_planejada` e `rj-smtr`.`gtfs`.`shapes_geom`) reduz a portabilidade. Recomendo:

```sql
from {{ ref("viagem_planejada") }}
left join {{ ref("shapes_geom_gtfs") }} using (...)
```

para manter consistência e desacoplamento.

</blockquote></details>
<details>
<summary>queries/models/monitoramento/gps.sql (1)</summary><blockquote>

`23-29`: **Otimizar filtros de data**  
Aplicar `date(datetime_gps)` impede o uso de partições no processamento em massa. Avalie usar diretamente faixas de `datetime_gps` (ex.:  
```sql
WHERE datetime_gps >= '{{ var("date_range_start") }}'
  AND datetime_gps <  '{{ var("date_range_end") }}'::timestamp + INTERVAL '1 day'
```  
) para melhorar performance.  



Also applies to: 95-101

</blockquote></details>
<details>
<summary>queries/models/monitoramento/staging/aux_gps_velocidade.sql (2)</summary><blockquote>

`34-34`: **Use `AS` para maior clareza no alias de coluna**  
Em vez de `* 3.6 velocidade`, prefira `* 3.6 AS velocidade` para deixar explícito que `velocidade` é o alias da expressão.

---

`36-43`: **Uniformizar condição incremental**  
Este modelo checa `flags.FULL_REFRESH`, enquanto outros usam `is_incremental()`. Recomendo padronizar para `is_incremental()` em todos os modelos DBT para manter consistência.

</blockquote></details>
<details>
<summary>queries/models/monitoramento/staging/aux_gps_realocacao.sql (1)</summary><blockquote>

`2-2`: **Comentário residual `-- verificar isso`**  
Remove ou esclareça o comentário `-- verificar isso` na configuração do materialization para evitar dúvidas futuras.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between b6d6ac597548435a6e850f4e5f90ea8c95638f60 and 646325fba8a3c31f77c8d5be38bf0c8ba602c64a.

</details>

<details>
<summary>📒 Files selected for processing (9)</summary>

* `queries/dbt_project.yml` (2 hunks)
* `queries/models/monitoramento/gps.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_gps.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_gps_filtrada.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_gps_parada.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_gps_realocacao.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_gps_trajeto_correto.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_gps_velocidade.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_realocacao.sql` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 GitHub Actions: CD-docs</summary>

<details>
<summary>queries/models/monitoramento/staging/aux_realocacao.sql</summary>

[error] 1-1: Compilation Error: Model depends on a source named 'br_rj_riodejaneiro_onibus_gps__staging.realocacao' which was not found.

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: WIP
* GitHub Check: WIP

</details>

<details>
<summary>🔇 Additional comments (7)</summary><blockquote>

<details>
<summary>queries/models/monitoramento/staging/aux_gps.sql (3)</summary>

`5-7`: **Método de conversão de data e hora está correto**  
A aplicação de `safe_cast(datetime(timestamp(datahora), "America/Sao_Paulo") as datetime)` assegura a conversão de fuso horário de forma segura.

---

`9-12`: **Extração do campo `servico` robusta**  
O uso de `regexp_extract` com `ifnull` garante cobertura para casos sem parte alfabética ou numérica.

---

`13-14`: **Conversão de coordenadas consistente**  
Substituir vírgulas por pontos e converter para `FLOAT64` está adequado para normalizar a latitude/longitude.

</details>
<details>
<summary>queries/models/monitoramento/staging/aux_gps_parada.sql (1)</summary>

`1-2`: **Uso adequado de materialização `ephemeral`**  
O `materialized="ephemeral"` mantém esta model como CTE, evitando criação de objetos físicos para estágios intermediários e alinhando-se à arquitetura dos estágios.

</details>
<details>
<summary>queries/models/monitoramento/staging/aux_gps_trajeto_correto.sql (2)</summary>

`35-39`: **Uso adequado de `buffer_segmento_metros`**  
A aplicação de `st_dwithin(shape, posicao_veiculo_geo, {{ var("buffer_segmento_metros") }})` (20 m) segue o parâmetro definido no `dbt_project.yml` para checar proximidade à rota.

---

`71-73`: **Uso correto de `USING` para simplificar o join**  
Bom uso de `USING (servico, data)` para eliminar duplicação de colunas e deixar a query mais limpa.

</details>
<details>
<summary>queries/models/monitoramento/gps.sql (1)</summary>

`1-8`: **Verificar composição do alias dinâmico**  
O uso de `alias=this.name ~ var("modo_gps") ~ var("fonte_gps")` pode gerar um identificador sem separadores (ex.: `gpsModoFonte`). Considere inserir delimitadores como `_` para garantir legibilidade e evitar colisões de nomes.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T16:59:05Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 5**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>queries/models/monitoramento/staging/staging_garagens.sql (1)</summary><blockquote>

`11-17`: **Refatoração opcional: comparações case-insensitive e remoção de acentos**  
As comparações exatas com `"SIM"`, `"NÃO"`, `"ATIVA"` e `"INATIVA"` podem falhar se houver variações de caixa ou ausência de acentos. Recomenda-se normalizar antes de comparar, por exemplo:

```diff
- case
-     when safe_cast(oficial as string) = "SIM"
+ case
+     when upper(trim(safe_cast(oficial as string))) = "SIM"
```
Replicar lógica para `"NÃO"`, `"ATIVA"` e `"INATIVA"`, garantindo robustez contra variações de texto.  


Also applies to: 19-24

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 6e99c0378a518d1330dd329966078b2469e74d47 and b1d090d568e7a1331cb88fefbe2cf4b8f96c9a5e.

</details>

<details>
<summary>📒 Files selected for processing (9)</summary>

* `queries/dbt_project.yml` (2 hunks)
* `queries/models/monitoramento/gps_15_minutos.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_gps.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_gps_parada.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_gps_realocacao.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_realocacao.sql` (1 hunks)
* `queries/models/monitoramento/staging/staging_garagens.sql` (1 hunks)
* `queries/models/sources.yml` (1 hunks)
* `queries/selectors.yml` (1 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (1)</summary>

* queries/models/sources.yml

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (5)</summary>

* queries/dbt_project.yml
* queries/models/monitoramento/staging/aux_gps_parada.sql
* queries/models/monitoramento/staging/aux_realocacao.sql
* queries/models/monitoramento/staging/aux_gps.sql
* queries/models/monitoramento/staging/aux_gps_realocacao.sql

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: Build and publish docs
* GitHub Check: WIP

</details>

<details>
<summary>🔇 Additional comments (3)</summary><blockquote>

<details>
<summary>queries/selectors.yml (1)</summary>

`254-255`: **Ignorar mudanças sem impacto funcional**  
As linhas correspondentes ao `snapshot_transito` não apresentam alteração prática no selector e não requerem ação.

</details>
<details>
<summary>queries/models/monitoramento/staging/staging_garagens.sql (1)</summary>

`1-5`: **Alias de modelo adequado**  
A definição `alias="garagens"` alinha o nome da tabela materializada com o conteúdo do modelo e facilita o uso em joins.

</details>
<details>
<summary>queries/models/monitoramento/gps_15_minutos.sql (1)</summary>

`1-8`: **Configuração do modelo incremental**  
A materialização incremental, particionamento diário e alias dinâmico via `var("modo_gps")` e `var("fonte_gps")` estão corretamente definidos.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-08T22:23:15Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>♻️ Duplicate comments (1)</summary><blockquote>

<details>
<summary>queries/models/monitoramento/staging/aux_gps.sql (1)</summary><blockquote>

`1-1`: **Duplicado: Valor padrão de `fonte_gps`**  
Sem valor padrão para `var("fonte_gps")`, o alias pode ficar inválido (ex: `aux_gps_`).

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>queries/models/sources.yml (1)</summary><blockquote>

`347-347`: **Ajuste de formatação: nova linha no fim do arquivo**  
O YAML requer um caractere de nova linha ao final do arquivo para passar na validação (`new-line-at-end-of-file`).

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 347-347: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</blockquote></details>
<details>
<summary>queries/models/monitoramento/staging/aux_gps.sql (2)</summary><blockquote>

`5-11`: **Sugestão de refactor opcional: simplificar parsing de data/hora**  
A lógica de conversão de timestamp e timezone se repete em vários campos (`datetime_gps`, `datetime_envio`, `datetime_servidor`, `datetime_captura`). Considere extrair uma macro (por exemplo, `parse_datetime(field, timezone)`) para reduzir duplicação e facilitar manutenção. 


Also applies to: 36-47, 48-50

---

`52-57`: **Nitpick: Vírgula extra na chamada de `source()`**  
A vírgula após `"registros"` pode ser removida para manter a sintaxe mais limpa, embora não cause erro.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between b1d090d568e7a1331cb88fefbe2cf4b8f96c9a5e and 29d2819fbc6418584be13c9d9c0fdda19d59a99e.

</details>

<details>
<summary>📒 Files selected for processing (9)</summary>

* `queries/dbt_project.yml` (2 hunks)
* `queries/models/monitoramento/staging/aux_gps.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_gps_parada.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_gps_realocacao.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_gps_trajeto_correto.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_realocacao.sql` (1 hunks)
* `queries/models/monitoramento/staging/staging_garagens.sql` (1 hunks)
* `queries/models/sources.yml` (1 hunks)
* `queries/selectors.yml` (1 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (7)</summary>

* queries/dbt_project.yml
* queries/models/monitoramento/staging/staging_garagens.sql
* queries/models/monitoramento/staging/aux_realocacao.sql
* queries/selectors.yml
* queries/models/monitoramento/staging/aux_gps_parada.sql
* queries/models/monitoramento/staging/aux_gps_trajeto_correto.sql
* queries/models/monitoramento/staging/aux_gps_realocacao.sql

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

<details>
<summary>queries/models/sources.yml</summary>

[error] 347-347: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: WIP
* GitHub Check: WIP

</details>

<details>
<summary>🔇 Additional comments (8)</summary><blockquote>

<details>
<summary>queries/models/sources.yml (4)</summary>

`321-327`: **Confirmação: Adição da fonte `monitoramento_staging`**  
A nova fonte `monitoramento_staging` com a tabela `garagens` reforça o pipeline de staging para monitoramento de GPS. As configurações de `database: rj-smtr-staging` estão corretas.

---

`328-334`: **Confirmação: Adição da fonte `source_cittati`**  
A fonte `source_cittati` e suas tabelas `registros` e `realocacao` estão alinhadas com os novos modelos de staging para processamento de dados de GPS.

---

`335-341`: **Confirmação: Adição da fonte `source_conecta`**  
A fonte `source_conecta` com as mesmas tabelas está configurada corretamente para suportar o processamento de GPS.

---

`342-347`: **Confirmação: Adição da fonte `source_zirix`**  
A fonte `source_zirix` e suas tabelas `registros` e `realocacao` seguem o padrão estabelecido para múltiplas origens de GPS.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 347-347: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</details>
<details>
<summary>queries/models/monitoramento/staging/aux_gps.sql (4)</summary>

`12-25`: **Aprovação: Extração do campo `servico`**  
A concatenação de partes alfabéticas e numéricas usando `regexp_extract` garante um serviço limpo. Implementação clara e eficiente.

---

`27-30`: **Aprovação: Conversão de coordenadas**  
O uso de `replace` para tratar vírgulas antes de converter para `float64` atende ao formato esperado dos dados.

---

`31-32`: **Aprovação: Conversão de velocidade e direção**  
Os casts para `int64` e `numeric` estão corretos e garantem o tipo adequado para cálculos posteriores.

---

`33-35`: **Aprovação: Captura de identificadores de rota**  
Os campos `route_id`, `trip_id` e `shape_id` são convertidos para `string` de forma consistente.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T18:29:00Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 4**

<details>
<summary>🧹 Nitpick comments (4)</summary><blockquote>

<details>
<summary>queries/models/monitoramento/staging/schema.yml (2)</summary><blockquote>

`79-101`: **Uniformizar uso de macros de documentação em `staging_garagens`**  
Enquanto nos modelos anteriores as descrições usam `{{ doc('...') }}`, aqui temos literais. Para manter consistência e reaproveitamento, avalie criar macros (em `docs.md`) para campos como `operador`, `endereco`, `bairro` e `area_m2`.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 101-101: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

---

`101-101`: **Adicionar newline ao final do arquivo**  
O YAML linter apontou ausência de quebra de linha ao final. Adicionar uma linha vazia no fim do arquivo evita esse erro.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 101-101: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</blockquote></details>
<details>
<summary>queries/models/monitoramento/schema.yml (2)</summary><blockquote>

`319-347`: **Modelo `gps_15_minutos`: duplicação, ausência de metadados e descrição genérica**  
1. Assim como em `gps`, faltam `data_type` e `quote` em todas as colunas.  
2. A definição de colunas é idêntica ao modelo `gps`; recomendo usar anchors YAML para evitar duplicação e facilitar futuras manutenções.  
3. Ajuste a `description` para evidenciar que este modelo é uma agregação de 15 minutos, diferenciando-o da tabela diária.  
  
Exemplo de refatoração com anchor:

```yaml
# Definição de colunas comum
columns_gps: &columns_gps
  - name: data
    description: "{{ doc('data_gps') }}"
    data_type: date
    quote: true
  # ... repita para cada coluna ...

models:
  - name: gps
    description: "Tabela com os dados tratados de registros de GPS da API {{ var('fonte_gps') }}, incluindo velocidade estimada, estado de movimento, parada em terminal ou garagem e interseção com o traçado da linha informada"
    columns: *columns_gps

  - name: gps_15_minutos
    description: "Agregação de 15 minutos dos dados tratados de GPS da API {{ var('fonte_gps') }}, incluindo velocidade estimada e estado de movimento"
    columns: *columns_gps
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 347-347: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

---

`347-347`: **Adicionar newline ao final do arquivo**  
O lint de YAML sinaliza ausência de nova linha ao fim do arquivo (`new-line-at-end-of-file`). Adicione uma linha em branco ao final para atender ao padrão POSIX.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 347-347: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between dc6c025ae146c50706b20abba8375844ceecdb86 and 2e1eadd4b35f36858a5a1ed75bee24fb3b0b5c2c.

</details>

<details>
<summary>📒 Files selected for processing (8)</summary>

* `queries/models/docs.md` (1 hunks)
* `queries/models/monitoramento/gps.sql` (1 hunks)
* `queries/models/monitoramento/gps_15_minutos.sql` (1 hunks)
* `queries/models/monitoramento/schema.yml` (1 hunks)
* `queries/models/monitoramento/staging/aux_gps.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_gps_realocacao.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_realocacao.sql` (1 hunks)
* `queries/models/monitoramento/staging/schema.yml` (1 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (2)</summary>

* queries/models/monitoramento/gps.sql
* queries/models/docs.md

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (4)</summary>

* queries/models/monitoramento/staging/aux_realocacao.sql
* queries/models/monitoramento/staging/aux_gps.sql
* queries/models/monitoramento/staging/aux_gps_realocacao.sql
* queries/models/monitoramento/gps_15_minutos.sql

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

<details>
<summary>queries/models/monitoramento/schema.yml</summary>

[error] 347-347: no new line character at the end of file

(new-line-at-end-of-file)

</details>
<details>
<summary>queries/models/monitoramento/staging/schema.yml</summary>

[error] 101-101: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: Build and publish docs
* GitHub Check: WIP

</details>

<details>
<summary>🔇 Additional comments (1)</summary><blockquote>

<details>
<summary>queries/models/monitoramento/staging/schema.yml (1)</summary>

`1-2`: **Estrutura de versão YAML válida**  
A declaração `version: 2` e o início do bloco `models:` seguem o padrão do dbt para esquemas.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T22:18:27Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>🧹 Nitpick comments (6)</summary><blockquote>

<details>
<summary>queries/models/monitoramento/staging/staging_garagens.sql (6)</summary><blockquote>

`1-5`: **Especifique a materialização do modelo**  
Para manter consistência com outros models de staging, recomendo adicionar por exemplo `materialized='view'` ou `'table'` dentro do `config()`.

---

`7-9`: **Evitando colisão de nomes entre CTE e alias do modelo**  
O CTE e o alias do modelo compartilham o mesmo nome `garagens`, o que pode causar confusão. Considere renomear o CTE (ex.: `raw_garagens` ou `stg_garagens`).

---

`10-13`: **Centralizar limpeza de strings em macro**  
Campos como `operador`, `endereco` e `bairro` repetem `nullif(trim(safe_cast(...)), "")`. Sugiro criar um macro (ex.: `clean_string`) para padronizar e reduzir duplicação.

---

`21-27`: **Consistência no tratamento de booleanos para 'ativa_ou_inativa'**  
Assim como em `oficial`, usar `trim()` e `upper()` em `safe_cast(ativa_ou_inativa as string)` evita bugs por formatação inesperada. Avalie também encapsular em macro.

---

`28-28`: **Ajuste na ordem de chamadas para legibilidade**  
Recomendo trocar para `nullif(lower(trim(...)), "")` em vez de `lower(nullif(trim(...), ""))`, pois a primeira forma torna mais claro o fluxo de limpeza e normalização.

---

`37-42`: **Sugestão de macro para cálculo de `fim_vigencia`**  
O padrão `date_sub(lead(...) over(...), interval 1 day)` é recorrente em SCDs. Considere usar o `dbt_utils.dateadd` ou um macro interno para manter o SQL consistente.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 2e1eadd4b35f36858a5a1ed75bee24fb3b0b5c2c and b7a088cfbd346e6a2a05d8c3a7566f41ad61f2e6.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `queries/models/monitoramento/staging/aux_gps_parada.sql` (1 hunks)
* `queries/models/monitoramento/staging/staging_garagens.sql` (1 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* queries/models/monitoramento/staging/aux_gps_parada.sql

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: Build and publish docs
* GitHub Check: WIP

</details>

<details>
<summary>🔇 Additional comments (4)</summary><blockquote>

<details>
<summary>queries/models/monitoramento/staging/staging_garagens.sql (4)</summary>

`29-29`: **Confirmação de renomeação de coluna 'obs'**  
O campo `obs` foi renomeado para `observacao`. Verifique se o `schema.yml` está atualizado e se não há dependências de `obs` em outros modelos.

---

`30-31`: **Verifique os tipos esperados para `area_m2` e `geometry_wkt`**  
Ambos são convertidos para `STRING`, mas `area_m2` pode precisar permanecer `NUMERIC` para cálculos downstream, e `geometry_wkt` talvez se beneficie de ser `GEOGRAPHY`. Confirme os requisitos.

---

`32-32`: **Valide a configuração de fonte `monitoramento_staging.garagens`**  
Assegure que esse `source` está corretamente definido em `queries/models/sources.yml` e que a tabela existe com as permissões apropriadas.

---

`35-36`: **Seleção final de colunas alinhada ao schema**  
O SELECT final mapeia corretamente todas as colunas transformadas conforme o `schema.yml`.  



Also applies to: 43-52

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T17:29:56Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>queries/CHANGELOG.md (1)</summary><blockquote>

`3-7`: **Sugestão de hyperlink para PR**  
Para atender à recomendação MD034 (sem URLs cruas), converta a URL em um link de texto mais legível.  


```diff
- - Adiciona selector `gps` (https://github.com/prefeitura-rio/pipelines_rj_smtr/pull/297)
+ - Adiciona selector `gps` ([#297](https://github.com/prefeitura-rio/pipelines_rj_smtr/pull/297))
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

7-7: Bare URL used
null

(MD034, no-bare-urls)

</details>

</details>

</blockquote></details>
<details>
<summary>queries/models/monitoramento/CHANGELOG.md (1)</summary><blockquote>

`7-7`: **Corrija a formatação do item de lista**  
- Remova o espaço antes do hífen para alinhar ao nível correto e atender MD007.  
- Evite URL “crua”: envolva `<https://github.com/prefeitura-rio/pipelines_rj_smtr/pull/297>` ou utilize texto âncora para atender MD034.  

Sugestão de diff:  
```diff
-  - Cria modelos `gps`, `gps_15_minutos`, `aux_gps`, `aux_gps_filtrada`, `aux_gps_parada`, `aux_gps_realocacao`, `aux_gps_trajeto_correto`, `aux_gps_velocidade` ,`aux_realocacao` e `staging_garagens`(https://github.com/prefeitura-rio/pipelines_rj_smtr/pull/297)
+ - Cria modelos `gps`, `gps_15_minutos`, `aux_gps`, `aux_gps_filtrada`, `aux_gps_parada`, `aux_gps_realocacao`, `aux_gps_trajeto_correto`, `aux_gps_velocidade`, `aux_realocacao` e `staging_garagens` (<https://github.com/prefeitura-rio/pipelines_rj_smtr/pull/297>)
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

7-7: Unordered list indentation
Expected: 0; Actual: 1

(MD007, ul-indent)

---

7-7: Bare URL used
null

(MD034, no-bare-urls)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between edf267c09c45e4109887a1fc9887071a8b01fb79 and 475587a45fda996d5234068b6653f0aab3c92f9c.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `queries/CHANGELOG.md` (1 hunks)
* `queries/models/monitoramento/CHANGELOG.md` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

<details>
<summary>queries/CHANGELOG.md</summary>

7-7: Bare URL used
null

(MD034, no-bare-urls)

</details>
<details>
<summary>queries/models/monitoramento/CHANGELOG.md</summary>

7-7: Unordered list indentation
Expected: 0; Actual: 1

(MD007, ul-indent)

---

7-7: Bare URL used
null

(MD034, no-bare-urls)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: Build and publish docs
* GitHub Check: WIP

</details>

<details>
<summary>🔇 Additional comments (1)</summary><blockquote>

<details>
<summary>queries/models/monitoramento/CHANGELOG.md (1)</summary>

`3-3`: **Valide versão e data de release**  
Confirme se a tag `[1.3.7]` e a data `2025-05-20` correspondem ao release pretendido, para manter o histórico de mudanças consistente.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T17:01:39Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>♻️ Duplicate comments (1)</summary><blockquote>

<details>
<summary>queries/models/monitoramento/staging/aux_gps.sql (1)</summary><blockquote>

`1-1`: _🛠️ Refactor suggestion_

**Garantir valor padrão ou validação de `fonte_gps`**  
Caso `var("fonte_gps")` não seja definido, o alias e a referência `source` ficarão inválidos, causando falha na compilação. Considere usar `var("fonte_gps", "valor_default")` ou lançar um erro claro se a variável não for especificada.

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (5)</summary><blockquote>

<details>
<summary>queries/models/monitoramento/staging/aux_gps.sql (5)</summary><blockquote>

`15-28`: **Simplificar extração do campo `servico`**  
A concatenação de duas chamadas de `regexp_extract` pode ser substituída por uma única expressão regular, por exemplo:  
```sql
regexp_extract(safe_cast(json_value(content, '$.servico') as string), r'([A-Z]+[0-9]+)') as servico
```  
Isso melhora a legibilidade e reduz repetição.

---

`29-35`: **Adicionar `TRIM` no cast de latitude/longitude**  
Para evitar falhas em casos de espaços em branco ou caracteres inesperados, envolva o resultado de `json_value` em `TRIM`, assim:  
```sql
safe_cast(
  replace(trim(json_value(content, '$.latitude')), ',', '.') 
  as float64
) latitude
```

---

`41-59`: **DRY na conversão de timestamps e verificação de tipo**  
A repetição de blocos para converter JSON em `datetime` sugere a criação de um macro Jinja para centralizar essa lógica de parsing.  
Além disso, confirme o tipo de `timestamp_captura` no schema de origem para garantir que `timestamp(timestamp_captura)` funcione sem erros de tipo.

---

`68-74`: **Uso de `DATETIME_DIFF`: avaliar `TIMESTAMP_DIFF`**  
Como ambos os campos são convertidos para `DATETIME`, pode haver perda de precisão ou desconsideração de fusos em limites de segundos. Considere usar `TIMESTAMP_DIFF` diretamente nos valores originais, ou unificar as condições em uma cláusula `BETWEEN`.

---

`75-90`: **Remover colunas não utilizadas na CTE `source_data`**  
Os campos `data` e `hora` são carregados mas não aparecem no `SELECT` final. Remova-os da CTE intermediária para reduzir uso de I/O e otimizar performance.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 475587a45fda996d5234068b6653f0aab3c92f9c and c65b5da5b108bf66904bff22946a6b2d1d46eb64.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `queries/models/monitoramento/staging/aux_gps.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_realocacao.sql` (1 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* queries/models/monitoramento/staging/aux_realocacao.sql

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: Build and publish docs
* GitHub Check: WIP

</details>

<details>
<summary>🔇 Additional comments (2)</summary><blockquote>

<details>
<summary>queries/models/monitoramento/staging/aux_gps.sql (2)</summary>

`4-13`: **Conversão de `datetime` e timezone está correta**  
O uso de `safe_cast(... as string)` em conjunto com `datetime(timestamp(...), "America/Sao_Paulo")` garante que os valores JSON sejam parseados adequadamente para o fuso de São Paulo.

---

`36-40`: **Conversões de campos JSON adequadas**  
As castings de `velocidade`, `direcao`, `route_id`, `trip_id` e `shape_id` estão corretas e lidam de forma apropriada com possíveis valores nulos ou formatos incorretos.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T22:35:25Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>queries/CHANGELOG.md (1)</summary><blockquote>

`7-7`: **Substituir URL nua por link Markdown para evitar alerta de lint**  
Para atender à regra MD034 (no-bare-urls) e melhorar a legibilidade, sugiro converter a URL em um link Markdown.  

```diff
- - Adiciona selector `gps` e `gps_15_minutos` (https://github.com/prefeitura-rio/pipelines_rj_smtr/pull/297)
+ - Adiciona selector `gps` e `gps_15_minutos` [#297](https://github.com/prefeitura-rio/pipelines_rj_smtr/pull/297)
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

7-7: Bare URL used
null

(MD034, no-bare-urls)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 88888bcc8d223489dde083b5dcc7fa51d5e59549 and f6f1f937d92a0cedf23c261201f1cbde2fda9695.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `queries/CHANGELOG.md` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

<details>
<summary>queries/CHANGELOG.md</summary>

7-7: Bare URL used
null

(MD034, no-bare-urls)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: Build and publish docs
* GitHub Check: WIP

</details>

<details>
<summary>🔇 Additional comments (1)</summary><blockquote>

<details>
<summary>queries/CHANGELOG.md (1)</summary>

`3-4`: **Confirmação do padrão de versionamento do changelog**  
A entrada `## [1.0.4] - 2025-05-20` segue o mesmo padrão de formatação das versões anteriores e está correta.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-21T19:11:41Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 4**

<details>
<summary>♻️ Duplicate comments (2)</summary><blockquote>

<details>
<summary>queries/models/monitoramento/gps_15_minutos.sql (1)</summary><blockquote>

`25-35`: _🛠️ Refactor suggestion_

**Aplicar filtragem incremental nas CTEs auxiliares**  
As CTEs `velocidades`, `paradas` e `indicadores` fazem varredura completa em cada execução. Para otimizar desempenho em runs incrementais, inclua condições `WHERE` com `{% if is_incremental() %}` delimitando `data` ou `datetime_gps` entre `var("date_range_start")` e `var("date_range_end")`.

</blockquote></details>
<details>
<summary>queries/models/monitoramento/gps.sql (1)</summary><blockquote>

`78-78`: _⚠️ Potential issue_

**Correção de sintaxe SQL: substituir aspas duplas por simples em literais**

As funções SQL requerem literais entre aspas simples. Substitua `concat("Parado ", tipo_parada)` por `concat('Parado ', tipo_parada)` e `current_datetime("America/Sao_Paulo")` por `current_datetime('America/Sao_Paulo')`.




Aplique esta correção:

```diff
-                        then concat("Parado ", tipo_parada)
+                        then concat('Parado ', tipo_parada)
```

```diff
-    current_datetime("America/Sao_Paulo") as datetime_ultima_atualizacao
+    current_datetime('America/Sao_Paulo') as datetime_ultima_atualizacao
```


Also applies to: 108-108

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (13)</summary><blockquote>

<details>
<summary>queries/macros/generate_date_hour_partition_filter.sql (3)</summary><blockquote>

`1-5`: **Validar e tratar entradas de timestamp**  
Atualmente o macro assume que `start_timestamp` e `end_timestamp` vêm em formato ISO válido e que `start <= end`. Seria interessante adicionar uma verificação para garantir que as strings são válidas e que a data inicial não é posterior à final, evitando erros de execução em tempo de compilação.

---

`10-13`: **Padronizar aspas e agrupamento na condição de dois dias**  
Além de trocar aspas duplas por simples nas chamadas `date()`, recomenda-se agrupar cada bloco OR entre parênteses para maior clareza e evitar ambiguidades de precedência:  
```diff
-    (data = date("{{ start_timestamp }}") and hora >= {{ start.hour }})
-    or (data = date("{{ end_timestamp }}") and hora <= {{ end.hour }})
+    (data = date('{{ start_timestamp }}') AND hora >= {{ start.hour }})
+    OR (data = date('{{ end_timestamp }}') AND hora <= {{ end.hour }})
```

---

`14-17`: **Envolver condição multi-dia em parênteses**  
Para o caso de intervalos maiores que um dia, recomenda-se envolver todo o bloco OR em um parêntese externo, garantindo consistência ao inserir o filtro em cláusulas `WHERE`:  
```diff
-    (data = date("{{ start_timestamp }}") and hora >= {{ start.hour }})
-    or (data > date("{{ start_timestamp }}") and data < date("{{ end_timestamp }}"))
-    or (data = date("{{ end_timestamp }}") and hora <= {{ end.hour }})
+    (
+      (data = date('{{ start_timestamp }}') AND hora >= {{ start.hour }})
+      OR (data > date('{{ start_timestamp }}') AND data < date('{{ end_timestamp }}'))
+      OR (data = date('{{ end_timestamp }}') AND hora <= {{ end.hour }})
+    )
```

</blockquote></details>
<details>
<summary>queries/models/br_rj_riodejaneiro_brt_gps/schema.yml (1)</summary><blockquote>

`68-96`: **Remover código comentado ou documentar intenção**  
A seção `registros_historico` está completamente comentada. Se este modelo não for mais necessário, remova-o para evitar confusão e manter o YAML limpo. Caso pretenda reativá-lo futuramente, adicione um comentário explicando o motivo do comentário em bloco.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.37.1)</summary>

[error] 96-96: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</blockquote></details>
<details>
<summary>queries/models/monitoramento/staging/staging_gps.sql (3)</summary><blockquote>

`8-14`: **Refatorar parsing de timestamp para macro reutilizável**  
A lógica de `datetime(parse_timestamp(...), "America/Sao_Paulo")` se repete diversas vezes. Recomendo criar um macro Jinja para centralizar essa conversão de timestamps JSON e aplicar em todos os campos, reduzindo duplicação e facilitando futuras alterações de fuso horário ou formato.

---

`16-29`: **Otimizar extração do campo `servico`**  
Atualmente usa duas expressões `regexp_extract` separadas para letras e números. Uma alternativa mais concisa é usar uma única expressão regex, por exemplo:  
```sql
regexp_extract(safe_cast(json_value(content, '$.servico') AS string), r'([A-Z]+[0-9]+)')
```  
Isso melhora legibilidade e mantém a lógica em um único passo.

---

`72-74`: **Aprimorar precisão do filtro temporal**  
O uso combinado de `datetime_diff` em `second` e `minute` pode deixar passar valores entre limites (ex.: 61 segundos retorna 1 minuto). Sugiro padronizar a condição usando apenas segundos, por exemplo:  
```sql
WHERE datetime_diff(datetime_envio, datetime_gps, second) BETWEEN -20 AND 3600
```  
Isso garante controle mais preciso do intervalo.

</blockquote></details>
<details>
<summary>queries/models/monitoramento/staging/staging_realocacao.sql (2)</summary><blockquote>

`8-14`: **Centralizar lógica de conversão de timestamp em macro**  
Semelhante ao modelo `staging_gps`, a expressão `datetime(parse_timestamp(...), "America/Sao_Paulo")` se repete. Recomendo criar um macro para conversão uniforme e aplicá-lo em `datetime_operacao`, `datetime_entrada`, `datetime_saida` e demais campos de data.

---

`70-81`: **Avaliar uso de `SELECT DISTINCT`**  
O `DISTINCT` garante unicidade, mas pode ser custoso em grandes volumes. Se possível, prefira deduplicação na CTE ou via `ROW_NUMBER()` em vez de pós-filtragem, melhorando desempenho.

</blockquote></details>
<details>
<summary>queries/models/monitoramento/staging/schema.yml (1)</summary><blockquote>

`1-82`: **Esquema bem estruturado com definições consistentes**

O arquivo de esquema está bem organizado, utilizando macros de documentação para garantir consistência nas descrições. A estrutura das três tabelas de staging (`staging_gps`, `staging_realocacao`, `staging_garagens`) está clara e bem documentada.




Corrija o problema de formatação identificado pela análise estática:

```diff
       - name: geometry_wkt
         description: "Geometria da garagem em formato WKT"
+
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.37.1)</summary>

[error] 82-82: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</blockquote></details>
<details>
<summary>queries/models/monitoramento/staging/aux_gps_realocacao.sql (2)</summary><blockquote>

`3-5`: **Unificar aplicação do filtro de partição**  
O macro `partition_filter` já encapsula o intervalo de datas de início e fim. Nos CTEs `realocacao` e `gps` há filtros manuais adicionais usando `var('date_range_start')` e `var('date_range_end')`. Se o macro garantir ambos os limites, considere removê-los para evitar redundância e possíveis inconsistências.

---

`32-33`: **Inclusividade do limite inferior do intervalo de data**  
O filtro `and datetime_gps > "{{ var('date_range_start') }}"` exclui registros exatamente no timestamp de início. Para incluir esses registros e manter consistência com `partition_filter`, recomendo usar `>=` em vez de `>`.

</blockquote></details>
<details>
<summary>queries/models/br_rj_riodejaneiro_onibus_gps/sppo_aux_registros_filtrada.sql (1)</summary><blockquote>

`3-8`: **Refatorar repetição de `var('15_minutos', false)` para melhorar legibilidade**

Recomendo capturar o valor de `var('15_minutos', false)` em uma variável temporária antes do bloco `config`, evitando chamadas repetidas e tornando o código mais limpo:

```diff
--- a/queries/models/br_rj_riodejaneiro_onibus_gps/sppo_aux_registros_filtrada.sql
+++ b/queries/models/br_rj_riodejaneiro_onibus_gps/sppo_aux_registros_filtrada.sql
@@
-{{
-    config(
-        materialized = 'ephemeral' if var('15_minutos', false) else 'incremental',
-        partition_by = {"field": "data", "data_type": "date", "granularity": "day"} if not var('15_minutos', false) else none,
-        require_partition_filter = true if not var('15_minutos', false) else false
-    )
-}}
+{%- set is_15_minutos = var('15_minutos', false) -%}
+{{
+    config(
+        materialized = 'ephemeral' if is_15_minutos else 'incremental',
+        partition_by = {"field": "data", "data_type": "date", "granularity": "day"} if not is_15_minutos else none,
+        require_partition_filter = true if not is_15_minutos else false
+    )
+}}
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between f6f1f937d92a0cedf23c261201f1cbde2fda9695 and 380292d64c92f20938fa9ba23eed4e1f4b0eed9b.

</details>

<details>
<summary>📒 Files selected for processing (18)</summary>

* `pipelines/migration/br_rj_riodejaneiro_onibus_gps/flows.py` (5 hunks)
* `queries/dbt_project.yml` (2 hunks)
* `queries/macros/generate_date_hour_partition_filter.sql` (1 hunks)
* `queries/models/br_rj_riodejaneiro_brt_gps/schema.yml` (1 hunks)
* `queries/models/br_rj_riodejaneiro_onibus_gps/sppo_aux_registros_filtrada.sql` (1 hunks)
* `queries/models/br_rj_riodejaneiro_onibus_gps/sppo_aux_registros_realocacao.sql` (1 hunks)
* `queries/models/monitoramento/gps.sql` (1 hunks)
* `queries/models/monitoramento/gps_15_minutos.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_gps_filtrada.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_gps_parada.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_gps_realocacao.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_gps_trajeto_correto.sql` (1 hunks)
* `queries/models/monitoramento/staging/aux_gps_velocidade.sql` (1 hunks)
* `queries/models/monitoramento/staging/schema.yml` (1 hunks)
* `queries/models/monitoramento/staging/staging_garagens.sql` (1 hunks)
* `queries/models/monitoramento/staging/staging_gps.sql` (1 hunks)
* `queries/models/monitoramento/staging/staging_realocacao.sql` (1 hunks)
* `queries/selectors.yml` (1 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (1)</summary>

* queries/models/br_rj_riodejaneiro_onibus_gps/sppo_aux_registros_realocacao.sql

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (7)</summary>

* queries/models/monitoramento/staging/staging_garagens.sql
* queries/dbt_project.yml
* queries/models/monitoramento/staging/aux_gps_filtrada.sql
* queries/models/monitoramento/staging/aux_gps_parada.sql
* queries/models/monitoramento/staging/aux_gps_velocidade.sql
* queries/selectors.yml
* queries/models/monitoramento/staging/aux_gps_trajeto_correto.sql

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 YAMLlint (1.37.1)</summary>

<details>
<summary>queries/models/br_rj_riodejaneiro_brt_gps/schema.yml</summary>

[error] 96-96: no new line character at the end of file

(new-line-at-end-of-file)

</details>
<details>
<summary>queries/models/monitoramento/staging/schema.yml</summary>

[error] 82-82: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (4)</summary>

* GitHub Check: Build and publish docs
* GitHub Check: Build Fedora Image
* GitHub Check: Register flows (staging)
* GitHub Check: WIP

</details>

<details>
<summary>🔇 Additional comments (16)</summary><blockquote>

<details>
<summary>queries/models/monitoramento/staging/staging_gps.sql (2)</summary>

`1-2`: **Alias dinâmico bem definido**  
O uso de `config(alias=this.name ~ "_" ~ var("fonte_gps"))` está correto e facilita a materialização de múltiplas fontes GPS.

---

`75-93`: **Verificar tratamento de nulos em `content`**  
Caso `json_value(content, ...)` retorne `NULL`, alguns campos (ex.: `trip_id`, `shape_id`) podem ser `NULL` e impactar junções posteriores. Recomendo validar na `filtered_data` ou adicionar filtros para descartar registros com campos críticos nulos, garantindo consistência nos modelos auxiliares.

</details>
<details>
<summary>queries/models/monitoramento/staging/staging_realocacao.sql (2)</summary>

`1-2`: **Alias dinâmico configurado corretamente**  
O uso de `config(alias=this.name ~ "_" ~ var("fonte_gps"))` atende ao padrão adotado nos demais modelos de staging e facilita a orquestração de pipelines.

---

`37-43`: **Verificar lógica de fallback para `datetime_saida`**  
O valor padrão `'1971-01-01 00:00:00-0300'` pode variar conforme fonte de dados ou fuso. Confirme com o time se esse timestamp é a única forma de identificar ausência de saída; caso contrário, considere tratar formatos alternativos ou usar `NULLIF`.

</details>
<details>
<summary>queries/models/br_rj_riodejaneiro_onibus_gps/sppo_aux_registros_filtrada.sql (3)</summary>

`1-9`: **Refatoração bem executada da configuração do modelo**

A mudança de uma estrutura condicional multi-branch para operadores ternários inline melhora significativamente a legibilidade do código. A renomeação da variável de `"fifteen_minutes"` para `"15_minutos"` está alinhada com as alterações do projeto e mantém a funcionalidade equivalente.

---

`1-2`: **Uso apropriado de `-- fmt: off/on` para preservar formatação do bloco de configuração**

Você desabilitou e reabilitou o formatador exatamente ao redor do bloco Jinja, garantindo que o config permaneça no formato desejado.  



Also applies to: 9-9

---

`4-6`: **Verificar tratamento de `none` no `partition_by`**

Confirme se o `config` do dbt aceita corretamente o `none` (Jinja) para desabilitar `partition_by`, ou se é necessário usar `null`. Isso evitará possíveis erros de parsing ao materializar o modelo.

</details>
<details>
<summary>pipelines/migration/br_rj_riodejaneiro_onibus_gps/flows.py (3)</summary>

`169-169`: **Melhoria na tipagem do parâmetro**

A alteração do parâmetro de `"fifteen_minutes"` (string) para `"15_minutos"` (boolean) melhora a tipagem e clareza do código. O valor padrão `False` é mais apropriado que uma string vazia.

---

`232-232`: **Atualização consistente das chaves do dicionário**

As referências ao parâmetro foram atualizadas consistentemente de `"fifteen_minutes"` para `"15_minutos"`, mantendo a funcionalidade do fluxo com a nova convenção de nomenclatura.




Also applies to: 242-242

---

`597-597`: **Valores hardcoded apropriados para fluxos de 15 minutos**

O uso de `"15_minutos": True` hardcoded é apropriado para estes fluxos específicos que são projetados para operar no modo de 15 minutos.




Also applies to: 624-624

</details>
<details>
<summary>queries/models/monitoramento/gps.sql (4)</summary>

`1-9`: **Configuração sólida para modelo incremental de GPS**

A configuração está bem estruturada com estratégia `insert_overwrite`, particionamento diário e aliasing dinâmico baseado nas variáveis do projeto. O uso de tags para categorização também é uma boa prática.

---

`11-23`: **Lógica de partições dinâmicas bem implementada**

A detecção dinâmica de partições para execuções incrementais está bem estruturada, usando adequadamente as proteções `execute` e `is_incremental()`. Essa abordagem permite otimização eficiente durante atualizações incrementais.

---

`89-91`: **Uso adequado de USING em joins**

O uso de `USING (id_veiculo, datetime_gps, servico)` nas junções está correto e segue as boas práticas quando as colunas têm os mesmos nomes, conforme indicado em comentários anteriores.

---

`57-104`: **Lógica de negócio bem estruturada para monitoramento GPS**

A estrutura com múltiplas CTEs organiza eficientemente os diferentes aspectos dos dados de GPS (registros, velocidades, paradas, indicadores). A lógica de status combinando movimento e correção de trajeto está bem fundamentada, e o sistema de prioridades para atualizações incrementais é uma boa prática.

</details>
<details>
<summary>queries/models/monitoramento/staging/aux_gps_realocacao.sql (2)</summary>

`19-20`: **Verificar métrica usada no `datetime_diff`**  
O comentário informa que a realocação deve ocorrer após o registro de GPS, mas o cálculo `datetime_diff(datetime_operacao, datetime_entrada, minute)` compara dois campos de realocação. Confirme se a intenção era medir o intervalo entre o timestamp de GPS (`datetime_gps`) e a operação ou se está correto como implementado.

---

`62-66`: **Priorizar registros realocados no `row_number`**  
Atualmente o `ORDER BY` é `datetime_captura DESC, datetime_realocado DESC`. Se o objetivo for sempre preferir o registro com realocação mais recente, avalie inverter para `ORDER BY datetime_realocado DESC, datetime_captura DESC`.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-24T01:14:43Z
user: login: pixuimpou
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-26T20:43:58Z
user: login: eng-rodrigocunha
body: SGTM
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-26T21:06:19Z

Review comments:
diff_hunk: @@ -0,0 +1,109 @@
+{{
+    config(
+        materialized="incremental",
+        partition_by={"field": "data", "data_type": "date", "granularity": "day"},
+        tags=["geolocalizacao"],
+        alias=this.name ~ var("modo_gps") ~ var("fonte_gps"),
+    )
+}}
+
+with
+    registros as (
+        -- 1. registros_filtrada
+        select
+            id_veiculo,
+            datetime_gps,
+            datetime_captura,
+            velocidade,
+            servico,
+            latitude,
+            longitude,
+        from {{ ref("aux_gps_filtrada") }}
+        {% if is_incremental() -%}
+            where
+                data between date("{{var('date_range_start')}}") and date(
+                    "{{var('date_range_end')}}"
+                )
+                and datetime_gps > "{{var('date_range_start')}}"
+                and datetime_gps <= "{{var('date_range_end')}}"
+        {%- endif -%}
+    ),
+    velocidades as (
+        -- 2. velocidades
+        select
+            id_veiculo,
+            datetime_gps,
+            servico,
+            velocidade,
+            distancia,
+            indicador_em_movimento
+        from {{ ref("aux_gps_velocidade") }}
+    ),
+    paradas as (
+        -- 3. paradas
+        select id_veiculo, datetime_gps, servico, tipo_parada,
+        from {{ ref("aux_gps_parada") }}
+    ),
+    indicadores as (
+        -- 4. indicador_trajeto_correto
+        select id_veiculo, datetime_gps, servico, route_id, indicador_trajeto_correto
+        from {{ ref("aux_gps_trajeto_correto") }}
+    )
+-- 5. Junção final
+select
+    date(r.datetime_gps) data,
+    r.datetime_gps,
+    r.id_veiculo,
+    r.servico,
+    r.latitude,
+    r.longitude,
+    case
+        when indicador_em_movimento is true and indicador_trajeto_correto is true
+        then 'Em operação'
+        when indicador_em_movimento is true and indicador_trajeto_correto is false
+        then 'Operando fora trajeto'
+        when indicador_em_movimento is false
+        then
+            case
+                when tipo_parada is not null
+                then concat("Parado ", tipo_parada)
+                else
+                    case
+                        when indicador_trajeto_correto is true
+                        then 'Parado trajeto correto'
+                        else 'Parado fora trajeto'
+                    end
+            end
+    end status,
+    r.velocidade as velocidade_instantanea,
+    v.velocidade as velocidade_estimada_10_min,
+    v.distancia,
+    '{{ var("version") }}' as versao,
+    current_datetime("America/Sao_Paulo") as datetime_ultima_atualizacao
+from registros r
+
+join
+    indicadores i
+    on r.id_veiculo = i.id_veiculo
+    and r.datetime_gps = i.datetime_gps
+    and r.servico = i.servico
+
+join
+    velocidades v
+    on r.id_veiculo = v.id_veiculo
+    and r.datetime_gps = v.datetime_gps
+    and r.servico = v.servico
+
+join
+    paradas p
+    on r.id_veiculo = p.id_veiculo
+    and r.datetime_gps = p.datetime_gps
+    and r.servico = p.servico
+{% if is_incremental() -%}
path: queries/models/monitoramento/gps.sql
user: login: eng-rodrigocunha
body: Utilizar `USING` ao invés de `OR` quando o nome das colunas é o mesmo
created_at: 2024-11-05T17:24:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,19 @@
+{{ config(alias=this.name ~ var("fonte_gps")) }}
+
+select
+    data,
+    safe_cast(
+        datetime(timestamp(datahora), "America/Sao_Paulo") as datetime
+    ) datetime_gps,
+    safe_cast(ordem as string) id_veiculo,
+    concat(
+        ifnull(regexp_extract(linha, r'[A-Z]+'), ""),
+        ifnull(regexp_extract(linha, r'[0-9]+'), "")
+    ) as servico,
+    safe_cast(replace(latitude, ',', '.') as float64) latitude,
+    safe_cast(replace(longitude, ',', '.') as float64) longitude,
+    safe_cast(
+        datetime(timestamp(timestamp_captura), "America/Sao_Paulo") as datetime
+    ) datetime_captura,
+    safe_cast(velocidade as int64) velocidade
+from {{ var("sppo_registros_staging") }}
path: queries/models/monitoramento/staging/aux_gps.sql
user: login: eng-rodrigocunha
body: Alterara para `source` e inserir variável para alterar conforme fonte
created_at: 2024-11-05T17:24:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,54 @@
+{{ config(materialized="ephemeral") }}
+
+with
+    box as (
+        /* 1. Geometria de caixa que contém a área do município de Rio de Janeiro.*/
+        select * from {{ var("limites_caixa") }}
+    ),
+    gps as (
+        /* 2. Filtra registros antigos. Remove registros que tem diferença maior que 1 minuto entre o timestamp_captura e datetime_gps.*/
+        select *, st_geogpoint(longitude, latitude) posicao_veiculo_geo
+        from {{ ref("aux_gps" ~ var("fonte_gps")) }}
+        where
+            data between date("{{var('date_range_start')}}") and date(
+                "{{var('date_range_end')}}"
+            )
+            {% if is_incremental() -%}
+                and datetime_gps > "{{var('date_range_start')}}"
+                and datetime_gps <= "{{var('date_range_end')}}"
+            {%- endif -%}
+    ),
+    realocacao as (
+        select g.* except (servico), coalesce(r.servico_realocado, g.servico) as servico
+        from gps g
+        left join
+            {{ ref("aux_gps_realocacao" ~ var("fonte_gps")) }} r
+            on g.id_veiculo = r.id_veiculo
+            and g.datetime_gps = r.datetime_gps
path: queries/models/monitoramento/staging/aux_gps_filtrada.sql
user: login: eng-rodrigocunha
body: Utilizar `USING` ao invés de `OR` quando o nome das colunas é o mesmo
created_at: 2024-11-05T17:26:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,100 @@
+{{ config(materialized="ephemeral") }}
+
+{% if execute %}
+    {% set feed_start_date = (
+        run_query(
+            "SELECT DISTINCT feed_start_date FROM rj-smtr-dev.rafael__planejamento.calendario WHERE data BETWEEN DATE('"
path: queries/models/monitoramento/staging/aux_gps_parada.sql
user: login: eng-rodrigocunha
body: Posteriormente atualizar ref
created_at: 2024-11-05T17:27:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,100 @@
+{{ config(materialized="ephemeral") }}
+
+{% if execute %}
+    {% set feed_start_date = (
+        run_query(
+            "SELECT DISTINCT feed_start_date FROM rj-smtr-dev.rafael__planejamento.calendario WHERE data BETWEEN DATE('"
+            ~ var("date_range_start")
+            ~ "') AND DATE('"
+            ~ var("date_range_end")
+            ~ "')"
+        )
+        .columns[0]
+        .values()[0]
+    ) %}
+{% endif %}
+
+with
+    terminais as (
+        -- 1. Selecionamos terminais, criando uma geometria de ponto para cada.
+        select
+            st_geogpoint(stop_lon, stop_lat) as ponto_parada,
+            stop_name as nome_parada,
+            'terminal' as tipo_parada
+        -- from {{ ref("stops_gtfs") }}
+        from `rj-smtr`.`gtfs`.`stops`
+        where location_type = "1" and feed_start_date = date("{{ feed_start_date }}")
+    ),
+    garagens as (
+        -- 1. Selecionamos as garagens, , criando uma geometria de ponto para cada.
+        select
+            st_geogpoint(stop_lon, stop_lat) as ponto_parada,
+            stop_name as nome_parada,
+            'garagens' as tipo_parada
+        -- from {{ ref("stops_gtfs") }}
+        from `rj-smtr`.`gtfs`.`stops`
+        left join
+            -- {{ ref("stop_times_gtfs") }} using (feed_version, feed_start_date,
+            -- stop_id)
+            `rj-smtr`.`gtfs`.`stop_times` using (feed_version, feed_start_date, stop_id)
path: queries/models/monitoramento/staging/aux_gps_parada.sql
user: login: eng-rodrigocunha
body: Um mesmo `stop_id` pode ter vários `stop_times`. Avaliar se há duplicação de dados.
created_at: 2024-11-05T17:29:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,100 @@
+{{ config(materialized="ephemeral") }}
+
+{% if execute %}
+    {% set feed_start_date = (
+        run_query(
+            "SELECT DISTINCT feed_start_date FROM rj-smtr-dev.rafael__planejamento.calendario WHERE data BETWEEN DATE('"
+            ~ var("date_range_start")
+            ~ "') AND DATE('"
+            ~ var("date_range_end")
+            ~ "')"
+        )
+        .columns[0]
+        .values()[0]
+    ) %}
+{% endif %}
+
+with
+    terminais as (
+        -- 1. Selecionamos terminais, criando uma geometria de ponto para cada.
+        select
+            st_geogpoint(stop_lon, stop_lat) as ponto_parada,
+            stop_name as nome_parada,
+            'terminal' as tipo_parada
+        -- from {{ ref("stops_gtfs") }}
+        from `rj-smtr`.`gtfs`.`stops`
+        where location_type = "1" and feed_start_date = date("{{ feed_start_date }}")
+    ),
+    garagens as (
+        -- 1. Selecionamos as garagens, , criando uma geometria de ponto para cada.
+        select
+            st_geogpoint(stop_lon, stop_lat) as ponto_parada,
+            stop_name as nome_parada,
+            'garagens' as tipo_parada
+        -- from {{ ref("stops_gtfs") }}
+        from `rj-smtr`.`gtfs`.`stops`
+        left join
+            -- {{ ref("stop_times_gtfs") }} using (feed_version, feed_start_date,
+            -- stop_id)
+            `rj-smtr`.`gtfs`.`stop_times` using (feed_version, feed_start_date, stop_id)
+        where
+            pickup_type is null
+            and drop_off_type is null
+            and stop_name like "Garagem%"
path: queries/models/monitoramento/staging/aux_gps_parada.sql
user: login: eng-rodrigocunha
body: ```suggestion
            and stop_name like "%Garagem%"
```
created_at: 2024-11-05T17:29:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,84 @@
+{{ config(materialized="ephemeral") }}
+
+with
+    registros as (
+        select
+            id_veiculo,
+            servico,
+            latitude,
+            longitude,
+            data,
+            posicao_veiculo_geo,
+            datetime_gps
+        from {{ ref("aux_gps_filtrada") }} r
+        {% if not flags.FULL_REFRESH -%}
+            where
+                data between date("{{var('date_range_start')}}") and date(
+                    "{{var('date_range_end')}}"
+                )
+                and datetime_gps > "{{var('date_range_start')}}"
+                and datetime_gps <= "{{var('date_range_end')}}"
+        {%- endif -%}
+    ),
+    intersec as (
+        select
+            r.*,
+            s.feed_version,
+            s.route_id,
+            -- 1. Histórico de intersecções nos últimos 10 minutos a partir da
+            -- datetime_gps atual
+            case
+                when
+                    count(
+                        case
+                            when
+                                st_dwithin(
+                                    shape,
+                                    posicao_veiculo_geo,
+                                    {{ var("tamanho_buffer_metros") }}
+                                )
path: queries/models/monitoramento/staging/aux_gps_trajeto_correto.sql
user: login: eng-rodrigocunha
body: Alterar para a mesma lógica do Viagens 2.0 (buffer de 20 m)
created_at: 2024-11-05T17:31:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,84 @@
+{{ config(materialized="ephemeral") }}
+
+with
+    registros as (
+        select
+            id_veiculo,
+            servico,
+            latitude,
+            longitude,
+            data,
+            posicao_veiculo_geo,
+            datetime_gps
+        from {{ ref("aux_gps_filtrada") }} r
+        {% if not flags.FULL_REFRESH -%}
+            where
+                data between date("{{var('date_range_start')}}") and date(
+                    "{{var('date_range_end')}}"
+                )
+                and datetime_gps > "{{var('date_range_start')}}"
+                and datetime_gps <= "{{var('date_range_end')}}"
+        {%- endif -%}
+    ),
+    intersec as (
+        select
+            r.*,
+            s.feed_version,
+            s.route_id,
+            -- 1. Histórico de intersecções nos últimos 10 minutos a partir da
+            -- datetime_gps atual
+            case
+                when
+                    count(
+                        case
+                            when
+                                st_dwithin(
+                                    shape,
+                                    posicao_veiculo_geo,
+                                    {{ var("tamanho_buffer_metros") }}
+                                )
+                            then 1
+                        end
+                    ) over (
+                        partition by id_veiculo
+                        order by
+                            unix_seconds(timestamp(datetime_gps))
+                            range
+                            between {{ var("intervalo_max_desvio_segundos") }} preceding
+                            and current row
+                    )
+                    >= 1
+                then true
+                else false
+            end as indicador_trajeto_correto,
+        -- 2. Join com data_versao_efetiva para definição de quais shapes serão
+        -- considerados no cálculo do indicador
+        from registros r
+        left join
+            (
+                select *
+                -- from {{ ref("viagem_planejada") }} --viagem_planejada_planejamento
+                from `rj-smtr-dev`.`rafael__planejamento`.`viagem_planejada`
path: queries/models/monitoramento/staging/aux_gps_trajeto_correto.sql
user: login: eng-rodrigocunha
body: Posteriormente atualizar ref
created_at: 2024-11-05T17:31:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,84 @@
+{{ config(materialized="ephemeral") }}
+
+with
+    registros as (
+        select
+            id_veiculo,
+            servico,
+            latitude,
+            longitude,
+            data,
+            posicao_veiculo_geo,
+            datetime_gps
+        from {{ ref("aux_gps_filtrada") }} r
+        {% if not flags.FULL_REFRESH -%}
+            where
+                data between date("{{var('date_range_start')}}") and date(
+                    "{{var('date_range_end')}}"
+                )
+                and datetime_gps > "{{var('date_range_start')}}"
+                and datetime_gps <= "{{var('date_range_end')}}"
+        {%- endif -%}
+    ),
+    intersec as (
+        select
+            r.*,
+            s.feed_version,
+            s.route_id,
+            -- 1. Histórico de intersecções nos últimos 10 minutos a partir da
+            -- datetime_gps atual
+            case
+                when
+                    count(
+                        case
+                            when
+                                st_dwithin(
+                                    shape,
+                                    posicao_veiculo_geo,
+                                    {{ var("tamanho_buffer_metros") }}
+                                )
+                            then 1
+                        end
+                    ) over (
+                        partition by id_veiculo
+                        order by
+                            unix_seconds(timestamp(datetime_gps))
+                            range
+                            between {{ var("intervalo_max_desvio_segundos") }} preceding
+                            and current row
+                    )
+                    >= 1
+                then true
+                else false
+            end as indicador_trajeto_correto,
+        -- 2. Join com data_versao_efetiva para definição de quais shapes serão
+        -- considerados no cálculo do indicador
+        from registros r
+        left join
+            (
+                select *
+                -- from {{ ref("viagem_planejada") }} --viagem_planejada_planejamento
+                from `rj-smtr-dev`.`rafael__planejamento`.`viagem_planejada`
+                left join
+                    -- {{ ref("shapes_geom_gtfs") }} using (
+                    `rj-smtr`.`gtfs`.`shapes_geom` using (
+                        feed_version, feed_start_date, shape_id
+                    )
+                where
+                    data between date("{{var('date_range_start')}}") and date(
+                        "{{var('date_range_end')}}"
+                    )
+            ) s
+            on r.servico = s.servico
+            and r.data = s.data
path: queries/models/monitoramento/staging/aux_gps_trajeto_correto.sql
user: login: eng-rodrigocunha
body: Utilizar `USING`
created_at: 2024-11-05T17:31:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,82 @@
+{{ config(materialized="ephemeral") }}
+
+with
+    t_velocidade as (
+        select
+            data,
+            id_veiculo,
+            datetime_gps,
+            servico,
+            st_distance(
+                posicao_veiculo_geo,
+                lag(posicao_veiculo_geo) over (
+                    partition by id_veiculo, servico order by datetime_gps
+                )
+            ) distancia,
+            ifnull(
+                safe_divide(
+                    st_distance(
+                        posicao_veiculo_geo,
+                        lag(posicao_veiculo_geo) over (
+                            partition by id_veiculo, servico order by datetime_gps
+                        )
+                    ),
+                    datetime_diff(
+                        datetime_gps,
+                        lag(datetime_gps) over (
+                            partition by id_veiculo, servico order by datetime_gps
+                        ),
+                        second
+                    )
+                ),
+                0
+            )
+            * 3.6 velocidade
+        from {{ ref("aux_gps_filtrada") }}
+        {% if not flags.FULL_REFRESH -%}
+            where
+                data between date("{{var('date_range_start')}}") and date(
+                    "{{var('date_range_end')}}"
+                )
+                and datetime_gps > "{{var('date_range_start')}}"
+                and datetime_gps <= "{{var('date_range_end')}}"
+        {%- endif -%}
+    ),
+    medias as (
+        select
+            data,
+            id_veiculo,
+            datetime_gps,
+            servico,
+            distancia,
+            velocidade,  -- velocidade do pontual
path: queries/models/monitoramento/staging/aux_gps_velocidade.sql
user: login: eng-rodrigocunha
body: velocidade do pontual?
created_at: 2024-11-05T17:32:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,25 @@
+{{ config(alias=this.name ~ var("fonte_gps")) }}
+
+select
+    data,
+    safe_cast(
+        datetime(timestamp(datetime_operacao), "America/Sao_Paulo") as datetime
+    ) datetime_operacao,
+    safe_cast(id_veiculo as string) id_veiculo,
+    concat(
+        ifnull(regexp_extract(servico, r'[A-Z]+'), ""),
+        ifnull(regexp_extract(servico, r'[0-9]+'), "")
+    ) as servico,
+    safe_cast(
+        datetime(timestamp(datetime_entrada), "America/Sao_Paulo") as datetime
+    ) as datetime_entrada,
+    safe_cast(
+        datetime(timestamp(datetime_saida), "America/Sao_Paulo") as datetime
+    ) as datetime_saida,
+    safe_cast(
+        datetime(timestamp(timestamp_processamento), "America/Sao_Paulo") as datetime
+    ) as datetime_processamento,
+    safe_cast(
+        datetime(timestamp(timestamp_captura), "America/Sao_Paulo") as datetime
+    ) as datetime_captura,
+from {{ var("sppo_realocacao_staging") }}
path: queries/models/monitoramento/staging/aux_realocacao.sql
user: login: eng-rodrigocunha
body: Alterar para source e considerar diferentes fontes
created_at: 2024-11-05T17:33:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,82 @@
+{{ config(materialized="ephemeral") }}
+
+with
+    t_velocidade as (
+        select
+            data,
+            id_veiculo,
+            datetime_gps,
+            servico,
+            st_distance(
+                posicao_veiculo_geo,
+                lag(posicao_veiculo_geo) over (
+                    partition by id_veiculo, servico order by datetime_gps
+                )
+            ) distancia,
+            ifnull(
+                safe_divide(
+                    st_distance(
+                        posicao_veiculo_geo,
+                        lag(posicao_veiculo_geo) over (
+                            partition by id_veiculo, servico order by datetime_gps
+                        )
+                    ),
+                    datetime_diff(
+                        datetime_gps,
+                        lag(datetime_gps) over (
+                            partition by id_veiculo, servico order by datetime_gps
+                        ),
+                        second
+                    )
+                ),
+                0
+            )
+            * 3.6 velocidade
+        from {{ ref("aux_gps_filtrada") }}
+        {% if not flags.FULL_REFRESH -%}
+            where
+                data between date("{{var('date_range_start')}}") and date(
+                    "{{var('date_range_end')}}"
+                )
+                and datetime_gps > "{{var('date_range_start')}}"
+                and datetime_gps <= "{{var('date_range_end')}}"
+        {%- endif -%}
+    ),
+    medias as (
+        select
+            data,
+            id_veiculo,
+            datetime_gps,
+            servico,
+            distancia,
+            velocidade,  -- velocidade do pontual
path: queries/models/monitoramento/staging/aux_gps_velocidade.sql
user: login: akaBotelho
body: Comentário do modelo antigo
created_at: 2024-11-05T17:55:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,19 @@
+{{ config(alias=this.name ~ var("fonte_gps")) }}
+
+select
+    data,
+    safe_cast(
+        datetime(timestamp(datahora), "America/Sao_Paulo") as datetime
+    ) datetime_gps,
+    safe_cast(ordem as string) id_veiculo,
+    concat(
+        ifnull(regexp_extract(linha, r'[A-Z]+'), ""),
+        ifnull(regexp_extract(linha, r'[0-9]+'), "")
+    ) as servico,
+    safe_cast(replace(latitude, ',', '.') as float64) latitude,
+    safe_cast(replace(longitude, ',', '.') as float64) longitude,
+    safe_cast(
+        datetime(timestamp(timestamp_captura), "America/Sao_Paulo") as datetime
+    ) datetime_captura,
+    safe_cast(velocidade as int64) velocidade
+from {{ source('br_rj_riodejaneiro_onibus_gps_' ~ var("fonte_gps") ~ '_staging', "registros") }}
path: queries/models/monitoramento/staging/aux_gps.sql
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Verificar valor padrão de `var("fonte_gps")`**  
Se `fonte_gps` estiver vazio, a fonte dinâmica vira `br_rj_riodejaneiro_onibus_gps__staging`, causando erros de compilação. Use um valor padrão ou force a definição de `fonte_gps` via variáveis de ambiente para evitar caminhos inválidos.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-06T16:59:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,101 @@
+{{
+    config(
+        materialized="incremental",
+        partition_by={"field": "data", "data_type": "date", "granularity": "day"},
+        tags=["geolocalizacao"],
+        alias=this.name ~ var("modo_gps") ~ var("fonte_gps"),
+    )
+}}
+
+with
+    registros as (
+        -- 1. registros_filtrada
+        select
+            id_veiculo,
+            datetime_gps,
+            datetime_captura,
+            velocidade,
+            servico,
+            latitude,
+            longitude,
+        from {{ ref("aux_gps_filtrada") }}
+        {% if is_incremental() -%}
+            where
+                data between date("{{var('date_range_start')}}") and date(
+                    "{{var('date_range_end')}}"
+                )
+                and datetime_gps > "{{var('date_range_start')}}"
+                and datetime_gps <= "{{var('date_range_end')}}"
+        {%- endif -%}
+    ),
+    velocidades as (
+        -- 2. velocidades
+        select
+            id_veiculo,
+            datetime_gps,
+            servico,
+            velocidade,
+            distancia,
+            indicador_em_movimento
+        from {{ ref("aux_gps_velocidade") }}
+    ),
+    paradas as (
+        -- 3. paradas
+        select id_veiculo, datetime_gps, servico, tipo_parada,
+        from {{ ref("aux_gps_parada") }}
+    ),
+    indicadores as (
+        -- 4. indicador_trajeto_correto
+        select id_veiculo, datetime_gps, servico, route_id, indicador_trajeto_correto
+        from {{ ref("aux_gps_trajeto_correto") }}
+    )
+-- 5. Junção final
+select
+    date(r.datetime_gps) data,
+    r.datetime_gps,
+    r.id_veiculo,
+    r.servico,
+    r.latitude,
+    r.longitude,
+    case
+        when indicador_em_movimento is true and indicador_trajeto_correto is true
+        then 'Em operação'
+        when indicador_em_movimento is true and indicador_trajeto_correto is false
+        then 'Operando fora trajeto'
+        when indicador_em_movimento is false
+        then
+            case
+                when tipo_parada is not null
+                then concat("Parado ", tipo_parada)
+                else
path: queries/models/monitoramento/gps.sql
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Uso incorreto de aspas duplas em literais de string**  
Funções SQL obrigam literais entre aspas simples. Substitua `concat("Parado ", tipo_parada)` por `concat('Parado ', tipo_parada)` e `current_datetime("America/Sao_Paulo")` por `current_datetime('America/Sao_Paulo')`.  



Also applies to: 82-82

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-06T16:59:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,101 @@
+{{
+    config(
+        materialized="incremental",
+        partition_by={"field": "data", "data_type": "date", "granularity": "day"},
+        tags=["geolocalizacao"],
+        alias=this.name ~ var("modo_gps") ~ var("fonte_gps"),
+    )
+}}
+
+with
+    registros as (
+        -- 1. registros_filtrada
+        select
+            id_veiculo,
+            datetime_gps,
+            datetime_captura,
+            velocidade,
+            servico,
+            latitude,
+            longitude,
+        from {{ ref("aux_gps_filtrada") }}
+        {% if is_incremental() -%}
+            where
+                data between date("{{var('date_range_start')}}") and date(
+                    "{{var('date_range_end')}}"
+                )
+                and datetime_gps > "{{var('date_range_start')}}"
+                and datetime_gps <= "{{var('date_range_end')}}"
+        {%- endif -%}
+    ),
+    velocidades as (
+        -- 2. velocidades
+        select
+            id_veiculo,
+            datetime_gps,
+            servico,
+            velocidade,
+            distancia,
+            indicador_em_movimento
+        from {{ ref("aux_gps_velocidade") }}
+    ),
+    paradas as (
+        -- 3. paradas
+        select id_veiculo, datetime_gps, servico, tipo_parada,
+        from {{ ref("aux_gps_parada") }}
+    ),
path: queries/models/monitoramento/gps.sql
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Erro de sintaxe: vírgula a mais na cláusula SELECT**  
Na CTE `paradas`, há uma vírgula após `tipo_parada` antes do `FROM`, o que resultará em erro de parsing. Remova a vírgula extra para corrigir.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-06T16:59:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,53 @@
+{{ config(materialized="ephemeral") }}
+
+with
+    box as (
+        /* 1. Geometria de caixa que contém a área do município de Rio de Janeiro.*/
+        select * from {{ var("limites_caixa") }}
+    ),
+    gps as (
+        /* 2. Filtra registros antigos. Remove registros que tem diferença maior que 1 minuto entre o timestamp_captura e datetime_gps.*/
+        select *, st_geogpoint(longitude, latitude) posicao_veiculo_geo
+        from {{ ref("aux_gps" ~ var("fonte_gps")) }}
+        where
+            data between date("{{var('date_range_start')}}") and date(
+                "{{var('date_range_end')}}"
+            )
+            {% if is_incremental() -%}
+                and datetime_gps > "{{var('date_range_start')}}"
+                and datetime_gps <= "{{var('date_range_end')}}"
+            {%- endif -%}
+    ),
+    realocacao as (
+        select g.* except (servico), coalesce(r.servico_realocado, g.servico) as servico
+        from gps g
+        left join
+            {{ ref("aux_gps_realocacao" ~ var("fonte_gps")) }} r
+            using(id_veiculo, datetime_gps)
+    ),
+    filtrada as (
+        /* 1,2, e 3. Muda o nome de variáveis para o padrão do projeto.*/
+        select
+            data,
+            datetime_gps,
+            id_veiculo,
+            servico,
+            latitude,
+            longitude,
+            posicao_veiculo_geo,
+            datetime_captura,
+            velocidade,
+            row_number() over (partition by id_veiculo, datetime_gps, servico) rn
+        from realocacao
+        where
+            st_intersectsbox(
+                posicao_veiculo_geo,
+                (select min_longitude from box),
+                (select min_latitude from box),
+                (select max_longitude from box),
+                (select max_latitude from box)
+            )
+    )
+select * except (rn), "{{ var('version') }}" as versao
+from filtrada
path: queries/models/monitoramento/staging/aux_gps_filtrada.sql
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Uso incorreto de aspas em literais no SELECT final**  
O trecho ` "{{ var('version') }}" as versao` gerará aspas duplas no SQL resultante. Utilize aspas simples:  
```sql
'{{ var("version") }}' AS versao
```

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-06T16:59:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,53 @@
+{{ config(materialized="ephemeral") }}
+
+with
+    box as (
+        /* 1. Geometria de caixa que contém a área do município de Rio de Janeiro.*/
+        select * from {{ var("limites_caixa") }}
+    ),
+    gps as (
+        /* 2. Filtra registros antigos. Remove registros que tem diferença maior que 1 minuto entre o timestamp_captura e datetime_gps.*/
+        select *, st_geogpoint(longitude, latitude) posicao_veiculo_geo
+        from {{ ref("aux_gps" ~ var("fonte_gps")) }}
+        where
+            data between date("{{var('date_range_start')}}") and date(
+                "{{var('date_range_end')}}"
+            )
+            {% if is_incremental() -%}
+                and datetime_gps > "{{var('date_range_start')}}"
+                and datetime_gps <= "{{var('date_range_end')}}"
path: queries/models/monitoramento/staging/aux_gps_filtrada.sql
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Lógica faltante para filtrar diferença de timestamp**  
O comentário indica remover registros com diferença maior que 1 minuto entre `timestamp_captura` e `datetime_gps`, mas não há nenhum `WHERE TIMESTAMP_DIFF(...)` implementado. Adicione esse filtro conforme especificado.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-06T16:59:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,82 @@
+{{ config(materialized="ephemeral") }}
+
+with
+    t_velocidade as (
+        select
+            data,
+            id_veiculo,
+            datetime_gps,
+            servico,
+            st_distance(
+                posicao_veiculo_geo,
+                lag(posicao_veiculo_geo) over (
+                    partition by id_veiculo, servico order by datetime_gps
+                )
+            ) distancia,
+            ifnull(
+                safe_divide(
+                    st_distance(
+                        posicao_veiculo_geo,
+                        lag(posicao_veiculo_geo) over (
+                            partition by id_veiculo, servico order by datetime_gps
+                        )
+                    ),
+                    datetime_diff(
+                        datetime_gps,
+                        lag(datetime_gps) over (
+                            partition by id_veiculo, servico order by datetime_gps
+                        ),
+                        second
+                    )
+                ),
+                0
+            )
+            * 3.6 velocidade
+        from {{ ref("aux_gps_filtrada") }}
+        {% if not flags.FULL_REFRESH -%}
+            where
+                data between date("{{var('date_range_start')}}") and date(
+                    "{{var('date_range_end')}}"
+                )
+                and datetime_gps > "{{var('date_range_start')}}"
+                and datetime_gps <= "{{var('date_range_end')}}"
+        {%- endif -%}
+    ),
+    medias as (
+        select
+            data,
+            id_veiculo,
+            datetime_gps,
+            servico,
+            distancia,
+            velocidade,
+            avg(velocidade) over (
+                partition by id_veiculo, servico
+                order by
+                    unix_seconds(timestamp(datetime_gps))
+                    range
+                    between {{ var("janela_movel_velocidade") }} preceding
+                    and current row
+            ) velocidade_media  -- velocidade com média móvel
+        from t_velocidade
+    )
+select
+    data,
+    datetime_gps,
+    id_veiculo,
+    servico,
+    distancia,
+    round(
+        case
+            when velocidade_media > {{ var("velocidade_maxima") }}
+            then {{ var("velocidade_maxima") }}
+            else velocidade_media
+        end,
+        1
+    ) as velocidade,
+    case
+        when velocidade_media < {{ var("velocidade_limiar_parado") }}
+        then false
+        else true
+    end indicador_em_movimento,
+from medias
path: queries/models/monitoramento/staging/aux_gps_velocidade.sql
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Erro de sintaxe: vírgula extra antes do `FROM`**  
Após o `END indicador_em_movimento` existe uma vírgula antes do `FROM medias`, o que causará falha de parsing. Remova essa vírgula.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-06T16:59:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,70 @@
+{% if var("fifteen_minutes") == "_15_minutos" %}
+    {{ config(materialized="ephemeral", alias=this.name ~ var("fonte_gps")) }}  -- verificar isso
+{% else %}
+    {{
+        config(
+            materialized="incremental",
+            partition_by={"field": "data", "data_type": "date", "granularity": "day"},
+            alias=this.name ~ var("fonte_gps"),
+        )
+    }}
+{% endif %}
+
+-- 1. Filtra realocações válidas dentro do intervalo de GPS avaliado
+with
+    realocacao as (
+        select
+            * except (datetime_saida),
+            case
+                when datetime_saida is null then datetime_operacao else datetime_saida
+            end as datetime_saida,
+        from {{ ref("aux_realocacao" ~ var("fonte_gps")) }}
+        where
+            -- Realocação deve acontecer após o registro de GPS e até 1 hora depois
+            datetime_diff(datetime_operacao, datetime_entrada, minute) between 0 and 60
+            and data between date("{{var('date_range_start')}}") and date(
+                datetime_add("{{var('date_range_end')}}", interval 1 hour)
+            )
+            and (
+                datetime_saida >= datetime("{{var('date_range_start')}}")
+                or datetime_operacao >= datetime("{{var('date_range_start')}}")
+            )
+    ),
+    -- 2. Altera registros de GPS com servicos realocados
+    gps as (
+        select id_veiculo, datetime_gps, servico, data,
+        from {{ ref("aux_gps" ~ var("fonte_gps")) }}
path: queries/models/monitoramento/staging/aux_gps_realocacao.sql
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Erro de sintaxe: vírgula extra no SELECT**  
Na CTE `gps`, o `SELECT id_veiculo, datetime_gps, servico, data,` contém uma vírgula após `data` antes do `FROM`, gerando erro de parsing. Remova essa vírgula final.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-06T16:59:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -251,4 +251,19 @@ selectors:
   - name: snapshot_transito
     definition:
       method: fqn
-      value: snapshot_transito_autuacao
\ No newline at end of file
+      value: snapshot_transito_autuacao
+
+  - name: gps
+    description: Materialização das tabelas de gps
+    definition:
+      union:
+        - method: fqn
+          value: aux_gps
+        - method: fqn
+          value: aux_gps_realocacao
+        - method: fqn
+          value: aux_realocacao
+        - method: fqn
+          value: staging_garagens
+        - method: fqn
+          value: gps
path: queries/selectors.yml
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Omissão do modelo `gps_15_minutos` no selector `gps`**  
Embora a pipeline GPS inclua o modelo incremental `gps_15_minutos`, ele não está listado no selector `gps`, deixando a materialização incompleta.  
  
Sugestão de diff:
```diff
   - method: fqn
     value: gps
+  - method: fqn
+    value: gps_15_minutos
```

---

_⚠️ Potential issue_

**Inconsistência de nome do modelo `staging_garagens`**  
O selector referencia `staging_garagens`, mas o modelo está configurado com `alias="garagens"` (em `staging_garagens.sql`). Isso impedirá a resolução correta do FQN.  
  
Proposta de correção:
```diff
  - method: fqn
-    value: staging_garagens
+    value: garagens
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
  - name: gps
    description: Materialização das tabelas de gps
    definition:
      union:
        - method: fqn
          value: aux_gps
        - method: fqn
          value: aux_gps_realocacao
        - method: fqn
          value: aux_realocacao
        - method: fqn
          value: garagens
        - method: fqn
          value: gps
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-08T22:23:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,97 @@
+{{
+    config(
+        materialized="incremental",
+        partition_by={"field": "data", "data_type": "date", "granularity": "day"},
+        tags=["geolocalizacao"],
+        alias=this.name ~ "_" ~ var("modo_gps") ~ "_" ~ var("fonte_gps"),
+    )
+}}
+
+with
+    registros as (
+        -- 1. registros_filtrada
+        select
+            id_veiculo,
+            datetime_gps,
+            datetime_captura,
+            velocidade,
+            servico,
+            latitude,
+            longitude,
+        from {{ ref("aux_gps_filtrada") }}
+        {% if is_incremental() -%}
+            where
+                data between date("{{var('date_range_start')}}") and date(
+                    "{{var('date_range_end')}}"
+                )
+                and datetime_gps
+                > datetime_sub("{{var('date_range_end')}}", interval 75 minute)
+                and datetime_gps <= "{{var('date_range_end')}}"
+        {%- endif -%}
+    ),
+    velocidades as (
+        -- 2. velocidades
+        select
+            id_veiculo,
+            datetime_gps,
+            servico,
+            velocidade,
+            distancia,
+            indicador_em_movimento
+        from {{ ref("aux_gps_velocidade") }}
+    ),
path: queries/models/monitoramento/gps_15_minutos.sql
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Filtragem incremental não aplicada nas CTEs auxiliares**  
As CTEs `velocidades`, `paradas` e `indicadores` fazem varreduras completas em cada execução, impactando performance. Recomenda-se adicionar filtros condicionais com `is_incremental()` para restringir ao intervalo de datas:

```diff
velocidades as (
    select … 
    from {{ ref("aux_gps_velocidade") }}
+   {% if is_incremental() -%}
+       where date(datetime_gps) between date('{{ var("date_range_start") }}') and date('{{ var("date_range_end") }}')
+   {% endif %}
),
paradas as (
    select … 
    from {{ ref("aux_gps_parada") }}
+   {% if is_incremental() -%}
+       where date(datetime_gps) between date('{{ var("date_range_start") }}') and date('{{ var("date_range_end") }}')
+   {% endif %}
),
indicadores as (
    select … 
    from {{ ref("aux_gps_trajeto_correto") }}
+   {% if is_incremental() -%}
+       where date(datetime_gps) between date('{{ var("date_range_start") }}') and date('{{ var("date_range_end") }}')
+   {% endif %}
)
```
Replique o padrão em todas as CTEs para otimizar o tempo de execução incremental.  


Also applies to: 43-47, 48-52

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-08T22:23:14Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,97 @@
+{{
+    config(
+        materialized="incremental",
+        partition_by={"field": "data", "data_type": "date", "granularity": "day"},
+        tags=["geolocalizacao"],
+        alias=this.name ~ "_" ~ var("modo_gps") ~ "_" ~ var("fonte_gps"),
+    )
+}}
+
+with
+    registros as (
+        -- 1. registros_filtrada
+        select
+            id_veiculo,
+            datetime_gps,
+            datetime_captura,
+            velocidade,
+            servico,
+            latitude,
+            longitude,
+        from {{ ref("aux_gps_filtrada") }}
+        {% if is_incremental() -%}
+            where
+                data between date("{{var('date_range_start')}}") and date(
+                    "{{var('date_range_end')}}"
+                )
+                and datetime_gps
+                > datetime_sub("{{var('date_range_end')}}", interval 75 minute)
+                and datetime_gps <= "{{var('date_range_end')}}"
+        {%- endif -%}
+    ),
+    velocidades as (
+        -- 2. velocidades
+        select
+            id_veiculo,
+            datetime_gps,
+            servico,
+            velocidade,
+            distancia,
+            indicador_em_movimento
+        from {{ ref("aux_gps_velocidade") }}
+    ),
+    paradas as (
+        -- 3. paradas
+        select id_veiculo, datetime_gps, servico, tipo_parada
+        from {{ ref("aux_gps_parada") }}
+    ),
+    indicadores as (
+        -- 4. indicador_trajeto_correto
+        select id_veiculo, datetime_gps, servico, route_id, indicador_trajeto_correto
+        from {{ ref("aux_gps_trajeto_correto") }}
+    )
+-- 5. Junção final
+select
+    date(r.datetime_gps) data,
+    r.datetime_gps,
+    r.id_veiculo,
+    r.servico,
+    r.latitude,
+    r.longitude,
+    case
+        when indicador_em_movimento is true and indicador_trajeto_correto is true
+        then 'Em operação'
+        when indicador_em_movimento is true and indicador_trajeto_correto is false
+        then 'Operando fora trajeto'
+        when indicador_em_movimento is false
+        then
+            case
+                when tipo_parada is not null
+                then concat("Parado ", tipo_parada)
+                else
+                    case
+                        when indicador_trajeto_correto is true
+                        then 'Parado trajeto correto'
+                        else 'Parado fora trajeto'
+                    end
+            end
+    end status,
+    r.velocidade as velocidade_instantanea,
+    v.velocidade as velocidade_estimada_10_min,
+    v.distancia,
+    '{{ var("version") }}' as versao,
+    current_datetime("America/Sao_Paulo") as datetime_ultima_atualizacao
+from registros r
+
+join indicadores i using (id_veiculo, datetime_gps, servico)
+join velocidades v using (id_veiculo, datetime_gps, servico)
+join paradas p using (id_veiculo, datetime_gps, servico)
+{% if is_incremental() -%}
+    where
+        date(r.datetime_gps) between date("{{var('date_range_start')}}") and date(
+            "{{var('date_range_end')}}"
+        )
+        and r.datetime_gps
+        > datetime_sub("{{var('date_range_end')}}", interval 75 minute)
+        and r.datetime_gps <= "{{var('date_range_end')}}"
+{%- endif -%}
path: queries/models/monitoramento/gps_15_minutos.sql
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Consistência de aspas no filtro incremental final**  
Aplica-se o mesmo ajuste de aspas simples na cláusula incremental do `where` inferior para evitar quebra de compilação.  
  
Exemplo de diff:
```diff
-{% if is_incremental() -%}
-    where
-        date(r.datetime_gps) between date("{{ var('date_range_start') }}") and date("{{ var('date_range_end') }}")
+{% if is_incremental() -%}
+    where
+        date(r.datetime_gps) between date('{{ var("date_range_start") }}') and date('{{ var("date_range_end") }}')
```


> Committable suggestion skipped: line range outside the PR's diff.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-08T22:23:14Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,97 @@
+{{
+    config(
+        materialized="incremental",
+        partition_by={"field": "data", "data_type": "date", "granularity": "day"},
+        tags=["geolocalizacao"],
+        alias=this.name ~ "_" ~ var("modo_gps") ~ "_" ~ var("fonte_gps"),
+    )
+}}
+
+with
+    registros as (
+        -- 1. registros_filtrada
+        select
+            id_veiculo,
+            datetime_gps,
+            datetime_captura,
+            velocidade,
+            servico,
+            latitude,
+            longitude,
+        from {{ ref("aux_gps_filtrada") }}
+        {% if is_incremental() -%}
+            where
+                data between date("{{var('date_range_start')}}") and date(
+                    "{{var('date_range_end')}}"
+                )
+                and datetime_gps
+                > datetime_sub("{{var('date_range_end')}}", interval 75 minute)
+                and datetime_gps <= "{{var('date_range_end')}}"
+        {%- endif -%}
path: queries/models/monitoramento/gps_15_minutos.sql
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Erro de aspas em literais de data**  
BigQuery exige aspas simples em literais de data. Usar `date('YYYY-MM-DD')` em vez de `date("YYYY-MM-DD")`.  
  
Proposta de correção:
```diff
-{% if is_incremental() -%}
-    where
-        data between date("{{ var('date_range_start') }}") and date("{{ var('date_range_end') }}")
+{% if is_incremental() -%}
+    where
+        date(data) between date('{{ var("date_range_start") }}') and date('{{ var("date_range_end") }}')
```

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-08T22:23:14Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,101 @@
+version: 2
+
+models:
+  - name: aux_gps
+    description: "Tabela com todos os registros de GPS da API {{ var('fonte_gps') }}"
+    columns:
+      - name: data
+        description: "{{ doc('data_captura') }}"
+      - name: hora
+        description: "{{ doc('hora_captura') }}"
+      - name: datetime_gps
+        description: "{{ doc('timestamp_gps') }}"
+      - name: id_veiculo
+        description: "{{ doc('id_veiculo') }}"
+      - name: servico
+        description: "{{ doc('servico') }}"
+      - name: sentido
+        description: "{{ doc('sentido') }}"
+      - name: latitude
+        description: "{{ doc('latitude_gps') }}"
+      - name: longitude
+        description: "{{ doc('longitude_gps') }}"
+      - name: velocidade
+        description: "{{ doc('velocidade_instantanea') }}"
+      - name: direcao
+        description: "{{ doc('direcao_gps') }}"
+      - name: route_id
+        description: "{{ doc('route_id') }}"
+      - name: trip_id
+        description: "{{ doc('trip_id') }}"
+      - name: shape_id
+        description: "{{ doc('shape_id') }}"
+      - name: datetime_envio
+        description: "{{ doc('datetime_envio_gps') }}"
+      - name: datetime_servidor
+        description: "{{ doc('datetime_servidor_gps') }}"
+      - name: datetime_captura
+        description: "{{ doc('datetime_captura') }}"
+  - name: aux_realocacao
+    description: "Tabela com todas as realocações de linha informadas pela API {{ var('fonte_gps') }}"
+    columns:
+      - name: data
+        description: "{{ doc('data_captura') }}"
+      - name: hora
+        description: "{{ doc('hora_captura') }}"
+      - name: datetime_operacao
+        description: "{{ doc('datetime_operacao') }}"
+      - name: id_veiculo
+        description: "{{ doc('id_veiculo') }}"
+      - name: servico
+        description: "{{ doc('servico_realocacao') }}"
+      - name: datetime_entrada
+        description: "{{ doc('datetime_entrada') }}"
+      - name: datetime_saida
+        description: "{{ doc('datetime_saida') }}"
+      - name: datetime_processamento
+        description: "{{ doc('datetime_processamento') }}"
+      - name: datetime_captura
+        description: "{{ doc('datetime_captura') }}"
+
path: queries/models/monitoramento/staging/schema.yml
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Adicionar testes de qualidade de dados em `aux_realocacao`**  
Sugiro definir testes para:
- `not_null` em `datetime_operacao`, `id_veiculo`  
- `unique` para a chave natural de realocação (ex.: `id_veiculo` + `datetime_entrada`)  

Assim reforçamos a confiabilidade das realocações importadas.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-13T22:18:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,101 @@
+version: 2
+
+models:
+  - name: aux_gps
+    description: "Tabela com todos os registros de GPS da API {{ var('fonte_gps') }}"
+    columns:
+      - name: data
+        description: "{{ doc('data_captura') }}"
+      - name: hora
+        description: "{{ doc('hora_captura') }}"
+      - name: datetime_gps
+        description: "{{ doc('timestamp_gps') }}"
+      - name: id_veiculo
+        description: "{{ doc('id_veiculo') }}"
+      - name: servico
+        description: "{{ doc('servico') }}"
+      - name: sentido
+        description: "{{ doc('sentido') }}"
+      - name: latitude
+        description: "{{ doc('latitude_gps') }}"
+      - name: longitude
+        description: "{{ doc('longitude_gps') }}"
+      - name: velocidade
+        description: "{{ doc('velocidade_instantanea') }}"
+      - name: direcao
+        description: "{{ doc('direcao_gps') }}"
+      - name: route_id
+        description: "{{ doc('route_id') }}"
+      - name: trip_id
+        description: "{{ doc('trip_id') }}"
+      - name: shape_id
+        description: "{{ doc('shape_id') }}"
+      - name: datetime_envio
+        description: "{{ doc('datetime_envio_gps') }}"
+      - name: datetime_servidor
+        description: "{{ doc('datetime_servidor_gps') }}"
+      - name: datetime_captura
+        description: "{{ doc('datetime_captura') }}"
path: queries/models/monitoramento/staging/schema.yml
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Adicionar testes de qualidade de dados em `aux_gps`**  
Recomendo incluir testes (`tests:`) para garantir integridade, como:
- `not_null` em colunas críticas (ex.: `datetime_gps`, `id_veiculo`)  
- `unique` em chaves naturais (ex.: combinação de `id_veiculo` + `datetime_gps`)  

Isso ajuda a detectar entradas duplicadas ou nulas no estágio de GPS.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-13T22:18:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,101 @@
+version: 2
+
+models:
+  - name: aux_gps
+    description: "Tabela com todos os registros de GPS da API {{ var('fonte_gps') }}"
+    columns:
+      - name: data
+        description: "{{ doc('data_captura') }}"
+      - name: hora
+        description: "{{ doc('hora_captura') }}"
+      - name: datetime_gps
+        description: "{{ doc('timestamp_gps') }}"
+      - name: id_veiculo
+        description: "{{ doc('id_veiculo') }}"
+      - name: servico
+        description: "{{ doc('servico') }}"
+      - name: sentido
+        description: "{{ doc('sentido') }}"
+      - name: latitude
+        description: "{{ doc('latitude_gps') }}"
+      - name: longitude
+        description: "{{ doc('longitude_gps') }}"
+      - name: velocidade
+        description: "{{ doc('velocidade_instantanea') }}"
+      - name: direcao
+        description: "{{ doc('direcao_gps') }}"
+      - name: route_id
+        description: "{{ doc('route_id') }}"
+      - name: trip_id
+        description: "{{ doc('trip_id') }}"
+      - name: shape_id
+        description: "{{ doc('shape_id') }}"
+      - name: datetime_envio
+        description: "{{ doc('datetime_envio_gps') }}"
+      - name: datetime_servidor
+        description: "{{ doc('datetime_servidor_gps') }}"
+      - name: datetime_captura
+        description: "{{ doc('datetime_captura') }}"
+  - name: aux_realocacao
+    description: "Tabela com todas as realocações de linha informadas pela API {{ var('fonte_gps') }}"
+    columns:
+      - name: data
+        description: "{{ doc('data_captura') }}"
+      - name: hora
+        description: "{{ doc('hora_captura') }}"
+      - name: datetime_operacao
+        description: "{{ doc('datetime_operacao') }}"
+      - name: id_veiculo
+        description: "{{ doc('id_veiculo') }}"
+      - name: servico
+        description: "{{ doc('servico_realocacao') }}"
+      - name: datetime_entrada
+        description: "{{ doc('datetime_entrada') }}"
+      - name: datetime_saida
+        description: "{{ doc('datetime_saida') }}"
+      - name: datetime_processamento
+        description: "{{ doc('datetime_processamento') }}"
+      - name: datetime_captura
+        description: "{{ doc('datetime_captura') }}"
+
+  - name: aux_gps_realocacao
+    description: "Tabela com realocações de linha válidas da API {{ var('fonte_gps') }}"
+    columns:
+      - name: data
+        description: "{{ doc('data_captura') }}"
+      - name: hora
+        description: "{{ doc('hora_captura') }}"
+      - name: datetime_gps
+        description: "{{ doc('timestamp_gps') }}"
+      - name: id_veiculo
+        description: "{{ doc('id_veiculo') }}"
+      - name: servico_gps
+        description: "{{ doc('servico_gps') }}"
+      - name: servico_realocado
+        description: "{{ doc('servico_realocacao') }}"
+      - name: datetime_realocado
+        description: "{{ doc('datetime_realocacao') }}"
+
path: queries/models/monitoramento/staging/schema.yml
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Adicionar testes de qualidade de dados em `aux_gps_realocacao`**  
Para `aux_gps_realocacao`, inclua:
- `not_null` em `datetime_gps`, `datetime_realocado`  
- `unique` na combinação `id_veiculo` + `datetime_realocado`  

Esses testes validam a correlação GPS ↔ realocação.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-13T22:18:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -285,3 +285,63 @@ models:
         description: "{{ doc('datetime_ultima_atualizacao') }}"
         data_type: datetime
         quote: true
+
+  - name: gps
+    description: "Tabela com os dados tratados de registros de GPS da API {{ var('fonte_gps') }}, incluindo velocidade estimada, estado de movimento, parada em terminal ou garagem e interseção com o traçado da linha informada"
+    columns:
+      - name: data
+        description: "{{ doc('data_gps') }}"
+      - name: hora
+        description: "{{ doc('hora_gps') }}"
+      - name: datetime_gps
+        description: "{{ doc('timestamp_gps') }}"
+      - name: id_veiculo
+        description: "{{ doc('id_veiculo') }}"
+      - name: servico
+        description: "{{ doc('servico') }}"
+      - name: latitude
+        description: "{{ doc('latitude_gps') }}"
+      - name: longitude
+        description: "{{ doc('longitude_gps') }}"
+      - name: status
+        description: "{{ doc('status_veiculo_gps') }}"
+      - name: velocidade_instantanea
+        description: "{{ doc('velocidade_instantanea') }}"
+      - name: velocidade_estimada_10_min
+        description: "{{ doc('velocidade_estimada_10_min') }}"
+      - name: distancia
+        description: "{{ doc('distancia_gps') }}"
+      - name: versao
+        description: "{{ doc('versao') }}"
+      - name: datetime_ultima_atualizacao
+        description: "{{ doc('datetime_ultima_atualizacao') }}"
+
path: queries/models/monitoramento/schema.yml
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Colunas do modelo `gps` sem tipo de dados e citação ausentes**  
No bloco do modelo `gps`, todas as colunas definidas possuem apenas `name` e `description`. Para manter consistência com os demais modelos, é necessário incluir os campos `data_type` e `quote` em cada coluna.  
  
Segue exemplo de diff para a única coluna de data; aplique o mesmo padrão para todas as demais colunas:

```diff
--- a/queries/models/monitoramento/schema.yml
+++ b/queries/models/monitoramento/schema.yml
@@ -292,6 +292,9 @@
       - name: data
         description: "{{ doc('data_gps') }}"
+        data_type: date
+        quote: true
       - name: hora
         description: "{{ doc('hora_gps') }}"
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
  - name: gps
    description: "Tabela com os dados tratados de registros de GPS da API {{ var('fonte_gps') }}, incluindo velocidade estimada, estado de movimento, parada em terminal ou garagem e interseção com o traçado da linha informada"
    columns:
      - name: data
        description: "{{ doc('data_gps') }}"
        data_type: date
        quote: true
      - name: hora
        description: "{{ doc('hora_gps') }}"
      - name: datetime_gps
        description: "{{ doc('timestamp_gps') }}"
      - name: id_veiculo
        description: "{{ doc('id_veiculo') }}"
      - name: servico
        description: "{{ doc('servico') }}"
      - name: latitude
        description: "{{ doc('latitude_gps') }}"
      - name: longitude
        description: "{{ doc('longitude_gps') }}"
      - name: status
        description: "{{ doc('status_veiculo_gps') }}"
      - name: velocidade_instantanea
        description: "{{ doc('velocidade_instantanea') }}"
      - name: velocidade_estimada_10_min
        description: "{{ doc('velocidade_estimada_10_min') }}"
      - name: distancia
        description: "{{ doc('distancia_gps') }}"
      - name: versao
        description: "{{ doc('versao') }}"
      - name: datetime_ultima_atualizacao
        description: "{{ doc('datetime_ultima_atualizacao') }}"
```

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-13T22:18:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,52 @@
+{{
+    config(
+        alias="garagens",
+    )
+}}
+
+with
+    garagens as (
+        select
+            data as inicio_vigencia,
+            nullif(trim(safe_cast(operador as string)), "") as operador,
+            nullif(trim(safe_cast(endereco as string)), "") as endereco,
+            nullif(trim(safe_cast(bairro as string)), "") as bairro,
+            case
+                when safe_cast(oficial as string) = "SIM"
+                then true
+                when safe_cast(oficial as string) = "NÃO"
+                then false
+                else null
+            end as oficial,
path: queries/models/monitoramento/staging/staging_garagens.sql
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Padronize comparações de texto antes de avaliar booleanos**  
Ao comparar `safe_cast(oficial as string) = "SIM"/"NÃO"`, aplique `trim()` e `upper()` para lidar com espaços e variações de caixa, ex.:  
```sql
case
  when upper(trim(safe_cast(oficial as string))) = "SIM" then true
  ...
end
```

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In queries/models/monitoramento/staging/staging_garagens.sql around lines 14 to
20, the text comparisons for "SIM" and "NÃO" should be standardized by applying
trim() and upper() functions to the safe_cast(oficial as string) expression.
Update the case statement to use upper(trim(safe_cast(oficial as string))) for
comparisons to handle extra spaces and case variations consistently.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-19T17:29:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+{{ config(alias=this.name ~ "_" ~ var("fonte_gps")) }}
+
+with
+    source_data as (
+        select
+            data,
+            safe_cast(hora as int64) hora,
+            safe_cast(
+                datetime(
+                    timestamp(safe_cast(json_value(content, '$.datetime') as string)),
+                    "America/Sao_Paulo"
+                ) as datetime
+            ) datetime_gps,
+            safe_cast(id_veiculo as string) id_veiculo,
+            concat(
+                ifnull(
+                    regexp_extract(
+                        safe_cast(json_value(content, '$.servico') as string), r'[A-Z]+'
+                    ),
+                    ""
+                ),
+                ifnull(
+                    regexp_extract(
+                        safe_cast(json_value(content, '$.servico') as string), r'[0-9]+'
+                    ),
+                    ""
+                )
+            ) as servico,
+            safe_cast(json_value(content, '$.sentido') as string) sentido,
+            safe_cast(
+                replace(json_value(content, '$.latitude'), ',', '.') as float64
+            ) latitude,
+            safe_cast(
+                replace(json_value(content, '$.longitude'), ',', '.') as float64
+            ) longitude,
+            safe_cast(json_value(content, '$.velocidade') as int64) velocidade,
+            safe_cast(json_value(content, '$.direcao') as numeric) direcao,
+            safe_cast(json_value(content, '$.route_id') as string) route_id,
+            safe_cast(json_value(content, '$.trip_id') as string) trip_id,
+            safe_cast(json_value(content, '$.shape_id') as string) shape_id,
+            safe_cast(
+                datetime(
+                    timestamp(
+                        safe_cast(json_value(content, '$.datetime_envio') as string)
+                    ),
+                    "America/Sao_Paulo"
+                ) as datetime
+            ) datetime_envio,
+            safe_cast(
+                datetime(
+                    timestamp(
+                        safe_cast(json_value(content, '$.datetime_servidor') as string)
+                    ),
+                    "America/Sao_Paulo"
+                ) as datetime
+            ) datetime_servidor,
+            safe_cast(
+                datetime(timestamp(timestamp_captura), "America/Sao_Paulo") as datetime
+            ) datetime_captura
+        from
+            {{
+                source(
+                    "source_" ~ var("fonte_gps"),
+                    "registros",
+                )
+            }}
+    ),
+    filtered_data as (
+        select *
+        from source_data
+        where
+            datetime_diff(datetime_envio, datetime_gps, second) >= -20
+            and datetime_diff(datetime_envio, datetime_gps, minute) <= 60
+    )
+select
+    id_veiculo,
+    servico,
+    sentido,
+    latitude,
+    longitude,
+    datetime_gps,
+    velocidade,
+    direcao,
+    route_id,
+    trip_id,
+    shape_id,
+    datetime_envio,
+    datetime_servidor,
+    datetime_captura
+from filtered_data
+qualify
+    row_number() over (
+        partition by id_veiculo, latitude, longitude, datetime_gps, datetime_captura
+        order by datetime_captura desc
+    )
+    = 1
path: queries/models/monitoramento/staging/aux_gps.sql
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Corrigir lógica de deduplicação**  
O `PARTITION BY` atual inclui `datetime_captura`, o que garante que cada linha seja única e impede a escolha do registro mais recente. Adapte conforme abaixo para funcionar corretamente:

```diff
- partition by id_veiculo, latitude, longitude, datetime_gps, datetime_captura
+ partition by id_veiculo, latitude, longitude, datetime_gps
  order by datetime_captura desc
```

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In queries/models/monitoramento/staging/aux_gps.sql around lines 91 to 96, the
deduplication logic is incorrect because the PARTITION BY clause includes
datetime_captura, which makes each row unique and prevents selecting the most
recent record. Remove datetime_captura from the PARTITION BY clause so that the
row_number() function partitions only by id_veiculo, latitude, longitude, and
datetime_gps, allowing the ORDER BY datetime_captura DESC to correctly pick the
latest record per group.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-20T22:35:24Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,19 @@
+{% macro generate_date_hour_partition_filter(start_timestamp, end_timestamp) %}
+    {% set start = modules.datetime.datetime.fromisoformat(start_timestamp) %}
+    {% set end = modules.datetime.datetime.fromisoformat(end_timestamp) %}
+    {% set days = (end.date() - start.date()).days %}
+
+    {% if days == 0 %}
+        data = date("{{ start_timestamp }}")
+        and hora between {{ start.hour }} and {{ end.hour }}
+
path: queries/macros/generate_date_hour_partition_filter.sql
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Uso de aspas em literais de data para BigQuery**  
Em BigQuery, literais de string devem ser envoltos por aspas simples (`'`) em vez de aspas duplas (`"`). A linha atual:  
```
data = date("{{ start_timestamp }}")
```  
pode causar erro de compilação.  
  
Use este diff para ajustar:
```diff
-        data = date("{{ start_timestamp }}")
+        data = date('{{ start_timestamp }}')
```  


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
    {% if days == 0 %}
        data = date('{{ start_timestamp }}')
        and hora between {{ start.hour }} and {{ end.hour }}
```

</details>

<!-- suggestion_end -->

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In queries/macros/generate_date_hour_partition_filter.sql around lines 6 to 9,
the date literal uses double quotes which is invalid in BigQuery. Replace the
double quotes around {{ start_timestamp }} with single quotes to correctly
format the date string literal as date('{{ start_timestamp }}').
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-24T01:14:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -64,32 +64,33 @@ models:
         description: "{{ doc('sentido') }}"
       - name: velocidade
         description: "{{ doc('velocidade_instantanea') }}"
-  - name: registros_historico
-    description: "View para os dados históricos capturados em staging com tratamento básico e conversão de valores"
-    columns:
-      - name: codigo
-        description: "{{ doc('codigo') }}"
-      - name: placa
-        description: "{{ doc('placa') }}"
-      - name: linha
-        description: "{{ doc('linha') }}"
-      - name: latitude
-        description: "{{ doc('latitude_gps') }}"
-      - name: longitude
-        description: "{{ doc('longitude_gps') }}"
-      - name: timestamp_gps
-        description: "{{ doc('timestamp_gps') }}"
-      - name: velocidade
-        description: "{{ doc('velocidade_instantanea') }}"
-      - name: id_migracao_trajeto
-        description: ""
-      - name: sentido
-        description: "{{ doc('sentido') }}"
-      - name: trajeto
-        description: "{{ doc('trajeto') }}"
-      - name: timestamp_captura
-        description: "{{ doc('timestamp_captura') }}"
-      - name: data
-        description: "{{ doc('data_captura') }}"
-      - name: hora
-        description: "Hora do 'timestamp_captura'"
\ No newline at end of file
+
+  # - name: registros_historico
+  #   description: "View para os dados históricos capturados em staging com tratamento básico e conversão de valores"
+  #   columns:
+  #     - name: codigo
+  #       description: "{{ doc('codigo') }}"
+  #     - name: placa
+  #       description: "{{ doc('placa') }}"
+  #     - name: linha
+  #       description: "{{ doc('linha') }}"
+  #     - name: latitude
+  #       description: "{{ doc('latitude_gps') }}"
+  #     - name: longitude
+  #       description: "{{ doc('longitude_gps') }}"
+  #     - name: timestamp_gps
+  #       description: "{{ doc('timestamp_gps') }}"
+  #     - name: velocidade
+  #       description: "{{ doc('velocidade_instantanea') }}"
+  #     - name: id_migracao_trajeto
+  #       description: ""
+  #     - name: sentido
+  #       description: "{{ doc('sentido') }}"
+  #     - name: trajeto
+  #       description: "{{ doc('trajeto') }}"
+  #     - name: timestamp_captura
+  #       description: "{{ doc('timestamp_captura') }}"
+  #     - name: data
+  #       description: "{{ doc('data_captura') }}"
+  #     - name: hora
+  #       description: "Hora do 'timestamp_captura'"
path: queries/models/br_rj_riodejaneiro_brt_gps/schema.yml
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Novo caractere de fim de arquivo ausente**  
O lint de YAML indica que não há uma nova linha ao final do arquivo. Adicione uma linha em branco após o conteúdo para satisfazer o padrão POSIX e evitar warnings de ferramentas de análise.  

```diff
 (conteúdo existente...)
+<newlineEOF>
```


> Committable suggestion skipped: line range outside the PR's diff.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.37.1)</summary>

[error] 96-96: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In queries/models/br_rj_riodejaneiro_brt_gps/schema.yml at line 96, the file is
missing a newline character at the end. Add a blank new line after the last line
of the file to comply with POSIX standards and prevent YAML lint warnings.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-24T01:14:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,81 @@
+{{
+    config(
+        materialized="table",
+        partition_by={"field": "data", "data_type": "date", "granularity": "day"},
+        tags=["geolocalizacao"],
+        alias=this.name ~ "_" ~ var("modo_gps") ~ "_" ~ var("fonte_gps"),
+    )
+}}
+
+with
+    registros as (
+        -- 1. registros_filtrada
+        select
+            data,
+            hora,
+            id_veiculo,
+            datetime_gps,
+            datetime_captura,
+            velocidade,
+            servico,
+            latitude,
+            longitude,
+        from {{ ref("aux_gps_filtrada") }}
+    ),
+    velocidades as (
+        -- 2. velocidades
+        select
+            id_veiculo,
+            datetime_gps,
+            servico,
+            velocidade,
+            distancia,
+            indicador_em_movimento
+        from {{ ref("aux_gps_velocidade") }}
+    ),
+    paradas as (
+        -- 3. paradas
+        select id_veiculo, datetime_gps, servico, tipo_parada
+        from {{ ref("aux_gps_parada") }}
+    ),
+    indicadores as (
+        -- 4. indicador_trajeto_correto
+        select id_veiculo, datetime_gps, servico, route_id, indicador_trajeto_correto
+        from {{ ref("aux_gps_trajeto_correto") }}
+    )
+-- 5. Junção final
+select
+    date(r.datetime_gps) data,
+    extract(hour from r.datetime_gps) hora,
+    r.datetime_gps,
+    r.id_veiculo,
+    r.servico,
+    r.latitude,
+    r.longitude,
+    case
+        when indicador_em_movimento is true and indicador_trajeto_correto is true
+        then 'Em operação'
+        when indicador_em_movimento is true and indicador_trajeto_correto is false
+        then 'Operando fora trajeto'
+        when indicador_em_movimento is false
+        then
+            case
+                when tipo_parada is not null
+                then concat("Parado ", tipo_parada)
path: queries/models/monitoramento/gps_15_minutos.sql
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Erro nas aspas de literais no `concat`**  
A função `concat("Parado ", tipo_parada)` utiliza aspas duplas para o literal, o que gera erro em BigQuery. Substitua por aspas simples:  
```diff
-                then concat("Parado ", tipo_parada)
+                then concat('Parado ', tipo_parada)
```  



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
                when tipo_parada is not null
                then concat('Parado ', tipo_parada)
```

</details>

<!-- suggestion_end -->

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In queries/models/monitoramento/gps_15_minutos.sql at lines 63 to 64, the concat
function uses double quotes for the string literal "Parado ", which causes an
error in BigQuery. Replace the double quotes with single quotes around the
literal so it reads concat('Parado ', tipo_parada).
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-24T01:14:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,68 @@
+{{ config(materialized="ephemeral") }}
+
+{% set partition_filter %}
+    ({{ generate_date_hour_partition_filter(var('date_range_start'), var('date_range_end')) }})
+{% endset %}
+
+-- 1. Filtra realocações válidas dentro do intervalo de GPS avaliado
+with
+    realocacao as (
+        select
+            * except (datetime_saida),
+            case
+                when datetime_saida is null then datetime_operacao else datetime_saida
+            end as datetime_saida,
+        from {{ ref("staging_realocacao") }}
path: queries/models/monitoramento/staging/aux_gps_realocacao.sql
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Erro de sintaxe: vírgula extra antes do FROM**  
Na CTE `realocacao`, existe uma vírgula após `end as datetime_saida,` antes do `from`, o que resultará em erro de parsing no BigQuery.  


Aplique este diff para corrigir:

```diff
@@ -13,4 +13,3
-    end as datetime_saida,
-from {{ ref("staging_realocacao") }}
+    end as datetime_saida
+from {{ ref("staging_realocacao") }}
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
            * except (datetime_saida),
            case
                when datetime_saida is null then datetime_operacao else datetime_saida
            end as datetime_saida
        from {{ ref("staging_realocacao") }}
```

</details>

<!-- suggestion_end -->

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In queries/models/monitoramento/staging/aux_gps_realocacao.sql around lines 11
to 15, there is an extra comma after the expression "end as datetime_saida,"
before the FROM clause in the CTE realocacao. Remove this trailing comma to fix
the syntax error and ensure the query parses correctly in BigQuery.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-24T01:14:42Z
author_association: CONTRIBUTOR

PR comments:
user: login: mergify[bot]
created_at: 2024-11-13T14:16:11Z
body: @akaBotelho esse pull request tem conflitos 😩
author_association: CONTRIBUTOR
user: login: coderabbitai[bot]
created_at: 2025-05-06T16:50:21Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough

Esta atualização introduz um conjunto abrangente de novos modelos SQL, macros, configurações e documentação para monitoramento de dados de GPS de ônibus, realocação de veículos e gestão de garagens. Foram adicionados novos fluxos, seletores, variáveis de configuração e fontes de dados. Diversos modelos e esquemas foram criados ou ajustados para suportar a materialização, processamento e documentação de dados de GPS e suas integrações.

## Changes

| Arquivo(s)                                                                                  | Resumo das alterações                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
|---------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| queries/dbt_project.yml, pipelines/migration/br_rj_riodejaneiro_onibus_gps/flows.py          | Variável `fifteen_minutes` substituída por `15_minutos` (booleano). Novas variáveis GPS adicionadas (`modo_gps`, `fonte_gps`, `buffer_segmento_metros`). Atualizações nos parâmetros dos fluxos para refletir o novo nome e tipo.                                                                                                                                                                                                                                                                                         |
| queries/models/monitoramento/gps.sql, queries/models/monitoramento/gps_15_minutos.sql        | Novos modelos incrementais para monitoramento de GPS, com particionamento diário, junção de tabelas auxiliares e cálculo de status do veículo. Configuração dinâmica de alias e tagging para geolocalização.                                                                                                                                                                                                                                                                      |
| queries/models/monitoramento/staging/aux_gps_filtrada.sql, aux_gps_parada.sql, aux_gps_realocacao.sql, aux_gps_trajeto_correto.sql, aux_gps_velocidade.sql | Novos modelos efêmeros para filtragem de GPS por bounding box, identificação de paradas, realocação, avaliação de trajeto correto e cálculo de velocidade. Utilizam variáveis configuráveis e funções espaciais.                                                                                                                                                                                                                                                                |
| queries/models/monitoramento/staging/staging_gps.sql, staging_realocacao.sql, staging_garagens.sql | Novos modelos de staging para ingestão e transformação de dados brutos de GPS, realocação e garagens, com parsing de campos JSON, tratamento de datas e normalização de atributos.                                                                                                                                                                                                                                                         |
| queries/models/monitoramento/schema.yml, queries/models/monitoramento/staging/schema.yml     | Novos arquivos de schema YAML detalhando modelos, colunas e descrições, referenciando macros de documentação e garantindo metadados centralizados e consistentes.                                                                                                                                                                                                                                                                          |
| queries/models/sources.yml                                                                  | Adição de quatro novas fontes: monitoramento_staging, source_cittati, source_conecta e source_zirix, cada uma com tabelas específicas para registros e realocações.                                                                                                                                                                                                                                                                       |
| queries/selectors.yml                                                                       | Inclusão de dois novos seletores: `gps` e `gps_15_minutos`, ambos agrupando modelos de staging e materializados para GPS.                                                                                                                                                                                                                                                                                                                 |
| queries/models/docs.md                                                                      | Documentação expandida com novos blocos para campos relacionados à captura de GPS e realocação de linhas de ônibus.                                                                                                                                                                                                                                                                                                                       |
| queries/models/monitoramento/CHANGELOG.md, queries/CHANGELOG.md                             | Novas entradas de changelog detalhando as adições de modelos, seletores e referência ao pull request associado.                                                                                                                                                                                                                                                                                                                           |
| queries/macros/generate_date_hour_partition_filter.sql                                      | Nova macro Jinja para gerar filtros de partição por data e hora a partir de timestamps de início e fim.                                                                                                                                                                                                                                                                                                                                  |
| queries/models/br_rj_riodejaneiro_onibus_gps/sppo_aux_registros_filtrada.sql, sppo_aux_registros_realocacao.sql | Refatoração do bloco de configuração para usar variáveis e expressões condicionais inline, simplificando a lógica de materialização e particionamento. Reformatado o SQL para melhor legibilidade sem alterar a lógica.                                                                                                                                                                                                                  |
| queries/models/br_rj_riodejaneiro_brt_gps/schema.yml                                       | Comentado o modelo `registros_historico`, desabilitando-o sem removê-lo do arquivo.                                                                                                                                                                                                                                                                                                                                                       |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant API GPS
    participant staging_gps
    participant aux_gps_filtrada
    participant aux_gps_velocidade
    participant aux_gps_parada
    participant aux_gps_realocacao
    participant aux_gps_trajeto_correto
    participant gps
    participant gps_15_minutos

    API GPS->>staging_gps: Ingesta e transformação de dados brutos
    staging_gps->>aux_gps_filtrada: Filtragem por bounding box
    aux_gps_filtrada->>aux_gps_velocidade: Cálculo de velocidades
    aux_gps_filtrada->>aux_gps_parada: Identificação de paradas
    aux_gps_filtrada->>aux_gps_realocacao: Aplicação de realocações
    aux_gps_filtrada->>aux_gps_trajeto_correto: Verificação de trajeto correto
    aux_gps_velocidade->>gps: Junção para cálculo de status e materialização
    aux_gps_parada->>gps: Junção para cálculo de status e materialização
    aux_gps_realocacao->>gps: Junção para cálculo de status e materialização
    aux_gps_trajeto_correto->>gps: Junção para cálculo de status e materialização
    gps->>gps_15_minutos: Agregação e materialização por 15 minutos
```

## Poema

> 🐇  
> Saltando entre dados, o coelho feliz,  
> GPS, garagens, trajetos — tudo eu quis!  
> Novos modelos e macros a brilhar,  
> Seletores saltando, prontos pra rodar.  
> Com cada partição, um pulinho a mais,  
> No mundo dos ônibus, sou mestre dos sinais!  
> 🚌✨

<!-- walkthrough_end -->


---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between d3c43c33c2230cf906802d17aadb52a15142aaff and 79cb13bb56b8a1058924581b635805ff3a5e2428.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `queries/selectors.yml` (1 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* queries/selectors.yml

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (4)</summary>

* GitHub Check: Build and publish docs
* GitHub Check: Register flows (staging)
* GitHub Check: Build Fedora Image
* GitHub Check: WIP

</details>

</details>
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=prefeitura-rio/pipelines_rj_smtr&utm_content=297):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR
user: login: mergify[bot]
created_at: 2025-05-13T18:10:45Z
body: @akaBotelho esse pull request tem conflitos 😩
author_association: CONTRIBUTOR
user: login: akaBotelho
created_at: 2025-05-21T20:42:44Z
body: - [ ] Verificar partições nos modelos ephemeral
- [ ] remover duplicados do aux_gps no gps_filtrada
- [ ] veriricar rownumber nos modelos ephemeral
- [ ] considerar generate_date_hour_partition_filter para insert_strategy usando incremental ou trocar para merge
- [ ] ajustar filtros com is_incremental
- [x] verificar com o Rodrigo o timezone da API
- [x] trocar fifteen_minutes para bool
- [x] trocar nome para staging (aux_gps e aux_realocacao)
- [ ] aux_gps_realocacao (criar um modelo ephemeral e fazer um select * como incremental)
- [ ] avaliar passar os filtros dos modelos ephemeral para o modelo incremental
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-05-26T22:29:30Z
body: ### Análise da árvore de código

**Os seguintes arquivos são afetados diretamente por alterações realizadas nesse pull request:**
	- `pipelines/migration/br_rj_riodejaneiro_onibus_gps/flows.py`
author_association: NONE