Esta aplicação é o componente técnico responsável pela inteligência de dados do ecossistema SolveLicita. Sua função é automatizar o ciclo completo de análise de risco fiscal de todos os municípios brasileiros, transformando dados públicos brutos em um Score de Solvência padronizado e acionável. Para isso, o pipeline executa um fluxo contínuo que coleta informações de múltiplas fontes oficiais via APIs, estrutura e consolida registros contábeis complexos através de camadas de modelagem SQL e aplica pós-processadores analíticos em Python para o cálculo final dos indicadores. Essa automação traduz relatórios técnicos dispersos em uma resposta direta sobre a capacidade real de pagamento de cada prefeitura, servindo como a base de dados fundamental para a plataforma web do SolveLicita.
Um Score de Solvência (0–100) calculado a partir de seis indicadores fiscais públicos, ponderados por relevância:
| Indicador | Fonte | Peso | O que mede |
|---|---|---|---|
| Liquidez Líquida | SICONFI / RGF Anexo 05 | 35% | Caixa disponível após Restos a Pagar |
| RP Crônicos | SICONFI / RREO Anexo 07 | 15% | Histórico de dívidas com fornecedores |
| Execução Orçamentária | SICONFI / RREO Anexo 01 | 15% | Aderência entre receita prevista e realizada |
| Transparência Fiscal | SICONFI | 15% | Continuidade de entrega de dados públicos |
| Autonomia Tributária | FINBRA / DCA | 10% | Dependência do FPM vs receita própria |
| Bloqueio Federal | CAUC / STN | 10% | Pendências que bloqueiam repasses federar |
A fórmula, as curvas de pontuação e as justificativas de cada escolha estão em docs/METODOLOGIA.md.
Classificação:
| Score | Classificação |
|---|---|
| ≥ 80 | 🟢 Risco Baixo |
| 60 – 79 | 🟡 Risco Médio |
| 40 – 59 | 🔴 Risco Alto |
| < 40 | ⛔ Crítico |
| — | ⚫ Sem Dados |
Além do score numérico, dois caps de classificação operam de forma independente: municípios com histórico de não entrega de dados não podem ser classificados como Risco Baixo, e municípios com padrão crônico de Restos a Pagar Processados têm teto em Risco Médio.
O score é validado por um backtest walk-forward reproduzível, versionado em src/analysis/backtest_validacao.py: o score é calculado em um ano e comparado com o comportamento fiscal observado no ano seguinte, usando a ocorrência futura de Restos a Pagar crônicos como desfecho.
Na validação geral documentada, o modelo operacional apresentou:
| Métrica | Resultado |
|---|---|
| Pares município-ano avaliados | 4.671 |
| AUC-ROC | 0.7443 |
| Spearman | -0.3827 |
Os dois recortes podem ser executados diretamente no repositório:
python src/analysis/backtest_validacao.py --geral --excluir-t0 2020
python src/analysis/backtest_validacao.py --geral --sem-rproc --excluir-t0 2020Resultados, limitações e testes de sensibilidade estão em docs/VALIDACAO.md.
O fluxo opera com um modelo BigQuery-first. Os dados públicos são coletados das APIs oficiais, estruturados com dbt, enriquecidos por pós-processadores Python e consolidados. O resultado é publicado em snapshots históricos e sincronizado no Supabase para consumo pela aplicação web do SolveLicita.
flowchart LR
PL(["pipeline.py"])
subgraph INGEST ["1. Ingestão"]
direction LR
APIS["APIs públicas<br/>IBGE / SICONFI / DCA / CAUC / PNCP"]
RAW[("BigQuery raw")]
APIS --> RAW
end
subgraph TRANSFORM ["2. Transformação"]
direction TB
DBT["dbt"]
STG["staging"]
INT["intermediate"]
MART["mart"]
DBT --> STG --> INT --> MART
end
subgraph ENRICH ["3. Enriquecimento"]
direction TB
PROC["Postprocessors Python"]
BQINT[("BigQuery intermediate")]
PROC -->|MERGE SQL| BQINT
end
subgraph SCORE ["4. Score"]
direction LR
ENG["Engine v7.0"]
CSV["CSV final"]
end
subgraph PUBLISH ["5. Publicação"]
direction LR
SNAP[("BigQuery snapshots")]
SB[("Supabase")]
WEB["Aplicação SolveLicita"]
end
PL --> INGEST
RAW --> TRANSFORM
MART --> ENRICH
MART --> ENG
BQINT --> ENG
ENG --> SNAP
ENG --> CSV
CSV --> SB
SB -. consumo .-> WEB
style PL fill:#0f2744,color:#e8f3ff,stroke:#7fc4ff,stroke-width:2px
style INGEST fill:#12263d,color:#e8f3ff,stroke:#185FA5,stroke-width:2px
style TRANSFORM fill:#12263d,color:#e8f3ff,stroke:#2B7BBB,stroke-width:2px
style ENRICH fill:#12263d,color:#e8f3ff,stroke:#4A97D9,stroke-width:2px
style SCORE fill:#12263d,color:#e8f3ff,stroke:#6FB4F0,stroke-width:2px
style PUBLISH fill:#12263d,color:#e8f3ff,stroke:#91CBFF,stroke-width:2px
style APIS fill:#1a1f26,color:#f2f7ff,stroke:#8aa7c4,stroke-width:1px
style RAW fill:#1a1f26,color:#f2f7ff,stroke:#8aa7c4,stroke-width:1px
style DBT fill:#1a1f26,color:#f2f7ff,stroke:#8aa7c4,stroke-width:1px
style STG fill:#1a1f26,color:#f2f7ff,stroke:#8aa7c4,stroke-width:1px
style INT fill:#1a1f26,color:#f2f7ff,stroke:#8aa7c4,stroke-width:1px
style MART fill:#1a1f26,color:#f2f7ff,stroke:#8aa7c4,stroke-width:1px
style PROC fill:#1a1f26,color:#f2f7ff,stroke:#8aa7c4,stroke-width:1px
style BQINT fill:#1a1f26,color:#f2f7ff,stroke:#8aa7c4,stroke-width:1px
style ENG fill:#1a1f26,color:#f2f7ff,stroke:#8aa7c4,stroke-width:1px
style CSV fill:#1a1f26,color:#f2f7ff,stroke:#8aa7c4,stroke-width:1px
style SNAP fill:#1a1f26,color:#f2f7ff,stroke:#8aa7c4,stroke-width:1px
style SB fill:#1a1f26,color:#f2f7ff,stroke:#8aa7c4,stroke-width:1px
style WEB fill:#1a1f26,color:#f2f7ff,stroke:#8aa7c4,stroke-width:1px
Cada camada tem uma responsabilidade distinta:
raw: dados oficiais coletados sem interpretação analítica.staging,intermediateemart: modelagem e consolidação comdbt.processors: regras complementares em Python.engine: cálculo final do score e classificação de risco.Supabase: camada de dados consumida pela aplicação SolveLicita.
solvelicita-engine/
├── dbt/ # Transformação SQL no data warehouse
│ ├── models/ # Camadas staging, intermediate e mart
│ └── dbt_project.yml # Configuração do projeto dbt
├── docs/ # Metodologia, validação e assets
├── src/ # Motor Python de coleta, processamento e score
│ ├── collectors/ # Clientes de APIs públicas
│ ├── processors/ # Pós-processamento analítico
│ ├── engine/ # Cálculo final do score
│ ├── scorers/ # Curvas, pesos e pontuações parciais
│ ├── jobs/ # Orquestração testável do pipeline
│ └── analysis/ # Backtests e análises estatísticas
├── tests/ # Testes automatizados
└── pipeline.py # CLI principal do pipeline
O pipeline pode ser reproduzido com dois ambientes isolados: um para coleta, processamento e score em Python; outro para transformação SQL com dbt.
git clone https://github.com/Fel-tby/solvelicita-engine.git
cd solvelicita-engine
# Ambiente principal
python -m venv venv
venv\Scripts\activate
pip install -r requirements.txt
deactivate
# Ambiente dbt
python -m venv venv_dbt
venv_dbt\Scripts\activate
pip install dbt-core dbt-bigquery
deactivateConfigure as credenciais de Google Cloud e Supabase no arquivo .env, usando .env.example como referência. Configure também o perfil dbt a partir de dbt/profiles.yml.example.
Execução principal:
venv\Scripts\activate
python pipeline.py --uf PB --mode incremental --steps collect,dbt,process,score,syncExecução parcial, quando os dados já foram coletados e transformados:
python pipeline.py --uf PB --steps process,score,sync| Documento | Conteúdo |
|---|---|
docs/METODOLOGIA.md |
Fórmula, pesos, curvas de pontuação, caps duros |
docs/VALIDACAO.md |
Backtest, AUC-ROC, análise de sensibilidade |
Executando Testes:
# Camada SQL / BigQuery
venv_dbt\Scripts\activate
cd dbt && dbt test
# Camada Python / Score
venv\Scripts\activate
pytest -vO repositório possui automações em GitHub Actions:
CI: rodapytestempushepull_request.Pipeline Nacional Full: dispara a pipeline em matrix para as 27 UFs porworkflow_dispatch.Pipeline Incremental Mensal Nacional: atualização incremental mensal para todas as UFs.Pipeline CAUC Semanal Nacional: atualização semanal de CAUC para todas as UFs.
Os workflows de pipeline reutilizam um executor único por UF e dependem dos secrets:
GCP_PROJECT_IDGCP_SA_KEYSUPABASE_URLSUPABASE_KEY