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
This commit is contained in:
109
backend/sql/schema_ranking.sql
Normal file
109
backend/sql/schema_ranking.sql
Normal file
@@ -0,0 +1,109 @@
|
||||
-- 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;
|
||||
Reference in New Issue
Block a user