feat: extrair docencias PPG e simplificar blocos de pontuacao
Backend: - Adicionar entidade DocenciaPPG para dados de docencia - Extrair docencias do Elasticsearch (tipo "Docência") - Serializar docencias no JSON de detalhes do consultor - Aumentar batch size de 500 para 2000 para melhor performance Frontend: - Remover Bloco B (Coord. PPG) - reservado para V2 - Simplificar formula para: Bloco A + Bloco C + Bloco D - Filtrar orientacoes/bancas da listagem (sao apenas selos) - Atualizar Header com nota que PPG_COORD e apenas indicador - Exibir pontuacao base nos modais de orientacao/banca
This commit is contained in:
@@ -12,7 +12,7 @@ class RankingOracleRepository:
|
||||
|
||||
def inserir_batch(self, consultores: List[Dict[str, Any]]) -> int:
|
||||
"""
|
||||
Insere ou atualiza um batch de consultores usando MERGE.
|
||||
Insere batch de consultores usando executemany (muito mais rápido).
|
||||
Retorna o número de registros processados.
|
||||
"""
|
||||
import oracledb
|
||||
@@ -20,68 +20,39 @@ class RankingOracleRepository:
|
||||
if not consultores:
|
||||
return 0
|
||||
|
||||
merge_sql = """
|
||||
MERGE INTO TB_RANKING_CONSULTOR t
|
||||
USING (
|
||||
SELECT
|
||||
:id_pessoa AS ID_PESSOA,
|
||||
:nome AS NOME,
|
||||
:pontuacao_total AS PONTUACAO_TOTAL,
|
||||
:componente_a AS COMPONENTE_A,
|
||||
:componente_b AS COMPONENTE_B,
|
||||
:componente_c AS COMPONENTE_C,
|
||||
:componente_d AS COMPONENTE_D,
|
||||
:ativo AS ATIVO,
|
||||
:anos_atuacao AS ANOS_ATUACAO,
|
||||
TO_CLOB(:json_detalhes) AS JSON_DETALHES
|
||||
FROM DUAL
|
||||
) s
|
||||
ON (t.ID_PESSOA = s.ID_PESSOA)
|
||||
WHEN MATCHED THEN
|
||||
UPDATE SET
|
||||
t.NOME = s.NOME,
|
||||
t.PONTUACAO_TOTAL = s.PONTUACAO_TOTAL,
|
||||
t.COMPONENTE_A = s.COMPONENTE_A,
|
||||
t.COMPONENTE_B = s.COMPONENTE_B,
|
||||
t.COMPONENTE_C = s.COMPONENTE_C,
|
||||
t.COMPONENTE_D = s.COMPONENTE_D,
|
||||
t.ATIVO = s.ATIVO,
|
||||
t.ANOS_ATUACAO = s.ANOS_ATUACAO,
|
||||
t.DT_CALCULO = CURRENT_TIMESTAMP,
|
||||
t.JSON_DETALHES = s.JSON_DETALHES
|
||||
WHEN NOT MATCHED THEN
|
||||
INSERT (
|
||||
ID_PESSOA, NOME, PONTUACAO_TOTAL,
|
||||
COMPONENTE_A, COMPONENTE_B, COMPONENTE_C, COMPONENTE_D,
|
||||
ATIVO, ANOS_ATUACAO, JSON_DETALHES, DT_CALCULO
|
||||
)
|
||||
VALUES (
|
||||
s.ID_PESSOA, s.NOME, s.PONTUACAO_TOTAL,
|
||||
s.COMPONENTE_A, s.COMPONENTE_B, s.COMPONENTE_C, s.COMPONENTE_D,
|
||||
s.ATIVO, s.ANOS_ATUACAO, s.JSON_DETALHES, CURRENT_TIMESTAMP
|
||||
)
|
||||
insert_sql = """
|
||||
INSERT INTO TB_RANKING_CONSULTOR (
|
||||
ID_PESSOA, NOME, PONTUACAO_TOTAL,
|
||||
COMPONENTE_A, COMPONENTE_B, COMPONENTE_C, COMPONENTE_D,
|
||||
ATIVO, ANOS_ATUACAO, JSON_DETALHES, DT_CALCULO
|
||||
) VALUES (
|
||||
:id_pessoa, :nome, :pontuacao_total,
|
||||
:componente_a, :componente_b, :componente_c, :componente_d,
|
||||
:ativo, :anos_atuacao, :json_detalhes, CURRENT_TIMESTAMP
|
||||
)
|
||||
"""
|
||||
|
||||
batch_data = []
|
||||
for consultor in consultores:
|
||||
json_str = json.dumps(consultor, ensure_ascii=False)
|
||||
batch_data.append({
|
||||
"id_pessoa": int(consultor["id_pessoa"]),
|
||||
"nome": str(consultor.get("nome", ""))[:500],
|
||||
"pontuacao_total": int(consultor.get("pontuacao_total") or 0),
|
||||
"componente_a": int(consultor.get("bloco_a") or consultor.get("componente_a") or 0),
|
||||
"componente_b": int(consultor.get("bloco_b") or consultor.get("componente_b") or 0),
|
||||
"componente_c": int(consultor.get("bloco_c") or consultor.get("componente_c") or 0),
|
||||
"componente_d": int(consultor.get("bloco_d") or consultor.get("componente_d") or 0),
|
||||
"ativo": "S" if consultor.get("ativo") else "N",
|
||||
"anos_atuacao": float(consultor.get("anos_atuacao") or 0),
|
||||
"json_detalhes": json_str
|
||||
})
|
||||
|
||||
with self.client.get_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
try:
|
||||
for consultor in consultores:
|
||||
json_str = json.dumps(consultor, ensure_ascii=False)
|
||||
cursor.setinputsizes(json_detalhes=oracledb.DB_TYPE_CLOB)
|
||||
params = {
|
||||
"id_pessoa": consultor["id_pessoa"],
|
||||
"nome": consultor["nome"],
|
||||
"pontuacao_total": consultor["pontuacao_total"],
|
||||
"componente_a": consultor.get("bloco_a") or consultor.get("componente_a", 0),
|
||||
"componente_b": consultor.get("bloco_b") or consultor.get("componente_b", 0),
|
||||
"componente_c": consultor.get("bloco_c") or consultor.get("componente_c", 0),
|
||||
"componente_d": consultor.get("bloco_d") or consultor.get("componente_d", 0),
|
||||
"ativo": "S" if consultor.get("ativo") else "N",
|
||||
"anos_atuacao": consultor.get("anos_atuacao", 0),
|
||||
"json_detalhes": json_str
|
||||
}
|
||||
cursor.execute(merge_sql, params)
|
||||
|
||||
cursor.setinputsizes(json_detalhes=oracledb.DB_TYPE_CLOB)
|
||||
cursor.executemany(insert_sql, batch_data)
|
||||
conn.commit()
|
||||
return len(consultores)
|
||||
except Exception as e:
|
||||
@@ -372,14 +343,18 @@ class RankingOracleRepository:
|
||||
"""
|
||||
Limpa todos os registros da tabela de ranking.
|
||||
Usar apenas quando for reprocessar do zero.
|
||||
TRUNCATE é muito mais rápido que DELETE para grandes volumes.
|
||||
"""
|
||||
with self.client.get_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
try:
|
||||
cursor.execute("DELETE FROM TB_RANKING_CONSULTOR")
|
||||
conn.commit()
|
||||
cursor.execute("TRUNCATE TABLE TB_RANKING_CONSULTOR")
|
||||
except Exception as e:
|
||||
conn.rollback()
|
||||
raise RuntimeError(f"Erro ao limpar tabela: {e}")
|
||||
try:
|
||||
cursor.execute("DELETE FROM TB_RANKING_CONSULTOR")
|
||||
conn.commit()
|
||||
except Exception as e2:
|
||||
conn.rollback()
|
||||
raise RuntimeError(f"Erro ao limpar tabela: {e2}")
|
||||
finally:
|
||||
cursor.close()
|
||||
|
||||
@@ -17,6 +17,7 @@ from ...domain.entities.consultor import (
|
||||
Participacao,
|
||||
Orientacao,
|
||||
MembroBanca,
|
||||
DocenciaPPG,
|
||||
)
|
||||
from ...domain.repositories.consultor_repository import ConsultorRepository
|
||||
from ...domain.services.calculador_pontuacao import CalculadorPontuacao
|
||||
@@ -554,6 +555,51 @@ class ConsultorRepositoryImpl(ConsultorRepository):
|
||||
|
||||
return membros
|
||||
|
||||
def _extrair_docencias(self, atuacoes: List[Dict[str, Any]]) -> List[DocenciaPPG]:
|
||||
docencias = []
|
||||
|
||||
for a in atuacoes:
|
||||
if a.get("tipo") != "Docência":
|
||||
continue
|
||||
|
||||
dados = a.get("dadosDocencia", {}) or {}
|
||||
if not dados:
|
||||
continue
|
||||
|
||||
programa_data = dados.get("programa", {}) or {}
|
||||
ies_data = dados.get("ies", {}) or {}
|
||||
area_data = dados.get("areaConhecimento", {}) or {}
|
||||
area_aval_data = area_data.get("areaAvaliacao", {}) or {}
|
||||
|
||||
programa = programa_data.get("nome", "") or a.get("descricao", "")
|
||||
codigo_programa = programa_data.get("codigo", "")
|
||||
if not programa and not codigo_programa:
|
||||
continue
|
||||
|
||||
inicio = self._parse_date(a.get("inicio"))
|
||||
fim = self._parse_date(a.get("fim"))
|
||||
|
||||
linhas = []
|
||||
for lp in dados.get("linhaPesquisa", []) or []:
|
||||
if lp.get("nome"):
|
||||
linhas.append(lp["nome"])
|
||||
|
||||
docencias.append(DocenciaPPG(
|
||||
programa=programa,
|
||||
codigo_programa=codigo_programa,
|
||||
ies_sigla=ies_data.get("sigla", ""),
|
||||
ies_nome=ies_data.get("nome", ""),
|
||||
categoria=dados.get("categoria", ""),
|
||||
area_avaliacao=area_aval_data.get("nome", "") or area_data.get("nome", ""),
|
||||
modalidade=programa_data.get("modalidade", ""),
|
||||
periodo=Periodo(inicio=inicio, fim=fim),
|
||||
carga_horaria=dados.get("cargaHoraria"),
|
||||
linhas_pesquisa=linhas[:3],
|
||||
))
|
||||
|
||||
docencias.sort(key=lambda d: (d.periodo.fim is not None, d.periodo.inicio or datetime.min), reverse=True)
|
||||
return docencias
|
||||
|
||||
async def _construir_consultor(self, doc: Dict[str, Any]) -> Consultor:
|
||||
id_pessoa = doc["id"]
|
||||
dados_pessoais = doc.get("dadosPessoais", {})
|
||||
@@ -569,6 +615,7 @@ class ConsultorRepositoryImpl(ConsultorRepository):
|
||||
orientacoes = self._extrair_orientacoes(atuacoes)
|
||||
coorientacoes = self._extrair_coorientacoes(atuacoes)
|
||||
membros_banca = self._extrair_membros_banca(atuacoes)
|
||||
docencias = self._extrair_docencias(atuacoes)
|
||||
coordenador_ppg = self._tem_coordenacao_ppg(atuacoes)
|
||||
|
||||
consultor = Consultor(
|
||||
@@ -585,6 +632,7 @@ class ConsultorRepositoryImpl(ConsultorRepository):
|
||||
participacoes=participacoes,
|
||||
orientacoes=orientacoes + coorientacoes,
|
||||
membros_banca=membros_banca,
|
||||
docencias=docencias,
|
||||
)
|
||||
|
||||
consultor.pontuacao = self.calculador.calcular_pontuacao_completa(consultor)
|
||||
|
||||
Reference in New Issue
Block a user