Files
ranking/backend/sql/schema_ranking.sql
Frederico Castro 3ea6a4409e feat: Implementa job de ranking para 300k consultores
Backend:
- Adiciona Scroll API no cliente Elasticsearch para processar todos os 300k+ consultores
- Cria tabela TB_RANKING_CONSULTOR no Oracle para ranking pré-calculado
- Implementa job de processamento com APScheduler (diário às 3h)
- Adiciona endpoints: /ranking/paginado, /ranking/status, /ranking/processar, /ranking/estatisticas
- Repository Oracle com paginação eficiente via ROW_NUMBER
- Status do job com progresso em tempo real (polling)
- Leitura automática de LOBs no OracleClient

Frontend:
- Componente RankingPaginado com paginação completa
- Barra de progresso do job em tempo real
- Botão para reprocessar ranking
- Alternância entre Top N (rápido) e Ranking Completo (300k)

Infraestrutura:
- Docker compose com depends_on para garantir Oracle disponível
- Schema SQL com procedure SP_ATUALIZAR_POSICOES
- Índices otimizados para paginação
2025-12-10 01:33:00 -03:00

110 lines
4.7 KiB
SQL

-- Schema para Ranking de Consultores CAPES
-- Versão: 1.0
-- Data: 2025-01-15
-- Tabela principal de ranking
CREATE TABLE TB_RANKING_CONSULTOR (
ID_PESSOA NUMBER(10) NOT NULL,
NOME VARCHAR2(200) NOT NULL,
POSICAO NUMBER(10),
PONTUACAO_TOTAL NUMBER(10,2) NOT NULL,
COMPONENTE_A NUMBER(10,2) DEFAULT 0,
COMPONENTE_B NUMBER(10,2) DEFAULT 0,
COMPONENTE_C NUMBER(10,2) DEFAULT 0,
COMPONENTE_D NUMBER(10,2) DEFAULT 0,
ATIVO CHAR(1) DEFAULT 'N',
ANOS_ATUACAO NUMBER(5,1) DEFAULT 0,
DT_CALCULO TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
JSON_DETALHES CLOB,
CONSTRAINT PK_RANKING_CONSULTOR PRIMARY KEY (ID_PESSOA),
CONSTRAINT CHK_ATIVO CHECK (ATIVO IN ('S', 'N'))
);
-- Índices para performance
CREATE INDEX IDX_RANKING_POSICAO ON TB_RANKING_CONSULTOR(POSICAO);
CREATE INDEX IDX_RANKING_PONTUACAO ON TB_RANKING_CONSULTOR(PONTUACAO_TOTAL DESC);
CREATE INDEX IDX_RANKING_ATIVO ON TB_RANKING_CONSULTOR(ATIVO);
CREATE INDEX IDX_RANKING_DT_CALCULO ON TB_RANKING_CONSULTOR(DT_CALCULO DESC);
-- Procedure para atualizar posições após processamento
CREATE OR REPLACE PROCEDURE SP_ATUALIZAR_POSICOES AS
BEGIN
MERGE INTO TB_RANKING_CONSULTOR t
USING (
SELECT ID_PESSOA,
ROW_NUMBER() OVER (ORDER BY PONTUACAO_TOTAL DESC, ID_PESSOA) AS NOVA_POSICAO
FROM TB_RANKING_CONSULTOR
) s
ON (t.ID_PESSOA = s.ID_PESSOA)
WHEN MATCHED THEN UPDATE SET t.POSICAO = s.NOVA_POSICAO;
COMMIT;
END SP_ATUALIZAR_POSICOES;
/
-- View para estatísticas do ranking
CREATE OR REPLACE VIEW VW_RANKING_ESTATISTICAS AS
SELECT
COUNT(*) AS TOTAL_CONSULTORES,
COUNT(CASE WHEN ATIVO = 'S' THEN 1 END) AS TOTAL_ATIVOS,
COUNT(CASE WHEN ATIVO = 'N' THEN 1 END) AS TOTAL_INATIVOS,
MAX(DT_CALCULO) AS ULTIMA_ATUALIZACAO,
AVG(PONTUACAO_TOTAL) AS PONTUACAO_MEDIA,
MAX(PONTUACAO_TOTAL) AS PONTUACAO_MAXIMA,
MIN(PONTUACAO_TOTAL) AS PONTUACAO_MINIMA,
AVG(COMPONENTE_A) AS MEDIA_COMP_A,
AVG(COMPONENTE_B) AS MEDIA_COMP_B,
AVG(COMPONENTE_C) AS MEDIA_COMP_C,
AVG(COMPONENTE_D) AS MEDIA_COMP_D
FROM TB_RANKING_CONSULTOR;
-- View para distribuição por faixas de pontuação
CREATE OR REPLACE VIEW VW_RANKING_DISTRIBUICAO AS
SELECT
CASE
WHEN PONTUACAO_TOTAL >= 800 THEN '800+'
WHEN PONTUACAO_TOTAL >= 600 THEN '600-799'
WHEN PONTUACAO_TOTAL >= 400 THEN '400-599'
WHEN PONTUACAO_TOTAL >= 200 THEN '200-399'
ELSE '0-199'
END AS FAIXA,
COUNT(*) AS QUANTIDADE,
ROUND(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM TB_RANKING_CONSULTOR), 2) AS PERCENTUAL
FROM TB_RANKING_CONSULTOR
GROUP BY
CASE
WHEN PONTUACAO_TOTAL >= 800 THEN '800+'
WHEN PONTUACAO_TOTAL >= 600 THEN '600-799'
WHEN PONTUACAO_TOTAL >= 400 THEN '400-599'
WHEN PONTUACAO_TOTAL >= 200 THEN '200-399'
ELSE '0-199'
END
ORDER BY
CASE
WHEN FAIXA = '800+' THEN 1
WHEN FAIXA = '600-799' THEN 2
WHEN FAIXA = '400-599' THEN 3
WHEN FAIXA = '200-399' THEN 4
ELSE 5
END;
-- Comentários nas tabelas e colunas
COMMENT ON TABLE TB_RANKING_CONSULTOR IS 'Tabela de ranking pré-calculado de consultores CAPES';
COMMENT ON COLUMN TB_RANKING_CONSULTOR.ID_PESSOA IS 'ID da pessoa no sistema AtuaCAPES';
COMMENT ON COLUMN TB_RANKING_CONSULTOR.NOME IS 'Nome completo do consultor';
COMMENT ON COLUMN TB_RANKING_CONSULTOR.POSICAO IS 'Posição no ranking (1 = primeiro lugar)';
COMMENT ON COLUMN TB_RANKING_CONSULTOR.PONTUACAO_TOTAL IS 'Pontuação total calculada (soma dos 4 componentes)';
COMMENT ON COLUMN TB_RANKING_CONSULTOR.COMPONENTE_A IS 'Pontuação do Componente A (Coordenação CAPES)';
COMMENT ON COLUMN TB_RANKING_CONSULTOR.COMPONENTE_B IS 'Pontuação do Componente B (Coordenação PPG)';
COMMENT ON COLUMN TB_RANKING_CONSULTOR.COMPONENTE_C IS 'Pontuação do Componente C (Consultoria)';
COMMENT ON COLUMN TB_RANKING_CONSULTOR.COMPONENTE_D IS 'Pontuação do Componente D (Premiações)';
COMMENT ON COLUMN TB_RANKING_CONSULTOR.ATIVO IS 'Indicador se o consultor está ativo (S/N)';
COMMENT ON COLUMN TB_RANKING_CONSULTOR.ANOS_ATUACAO IS 'Anos de atuação do consultor';
COMMENT ON COLUMN TB_RANKING_CONSULTOR.DT_CALCULO IS 'Data/hora do último cálculo';
COMMENT ON COLUMN TB_RANKING_CONSULTOR.JSON_DETALHES IS 'Dados completos do consultor em JSON para exibição';
-- Grant de permissões para o usuário de aplicação (ajustar conforme necessário)
-- GRANT SELECT, INSERT, UPDATE, DELETE ON TB_RANKING_CONSULTOR TO app_user;
-- GRANT SELECT ON VW_RANKING_ESTATISTICAS TO app_user;
-- GRANT SELECT ON VW_RANKING_DISTRIBUICAO TO app_user;
-- GRANT EXECUTE ON SP_ATUALIZAR_POSICOES TO app_user;