Corrige calculo do Componente C (Consultoria)

- Adiciona campo vezes_responsavel na entidade Consultoria
- Corrige calculo de base: usa eventos_recentes > 0 (nao string situacao)
- Implementa calculo de extras:
  - extras_eventos: 2 pts/evento (max 20)
  - extras_responsavel: 5 pts/vez (max 25)
  - extras_areas: 10 pts/area extra (max 30)
- Extrai dados de consultorResponsavel dos eventos no repository
- Atualiza DTOs e schemas para incluir novo campo
This commit is contained in:
Frederico Castro
2025-12-13 11:57:33 -03:00
parent 8a8b4230c2
commit b18ae8199c
7 changed files with 32 additions and 12 deletions

View File

@@ -37,12 +37,13 @@ class ConsultoriaDTO:
eventos_recentes: int eventos_recentes: int
primeiro_evento: str primeiro_evento: str
ultimo_evento: str ultimo_evento: str
vezes_responsavel: int continuidade: int
areas: List[str] areas: List[str]
situacao: str situacao: str
anos_completos: int anos_completos: int
anos_consecutivos: int anos_consecutivos: int
retornos: int retornos: int
vezes_responsavel: int
@dataclass @dataclass

View File

@@ -150,10 +150,12 @@ class ProcessarRankingJob:
"consultoria": { "consultoria": {
"total_eventos": consultor.consultoria.total_eventos, "total_eventos": consultor.consultoria.total_eventos,
"eventos_recentes": consultor.consultoria.eventos_recentes, "eventos_recentes": consultor.consultoria.eventos_recentes,
"vezes_responsavel": consultor.consultoria.vezes_responsavel, "continuidade": consultor.consultoria.continuidade,
"anos_consecutivos": consultor.consultoria.anos_consecutivos,
"situacao": consultor.consultoria.situacao, "situacao": consultor.consultoria.situacao,
"anos_completos": consultor.consultoria.anos_completos, "anos_completos": consultor.consultoria.anos_completos,
"areas": consultor.consultoria.areas "areas": consultor.consultoria.areas,
"vezes_responsavel": consultor.consultoria.vezes_responsavel
} if consultor.consultoria else None, } if consultor.consultoria else None,
"premiacoes": [ "premiacoes": [
{ {

View File

@@ -92,12 +92,13 @@ class ObterRankingUseCase:
eventos_recentes=consultor.consultoria.eventos_recentes, eventos_recentes=consultor.consultoria.eventos_recentes,
primeiro_evento=consultor.consultoria.primeiro_evento.isoformat(), primeiro_evento=consultor.consultoria.primeiro_evento.isoformat(),
ultimo_evento=consultor.consultoria.ultimo_evento.isoformat(), ultimo_evento=consultor.consultoria.ultimo_evento.isoformat(),
vezes_responsavel=consultor.consultoria.vezes_responsavel, continuidade=consultor.consultoria.continuidade,
areas=consultor.consultoria.areas, areas=consultor.consultoria.areas,
situacao=consultor.consultoria.situacao, situacao=consultor.consultoria.situacao,
anos_completos=consultor.consultoria.anos_completos, anos_completos=consultor.consultoria.anos_completos,
anos_consecutivos=consultor.consultoria.anos_consecutivos, anos_consecutivos=consultor.consultoria.anos_consecutivos,
retornos=consultor.consultoria.retornos, retornos=consultor.consultoria.retornos,
vezes_responsavel=consultor.consultoria.vezes_responsavel,
) )
if consultor.consultoria if consultor.consultoria
else None, else None,

View File

@@ -32,12 +32,22 @@ class Consultoria:
eventos_recentes: int eventos_recentes: int
primeiro_evento: datetime primeiro_evento: datetime
ultimo_evento: datetime ultimo_evento: datetime
vezes_responsavel: int
areas: List[str] = field(default_factory=list) areas: List[str] = field(default_factory=list)
situacao: str = "N/A" situacao: str = "N/A"
anos_completos: int = 0 anos_completos: int = 0
anos_consecutivos: int = 0 anos_consecutivos: int = 0
retornos: int = 0 retornos: int = 0
vezes_responsavel: int = 0
@property
def continuidade(self) -> int:
if self.anos_consecutivos >= 8:
return 15
elif self.anos_consecutivos >= 5:
return 10
elif self.anos_consecutivos >= 3:
return 5
return 0
@dataclass @dataclass

View File

@@ -157,14 +157,18 @@ class CalculadorPontuacao:
if not consultoria: if not consultoria:
return ComponentePontuacao(base=0, tempo=0, extras=0, bonus=0) return ComponentePontuacao(base=0, tempo=0, extras=0, bonus=0)
situacao = (consultoria.situacao or "").lower() base = 150 if consultoria.eventos_recentes > 0 else 100
base = 150 if "atividade" in situacao else 100
anos = consultoria.anos_completos if consultoria.anos_completos else int( anos = consultoria.anos_completos if consultoria.anos_completos else int(
((datetime.now() - consultoria.primeiro_evento).days) // 365 ((datetime.now() - consultoria.primeiro_evento).days) // 365
) )
tempo = min(int(anos * 5), 50) tempo = min(int(anos * 5), 50)
extras_eventos = min(consultoria.total_eventos * 2, 20)
extras_responsavel = min(consultoria.vezes_responsavel * 5, 25)
extras_areas = min((len(consultoria.areas) - 1) * 10, 30) if len(consultoria.areas) > 1 else 0
extras = extras_eventos + extras_responsavel + extras_areas
continuidade = consultoria.anos_consecutivos continuidade = consultoria.anos_consecutivos
if continuidade >= 8: if continuidade >= 8:
bonus_continuidade = 15 bonus_continuidade = 15
@@ -176,8 +180,6 @@ class CalculadorPontuacao:
bonus_continuidade = 0 bonus_continuidade = 0
retorno_bonus = 15 if consultoria.retornos > 0 else 0 retorno_bonus = 15 if consultoria.retornos > 0 else 0
extras = 0
bonus = bonus_continuidade + retorno_bonus bonus = bonus_continuidade + retorno_bonus
return ComponentePontuacao(base=base, tempo=tempo, extras=extras, bonus=bonus) return ComponentePontuacao(base=base, tempo=tempo, extras=extras, bonus=bonus)

View File

@@ -134,16 +134,19 @@ class ConsultorRepositoryImpl(ConsultorRepository):
total_eventos = len(eventos_sae) total_eventos = len(eventos_sae)
limite_recente = datetime.now() - timedelta(days=730) limite_recente = datetime.now() - timedelta(days=730)
eventos_recentes = 0 eventos_recentes = 0
vezes_responsavel = 0
for ev in eventos_sae: for ev in eventos_sae:
data_fim = self._parse_date(ev.get("fim")) or self._parse_date(ev.get("inicio")) data_fim = self._parse_date(ev.get("fim")) or self._parse_date(ev.get("inicio"))
if data_fim and data_fim >= limite_recente: if data_fim and data_fim >= limite_recente:
eventos_recentes += 1 eventos_recentes += 1
dados_evento = ev.get("dadosEvento", {}) or {}
if dados_evento.get("consultorResponsavel") == "Sim":
vezes_responsavel += 1
primeiro_evento = min(p.inicio for p in periodos) primeiro_evento = min(p.inicio for p in periodos)
ultimo_evento = max((p.fim or datetime.now()) for p in periodos) if not ativo else datetime.now() ultimo_evento = max((p.fim or datetime.now()) for p in periodos) if not ativo else datetime.now()
areas = list(set(areas)) if areas else ["N/A"] areas = list(set(areas)) if areas else ["N/A"]
vezes_responsavel = sum(1 for c in consultorias if c.get("responsavel", False))
situacao_final = situacoes[0] if situacoes else "N/A" situacao_final = situacoes[0] if situacoes else "N/A"
@@ -152,12 +155,12 @@ class ConsultorRepositoryImpl(ConsultorRepository):
eventos_recentes=eventos_recentes, eventos_recentes=eventos_recentes,
primeiro_evento=primeiro_evento, primeiro_evento=primeiro_evento,
ultimo_evento=ultimo_evento, ultimo_evento=ultimo_evento,
vezes_responsavel=vezes_responsavel,
areas=areas, areas=areas,
situacao=situacao_final, situacao=situacao_final,
anos_completos=anos_total, anos_completos=anos_total,
anos_consecutivos=anos_consecutivos, anos_consecutivos=anos_consecutivos,
retornos=retornos, retornos=retornos,
vezes_responsavel=vezes_responsavel,
) )
def _extrair_coordenacoes_capes( def _extrair_coordenacoes_capes(

View File

@@ -32,12 +32,13 @@ class ConsultoriaSchema(BaseModel):
eventos_recentes: int eventos_recentes: int
primeiro_evento: str primeiro_evento: str
ultimo_evento: str ultimo_evento: str
vezes_responsavel: int continuidade: int
areas: List[str] areas: List[str]
situacao: str situacao: str
anos_completos: int anos_completos: int
anos_consecutivos: int anos_consecutivos: int
retornos: int retornos: int
vezes_responsavel: int
class PremiacaoSchema(BaseModel): class PremiacaoSchema(BaseModel):