Skip to content

feat: modal pro Checar Metadados e botão de sincronizar Update.latest - staging - #1068

Merged
Winzen merged 3 commits into
stagingfrom
feat/check-metadados-button
Aug 22, 2026
Merged

feat: modal pro Checar Metadados e botão de sincronizar Update.latest - staging#1068
Winzen merged 3 commits into
stagingfrom
feat/check-metadados-button

Conversation

@Winzen

@Winzen Winzen commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Nova funcionalidade: modal no Checar Metadados + botão Sincronizar Update.latest

Contexto

O botão "Checar Metadados" (introduzido nos PRs #1066/#1067) comparava o schema da Table no BigQuery com as Columns cadastradas na API, mas mostrava o resultado num alert() de texto solto — difícil de ler quando há várias discrepâncias.

Esse PR também adiciona um botão pra sincronizar Update.latest com o BigQuery direto da UI, sem precisar de acesso ao banco — contexto completo em #1069.

O que tem nesse PR

1. Checar Metadados — resultado num modal estruturado

A view agora devolve uma lista de discrepâncias estruturadas em vez de uma string já formatada, e o front renderiza cada uma como uma linha com um badge por tipo.

backend/apps/admin_data_tools/
├── views.py   # CheckMetadadosView devolve {"discrepancias": [{"coluna", "tipo", "bigquery"?, "api"?}]}
└── urls.py

backend/apps/core/static/core/
├── js/ferramentas.js   # mostrarResultadoMetadados() monta o modal a partir da lista
└── css/main.css        # badge por tipo de discrepância

backend/templates/admin/change_form.html   # markup do #metadadosModal

Diagrama de fluxo

Botão "Checar Metadados" (change_form.html)
        │
        │  onclick
        ▼
checarMetadados()                         (ferramentas.js)
        │
        │  POST /admin-tools/check-metadados/
        ▼
CheckMetadadosView.post()                 (views.py)
        │
        │  get_gbq_client().get_table(gbq_slug)
        ▼
BigQuery — basedosdados-dev fora de prod, basedosdados em prod
        │
        │  schema real da tabela
        ▼
compara com Column.objects (nome, tipo, descrição)
        │
        │  {"status", "discrepancias": [...]}
        ▼
mostrarResultadoMetadados() → modal com uma linha por discrepância

Tipos de discrepância

tipo Quando aparece Campos extra
somente_bigquery Coluna existe no BigQuery, não na API
somente_api Coluna existe na API, não no BigQuery
tipo_diferente bigquery_type da API não bate com o schema do BQ bigquery, api
descricao_diferente Descrição da coluna diverge entre os dois lados bigquery, api

Tradução de tipo legacy → standard SQL

field.field_type do client do BigQuery sempre reporta o nome legacy (INTEGER, FLOAT, RECORD), enquanto bigquery_type na API usa o nome standard SQL (INT64, FLOAT64, STRUCT). Sem tradução, toda coluna numérica dava falso positivo:

_BQ_LEGACY_TYPE_ALIASES: dict[str, str] = {
    "integer": "int64",
    "float": "float64",
    "record": "struct",
}


def _bq_type_to_api_type(field_type: str) -> str:
    field_type = field_type.lower()
    return _BQ_LEGACY_TYPE_ALIASES.get(field_type, field_type)

A tradução só se aplica ao lado do BigQuery — a API já usa o nome padrão (inclusive BOOLEAN, não BOOL, então esse alias foi deliberadamente deixado de fora).

2. Botão "Sincronizar com o BigQuery"

Aparece ao lado do link do Update, no campo "Update and Poll Info" da página de admin de uma Table — só quando há exatamente 1 Update vinculado (evita gravar no lugar errado se a tabela estiver com Updates duplicados/ambíguos).

class SyncUpdateLatestView(View):
    def post(self, request):
        ...
        updates = list(selected_table.updates.all())
        if len(updates) != 1:
            return JsonResponse({"status": "erro", "erro": "..."})
        update = updates[0]

        gbq_slug = _gbq_slug_for_table(cloud_table)
        bq_table = get_gbq_client().get_table(gbq_slug)

        update.latest = bq_table.modified
        update.save(update_fields=["latest"])

Diagrama de fluxo

Botão "Sincronizar com o BigQuery" (get_update_display, admin.py)
        │
        │  onclick (confirm + disable)
        ▼
syncUpdateLatest()                        (ferramentas.js)
        │
        │  POST /admin-tools/sync-update-latest/
        ▼
SyncUpdateLatestView.post()               (views.py)
        │
        │  resolve o único Update da Table
        │  get_gbq_client().get_table(gbq_slug).modified
        ▼
Update.latest = last_modified real do BigQuery
        │
        ▼
modal com spinner → mensagem de sucesso/erro → fecha e recarrega a página

_gbq_slug_for_table() foi extraído como helper compartilhado entre as duas views, pra manter a mesma lógica de projeto por ambiente (is_prd()):

def _gbq_slug_for_table(cloud_table) -> str:
    gcp_project_id = "basedosdados" if is_prd() else "basedosdados-dev"
    return f"{gcp_project_id}.{cloud_table.gcp_dataset_id}.{cloud_table.gcp_table_id}"

Proteção contra clique duplicado

Os dois fluxos abrem um modal com spinner assim que a requisição começa — o .modal cobre a tela inteira (position: fixed, z-index: 1000), então não dá pra clicar no botão de novo por baixo dele enquanto a chamada está em andamento. O botão do Sync também é desabilitado como reforço.

Benefícios

  • Legível: várias discrepâncias aparecem uma por linha, com badge, em vez de um bloco de texto com \n
  • Corrige metadados sem SQL direto em produção: o botão de sync substitui o processo manual (GraphQL pra achar o ID + psql via kubectl exec) documentado em Acesso direto ao banco de prod.md
  • Consistente por ambiente: os dois botões respeitam is_prd() — em staging/dev comparam/sincronizam contra basedosdados-dev, em prod contra basedosdados

Acompanhamento

Registro do que foi feito e test plan em #1069. Fecha os dois itens pendentes de #1050.

Winzen added 3 commits August 21, 2026 14:46
field.field_type do client do BigQuery retorna o nome legacy do tipo
(INTEGER, FLOAT, RECORD), enquanto bigquery_type na API usa o nome
standard SQL (INT64, FLOAT64, STRUCT) — mesma coluna dava falso positivo
de "tipo diferente". Mesmos aliases do check_metadata.py (repo
pipelines), que já lida com essa mesma divergência.
A tradução (INTEGER->INT64, FLOAT->FLOAT64, RECORD->STRUCT) só faz
sentido no lado do BigQuery — a API já usa o nome padrão. Normalizar os
dois lados pela mesma tabela de alias escondia um bug: o alias
"boolean"->"bool" (copiado do check_metadata.py) não vale pra essa API,
que usa BOOLEAN — teria dado falso positivo numa coluna booleana real.
Checar Metadados agora devolve discrepâncias estruturadas e mostra o
resultado num modal (uma linha por discrepância, com badge por tipo),
em vez de um alert() com texto solto.

Novo botão "Sincronizar com o BigQuery" ao lado do "Update and Poll
Info" na página de admin da Table: grava o last_modified real do
BigQuery em Update.latest sem precisar esperar o próximo flow rodar.
Só aparece quando há exatamente 1 Update vinculado à tabela, e usa o
mesmo helper de projeto/ambiente (basedosdados-dev fora de prod) do
Checar Metadados.

Os dois mostram progresso num modal com spinner e bloqueiam o botão
enquanto a requisição está em andamento, evitando cliques repetidos.
@mergify

mergify Bot commented Aug 22, 2026

Copy link
Copy Markdown

⚠️ The sha of the head commit of this PR conflicts with #1066. Mergify cannot evaluate rules on this PR. Once #1066 is merged or closed, Mergify will resume processing this PR. ⚠️

@Winzen Winzen self-assigned this Aug 22, 2026
@Winzen Winzen added sync Aplicar em PRs que fazem merge de main → staging, develop, ou outras branches de longa duração. staging Indica que o Pull Request está com a branch de destino (base) apontando para staging and removed sync Aplicar em PRs que fazem merge de main → staging, develop, ou outras branches de longa duração. labels Aug 22, 2026
@Winzen
Winzen merged commit 071087a into staging Aug 22, 2026
8 checks passed
@Winzen
Winzen deleted the feat/check-metadados-button branch August 22, 2026 08:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

staging Indica que o Pull Request está com a branch de destino (base) apontando para staging

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant