fix: corrigir filtro Ativo/Inativo e cálculo de anos para consultores

Filtro E_CONSULTOR:
- Adicionar coluna E_CONSULTOR na tabela TB_RANKING_CONSULTOR
- Filtrar apenas consultores ao selecionar Ativo/Inativo
- Não-consultores não aparecem mais no filtro de inativos

Correção de anos para inativos:
- Calcular anos_consecutivos baseado no período histórico (não mais 0)
- Calcular anos_atuacao usando data fim do período (não datetime.now())
This commit is contained in:
Frederico Castro
2025-12-31 03:12:43 -03:00
parent 0a0a47ecc4
commit c273349663
7 changed files with 34 additions and 11 deletions

View File

@@ -14,17 +14,20 @@ CREATE TABLE TB_RANKING_CONSULTOR (
COMPONENTE_D NUMBER(10,2) DEFAULT 0, COMPONENTE_D NUMBER(10,2) DEFAULT 0,
COMPONENTE_E NUMBER(10,2) DEFAULT 0, COMPONENTE_E NUMBER(10,2) DEFAULT 0,
ATIVO CHAR(1) DEFAULT 'N', ATIVO CHAR(1) DEFAULT 'N',
E_CONSULTOR CHAR(1) DEFAULT 'N',
ANOS_ATUACAO NUMBER(5,1) DEFAULT 0, ANOS_ATUACAO NUMBER(5,1) DEFAULT 0,
DT_CALCULO TIMESTAMP DEFAULT CURRENT_TIMESTAMP, DT_CALCULO TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
JSON_DETALHES CLOB, JSON_DETALHES CLOB,
CONSTRAINT PK_RANKING_CONSULTOR PRIMARY KEY (ID_PESSOA), CONSTRAINT PK_RANKING_CONSULTOR PRIMARY KEY (ID_PESSOA),
CONSTRAINT CHK_ATIVO CHECK (ATIVO IN ('S', 'N')) CONSTRAINT CHK_ATIVO CHECK (ATIVO IN ('S', 'N')),
CONSTRAINT CHK_E_CONSULTOR CHECK (E_CONSULTOR IN ('S', 'N'))
); );
-- Índices para performance -- Índices para performance
CREATE INDEX IDX_RANKING_POSICAO ON TB_RANKING_CONSULTOR(POSICAO); 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_PONTUACAO ON TB_RANKING_CONSULTOR(PONTUACAO_TOTAL DESC);
CREATE INDEX IDX_RANKING_ATIVO ON TB_RANKING_CONSULTOR(ATIVO); CREATE INDEX IDX_RANKING_ATIVO ON TB_RANKING_CONSULTOR(ATIVO);
CREATE INDEX IDX_RANKING_E_CONSULTOR ON TB_RANKING_CONSULTOR(E_CONSULTOR);
CREATE INDEX IDX_RANKING_DT_CALCULO ON TB_RANKING_CONSULTOR(DT_CALCULO DESC); CREATE INDEX IDX_RANKING_DT_CALCULO ON TB_RANKING_CONSULTOR(DT_CALCULO DESC);
-- Procedure para atualizar posições após processamento -- Procedure para atualizar posições após processamento

View File

@@ -260,6 +260,7 @@ class ProcessarRankingJob:
bloco_d=int(c.get("bloco_d", 0)), bloco_d=int(c.get("bloco_d", 0)),
bloco_e=int(c.get("bloco_e", 0)), bloco_e=int(c.get("bloco_e", 0)),
ativo=bool(c.get("ativo", False)), ativo=bool(c.get("ativo", False)),
e_consultor=c.get("consultoria") is not None,
anos_atuacao=float(c.get("anos_atuacao", 0) or 0), anos_atuacao=float(c.get("anos_atuacao", 0) or 0),
detalhes=c, detalhes=c,
) )

View File

@@ -153,7 +153,8 @@ class Consultor:
def anos_atuacao(self) -> float: def anos_atuacao(self) -> float:
if not self.consultoria or not self.consultoria.periodo.inicio: if not self.consultoria or not self.consultoria.periodo.inicio:
return 0.0 return 0.0
dias = (datetime.now() - self.consultoria.periodo.inicio).days fim = self.consultoria.periodo.fim or datetime.now()
dias = (fim - self.consultoria.periodo.inicio).days
return round(dias / 365.25, 1) return round(dias / 365.25, 1)
@property @property

View File

@@ -25,11 +25,11 @@ class RankingOracleRepository:
INSERT INTO TB_RANKING_CONSULTOR ( INSERT INTO TB_RANKING_CONSULTOR (
ID_PESSOA, NOME, PONTUACAO_TOTAL, ID_PESSOA, NOME, PONTUACAO_TOTAL,
COMPONENTE_A, COMPONENTE_B, COMPONENTE_C, COMPONENTE_D, COMPONENTE_E, COMPONENTE_A, COMPONENTE_B, COMPONENTE_C, COMPONENTE_D, COMPONENTE_E,
ATIVO, ANOS_ATUACAO, JSON_DETALHES, SELOS, DT_CALCULO ATIVO, E_CONSULTOR, ANOS_ATUACAO, JSON_DETALHES, SELOS, DT_CALCULO
) VALUES ( ) VALUES (
:id_pessoa, :nome, :pontuacao_total, :id_pessoa, :nome, :pontuacao_total,
:componente_a, :componente_b, :componente_c, :componente_d, :componente_e, :componente_a, :componente_b, :componente_c, :componente_d, :componente_e,
:ativo, :anos_atuacao, :json_detalhes, :selos, CURRENT_TIMESTAMP :ativo, :e_consultor, :anos_atuacao, :json_detalhes, :selos, CURRENT_TIMESTAMP
) )
""" """
@@ -38,6 +38,7 @@ class RankingOracleRepository:
json_str = json.dumps(consultor, ensure_ascii=False) json_str = json.dumps(consultor, ensure_ascii=False)
selos_set = extrair_selos_entry(consultor) selos_set = extrair_selos_entry(consultor)
selos_str = ",".join(sorted(selos_set)) if selos_set else None selos_str = ",".join(sorted(selos_set)) if selos_set else None
e_consultor = consultor.get("consultoria") is not None
batch_data.append({ batch_data.append({
"id_pessoa": int(consultor["id_pessoa"]), "id_pessoa": int(consultor["id_pessoa"]),
"nome": str(consultor.get("nome", ""))[:500], "nome": str(consultor.get("nome", ""))[:500],
@@ -48,6 +49,7 @@ class RankingOracleRepository:
"componente_d": int(consultor.get("bloco_d") or consultor.get("componente_d") or 0), "componente_d": int(consultor.get("bloco_d") or consultor.get("componente_d") or 0),
"componente_e": int(consultor.get("bloco_e") or consultor.get("componente_e") or 0), "componente_e": int(consultor.get("bloco_e") or consultor.get("componente_e") or 0),
"ativo": "S" if consultor.get("ativo") else "N", "ativo": "S" if consultor.get("ativo") else "N",
"e_consultor": "S" if e_consultor else "N",
"anos_atuacao": float(consultor.get("anos_atuacao") or 0), "anos_atuacao": float(consultor.get("anos_atuacao") or 0),
"json_detalhes": json_str, "json_detalhes": json_str,
"selos": selos_str "selos": selos_str
@@ -91,6 +93,7 @@ class RankingOracleRepository:
} }
if filtro_ativo is not None: if filtro_ativo is not None:
where_clauses.append("E_CONSULTOR = 'S'")
where_clauses.append("ATIVO = :ativo") where_clauses.append("ATIVO = :ativo")
params["ativo"] = "S" if filtro_ativo else "N" params["ativo"] = "S" if filtro_ativo else "N"
@@ -169,6 +172,7 @@ class RankingOracleRepository:
params = {} params = {}
if filtro_ativo is not None: if filtro_ativo is not None:
where_clauses.append("E_CONSULTOR = 'S'")
where_clauses.append("ATIVO = :ativo") where_clauses.append("ATIVO = :ativo")
params["ativo"] = "S" if filtro_ativo else "N" params["ativo"] = "S" if filtro_ativo else "N"
@@ -410,6 +414,7 @@ class RankingOracleRepository:
params = {} params = {}
if filtro_ativo is not None: if filtro_ativo is not None:
where_clauses.append("E_CONSULTOR = 'S'")
where_clauses.append("ATIVO = :ativo") where_clauses.append("ATIVO = :ativo")
params["ativo"] = "S" if filtro_ativo else "N" params["ativo"] = "S" if filtro_ativo else "N"
@@ -477,6 +482,7 @@ class RankingOracleRepository:
params = {} params = {}
if filtro_ativo is not None: if filtro_ativo is not None:
where_clauses.append("E_CONSULTOR = 'S'")
where_clauses.append("ATIVO = :ativo") where_clauses.append("ATIVO = :ativo")
params["ativo"] = "S" if filtro_ativo else "N" params["ativo"] = "S" if filtro_ativo else "N"

View File

@@ -161,6 +161,7 @@ class RankingEntry:
bloco_d: int bloco_d: int
bloco_e: int bloco_e: int
ativo: bool ativo: bool
e_consultor: bool
anos_atuacao: float anos_atuacao: float
detalhes: Dict[str, Any] detalhes: Dict[str, Any]
@@ -192,7 +193,7 @@ class RankingStore:
def total(self, filtro_ativo: Optional[bool] = None) -> int: def total(self, filtro_ativo: Optional[bool] = None) -> int:
if filtro_ativo is None: if filtro_ativo is None:
return len(self._entries) return len(self._entries)
return sum(1 for e in self._entries if e.ativo == filtro_ativo) return sum(1 for e in self._entries if e.e_consultor and e.ativo == filtro_ativo)
def get_page( def get_page(
self, self,
@@ -209,7 +210,7 @@ class RankingStore:
entries = self._entries entries = self._entries
if filtro_ativo is not None: if filtro_ativo is not None:
entries = [e for e in entries if e.ativo == filtro_ativo] entries = [e for e in entries if e.e_consultor and e.ativo == filtro_ativo]
if filtro_selos: if filtro_selos:
selos_set = set(filtro_selos) selos_set = set(filtro_selos)
@@ -234,7 +235,7 @@ class RankingStore:
if filtro_ativo is None: if filtro_ativo is None:
entries = self._entries entries = self._entries
else: else:
entries = [e for e in self._entries if e.ativo == filtro_ativo] entries = [e for e in self._entries if e.e_consultor and e.ativo == filtro_ativo]
total = len(entries) total = len(entries)
return total, entries[offset : offset + limit] return total, entries[offset : offset + limit]

View File

@@ -222,13 +222,24 @@ class ConsultorRepositoryImpl(ConsultorRepository):
mesclados = mesclar_periodos(periodos) mesclados = mesclar_periodos(periodos)
periodo_ativo = next((p for p in mesclados if p.ativo), None) periodo_ativo = next((p for p in mesclados if p.ativo), None)
anos_consecutivos = periodo_ativo.anos_completos(datetime.now()) if periodo_ativo else 0 if periodo_ativo:
anos_consecutivos = periodo_ativo.anos_completos(datetime.now())
elif mesclados:
anos_list = [p.anos_completos(p.fim or datetime.now()) for p in mesclados]
anos_consecutivos = max(anos_list) if anos_list else 0
else:
anos_consecutivos = 0
retornos = max(0, len(mesclados) - 1) retornos = max(0, len(mesclados) - 1)
ativo = any(p.ativo for p in periodos) ativo = any(p.ativo for p in periodos)
situacao_final = situacoes[-1] if situacoes else "N/A" situacao_final = situacoes[-1] if situacoes else "N/A"
is_ativo = ativo or "atividade" in situacao_final.lower() or "ativo" in situacao_final.lower() situacao_lower = situacao_final.lower()
is_falecido = "falecido" in situacao_final.lower() is_ativo = ativo or (
("atividade" in situacao_lower or "ativo" in situacao_lower)
and "inatividade" not in situacao_lower
and "inativo" not in situacao_lower
)
is_falecido = "falecido" in situacao_lower
if is_falecido: if is_falecido:
codigo = "CONS_FALECIDO" codigo = "CONS_FALECIDO"

View File

@@ -222,7 +222,7 @@ async def ranking_paginado(
total = oracle_repo.contar_total(filtro_ativo=ativo, filtro_selos=selos_lista) total = oracle_repo.contar_total(filtro_ativo=ativo, filtro_selos=selos_lista)
if total == 0: if total == 0:
if selos_lista: if selos_lista or ativo is not None:
return RankingPaginadoResponseSchema( return RankingPaginadoResponseSchema(
total=0, page=page, size=size, total_pages=0, consultores=[] total=0, page=page, size=size, total_pages=0, consultores=[]
) )